950-0106-Add-support-for-all-the-downstream-rpi-sound-card-dr.patch 520 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594
  1. From 74bd4038e58c360675a25d766634b424239c4b98 Mon Sep 17 00:00:00 2001
  2. From: Florian Meier <[email protected]>
  3. Date: Mon, 25 Jan 2016 15:48:59 +0000
  4. Subject: [PATCH 0106/1085] Add support for all the downstream rpi sound card
  5. drivers
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. ASoC: Add support for Rpi-DAC
  10. ASoC: Add prompt for ICS43432 codec
  11. Without a prompt string, a config setting can't be included in a
  12. defconfig. Give CONFIG_SND_SOC_ICS43432 a prompt so that Pi soundcards
  13. can use the driver.
  14. Signed-off-by: Phil Elwell <[email protected]>
  15. Add IQaudIO Sound Card support for Raspberry Pi
  16. Set a limit of 0dB on Digital Volume Control
  17. The main volume control in the PCM512x DAC has a range up to
  18. +24dB. This is dangerously loud and can potentially cause massive
  19. clipping in the output stages. Therefore this sets a sensible
  20. limit of 0dB for this control.
  21. Allow up to 24dB digital gain to be applied when using IQAudIO DAC+
  22. 24db_digital_gain DT param can be used to specify that PCM512x
  23. codec "Digital" volume control should not be limited to 0dB gain,
  24. and if specified will allow the full 24dB gain.
  25. Modify IQAudIO DAC+ ASoC driver to set card/dai config from dt
  26. Add the ability to set the card name, dai name and dai stream name, from
  27. dt config.
  28. Signed-off-by: DigitalDreamtime <[email protected]>
  29. IQaudIO: auto-mute for AMP+ and DigiAMP+
  30. IQAudIO amplifier mute via GPIO22. Add dt params for "one-shot" unmute
  31. and auto mute.
  32. Revision 2, auto mute implementing HiassofT suggestion to mute/unmute
  33. using set_bias_level, rather than startup/shutdown....
  34. "By default DAPM waits 5 seconds (pmdown_time) before shutting down
  35. playback streams so a close/stop immediately followed by open/start
  36. doesn't trigger an amp mute+unmute."
  37. Tested on both AMP+ (via DAC+) and DigiAMP+, with both options...
  38. dtoverlay=iqaudio-dacplus,unmute_amp
  39. "one-shot" unmute when kernel module loads.
  40. dtoverlay=iqaudio-dacplus,auto_mute_amp
  41. Unmute amp when ALSA device opened by a client. Mute, with 5 second delay
  42. when ALSA device closed. (Re-opening the device within the 5 second close
  43. window, will cancel mute.)
  44. Revision 4, using gpiod.
  45. Revision 5, clean-up formatting before adding mute code.
  46. - Convert tab plus 4 space formatting to 2x tab
  47. - Remove '// NOT USED' commented code
  48. Revision 6, don't attempt to "one-shot" unmute amp, unless card is
  49. successfully registered.
  50. Signed-off-by: DigitalDreamtime <[email protected]>
  51. ASoC: iqaudio-dac: fix S24_LE format
  52. Remove set_bclk_ratio call so 24-bit data is transmitted in
  53. 24 bclk cycles.
  54. Signed-off-by: Matthias Reichl <[email protected]>
  55. ASoC: iqaudio-dac: use modern dai_link style
  56. Signed-off-by: Matthias Reichl <[email protected]>
  57. Added support for HiFiBerry DAC+
  58. The driver is based on the HiFiBerry DAC driver. However HiFiBerry DAC+ uses
  59. a different codec chip (PCM5122), therefore a new driver is necessary.
  60. Add support for the HiFiBerry DAC+ Pro.
  61. The HiFiBerry DAC+ and DAC+ Pro products both use the existing bcm sound driver with the DAC+ Pro having a special clock device driver representing the two high precision oscillators.
  62. An addition bug fix is included for the PCM512x codec where by the physical size of the sample frame is used in the calculation of the LRCK divisor as it was found to be wrong when using 24-bit depth sample contained in a little endian 4-byte sample frame.
  63. Limit PCM512x "Digital" gain to 0dB by default with HiFiBerry DAC+
  64. 24db_digital_gain DT param can be used to specify that PCM512x
  65. codec "Digital" volume control should not be limited to 0dB gain,
  66. and if specified will allow the full 24dB gain.
  67. Add dt param to force HiFiBerry DAC+ Pro into slave mode
  68. "dtoverlay=hifiberry-dacplus,slave"
  69. Add 'slave' param to use HiFiBerry DAC+ Pro in slave mode,
  70. with Pi as master for bit and frame clock.
  71. Signed-off-by: DigitalDreamtime <[email protected]>
  72. Fixed a bug when using 352.8kHz sample rate
  73. Signed-off-by: Daniel Matuschek <[email protected]>
  74. ASoC: pcm512x: revert downstream changes
  75. This partially reverts commit 185ea05465aac8bf02a0d2b2f4289d42c72870b7
  76. which was added by https://github.com/raspberrypi/linux/pull/1152
  77. The downstream pcm512x changes caused a regression, it broke normal
  78. use of the 24bit format with the codec, eg when using simple-audio-card.
  79. The actual bug with 24bit playback is the incorrect usage
  80. of physical_width in various drivers in the downstream tree
  81. which causes 24bit data to be transmitted with 32 clock
  82. cycles. So it's not the pcm512x that needs fixing, it's the
  83. soundcard drivers.
  84. Signed-off-by: Matthias Reichl <[email protected]>
  85. ASoC: hifiberry_dacplus: fix S24_LE format
  86. Remove set_bclk_ratio call so 24-bit data is transmitted in
  87. 24 bclk cycles.
  88. Signed-off-by: Matthias Reichl <[email protected]>
  89. ASoC: hifiberry_dacplus: transmit S24_LE with 64 BCLK cycles
  90. Signed-off-by: Matthias Reichl <[email protected]>
  91. hifiberry_dacplus: switch to snd_soc_dai_set_bclk_ratio
  92. Signed-off-by: Matthias Reichl <[email protected]>
  93. ASoC: hifiberry_dacplus: use modern dai_link style
  94. Signed-off-by: Hui Wang <[email protected]>
  95. Add driver for rpi-proto
  96. Forward port of 3.10.x driver from https://github.com/koalo
  97. We are using a custom board and would like to use rpi 3.18.x
  98. kernel. Patch works fine for our embedded system.
  99. URL to the audio chip:
  100. http://www.mikroe.com/add-on-boards/audio-voice/audio-codec-proto/
  101. Playback tested with devicetree enabled.
  102. Signed-off-by: Waldemar Brodkorb <[email protected]>
  103. ASoC: rpi-proto: use modern dai_link style
  104. Signed-off-by: Hui Wang <[email protected]>
  105. Add Support for JustBoom Audio boards
  106. justboom-dac: Adjust for ALSA API change
  107. As of 4.4, snd_soc_limit_volume now takes a struct snd_soc_card *
  108. rather than a struct snd_soc_codec *.
  109. Signed-off-by: Phil Elwell <[email protected]>
  110. ASoC: justboom-dac: fix S24_LE format
  111. Remove set_bclk_ratio call so 24-bit data is transmitted in
  112. 24 bclk cycles.
  113. Also remove hw_params as it's no longer needed.
  114. Signed-off-by: Matthias Reichl <[email protected]>
  115. ASoC: justboom-dac: use modern dai_link style
  116. Signed-off-by: Matthias Reichl <[email protected]>
  117. New AudioInjector.net Pi soundcard with low jitter audio in and out.
  118. Contains the sound/soc/bcm ALSA machine driver and necessary alterations to the Kconfig and Makefile.
  119. Adds the dts overlay and updates the Makefile and README.
  120. Updates the relevant defconfig files to enable building for the Raspberry Pi.
  121. Thanks to Phil Elwell (pelwell) for the review, simple-card concepts and discussion. Thanks to Clive Messer for overlay naming suggestions.
  122. Added support for headphones, microphone and bclk_ratio settings.
  123. This patch adds headphone and microphone capability to the Audio Injector sound card. The patch also sets the bit clock ratio for use in the bcm2835-i2s driver. The bcm2835-i2s can't handle an 8 kHz sample rate when the bit clock is at 12 MHz because its register is only 10 bits wide which can't represent the ch2 offset of 1508. For that reason, the rate constraint is added.
  124. ASoC: audioinjector-pi-soundcard: use modern dai_link style
  125. Signed-off-by: Hui Wang <[email protected]>
  126. New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804
  127. ASoC: digidac1-soundcard: use modern dai_link style
  128. Signed-off-by: Hui Wang <[email protected]>
  129. Add support for Dion Audio LOCO DAC-AMP HAT
  130. Using dedicated machine driver and pcm5102a codec driver.
  131. Signed-off-by: DigitalDreamtime <[email protected]>
  132. ASoC: dionaudio_loco: use modern dai_link style
  133. Signed-off-by: Hui Wang <[email protected]>
  134. Allo Piano DAC boards: Initial 2 channel (stereo) support (#1645)
  135. Add initial 2 channel (stereo) support for Allo Piano DAC (2.0/2.1) boards,
  136. using allo-piano-dac-pcm512x-audio overlay and allo-piano-dac ALSA ASoC
  137. machine driver.
  138. NB. The initial support is 2 channel (stereo) ONLY!
  139. (The Piano DAC 2.1 will only support 2 channel (stereo) left/right output,
  140. pending an update to the upstream pcm512x codec driver, which will have
  141. to be submitted via upstream. With the initial downstream support,
  142. provided by this patch, the Piano DAC 2.1 subwoofer outputs will
  143. not function.)
  144. Signed-off-by: Baswaraj K <[email protected]>
  145. Signed-off-by: Clive Messer <[email protected]>
  146. Tested-by: Clive Messer <[email protected]>
  147. ASoC: allo-piano-dac: fix S24_LE format
  148. Remove set_bclk_ratio call so 24-bit data is transmitted in
  149. 24 bclk cycles.
  150. Also remove hw_params and ops as they are no longer needed.
  151. Signed-off-by: Matthias Reichl <[email protected]>
  152. ASoC: allo-piano-dac: use modern dai_link style
  153. Signed-off-by: Hui Wang <[email protected]>
  154. Add support for Allo Piano DAC 2.1 plus add-on board for Raspberry Pi.
  155. The Piano DAC 2.1 has support for 4 channels with subwoofer.
  156. Signed-off-by: Baswaraj K <[email protected]>
  157. Reviewed-by: Vijay Kumar B. <[email protected]>
  158. Reviewed-by: Raashid Muhammed <[email protected]>
  159. Add clock changes and mute gpios (#1938)
  160. Also improve code style and adhere to ALSA coding conventions.
  161. Signed-off-by: Baswaraj K <[email protected]>
  162. Reviewed-by: Vijay Kumar B. <[email protected]>
  163. Reviewed-by: Raashid Muhammed <[email protected]>
  164. PianoPlus: Dual Mono & Dual Stereo features added (#2069)
  165. allo-piano-dac-plus: Master volume added + fixes
  166. Master volume added, which controls both DACs volumes.
  167. See: https://github.com/raspberrypi/linux/pull/2149
  168. Also fix initial max volume, default mode value, and unmute.
  169. Signed-off-by: allocom <[email protected]>
  170. ASoC: allo-piano-dac-plus: fix S24_LE format
  171. Remove set_bclk_ratio call so 24-bit data is transmitted in
  172. 24 bclk cycles.
  173. Signed-off-by: Matthias Reichl <[email protected]>
  174. sound: bcm: Fix memset dereference warning
  175. This warning appears with GCC 6.4.0 from toolchains.bootlin.com:
  176. ../sound/soc/bcm/allo-piano-dac-plus.c: In function ‘snd_allo_piano_dac_init’:
  177. ../sound/soc/bcm/allo-piano-dac-plus.c:711:30: warning: argument to ‘sizeof’ in ‘memset’ call is the same expression as the destination; did you mean to dereference it? [-Wsizeof-pointer-memaccess]
  178. memset(glb_ptr, 0x00, sizeof(glb_ptr));
  179. ^
  180. Suggested-by: Phil Elwell <[email protected]>
  181. Signed-off-by: Nathan Chancellor <[email protected]>
  182. ASoC: allo-piano-dac-plus: use modern dai_link style
  183. Signed-off-by: Hui Wang <[email protected]>
  184. Add support for Allo Boss DAC add-on board for Raspberry Pi. (#1924)
  185. Signed-off-by: Baswaraj K <[email protected]>
  186. Reviewed-by: Deepak <[email protected]>
  187. Reviewed-by: BabuSubashChandar <[email protected]>
  188. Add support for new clock rate and mute gpios.
  189. Signed-off-by: Baswaraj K <[email protected]>
  190. Reviewed-by: Deepak <[email protected]>
  191. Reviewed-by: BabuSubashChandar <[email protected]>
  192. ASoC: allo-boss-dac: fix S24_LE format
  193. Remove set_bclk_ratio call so 24-bit data is transmitted in
  194. 24 bclk cycles.
  195. Signed-off-by: Matthias Reichl <[email protected]>
  196. ASoC: allo-boss-dac: transmit S24_LE with 64 BCLK cycles
  197. Signed-off-by: Matthias Reichl <[email protected]>
  198. allo-boss-dac: switch to snd_soc_dai_set_bclk_ratio
  199. Signed-off-by: Matthias Reichl <[email protected]>
  200. ASoC: allo-boss-dac: use modern dai_link style
  201. Signed-off-by: Hui Wang <[email protected]>
  202. Support for Blokas Labs pisound board
  203. Pisound dynamic overlay (#1760)
  204. Restructuring pisound-overlay.dts, so it can be loaded and unloaded dynamically using dtoverlay.
  205. Print a logline when the kernel module is removed.
  206. pisound improvements:
  207. * Added a writable sysfs object to enable scripts / user space software
  208. to blink MIDI activity LEDs for variable duration.
  209. * Improved hw_param constraints setting.
  210. * Added compatibility with S16_LE sample format.
  211. * Exposed some simple placeholder volume controls, so the card appears
  212. in volumealsa widget.
  213. Add missing SND_PISOUND selects dependency to SND_RAWMIDI
  214. Without it the Pisound module fails to compile.
  215. See https://github.com/raspberrypi/linux/issues/2366
  216. Updates for Pisound module code:
  217. * Merged 'Fix a warning in DEBUG builds' (1c8b82b).
  218. * Updating some strings and copyright information.
  219. * Fix for handling high load of MIDI input and output.
  220. * Use dual rate oversampling ratio for 96kHz instead of single
  221. rate one.
  222. Signed-off-by: Giedrius Trainavicius <[email protected]>
  223. Fixing memset call in pisound.c
  224. Signed-off-by: Giedrius Trainavicius <[email protected]>
  225. Fix for Pisound's MIDI Input getting blocked for a while in rare cases.
  226. There was a possible race condition which could lead to Input's FIFO queue
  227. to be underflown, causing high amount of processing in the worker thread for
  228. some period of time.
  229. Signed-off-by: Giedrius Trainavicius <[email protected]>
  230. Fix for Pisound kernel module in Real Time kernel configuration.
  231. When handler of data_available interrupt is fired, queue_work ends up
  232. getting called and it can block on a spin lock which is not allowed in
  233. interrupt context. The fix was to run the handler from a thread context
  234. instead.
  235. Pisound: Remove spinlock usage around spi_sync
  236. ASoC: pisound: use modern dai_link style
  237. Signed-off-by: Hui Wang <[email protected]>
  238. ASoC: pisound: fix the parameter for spi_device_match
  239. Signed-off-by: Hui Wang <[email protected]>
  240. ASoC: Add driver for Cirrus Logic Audio Card
  241. Note: due to problems with deferred probing of regulators
  242. the following softdep should be added to a modprobe.d file
  243. softdep arizona-spi pre: arizona-ldo1
  244. Signed-off-by: Matthias Reichl <[email protected]>
  245. ASoC: rpi-cirrus: use modern dai_link style
  246. Signed-off-by: Matthias Reichl <[email protected]>
  247. sound: Support for Dion Audio LOCO-V2 DAC-AMP HAT
  248. Signed-off-by: Miquel Blauw <[email protected]>
  249. ASoC: dionaudio_loco-v2: fix S24_LE format
  250. Remove set_bclk_ratio call so 24-bit data is transmitted in
  251. 24 bclk cycles.
  252. Also remove hw_params and ops as they are no longer needed.
  253. Signed-off-by: Matthias Reichl <[email protected]>
  254. ASoC: dionaudio_loco-v2: use modern dai_link style
  255. Signed-off-by: Hui Wang <[email protected]>
  256. Add support for Fe-Pi audio sound card. (#1867)
  257. Fe-Pi Audio Sound Card is based on NXP SGTL5000 codec.
  258. Mechanical specification of the board is the same the Raspberry Pi Zero.
  259. 3.5mm jacks for Headphone/Mic, Line In, and Line Out.
  260. Signed-off-by: Henry Kupis <[email protected]>
  261. ASoC: fe-pi-audio: use modern dai_link style
  262. Signed-off-by: Hui Wang <[email protected]>
  263. Add support for the AudioInjector.net Octo sound card
  264. AudioInjector Octo: sample rates, regulators, reset
  265. This patch adds new sample rates to the Audioinjector Octo sound card. The
  266. new supported rates are (in kHz) :
  267. 96, 48, 32, 24, 16, 8, 88.2, 44.1, 29.4, 22.05, 14.7
  268. Reference the bcm270x DT regulators in the overlay.
  269. This patch adds a reset GPIO for the AudioInjector.net octo sound card.
  270. Audioinjector octo : Make the playback and capture symmetric
  271. This patch ensures that the sample rate and channel count of the audioinjector
  272. octo sound card are symmetric.
  273. audioinjector-octo: Add continuous clock feature
  274. By user request, add a switch to prevent the clocks being stopped when
  275. the stream is paused, stopped or shutdown. Provide access to the switch
  276. by adding a 'non-stop-clocks' parameter to the audioinjector-addons
  277. overlay.
  278. See: https://github.com/raspberrypi/linux/issues/2409
  279. Signed-off-by: Phil Elwell <[email protected]>
  280. sound: Fixes for audioinjector-octo under 4.19
  281. 1. Move the DT alias declaration to the I2C shim in the cases
  282. where the shim is enabled. This works around a problem caused by a
  283. 4.19 commit [1] that generates DT/OF uevents for I2C drivers.
  284. 2. Fix the diagnostics in an error path of the soundcard driver to
  285. correctly identify the reason for the failure to load.
  286. 3. Move the declaration of the clock node in the overlay outside
  287. the I2C node to avoid warnings.
  288. 4. Sort the overlay nodes so that dependencies are only to earlier
  289. fragments, in an attempt to get runtime dtoverlay application to
  290. work (it still doesn't...)
  291. See: https://github.com/Audio-Injector/Octo/issues/14
  292. Signed-off-by: Phil Elwell <[email protected]>
  293. [1] af503716ac14 ("i2c: core: report OF style module alias for devices registered via OF")
  294. ASoC: audioinjector-octo-soundcard: use modern dai_link style
  295. Signed-off-by: Hui Wang <[email protected]>
  296. Driver support for Google voiceHAT soundcard.
  297. ASoC: googlevoicehat-codec: Use correct device when grabbing GPIO
  298. The fixup for the VoiceHAT in 4.18 incorrectly tried to find the
  299. sdmode GPIO pin under the card device, not the codec device.
  300. This failed, and therefore caused the device probe to fail.
  301. Signed-off-by: Dave Stevenson <[email protected]>
  302. ASoC: googlevoicehat-codec: Reformat for kernel coding standards
  303. Fix all whitespace, indentation, and bracing errors.
  304. Signed-off-by: Dave Stevenson <[email protected]>
  305. ASoC: googlevoicehat-codec: Make driver function structure const
  306. Make voicehat_component_driver a const structure.
  307. Signed-off-by: Dave Stevenson <[email protected]>
  308. ASoC: googlevoicehat-codec: Only convert from ms to jiffies once
  309. Minor optimisation and allows to become checkpatch clean.
  310. A msec value is read out of DT or from a define, and convert once to
  311. jiffies, rather than every time that it is used.
  312. Signed-off-by: Dave Stevenson <[email protected]>
  313. Driver and overlay for Allo Katana DAC
  314. Allo Katana DAC: Updated default values
  315. Signed-off-by: Jaikumar <[email protected]>
  316. Added mute stream func
  317. Signed-off-by: Jaikumar <[email protected]>
  318. codecs: Correct Katana minimum volume
  319. Update Katana minimum volume to get the exact 0.5 dB value in each step.
  320. Signed-off-by: Sudeep Kumar <[email protected]>
  321. ASoC: Add generic RPI driver for simple soundcards.
  322. The RPI simple sound card driver provides a generic ALSA SOC card driver
  323. supporting a variety of Pi HAT soundcards. The intention is to avoid
  324. the duplication of code for cards that can't be fully supported by
  325. the soc simple/graph cards but are otherwise almost identical.
  326. This initial commit adds support for the ADAU1977 ADC, Google VoiceHat,
  327. HifiBerry AMP, HifiBerry DAC and RPI DAC.
  328. Signed-off-by: Tim Gover <[email protected]>
  329. ASoC: Use correct card name in rpi-simple driver
  330. Use the specific card name from drvdata instead of the snd_rpi_simple
  331. rpi-simple-soundcard: Use nicer driver name "RPi-simple"
  332. Rename the driver from "RPI simple soundcard" to "RPi-simple" so that
  333. the driver name won't be mangled allowing to be used unaltered as the
  334. card conf filename.
  335. ASoC: rpi-simple-soundcard: use modern dai_link style
  336. Signed-off-by: Hui Wang <[email protected]>
  337. ASoC: Add Kconfig and Makefile for sound/soc/bcm
  338. Signed-off-by: popcornmix <[email protected]>
  339. ASoC: Create a generic Pi Hat WM8804 driver
  340. Reduce the amount of duplicated code by creating a generic driver for
  341. Pi Hat digi cards using the WM8804 codec.
  342. This replaces the
  343. Allo DigiOne, Hifiberry Digi/Pro, JustBoom Digi and IQAudIO Digi
  344. dedicate soundcard drivers with a generic driver.
  345. There are no significant changes to the runtime behavior of the drivers
  346. and end users should not have to change any configuration settings
  347. after upgrading.
  348. Minor changes
  349. * Check the return value of snd_soc_component_update_bits
  350. * Added some pr_debug tracing
  351. * Various checkpatch tidyups
  352. * Updated allodigi-one to use use 128FS at > 96 Khz. This appears to
  353. be an omission in the original driver code so followed the Hifiberry
  354. DAC driver approach.
  355. ASoC: rpi-wm8804-soundcard: use modern dai_link style
  356. Signed-off-by: Matthias Reichl <[email protected]>
  357. rpi-wm8804-soundcard: drop PWRDN register writes
  358. Since kernel 4.0 the PWRDN register bits are under DAPM
  359. control from the wm8804 driver.
  360. Drop code that modifies that register to avoid interfering
  361. with DAPM.
  362. Signed-off-by: Matthias Reichl <[email protected]>
  363. rpi-wm8804-soundcard: configure wm8804 clocks only on rate change
  364. This should avoid clicks when stopping and immediately afterwards
  365. starting a stream with the same samplerate as before.
  366. Signed-off-by: Matthias Reichl <[email protected]>
  367. rpi-wm8804-soundcard: Fixed MCLKDIV for Allo Digione
  368. The Allo Digione board wants a fixed MCLKDIV of 256.
  369. See: https://github.com/raspberrypi/linux/issues/3296
  370. Signed-off-by: Phil Elwell <[email protected]>
  371. ASoC: Add support for AudioSense-Pi add-on soundcard
  372. AudioSense-Pi is a RPi HAT based on a TI's TLV320AIC32x4 stereo codec
  373. This hardware provides multiple audio I/O capabilities to the RPi.
  374. The codec connects to the RPi's SoC through the I2S Bus.
  375. The following devices can be connected through a 3.5mm jack
  376. 1. Line-In: Plain old audio in from mobile phones, PCs, etc.,
  377. 2. Mic-In: Connect a microphone
  378. 3. Line-Out: Connect the output to a speaker
  379. 4. Headphones: Connect a Headphone w or w/o microphones
  380. Multiple Inputs:
  381. It supports the following combinations
  382. 1. Two stereo Line-Inputs and a microphone
  383. 2. One stereo Line-Input and two microphones
  384. 3. Two stereo Line-Inputs, a microphone and
  385. one mono line-input (with h/w hack)
  386. 4. One stereo Line-Input, two microphones and
  387. one mono line-input (with h/w hack)
  388. Multiple Outputs:
  389. Audio output can be routed to the headphones or
  390. speakers (with additional hardware)
  391. Signed-off-by: b-ak <[email protected]>
  392. ASoC: audiosense-pi: use modern dai_link style
  393. Signed-off-by: Hui Wang <[email protected]>
  394. Added driver for the HiFiBerry DAC+ ADC (#2694)
  395. Signed-off-by: Daniel Matuschek <[email protected]>
  396. hifiberry_dacplusadc: switch to snd_soc_dai_set_bclk_ratio
  397. Signed-off-by: Matthias Reichl <[email protected]>
  398. ASoC: hifiberry_dacplusadc: fix DAI link setup
  399. The driver only defines a single DAI link and the code that tries
  400. to setup the second (non-existent) DAI link looks wrong - using dmic
  401. as a CPU/platform driver doesn't make any sense.
  402. The DT overlay doesn't define a dmic property, so the code was never
  403. executed (otherwise it would have resulted in a memory corruption).
  404. So drop the offending code to prevent issues if a dmic property
  405. should be added to the DT overlay.
  406. Signed-off-by: Matthias Reichl <[email protected]>
  407. ASoC: hifiberry_dacplusadc: use modern dai_link style
  408. Signed-off-by: Matthias Reichl <[email protected]>
  409. Audiophonics I-Sabre 9038Q2M DAC driver
  410. Signed-off-by: Audiophonics <[email protected]>
  411. ASoC: i-sabre-q2m: use modern dai_link style
  412. Signed-off-by: Hui Wang <[email protected]>
  413. Added IQaudIO Pi-Codec board support (#2969)
  414. Add support for the IQaudIO Pi-Codec board.
  415. Signed-off-by: Gordon <[email protected]>
  416. Fixed 48k timing issue
  417. ASoC: iqaudio-codec: use modern dai_link style
  418. Signed-off-by: Hui Wang <[email protected]>
  419. adds the Hifiberry DAC+ADC PRO version
  420. This adds the driver for the DAC+ADC PRO version of the Hifiberry soundcard with software controlled PCM1863 ADC
  421. Signed-off-by: Joerg Schambacher [email protected]
  422. Add Hifiberry DAC+DSP soundcard driver (#3224)
  423. Adds the driver for the Hifiberry DAC+DSP. It supports capture and
  424. playback depending on the DSP firmware.
  425. Signed-off-by: Joerg Schambacher <[email protected]>
  426. Allow simultaneous use of JustBoom DAC and Digi
  427. Signed-off-by: Johannes Krude <[email protected]>
  428. Pisound: MIDI communication fixes for scaled down CPU.
  429. * Increased maximum SPI communication speed to avoid running too slow
  430. when the CPU is scaled down and losing MIDI data.
  431. * Keep track of buffer usage in millibytes for higher precision.
  432. Signed-off-by: Giedrius Trainavičius <[email protected]>
  433. sound: Add the HiFiBerry DAC+HD version
  434. This adds the driver for the DAC+HD version supporting HiFiBerry's
  435. PCM179x based DACs. It also adds PLL control for clock generation.
  436. Signed-off-by: Joerg Schambacher <[email protected]>
  437. Fix master mode settings of HiFiBerry DAC+ADC PRO card (#3424)
  438. This patch fixes the board DAI setting when in master-mode.
  439. Wrong setting could have caused random pop noise.
  440. Signed-off-by: Joerg Schambacher <[email protected]>
  441. adds LED OFF feature to HiFiBerry DAC+ADC PRO sound card
  442. This adds a DT overlay parameter 'leds_off' which allows
  443. to switch off the onboard activity LEDs at all times
  444. which has been requested by some users.
  445. Signed-off-by: Joerg Schambacher <[email protected]>
  446. adds LED OFF feature to HiFiBerry DAC+ADC sound card
  447. This adds a DT overlay parameter 'leds_off' which allows
  448. to switch off the onboard activity LEDs at all times
  449. which has been requested by some users.
  450. Signed-off-by: Joerg Schambacher <[email protected]>
  451. adds LED OFF feature to HiFiBerry DAC+/DAC+PRO sound cards
  452. This adds a DT overlay parameter 'leds_off' which allows
  453. to switch off the onboard activity LEDs at all times
  454. which has been requested by some users.
  455. Signed-off-by: Joerg Schambacher <[email protected]>
  456. pisound: Added reading Pisound board hardware revision and exposing it (#3425)
  457. pisound: Added reading Pisound board hardware revision and exposing it in kernel log and sysfs file:
  458. /sys/kernel/pisound/hw_version
  459. Signed-off-by: Giedrius <[email protected]>
  460. Added driver for HiFiBerry Amp amplifier add-on board
  461. The driver contains a low-level hardware driver for the TAS5713 and the
  462. drivers for the Raspberry Pi I2S subsystem.
  463. TAS5713: return error if initialisation fails
  464. Existing TAS5713 driver logs errors during initialisation, but does not return
  465. an error code. Therefore even if initialisation fails, the driver will still be
  466. loaded, but won't work. This patch fixes this. I2C communication error will now
  467. reported correctly by a non-zero return code.
  468. HiFiBerry Amp: fix device-tree problems
  469. Some code to load the driver based on device-tree-overlays was missing. This is added by this patch.
  470. According to 5713 pdf doc CLOCK_CTRL is a readonly status register, and it behaves so. Remove useless setting
  471. sound: pcm512x-codec: Adding 352.8kHz samplerate support
  472. sound/soc: only first codec is master in multicodec setup
  473. When using multiple codecs, at most one codec should generate the master
  474. clock. All codecs except the first are therefore configured for slave
  475. mode.
  476. Signed-off-by: Johannes Krude <[email protected]>
  477. ASoC: Fix snd_soc_get_pcm_runtime usage
  478. Commit [1] changed the snd_soc_get_pcm_runtime to take a dai_link
  479. pointer instead of a string. Patch up the downstream drivers to use
  480. the modified API.
  481. Signed-off-by: Phil Elwell <[email protected]>
  482. [1] 4468189ff307 ("ASoC: soc-core: find rtd via dai_link pointer at snd_soc_get_pcm_runtime()")
  483. Add support for the AudioInjector.net Isolated sound card
  484. This patch adds support for the Audio Injector Isolated sound card.
  485. Signed-off-by: Matt Flax <[email protected]>
  486. Add support for merus-amp soundcard and ma120x0p codec
  487. Add 96KHz rate support to MA120X0P codec and make enable and mute gpio
  488. pins optional.
  489. Signed-off-by: AMuszkat <[email protected]>
  490. Fixes a problem with clock settings of HiFiBerry DAC+ADC PRO (#3545)
  491. This patch fixes a problem of the re-calculation of
  492. i2s-clock and -parameter settings when only the ADC is activated.
  493. Signed-off-by: Joerg Schambacher <[email protected]>
  494. configs: Enable the AD193x codecs
  495. See: https://github.com/raspberrypi/linux/issues/2850
  496. Signed-off-by: Phil Elwell <[email protected]>
  497. Switch to snd_soc_dai_set_bclk_ratio
  498. Replaces obsolete function snd_soc_dai_set_tdm_slot
  499. Signed-off-by: Joerg Schambacher <[email protected]>
  500. Enhances the DAC+ driver to control the optional headphone amplifier
  501. Probes on the I2C bus for TPA6130A2, if successful, it sets DT-parameter
  502. 'status' from 'disabled' to 'okay' using change_sets to enable
  503. the headphone control.
  504. Signed-off-by: Joerg Schambacher [email protected]
  505. Update Allo Piano Dac Driver
  506. Add unique names to the individual dac coded drivers
  507. Remove some of the codec controls that are not used.
  508. Signed-off-by: Paul Hermann <[email protected]>
  509. Fixes an onboard clock detection problem of the PRO versions
  510. Increasing the sleep time after clock selection to 3-4ms
  511. allows the correct detection of all combinations of DAC+ Pro
  512. and DAC+ADC Pro sound cards and the various PI revisions.
  513. Signed-off-by: Joerg Schambacher <[email protected]>
  514. ASoC:ma120x0p: Increase maximum sample rate to 192KHz
  515. Change the maximum sample rate for the amplifier to
  516. 192KHz as given in the Infineon specification.
  517. Signed-off-by: Joerg Schambacher <[email protected]>
  518. ASoC: ma120x0p: Remove unnecessary const specifier
  519. Clang warns:
  520. sound/soc/codecs/ma120x0p.c:891:14: warning: duplicate 'const' declaration specifier [-Wduplicate-decl-specifier]
  521. static const SOC_VALUE_ENUM_SINGLE_DECL(pwr_mode_ctrl,
  522. ^
  523. ./include/sound/soc.h:362:2: note: expanded from macro 'SOC_VALUE_ENUM_SINGLE_DECL'
  524. SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues)
  525. ^
  526. ./include/sound/soc.h:359:2: note: expanded from macro 'SOC_VALUE_ENUM_DOUBLE_DECL'
  527. const struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \
  528. ^
  529. 1 warning generated.
  530. SOC_VALUE_ENUM_DOUBLE_DECL already has a const specifier. Remove the duplicate
  531. const to clean up the warning.
  532. Fixes: 42444979e710 ("Add support for all the downstream rpi sound card drivers")
  533. Signed-off-by: Nathan Chancellor <[email protected]>
  534. ASoC: bcm: allo-piano-dac-plus: Remove unnecessary const specifiers
  535. Clang warns:
  536. sound/soc/bcm/allo-piano-dac-plus.c:66:14: warning: duplicate 'const' declaration specifier [-Wduplicate-decl-specifier]
  537. static const SOC_ENUM_SINGLE_DECL(allo_piano_mode_enum,
  538. ^
  539. ./include/sound/soc.h:355:2: note: expanded from macro 'SOC_ENUM_SINGLE_DECL'
  540. SOC_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xtexts)
  541. ^
  542. ./include/sound/soc.h:352:2: note: expanded from macro 'SOC_ENUM_DOUBLE_DECL'
  543. const struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \
  544. ^
  545. sound/soc/bcm/allo-piano-dac-plus.c:75:14: warning: duplicate 'const' declaration specifier [-Wduplicate-decl-specifier]
  546. static const SOC_ENUM_SINGLE_DECL(allo_piano_dual_mode_enum,
  547. ^
  548. ./include/sound/soc.h:355:2: note: expanded from macro 'SOC_ENUM_SINGLE_DECL'
  549. SOC_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xtexts)
  550. ^
  551. ./include/sound/soc.h:352:2: note: expanded from macro 'SOC_ENUM_DOUBLE_DECL'
  552. const struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \
  553. ^
  554. sound/soc/bcm/allo-piano-dac-plus.c:96:14: warning: duplicate 'const' declaration specifier [-Wduplicate-decl-specifier]
  555. static const SOC_ENUM_SINGLE_DECL(allo_piano_enum,
  556. ^
  557. ./include/sound/soc.h:355:2: note: expanded from macro 'SOC_ENUM_SINGLE_DECL'
  558. SOC_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xtexts)
  559. ^
  560. ./include/sound/soc.h:352:2: note: expanded from macro 'SOC_ENUM_DOUBLE_DECL'
  561. const struct soc_enum name = SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, \
  562. ^
  563. 3 warnings generated.
  564. SOC_VALUE_ENUM_DOUBLE_DECL already has a const specifier. Remove the duplicate
  565. const specifiers to clean up the warnings.
  566. Fixes: 42444979e710 ("Add support for all the downstream rpi sound card drivers")
  567. Signed-off-by: Nathan Chancellor <[email protected]>
  568. rpi-simple-soundcard: Add Dion Audio KIWI streamer
  569. Signed-off-by: Miquel Blauw <[email protected]>
  570. rpi-simple-soundcard: adds definitions for the HiFiBerry AMP3 card
  571. Uses Infineon MA120x0 amplifier and supports full sample rate of 192ksps.
  572. Signed-off-by: Joerg Schambacher <[email protected]>
  573. sound: soc: bcm: Added Sound card driver for Dacberry400 Audio card for Raspberry Pi 400
  574. Added Sound card driver for DACberry400 Audio card.
  575. Signed-off-by: Ashish Vara <[email protected]>
  576. ASoC:ma120x0p: Corrects the volume level display
  577. Fixes the wrongly changed 'limiter volume' display back to -50dB minimum
  578. and sets the correct minimum volume level to -144dB to be aligned with
  579. the controls and display in alsamixer etc.
  580. Signed-off-by: Joerg Schambacher <[email protected]>
  581. ASoC: bcm: Fix Rpi-PROTO and audioinjector.net Pi
  582. As of kernel 5.19 the WM8731 driver has separate I2C and SPI support
  583. modules. Change the Kconfig definitions for the audioinjector.net Pi
  584. and Rpi-PROTO soundcards to select SND_SOC_WM8731_I2C.
  585. See: https://github.com/raspberrypi/linux/issues/5364
  586. Signed-off-by: Phil Elwell <[email protected]>
  587. ASoC: adau1977: Add correct compatible strings
  588. Signed-off-by: Phil Elwell <[email protected]>
  589. ASoC: bcm2835-i2s: Use phys addresses for DAI DMA
  590. Contrary to what struct snd_dmaengine_dai_dma_data suggests, the
  591. configuration of addresses of DMA slave interfaces should be done in
  592. CPU physical addresses.
  593. Signed-off-by: Phil Elwell <[email protected]>
  594. rpi sound cards: Fix Codec Zero rate switching
  595. The Raspberry Pi Codec Zero (and IQaudIO Codec) don't notify the DA7213
  596. codec when it needs to change PLL frequencies. As a result, audio can
  597. be played at the wrong rate - play a 48kHz sound immediately after a
  598. 44.1kHz sound to see the effect, but in some configurations the codec
  599. can lock into the wrong state and always get some rates wrong.
  600. Add the necessary notification to fix the issue.
  601. Signed-off-by: Phil Elwell <[email protected]>
  602. ---
  603. .../devicetree/bindings/vendor-prefixes.txt | 463 ++++++
  604. .../devicetree/bindings/vendor-prefixes.yaml | 2 +
  605. drivers/clk/Kconfig | 6 +
  606. drivers/clk/Makefile | 2 +
  607. drivers/clk/clk-hifiberry-dachd.c | 331 ++++
  608. drivers/clk/clk-hifiberry-dacpro.c | 181 +++
  609. sound/soc/bcm/Kconfig | 306 ++++
  610. sound/soc/bcm/Makefile | 71 +-
  611. sound/soc/bcm/allo-boss-dac.c | 457 ++++++
  612. sound/soc/bcm/allo-boss2-dac.c | 1130 ++++++++++++++
  613. sound/soc/bcm/allo-katana-codec.c | 386 +++++
  614. sound/soc/bcm/allo-piano-dac-plus.c | 1064 +++++++++++++
  615. sound/soc/bcm/allo-piano-dac.c | 122 ++
  616. .../bcm/audioinjector-isolated-soundcard.c | 183 +++
  617. sound/soc/bcm/audioinjector-octo-soundcard.c | 346 +++++
  618. sound/soc/bcm/audioinjector-pi-soundcard.c | 189 +++
  619. sound/soc/bcm/audiosense-pi.c | 248 +++
  620. sound/soc/bcm/bcm2835-i2s.c | 18 +-
  621. sound/soc/bcm/chipdip-dac.c | 275 ++++
  622. sound/soc/bcm/dacberry400.c | 259 ++++
  623. sound/soc/bcm/digidac1-soundcard.c | 421 +++++
  624. sound/soc/bcm/dionaudio_loco-v2.c | 117 ++
  625. sound/soc/bcm/dionaudio_loco.c | 117 ++
  626. sound/soc/bcm/fe-pi-audio.c | 154 ++
  627. sound/soc/bcm/googlevoicehat-codec.c | 214 +++
  628. sound/soc/bcm/hifiberry_dacplus.c | 527 +++++++
  629. sound/soc/bcm/hifiberry_dacplusadc.c | 398 +++++
  630. sound/soc/bcm/hifiberry_dacplusadcpro.c | 605 ++++++++
  631. sound/soc/bcm/hifiberry_dacplusdsp.c | 90 ++
  632. sound/soc/bcm/hifiberry_dacplushd.c | 238 +++
  633. sound/soc/bcm/i-sabre-q2m.c | 159 ++
  634. sound/soc/bcm/iqaudio-codec.c | 278 ++++
  635. sound/soc/bcm/iqaudio-dac.c | 224 +++
  636. sound/soc/bcm/justboom-both.c | 267 ++++
  637. sound/soc/bcm/justboom-dac.c | 147 ++
  638. sound/soc/bcm/pifi-40.c | 284 ++++
  639. sound/soc/bcm/pisound.c | 1241 +++++++++++++++
  640. sound/soc/bcm/rpi-cirrus.c | 1025 ++++++++++++
  641. sound/soc/bcm/rpi-proto.c | 147 ++
  642. sound/soc/bcm/rpi-simple-soundcard.c | 487 ++++++
  643. sound/soc/bcm/rpi-wm8804-soundcard.c | 410 +++++
  644. sound/soc/codecs/Kconfig | 26 +-
  645. sound/soc/codecs/Makefile | 8 +
  646. sound/soc/codecs/adau1977-i2c.c | 10 +
  647. sound/soc/codecs/cs42xx8-i2c.c | 9 +-
  648. sound/soc/codecs/cs42xx8.c | 10 +
  649. sound/soc/codecs/i-sabre-codec.c | 389 +++++
  650. sound/soc/codecs/i-sabre-codec.h | 42 +
  651. sound/soc/codecs/ma120x0p.c | 1380 +++++++++++++++++
  652. sound/soc/codecs/pcm1794a.c | 69 +
  653. sound/soc/codecs/pcm512x.c | 2 +-
  654. sound/soc/codecs/tas5713.c | 360 +++++
  655. sound/soc/codecs/tas5713.h | 210 +++
  656. sound/soc/soc-core.c | 10 +-
  657. sound/usb/card.c | 8 +-
  658. sound/usb/quirks.c | 2 +
  659. 56 files changed, 16103 insertions(+), 21 deletions(-)
  660. create mode 100644 Documentation/devicetree/bindings/vendor-prefixes.txt
  661. create mode 100644 drivers/clk/clk-hifiberry-dachd.c
  662. create mode 100644 drivers/clk/clk-hifiberry-dacpro.c
  663. create mode 100644 sound/soc/bcm/allo-boss-dac.c
  664. create mode 100644 sound/soc/bcm/allo-boss2-dac.c
  665. create mode 100644 sound/soc/bcm/allo-katana-codec.c
  666. create mode 100644 sound/soc/bcm/allo-piano-dac-plus.c
  667. create mode 100644 sound/soc/bcm/allo-piano-dac.c
  668. create mode 100644 sound/soc/bcm/audioinjector-isolated-soundcard.c
  669. create mode 100644 sound/soc/bcm/audioinjector-octo-soundcard.c
  670. create mode 100644 sound/soc/bcm/audioinjector-pi-soundcard.c
  671. create mode 100644 sound/soc/bcm/audiosense-pi.c
  672. create mode 100644 sound/soc/bcm/chipdip-dac.c
  673. create mode 100644 sound/soc/bcm/dacberry400.c
  674. create mode 100644 sound/soc/bcm/digidac1-soundcard.c
  675. create mode 100644 sound/soc/bcm/dionaudio_loco-v2.c
  676. create mode 100644 sound/soc/bcm/dionaudio_loco.c
  677. create mode 100644 sound/soc/bcm/fe-pi-audio.c
  678. create mode 100644 sound/soc/bcm/googlevoicehat-codec.c
  679. create mode 100644 sound/soc/bcm/hifiberry_dacplus.c
  680. create mode 100644 sound/soc/bcm/hifiberry_dacplusadc.c
  681. create mode 100644 sound/soc/bcm/hifiberry_dacplusadcpro.c
  682. create mode 100644 sound/soc/bcm/hifiberry_dacplusdsp.c
  683. create mode 100644 sound/soc/bcm/hifiberry_dacplushd.c
  684. create mode 100644 sound/soc/bcm/i-sabre-q2m.c
  685. create mode 100644 sound/soc/bcm/iqaudio-codec.c
  686. create mode 100644 sound/soc/bcm/iqaudio-dac.c
  687. create mode 100644 sound/soc/bcm/justboom-both.c
  688. create mode 100644 sound/soc/bcm/justboom-dac.c
  689. create mode 100644 sound/soc/bcm/pifi-40.c
  690. create mode 100644 sound/soc/bcm/pisound.c
  691. create mode 100644 sound/soc/bcm/rpi-cirrus.c
  692. create mode 100644 sound/soc/bcm/rpi-proto.c
  693. create mode 100644 sound/soc/bcm/rpi-simple-soundcard.c
  694. create mode 100644 sound/soc/bcm/rpi-wm8804-soundcard.c
  695. create mode 100644 sound/soc/codecs/i-sabre-codec.c
  696. create mode 100644 sound/soc/codecs/i-sabre-codec.h
  697. create mode 100644 sound/soc/codecs/ma120x0p.c
  698. create mode 100644 sound/soc/codecs/pcm1794a.c
  699. create mode 100644 sound/soc/codecs/tas5713.c
  700. create mode 100644 sound/soc/codecs/tas5713.h
  701. --- /dev/null
  702. +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
  703. @@ -0,0 +1,463 @@
  704. +Device tree binding vendor prefix registry. Keep list in alphabetical order.
  705. +
  706. +This isn't an exhaustive list, but you should add new prefixes to it before
  707. +using them to avoid name-space collisions.
  708. +
  709. +abilis Abilis Systems
  710. +abracon Abracon Corporation
  711. +actions Actions Semiconductor Co., Ltd.
  712. +active-semi Active-Semi International Inc
  713. +ad Avionic Design GmbH
  714. +adafruit Adafruit Industries, LLC
  715. +adapteva Adapteva, Inc.
  716. +adaptrum Adaptrum, Inc.
  717. +adh AD Holdings Plc.
  718. +adi Analog Devices, Inc.
  719. +advantech Advantech Corporation
  720. +aeroflexgaisler Aeroflex Gaisler AB
  721. +al Annapurna Labs
  722. +allo Allo.com
  723. +allwinner Allwinner Technology Co., Ltd.
  724. +alphascale AlphaScale Integrated Circuits Systems, Inc.
  725. +altr Altera Corp.
  726. +amarula Amarula Solutions
  727. +amazon Amazon.com, Inc.
  728. +amcc Applied Micro Circuits Corporation (APM, formally AMCC)
  729. +amd Advanced Micro Devices (AMD), Inc.
  730. +amediatech Shenzhen Amediatech Technology Co., Ltd
  731. +amlogic Amlogic, Inc.
  732. +ampire Ampire Co., Ltd.
  733. +ams AMS AG
  734. +amstaos AMS-Taos Inc.
  735. +analogix Analogix Semiconductor, Inc.
  736. +andestech Andes Technology Corporation
  737. +apm Applied Micro Circuits Corporation (APM)
  738. +aptina Aptina Imaging
  739. +arasan Arasan Chip Systems
  740. +archermind ArcherMind Technology (Nanjing) Co., Ltd.
  741. +arctic Arctic Sand
  742. +aries Aries Embedded GmbH
  743. +arm ARM Ltd.
  744. +armadeus ARMadeus Systems SARL
  745. +arrow Arrow Electronics
  746. +artesyn Artesyn Embedded Technologies Inc.
  747. +asahi-kasei Asahi Kasei Corp.
  748. +aspeed ASPEED Technology Inc.
  749. +asus AsusTek Computer Inc.
  750. +atlas Atlas Scientific LLC
  751. +atmel Atmel Corporation
  752. +auo AU Optronics Corporation
  753. +auvidea Auvidea GmbH
  754. +avago Avago Technologies
  755. +avia avia semiconductor
  756. +avic Shanghai AVIC Optoelectronics Co., Ltd.
  757. +avnet Avnet, Inc.
  758. +axentia Axentia Technologies AB
  759. +axis Axis Communications AB
  760. +bananapi BIPAI KEJI LIMITED
  761. +bhf Beckhoff Automation GmbH & Co. KG
  762. +bitmain Bitmain Technologies
  763. +blokaslabs Vilniaus Blokas UAB
  764. +boe BOE Technology Group Co., Ltd.
  765. +bosch Bosch Sensortec GmbH
  766. +boundary Boundary Devices Inc.
  767. +brcm Broadcom Corporation
  768. +buffalo Buffalo, Inc.
  769. +bticino Bticino International
  770. +calxeda Calxeda
  771. +capella Capella Microsystems, Inc
  772. +cascoda Cascoda, Ltd.
  773. +catalyst Catalyst Semiconductor, Inc.
  774. +cavium Cavium, Inc.
  775. +cdns Cadence Design Systems Inc.
  776. +cdtech CDTech(H.K.) Electronics Limited
  777. +ceva Ceva, Inc.
  778. +chipidea Chipidea, Inc
  779. +chipone ChipOne
  780. +chipspark ChipSPARK
  781. +chrp Common Hardware Reference Platform
  782. +chunghwa Chunghwa Picture Tubes Ltd.
  783. +ciaa Computadora Industrial Abierta Argentina
  784. +cirrus Cirrus Logic, Inc.
  785. +cloudengines Cloud Engines, Inc.
  786. +cnm Chips&Media, Inc.
  787. +cnxt Conexant Systems, Inc.
  788. +compulab CompuLab Ltd.
  789. +cortina Cortina Systems, Inc.
  790. +cosmic Cosmic Circuits
  791. +crane Crane Connectivity Solutions
  792. +creative Creative Technology Ltd
  793. +crystalfontz Crystalfontz America, Inc.
  794. +csky Hangzhou C-SKY Microsystems Co., Ltd
  795. +cubietech Cubietech, Ltd.
  796. +cypress Cypress Semiconductor Corporation
  797. +cznic CZ.NIC, z.s.p.o.
  798. +dallas Maxim Integrated Products (formerly Dallas Semiconductor)
  799. +dataimage DataImage, Inc.
  800. +davicom DAVICOM Semiconductor, Inc.
  801. +delta Delta Electronics, Inc.
  802. +denx Denx Software Engineering
  803. +devantech Devantech, Ltd.
  804. +dh DH electronics GmbH
  805. +digi Digi International Inc.
  806. +digilent Diglent, Inc.
  807. +dioo Dioo Microcircuit Co., Ltd
  808. +dlc DLC Display Co., Ltd.
  809. +dlg Dialog Semiconductor
  810. +dlink D-Link Corporation
  811. +dmo Data Modul AG
  812. +domintech Domintech Co., Ltd.
  813. +dongwoon Dongwoon Anatech
  814. +dptechnics DPTechnics
  815. +dragino Dragino Technology Co., Limited
  816. +ea Embedded Artists AB
  817. +ebs-systart EBS-SYSTART GmbH
  818. +ebv EBV Elektronik
  819. +eckelmann Eckelmann AG
  820. +edt Emerging Display Technologies
  821. +eeti eGalax_eMPIA Technology Inc
  822. +elan Elan Microelectronic Corp.
  823. +elgin Elgin S/A.
  824. +embest Shenzhen Embest Technology Co., Ltd.
  825. +emlid Emlid, Ltd.
  826. +emmicro EM Microelectronic
  827. +emtrion emtrion GmbH
  828. +endless Endless Mobile, Inc.
  829. +energymicro Silicon Laboratories (formerly Energy Micro AS)
  830. +engicam Engicam S.r.l.
  831. +epcos EPCOS AG
  832. +epfl Ecole Polytechnique Fédérale de Lausanne
  833. +epson Seiko Epson Corp.
  834. +est ESTeem Wireless Modems
  835. +ettus NI Ettus Research
  836. +eukrea Eukréa Electromatique
  837. +everest Everest Semiconductor Co. Ltd.
  838. +everspin Everspin Technologies, Inc.
  839. +exar Exar Corporation
  840. +excito Excito
  841. +ezchip EZchip Semiconductor
  842. +facebook Facebook
  843. +fairphone Fairphone B.V.
  844. +faraday Faraday Technology Corporation
  845. +fastrax Fastrax Oy
  846. +fcs Fairchild Semiconductor
  847. +feiyang Shenzhen Fly Young Technology Co.,LTD.
  848. +firefly Firefly
  849. +focaltech FocalTech Systems Co.,Ltd
  850. +friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd
  851. +fsl Freescale Semiconductor
  852. +fujitsu Fujitsu Ltd.
  853. +gateworks Gateworks Corporation
  854. +gcw Game Consoles Worldwide
  855. +ge General Electric Company
  856. +geekbuying GeekBuying
  857. +gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.
  858. +GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc.
  859. +geniatech Geniatech, Inc.
  860. +giantec Giantec Semiconductor, Inc.
  861. +giantplus Giantplus Technology Co., Ltd.
  862. +globalscale Globalscale Technologies, Inc.
  863. +globaltop GlobalTop Technology, Inc.
  864. +gmt Global Mixed-mode Technology, Inc.
  865. +goodix Shenzhen Huiding Technology Co., Ltd.
  866. +google Google, Inc.
  867. +grinn Grinn
  868. +grmn Garmin Limited
  869. +gumstix Gumstix, Inc.
  870. +gw Gateworks Corporation
  871. +hannstar HannStar Display Corporation
  872. +haoyu Haoyu Microelectronic Co. Ltd.
  873. +hardkernel Hardkernel Co., Ltd
  874. +hideep HiDeep Inc.
  875. +himax Himax Technologies, Inc.
  876. +hisilicon Hisilicon Limited.
  877. +hit Hitachi Ltd.
  878. +hitex Hitex Development Tools
  879. +holt Holt Integrated Circuits, Inc.
  880. +honeywell Honeywell
  881. +hp Hewlett Packard
  882. +holtek Holtek Semiconductor, Inc.
  883. +hwacom HwaCom Systems Inc.
  884. +i2se I2SE GmbH
  885. +ibm International Business Machines (IBM)
  886. +icplus IC Plus Corp.
  887. +idt Integrated Device Technologies, Inc.
  888. +ifi Ingenieurburo Fur Ic-Technologie (I/F/I)
  889. +ilitek ILI Technology Corporation (ILITEK)
  890. +img Imagination Technologies Ltd.
  891. +infineon Infineon Technologies
  892. +inforce Inforce Computing
  893. +ingenic Ingenic Semiconductor
  894. +innolux Innolux Corporation
  895. +inside-secure INSIDE Secure
  896. +intel Intel Corporation
  897. +intercontrol Inter Control Group
  898. +invensense InvenSense Inc.
  899. +inversepath Inverse Path
  900. +iom Iomega Corporation
  901. +isee ISEE 2007 S.L.
  902. +isil Intersil
  903. +issi Integrated Silicon Solutions Inc.
  904. +itead ITEAD Intelligent Systems Co.Ltd
  905. +iwave iWave Systems Technologies Pvt. Ltd.
  906. +jdi Japan Display Inc.
  907. +jedec JEDEC Solid State Technology Association
  908. +jianda Jiandangjing Technology Co., Ltd.
  909. +karo Ka-Ro electronics GmbH
  910. +keithkoep Keith & Koep GmbH
  911. +keymile Keymile GmbH
  912. +khadas Khadas
  913. +kiebackpeter Kieback & Peter GmbH
  914. +kinetic Kinetic Technologies
  915. +kingdisplay King & Display Technology Co., Ltd.
  916. +kingnovel Kingnovel Technology Co., Ltd.
  917. +koe Kaohsiung Opto-Electronics Inc.
  918. +kosagi Sutajio Ko-Usagi PTE Ltd.
  919. +kyo Kyocera Corporation
  920. +lacie LaCie
  921. +laird Laird PLC
  922. +lantiq Lantiq Semiconductor
  923. +lattice Lattice Semiconductor
  924. +lego LEGO Systems A/S
  925. +lemaker Shenzhen LeMaker Technology Co., Ltd.
  926. +lenovo Lenovo Group Ltd.
  927. +lg LG Corporation
  928. +libretech Shenzhen Libre Technology Co., Ltd
  929. +licheepi Lichee Pi
  930. +linaro Linaro Limited
  931. +linksys Belkin International, Inc. (Linksys)
  932. +linux Linux-specific binding
  933. +linx Linx Technologies
  934. +lltc Linear Technology Corporation
  935. +logicpd Logic PD, Inc.
  936. +lsi LSI Corp. (LSI Logic)
  937. +lwn Liebherr-Werk Nenzing GmbH
  938. +macnica Macnica Americas
  939. +marvell Marvell Technology Group Ltd.
  940. +maxim Maxim Integrated Products
  941. +mbvl Mobiveil Inc.
  942. +mcube mCube
  943. +meas Measurement Specialties
  944. +mediatek MediaTek Inc.
  945. +megachips MegaChips
  946. +mele Shenzhen MeLE Digital Technology Ltd.
  947. +melexis Melexis N.V.
  948. +melfas MELFAS Inc.
  949. +mellanox Mellanox Technologies
  950. +memsic MEMSIC Inc.
  951. +merrii Merrii Technology Co., Ltd.
  952. +micrel Micrel Inc.
  953. +microchip Microchip Technology Inc.
  954. +microcrystal Micro Crystal AG
  955. +micron Micron Technology Inc.
  956. +mikroe MikroElektronika d.o.o.
  957. +minix MINIX Technology Ltd.
  958. +miramems MiraMEMS Sensing Technology Co., Ltd.
  959. +mitsubishi Mitsubishi Electric Corporation
  960. +mosaixtech Mosaix Technologies, Inc.
  961. +motorola Motorola, Inc.
  962. +moxa Moxa Inc.
  963. +mpl MPL AG
  964. +mqmaker mqmaker Inc.
  965. +mscc Microsemi Corporation
  966. +msi Micro-Star International Co. Ltd.
  967. +mti Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
  968. +multi-inno Multi-Inno Technology Co.,Ltd
  969. +mundoreader Mundo Reader S.L.
  970. +murata Murata Manufacturing Co., Ltd.
  971. +mxicy Macronix International Co., Ltd.
  972. +myir MYIR Tech Limited
  973. +national National Semiconductor
  974. +nec NEC LCD Technologies, Ltd.
  975. +neonode Neonode Inc.
  976. +netgear NETGEAR
  977. +netlogic Broadcom Corporation (formerly NetLogic Microsystems)
  978. +netron-dy Netron DY
  979. +netxeon Shenzhen Netxeon Technology CO., LTD
  980. +nexbox Nexbox
  981. +nextthing Next Thing Co.
  982. +newhaven Newhaven Display International
  983. +ni National Instruments
  984. +nintendo Nintendo
  985. +nlt NLT Technologies, Ltd.
  986. +nokia Nokia
  987. +nordic Nordic Semiconductor
  988. +novtech NovTech, Inc.
  989. +nutsboard NutsBoard
  990. +nuvoton Nuvoton Technology Corporation
  991. +nvd New Vision Display
  992. +nvidia NVIDIA
  993. +nxp NXP Semiconductors
  994. +okaya Okaya Electric America, Inc.
  995. +oki Oki Electric Industry Co., Ltd.
  996. +olimex OLIMEX Ltd.
  997. +olpc One Laptop Per Child
  998. +onion Onion Corporation
  999. +onnn ON Semiconductor Corp.
  1000. +ontat On Tat Industrial Company
  1001. +opalkelly Opal Kelly Incorporated
  1002. +opencores OpenCores.org
  1003. +openrisc OpenRISC.io
  1004. +option Option NV
  1005. +oranth Shenzhen Oranth Technology Co., Ltd.
  1006. +ORCL Oracle Corporation
  1007. +orisetech Orise Technology
  1008. +ortustech Ortus Technology Co., Ltd.
  1009. +ovti OmniVision Technologies
  1010. +oxsemi Oxford Semiconductor, Ltd.
  1011. +panasonic Panasonic Corporation
  1012. +parade Parade Technologies Inc.
  1013. +pda Precision Design Associates, Inc.
  1014. +pericom Pericom Technology Inc.
  1015. +pervasive Pervasive Displays, Inc.
  1016. +phicomm PHICOMM Co., Ltd.
  1017. +phytec PHYTEC Messtechnik GmbH
  1018. +picochip Picochip Ltd
  1019. +pine64 Pine64
  1020. +pixcir PIXCIR MICROELECTRONICS Co., Ltd
  1021. +plantower Plantower Co., Ltd
  1022. +plathome Plat'Home Co., Ltd.
  1023. +plda PLDA
  1024. +plx Broadcom Corporation (formerly PLX Technology)
  1025. +pni PNI Sensor Corporation
  1026. +portwell Portwell Inc.
  1027. +poslab Poslab Technology Co., Ltd.
  1028. +powervr PowerVR (deprecated, use img)
  1029. +probox2 PROBOX2 (by W2COMP Co., Ltd.)
  1030. +pulsedlight PulsedLight, Inc
  1031. +qca Qualcomm Atheros, Inc.
  1032. +qcom Qualcomm Technologies, Inc
  1033. +qemu QEMU, a generic and open source machine emulator and virtualizer
  1034. +qi Qi Hardware
  1035. +qiaodian QiaoDian XianShi Corporation
  1036. +qnap QNAP Systems, Inc.
  1037. +radxa Radxa
  1038. +raidsonic RaidSonic Technology GmbH
  1039. +ralink Mediatek/Ralink Technology Corp.
  1040. +ramtron Ramtron International
  1041. +raspberrypi Raspberry Pi Foundation
  1042. +raydium Raydium Semiconductor Corp.
  1043. +rda Unisoc Communications, Inc.
  1044. +realtek Realtek Semiconductor Corp.
  1045. +renesas Renesas Electronics Corporation
  1046. +richtek Richtek Technology Corporation
  1047. +ricoh Ricoh Co. Ltd.
  1048. +rikomagic Rikomagic Tech Corp. Ltd
  1049. +riscv RISC-V Foundation
  1050. +rockchip Fuzhou Rockchip Electronics Co., Ltd
  1051. +rohm ROHM Semiconductor Co., Ltd
  1052. +roofull Shenzhen Roofull Technology Co, Ltd
  1053. +samsung Samsung Semiconductor
  1054. +samtec Samtec/Softing company
  1055. +sancloud Sancloud Ltd
  1056. +sandisk Sandisk Corporation
  1057. +sbs Smart Battery System
  1058. +schindler Schindler
  1059. +seagate Seagate Technology PLC
  1060. +semtech Semtech Corporation
  1061. +sensirion Sensirion AG
  1062. +sff Small Form Factor Committee
  1063. +sgd Solomon Goldentek Display Corporation
  1064. +sgx SGX Sensortech
  1065. +sharp Sharp Corporation
  1066. +shimafuji Shimafuji Electric, Inc.
  1067. +si-en Si-En Technology Ltd.
  1068. +sifive SiFive, Inc.
  1069. +sigma Sigma Designs, Inc.
  1070. +sii Seiko Instruments, Inc.
  1071. +sil Silicon Image
  1072. +silabs Silicon Laboratories
  1073. +silead Silead Inc.
  1074. +silergy Silergy Corp.
  1075. +siliconmitus Silicon Mitus, Inc.
  1076. +simtek
  1077. +sirf SiRF Technology, Inc.
  1078. +sis Silicon Integrated Systems Corp.
  1079. +sitronix Sitronix Technology Corporation
  1080. +skyworks Skyworks Solutions, Inc.
  1081. +smsc Standard Microsystems Corporation
  1082. +snps Synopsys, Inc.
  1083. +socionext Socionext Inc.
  1084. +solidrun SolidRun
  1085. +solomon Solomon Systech Limited
  1086. +sony Sony Corporation
  1087. +spansion Spansion Inc.
  1088. +sprd Spreadtrum Communications Inc.
  1089. +sst Silicon Storage Technology, Inc.
  1090. +st STMicroelectronics
  1091. +starry Starry Electronic Technology (ShenZhen) Co., LTD
  1092. +startek Startek
  1093. +ste ST-Ericsson
  1094. +stericsson ST-Ericsson
  1095. +summit Summit microelectronics
  1096. +sunchip Shenzhen Sunchip Technology Co., Ltd
  1097. +SUNW Sun Microsystems, Inc
  1098. +swir Sierra Wireless
  1099. +syna Synaptics Inc.
  1100. +synology Synology, Inc.
  1101. +tbs TBS Technologies
  1102. +tbs-biometrics Touchless Biometric Systems AG
  1103. +tcg Trusted Computing Group
  1104. +tcl Toby Churchill Ltd.
  1105. +technexion TechNexion
  1106. +technologic Technologic Systems
  1107. +tempo Tempo Semiconductor
  1108. +techstar Shenzhen Techstar Electronics Co., Ltd.
  1109. +terasic Terasic Inc.
  1110. +thine THine Electronics, Inc.
  1111. +ti Texas Instruments
  1112. +tianma Tianma Micro-electronics Co., Ltd.
  1113. +tlm Trusted Logic Mobility
  1114. +tmt Tecon Microprocessor Technologies, LLC.
  1115. +topeet Topeet
  1116. +toradex Toradex AG
  1117. +toshiba Toshiba Corporation
  1118. +toumaz Toumaz
  1119. +tpk TPK U.S.A. LLC
  1120. +tplink TP-LINK Technologies Co., Ltd.
  1121. +tpo TPO
  1122. +tronfy Tronfy
  1123. +tronsmart Tronsmart
  1124. +truly Truly Semiconductors Limited
  1125. +tsd Theobroma Systems Design und Consulting GmbH
  1126. +tyan Tyan Computer Corporation
  1127. +u-blox u-blox
  1128. +ucrobotics uCRobotics
  1129. +ubnt Ubiquiti Networks
  1130. +udoo Udoo
  1131. +uniwest United Western Technologies Corp (UniWest)
  1132. +upisemi uPI Semiconductor Corp.
  1133. +urt United Radiant Technology Corporation
  1134. +usi Universal Scientific Industrial Co., Ltd.
  1135. +v3 V3 Semiconductor
  1136. +vamrs Vamrs Ltd.
  1137. +variscite Variscite Ltd.
  1138. +via VIA Technologies, Inc.
  1139. +virtio Virtual I/O Device Specification, developed by the OASIS consortium
  1140. +vishay Vishay Intertechnology, Inc
  1141. +vitesse Vitesse Semiconductor Corporation
  1142. +vivante Vivante Corporation
  1143. +vocore VoCore Studio
  1144. +voipac Voipac Technologies s.r.o.
  1145. +vot Vision Optical Technology Co., Ltd.
  1146. +wd Western Digital Corp.
  1147. +wetek WeTek Electronics, limited.
  1148. +wexler Wexler
  1149. +whwave Shenzhen whwave Electronics, Inc.
  1150. +wi2wi Wi2Wi, Inc.
  1151. +winbond Winbond Electronics corp.
  1152. +winstar Winstar Display Corp.
  1153. +wlf Wolfson Microelectronics
  1154. +wm Wondermedia Technologies, Inc.
  1155. +x-powers X-Powers
  1156. +xes Extreme Engineering Solutions (X-ES)
  1157. +xillybus Xillybus Ltd.
  1158. +xlnx Xilinx
  1159. +xunlong Shenzhen Xunlong Software CO.,Limited
  1160. +ysoft Y Soft Corporation a.s.
  1161. +zarlink Zarlink Semiconductor
  1162. +zeitec ZEITEC Semiconductor Co., LTD.
  1163. +zidoo Shenzhen Zidoo Technology Co., Ltd.
  1164. +zii Zodiac Inflight Innovations
  1165. +zte ZTE Corp.
  1166. +zyxel Zyxel Communications Corp.
  1167. --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
  1168. +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
  1169. @@ -196,6 +196,8 @@ patternProperties:
  1170. description: Beckhoff Automation GmbH & Co. KG
  1171. "^bitmain,.*":
  1172. description: Bitmain Technologies
  1173. + "^blokaslabs,.*":
  1174. + description: Vilniaus Blokas UAB
  1175. "^blutek,.*":
  1176. description: BluTek Power
  1177. "^boe,.*":
  1178. --- a/drivers/clk/Kconfig
  1179. +++ b/drivers/clk/Kconfig
  1180. @@ -98,6 +98,12 @@ config COMMON_CLK_HI655X
  1181. multi-function device has one fixed-rate oscillator, clocked
  1182. at 32KHz.
  1183. +config COMMON_CLK_HIFIBERRY_DACPLUSHD
  1184. + tristate
  1185. +
  1186. +config COMMON_CLK_HIFIBERRY_DACPRO
  1187. + tristate
  1188. +
  1189. config COMMON_CLK_SCMI
  1190. tristate "Clock driver controlled via SCMI interface"
  1191. depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
  1192. --- a/drivers/clk/Makefile
  1193. +++ b/drivers/clk/Makefile
  1194. @@ -45,6 +45,8 @@ obj-$(CONFIG_COMMON_CLK_LAN966X) += clk-
  1195. obj-$(CONFIG_COMMON_CLK_LOCHNAGAR) += clk-lochnagar.o
  1196. obj-$(CONFIG_MACH_LOONGSON32) += clk-loongson1.o
  1197. obj-$(CONFIG_COMMON_CLK_LOONGSON2) += clk-loongson2.o
  1198. +obj-$(CONFIG_COMMON_CLK_HIFIBERRY_DACPRO) += clk-hifiberry-dacpro.o
  1199. +obj-$(CONFIG_COMMON_CLK_HIFIBERRY_DACPLUSHD) += clk-hifiberry-dachd.o
  1200. obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
  1201. obj-$(CONFIG_COMMON_CLK_MAX9485) += clk-max9485.o
  1202. obj-$(CONFIG_ARCH_MILBEAUT_M10V) += clk-milbeaut.o
  1203. --- /dev/null
  1204. +++ b/drivers/clk/clk-hifiberry-dachd.c
  1205. @@ -0,0 +1,331 @@
  1206. +// SPDX-License-Identifier: GPL-2.0
  1207. +/*
  1208. + * Clock Driver for HiFiBerry DAC+ HD
  1209. + *
  1210. + * Author: Joerg Schambacher, i2Audio GmbH for HiFiBerry
  1211. + * Copyright 2020
  1212. + *
  1213. + * This program is free software; you can redistribute it and/or
  1214. + * modify it under the terms of the GNU General Public License
  1215. + * version 2 as published by the Free Software Foundation.
  1216. + *
  1217. + * This program is distributed in the hope that it will be useful, but
  1218. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  1219. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1220. + * General Public License for more details.
  1221. + */
  1222. +
  1223. +#include <linux/clk-provider.h>
  1224. +#include <linux/clk.h>
  1225. +#include <linux/kernel.h>
  1226. +#include <linux/module.h>
  1227. +#include <linux/of.h>
  1228. +#include <linux/slab.h>
  1229. +#include <linux/platform_device.h>
  1230. +#include <linux/i2c.h>
  1231. +#include <linux/regmap.h>
  1232. +
  1233. +#define NO_PLL_RESET 0
  1234. +#define PLL_RESET 1
  1235. +#define HIFIBERRY_PLL_MAX_REGISTER 256
  1236. +#define DEFAULT_RATE 44100
  1237. +
  1238. +static struct reg_default hifiberry_pll_reg_defaults[] = {
  1239. + {0x02, 0x53}, {0x03, 0x00}, {0x07, 0x20}, {0x0F, 0x00},
  1240. + {0x10, 0x0D}, {0x11, 0x1D}, {0x12, 0x0D}, {0x13, 0x8C},
  1241. + {0x14, 0x8C}, {0x15, 0x8C}, {0x16, 0x8C}, {0x17, 0x8C},
  1242. + {0x18, 0x2A}, {0x1C, 0x00}, {0x1D, 0x0F}, {0x1F, 0x00},
  1243. + {0x2A, 0x00}, {0x2C, 0x00}, {0x2F, 0x00}, {0x30, 0x00},
  1244. + {0x31, 0x00}, {0x32, 0x00}, {0x34, 0x00}, {0x37, 0x00},
  1245. + {0x38, 0x00}, {0x39, 0x00}, {0x3A, 0x00}, {0x3B, 0x01},
  1246. + {0x3E, 0x00}, {0x3F, 0x00}, {0x40, 0x00}, {0x41, 0x00},
  1247. + {0x5A, 0x00}, {0x5B, 0x00}, {0x95, 0x00}, {0x96, 0x00},
  1248. + {0x97, 0x00}, {0x98, 0x00}, {0x99, 0x00}, {0x9A, 0x00},
  1249. + {0x9B, 0x00}, {0xA2, 0x00}, {0xA3, 0x00}, {0xA4, 0x00},
  1250. + {0xB7, 0x92},
  1251. + {0x1A, 0x3D}, {0x1B, 0x09}, {0x1E, 0xF3}, {0x20, 0x13},
  1252. + {0x21, 0x75}, {0x2B, 0x04}, {0x2D, 0x11}, {0x2E, 0xE0},
  1253. + {0x3D, 0x7A},
  1254. + {0x35, 0x9D}, {0x36, 0x00}, {0x3C, 0x42},
  1255. + { 177, 0xAC},
  1256. +};
  1257. +static struct reg_default common_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
  1258. +static int num_common_pll_regs;
  1259. +static struct reg_default dedicated_192k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
  1260. +static int num_dedicated_192k_pll_regs;
  1261. +static struct reg_default dedicated_96k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
  1262. +static int num_dedicated_96k_pll_regs;
  1263. +static struct reg_default dedicated_48k_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
  1264. +static int num_dedicated_48k_pll_regs;
  1265. +static struct reg_default dedicated_176k4_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
  1266. +static int num_dedicated_176k4_pll_regs;
  1267. +static struct reg_default dedicated_88k2_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
  1268. +static int num_dedicated_88k2_pll_regs;
  1269. +static struct reg_default dedicated_44k1_pll_regs[HIFIBERRY_PLL_MAX_REGISTER];
  1270. +static int num_dedicated_44k1_pll_regs;
  1271. +
  1272. +/**
  1273. + * struct clk_hifiberry_drvdata - Common struct to the HiFiBerry DAC HD Clk
  1274. + * @hw: clk_hw for the common clk framework
  1275. + */
  1276. +struct clk_hifiberry_drvdata {
  1277. + struct regmap *regmap;
  1278. + struct clk *clk;
  1279. + struct clk_hw hw;
  1280. + unsigned long rate;
  1281. +};
  1282. +
  1283. +#define to_hifiberry_clk(_hw) \
  1284. + container_of(_hw, struct clk_hifiberry_drvdata, hw)
  1285. +
  1286. +static int clk_hifiberry_dachd_write_pll_regs(struct regmap *regmap,
  1287. + struct reg_default *regs,
  1288. + int num, int do_pll_reset)
  1289. +{
  1290. + int i;
  1291. + int ret = 0;
  1292. + char pll_soft_reset[] = { 177, 0xAC, };
  1293. +
  1294. + for (i = 0; i < num; i++) {
  1295. + ret |= regmap_write(regmap, regs[i].reg, regs[i].def);
  1296. + if (ret)
  1297. + return ret;
  1298. + }
  1299. + if (do_pll_reset) {
  1300. + ret |= regmap_write(regmap, pll_soft_reset[0],
  1301. + pll_soft_reset[1]);
  1302. + mdelay(10);
  1303. + }
  1304. + return ret;
  1305. +}
  1306. +
  1307. +static unsigned long clk_hifiberry_dachd_recalc_rate(struct clk_hw *hw,
  1308. + unsigned long parent_rate)
  1309. +{
  1310. + return to_hifiberry_clk(hw)->rate;
  1311. +}
  1312. +
  1313. +static long clk_hifiberry_dachd_round_rate(struct clk_hw *hw,
  1314. + unsigned long rate, unsigned long *parent_rate)
  1315. +{
  1316. + return rate;
  1317. +}
  1318. +
  1319. +static int clk_hifiberry_dachd_set_rate(struct clk_hw *hw,
  1320. + unsigned long rate, unsigned long parent_rate)
  1321. +{
  1322. + int ret;
  1323. + struct clk_hifiberry_drvdata *drvdata = to_hifiberry_clk(hw);
  1324. +
  1325. + switch (rate) {
  1326. + case 44100:
  1327. + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
  1328. + dedicated_44k1_pll_regs, num_dedicated_44k1_pll_regs,
  1329. + PLL_RESET);
  1330. + break;
  1331. + case 88200:
  1332. + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
  1333. + dedicated_88k2_pll_regs, num_dedicated_88k2_pll_regs,
  1334. + PLL_RESET);
  1335. + break;
  1336. + case 176400:
  1337. + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
  1338. + dedicated_176k4_pll_regs, num_dedicated_176k4_pll_regs,
  1339. + PLL_RESET);
  1340. + break;
  1341. + case 48000:
  1342. + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
  1343. + dedicated_48k_pll_regs, num_dedicated_48k_pll_regs,
  1344. + PLL_RESET);
  1345. + break;
  1346. + case 96000:
  1347. + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
  1348. + dedicated_96k_pll_regs, num_dedicated_96k_pll_regs,
  1349. + PLL_RESET);
  1350. + break;
  1351. + case 192000:
  1352. + ret = clk_hifiberry_dachd_write_pll_regs(drvdata->regmap,
  1353. + dedicated_192k_pll_regs, num_dedicated_192k_pll_regs,
  1354. + PLL_RESET);
  1355. + break;
  1356. + default:
  1357. + ret = -EINVAL;
  1358. + break;
  1359. + }
  1360. + to_hifiberry_clk(hw)->rate = rate;
  1361. +
  1362. + return ret;
  1363. +}
  1364. +
  1365. +const struct clk_ops clk_hifiberry_dachd_rate_ops = {
  1366. + .recalc_rate = clk_hifiberry_dachd_recalc_rate,
  1367. + .round_rate = clk_hifiberry_dachd_round_rate,
  1368. + .set_rate = clk_hifiberry_dachd_set_rate,
  1369. +};
  1370. +
  1371. +static int clk_hifiberry_get_prop_values(struct device *dev,
  1372. + char *prop_name,
  1373. + struct reg_default *regs)
  1374. +{
  1375. + int ret;
  1376. + int i;
  1377. + u8 tmp[2 * HIFIBERRY_PLL_MAX_REGISTER];
  1378. +
  1379. + ret = of_property_read_variable_u8_array(dev->of_node, prop_name,
  1380. + tmp, 0, 2 * HIFIBERRY_PLL_MAX_REGISTER);
  1381. + if (ret < 0)
  1382. + return ret;
  1383. + if (ret & 1) {
  1384. + dev_err(dev,
  1385. + "%s <%s> -> #%i odd number of bytes for reg/val pairs!",
  1386. + __func__,
  1387. + prop_name,
  1388. + ret);
  1389. + return -EINVAL;
  1390. + }
  1391. + ret /= 2;
  1392. + for (i = 0; i < ret; i++) {
  1393. + regs[i].reg = (u32)tmp[2 * i];
  1394. + regs[i].def = (u32)tmp[2 * i + 1];
  1395. + }
  1396. + return ret;
  1397. +}
  1398. +
  1399. +
  1400. +static int clk_hifiberry_dachd_dt_parse(struct device *dev)
  1401. +{
  1402. + num_common_pll_regs = clk_hifiberry_get_prop_values(dev,
  1403. + "common_pll_regs", common_pll_regs);
  1404. + num_dedicated_44k1_pll_regs = clk_hifiberry_get_prop_values(dev,
  1405. + "44k1_pll_regs", dedicated_44k1_pll_regs);
  1406. + num_dedicated_88k2_pll_regs = clk_hifiberry_get_prop_values(dev,
  1407. + "88k2_pll_regs", dedicated_88k2_pll_regs);
  1408. + num_dedicated_176k4_pll_regs = clk_hifiberry_get_prop_values(dev,
  1409. + "176k4_pll_regs", dedicated_176k4_pll_regs);
  1410. + num_dedicated_48k_pll_regs = clk_hifiberry_get_prop_values(dev,
  1411. + "48k_pll_regs", dedicated_48k_pll_regs);
  1412. + num_dedicated_96k_pll_regs = clk_hifiberry_get_prop_values(dev,
  1413. + "96k_pll_regs", dedicated_96k_pll_regs);
  1414. + num_dedicated_192k_pll_regs = clk_hifiberry_get_prop_values(dev,
  1415. + "192k_pll_regs", dedicated_192k_pll_regs);
  1416. + return 0;
  1417. +}
  1418. +
  1419. +
  1420. +static int clk_hifiberry_dachd_remove(struct device *dev)
  1421. +{
  1422. + of_clk_del_provider(dev->of_node);
  1423. + return 0;
  1424. +}
  1425. +
  1426. +const struct regmap_config hifiberry_pll_regmap = {
  1427. + .reg_bits = 8,
  1428. + .val_bits = 8,
  1429. + .max_register = HIFIBERRY_PLL_MAX_REGISTER,
  1430. + .reg_defaults = hifiberry_pll_reg_defaults,
  1431. + .num_reg_defaults = ARRAY_SIZE(hifiberry_pll_reg_defaults),
  1432. + .cache_type = REGCACHE_RBTREE,
  1433. +};
  1434. +EXPORT_SYMBOL_GPL(hifiberry_pll_regmap);
  1435. +
  1436. +
  1437. +static int clk_hifiberry_dachd_i2c_probe(struct i2c_client *i2c)
  1438. +{
  1439. + struct clk_hifiberry_drvdata *hdclk;
  1440. + int ret = 0;
  1441. + struct clk_init_data init;
  1442. + struct device *dev = &i2c->dev;
  1443. + struct device_node *dev_node = dev->of_node;
  1444. + struct regmap_config config = hifiberry_pll_regmap;
  1445. +
  1446. + hdclk = devm_kzalloc(&i2c->dev,
  1447. + sizeof(struct clk_hifiberry_drvdata), GFP_KERNEL);
  1448. + if (!hdclk)
  1449. + return -ENOMEM;
  1450. +
  1451. + i2c_set_clientdata(i2c, hdclk);
  1452. +
  1453. + hdclk->regmap = devm_regmap_init_i2c(i2c, &config);
  1454. +
  1455. + if (IS_ERR(hdclk->regmap))
  1456. + return PTR_ERR(hdclk->regmap);
  1457. +
  1458. + /* start PLL to allow detection of DAC */
  1459. + ret = clk_hifiberry_dachd_write_pll_regs(hdclk->regmap,
  1460. + hifiberry_pll_reg_defaults,
  1461. + ARRAY_SIZE(hifiberry_pll_reg_defaults),
  1462. + PLL_RESET);
  1463. + if (ret)
  1464. + return ret;
  1465. +
  1466. + clk_hifiberry_dachd_dt_parse(dev);
  1467. +
  1468. + /* restart PLL with configs from DTB */
  1469. + ret = clk_hifiberry_dachd_write_pll_regs(hdclk->regmap, common_pll_regs,
  1470. + num_common_pll_regs, PLL_RESET);
  1471. + if (ret)
  1472. + return ret;
  1473. +
  1474. + init.name = "clk-hifiberry-dachd";
  1475. + init.ops = &clk_hifiberry_dachd_rate_ops;
  1476. + init.flags = 0;
  1477. + init.parent_names = NULL;
  1478. + init.num_parents = 0;
  1479. +
  1480. + hdclk->hw.init = &init;
  1481. +
  1482. + hdclk->clk = devm_clk_register(dev, &hdclk->hw);
  1483. + if (IS_ERR(hdclk->clk)) {
  1484. + dev_err(dev, "unable to register %s\n", init.name);
  1485. + return PTR_ERR(hdclk->clk);
  1486. + }
  1487. +
  1488. + ret = of_clk_add_provider(dev_node, of_clk_src_simple_get, hdclk->clk);
  1489. + if (ret != 0) {
  1490. + dev_err(dev, "Cannot of_clk_add_provider");
  1491. + return ret;
  1492. + }
  1493. +
  1494. + ret = clk_set_rate(hdclk->hw.clk, DEFAULT_RATE);
  1495. + if (ret != 0) {
  1496. + dev_err(dev, "Cannot set rate : %d\n", ret);
  1497. + return -EINVAL;
  1498. + }
  1499. +
  1500. + return ret;
  1501. +}
  1502. +
  1503. +static void clk_hifiberry_dachd_i2c_remove(struct i2c_client *i2c)
  1504. +{
  1505. + clk_hifiberry_dachd_remove(&i2c->dev);
  1506. +}
  1507. +
  1508. +static const struct i2c_device_id clk_hifiberry_dachd_i2c_id[] = {
  1509. + { "dachd-clk", },
  1510. + { }
  1511. +};
  1512. +MODULE_DEVICE_TABLE(i2c, clk_hifiberry_dachd_i2c_id);
  1513. +
  1514. +static const struct of_device_id clk_hifiberry_dachd_of_match[] = {
  1515. + { .compatible = "hifiberry,dachd-clk", },
  1516. + { }
  1517. +};
  1518. +MODULE_DEVICE_TABLE(of, clk_hifiberry_dachd_of_match);
  1519. +
  1520. +static struct i2c_driver clk_hifiberry_dachd_i2c_driver = {
  1521. + .probe = clk_hifiberry_dachd_i2c_probe,
  1522. + .remove = clk_hifiberry_dachd_i2c_remove,
  1523. + .id_table = clk_hifiberry_dachd_i2c_id,
  1524. + .driver = {
  1525. + .name = "dachd-clk",
  1526. + .of_match_table = of_match_ptr(clk_hifiberry_dachd_of_match),
  1527. + },
  1528. +};
  1529. +
  1530. +module_i2c_driver(clk_hifiberry_dachd_i2c_driver);
  1531. +
  1532. +
  1533. +MODULE_DESCRIPTION("HiFiBerry DAC+ HD clock driver");
  1534. +MODULE_AUTHOR("Joerg Schambacher <[email protected]>");
  1535. +MODULE_LICENSE("GPL v2");
  1536. +MODULE_ALIAS("platform:clk-hifiberry-dachd");
  1537. --- /dev/null
  1538. +++ b/drivers/clk/clk-hifiberry-dacpro.c
  1539. @@ -0,0 +1,181 @@
  1540. +/*
  1541. + * Clock Driver for HiFiBerry DAC Pro
  1542. + *
  1543. + * Author: Stuart MacLean
  1544. + * Copyright 2015
  1545. + *
  1546. + * This program is free software; you can redistribute it and/or
  1547. + * modify it under the terms of the GNU General Public License
  1548. + * version 2 as published by the Free Software Foundation.
  1549. + *
  1550. + * This program is distributed in the hope that it will be useful, but
  1551. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  1552. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1553. + * General Public License for more details.
  1554. + */
  1555. +
  1556. +#include <linux/clk-provider.h>
  1557. +#include <linux/clkdev.h>
  1558. +#include <linux/kernel.h>
  1559. +#include <linux/module.h>
  1560. +#include <linux/of.h>
  1561. +#include <linux/slab.h>
  1562. +#include <linux/platform_device.h>
  1563. +
  1564. +struct ext_clk_rates {
  1565. + /* Clock rate of CLK44EN attached to GPIO6 pin */
  1566. + unsigned long clk_44en;
  1567. + /* Clock rate of CLK48EN attached to GPIO3 pin */
  1568. + unsigned long clk_48en;
  1569. +};
  1570. +
  1571. +/**
  1572. + * struct hifiberry_dacpro_clk - Common struct to the HiFiBerry DAC Pro
  1573. + * @hw: clk_hw for the common clk framework
  1574. + * @mode: 0 => CLK44EN, 1 => CLK48EN
  1575. + */
  1576. +struct clk_hifiberry_hw {
  1577. + struct clk_hw hw;
  1578. + uint8_t mode;
  1579. + struct ext_clk_rates clk_rates;
  1580. +};
  1581. +
  1582. +#define to_hifiberry_clk(_hw) container_of(_hw, struct clk_hifiberry_hw, hw)
  1583. +
  1584. +static const struct ext_clk_rates hifiberry_dacpro_clks = {
  1585. + .clk_44en = 22579200UL,
  1586. + .clk_48en = 24576000UL,
  1587. +};
  1588. +
  1589. +static const struct ext_clk_rates allo_dac_clks = {
  1590. + .clk_44en = 45158400UL,
  1591. + .clk_48en = 49152000UL,
  1592. +};
  1593. +
  1594. +static const struct of_device_id clk_hifiberry_dacpro_dt_ids[] = {
  1595. + { .compatible = "hifiberry,dacpro-clk", &hifiberry_dacpro_clks },
  1596. + { .compatible = "allo,dac-clk", &allo_dac_clks },
  1597. + { }
  1598. +};
  1599. +MODULE_DEVICE_TABLE(of, clk_hifiberry_dacpro_dt_ids);
  1600. +
  1601. +static unsigned long clk_hifiberry_dacpro_recalc_rate(struct clk_hw *hw,
  1602. + unsigned long parent_rate)
  1603. +{
  1604. + struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw);
  1605. + return (clk->mode == 0) ? clk->clk_rates.clk_44en :
  1606. + clk->clk_rates.clk_48en;
  1607. +}
  1608. +
  1609. +static long clk_hifiberry_dacpro_round_rate(struct clk_hw *hw,
  1610. + unsigned long rate, unsigned long *parent_rate)
  1611. +{
  1612. + struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw);
  1613. + long actual_rate;
  1614. +
  1615. + if (rate <= clk->clk_rates.clk_44en) {
  1616. + actual_rate = (long)clk->clk_rates.clk_44en;
  1617. + } else if (rate >= clk->clk_rates.clk_48en) {
  1618. + actual_rate = (long)clk->clk_rates.clk_48en;
  1619. + } else {
  1620. + long diff44Rate = (long)(rate - clk->clk_rates.clk_44en);
  1621. + long diff48Rate = (long)(clk->clk_rates.clk_48en - rate);
  1622. +
  1623. + if (diff44Rate < diff48Rate)
  1624. + actual_rate = (long)clk->clk_rates.clk_44en;
  1625. + else
  1626. + actual_rate = (long)clk->clk_rates.clk_48en;
  1627. + }
  1628. + return actual_rate;
  1629. +}
  1630. +
  1631. +
  1632. +static int clk_hifiberry_dacpro_set_rate(struct clk_hw *hw,
  1633. + unsigned long rate, unsigned long parent_rate)
  1634. +{
  1635. + struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw);
  1636. + unsigned long actual_rate;
  1637. +
  1638. + actual_rate = (unsigned long)clk_hifiberry_dacpro_round_rate(hw, rate,
  1639. + &parent_rate);
  1640. + clk->mode = (actual_rate == clk->clk_rates.clk_44en) ? 0 : 1;
  1641. + return 0;
  1642. +}
  1643. +
  1644. +
  1645. +const struct clk_ops clk_hifiberry_dacpro_rate_ops = {
  1646. + .recalc_rate = clk_hifiberry_dacpro_recalc_rate,
  1647. + .round_rate = clk_hifiberry_dacpro_round_rate,
  1648. + .set_rate = clk_hifiberry_dacpro_set_rate,
  1649. +};
  1650. +
  1651. +static int clk_hifiberry_dacpro_probe(struct platform_device *pdev)
  1652. +{
  1653. + const struct of_device_id *of_id;
  1654. + struct clk_hifiberry_hw *proclk;
  1655. + struct clk *clk;
  1656. + struct device *dev;
  1657. + struct clk_init_data init;
  1658. + int ret;
  1659. +
  1660. + dev = &pdev->dev;
  1661. + of_id = of_match_node(clk_hifiberry_dacpro_dt_ids, dev->of_node);
  1662. + if (!of_id)
  1663. + return -EINVAL;
  1664. +
  1665. + proclk = kzalloc(sizeof(struct clk_hifiberry_hw), GFP_KERNEL);
  1666. + if (!proclk)
  1667. + return -ENOMEM;
  1668. +
  1669. + init.name = "clk-hifiberry-dacpro";
  1670. + init.ops = &clk_hifiberry_dacpro_rate_ops;
  1671. + init.flags = 0;
  1672. + init.parent_names = NULL;
  1673. + init.num_parents = 0;
  1674. +
  1675. + proclk->mode = 0;
  1676. + proclk->hw.init = &init;
  1677. + memcpy(&proclk->clk_rates, of_id->data, sizeof(proclk->clk_rates));
  1678. +
  1679. + clk = devm_clk_register(dev, &proclk->hw);
  1680. + if (!IS_ERR(clk)) {
  1681. + ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
  1682. + clk);
  1683. + } else {
  1684. + dev_err(dev, "Fail to register clock driver\n");
  1685. + kfree(proclk);
  1686. + ret = PTR_ERR(clk);
  1687. + }
  1688. + return ret;
  1689. +}
  1690. +
  1691. +static int clk_hifiberry_dacpro_remove(struct platform_device *pdev)
  1692. +{
  1693. + of_clk_del_provider(pdev->dev.of_node);
  1694. + return 0;
  1695. +}
  1696. +
  1697. +static struct platform_driver clk_hifiberry_dacpro_driver = {
  1698. + .probe = clk_hifiberry_dacpro_probe,
  1699. + .remove = clk_hifiberry_dacpro_remove,
  1700. + .driver = {
  1701. + .name = "clk-hifiberry-dacpro",
  1702. + .of_match_table = clk_hifiberry_dacpro_dt_ids,
  1703. + },
  1704. +};
  1705. +
  1706. +static int __init clk_hifiberry_dacpro_init(void)
  1707. +{
  1708. + return platform_driver_register(&clk_hifiberry_dacpro_driver);
  1709. +}
  1710. +core_initcall(clk_hifiberry_dacpro_init);
  1711. +
  1712. +static void __exit clk_hifiberry_dacpro_exit(void)
  1713. +{
  1714. + platform_driver_unregister(&clk_hifiberry_dacpro_driver);
  1715. +}
  1716. +module_exit(clk_hifiberry_dacpro_exit);
  1717. +
  1718. +MODULE_DESCRIPTION("HiFiBerry DAC Pro clock driver");
  1719. +MODULE_LICENSE("GPL v2");
  1720. +MODULE_ALIAS("platform:clk-hifiberry-dacpro");
  1721. --- a/sound/soc/bcm/Kconfig
  1722. +++ b/sound/soc/bcm/Kconfig
  1723. @@ -26,3 +26,309 @@ config SND_BCM63XX_I2S_WHISTLER
  1724. DSL/PON chips (bcm63158, bcm63178)
  1725. If you don't know what to do here, say N
  1726. +
  1727. +config SND_BCM2708_SOC_CHIPDIP_DAC
  1728. + tristate "Support for the ChipDip DAC"
  1729. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1730. + help
  1731. + Say Y or M if you want to add support for the ChipDip DAC soundcard
  1732. +
  1733. +config SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD
  1734. + tristate "Support for Google voiceHAT soundcard"
  1735. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1736. + select SND_SOC_VOICEHAT
  1737. + select SND_RPI_SIMPLE_SOUNDCARD
  1738. + help
  1739. + Say Y or M if you want to add support for voiceHAT soundcard.
  1740. +
  1741. +config SND_BCM2708_SOC_HIFIBERRY_DAC
  1742. + tristate "Support for HifiBerry DAC"
  1743. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1744. + select SND_SOC_PCM5102A
  1745. + select SND_RPI_SIMPLE_SOUNDCARD
  1746. + help
  1747. + Say Y or M if you want to add support for HifiBerry DAC.
  1748. +
  1749. +config SND_BCM2708_SOC_HIFIBERRY_DACPLUS
  1750. + tristate "Support for HifiBerry DAC+"
  1751. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1752. + select SND_SOC_PCM512x
  1753. + select SND_SOC_TPA6130A2
  1754. + select COMMON_CLK_HIFIBERRY_DACPRO
  1755. + help
  1756. + Say Y or M if you want to add support for HifiBerry DAC+.
  1757. +
  1758. +config SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD
  1759. + tristate "Support for HifiBerry DAC+ HD"
  1760. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1761. + select SND_SOC_PCM179X_I2C
  1762. + select COMMON_CLK_HIFIBERRY_DACPLUSHD
  1763. + help
  1764. + Say Y or M if you want to add support for HifiBerry DAC+ HD.
  1765. +
  1766. +config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC
  1767. + tristate "Support for HifiBerry DAC+ADC"
  1768. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1769. + select SND_SOC_PCM512x_I2C
  1770. + select SND_SOC_DMIC
  1771. + select COMMON_CLK_HIFIBERRY_DACPRO
  1772. + help
  1773. + Say Y or M if you want to add support for HifiBerry DAC+ADC.
  1774. +
  1775. +config SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO
  1776. + tristate "Support for HifiBerry DAC+ADC PRO"
  1777. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1778. + select SND_SOC_PCM512x_I2C
  1779. + select SND_SOC_PCM186X_I2C
  1780. + select SND_SOC_TPA6130A2
  1781. + select COMMON_CLK_HIFIBERRY_DACPRO
  1782. + help
  1783. + Say Y or M if you want to add support for HifiBerry DAC+ADC PRO.
  1784. +
  1785. +config SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP
  1786. + tristate "Support for HifiBerry DAC+DSP"
  1787. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1788. + select SND_RPI_SIMPLE_SOUNDCARD
  1789. + help
  1790. + Say Y or M if you want to add support for HifiBerry DSP-DAC.
  1791. +
  1792. +config SND_BCM2708_SOC_HIFIBERRY_DIGI
  1793. + tristate "Support for HifiBerry Digi"
  1794. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1795. + select SND_SOC_WM8804
  1796. + help
  1797. + Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board.
  1798. +
  1799. +config SND_BCM2708_SOC_HIFIBERRY_AMP
  1800. + tristate "Support for the HifiBerry Amp"
  1801. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1802. + select SND_SOC_TAS5713
  1803. + select SND_RPI_SIMPLE_SOUNDCARD
  1804. + help
  1805. + Say Y or M if you want to add support for the HifiBerry Amp amplifier board.
  1806. +
  1807. + config SND_BCM2708_SOC_PIFI_40
  1808. + tristate "Support for the PiFi-40 amp"
  1809. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1810. + select SND_SOC_TAS571X
  1811. + select SND_PIFI_40
  1812. + help
  1813. + Say Y or M if you want to add support for the PiFi40 amp board
  1814. +
  1815. +config SND_BCM2708_SOC_RPI_CIRRUS
  1816. + tristate "Support for Cirrus Logic Audio Card"
  1817. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1818. + select SND_SOC_WM5102
  1819. + select SND_SOC_WM8804
  1820. + help
  1821. + Say Y or M if you want to add support for the Wolfson and
  1822. + Cirrus Logic audio cards.
  1823. +
  1824. +config SND_BCM2708_SOC_RPI_DAC
  1825. + tristate "Support for RPi-DAC"
  1826. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1827. + select SND_SOC_PCM1794A
  1828. + select SND_RPI_SIMPLE_SOUNDCARD
  1829. + help
  1830. + Say Y or M if you want to add support for RPi-DAC.
  1831. +
  1832. +config SND_BCM2708_SOC_RPI_PROTO
  1833. + tristate "Support for Rpi-PROTO"
  1834. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1835. + select SND_SOC_WM8731_I2C
  1836. + help
  1837. + Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731).
  1838. +
  1839. +config SND_BCM2708_SOC_JUSTBOOM_BOTH
  1840. + tristate "Support for simultaneous JustBoom Digi and JustBoom DAC"
  1841. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1842. + select SND_SOC_WM8804
  1843. + select SND_SOC_PCM512x
  1844. + help
  1845. + Say Y or M if you want to add support for simultaneous
  1846. + JustBoom Digi and JustBoom DAC.
  1847. +
  1848. + This is not the right choice if you only have one but both of
  1849. + these cards.
  1850. +
  1851. +config SND_BCM2708_SOC_JUSTBOOM_DAC
  1852. + tristate "Support for JustBoom DAC"
  1853. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1854. + select SND_SOC_PCM512x
  1855. + help
  1856. + Say Y or M if you want to add support for JustBoom DAC.
  1857. +
  1858. +config SND_BCM2708_SOC_JUSTBOOM_DIGI
  1859. + tristate "Support for JustBoom Digi"
  1860. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1861. + select SND_SOC_WM8804
  1862. + select SND_RPI_WM8804_SOUNDCARD
  1863. + help
  1864. + Say Y or M if you want to add support for JustBoom Digi.
  1865. +
  1866. +config SND_BCM2708_SOC_IQAUDIO_CODEC
  1867. + tristate "Support for IQaudIO-CODEC"
  1868. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1869. + select SND_SOC_DA7213
  1870. + help
  1871. + Say Y or M if you want to add support for IQaudIO-CODEC.
  1872. +
  1873. +config SND_BCM2708_SOC_IQAUDIO_DAC
  1874. + tristate "Support for IQaudIO-DAC"
  1875. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1876. + select SND_SOC_PCM512x_I2C
  1877. + help
  1878. + Say Y or M if you want to add support for IQaudIO-DAC.
  1879. +
  1880. +config SND_BCM2708_SOC_IQAUDIO_DIGI
  1881. + tristate "Support for IQAudIO Digi"
  1882. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1883. + select SND_SOC_WM8804
  1884. + select SND_RPI_WM8804_SOUNDCARD
  1885. + help
  1886. + Say Y or M if you want to add support for IQAudIO Digital IO board.
  1887. +
  1888. +config SND_BCM2708_SOC_I_SABRE_Q2M
  1889. + tristate "Support for Audiophonics I-Sabre Q2M DAC"
  1890. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1891. + select SND_SOC_I_SABRE_CODEC
  1892. + help
  1893. + Say Y or M if you want to add support for Audiophonics I-SABRE Q2M DAC
  1894. +
  1895. +config SND_BCM2708_SOC_ADAU1977_ADC
  1896. + tristate "Support for ADAU1977 ADC"
  1897. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1898. + select SND_SOC_ADAU1977_I2C
  1899. + select SND_RPI_SIMPLE_SOUNDCARD
  1900. + help
  1901. + Say Y or M if you want to add support for ADAU1977 ADC.
  1902. +
  1903. +config SND_AUDIOINJECTOR_PI_SOUNDCARD
  1904. + tristate "Support for audioinjector.net Pi add on soundcard"
  1905. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1906. + select SND_SOC_WM8731_I2C
  1907. + help
  1908. + Say Y or M if you want to add support for audioinjector.net Pi Hat
  1909. +
  1910. +config SND_AUDIOINJECTOR_OCTO_SOUNDCARD
  1911. + tristate "Support for audioinjector.net Octo channel (Hat) soundcard"
  1912. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1913. + select SND_SOC_CS42XX8_I2C
  1914. + help
  1915. + Say Y or M if you want to add support for audioinjector.net octo add on
  1916. +
  1917. +config SND_AUDIOINJECTOR_ISOLATED_SOUNDCARD
  1918. + tristate "Support for audioinjector.net isolated DAC and ADC soundcard"
  1919. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1920. + select SND_SOC_CS4271_I2C
  1921. + help
  1922. + Say Y or M if you want to add support for audioinjector.net isolated soundcard
  1923. +
  1924. +config SND_AUDIOSENSE_PI
  1925. + tristate "Support for AudioSense Add-On Soundcard"
  1926. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1927. + select SND_SOC_TLV320AIC32X4_I2C
  1928. + help
  1929. + Say Y or M if you want to add support for tlv320aic32x4 add-on
  1930. +
  1931. +config SND_DIGIDAC1_SOUNDCARD
  1932. + tristate "Support for Red Rocks Audio DigiDAC1"
  1933. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1934. + select SND_SOC_WM8804
  1935. + select SND_SOC_WM8741
  1936. + help
  1937. + Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board.
  1938. +
  1939. +config SND_BCM2708_SOC_DIONAUDIO_LOCO
  1940. + tristate "Support for Dion Audio LOCO DAC-AMP"
  1941. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1942. + select SND_SOC_PCM5102a
  1943. + help
  1944. + Say Y or M if you want to add support for Dion Audio LOCO.
  1945. +
  1946. +config SND_BCM2708_SOC_DIONAUDIO_LOCO_V2
  1947. + tristate "Support for Dion Audio LOCO-V2 DAC-AMP"
  1948. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1949. + select SND_SOC_PCM5122
  1950. + help
  1951. + Say Y or M if you want to add support for Dion Audio LOCO-V2.
  1952. +
  1953. +config SND_BCM2708_SOC_ALLO_PIANO_DAC
  1954. + tristate "Support for Allo Piano DAC"
  1955. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1956. + select SND_SOC_PCM512x_I2C
  1957. + help
  1958. + Say Y or M if you want to add support for Allo Piano DAC.
  1959. +
  1960. +config SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS
  1961. + tristate "Support for Allo Piano DAC Plus"
  1962. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1963. + select SND_SOC_PCM512x_I2C
  1964. + help
  1965. + Say Y or M if you want to add support for Allo Piano DAC Plus.
  1966. +
  1967. +config SND_BCM2708_SOC_ALLO_BOSS_DAC
  1968. + tristate "Support for Allo Boss DAC"
  1969. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1970. + select SND_SOC_PCM512x_I2C
  1971. + select COMMON_CLK_HIFIBERRY_DACPRO
  1972. + help
  1973. + Say Y or M if you want to add support for Allo Boss DAC.
  1974. +
  1975. +config SND_BCM2708_SOC_ALLO_BOSS2_DAC
  1976. + tristate "Support for Allo Boss2 DAC"
  1977. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1978. + depends on I2C
  1979. + select REGMAP_I2C
  1980. + select SND_AUDIO_GRAPH_CARD
  1981. + help
  1982. + Say Y or M if you want to add support for Allo Boss2 DAC.
  1983. +
  1984. +config SND_BCM2708_SOC_ALLO_DIGIONE
  1985. + tristate "Support for Allo DigiOne"
  1986. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1987. + select SND_SOC_WM8804
  1988. + select SND_RPI_WM8804_SOUNDCARD
  1989. + help
  1990. + Say Y or M if you want to add support for Allo DigiOne.
  1991. +
  1992. +config SND_BCM2708_SOC_ALLO_KATANA_DAC
  1993. + tristate "Support for Allo Katana DAC"
  1994. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  1995. + depends on I2C
  1996. + select REGMAP_I2C
  1997. + select SND_AUDIO_GRAPH_CARD
  1998. + help
  1999. + Say Y or M if you want to add support for Allo Katana DAC.
  2000. +
  2001. +config SND_BCM2708_SOC_FE_PI_AUDIO
  2002. + tristate "Support for Fe-Pi-Audio"
  2003. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  2004. + select SND_SOC_SGTL5000
  2005. + help
  2006. + Say Y or M if you want to add support for Fe-Pi-Audio.
  2007. +
  2008. +config SND_PISOUND
  2009. + tristate "Support for Blokas Labs pisound"
  2010. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  2011. + select SND_RAWMIDI
  2012. + help
  2013. + Say Y or M if you want to add support for Blokas Labs pisound.
  2014. +
  2015. +config SND_RPI_SIMPLE_SOUNDCARD
  2016. + tristate "Support for Raspberry Pi simple soundcards"
  2017. + help
  2018. + Say Y or M if you want to add support Raspbery Pi simple soundcards
  2019. +
  2020. +config SND_RPI_WM8804_SOUNDCARD
  2021. + tristate "Support for Raspberry Pi generic WM8804 soundcards"
  2022. + help
  2023. + Say Y or M if you want to add support for the Raspberry Pi
  2024. + generic driver for WM8804 based soundcards.
  2025. +
  2026. +config SND_DACBERRY400
  2027. + tristate "Support for DACBERRY400 Soundcard"
  2028. + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
  2029. + select SND_SOC_TLV320AIC3X_I2C
  2030. + help
  2031. + Say Y or M if you want to add support for tlv320aic3x add-on
  2032. --- a/sound/soc/bcm/Makefile
  2033. +++ b/sound/soc/bcm/Makefile
  2034. @@ -12,4 +12,73 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-
  2035. # BCM63XX Platform Support
  2036. snd-soc-63xx-objs := bcm63xx-i2s-whistler.o bcm63xx-pcm-whistler.o
  2037. -obj-$(CONFIG_SND_BCM63XX_I2S_WHISTLER) += snd-soc-63xx.o
  2038. \ No newline at end of file
  2039. +obj-$(CONFIG_SND_BCM63XX_I2S_WHISTLER) += snd-soc-63xx.o
  2040. +
  2041. +# Google voiceHAT custom codec support
  2042. +snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
  2043. +
  2044. +# BCM2708 Machine Support
  2045. +snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o
  2046. +snd-soc-hifiberry-dacplushd-objs := hifiberry_dacplushd.o
  2047. +snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
  2048. +snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
  2049. +snd-soc-hifiberry-dacplusdsp-objs := hifiberry_dacplusdsp.o
  2050. +snd-soc-justboom-both-objs := justboom-both.o
  2051. +snd-soc-justboom-dac-objs := justboom-dac.o
  2052. +snd-soc-rpi-cirrus-objs := rpi-cirrus.o
  2053. +snd-soc-rpi-proto-objs := rpi-proto.o
  2054. +snd-soc-iqaudio-codec-objs := iqaudio-codec.o
  2055. +snd-soc-iqaudio-dac-objs := iqaudio-dac.o
  2056. + snd-soc-i-sabre-q2m-objs := i-sabre-q2m.o
  2057. +snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o
  2058. +snd-soc-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o
  2059. +snd-soc-audioinjector-isolated-soundcard-objs := audioinjector-isolated-soundcard.o
  2060. +snd-soc-audiosense-pi-objs := audiosense-pi.o
  2061. +snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o
  2062. +snd-soc-dionaudio-loco-objs := dionaudio_loco.o
  2063. +snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o
  2064. +snd-soc-allo-boss-dac-objs := allo-boss-dac.o
  2065. +snd-soc-allo-boss2-dac-objs := allo-boss2-dac.o
  2066. +snd-soc-allo-piano-dac-objs := allo-piano-dac.o
  2067. +snd-soc-allo-piano-dac-plus-objs := allo-piano-dac-plus.o
  2068. +snd-soc-allo-katana-codec-objs := allo-katana-codec.o
  2069. +snd-soc-pisound-objs := pisound.o
  2070. +snd-soc-fe-pi-audio-objs := fe-pi-audio.o
  2071. +snd-soc-rpi-simple-soundcard-objs := rpi-simple-soundcard.o
  2072. +snd-soc-rpi-wm8804-soundcard-objs := rpi-wm8804-soundcard.o
  2073. +snd-soc-pifi-40-objs := pifi-40.o
  2074. +snd-soc-chipdip-dac-objs := chipdip-dac.o
  2075. +snd-soc-dacberry400-objs := dacberry400.o
  2076. +
  2077. +obj-$(CONFIG_SND_BCM2708_SOC_GOOGLEVOICEHAT_SOUNDCARD) += snd-soc-googlevoicehat-codec.o
  2078. +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
  2079. +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSHD) += snd-soc-hifiberry-dacplushd.o
  2080. +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
  2081. +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
  2082. +obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP) += snd-soc-hifiberry-dacplusdsp.o
  2083. +obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_BOTH) += snd-soc-justboom-both.o
  2084. +obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
  2085. +obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
  2086. +obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
  2087. +obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_CODEC) += snd-soc-iqaudio-codec.o
  2088. +obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
  2089. +obj-$(CONFIG_SND_BCM2708_SOC_I_SABRE_Q2M) += snd-soc-i-sabre-q2m.o
  2090. +obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o
  2091. +obj-$(CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD) += snd-soc-audioinjector-octo-soundcard.o
  2092. +obj-$(CONFIG_SND_AUDIOINJECTOR_ISOLATED_SOUNDCARD) += snd-soc-audioinjector-isolated-soundcard.o
  2093. +obj-$(CONFIG_SND_AUDIOSENSE_PI) += snd-soc-audiosense-pi.o
  2094. +obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o
  2095. +obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o
  2096. +obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o
  2097. +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC) += snd-soc-allo-boss-dac.o
  2098. +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_BOSS2_DAC) += snd-soc-allo-boss2-dac.o
  2099. +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o
  2100. +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC_PLUS) += snd-soc-allo-piano-dac-plus.o
  2101. +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_KATANA_DAC) += snd-soc-allo-katana-codec.o
  2102. +obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o
  2103. +obj-$(CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO) += snd-soc-fe-pi-audio.o
  2104. +obj-$(CONFIG_SND_RPI_SIMPLE_SOUNDCARD) += snd-soc-rpi-simple-soundcard.o
  2105. +obj-$(CONFIG_SND_RPI_WM8804_SOUNDCARD) += snd-soc-rpi-wm8804-soundcard.o
  2106. +obj-$(CONFIG_SND_BCM2708_SOC_PIFI_40) += snd-soc-pifi-40.o
  2107. +obj-$(CONFIG_SND_BCM2708_SOC_CHIPDIP_DAC) += snd-soc-chipdip-dac.o
  2108. +obj-$(CONFIG_SND_DACBERRY400) += snd-soc-dacberry400.o
  2109. --- /dev/null
  2110. +++ b/sound/soc/bcm/allo-boss-dac.c
  2111. @@ -0,0 +1,457 @@
  2112. +/*
  2113. + * ALSA ASoC Machine Driver for Allo Boss DAC
  2114. + *
  2115. + * Author: Baswaraj K <[email protected]>
  2116. + * Copyright 2017
  2117. + * based on code by Daniel Matuschek,
  2118. + * Stuart MacLean <[email protected]>
  2119. + * based on code by Florian Meier <[email protected]>
  2120. + *
  2121. + * This program is free software; you can redistribute it and/or
  2122. + * modify it under the terms of the GNU General Public License
  2123. + * version 2 as published by the Free Software Foundation.
  2124. + *
  2125. + * This program is distributed in the hope that it will be useful, but
  2126. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  2127. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  2128. + * General Public License for more details.
  2129. + */
  2130. +
  2131. +#include <linux/module.h>
  2132. +#include <linux/gpio/consumer.h>
  2133. +#include <linux/platform_device.h>
  2134. +#include <linux/clk.h>
  2135. +#include <linux/delay.h>
  2136. +
  2137. +#include <sound/core.h>
  2138. +#include <sound/pcm.h>
  2139. +#include <sound/pcm_params.h>
  2140. +#include <sound/soc.h>
  2141. +#include "../codecs/pcm512x.h"
  2142. +
  2143. +#define ALLO_BOSS_NOCLOCK 0
  2144. +#define ALLO_BOSS_CLK44EN 1
  2145. +#define ALLO_BOSS_CLK48EN 2
  2146. +
  2147. +struct pcm512x_priv {
  2148. + struct regmap *regmap;
  2149. + struct clk *sclk;
  2150. +};
  2151. +
  2152. +static struct gpio_desc *mute_gpio;
  2153. +
  2154. +/* Clock rate of CLK44EN attached to GPIO6 pin */
  2155. +#define CLK_44EN_RATE 45158400UL
  2156. +/* Clock rate of CLK48EN attached to GPIO3 pin */
  2157. +#define CLK_48EN_RATE 49152000UL
  2158. +
  2159. +static bool slave;
  2160. +static bool snd_soc_allo_boss_master;
  2161. +static bool digital_gain_0db_limit = true;
  2162. +
  2163. +static void snd_allo_boss_select_clk(struct snd_soc_component *component,
  2164. + int clk_id)
  2165. +{
  2166. + switch (clk_id) {
  2167. + case ALLO_BOSS_NOCLOCK:
  2168. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
  2169. + break;
  2170. + case ALLO_BOSS_CLK44EN:
  2171. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
  2172. + break;
  2173. + case ALLO_BOSS_CLK48EN:
  2174. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
  2175. + break;
  2176. + }
  2177. +}
  2178. +
  2179. +static void snd_allo_boss_clk_gpio(struct snd_soc_component *component)
  2180. +{
  2181. + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
  2182. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
  2183. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
  2184. +}
  2185. +
  2186. +static bool snd_allo_boss_is_sclk(struct snd_soc_component *component)
  2187. +{
  2188. + unsigned int sck;
  2189. +
  2190. + sck = snd_soc_component_read(component, PCM512x_RATE_DET_4);
  2191. + return (!(sck & 0x40));
  2192. +}
  2193. +
  2194. +static bool snd_allo_boss_is_sclk_sleep(
  2195. + struct snd_soc_component *component)
  2196. +{
  2197. + msleep(2);
  2198. + return snd_allo_boss_is_sclk(component);
  2199. +}
  2200. +
  2201. +static bool snd_allo_boss_is_master_card(struct snd_soc_component *component)
  2202. +{
  2203. + bool isClk44EN, isClk48En, isNoClk;
  2204. +
  2205. + snd_allo_boss_clk_gpio(component);
  2206. +
  2207. + snd_allo_boss_select_clk(component, ALLO_BOSS_CLK44EN);
  2208. + isClk44EN = snd_allo_boss_is_sclk_sleep(component);
  2209. +
  2210. + snd_allo_boss_select_clk(component, ALLO_BOSS_NOCLOCK);
  2211. + isNoClk = snd_allo_boss_is_sclk_sleep(component);
  2212. +
  2213. + snd_allo_boss_select_clk(component, ALLO_BOSS_CLK48EN);
  2214. + isClk48En = snd_allo_boss_is_sclk_sleep(component);
  2215. +
  2216. + return (isClk44EN && isClk48En && !isNoClk);
  2217. +}
  2218. +
  2219. +static int snd_allo_boss_clk_for_rate(int sample_rate)
  2220. +{
  2221. + int type;
  2222. +
  2223. + switch (sample_rate) {
  2224. + case 11025:
  2225. + case 22050:
  2226. + case 44100:
  2227. + case 88200:
  2228. + case 176400:
  2229. + case 352800:
  2230. + type = ALLO_BOSS_CLK44EN;
  2231. + break;
  2232. + default:
  2233. + type = ALLO_BOSS_CLK48EN;
  2234. + break;
  2235. + }
  2236. + return type;
  2237. +}
  2238. +
  2239. +static void snd_allo_boss_set_sclk(struct snd_soc_component *component,
  2240. + int sample_rate)
  2241. +{
  2242. + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
  2243. +
  2244. + if (!IS_ERR(pcm512x->sclk)) {
  2245. + int ctype;
  2246. +
  2247. + ctype = snd_allo_boss_clk_for_rate(sample_rate);
  2248. + clk_set_rate(pcm512x->sclk, (ctype == ALLO_BOSS_CLK44EN)
  2249. + ? CLK_44EN_RATE : CLK_48EN_RATE);
  2250. + snd_allo_boss_select_clk(component, ctype);
  2251. + }
  2252. +}
  2253. +
  2254. +static int snd_allo_boss_init(struct snd_soc_pcm_runtime *rtd)
  2255. +{
  2256. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  2257. + struct pcm512x_priv *priv = snd_soc_component_get_drvdata(component);
  2258. +
  2259. + if (slave)
  2260. + snd_soc_allo_boss_master = false;
  2261. + else
  2262. + snd_soc_allo_boss_master =
  2263. + snd_allo_boss_is_master_card(component);
  2264. +
  2265. + if (snd_soc_allo_boss_master) {
  2266. + struct snd_soc_dai_link *dai = rtd->dai_link;
  2267. +
  2268. + dai->name = "BossDAC";
  2269. + dai->stream_name = "Boss DAC HiFi [Master]";
  2270. + dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
  2271. + | SND_SOC_DAIFMT_CBM_CFM;
  2272. +
  2273. + snd_soc_component_update_bits(component, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
  2274. + snd_soc_component_update_bits(component, PCM512x_MASTER_MODE, 0x03, 0x03);
  2275. + snd_soc_component_update_bits(component, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
  2276. + /*
  2277. + * Default sclk to CLK_48EN_RATE, otherwise codec
  2278. + * pcm512x_dai_startup_master method could call
  2279. + * snd_pcm_hw_constraint_ratnums using CLK_44EN/64
  2280. + * which will mask 384k sample rate.
  2281. + */
  2282. + if (!IS_ERR(priv->sclk))
  2283. + clk_set_rate(priv->sclk, CLK_48EN_RATE);
  2284. + } else {
  2285. + priv->sclk = ERR_PTR(-ENOENT);
  2286. + }
  2287. +
  2288. + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
  2289. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
  2290. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
  2291. +
  2292. + if (digital_gain_0db_limit) {
  2293. + int ret;
  2294. + struct snd_soc_card *card = rtd->card;
  2295. +
  2296. + ret = snd_soc_limit_volume(card, "Digital Playback Volume",
  2297. + 207);
  2298. + if (ret < 0)
  2299. + dev_warn(card->dev, "Failed to set volume limit: %d\n",
  2300. + ret);
  2301. + }
  2302. +
  2303. + return 0;
  2304. +}
  2305. +
  2306. +static int snd_allo_boss_update_rate_den(
  2307. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  2308. +{
  2309. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  2310. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  2311. + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
  2312. + struct snd_ratnum *rats_no_pll;
  2313. + unsigned int num = 0, den = 0;
  2314. + int err;
  2315. +
  2316. + rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
  2317. + if (!rats_no_pll)
  2318. + return -ENOMEM;
  2319. +
  2320. + rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
  2321. + rats_no_pll->den_min = 1;
  2322. + rats_no_pll->den_max = 128;
  2323. + rats_no_pll->den_step = 1;
  2324. +
  2325. + err = snd_interval_ratnum(hw_param_interval(params,
  2326. + SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
  2327. + if (err >= 0 && den) {
  2328. + params->rate_num = num;
  2329. + params->rate_den = den;
  2330. + }
  2331. +
  2332. + devm_kfree(rtd->dev, rats_no_pll);
  2333. + return 0;
  2334. +}
  2335. +
  2336. +static void snd_allo_boss_gpio_mute(struct snd_soc_card *card)
  2337. +{
  2338. + if (mute_gpio)
  2339. + gpiod_set_value_cansleep(mute_gpio, 1);
  2340. +}
  2341. +
  2342. +static void snd_allo_boss_gpio_unmute(struct snd_soc_card *card)
  2343. +{
  2344. + if (mute_gpio)
  2345. + gpiod_set_value_cansleep(mute_gpio, 0);
  2346. +}
  2347. +
  2348. +static int snd_allo_boss_set_bias_level(struct snd_soc_card *card,
  2349. + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
  2350. +{
  2351. + struct snd_soc_pcm_runtime *rtd;
  2352. + struct snd_soc_dai *codec_dai;
  2353. +
  2354. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  2355. + codec_dai = asoc_rtd_to_codec(rtd, 0);
  2356. +
  2357. + if (dapm->dev != codec_dai->dev)
  2358. + return 0;
  2359. +
  2360. + switch (level) {
  2361. + case SND_SOC_BIAS_PREPARE:
  2362. + if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
  2363. + break;
  2364. + /* UNMUTE DAC */
  2365. + snd_allo_boss_gpio_unmute(card);
  2366. + break;
  2367. +
  2368. + case SND_SOC_BIAS_STANDBY:
  2369. + if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
  2370. + break;
  2371. + /* MUTE DAC */
  2372. + snd_allo_boss_gpio_mute(card);
  2373. + break;
  2374. +
  2375. + default:
  2376. + break;
  2377. + }
  2378. +
  2379. + return 0;
  2380. +}
  2381. +
  2382. +static int snd_allo_boss_hw_params(
  2383. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  2384. +{
  2385. + int ret = 0;
  2386. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  2387. + int channels = params_channels(params);
  2388. + int width = snd_pcm_format_physical_width(params_format(params));
  2389. +
  2390. + if (snd_soc_allo_boss_master) {
  2391. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  2392. +
  2393. + snd_allo_boss_set_sclk(component,
  2394. + params_rate(params));
  2395. +
  2396. + ret = snd_allo_boss_update_rate_den(
  2397. + substream, params);
  2398. + if (ret)
  2399. + return ret;
  2400. + }
  2401. +
  2402. + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), channels * width);
  2403. + if (ret)
  2404. + return ret;
  2405. + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), channels * width);
  2406. + return ret;
  2407. +}
  2408. +
  2409. +static int snd_allo_boss_startup(
  2410. + struct snd_pcm_substream *substream)
  2411. +{
  2412. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  2413. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  2414. + struct snd_soc_card *card = rtd->card;
  2415. +
  2416. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
  2417. + snd_allo_boss_gpio_mute(card);
  2418. +
  2419. + if (snd_soc_allo_boss_master) {
  2420. + struct pcm512x_priv *priv = snd_soc_component_get_drvdata(component);
  2421. + /*
  2422. + * Default sclk to CLK_48EN_RATE, otherwise codec
  2423. + * pcm512x_dai_startup_master method could call
  2424. + * snd_pcm_hw_constraint_ratnums using CLK_44EN/64
  2425. + * which will mask 384k sample rate.
  2426. + */
  2427. + if (!IS_ERR(priv->sclk))
  2428. + clk_set_rate(priv->sclk, CLK_48EN_RATE);
  2429. + }
  2430. +
  2431. + return 0;
  2432. +}
  2433. +
  2434. +static void snd_allo_boss_shutdown(
  2435. + struct snd_pcm_substream *substream)
  2436. +{
  2437. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  2438. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  2439. +
  2440. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
  2441. +}
  2442. +
  2443. +static int snd_allo_boss_prepare(
  2444. + struct snd_pcm_substream *substream)
  2445. +{
  2446. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  2447. + struct snd_soc_card *card = rtd->card;
  2448. +
  2449. + snd_allo_boss_gpio_unmute(card);
  2450. + return 0;
  2451. +}
  2452. +/* machine stream operations */
  2453. +static struct snd_soc_ops snd_allo_boss_ops = {
  2454. + .hw_params = snd_allo_boss_hw_params,
  2455. + .startup = snd_allo_boss_startup,
  2456. + .shutdown = snd_allo_boss_shutdown,
  2457. + .prepare = snd_allo_boss_prepare,
  2458. +};
  2459. +
  2460. +SND_SOC_DAILINK_DEFS(allo_boss,
  2461. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  2462. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi")),
  2463. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  2464. +
  2465. +static struct snd_soc_dai_link snd_allo_boss_dai[] = {
  2466. +{
  2467. + .name = "Boss DAC",
  2468. + .stream_name = "Boss DAC HiFi",
  2469. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  2470. + SND_SOC_DAIFMT_NB_NF |
  2471. + SND_SOC_DAIFMT_CBS_CFS,
  2472. + .ops = &snd_allo_boss_ops,
  2473. + .init = snd_allo_boss_init,
  2474. + SND_SOC_DAILINK_REG(allo_boss),
  2475. +},
  2476. +};
  2477. +
  2478. +/* audio machine driver */
  2479. +static struct snd_soc_card snd_allo_boss = {
  2480. + .name = "BossDAC",
  2481. + .owner = THIS_MODULE,
  2482. + .dai_link = snd_allo_boss_dai,
  2483. + .num_links = ARRAY_SIZE(snd_allo_boss_dai),
  2484. +};
  2485. +
  2486. +static int snd_allo_boss_probe(struct platform_device *pdev)
  2487. +{
  2488. + int ret = 0;
  2489. +
  2490. + snd_allo_boss.dev = &pdev->dev;
  2491. +
  2492. + if (pdev->dev.of_node) {
  2493. + struct device_node *i2s_node;
  2494. + struct snd_soc_dai_link *dai;
  2495. +
  2496. + dai = &snd_allo_boss_dai[0];
  2497. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  2498. + "i2s-controller", 0);
  2499. +
  2500. + if (i2s_node) {
  2501. + dai->cpus->dai_name = NULL;
  2502. + dai->cpus->of_node = i2s_node;
  2503. + dai->platforms->name = NULL;
  2504. + dai->platforms->of_node = i2s_node;
  2505. + }
  2506. +
  2507. + digital_gain_0db_limit = !of_property_read_bool(
  2508. + pdev->dev.of_node, "allo,24db_digital_gain");
  2509. + slave = of_property_read_bool(pdev->dev.of_node,
  2510. + "allo,slave");
  2511. +
  2512. + mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute",
  2513. + GPIOD_OUT_LOW);
  2514. + if (IS_ERR(mute_gpio)) {
  2515. + ret = PTR_ERR(mute_gpio);
  2516. + dev_err(&pdev->dev,
  2517. + "failed to get mute gpio: %d\n", ret);
  2518. + return ret;
  2519. + }
  2520. +
  2521. + if (mute_gpio)
  2522. + snd_allo_boss.set_bias_level =
  2523. + snd_allo_boss_set_bias_level;
  2524. +
  2525. + ret = snd_soc_register_card(&snd_allo_boss);
  2526. + if (ret) {
  2527. + dev_err(&pdev->dev,
  2528. + "snd_soc_register_card() failed: %d\n", ret);
  2529. + return ret;
  2530. + }
  2531. +
  2532. + if (mute_gpio)
  2533. + snd_allo_boss_gpio_mute(&snd_allo_boss);
  2534. +
  2535. + return 0;
  2536. + }
  2537. +
  2538. + return -EINVAL;
  2539. +}
  2540. +
  2541. +static int snd_allo_boss_remove(struct platform_device *pdev)
  2542. +{
  2543. + snd_allo_boss_gpio_mute(&snd_allo_boss);
  2544. + snd_soc_unregister_card(&snd_allo_boss);
  2545. + return 0;
  2546. +}
  2547. +
  2548. +static const struct of_device_id snd_allo_boss_of_match[] = {
  2549. + { .compatible = "allo,boss-dac", },
  2550. + { /* sentinel */ },
  2551. +};
  2552. +MODULE_DEVICE_TABLE(of, snd_allo_boss_of_match);
  2553. +
  2554. +static struct platform_driver snd_allo_boss_driver = {
  2555. + .driver = {
  2556. + .name = "snd-allo-boss-dac",
  2557. + .owner = THIS_MODULE,
  2558. + .of_match_table = snd_allo_boss_of_match,
  2559. + },
  2560. + .probe = snd_allo_boss_probe,
  2561. + .remove = snd_allo_boss_remove,
  2562. +};
  2563. +
  2564. +module_platform_driver(snd_allo_boss_driver);
  2565. +
  2566. +MODULE_AUTHOR("Baswaraj K <[email protected]>");
  2567. +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Boss DAC");
  2568. +MODULE_LICENSE("GPL v2");
  2569. --- /dev/null
  2570. +++ b/sound/soc/bcm/allo-boss2-dac.c
  2571. @@ -0,0 +1,1130 @@
  2572. +/*
  2573. + * Driver for the ALLO KATANA CODEC
  2574. + *
  2575. + * Author: Jaikumar <[email protected]>
  2576. + * Copyright 2018
  2577. + *
  2578. + * This program is free software; you can redistribute it and/or
  2579. + * modify it under the terms of the GNU General Public License
  2580. + * version 2 as published by the Free Software Foundation.
  2581. + *
  2582. + * This program is distributed in the hope that it will be useful, but
  2583. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  2584. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  2585. + * General Public License for more details.
  2586. + */
  2587. +
  2588. +#include <linux/module.h>
  2589. +#include <linux/moduleparam.h>
  2590. +#include <linux/kernel.h>
  2591. +#include <linux/init.h>
  2592. +#include <linux/delay.h>
  2593. +#include <linux/gpio.h>
  2594. +#include <linux/gpio/consumer.h>
  2595. +#include <linux/platform_device.h>
  2596. +#include <linux/pm.h>
  2597. +#include <linux/i2c.h>
  2598. +#include <linux/of_device.h>
  2599. +#include <linux/regmap.h>
  2600. +#include <linux/slab.h>
  2601. +#include <sound/core.h>
  2602. +#include <sound/pcm.h>
  2603. +#include <sound/pcm_params.h>
  2604. +#include <sound/soc.h>
  2605. +#include <sound/soc-dapm.h>
  2606. +#include <sound/initval.h>
  2607. +#include <sound/tlv.h>
  2608. +#include <linux/of_gpio.h>
  2609. +#include <linux/regulator/consumer.h>
  2610. +#include <linux/pm_runtime.h>
  2611. +#include <linux/of_irq.h>
  2612. +#include <linux/completion.h>
  2613. +#include <linux/mutex.h>
  2614. +#include <linux/workqueue.h>
  2615. +#include <sound/jack.h>
  2616. +
  2617. +#include "../codecs/cs43130.h"
  2618. +
  2619. +#include <linux/clk.h>
  2620. +#include <linux/gcd.h>
  2621. +#define DEBUG
  2622. +
  2623. +#define CS43130_DSD_EN_MASK 0x10
  2624. +#define CS43130_PDN_DONE_INT_MASK 0x00
  2625. +
  2626. +static struct gpio_desc *snd_allo_clk44gpio;
  2627. +static struct gpio_desc *snd_allo_clk48gpio;
  2628. +
  2629. +struct cs43130_priv {
  2630. + struct snd_soc_component *component;
  2631. + struct regmap *regmap;
  2632. + struct regulator_bulk_data supplies[CS43130_NUM_SUPPLIES];
  2633. + struct gpio_desc *reset_gpio;
  2634. + unsigned int dev_id; /* codec device ID */
  2635. + int xtal_ibias;
  2636. + /* shared by both DAIs */
  2637. + struct mutex clk_mutex;
  2638. + int clk_req;
  2639. + bool pll_bypass;
  2640. + struct completion xtal_rdy;
  2641. + struct completion pll_rdy;
  2642. + unsigned int mclk;
  2643. + unsigned int mclk_int;
  2644. + int mclk_int_src;
  2645. +
  2646. + /* DAI specific */
  2647. + struct cs43130_dai dais[CS43130_DAI_ID_MAX];
  2648. +
  2649. + /* HP load specific */
  2650. + bool dc_meas;
  2651. + bool ac_meas;
  2652. + bool hpload_done;
  2653. + struct completion hpload_evt;
  2654. + unsigned int hpload_stat;
  2655. + u16 hpload_dc[2];
  2656. + u16 dc_threshold[CS43130_DC_THRESHOLD];
  2657. + u16 ac_freq[CS43130_AC_FREQ];
  2658. + u16 hpload_ac[CS43130_AC_FREQ][2];
  2659. + struct workqueue_struct *wq;
  2660. + struct work_struct work;
  2661. + struct snd_soc_jack jack;
  2662. +};
  2663. +
  2664. +static const struct reg_default cs43130_reg_defaults[] = {
  2665. + {CS43130_SYS_CLK_CTL_1, 0x06},
  2666. + {CS43130_SP_SRATE, 0x01},
  2667. + {CS43130_SP_BITSIZE, 0x05},
  2668. + {CS43130_PAD_INT_CFG, 0x03},
  2669. + {CS43130_PWDN_CTL, 0xFE},
  2670. + {CS43130_CRYSTAL_SET, 0x04},
  2671. + {CS43130_PLL_SET_1, 0x00},
  2672. + {CS43130_PLL_SET_2, 0x00},
  2673. + {CS43130_PLL_SET_3, 0x00},
  2674. + {CS43130_PLL_SET_4, 0x00},
  2675. + {CS43130_PLL_SET_5, 0x40},
  2676. + {CS43130_PLL_SET_6, 0x10},
  2677. + {CS43130_PLL_SET_7, 0x80},
  2678. + {CS43130_PLL_SET_8, 0x03},
  2679. + {CS43130_PLL_SET_9, 0x02},
  2680. + {CS43130_PLL_SET_10, 0x02},
  2681. + {CS43130_CLKOUT_CTL, 0x00},
  2682. + {CS43130_ASP_NUM_1, 0x01},
  2683. + {CS43130_ASP_NUM_2, 0x00},
  2684. + {CS43130_ASP_DEN_1, 0x08},
  2685. + {CS43130_ASP_DEN_2, 0x00},
  2686. + {CS43130_ASP_LRCK_HI_TIME_1, 0x1F},
  2687. + {CS43130_ASP_LRCK_HI_TIME_2, 0x00},
  2688. + {CS43130_ASP_LRCK_PERIOD_1, 0x3F},
  2689. + {CS43130_ASP_LRCK_PERIOD_2, 0x00},
  2690. + {CS43130_ASP_CLOCK_CONF, 0x0C},
  2691. + {CS43130_ASP_FRAME_CONF, 0x0A},
  2692. + {CS43130_XSP_NUM_1, 0x01},
  2693. + {CS43130_XSP_NUM_2, 0x00},
  2694. + {CS43130_XSP_DEN_1, 0x02},
  2695. + {CS43130_XSP_DEN_2, 0x00},
  2696. + {CS43130_XSP_LRCK_HI_TIME_1, 0x1F},
  2697. + {CS43130_XSP_LRCK_HI_TIME_2, 0x00},
  2698. + {CS43130_XSP_LRCK_PERIOD_1, 0x3F},
  2699. + {CS43130_XSP_LRCK_PERIOD_2, 0x00},
  2700. + {CS43130_XSP_CLOCK_CONF, 0x0C},
  2701. + {CS43130_XSP_FRAME_CONF, 0x0A},
  2702. + {CS43130_ASP_CH_1_LOC, 0x00},
  2703. + {CS43130_ASP_CH_2_LOC, 0x00},
  2704. + {CS43130_ASP_CH_1_SZ_EN, 0x06},
  2705. + {CS43130_ASP_CH_2_SZ_EN, 0x0E},
  2706. + {CS43130_XSP_CH_1_LOC, 0x00},
  2707. + {CS43130_XSP_CH_2_LOC, 0x00},
  2708. + {CS43130_XSP_CH_1_SZ_EN, 0x06},
  2709. + {CS43130_XSP_CH_2_SZ_EN, 0x0E},
  2710. + {CS43130_DSD_VOL_B, 0x78},
  2711. + {CS43130_DSD_VOL_A, 0x78},
  2712. + {CS43130_DSD_PATH_CTL_1, 0xA8},
  2713. + {CS43130_DSD_INT_CFG, 0x00},
  2714. + {CS43130_DSD_PATH_CTL_2, 0x02},
  2715. + {CS43130_DSD_PCM_MIX_CTL, 0x00},
  2716. + {CS43130_DSD_PATH_CTL_3, 0x40},
  2717. + {CS43130_HP_OUT_CTL_1, 0x30},
  2718. + {CS43130_PCM_FILT_OPT, 0x02},
  2719. + {CS43130_PCM_VOL_B, 0x78},
  2720. + {CS43130_PCM_VOL_A, 0x78},
  2721. + {CS43130_PCM_PATH_CTL_1, 0xA8},
  2722. + {CS43130_PCM_PATH_CTL_2, 0x00},
  2723. + {CS43130_CLASS_H_CTL, 0x1E},
  2724. + {CS43130_HP_DETECT, 0x04},
  2725. + {CS43130_HP_LOAD_1, 0x00},
  2726. + {CS43130_HP_MEAS_LOAD_1, 0x00},
  2727. + {CS43130_HP_MEAS_LOAD_2, 0x00},
  2728. + {CS43130_INT_MASK_1, 0xFF},
  2729. + {CS43130_INT_MASK_2, 0xFF},
  2730. + {CS43130_INT_MASK_3, 0xFF},
  2731. + {CS43130_INT_MASK_4, 0xFF},
  2732. + {CS43130_INT_MASK_5, 0xFF},
  2733. +};
  2734. +static bool cs43130_volatile_register(struct device *dev, unsigned int reg)
  2735. +{
  2736. + switch (reg) {
  2737. + case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
  2738. + case CS43130_HP_DC_STAT_1 ... CS43130_HP_DC_STAT_2:
  2739. + case CS43130_HP_AC_STAT_1 ... CS43130_HP_AC_STAT_2:
  2740. + return true;
  2741. + default:
  2742. + return false;
  2743. + }
  2744. +}
  2745. +
  2746. +static const char * const pcm_spd_texts[] = {
  2747. + "Fast",
  2748. + "Slow",
  2749. +};
  2750. +
  2751. +static SOC_ENUM_SINGLE_DECL(pcm_spd_enum, CS43130_PCM_FILT_OPT, 7,
  2752. + pcm_spd_texts);
  2753. +
  2754. +static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12750, 0);
  2755. +
  2756. +static const struct snd_kcontrol_new cs43130_controls[] = {
  2757. + SOC_DOUBLE_R_TLV("Master Playback Volume", CS43130_PCM_VOL_B,
  2758. + CS43130_PCM_VOL_A, 0, 255, 1, master_tlv),
  2759. + SOC_DOUBLE("Master Playback Switch", CS43130_PCM_PATH_CTL_1,
  2760. + 0, 1, 1, 1),
  2761. + SOC_DOUBLE_R_TLV("Digital Playback Volume", CS43130_DSD_VOL_B,
  2762. + CS43130_DSD_VOL_A, 0, 255, 1, master_tlv),
  2763. + SOC_DOUBLE("Digital Playback Switch", CS43130_DSD_PATH_CTL_1,
  2764. + 0, 1, 1, 1),
  2765. + SOC_SINGLE("HV_Enable", CS43130_HP_OUT_CTL_1, 0, 1, 0),
  2766. + SOC_ENUM("PCM Filter Speed", pcm_spd_enum),
  2767. + SOC_SINGLE("PCM Phase Compensation", CS43130_PCM_FILT_OPT, 6, 1, 0),
  2768. + SOC_SINGLE("PCM Nonoversample Emulate", CS43130_PCM_FILT_OPT, 5, 1, 0),
  2769. + SOC_SINGLE("PCM High-pass Filter", CS43130_PCM_FILT_OPT, 1, 1, 0),
  2770. + SOC_SINGLE("PCM De-emphasis Filter", CS43130_PCM_FILT_OPT, 0, 1, 0),
  2771. +};
  2772. +
  2773. +static bool cs43130_readable_register(struct device *dev, unsigned int reg)
  2774. +{
  2775. + switch (reg) {
  2776. + case CS43130_DEVID_AB ... CS43130_SYS_CLK_CTL_1:
  2777. + case CS43130_SP_SRATE ... CS43130_PAD_INT_CFG:
  2778. + case CS43130_PWDN_CTL:
  2779. + case CS43130_CRYSTAL_SET:
  2780. + case CS43130_PLL_SET_1 ... CS43130_PLL_SET_5:
  2781. + case CS43130_PLL_SET_6:
  2782. + case CS43130_PLL_SET_7:
  2783. + case CS43130_PLL_SET_8:
  2784. + case CS43130_PLL_SET_9:
  2785. + case CS43130_PLL_SET_10:
  2786. + case CS43130_CLKOUT_CTL:
  2787. + case CS43130_ASP_NUM_1 ... CS43130_ASP_FRAME_CONF:
  2788. + case CS43130_XSP_NUM_1 ... CS43130_XSP_FRAME_CONF:
  2789. + case CS43130_ASP_CH_1_LOC:
  2790. + case CS43130_ASP_CH_2_LOC:
  2791. + case CS43130_ASP_CH_1_SZ_EN:
  2792. + case CS43130_ASP_CH_2_SZ_EN:
  2793. + case CS43130_XSP_CH_1_LOC:
  2794. + case CS43130_XSP_CH_2_LOC:
  2795. + case CS43130_XSP_CH_1_SZ_EN:
  2796. + case CS43130_XSP_CH_2_SZ_EN:
  2797. + case CS43130_DSD_VOL_B ... CS43130_DSD_PATH_CTL_3:
  2798. + case CS43130_HP_OUT_CTL_1:
  2799. + case CS43130_PCM_FILT_OPT ... CS43130_PCM_PATH_CTL_2:
  2800. + case CS43130_CLASS_H_CTL:
  2801. + case CS43130_HP_DETECT:
  2802. + case CS43130_HP_STATUS:
  2803. + case CS43130_HP_LOAD_1:
  2804. + case CS43130_HP_MEAS_LOAD_1:
  2805. + case CS43130_HP_MEAS_LOAD_2:
  2806. + case CS43130_HP_DC_STAT_1:
  2807. + case CS43130_HP_DC_STAT_2:
  2808. + case CS43130_HP_AC_STAT_1:
  2809. + case CS43130_HP_AC_STAT_2:
  2810. + case CS43130_HP_LOAD_STAT:
  2811. + case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
  2812. + case CS43130_INT_MASK_1 ... CS43130_INT_MASK_5:
  2813. + return true;
  2814. + default:
  2815. + return false;
  2816. + }
  2817. +}
  2818. +static bool cs43130_precious_register(struct device *dev, unsigned int reg)
  2819. +{
  2820. + switch (reg) {
  2821. + case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:
  2822. + return true;
  2823. + default:
  2824. + return false;
  2825. + }
  2826. +}
  2827. +static int cs43130_pcm_pdn(struct snd_soc_component *component)
  2828. +{
  2829. + struct cs43130_priv *cs43130 =
  2830. + snd_soc_component_get_drvdata(component);
  2831. + int ret;
  2832. + unsigned int reg, pdn_int;
  2833. +
  2834. + regmap_write(cs43130->regmap, CS43130_DSD_PATH_CTL_2, 0x02);
  2835. + regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
  2836. + CS43130_PDN_DONE_INT_MASK, 0);
  2837. + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
  2838. + CS43130_PDN_HP_MASK, 1 << CS43130_PDN_HP_SHIFT);
  2839. + usleep_range(10, 50);
  2840. + ret = regmap_read(cs43130->regmap, CS43130_INT_STATUS_1, &reg);
  2841. + pdn_int = reg & 0xFE;
  2842. + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
  2843. + CS43130_PDN_ASP_MASK, 1 << CS43130_PDN_ASP_SHIFT);
  2844. + return 0;
  2845. +
  2846. +}
  2847. +static int cs43130_pwr_up_asp_dac(struct snd_soc_component *component)
  2848. +{
  2849. + struct cs43130_priv *cs43130 =
  2850. + snd_soc_component_get_drvdata(component);
  2851. +
  2852. + regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
  2853. + CS43130_ASP_3ST_MASK, 0);
  2854. + regmap_write(cs43130->regmap, CS43130_DXD1, 0x99);
  2855. + regmap_write(cs43130->regmap, CS43130_DXD13, 0x20);
  2856. + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
  2857. + CS43130_PDN_ASP_MASK, 0);
  2858. + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
  2859. + CS43130_PDN_HP_MASK, 0);
  2860. + usleep_range(10000, 12000);
  2861. + regmap_write(cs43130->regmap, CS43130_DXD1, 0x00);
  2862. + regmap_write(cs43130->regmap, CS43130_DXD13, 0x00);
  2863. + return 0;
  2864. +}
  2865. +static int cs43130_change_clksrc(struct snd_soc_component *component,
  2866. + enum cs43130_mclk_src_sel src)
  2867. +{
  2868. + int ret;
  2869. + struct cs43130_priv *cs43130 =
  2870. + snd_soc_component_get_drvdata(component);
  2871. + int mclk_int_decoded;
  2872. +
  2873. + if (src == cs43130->mclk_int_src) {
  2874. + /* clk source has not changed */
  2875. + return 0;
  2876. + }
  2877. + switch (cs43130->mclk_int) {
  2878. + case CS43130_MCLK_22M:
  2879. + mclk_int_decoded = CS43130_MCLK_22P5;
  2880. + break;
  2881. + case CS43130_MCLK_24M:
  2882. + mclk_int_decoded = CS43130_MCLK_24P5;
  2883. + break;
  2884. + default:
  2885. + dev_err(component->dev, "Invalid MCLK INT freq: %u\n",
  2886. + cs43130->mclk_int);
  2887. + return -EINVAL;
  2888. + }
  2889. +
  2890. + switch (src) {
  2891. + case CS43130_MCLK_SRC_EXT:
  2892. + cs43130->pll_bypass = true;
  2893. + cs43130->mclk_int_src = CS43130_MCLK_SRC_EXT;
  2894. + if (cs43130->xtal_ibias == CS43130_XTAL_UNUSED) {
  2895. + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
  2896. + CS43130_PDN_XTAL_MASK,
  2897. + 1 << CS43130_PDN_XTAL_SHIFT);
  2898. + } else {
  2899. + reinit_completion(&cs43130->xtal_rdy);
  2900. + regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
  2901. + CS43130_XTAL_RDY_INT_MASK, 0);
  2902. + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
  2903. + CS43130_PDN_XTAL_MASK, 0);
  2904. + ret = wait_for_completion_timeout(&cs43130->xtal_rdy,
  2905. + msecs_to_jiffies(100));
  2906. + regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
  2907. + CS43130_XTAL_RDY_INT_MASK,
  2908. + 1 << CS43130_XTAL_RDY_INT_SHIFT);
  2909. + if (ret == 0) {
  2910. + dev_err(component->dev, "Timeout waiting for XTAL_READY interrupt\n");
  2911. + return -ETIMEDOUT;
  2912. + }
  2913. + }
  2914. + regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
  2915. + CS43130_MCLK_SRC_SEL_MASK,
  2916. + src << CS43130_MCLK_SRC_SEL_SHIFT);
  2917. + regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
  2918. + CS43130_MCLK_INT_MASK,
  2919. + mclk_int_decoded << CS43130_MCLK_INT_SHIFT);
  2920. + usleep_range(150, 200);
  2921. + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
  2922. + CS43130_PDN_PLL_MASK,
  2923. + 1 << CS43130_PDN_PLL_SHIFT);
  2924. + break;
  2925. + case CS43130_MCLK_SRC_RCO:
  2926. + cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;
  2927. +
  2928. + regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
  2929. + CS43130_MCLK_SRC_SEL_MASK,
  2930. + src << CS43130_MCLK_SRC_SEL_SHIFT);
  2931. + regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,
  2932. + CS43130_MCLK_INT_MASK,
  2933. + CS43130_MCLK_22P5 << CS43130_MCLK_INT_SHIFT);
  2934. + usleep_range(150, 200);
  2935. + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
  2936. + CS43130_PDN_XTAL_MASK,
  2937. + 1 << CS43130_PDN_XTAL_SHIFT);
  2938. + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
  2939. + CS43130_PDN_PLL_MASK,
  2940. + 1 << CS43130_PDN_PLL_SHIFT);
  2941. + break;
  2942. + default:
  2943. + dev_err(component->dev, "Invalid MCLK source value\n");
  2944. + return -EINVAL;
  2945. + }
  2946. +
  2947. + return 0;
  2948. +}
  2949. +static const struct cs43130_bitwidth_map cs43130_bitwidth_table[] = {
  2950. + {8, CS43130_SP_BIT_SIZE_8, CS43130_CH_BIT_SIZE_8},
  2951. + {16, CS43130_SP_BIT_SIZE_16, CS43130_CH_BIT_SIZE_16},
  2952. + {24, CS43130_SP_BIT_SIZE_24, CS43130_CH_BIT_SIZE_24},
  2953. + {32, CS43130_SP_BIT_SIZE_32, CS43130_CH_BIT_SIZE_32},
  2954. +};
  2955. +
  2956. +static const struct cs43130_bitwidth_map *cs43130_get_bitwidth_table(
  2957. + unsigned int bitwidth)
  2958. +{
  2959. + int i;
  2960. +
  2961. + for (i = 0; i < ARRAY_SIZE(cs43130_bitwidth_table); i++) {
  2962. + if (cs43130_bitwidth_table[i].bitwidth == bitwidth)
  2963. + return &cs43130_bitwidth_table[i];
  2964. + }
  2965. +
  2966. + return NULL;
  2967. +}
  2968. +static int cs43130_set_bitwidth(int dai_id, unsigned int bitwidth_dai,
  2969. + struct regmap *regmap)
  2970. +{
  2971. + const struct cs43130_bitwidth_map *bw_map;
  2972. +
  2973. + bw_map = cs43130_get_bitwidth_table(bitwidth_dai);
  2974. + if (!bw_map)
  2975. + return -EINVAL;
  2976. +
  2977. + switch (dai_id) {
  2978. + case CS43130_ASP_PCM_DAI:
  2979. + case CS43130_ASP_DOP_DAI:
  2980. + regmap_update_bits(regmap, CS43130_ASP_CH_1_SZ_EN,
  2981. + CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
  2982. + regmap_update_bits(regmap, CS43130_ASP_CH_2_SZ_EN,
  2983. + CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
  2984. + regmap_update_bits(regmap, CS43130_SP_BITSIZE,
  2985. + CS43130_ASP_BITSIZE_MASK, bw_map->sp_bit);
  2986. + break;
  2987. + case CS43130_XSP_DOP_DAI:
  2988. + regmap_update_bits(regmap, CS43130_XSP_CH_1_SZ_EN,
  2989. + CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
  2990. + regmap_update_bits(regmap, CS43130_XSP_CH_2_SZ_EN,
  2991. + CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);
  2992. + regmap_update_bits(regmap, CS43130_SP_BITSIZE,
  2993. + CS43130_XSP_BITSIZE_MASK, bw_map->sp_bit <<
  2994. + CS43130_XSP_BITSIZE_SHIFT);
  2995. + break;
  2996. + default:
  2997. + return -EINVAL;
  2998. + }
  2999. +
  3000. + return 0;
  3001. +}
  3002. +static const struct cs43130_rate_map cs43130_rate_table[] = {
  3003. + {32000, CS43130_ASP_SPRATE_32K},
  3004. + {44100, CS43130_ASP_SPRATE_44_1K},
  3005. + {48000, CS43130_ASP_SPRATE_48K},
  3006. + {88200, CS43130_ASP_SPRATE_88_2K},
  3007. + {96000, CS43130_ASP_SPRATE_96K},
  3008. + {176400, CS43130_ASP_SPRATE_176_4K},
  3009. + {192000, CS43130_ASP_SPRATE_192K},
  3010. + {352800, CS43130_ASP_SPRATE_352_8K},
  3011. + {384000, CS43130_ASP_SPRATE_384K},
  3012. +};
  3013. +
  3014. +static const struct cs43130_rate_map *cs43130_get_rate_table(int fs)
  3015. +{
  3016. + int i;
  3017. +
  3018. + for (i = 0; i < ARRAY_SIZE(cs43130_rate_table); i++) {
  3019. + if (cs43130_rate_table[i].fs == fs)
  3020. + return &cs43130_rate_table[i];
  3021. + }
  3022. +
  3023. + return NULL;
  3024. +}
  3025. +
  3026. +static const struct cs43130_clk_gen *cs43130_get_clk_gen(int mclk_int, int fs,
  3027. + const struct cs43130_clk_gen *clk_gen_table, int len_clk_gen_table)
  3028. +{
  3029. + int i;
  3030. +
  3031. + for (i = 0; i < len_clk_gen_table; i++) {
  3032. + if (clk_gen_table[i].mclk_int == mclk_int &&
  3033. + clk_gen_table[i].fs == fs)
  3034. + return &clk_gen_table[i];
  3035. + }
  3036. + return NULL;
  3037. +}
  3038. +
  3039. +static int cs43130_set_sp_fmt(int dai_id, unsigned int bitwidth_sclk,
  3040. + struct snd_pcm_hw_params *params,
  3041. + struct cs43130_priv *cs43130)
  3042. +{
  3043. + u16 frm_size;
  3044. + u16 hi_size;
  3045. + u8 frm_delay;
  3046. + u8 frm_phase;
  3047. + u8 frm_data;
  3048. + u8 sclk_edge;
  3049. + u8 lrck_edge;
  3050. + u8 clk_data;
  3051. + u8 loc_ch1;
  3052. + u8 loc_ch2;
  3053. + u8 dai_mode_val;
  3054. + const struct cs43130_clk_gen *clk_gen;
  3055. +
  3056. + switch (cs43130->dais[dai_id].dai_format) {
  3057. + case SND_SOC_DAIFMT_I2S:
  3058. + hi_size = bitwidth_sclk;
  3059. + frm_delay = 2;
  3060. + frm_phase = 0;
  3061. + break;
  3062. + case SND_SOC_DAIFMT_LEFT_J:
  3063. + hi_size = bitwidth_sclk;
  3064. + frm_delay = 2;
  3065. + frm_phase = 1;
  3066. + break;
  3067. + case SND_SOC_DAIFMT_DSP_A:
  3068. + hi_size = 1;
  3069. + frm_delay = 2;
  3070. + frm_phase = 1;
  3071. + break;
  3072. + case SND_SOC_DAIFMT_DSP_B:
  3073. + hi_size = 1;
  3074. + frm_delay = 0;
  3075. + frm_phase = 1;
  3076. + break;
  3077. + default:
  3078. + return -EINVAL;
  3079. + }
  3080. + switch (cs43130->dais[dai_id].dai_mode) {
  3081. + case SND_SOC_DAIFMT_CBS_CFS:
  3082. + dai_mode_val = 0;
  3083. + break;
  3084. + case SND_SOC_DAIFMT_CBM_CFM:
  3085. + dai_mode_val = 1;
  3086. + break;
  3087. + default:
  3088. + return -EINVAL;
  3089. + }
  3090. +
  3091. + frm_size = bitwidth_sclk * params_channels(params);
  3092. + sclk_edge = 1;
  3093. + lrck_edge = 0;
  3094. + loc_ch1 = 0;
  3095. + loc_ch2 = bitwidth_sclk * (params_channels(params) - 1);
  3096. +
  3097. + frm_data = frm_delay & CS43130_SP_FSD_MASK;
  3098. + frm_data |= (frm_phase << CS43130_SP_STP_SHIFT) & CS43130_SP_STP_MASK;
  3099. +
  3100. + clk_data = lrck_edge & CS43130_SP_LCPOL_IN_MASK;
  3101. + clk_data |= (lrck_edge << CS43130_SP_LCPOL_OUT_SHIFT) &
  3102. + CS43130_SP_LCPOL_OUT_MASK;
  3103. + clk_data |= (sclk_edge << CS43130_SP_SCPOL_IN_SHIFT) &
  3104. + CS43130_SP_SCPOL_IN_MASK;
  3105. + clk_data |= (sclk_edge << CS43130_SP_SCPOL_OUT_SHIFT) &
  3106. + CS43130_SP_SCPOL_OUT_MASK;
  3107. + clk_data |= (dai_mode_val << CS43130_SP_MODE_SHIFT) &
  3108. + CS43130_SP_MODE_MASK;
  3109. + switch (dai_id) {
  3110. + case CS43130_ASP_PCM_DAI:
  3111. + case CS43130_ASP_DOP_DAI:
  3112. + regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_1,
  3113. + CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
  3114. + CS43130_SP_LCPR_LSB_DATA_SHIFT);
  3115. + regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_2,
  3116. + CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
  3117. + CS43130_SP_LCPR_MSB_DATA_SHIFT);
  3118. + regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_1,
  3119. + CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
  3120. + CS43130_SP_LCHI_LSB_DATA_SHIFT);
  3121. + regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_2,
  3122. + CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
  3123. + CS43130_SP_LCHI_MSB_DATA_SHIFT);
  3124. + regmap_write(cs43130->regmap, CS43130_ASP_FRAME_CONF, frm_data);
  3125. + regmap_write(cs43130->regmap, CS43130_ASP_CH_1_LOC, loc_ch1);
  3126. + regmap_write(cs43130->regmap, CS43130_ASP_CH_2_LOC, loc_ch2);
  3127. + regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_1_SZ_EN,
  3128. + CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
  3129. + regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_2_SZ_EN,
  3130. + CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
  3131. + regmap_write(cs43130->regmap, CS43130_ASP_CLOCK_CONF, clk_data);
  3132. + break;
  3133. + case CS43130_XSP_DOP_DAI:
  3134. + regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_1,
  3135. + CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
  3136. + CS43130_SP_LCPR_LSB_DATA_SHIFT);
  3137. + regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_2,
  3138. + CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>
  3139. + CS43130_SP_LCPR_MSB_DATA_SHIFT);
  3140. + regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_1,
  3141. + CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
  3142. + CS43130_SP_LCHI_LSB_DATA_SHIFT);
  3143. + regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_2,
  3144. + CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>
  3145. + CS43130_SP_LCHI_MSB_DATA_SHIFT);
  3146. + regmap_write(cs43130->regmap, CS43130_XSP_FRAME_CONF, frm_data);
  3147. + regmap_write(cs43130->regmap, CS43130_XSP_CH_1_LOC, loc_ch1);
  3148. + regmap_write(cs43130->regmap, CS43130_XSP_CH_2_LOC, loc_ch2);
  3149. + regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_1_SZ_EN,
  3150. + CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
  3151. + regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_2_SZ_EN,
  3152. + CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);
  3153. + regmap_write(cs43130->regmap, CS43130_XSP_CLOCK_CONF, clk_data);
  3154. + break;
  3155. + default:
  3156. + return -EINVAL;
  3157. + }
  3158. + switch (frm_size) {
  3159. + case 16:
  3160. + clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
  3161. + params_rate(params),
  3162. + cs43130_16_clk_gen,
  3163. + ARRAY_SIZE(cs43130_16_clk_gen));
  3164. + break;
  3165. + case 32:
  3166. + clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
  3167. + params_rate(params),
  3168. + cs43130_32_clk_gen,
  3169. + ARRAY_SIZE(cs43130_32_clk_gen));
  3170. + break;
  3171. + case 48:
  3172. + clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
  3173. + params_rate(params),
  3174. + cs43130_48_clk_gen,
  3175. + ARRAY_SIZE(cs43130_48_clk_gen));
  3176. + break;
  3177. + case 64:
  3178. + clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,
  3179. + params_rate(params),
  3180. + cs43130_64_clk_gen,
  3181. + ARRAY_SIZE(cs43130_64_clk_gen));
  3182. + break;
  3183. + default:
  3184. + return -EINVAL;
  3185. + }
  3186. + if (!clk_gen)
  3187. + return -EINVAL;
  3188. + switch (dai_id) {
  3189. + case CS43130_ASP_PCM_DAI:
  3190. + case CS43130_ASP_DOP_DAI:
  3191. + regmap_write(cs43130->regmap, CS43130_ASP_DEN_1,
  3192. + (clk_gen->v.denominator & CS43130_SP_M_LSB_DATA_MASK) >>
  3193. + CS43130_SP_M_LSB_DATA_SHIFT);
  3194. + regmap_write(cs43130->regmap, CS43130_ASP_DEN_2,
  3195. + (clk_gen->v.denominator & CS43130_SP_M_MSB_DATA_MASK) >>
  3196. + CS43130_SP_M_MSB_DATA_SHIFT);
  3197. + regmap_write(cs43130->regmap, CS43130_ASP_NUM_1,
  3198. + (clk_gen->v.numerator & CS43130_SP_N_LSB_DATA_MASK) >>
  3199. + CS43130_SP_N_LSB_DATA_SHIFT);
  3200. + regmap_write(cs43130->regmap, CS43130_ASP_NUM_2,
  3201. + (clk_gen->v.numerator & CS43130_SP_N_MSB_DATA_MASK) >>
  3202. + CS43130_SP_N_MSB_DATA_SHIFT);
  3203. + break;
  3204. + case CS43130_XSP_DOP_DAI:
  3205. + regmap_write(cs43130->regmap, CS43130_XSP_DEN_1,
  3206. + (clk_gen->v.denominator & CS43130_SP_M_LSB_DATA_MASK) >>
  3207. + CS43130_SP_M_LSB_DATA_SHIFT);
  3208. + regmap_write(cs43130->regmap, CS43130_XSP_DEN_2,
  3209. + (clk_gen->v.denominator & CS43130_SP_M_MSB_DATA_MASK) >>
  3210. + CS43130_SP_M_MSB_DATA_SHIFT);
  3211. + regmap_write(cs43130->regmap, CS43130_XSP_NUM_1,
  3212. + (clk_gen->v.numerator & CS43130_SP_N_LSB_DATA_MASK) >>
  3213. + CS43130_SP_N_LSB_DATA_SHIFT);
  3214. + regmap_write(cs43130->regmap, CS43130_XSP_NUM_2,
  3215. + (clk_gen->v.numerator & CS43130_SP_N_MSB_DATA_MASK) >>
  3216. + CS43130_SP_N_MSB_DATA_SHIFT);
  3217. + break;
  3218. + default:
  3219. + return -EINVAL;
  3220. + }
  3221. + return 0;
  3222. +}
  3223. +
  3224. +static int cs43130_hw_params(struct snd_pcm_substream *substream,
  3225. + struct snd_pcm_hw_params *params,
  3226. + struct snd_soc_dai *dai)
  3227. +{
  3228. + struct snd_soc_component *component = dai->component;
  3229. + struct cs43130_priv *cs43130 =
  3230. + snd_soc_component_get_drvdata(component);
  3231. + const struct cs43130_rate_map *rate_map;
  3232. + unsigned int sclk = cs43130->dais[dai->id].sclk;
  3233. + unsigned int bitwidth_sclk;
  3234. + unsigned int bitwidth_dai = (unsigned int)(params_width(params));
  3235. + unsigned int dop_rate = (unsigned int)(params_rate(params));
  3236. + unsigned int required_clk, ret;
  3237. + u8 dsd_speed;
  3238. +
  3239. + cs43130->pll_bypass = true;
  3240. + cs43130_pcm_pdn(component);
  3241. + mutex_lock(&cs43130->clk_mutex);
  3242. + if (!cs43130->clk_req) {
  3243. + /* no DAI is currently using clk */
  3244. + if (!(CS43130_MCLK_22M % params_rate(params))) {
  3245. + required_clk = CS43130_MCLK_22M;
  3246. + cs43130->mclk_int = CS43130_MCLK_22M;
  3247. + gpiod_set_value_cansleep(snd_allo_clk44gpio, 1);
  3248. + gpiod_set_value_cansleep(snd_allo_clk48gpio, 0);
  3249. + usleep_range(13500, 14000);
  3250. + } else {
  3251. + required_clk = CS43130_MCLK_24M;
  3252. + cs43130->mclk_int = CS43130_MCLK_24M;
  3253. + gpiod_set_value_cansleep(snd_allo_clk48gpio, 1);
  3254. + gpiod_set_value_cansleep(snd_allo_clk44gpio, 0);
  3255. + usleep_range(13500, 14000);
  3256. + }
  3257. + if (cs43130->pll_bypass)
  3258. + cs43130_change_clksrc(component, CS43130_MCLK_SRC_EXT);
  3259. + else
  3260. + cs43130_change_clksrc(component, CS43130_MCLK_SRC_PLL);
  3261. + }
  3262. +
  3263. + cs43130->clk_req++;
  3264. + mutex_unlock(&cs43130->clk_mutex);
  3265. +
  3266. + switch (dai->id) {
  3267. + case CS43130_ASP_DOP_DAI:
  3268. + case CS43130_XSP_DOP_DAI:
  3269. + /* DoP bitwidth is always 24-bit */
  3270. + bitwidth_dai = 24;
  3271. + sclk = params_rate(params) * bitwidth_dai *
  3272. + params_channels(params);
  3273. +
  3274. + switch (params_rate(params)) {
  3275. + case 176400:
  3276. + dsd_speed = 0;
  3277. + break;
  3278. + case 352800:
  3279. + dsd_speed = 1;
  3280. + break;
  3281. + default:
  3282. + dev_err(component->dev, "Rate(%u) not supported\n",
  3283. + params_rate(params));
  3284. + return -EINVAL;
  3285. + }
  3286. +
  3287. + regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
  3288. + CS43130_DSD_SPEED_MASK,
  3289. + dsd_speed << CS43130_DSD_SPEED_SHIFT);
  3290. + break;
  3291. + case CS43130_ASP_PCM_DAI:
  3292. + rate_map = cs43130_get_rate_table(params_rate(params));
  3293. + if (!rate_map)
  3294. + return -EINVAL;
  3295. +
  3296. + regmap_write(cs43130->regmap, CS43130_SP_SRATE, rate_map->val);
  3297. + if ((dop_rate == 176400) && (bitwidth_dai == 24)) {
  3298. + dsd_speed = 0;
  3299. + regmap_update_bits(cs43130->regmap,
  3300. + CS43130_DSD_PATH_CTL_2,
  3301. + CS43130_DSD_SPEED_MASK,
  3302. + dsd_speed << CS43130_DSD_SPEED_SHIFT);
  3303. + regmap_update_bits(cs43130->regmap,
  3304. + CS43130_DSD_PATH_CTL_2,
  3305. + CS43130_DSD_SRC_MASK,
  3306. + CS43130_DSD_SRC_ASP <<
  3307. + CS43130_DSD_SRC_SHIFT);
  3308. + regmap_update_bits(cs43130->regmap,
  3309. + CS43130_DSD_PATH_CTL_2,
  3310. + CS43130_DSD_EN_MASK, 0x01 <<
  3311. + CS43130_DSD_EN_SHIFT);
  3312. + }
  3313. + break;
  3314. + default:
  3315. + dev_err(component->dev, "Invalid DAI (%d)\n", dai->id);
  3316. + return -EINVAL;
  3317. + }
  3318. +
  3319. + switch (dai->id) {
  3320. + case CS43130_ASP_DOP_DAI:
  3321. + regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
  3322. + CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_ASP <<
  3323. + CS43130_DSD_SRC_SHIFT);
  3324. + regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
  3325. + CS43130_DSD_EN_MASK, 0x01 <<
  3326. + CS43130_DSD_EN_SHIFT);
  3327. + break;
  3328. + case CS43130_XSP_DOP_DAI:
  3329. + regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,
  3330. + CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_XSP <<
  3331. + CS43130_DSD_SRC_SHIFT);
  3332. + break;
  3333. + }
  3334. + if (!sclk && cs43130->dais[dai->id].dai_mode ==
  3335. + SND_SOC_DAIFMT_CBM_CFM) {
  3336. + /* Calculate SCLK in master mode if unassigned */
  3337. + sclk = params_rate(params) * bitwidth_dai *
  3338. + params_channels(params);
  3339. + }
  3340. + if (!sclk) {
  3341. + /* at this point, SCLK must be set */
  3342. + dev_err(component->dev, "SCLK freq is not set\n");
  3343. + return -EINVAL;
  3344. + }
  3345. +
  3346. + bitwidth_sclk = (sclk / params_rate(params)) / params_channels(params);
  3347. + if (bitwidth_sclk < bitwidth_dai) {
  3348. + dev_err(component->dev, "Format not supported: SCLK freq is too low\n");
  3349. + return -EINVAL;
  3350. + }
  3351. +
  3352. + dev_dbg(component->dev,
  3353. + "sclk = %u, fs = %d, bitwidth_dai = %u\n",
  3354. + sclk, params_rate(params), bitwidth_dai);
  3355. +
  3356. + dev_dbg(component->dev,
  3357. + "bitwidth_sclk = %u, num_ch = %u\n",
  3358. + bitwidth_sclk, params_channels(params));
  3359. +
  3360. + cs43130_set_bitwidth(dai->id, bitwidth_dai, cs43130->regmap);
  3361. + cs43130_set_sp_fmt(dai->id, bitwidth_sclk, params, cs43130);
  3362. + ret = cs43130_pwr_up_asp_dac(component);
  3363. + return 0;
  3364. +}
  3365. +
  3366. +static int cs43130_hw_free(struct snd_pcm_substream *substream,
  3367. + struct snd_soc_dai *dai)
  3368. +{
  3369. + struct snd_soc_component *component = dai->component;
  3370. + struct cs43130_priv *cs43130 =
  3371. + snd_soc_component_get_drvdata(component);
  3372. +
  3373. + mutex_lock(&cs43130->clk_mutex);
  3374. + cs43130->clk_req--;
  3375. + if (!cs43130->clk_req) {
  3376. + /* no DAI is currently using clk */
  3377. + cs43130_change_clksrc(component, CS43130_MCLK_SRC_RCO);
  3378. + cs43130_pcm_pdn(component);
  3379. + }
  3380. + mutex_unlock(&cs43130->clk_mutex);
  3381. +
  3382. + return 0;
  3383. +}
  3384. +
  3385. +static const unsigned int cs43130_asp_src_rates[] = {
  3386. + 32000, 44100, 48000, 88200, 96000, 176400, 192000
  3387. +};
  3388. +
  3389. +static const struct snd_pcm_hw_constraint_list cs43130_asp_constraints = {
  3390. + .count = ARRAY_SIZE(cs43130_asp_src_rates),
  3391. + .list = cs43130_asp_src_rates,
  3392. +};
  3393. +
  3394. +static int cs43130_pcm_startup(struct snd_pcm_substream *substream,
  3395. + struct snd_soc_dai *dai)
  3396. +{
  3397. + return snd_pcm_hw_constraint_list(substream->runtime, 0,
  3398. + SNDRV_PCM_HW_PARAM_RATE,
  3399. + &cs43130_asp_constraints);
  3400. +}
  3401. +
  3402. +static int cs43130_pcm_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
  3403. +{
  3404. + struct snd_soc_component *component = codec_dai->component;
  3405. + struct cs43130_priv *cs43130 =
  3406. + snd_soc_component_get_drvdata(component);
  3407. +
  3408. + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  3409. + case SND_SOC_DAIFMT_CBS_CFS:
  3410. + cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBS_CFS;
  3411. + break;
  3412. + case SND_SOC_DAIFMT_CBM_CFM:
  3413. + cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBM_CFM;
  3414. + break;
  3415. + default:
  3416. + dev_err(component->dev, "unsupported mode\n");
  3417. + return -EINVAL;
  3418. + }
  3419. +
  3420. + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  3421. + case SND_SOC_DAIFMT_I2S:
  3422. + cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_I2S;
  3423. + break;
  3424. + case SND_SOC_DAIFMT_LEFT_J:
  3425. + cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_LEFT_J;
  3426. + break;
  3427. + default:
  3428. + dev_err(component->dev,
  3429. + "unsupported audio format\n");
  3430. + return -EINVAL;
  3431. + }
  3432. +
  3433. + dev_dbg(component->dev, "dai_id = %d, dai_mode = %u, dai_format = %u\n",
  3434. + codec_dai->id,
  3435. + cs43130->dais[codec_dai->id].dai_mode,
  3436. + cs43130->dais[codec_dai->id].dai_format);
  3437. +
  3438. + return 0;
  3439. +}
  3440. +
  3441. +static int cs43130_set_sysclk(struct snd_soc_dai *codec_dai,
  3442. + int clk_id, unsigned int freq, int dir)
  3443. +{
  3444. + struct snd_soc_component *component = codec_dai->component;
  3445. + struct cs43130_priv *cs43130 =
  3446. + snd_soc_component_get_drvdata(component);
  3447. +
  3448. + cs43130->dais[codec_dai->id].sclk = freq;
  3449. + dev_dbg(component->dev, "dai_id = %d, sclk = %u\n", codec_dai->id,
  3450. + cs43130->dais[codec_dai->id].sclk);
  3451. +
  3452. + return 0;
  3453. +}
  3454. +
  3455. +static int cs43130_component_set_sysclk(struct snd_soc_component *component,
  3456. + int clk_id, int source,
  3457. + unsigned int freq, int dir)
  3458. +{
  3459. + struct cs43130_priv *cs43130 =
  3460. + snd_soc_component_get_drvdata(component);
  3461. +
  3462. + dev_dbg(component->dev, "clk_id = %d, source = %d, freq = %d, dir = %d\n",
  3463. + clk_id, source, freq, dir);
  3464. +
  3465. + switch (freq) {
  3466. + case CS43130_MCLK_22M:
  3467. + case CS43130_MCLK_24M:
  3468. + cs43130->mclk = freq;
  3469. + break;
  3470. + default:
  3471. + dev_err(component->dev, "Invalid MCLK INT freq: %u\n", freq);
  3472. + return -EINVAL;
  3473. + }
  3474. +
  3475. + if (source == CS43130_MCLK_SRC_EXT) {
  3476. + cs43130->pll_bypass = true;
  3477. + } else {
  3478. + dev_err(component->dev, "Invalid MCLK source\n");
  3479. + return -EINVAL;
  3480. + }
  3481. +
  3482. + return 0;
  3483. +}
  3484. +static u16 const cs43130_ac_freq[CS43130_AC_FREQ] = {
  3485. + 24,
  3486. + 43,
  3487. + 93,
  3488. + 200,
  3489. + 431,
  3490. + 928,
  3491. + 2000,
  3492. + 4309,
  3493. + 9283,
  3494. + 20000,
  3495. +};
  3496. +static const struct snd_soc_dai_ops cs43130_dai_ops = {
  3497. + .startup = cs43130_pcm_startup,
  3498. + .hw_params = cs43130_hw_params,
  3499. + .hw_free = cs43130_hw_free,
  3500. + .set_sysclk = cs43130_set_sysclk,
  3501. + .set_fmt = cs43130_pcm_set_fmt,
  3502. +};
  3503. +
  3504. +static struct snd_soc_dai_driver cs43130_codec_dai = {
  3505. + .name = "allo-cs43130",
  3506. + .playback = {
  3507. + .stream_name = "Playback",
  3508. + .channels_min = 2,
  3509. + .channels_max = 2,
  3510. + .rates = SNDRV_PCM_RATE_CONTINUOUS,
  3511. + .rate_min = 44100,
  3512. + .rate_max = 192000,
  3513. + .formats = SNDRV_PCM_FMTBIT_S16_LE |
  3514. + SNDRV_PCM_FMTBIT_S24_LE |
  3515. + SNDRV_PCM_FMTBIT_S32_LE
  3516. +
  3517. + },
  3518. + .ops = &cs43130_dai_ops,
  3519. +};
  3520. +
  3521. +static struct snd_soc_component_driver cs43130_component_driver = {
  3522. + .idle_bias_on = true,
  3523. + .controls = cs43130_controls,
  3524. + .num_controls = ARRAY_SIZE(cs43130_controls),
  3525. + .set_sysclk = cs43130_component_set_sysclk,
  3526. + .idle_bias_on = 1,
  3527. + .use_pmdown_time = 1,
  3528. + .endianness = 1,
  3529. +};
  3530. +
  3531. +static const struct regmap_config cs43130_regmap = {
  3532. + .reg_bits = 24,
  3533. + .pad_bits = 8,
  3534. + .val_bits = 8,
  3535. +
  3536. + .max_register = CS43130_LASTREG,
  3537. + .reg_defaults = cs43130_reg_defaults,
  3538. + .num_reg_defaults = ARRAY_SIZE(cs43130_reg_defaults),
  3539. + .readable_reg = cs43130_readable_register,
  3540. + .precious_reg = cs43130_precious_register,
  3541. + .volatile_reg = cs43130_volatile_register,
  3542. + .cache_type = REGCACHE_RBTREE,
  3543. + /* needed for regcache_sync */
  3544. + .use_single_read = true,
  3545. + .use_single_write = true,
  3546. +};
  3547. +
  3548. +static u16 const cs43130_dc_threshold[CS43130_DC_THRESHOLD] = {
  3549. + 50,
  3550. + 120,
  3551. +};
  3552. +
  3553. +static int cs43130_handle_device_data(struct i2c_client *i2c_client,
  3554. + struct cs43130_priv *cs43130)
  3555. +{
  3556. + struct device_node *np = i2c_client->dev.of_node;
  3557. + unsigned int val;
  3558. + int i;
  3559. +
  3560. + if (of_property_read_u32(np, "cirrus,xtal-ibias", &val) < 0) {
  3561. + /* Crystal is unused. System clock is used for external MCLK */
  3562. + cs43130->xtal_ibias = CS43130_XTAL_UNUSED;
  3563. + return 0;
  3564. + }
  3565. +
  3566. + switch (val) {
  3567. + case 1:
  3568. + cs43130->xtal_ibias = CS43130_XTAL_IBIAS_7_5UA;
  3569. + break;
  3570. + case 2:
  3571. + cs43130->xtal_ibias = CS43130_XTAL_IBIAS_12_5UA;
  3572. + break;
  3573. + case 3:
  3574. + cs43130->xtal_ibias = CS43130_XTAL_IBIAS_15UA;
  3575. + break;
  3576. + default:
  3577. + dev_err(&i2c_client->dev,
  3578. + "Invalid cirrus,xtal-ibias value: %d\n", val);
  3579. + return -EINVAL;
  3580. + }
  3581. +
  3582. + cs43130->dc_meas = of_property_read_bool(np, "cirrus,dc-measure");
  3583. + cs43130->ac_meas = of_property_read_bool(np, "cirrus,ac-measure");
  3584. +
  3585. + if (of_property_read_u16_array(np, "cirrus,ac-freq", cs43130->ac_freq,
  3586. + CS43130_AC_FREQ) < 0) {
  3587. + for (i = 0; i < CS43130_AC_FREQ; i++)
  3588. + cs43130->ac_freq[i] = cs43130_ac_freq[i];
  3589. + }
  3590. +
  3591. + if (of_property_read_u16_array(np, "cirrus,dc-threshold",
  3592. + cs43130->dc_threshold,
  3593. + CS43130_DC_THRESHOLD) < 0) {
  3594. + for (i = 0; i < CS43130_DC_THRESHOLD; i++)
  3595. + cs43130->dc_threshold[i] = cs43130_dc_threshold[i];
  3596. + }
  3597. +
  3598. + return 0;
  3599. +}
  3600. +
  3601. +
  3602. +static int allo_cs43130_component_probe(struct i2c_client *i2c)
  3603. +{
  3604. + struct regmap *regmap;
  3605. + struct regmap_config config = cs43130_regmap;
  3606. + struct device *dev = &i2c->dev;
  3607. + struct cs43130_priv *cs43130;
  3608. + unsigned int devid = 0;
  3609. + unsigned int reg;
  3610. + int ret;
  3611. +
  3612. + regmap = devm_regmap_init_i2c(i2c, &config);
  3613. + if (IS_ERR(regmap))
  3614. + return PTR_ERR(regmap);
  3615. +
  3616. + cs43130 = devm_kzalloc(dev, sizeof(struct cs43130_priv),
  3617. + GFP_KERNEL);
  3618. + if (!cs43130)
  3619. + return -ENOMEM;
  3620. +
  3621. + dev_set_drvdata(dev, cs43130);
  3622. + cs43130->regmap = regmap;
  3623. +
  3624. + if (i2c->dev.of_node) {
  3625. + ret = cs43130_handle_device_data(i2c, cs43130);
  3626. + if (ret != 0)
  3627. + return ret;
  3628. + }
  3629. + usleep_range(2000, 2050);
  3630. +
  3631. + ret = regmap_read(cs43130->regmap, CS43130_DEVID_AB, &reg);
  3632. + devid = (reg & 0xFF) << 12;
  3633. + ret = regmap_read(cs43130->regmap, CS43130_DEVID_CD, &reg);
  3634. + devid |= (reg & 0xFF) << 4;
  3635. + ret = regmap_read(cs43130->regmap, CS43130_DEVID_E, &reg);
  3636. + devid |= (reg & 0xF0) >> 4;
  3637. + if (devid != CS43198_CHIP_ID) {
  3638. + dev_err(dev, "Failed to read Chip or wrong Chip id: %d\n", ret);
  3639. + return ret;
  3640. + }
  3641. +
  3642. + cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;
  3643. + msleep(20);
  3644. +
  3645. + ret = snd_soc_register_component(dev, &cs43130_component_driver,
  3646. + &cs43130_codec_dai, 1);
  3647. + if (ret != 0) {
  3648. + dev_err(dev, "failed to register codec: %d\n", ret);
  3649. + return ret;
  3650. + }
  3651. + regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
  3652. + CS43130_ASP_3ST_MASK, 0);
  3653. + regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
  3654. + CS43130_XSP_3ST_MASK, 1);
  3655. + regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,
  3656. + CS43130_PDN_HP_MASK, 1 << CS43130_PDN_HP_SHIFT);
  3657. + msleep(20);
  3658. + regmap_write(cs43130->regmap, CS43130_CLASS_H_CTL, 0x06);
  3659. + snd_allo_clk44gpio = devm_gpiod_get(dev, "clock44", GPIOD_OUT_HIGH);
  3660. + if (IS_ERR(snd_allo_clk44gpio))
  3661. + dev_err(dev, "devm_gpiod_get() failed\n");
  3662. +
  3663. + snd_allo_clk48gpio = devm_gpiod_get(dev, "clock48", GPIOD_OUT_LOW);
  3664. + if (IS_ERR(snd_allo_clk48gpio))
  3665. + dev_err(dev, "devm_gpiod_get() failed\n");
  3666. +
  3667. + return 0;
  3668. +}
  3669. +
  3670. +static void allo_cs43130_component_remove(struct i2c_client *i2c)
  3671. +{
  3672. + snd_soc_unregister_component(&i2c->dev);
  3673. +}
  3674. +
  3675. +static const struct i2c_device_id allo_cs43130_component_id[] = {
  3676. + { "allo-cs43198", },
  3677. + { }
  3678. +};
  3679. +MODULE_DEVICE_TABLE(i2c, allo_cs43130_component_id);
  3680. +
  3681. +static const struct of_device_id allo_cs43130_codec_of_match[] = {
  3682. + { .compatible = "allo,allo-cs43198", },
  3683. + { }
  3684. +};
  3685. +MODULE_DEVICE_TABLE(of, allo_cs43130_codec_of_match);
  3686. +
  3687. +static struct i2c_driver allo_cs43130_component_driver = {
  3688. + .probe = allo_cs43130_component_probe,
  3689. + .remove = allo_cs43130_component_remove,
  3690. + .id_table = allo_cs43130_component_id,
  3691. + .driver = {
  3692. + .name = "allo-cs43198",
  3693. + .of_match_table = allo_cs43130_codec_of_match,
  3694. + },
  3695. +};
  3696. +
  3697. +module_i2c_driver(allo_cs43130_component_driver);
  3698. +
  3699. +MODULE_DESCRIPTION("ASoC Allo Boss2 Codec Driver");
  3700. +MODULE_AUTHOR("Sudeepkumar <[email protected]>");
  3701. +MODULE_LICENSE("GPL v2");
  3702. --- /dev/null
  3703. +++ b/sound/soc/bcm/allo-katana-codec.c
  3704. @@ -0,0 +1,386 @@
  3705. +/*
  3706. + * Driver for the ALLO KATANA CODEC
  3707. + *
  3708. + * Author: Jaikumar <[email protected]>
  3709. + * Copyright 2018
  3710. + *
  3711. + * This program is free software; you can redistribute it and/or
  3712. + * modify it under the terms of the GNU General Public License
  3713. + * version 2 as published by the Free Software Foundation.
  3714. + *
  3715. + * This program is distributed in the hope that it will be useful, but
  3716. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  3717. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  3718. + * General Public License for more details.
  3719. + */
  3720. +
  3721. +
  3722. +#include <linux/init.h>
  3723. +#include <linux/module.h>
  3724. +#include <linux/clk.h>
  3725. +#include <linux/kernel.h>
  3726. +#include <linux/regmap.h>
  3727. +#include <linux/regulator/consumer.h>
  3728. +#include <linux/gcd.h>
  3729. +#include <sound/soc.h>
  3730. +#include <sound/soc-dapm.h>
  3731. +#include <sound/pcm_params.h>
  3732. +#include <sound/tlv.h>
  3733. +#include <linux/i2c.h>
  3734. +
  3735. +
  3736. +#define KATANA_CODEC_CHIP_ID 0x30
  3737. +#define KATANA_CODEC_VIRT_BASE 0x100
  3738. +#define KATANA_CODEC_PAGE 0
  3739. +
  3740. +#define KATANA_CODEC_CHIP_ID_REG (KATANA_CODEC_VIRT_BASE + 0)
  3741. +#define KATANA_CODEC_RESET (KATANA_CODEC_VIRT_BASE + 1)
  3742. +#define KATANA_CODEC_VOLUME_1 (KATANA_CODEC_VIRT_BASE + 2)
  3743. +#define KATANA_CODEC_VOLUME_2 (KATANA_CODEC_VIRT_BASE + 3)
  3744. +#define KATANA_CODEC_MUTE (KATANA_CODEC_VIRT_BASE + 4)
  3745. +#define KATANA_CODEC_DSP_PROGRAM (KATANA_CODEC_VIRT_BASE + 5)
  3746. +#define KATANA_CODEC_DEEMPHASIS (KATANA_CODEC_VIRT_BASE + 6)
  3747. +#define KATANA_CODEC_DOP (KATANA_CODEC_VIRT_BASE + 7)
  3748. +#define KATANA_CODEC_FORMAT (KATANA_CODEC_VIRT_BASE + 8)
  3749. +#define KATANA_CODEC_COMMAND (KATANA_CODEC_VIRT_BASE + 9)
  3750. +#define KATANA_CODEC_MUTE_STREAM (KATANA_CODEC_VIRT_BASE + 10)
  3751. +
  3752. +#define KATANA_CODEC_MAX_REGISTER (KATANA_CODEC_VIRT_BASE + 10)
  3753. +
  3754. +#define KATANA_CODEC_FMT 0xff
  3755. +#define KATANA_CODEC_CHAN_MONO 0x00
  3756. +#define KATANA_CODEC_CHAN_STEREO 0x80
  3757. +#define KATANA_CODEC_ALEN_16 0x10
  3758. +#define KATANA_CODEC_ALEN_24 0x20
  3759. +#define KATANA_CODEC_ALEN_32 0x30
  3760. +#define KATANA_CODEC_RATE_11025 0x01
  3761. +#define KATANA_CODEC_RATE_22050 0x02
  3762. +#define KATANA_CODEC_RATE_32000 0x03
  3763. +#define KATANA_CODEC_RATE_44100 0x04
  3764. +#define KATANA_CODEC_RATE_48000 0x05
  3765. +#define KATANA_CODEC_RATE_88200 0x06
  3766. +#define KATANA_CODEC_RATE_96000 0x07
  3767. +#define KATANA_CODEC_RATE_176400 0x08
  3768. +#define KATANA_CODEC_RATE_192000 0x09
  3769. +#define KATANA_CODEC_RATE_352800 0x0a
  3770. +#define KATANA_CODEC_RATE_384000 0x0b
  3771. +
  3772. +
  3773. +struct katana_codec_priv {
  3774. + struct regmap *regmap;
  3775. + int fmt;
  3776. +};
  3777. +
  3778. +static const struct reg_default katana_codec_reg_defaults[] = {
  3779. + { KATANA_CODEC_RESET, 0x00 },
  3780. + { KATANA_CODEC_VOLUME_1, 0xF0 },
  3781. + { KATANA_CODEC_VOLUME_2, 0xF0 },
  3782. + { KATANA_CODEC_MUTE, 0x00 },
  3783. + { KATANA_CODEC_DSP_PROGRAM, 0x04 },
  3784. + { KATANA_CODEC_DEEMPHASIS, 0x00 },
  3785. + { KATANA_CODEC_DOP, 0x00 },
  3786. + { KATANA_CODEC_FORMAT, 0xb4 },
  3787. +};
  3788. +
  3789. +static const char * const katana_codec_dsp_program_texts[] = {
  3790. + "Linear Phase Fast Roll-off Filter",
  3791. + "Linear Phase Slow Roll-off Filter",
  3792. + "Minimum Phase Fast Roll-off Filter",
  3793. + "Minimum Phase Slow Roll-off Filter",
  3794. + "Apodizing Fast Roll-off Filter",
  3795. + "Corrected Minimum Phase Fast Roll-off Filter",
  3796. + "Brick Wall Filter",
  3797. +};
  3798. +
  3799. +static const unsigned int katana_codec_dsp_program_values[] = {
  3800. + 0,
  3801. + 1,
  3802. + 2,
  3803. + 3,
  3804. + 4,
  3805. + 6,
  3806. + 7,
  3807. +};
  3808. +
  3809. +static SOC_VALUE_ENUM_SINGLE_DECL(katana_codec_dsp_program,
  3810. + KATANA_CODEC_DSP_PROGRAM, 0, 0x07,
  3811. + katana_codec_dsp_program_texts,
  3812. + katana_codec_dsp_program_values);
  3813. +
  3814. +static const char * const katana_codec_deemphasis_texts[] = {
  3815. + "Bypass",
  3816. + "32kHz",
  3817. + "44.1kHz",
  3818. + "48kHz",
  3819. +};
  3820. +
  3821. +static const unsigned int katana_codec_deemphasis_values[] = {
  3822. + 0,
  3823. + 1,
  3824. + 2,
  3825. + 3,
  3826. +};
  3827. +
  3828. +static SOC_VALUE_ENUM_SINGLE_DECL(katana_codec_deemphasis,
  3829. + KATANA_CODEC_DEEMPHASIS, 0, 0x03,
  3830. + katana_codec_deemphasis_texts,
  3831. + katana_codec_deemphasis_values);
  3832. +
  3833. +static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(master_tlv, -12750, 0);
  3834. +
  3835. +static const struct snd_kcontrol_new katana_codec_controls[] = {
  3836. + SOC_DOUBLE_R_TLV("Master Playback Volume", KATANA_CODEC_VOLUME_1,
  3837. + KATANA_CODEC_VOLUME_2, 0, 255, 1, master_tlv),
  3838. + SOC_DOUBLE("Master Playback Switch", KATANA_CODEC_MUTE, 0, 0, 1, 1),
  3839. + SOC_ENUM("DSP Program Route", katana_codec_dsp_program),
  3840. + SOC_ENUM("Deemphasis Route", katana_codec_deemphasis),
  3841. + SOC_SINGLE("DoP Playback Switch", KATANA_CODEC_DOP, 0, 1, 1)
  3842. +};
  3843. +
  3844. +static bool katana_codec_readable_register(struct device *dev,
  3845. + unsigned int reg)
  3846. +{
  3847. + switch (reg) {
  3848. + case KATANA_CODEC_CHIP_ID_REG:
  3849. + return true;
  3850. + default:
  3851. + return reg < 0xff;
  3852. + }
  3853. +}
  3854. +
  3855. +static int katana_codec_hw_params(struct snd_pcm_substream *substream,
  3856. + struct snd_pcm_hw_params *params,
  3857. + struct snd_soc_dai *dai)
  3858. +{
  3859. + struct snd_soc_component *component = dai->component;
  3860. + struct katana_codec_priv *katana_codec =
  3861. + snd_soc_component_get_drvdata(component);
  3862. + int fmt = 0;
  3863. + int ret;
  3864. +
  3865. + dev_dbg(component->card->dev, "hw_params %u Hz, %u channels, %u bits\n",
  3866. + params_rate(params),
  3867. + params_channels(params),
  3868. + params_width(params));
  3869. +
  3870. + switch (katana_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  3871. + case SND_SOC_DAIFMT_CBM_CFM: // master
  3872. + if (params_channels(params) == 2)
  3873. + fmt = KATANA_CODEC_CHAN_STEREO;
  3874. + else
  3875. + fmt = KATANA_CODEC_CHAN_MONO;
  3876. +
  3877. + switch (params_width(params)) {
  3878. + case 16:
  3879. + fmt |= KATANA_CODEC_ALEN_16;
  3880. + break;
  3881. + case 24:
  3882. + fmt |= KATANA_CODEC_ALEN_24;
  3883. + break;
  3884. + case 32:
  3885. + fmt |= KATANA_CODEC_ALEN_32;
  3886. + break;
  3887. + default:
  3888. + dev_err(component->card->dev, "Bad frame size: %d\n",
  3889. + params_width(params));
  3890. + return -EINVAL;
  3891. + }
  3892. +
  3893. + switch (params_rate(params)) {
  3894. + case 44100:
  3895. + fmt |= KATANA_CODEC_RATE_44100;
  3896. + break;
  3897. + case 48000:
  3898. + fmt |= KATANA_CODEC_RATE_48000;
  3899. + break;
  3900. + case 88200:
  3901. + fmt |= KATANA_CODEC_RATE_88200;
  3902. + break;
  3903. + case 96000:
  3904. + fmt |= KATANA_CODEC_RATE_96000;
  3905. + break;
  3906. + case 176400:
  3907. + fmt |= KATANA_CODEC_RATE_176400;
  3908. + break;
  3909. + case 192000:
  3910. + fmt |= KATANA_CODEC_RATE_192000;
  3911. + break;
  3912. + case 352800:
  3913. + fmt |= KATANA_CODEC_RATE_352800;
  3914. + break;
  3915. + case 384000:
  3916. + fmt |= KATANA_CODEC_RATE_384000;
  3917. + break;
  3918. + default:
  3919. + dev_err(component->card->dev, "Bad sample rate: %d\n",
  3920. + params_rate(params));
  3921. + return -EINVAL;
  3922. + }
  3923. +
  3924. + ret = regmap_write(katana_codec->regmap, KATANA_CODEC_FORMAT,
  3925. + fmt);
  3926. + if (ret != 0) {
  3927. + dev_err(component->card->dev, "Failed to set format: %d\n", ret);
  3928. + return ret;
  3929. + }
  3930. + break;
  3931. +
  3932. + case SND_SOC_DAIFMT_CBS_CFS:
  3933. + break;
  3934. +
  3935. + default:
  3936. + return -EINVAL;
  3937. + }
  3938. +
  3939. + return 0;
  3940. +}
  3941. +
  3942. +static int katana_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  3943. +{
  3944. + struct snd_soc_component *component = dai->component;
  3945. + struct katana_codec_priv *katana_codec =
  3946. + snd_soc_component_get_drvdata(component);
  3947. +
  3948. + katana_codec->fmt = fmt;
  3949. +
  3950. + return 0;
  3951. +}
  3952. +
  3953. +int katana_codec_dai_mute_stream(struct snd_soc_dai *dai, int mute,
  3954. + int stream)
  3955. +{
  3956. + struct snd_soc_component *component = dai->component;
  3957. + struct katana_codec_priv *katana_codec =
  3958. + snd_soc_component_get_drvdata(component);
  3959. + int ret = 0;
  3960. +
  3961. + ret = regmap_write(katana_codec->regmap, KATANA_CODEC_MUTE_STREAM,
  3962. + mute);
  3963. + if (ret != 0) {
  3964. + dev_err(component->card->dev, "Failed to set mute: %d\n", ret);
  3965. + return ret;
  3966. + }
  3967. + return ret;
  3968. +}
  3969. +
  3970. +static const struct snd_soc_dai_ops katana_codec_dai_ops = {
  3971. + .mute_stream = katana_codec_dai_mute_stream,
  3972. + .hw_params = katana_codec_hw_params,
  3973. + .set_fmt = katana_codec_set_fmt,
  3974. +};
  3975. +
  3976. +static struct snd_soc_dai_driver katana_codec_dai = {
  3977. + .name = "allo-katana-codec",
  3978. + .playback = {
  3979. + .stream_name = "Playback",
  3980. + .channels_min = 2,
  3981. + .channels_max = 2,
  3982. + .rates = SNDRV_PCM_RATE_CONTINUOUS,
  3983. + .rate_min = 44100,
  3984. + .rate_max = 384000,
  3985. + .formats = SNDRV_PCM_FMTBIT_S16_LE |
  3986. + SNDRV_PCM_FMTBIT_S32_LE
  3987. + },
  3988. + .ops = &katana_codec_dai_ops,
  3989. +};
  3990. +
  3991. +static struct snd_soc_component_driver katana_codec_component_driver = {
  3992. + .idle_bias_on = true,
  3993. +
  3994. + .controls = katana_codec_controls,
  3995. + .num_controls = ARRAY_SIZE(katana_codec_controls),
  3996. +};
  3997. +
  3998. +static const struct regmap_range_cfg katana_codec_range = {
  3999. + .name = "Pages", .range_min = KATANA_CODEC_VIRT_BASE,
  4000. + .range_max = KATANA_CODEC_MAX_REGISTER,
  4001. + .selector_reg = KATANA_CODEC_PAGE,
  4002. + .selector_mask = 0xff,
  4003. + .window_start = 0, .window_len = 0x100,
  4004. +};
  4005. +
  4006. +const struct regmap_config katana_codec_regmap = {
  4007. + .reg_bits = 8,
  4008. + .val_bits = 8,
  4009. +
  4010. + .ranges = &katana_codec_range,
  4011. + .num_ranges = 1,
  4012. +
  4013. + .max_register = KATANA_CODEC_MAX_REGISTER,
  4014. + .readable_reg = katana_codec_readable_register,
  4015. + .reg_defaults = katana_codec_reg_defaults,
  4016. + .num_reg_defaults = ARRAY_SIZE(katana_codec_reg_defaults),
  4017. + .cache_type = REGCACHE_RBTREE,
  4018. +};
  4019. +
  4020. +static int allo_katana_component_probe(struct i2c_client *i2c)
  4021. +{
  4022. + struct regmap *regmap;
  4023. + struct regmap_config config = katana_codec_regmap;
  4024. + struct device *dev = &i2c->dev;
  4025. + struct katana_codec_priv *katana_codec;
  4026. + unsigned int chip_id = 0;
  4027. + int ret;
  4028. +
  4029. + regmap = devm_regmap_init_i2c(i2c, &config);
  4030. + if (IS_ERR(regmap))
  4031. + return PTR_ERR(regmap);
  4032. +
  4033. + katana_codec = devm_kzalloc(dev, sizeof(struct katana_codec_priv),
  4034. + GFP_KERNEL);
  4035. + if (!katana_codec)
  4036. + return -ENOMEM;
  4037. +
  4038. + dev_set_drvdata(dev, katana_codec);
  4039. + katana_codec->regmap = regmap;
  4040. +
  4041. + ret = regmap_read(regmap, KATANA_CODEC_CHIP_ID_REG, &chip_id);
  4042. + if ((ret != 0) || (chip_id != KATANA_CODEC_CHIP_ID)) {
  4043. + dev_err(dev, "Failed to read Chip or wrong Chip id: %d\n", ret);
  4044. + return ret;
  4045. + }
  4046. + regmap_update_bits(regmap, KATANA_CODEC_RESET, 0x01, 0x01);
  4047. + msleep(10);
  4048. +
  4049. + ret = snd_soc_register_component(dev, &katana_codec_component_driver,
  4050. + &katana_codec_dai, 1);
  4051. + if (ret != 0) {
  4052. + dev_err(dev, "failed to register codec: %d\n", ret);
  4053. + return ret;
  4054. + }
  4055. +
  4056. + return 0;
  4057. +}
  4058. +
  4059. +static void allo_katana_component_remove(struct i2c_client *i2c)
  4060. +{
  4061. + snd_soc_unregister_component(&i2c->dev);
  4062. +}
  4063. +
  4064. +static const struct i2c_device_id allo_katana_component_id[] = {
  4065. + { "allo-katana-codec", },
  4066. + { }
  4067. +};
  4068. +MODULE_DEVICE_TABLE(i2c, allo_katana_component_id);
  4069. +
  4070. +static const struct of_device_id allo_katana_codec_of_match[] = {
  4071. + { .compatible = "allo,allo-katana-codec", },
  4072. + { }
  4073. +};
  4074. +MODULE_DEVICE_TABLE(of, allo_katana_codec_of_match);
  4075. +
  4076. +static struct i2c_driver allo_katana_component_driver = {
  4077. + .probe = allo_katana_component_probe,
  4078. + .remove = allo_katana_component_remove,
  4079. + .id_table = allo_katana_component_id,
  4080. + .driver = {
  4081. + .name = "allo-katana-codec",
  4082. + .of_match_table = allo_katana_codec_of_match,
  4083. + },
  4084. +};
  4085. +
  4086. +module_i2c_driver(allo_katana_component_driver);
  4087. +
  4088. +MODULE_DESCRIPTION("ASoC Allo Katana Codec Driver");
  4089. +MODULE_AUTHOR("Jaikumar <[email protected]>");
  4090. +MODULE_LICENSE("GPL v2");
  4091. --- /dev/null
  4092. +++ b/sound/soc/bcm/allo-piano-dac-plus.c
  4093. @@ -0,0 +1,1064 @@
  4094. +/*
  4095. + * ALSA ASoC Machine Driver for Allo Piano DAC Plus Subwoofer
  4096. + *
  4097. + * Author: Baswaraj K <[email protected]>
  4098. + * Copyright 2020
  4099. + * based on code by David Knell <[email protected])
  4100. + * based on code by Daniel Matuschek <[email protected]>
  4101. + * based on code by Florian Meier <[email protected]>
  4102. + *
  4103. + * This program is free software; you can redistribute it and/or
  4104. + * modify it under the terms of the GNU General Public License
  4105. + * version 2 as published by the Free Software Foundation.
  4106. + *
  4107. + * This program is distributed in the hope that it will be useful, but
  4108. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  4109. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  4110. + * General Public License for more details.
  4111. + */
  4112. +
  4113. +#include <linux/module.h>
  4114. +#include <linux/platform_device.h>
  4115. +#include <linux/gpio/consumer.h>
  4116. +#include <sound/core.h>
  4117. +#include <sound/pcm.h>
  4118. +#include <sound/pcm_params.h>
  4119. +#include <sound/soc.h>
  4120. +#include <linux/firmware.h>
  4121. +#include <linux/delay.h>
  4122. +#include <sound/tlv.h>
  4123. +#include "../codecs/pcm512x.h"
  4124. +
  4125. +#define P_DAC_LEFT_MUTE 0x10
  4126. +#define P_DAC_RIGHT_MUTE 0x01
  4127. +#define P_DAC_MUTE 0x11
  4128. +#define P_DAC_UNMUTE 0x00
  4129. +#define P_MUTE 1
  4130. +#define P_UNMUTE 0
  4131. +
  4132. +struct dsp_code {
  4133. + char i2c_addr;
  4134. + char offset;
  4135. + char val;
  4136. +};
  4137. +
  4138. +struct glb_pool {
  4139. + struct mutex lock;
  4140. + unsigned int dual_mode;
  4141. + unsigned int set_lowpass;
  4142. + unsigned int set_mode;
  4143. + unsigned int set_rate;
  4144. + unsigned int dsp_page_number;
  4145. +};
  4146. +
  4147. +static bool digital_gain_0db_limit = true;
  4148. +bool glb_mclk;
  4149. +
  4150. +static struct gpio_desc *mute_gpio[2];
  4151. +
  4152. +static const char * const allo_piano_mode_texts[] = {
  4153. + "None",
  4154. + "2.0",
  4155. + "2.1",
  4156. + "2.2",
  4157. +};
  4158. +
  4159. +static SOC_ENUM_SINGLE_DECL(allo_piano_mode_enum,
  4160. + 0, 0, allo_piano_mode_texts);
  4161. +
  4162. +static const char * const allo_piano_dual_mode_texts[] = {
  4163. + "None",
  4164. + "Dual-Mono",
  4165. + "Dual-Stereo",
  4166. +};
  4167. +
  4168. +static SOC_ENUM_SINGLE_DECL(allo_piano_dual_mode_enum,
  4169. + 0, 0, allo_piano_dual_mode_texts);
  4170. +
  4171. +static const char * const allo_piano_dsp_low_pass_texts[] = {
  4172. + "60",
  4173. + "70",
  4174. + "80",
  4175. + "90",
  4176. + "100",
  4177. + "110",
  4178. + "120",
  4179. + "130",
  4180. + "140",
  4181. + "150",
  4182. + "160",
  4183. + "170",
  4184. + "180",
  4185. + "190",
  4186. + "200",
  4187. +};
  4188. +
  4189. +static SOC_ENUM_SINGLE_DECL(allo_piano_enum,
  4190. + 0, 0, allo_piano_dsp_low_pass_texts);
  4191. +
  4192. +static int __snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
  4193. + unsigned int mode, unsigned int rate, unsigned int lowpass)
  4194. +{
  4195. + const struct firmware *fw;
  4196. + struct snd_soc_card *card = rtd->card;
  4197. + struct glb_pool *glb_ptr = card->drvdata;
  4198. + char firmware_name[60];
  4199. + int ret = 0, dac = 0;
  4200. +
  4201. + if (rate <= 46000)
  4202. + rate = 44100;
  4203. + else if (rate <= 68000)
  4204. + rate = 48000;
  4205. + else if (rate <= 92000)
  4206. + rate = 88200;
  4207. + else if (rate <= 136000)
  4208. + rate = 96000;
  4209. + else if (rate <= 184000)
  4210. + rate = 176400;
  4211. + else
  4212. + rate = 192000;
  4213. +
  4214. + if (lowpass > 14)
  4215. + glb_ptr->set_lowpass = lowpass = 0;
  4216. +
  4217. + if (mode > 3)
  4218. + glb_ptr->set_mode = mode = 0;
  4219. +
  4220. + if (mode > 0)
  4221. + glb_ptr->dual_mode = 0;
  4222. +
  4223. + /* same configuration loaded */
  4224. + if ((rate == glb_ptr->set_rate) && (lowpass == glb_ptr->set_lowpass)
  4225. + && (mode == glb_ptr->set_mode))
  4226. + return 0;
  4227. +
  4228. + switch (mode) {
  4229. + case 0: /* None */
  4230. + return 1;
  4231. +
  4232. + case 1: /* 2.0 */
  4233. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
  4234. + PCM512x_MUTE, P_DAC_UNMUTE);
  4235. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
  4236. + PCM512x_MUTE, P_DAC_MUTE);
  4237. + glb_ptr->set_rate = rate;
  4238. + glb_ptr->set_mode = mode;
  4239. + glb_ptr->set_lowpass = lowpass;
  4240. + return 1;
  4241. +
  4242. + default:
  4243. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
  4244. + PCM512x_MUTE, P_DAC_UNMUTE);
  4245. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
  4246. + PCM512x_MUTE, P_DAC_UNMUTE);
  4247. + }
  4248. +
  4249. + for (dac = 0; dac < rtd->dai_link->num_codecs; dac++) {
  4250. + struct dsp_code *dsp_code_read;
  4251. + int i = 1;
  4252. +
  4253. + if (dac == 0) { /* high */
  4254. + snprintf(firmware_name, sizeof(firmware_name),
  4255. + "allo/piano/2.2/allo-piano-dsp-%d-%d-%d.bin",
  4256. + rate, ((lowpass * 10) + 60), dac);
  4257. + } else { /* low */
  4258. + snprintf(firmware_name, sizeof(firmware_name),
  4259. + "allo/piano/2.%d/allo-piano-dsp-%d-%d-%d.bin",
  4260. + (mode - 1), rate, ((lowpass * 10) + 60), dac);
  4261. + }
  4262. +
  4263. + dev_info(rtd->card->dev, "Dsp Firmware File Name: %s\n",
  4264. + firmware_name);
  4265. +
  4266. + ret = request_firmware(&fw, firmware_name, rtd->card->dev);
  4267. + if (ret < 0) {
  4268. + dev_err(rtd->card->dev,
  4269. + "Error: Allo Piano Firmware %s missing. %d\n",
  4270. + firmware_name, ret);
  4271. + goto err;
  4272. + }
  4273. +
  4274. + while (i < (fw->size - 1)) {
  4275. + dsp_code_read = (struct dsp_code *)&fw->data[i];
  4276. +
  4277. + if (dsp_code_read->offset == 0) {
  4278. + glb_ptr->dsp_page_number = dsp_code_read->val;
  4279. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, dac)->component,
  4280. + PCM512x_PAGE_BASE(0),
  4281. + dsp_code_read->val);
  4282. +
  4283. + } else if (dsp_code_read->offset != 0) {
  4284. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, dac)->component,
  4285. + (PCM512x_PAGE_BASE(
  4286. + glb_ptr->dsp_page_number) +
  4287. + dsp_code_read->offset),
  4288. + dsp_code_read->val);
  4289. + }
  4290. + if (ret < 0) {
  4291. + dev_err(rtd->card->dev,
  4292. + "Failed to write Register: %d\n", ret);
  4293. + release_firmware(fw);
  4294. + goto err;
  4295. + }
  4296. + i = i + 3;
  4297. + }
  4298. + release_firmware(fw);
  4299. + }
  4300. + glb_ptr->set_rate = rate;
  4301. + glb_ptr->set_mode = mode;
  4302. + glb_ptr->set_lowpass = lowpass;
  4303. + return 1;
  4304. +
  4305. +err:
  4306. + return ret;
  4307. +}
  4308. +
  4309. +static int snd_allo_piano_dsp_program(struct snd_soc_pcm_runtime *rtd,
  4310. + unsigned int mode, unsigned int rate, unsigned int lowpass)
  4311. +{
  4312. + struct snd_soc_card *card = rtd->card;
  4313. + struct glb_pool *glb_ptr = card->drvdata;
  4314. + int ret = 0;
  4315. +
  4316. + mutex_lock(&glb_ptr->lock);
  4317. +
  4318. + ret = __snd_allo_piano_dsp_program(rtd, mode, rate, lowpass);
  4319. +
  4320. + mutex_unlock(&glb_ptr->lock);
  4321. +
  4322. + return ret;
  4323. +}
  4324. +
  4325. +static int snd_allo_piano_dual_mode_get(struct snd_kcontrol *kcontrol,
  4326. + struct snd_ctl_elem_value *ucontrol)
  4327. +{
  4328. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4329. + struct glb_pool *glb_ptr = card->drvdata;
  4330. +
  4331. + ucontrol->value.integer.value[0] = glb_ptr->dual_mode;
  4332. +
  4333. + return 0;
  4334. +}
  4335. +
  4336. +static int snd_allo_piano_dual_mode_put(struct snd_kcontrol *kcontrol,
  4337. + struct snd_ctl_elem_value *ucontrol)
  4338. +{
  4339. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4340. + struct glb_pool *glb_ptr = card->drvdata;
  4341. + struct snd_soc_pcm_runtime *rtd;
  4342. + struct snd_card *snd_card_ptr = card->snd_card;
  4343. + struct snd_kcontrol *kctl;
  4344. + struct soc_mixer_control *mc;
  4345. + unsigned int left_val = 0, right_val = 0;
  4346. +
  4347. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4348. +
  4349. + if (ucontrol->value.integer.value[0] > 0) {
  4350. + glb_ptr->dual_mode = ucontrol->value.integer.value[0];
  4351. + glb_ptr->set_mode = 0;
  4352. + } else {
  4353. + if (glb_ptr->set_mode <= 0) {
  4354. + glb_ptr->dual_mode = 1;
  4355. + glb_ptr->set_mode = 0;
  4356. + } else {
  4357. + glb_ptr->dual_mode = 0;
  4358. + return 0;
  4359. + }
  4360. + }
  4361. +
  4362. + if (glb_ptr->dual_mode == 1) { // Dual Mono
  4363. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
  4364. + PCM512x_MUTE, P_DAC_RIGHT_MUTE);
  4365. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
  4366. + PCM512x_MUTE, P_DAC_LEFT_MUTE);
  4367. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
  4368. + PCM512x_DIGITAL_VOLUME_3, 0xff);
  4369. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
  4370. + PCM512x_DIGITAL_VOLUME_2, 0xff);
  4371. +
  4372. + list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
  4373. + if (!strncmp(kctl->id.name, "Main Digital Playback Volume",
  4374. + sizeof(kctl->id.name))) {
  4375. + mc = (struct soc_mixer_control *)
  4376. + kctl->private_value;
  4377. + mc->rreg = mc->reg;
  4378. + break;
  4379. + }
  4380. + if (!strncmp(kctl->id.name, "Sub Digital Playback Volume",
  4381. + sizeof(kctl->id.name))) {
  4382. + mc = (struct soc_mixer_control *)
  4383. + kctl->private_value;
  4384. + mc->rreg = mc->reg;
  4385. + break;
  4386. + }
  4387. + }
  4388. + } else {
  4389. + left_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 0)->component,
  4390. + PCM512x_DIGITAL_VOLUME_2);
  4391. + right_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component,
  4392. + PCM512x_DIGITAL_VOLUME_3);
  4393. +
  4394. + list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
  4395. + if (!strncmp(kctl->id.name, "Main Digital Playback Volume",
  4396. + sizeof(kctl->id.name))) {
  4397. + mc = (struct soc_mixer_control *)
  4398. + kctl->private_value;
  4399. + mc->rreg = PCM512x_DIGITAL_VOLUME_3;
  4400. + break;
  4401. + }
  4402. + if (!strncmp(kctl->id.name, "Sub Digital Playback Volume",
  4403. + sizeof(kctl->id.name))) {
  4404. + mc = (struct soc_mixer_control *)
  4405. + kctl->private_value;
  4406. + mc->rreg = PCM512x_DIGITAL_VOLUME_2;
  4407. + break;
  4408. + }
  4409. + }
  4410. +
  4411. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
  4412. + PCM512x_DIGITAL_VOLUME_3, left_val);
  4413. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
  4414. + PCM512x_DIGITAL_VOLUME_2, right_val);
  4415. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
  4416. + PCM512x_MUTE, P_DAC_UNMUTE);
  4417. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
  4418. + PCM512x_MUTE, P_DAC_UNMUTE);
  4419. + }
  4420. +
  4421. + return 0;
  4422. +}
  4423. +
  4424. +static int snd_allo_piano_mode_get(struct snd_kcontrol *kcontrol,
  4425. + struct snd_ctl_elem_value *ucontrol)
  4426. +{
  4427. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4428. + struct glb_pool *glb_ptr = card->drvdata;
  4429. +
  4430. + ucontrol->value.integer.value[0] = glb_ptr->set_mode;
  4431. + return 0;
  4432. +}
  4433. +
  4434. +static int snd_allo_piano_mode_put(struct snd_kcontrol *kcontrol,
  4435. + struct snd_ctl_elem_value *ucontrol)
  4436. +{
  4437. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4438. + struct snd_soc_pcm_runtime *rtd;
  4439. + struct glb_pool *glb_ptr = card->drvdata;
  4440. + struct snd_card *snd_card_ptr = card->snd_card;
  4441. + struct snd_kcontrol *kctl;
  4442. + struct soc_mixer_control *mc;
  4443. + unsigned int left_val = 0, right_val = 0;
  4444. +
  4445. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4446. +
  4447. + if ((glb_ptr->dual_mode == 1) &&
  4448. + (ucontrol->value.integer.value[0] > 0)) {
  4449. + left_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 0)->component,
  4450. + PCM512x_DIGITAL_VOLUME_2);
  4451. + right_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component,
  4452. + PCM512x_DIGITAL_VOLUME_2);
  4453. +
  4454. + list_for_each_entry(kctl, &snd_card_ptr->controls, list) {
  4455. + if (!strncmp(kctl->id.name, "Main Digital Playback Volume",
  4456. + sizeof(kctl->id.name))) {
  4457. + mc = (struct soc_mixer_control *)
  4458. + kctl->private_value;
  4459. + mc->rreg = PCM512x_DIGITAL_VOLUME_3;
  4460. + break;
  4461. + }
  4462. + if (!strncmp(kctl->id.name, "Sub Digital Playback Volume",
  4463. + sizeof(kctl->id.name))) {
  4464. + mc = (struct soc_mixer_control *)
  4465. + kctl->private_value;
  4466. + mc->rreg = PCM512x_DIGITAL_VOLUME_2;
  4467. + break;
  4468. + }
  4469. + }
  4470. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
  4471. + PCM512x_DIGITAL_VOLUME_3, left_val);
  4472. + snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
  4473. + PCM512x_DIGITAL_VOLUME_3, right_val);
  4474. + }
  4475. +
  4476. + return(snd_allo_piano_dsp_program(rtd,
  4477. + ucontrol->value.integer.value[0],
  4478. + glb_ptr->set_rate, glb_ptr->set_lowpass));
  4479. +}
  4480. +
  4481. +static int snd_allo_piano_lowpass_get(struct snd_kcontrol *kcontrol,
  4482. + struct snd_ctl_elem_value *ucontrol)
  4483. +{
  4484. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4485. + struct glb_pool *glb_ptr = card->drvdata;
  4486. +
  4487. + ucontrol->value.integer.value[0] = glb_ptr->set_lowpass;
  4488. + return 0;
  4489. +}
  4490. +
  4491. +static int snd_allo_piano_lowpass_put(struct snd_kcontrol *kcontrol,
  4492. + struct snd_ctl_elem_value *ucontrol)
  4493. +{
  4494. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4495. + struct snd_soc_pcm_runtime *rtd;
  4496. + struct glb_pool *glb_ptr = card->drvdata;
  4497. +
  4498. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4499. + return(snd_allo_piano_dsp_program(rtd,
  4500. + glb_ptr->set_mode, glb_ptr->set_rate,
  4501. + ucontrol->value.integer.value[0]));
  4502. +}
  4503. +
  4504. +static int pcm512x_get_reg_sub(struct snd_kcontrol *kcontrol,
  4505. + struct snd_ctl_elem_value *ucontrol)
  4506. +{
  4507. + struct soc_mixer_control *mc =
  4508. + (struct soc_mixer_control *)kcontrol->private_value;
  4509. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4510. + struct glb_pool *glb_ptr = card->drvdata;
  4511. + struct snd_soc_pcm_runtime *rtd;
  4512. + unsigned int left_val = 0;
  4513. + unsigned int right_val = 0;
  4514. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4515. +
  4516. + right_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component,
  4517. + PCM512x_DIGITAL_VOLUME_3);
  4518. + if (glb_ptr->dual_mode != 1) {
  4519. + left_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component,
  4520. + PCM512x_DIGITAL_VOLUME_2);
  4521. +
  4522. + } else {
  4523. + left_val = right_val;
  4524. + }
  4525. +
  4526. + ucontrol->value.integer.value[0] =
  4527. + (~(left_val >> mc->shift)) & mc->max;
  4528. + ucontrol->value.integer.value[1] =
  4529. + (~(right_val >> mc->shift)) & mc->max;
  4530. +
  4531. + return 0;
  4532. +}
  4533. +
  4534. +static int pcm512x_set_reg_sub(struct snd_kcontrol *kcontrol,
  4535. + struct snd_ctl_elem_value *ucontrol)
  4536. +{
  4537. + struct soc_mixer_control *mc =
  4538. + (struct soc_mixer_control *)kcontrol->private_value;
  4539. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4540. + struct glb_pool *glb_ptr = card->drvdata;
  4541. + struct snd_soc_pcm_runtime *rtd;
  4542. + unsigned int left_val = (ucontrol->value.integer.value[0] & mc->max);
  4543. + unsigned int right_val = (ucontrol->value.integer.value[1] & mc->max);
  4544. + int ret = 0;
  4545. +
  4546. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4547. +
  4548. + if (digital_gain_0db_limit) {
  4549. + ret = snd_soc_limit_volume(card, "Subwoofer Playback Volume",
  4550. + 207);
  4551. + if (ret < 0)
  4552. + dev_warn(card->dev, "Failed to set volume limit: %d\n",
  4553. + ret);
  4554. + }
  4555. +
  4556. + // When in Dual Mono, Sub vol control should not set anything.
  4557. + if (glb_ptr->dual_mode != 1) { //Not in Dual Mono mode
  4558. +
  4559. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
  4560. + PCM512x_DIGITAL_VOLUME_2, (~left_val));
  4561. + if (ret < 0)
  4562. + return ret;
  4563. +
  4564. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
  4565. + PCM512x_DIGITAL_VOLUME_3, (~right_val));
  4566. + if (ret < 0)
  4567. + return ret;
  4568. +
  4569. + }
  4570. +
  4571. + return 1;
  4572. +}
  4573. +
  4574. +static int pcm512x_get_reg_sub_switch(struct snd_kcontrol *kcontrol,
  4575. + struct snd_ctl_elem_value *ucontrol)
  4576. +{
  4577. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4578. + struct snd_soc_pcm_runtime *rtd;
  4579. + int val = 0;
  4580. +
  4581. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4582. + val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component, PCM512x_MUTE);
  4583. +
  4584. + ucontrol->value.integer.value[0] =
  4585. + (val & P_DAC_LEFT_MUTE) ? P_UNMUTE : P_MUTE;
  4586. + ucontrol->value.integer.value[1] =
  4587. + (val & P_DAC_RIGHT_MUTE) ? P_UNMUTE : P_MUTE;
  4588. +
  4589. + return val;
  4590. +}
  4591. +
  4592. +static int pcm512x_set_reg_sub_switch(struct snd_kcontrol *kcontrol,
  4593. + struct snd_ctl_elem_value *ucontrol)
  4594. +{
  4595. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4596. + struct snd_soc_pcm_runtime *rtd;
  4597. + struct glb_pool *glb_ptr = card->drvdata;
  4598. + unsigned int left_val = (ucontrol->value.integer.value[0]);
  4599. + unsigned int right_val = (ucontrol->value.integer.value[1]);
  4600. + int ret = 0;
  4601. +
  4602. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4603. + if (glb_ptr->set_mode != 1) {
  4604. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component, PCM512x_MUTE,
  4605. + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
  4606. + if (ret < 0)
  4607. + return ret;
  4608. + }
  4609. + return 1;
  4610. +
  4611. +}
  4612. +
  4613. +static int pcm512x_get_reg_master(struct snd_kcontrol *kcontrol,
  4614. + struct snd_ctl_elem_value *ucontrol)
  4615. +{
  4616. + struct soc_mixer_control *mc =
  4617. + (struct soc_mixer_control *)kcontrol->private_value;
  4618. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4619. + struct glb_pool *glb_ptr = card->drvdata;
  4620. + struct snd_soc_pcm_runtime *rtd;
  4621. + unsigned int left_val = 0, right_val = 0;
  4622. +
  4623. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4624. +
  4625. + left_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 0)->component,
  4626. + PCM512x_DIGITAL_VOLUME_2);
  4627. +
  4628. + if (glb_ptr->dual_mode == 1) { // in Dual Mono mode
  4629. + right_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component,
  4630. + PCM512x_DIGITAL_VOLUME_3);
  4631. + } else {
  4632. + right_val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 0)->component,
  4633. + PCM512x_DIGITAL_VOLUME_3);
  4634. + }
  4635. +
  4636. + ucontrol->value.integer.value[0] =
  4637. + (~(left_val >> mc->shift)) & mc->max;
  4638. + ucontrol->value.integer.value[1] =
  4639. + (~(right_val >> mc->shift)) & mc->max;
  4640. +
  4641. + return 0;
  4642. +}
  4643. +
  4644. +static int pcm512x_set_reg_master(struct snd_kcontrol *kcontrol,
  4645. + struct snd_ctl_elem_value *ucontrol)
  4646. +{
  4647. + struct soc_mixer_control *mc =
  4648. + (struct soc_mixer_control *)kcontrol->private_value;
  4649. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4650. + struct glb_pool *glb_ptr = card->drvdata;
  4651. + struct snd_soc_pcm_runtime *rtd;
  4652. + unsigned int left_val = (ucontrol->value.integer.value[0] & mc->max);
  4653. + unsigned int right_val = (ucontrol->value.integer.value[1] & mc->max);
  4654. + int ret = 0;
  4655. +
  4656. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4657. +
  4658. + if (digital_gain_0db_limit) {
  4659. + ret = snd_soc_limit_volume(card, "Master Playback Volume",
  4660. + 207);
  4661. + if (ret < 0)
  4662. + dev_warn(card->dev, "Failed to set volume limit: %d\n",
  4663. + ret);
  4664. + }
  4665. +
  4666. + if (glb_ptr->dual_mode == 1) { //in Dual Mono Mode
  4667. +
  4668. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
  4669. + PCM512x_DIGITAL_VOLUME_2, (~left_val));
  4670. + if (ret < 0)
  4671. + return ret;
  4672. +
  4673. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component,
  4674. + PCM512x_DIGITAL_VOLUME_3, (~right_val));
  4675. + if (ret < 0)
  4676. + return ret;
  4677. +
  4678. + } else {
  4679. +
  4680. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
  4681. + PCM512x_DIGITAL_VOLUME_2, (~left_val));
  4682. + if (ret < 0)
  4683. + return ret;
  4684. +
  4685. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component,
  4686. + PCM512x_DIGITAL_VOLUME_3, (~right_val));
  4687. + if (ret < 0)
  4688. + return ret;
  4689. +
  4690. + }
  4691. + return 1;
  4692. +}
  4693. +
  4694. +static int pcm512x_get_reg_master_switch(struct snd_kcontrol *kcontrol,
  4695. + struct snd_ctl_elem_value *ucontrol)
  4696. +{
  4697. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4698. + struct glb_pool *glb_ptr = card->drvdata;
  4699. + struct snd_soc_pcm_runtime *rtd;
  4700. + int val = 0;
  4701. +
  4702. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4703. +
  4704. + val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 0)->component, PCM512x_MUTE);
  4705. +
  4706. + ucontrol->value.integer.value[0] =
  4707. + (val & P_DAC_LEFT_MUTE) ? P_UNMUTE : P_MUTE;
  4708. +
  4709. + if (glb_ptr->dual_mode == 1) {
  4710. + val = snd_soc_component_read(asoc_rtd_to_codec(rtd, 1)->component, PCM512x_MUTE);
  4711. + }
  4712. + ucontrol->value.integer.value[1] =
  4713. + (val & P_DAC_RIGHT_MUTE) ? P_UNMUTE : P_MUTE;
  4714. +
  4715. + return val;
  4716. +}
  4717. +
  4718. +static int pcm512x_set_reg_master_switch(struct snd_kcontrol *kcontrol,
  4719. + struct snd_ctl_elem_value *ucontrol)
  4720. +{
  4721. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  4722. + struct snd_soc_pcm_runtime *rtd;
  4723. + struct glb_pool *glb_ptr = card->drvdata;
  4724. + unsigned int left_val = (ucontrol->value.integer.value[0]);
  4725. + unsigned int right_val = (ucontrol->value.integer.value[1]);
  4726. + int ret = 0;
  4727. +
  4728. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4729. + if (glb_ptr->dual_mode == 1) {
  4730. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component, PCM512x_MUTE,
  4731. + ~((left_val & 0x01)<<4));
  4732. + if (ret < 0)
  4733. + return ret;
  4734. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component, PCM512x_MUTE,
  4735. + ~((right_val & 0x01)));
  4736. + if (ret < 0)
  4737. + return ret;
  4738. +
  4739. + } else if (glb_ptr->set_mode == 1) {
  4740. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component, PCM512x_MUTE,
  4741. + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
  4742. + if (ret < 0)
  4743. + return ret;
  4744. +
  4745. + } else {
  4746. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 0)->component, PCM512x_MUTE,
  4747. + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
  4748. + if (ret < 0)
  4749. + return ret;
  4750. +
  4751. + ret = snd_soc_component_write(asoc_rtd_to_codec(rtd, 1)->component, PCM512x_MUTE,
  4752. + ~((left_val & 0x01)<<4 | (right_val & 0x01)));
  4753. + if (ret < 0)
  4754. + return ret;
  4755. + }
  4756. + return 1;
  4757. +}
  4758. +
  4759. +static const DECLARE_TLV_DB_SCALE(digital_tlv_sub, -10350, 50, 1);
  4760. +static const DECLARE_TLV_DB_SCALE(digital_tlv_master, -10350, 50, 1);
  4761. +
  4762. +static const struct snd_kcontrol_new allo_piano_controls[] = {
  4763. + SOC_ENUM_EXT("Subwoofer mode Route",
  4764. + allo_piano_mode_enum,
  4765. + snd_allo_piano_mode_get,
  4766. + snd_allo_piano_mode_put),
  4767. +
  4768. + SOC_ENUM_EXT("Dual Mode Route",
  4769. + allo_piano_dual_mode_enum,
  4770. + snd_allo_piano_dual_mode_get,
  4771. + snd_allo_piano_dual_mode_put),
  4772. +
  4773. + SOC_ENUM_EXT("Lowpass Route", allo_piano_enum,
  4774. + snd_allo_piano_lowpass_get,
  4775. + snd_allo_piano_lowpass_put),
  4776. +
  4777. + SOC_DOUBLE_R_EXT_TLV("Subwoofer Playback Volume",
  4778. + PCM512x_DIGITAL_VOLUME_2,
  4779. + PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
  4780. + pcm512x_get_reg_sub,
  4781. + pcm512x_set_reg_sub,
  4782. + digital_tlv_sub),
  4783. +
  4784. + SOC_DOUBLE_EXT("Subwoofer Playback Switch",
  4785. + PCM512x_MUTE,
  4786. + PCM512x_RQML_SHIFT,
  4787. + PCM512x_RQMR_SHIFT, 1, 1,
  4788. + pcm512x_get_reg_sub_switch,
  4789. + pcm512x_set_reg_sub_switch),
  4790. +
  4791. + SOC_DOUBLE_R_EXT_TLV("Master Playback Volume",
  4792. + PCM512x_DIGITAL_VOLUME_2,
  4793. + PCM512x_DIGITAL_VOLUME_3, 0, 255, 1,
  4794. + pcm512x_get_reg_master,
  4795. + pcm512x_set_reg_master,
  4796. + digital_tlv_master),
  4797. +
  4798. + SOC_DOUBLE_EXT("Master Playback Switch",
  4799. + PCM512x_MUTE,
  4800. + PCM512x_RQML_SHIFT,
  4801. + PCM512x_RQMR_SHIFT, 1, 1,
  4802. + pcm512x_get_reg_master_switch,
  4803. + pcm512x_set_reg_master_switch),
  4804. +};
  4805. +
  4806. +static const char * const codec_ctl_pfx[] = { "Main", "Sub" };
  4807. +static const char * const codec_ctl_name[] = {
  4808. + "Digital Playback Volume",
  4809. + "Digital Playback Switch",
  4810. + "Auto Mute Mono Switch",
  4811. + "Auto Mute Switch",
  4812. + "Auto Mute Time Left",
  4813. + "Auto Mute Time Right",
  4814. + "Clock Missing Period",
  4815. + "Max Overclock DAC",
  4816. + "Max Overclock DSP",
  4817. + "Max Overclock PLL",
  4818. + "Volume Ramp Down Emergency Rate",
  4819. + "Volume Ramp Down Emergency Step",
  4820. + "Volume Ramp Up Rate",
  4821. + "Volume Ramp Down Rate",
  4822. + "Volume Ramp Up Step",
  4823. + "Volume Ramp Down Step"
  4824. +};
  4825. +
  4826. +static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
  4827. +{
  4828. + struct snd_soc_card *card = rtd->card;
  4829. + struct glb_pool *glb_ptr;
  4830. + struct snd_kcontrol *kctl;
  4831. + int i, j;
  4832. +
  4833. + glb_ptr = kzalloc(sizeof(struct glb_pool), GFP_KERNEL);
  4834. + if (!glb_ptr)
  4835. + return -ENOMEM;
  4836. +
  4837. + card->drvdata = glb_ptr;
  4838. + glb_ptr->dual_mode = 2;
  4839. + glb_ptr->set_mode = 0;
  4840. +
  4841. + mutex_init(&glb_ptr->lock);
  4842. +
  4843. + if (digital_gain_0db_limit) {
  4844. + int ret;
  4845. +
  4846. + //Set volume limit on both dacs
  4847. + for (i = 0; i < ARRAY_SIZE(codec_ctl_pfx); i++) {
  4848. + char cname[256];
  4849. +
  4850. + sprintf(cname, "%s %s", codec_ctl_pfx[i], codec_ctl_name[0]);
  4851. + ret = snd_soc_limit_volume(card, cname, 207);
  4852. + if (ret < 0)
  4853. + dev_warn(card->dev, "Failed to set volume limit: %d\n",
  4854. + ret);
  4855. + }
  4856. + }
  4857. +
  4858. + // Remove codec controls
  4859. + for (i = 0; i < ARRAY_SIZE(codec_ctl_pfx); i++) {
  4860. + for (j = 0; j < ARRAY_SIZE(codec_ctl_name); j++) {
  4861. + char cname[256];
  4862. +
  4863. + sprintf(cname, "%s %s", codec_ctl_pfx[i], codec_ctl_name[j]);
  4864. + kctl = snd_soc_card_get_kcontrol(card, cname);
  4865. + if (!kctl) {
  4866. + dev_err(rtd->card->dev, "Control %s not found\n",
  4867. + cname);
  4868. + } else {
  4869. + kctl->vd[0].access =
  4870. + SNDRV_CTL_ELEM_ACCESS_READWRITE;
  4871. + snd_ctl_remove(card->snd_card, kctl);
  4872. + }
  4873. + }
  4874. + }
  4875. +
  4876. + return 0;
  4877. +}
  4878. +
  4879. +static void snd_allo_piano_gpio_mute(struct snd_soc_card *card)
  4880. +{
  4881. + if (mute_gpio[0])
  4882. + gpiod_set_value_cansleep(mute_gpio[0], P_MUTE);
  4883. +
  4884. + if (mute_gpio[1])
  4885. + gpiod_set_value_cansleep(mute_gpio[1], P_MUTE);
  4886. +}
  4887. +
  4888. +static void snd_allo_piano_gpio_unmute(struct snd_soc_card *card)
  4889. +{
  4890. + if (mute_gpio[0])
  4891. + gpiod_set_value_cansleep(mute_gpio[0], P_UNMUTE);
  4892. +
  4893. + if (mute_gpio[1])
  4894. + gpiod_set_value_cansleep(mute_gpio[1], P_UNMUTE);
  4895. +}
  4896. +
  4897. +static int snd_allo_piano_set_bias_level(struct snd_soc_card *card,
  4898. + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
  4899. +{
  4900. + struct snd_soc_pcm_runtime *rtd;
  4901. + struct snd_soc_dai *codec_dai;
  4902. +
  4903. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  4904. + codec_dai = asoc_rtd_to_codec(rtd, 0);
  4905. +
  4906. + if (dapm->dev != codec_dai->dev)
  4907. + return 0;
  4908. +
  4909. + switch (level) {
  4910. + case SND_SOC_BIAS_PREPARE:
  4911. + if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
  4912. + break;
  4913. + /* UNMUTE DAC */
  4914. + snd_allo_piano_gpio_unmute(card);
  4915. + break;
  4916. +
  4917. + case SND_SOC_BIAS_STANDBY:
  4918. + if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
  4919. + break;
  4920. + /* MUTE DAC */
  4921. + snd_allo_piano_gpio_mute(card);
  4922. + break;
  4923. +
  4924. + default:
  4925. + break;
  4926. + }
  4927. +
  4928. + return 0;
  4929. +}
  4930. +
  4931. +static int snd_allo_piano_dac_startup(
  4932. + struct snd_pcm_substream *substream)
  4933. +{
  4934. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  4935. + struct snd_soc_card *card = rtd->card;
  4936. +
  4937. + snd_allo_piano_gpio_mute(card);
  4938. +
  4939. + return 0;
  4940. +}
  4941. +
  4942. +static int snd_allo_piano_dac_hw_params(
  4943. + struct snd_pcm_substream *substream,
  4944. + struct snd_pcm_hw_params *params)
  4945. +{
  4946. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  4947. + unsigned int rate = params_rate(params);
  4948. + struct snd_soc_card *card = rtd->card;
  4949. + struct glb_pool *glb_ptr = card->drvdata;
  4950. + int ret = 0, val = 0, dac;
  4951. +
  4952. + for (dac = 0; (glb_mclk && dac < 2); dac++) {
  4953. + /* Configure the PLL clock reference for both the Codecs */
  4954. + val = snd_soc_component_read(asoc_rtd_to_codec(rtd, dac)->component,
  4955. + PCM512x_RATE_DET_4);
  4956. +
  4957. + if (val & 0x40) {
  4958. + snd_soc_component_write(asoc_rtd_to_codec(rtd, dac)->component,
  4959. + PCM512x_PLL_REF,
  4960. + PCM512x_SREF_BCK);
  4961. +
  4962. + dev_info(asoc_rtd_to_codec(rtd, dac)->component->dev,
  4963. + "Setting BCLK as input clock & Enable PLL\n");
  4964. + } else {
  4965. + snd_soc_component_write(asoc_rtd_to_codec(rtd, dac)->component,
  4966. + PCM512x_PLL_EN,
  4967. + 0x00);
  4968. +
  4969. + snd_soc_component_write(asoc_rtd_to_codec(rtd, dac)->component,
  4970. + PCM512x_PLL_REF,
  4971. + PCM512x_SREF_SCK);
  4972. +
  4973. + dev_info(asoc_rtd_to_codec(rtd, dac)->component->dev,
  4974. + "Setting SCLK as input clock & disabled PLL\n");
  4975. + }
  4976. + }
  4977. +
  4978. + ret = snd_allo_piano_dsp_program(rtd, glb_ptr->set_mode, rate,
  4979. + glb_ptr->set_lowpass);
  4980. + if (ret < 0)
  4981. + return ret;
  4982. +
  4983. + return ret;
  4984. +}
  4985. +
  4986. +static int snd_allo_piano_dac_prepare(
  4987. + struct snd_pcm_substream *substream)
  4988. +{
  4989. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  4990. + struct snd_soc_card *card = rtd->card;
  4991. +
  4992. + snd_allo_piano_gpio_unmute(card);
  4993. +
  4994. + return 0;
  4995. +}
  4996. +
  4997. +/* machine stream operations */
  4998. +static struct snd_soc_ops snd_allo_piano_dac_ops = {
  4999. + .startup = snd_allo_piano_dac_startup,
  5000. + .hw_params = snd_allo_piano_dac_hw_params,
  5001. + .prepare = snd_allo_piano_dac_prepare,
  5002. +};
  5003. +
  5004. +static struct snd_soc_dai_link_component allo_piano_2_1_codecs[] = {
  5005. + {
  5006. + .dai_name = "pcm512x-hifi",
  5007. + },
  5008. + {
  5009. + .dai_name = "pcm512x-hifi",
  5010. + },
  5011. +};
  5012. +
  5013. +SND_SOC_DAILINK_DEFS(allo_piano_dai_plus,
  5014. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  5015. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004c", "pcm512x-hifi"),
  5016. + COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi")),
  5017. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  5018. +
  5019. +static struct snd_soc_dai_link snd_allo_piano_dac_dai[] = {
  5020. + {
  5021. + .name = "PianoDACPlus",
  5022. + .stream_name = "PianoDACPlus",
  5023. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  5024. + SND_SOC_DAIFMT_NB_NF |
  5025. + SND_SOC_DAIFMT_CBS_CFS,
  5026. + .ops = &snd_allo_piano_dac_ops,
  5027. + .init = snd_allo_piano_dac_init,
  5028. + SND_SOC_DAILINK_REG(allo_piano_dai_plus),
  5029. + },
  5030. +};
  5031. +
  5032. +/* audio machine driver */
  5033. +static struct snd_soc_card snd_allo_piano_dac = {
  5034. + .name = "PianoDACPlus",
  5035. + .owner = THIS_MODULE,
  5036. + .dai_link = snd_allo_piano_dac_dai,
  5037. + .num_links = ARRAY_SIZE(snd_allo_piano_dac_dai),
  5038. + .controls = allo_piano_controls,
  5039. + .num_controls = ARRAY_SIZE(allo_piano_controls),
  5040. +};
  5041. +
  5042. +static int snd_allo_piano_dac_probe(struct platform_device *pdev)
  5043. +{
  5044. + struct snd_soc_card *card = &snd_allo_piano_dac;
  5045. + int ret = 0, i = 0;
  5046. +
  5047. + card->dev = &pdev->dev;
  5048. + platform_set_drvdata(pdev, &snd_allo_piano_dac);
  5049. +
  5050. + if (pdev->dev.of_node) {
  5051. + struct device_node *i2s_node;
  5052. + struct snd_soc_dai_link *dai;
  5053. +
  5054. + dai = &snd_allo_piano_dac_dai[0];
  5055. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  5056. + "i2s-controller", 0);
  5057. + if (i2s_node) {
  5058. + for (i = 0; i < card->num_links; i++) {
  5059. + dai->cpus->dai_name = NULL;
  5060. + dai->cpus->of_node = i2s_node;
  5061. + dai->platforms->name = NULL;
  5062. + dai->platforms->of_node = i2s_node;
  5063. + }
  5064. + }
  5065. + digital_gain_0db_limit =
  5066. + !of_property_read_bool(pdev->dev.of_node,
  5067. + "allo,24db_digital_gain");
  5068. +
  5069. + glb_mclk = of_property_read_bool(pdev->dev.of_node,
  5070. + "allo,glb_mclk");
  5071. +
  5072. + allo_piano_2_1_codecs[0].of_node =
  5073. + of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
  5074. + if (!allo_piano_2_1_codecs[0].of_node) {
  5075. + dev_err(&pdev->dev,
  5076. + "Property 'audio-codec' missing or invalid\n");
  5077. + return -EINVAL;
  5078. + }
  5079. +
  5080. + allo_piano_2_1_codecs[1].of_node =
  5081. + of_parse_phandle(pdev->dev.of_node, "audio-codec", 1);
  5082. + if (!allo_piano_2_1_codecs[1].of_node) {
  5083. + dev_err(&pdev->dev,
  5084. + "Property 'audio-codec' missing or invalid\n");
  5085. + return -EINVAL;
  5086. + }
  5087. +
  5088. + mute_gpio[0] = devm_gpiod_get_optional(&pdev->dev, "mute1",
  5089. + GPIOD_OUT_LOW);
  5090. + if (IS_ERR(mute_gpio[0])) {
  5091. + ret = PTR_ERR(mute_gpio[0]);
  5092. + dev_err(&pdev->dev,
  5093. + "failed to get mute1 gpio6: %d\n", ret);
  5094. + return ret;
  5095. + }
  5096. +
  5097. + mute_gpio[1] = devm_gpiod_get_optional(&pdev->dev, "mute2",
  5098. + GPIOD_OUT_LOW);
  5099. + if (IS_ERR(mute_gpio[1])) {
  5100. + ret = PTR_ERR(mute_gpio[1]);
  5101. + dev_err(&pdev->dev,
  5102. + "failed to get mute2 gpio25: %d\n", ret);
  5103. + return ret;
  5104. + }
  5105. +
  5106. + if (mute_gpio[0] && mute_gpio[1])
  5107. + snd_allo_piano_dac.set_bias_level =
  5108. + snd_allo_piano_set_bias_level;
  5109. +
  5110. + ret = snd_soc_register_card(&snd_allo_piano_dac);
  5111. + if (ret < 0) {
  5112. + dev_err(&pdev->dev,
  5113. + "snd_soc_register_card() failed: %d\n", ret);
  5114. + return ret;
  5115. + }
  5116. +
  5117. + if ((mute_gpio[0]) && (mute_gpio[1]))
  5118. + snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
  5119. +
  5120. + return 0;
  5121. + }
  5122. +
  5123. + return -EINVAL;
  5124. +}
  5125. +
  5126. +static int snd_allo_piano_dac_remove(struct platform_device *pdev)
  5127. +{
  5128. + struct snd_soc_card *card = platform_get_drvdata(pdev);
  5129. +
  5130. + kfree(&card->drvdata);
  5131. + snd_allo_piano_gpio_mute(&snd_allo_piano_dac);
  5132. + snd_soc_unregister_card(&snd_allo_piano_dac);
  5133. + return 0;
  5134. +}
  5135. +
  5136. +static const struct of_device_id snd_allo_piano_dac_of_match[] = {
  5137. + { .compatible = "allo,piano-dac-plus", },
  5138. + { /* sentinel */ },
  5139. +};
  5140. +
  5141. +MODULE_DEVICE_TABLE(of, snd_allo_piano_dac_of_match);
  5142. +
  5143. +static struct platform_driver snd_allo_piano_dac_driver = {
  5144. + .driver = {
  5145. + .name = "snd-allo-piano-dac-plus",
  5146. + .owner = THIS_MODULE,
  5147. + .of_match_table = snd_allo_piano_dac_of_match,
  5148. + },
  5149. + .probe = snd_allo_piano_dac_probe,
  5150. + .remove = snd_allo_piano_dac_remove,
  5151. +};
  5152. +
  5153. +module_platform_driver(snd_allo_piano_dac_driver);
  5154. +
  5155. +MODULE_AUTHOR("Baswaraj K <[email protected]>");
  5156. +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC Plus");
  5157. +MODULE_LICENSE("GPL v2");
  5158. --- /dev/null
  5159. +++ b/sound/soc/bcm/allo-piano-dac.c
  5160. @@ -0,0 +1,122 @@
  5161. +/*
  5162. + * ALSA ASoC Machine Driver for Allo Piano DAC
  5163. + *
  5164. + * Author: Baswaraj K <[email protected]>
  5165. + * Copyright 2016
  5166. + * based on code by Daniel Matuschek <[email protected]>
  5167. + * based on code by Florian Meier <[email protected]>
  5168. + *
  5169. + * This program is free software; you can redistribute it and/or
  5170. + * modify it under the terms of the GNU General Public License
  5171. + * version 2 as published by the Free Software Foundation.
  5172. + *
  5173. + * This program is distributed in the hope that it will be useful, but
  5174. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  5175. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  5176. + * General Public License for more details.
  5177. + */
  5178. +
  5179. +#include <linux/module.h>
  5180. +#include <linux/platform_device.h>
  5181. +
  5182. +#include <sound/core.h>
  5183. +#include <sound/pcm.h>
  5184. +#include <sound/pcm_params.h>
  5185. +#include <sound/soc.h>
  5186. +
  5187. +static bool digital_gain_0db_limit = true;
  5188. +
  5189. +static int snd_allo_piano_dac_init(struct snd_soc_pcm_runtime *rtd)
  5190. +{
  5191. + if (digital_gain_0db_limit) {
  5192. + int ret;
  5193. + struct snd_soc_card *card = rtd->card;
  5194. +
  5195. + ret = snd_soc_limit_volume(card, "Digital Playback Volume",
  5196. + 207);
  5197. + if (ret < 0)
  5198. + dev_warn(card->dev, "Failed to set volume limit: %d\n",
  5199. + ret);
  5200. + }
  5201. +
  5202. + return 0;
  5203. +}
  5204. +
  5205. +SND_SOC_DAILINK_DEFS(allo_piano_dai,
  5206. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  5207. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004c", "pcm512x-hifi")),
  5208. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  5209. +
  5210. +static struct snd_soc_dai_link snd_allo_piano_dac_dai[] = {
  5211. +{
  5212. + .name = "Piano DAC",
  5213. + .stream_name = "Piano DAC HiFi",
  5214. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  5215. + SND_SOC_DAIFMT_NB_NF |
  5216. + SND_SOC_DAIFMT_CBS_CFS,
  5217. + .init = snd_allo_piano_dac_init,
  5218. + SND_SOC_DAILINK_REG(allo_piano_dai),
  5219. +},
  5220. +};
  5221. +
  5222. +/* audio machine driver */
  5223. +static struct snd_soc_card snd_allo_piano_dac = {
  5224. + .name = "PianoDAC",
  5225. + .owner = THIS_MODULE,
  5226. + .dai_link = snd_allo_piano_dac_dai,
  5227. + .num_links = ARRAY_SIZE(snd_allo_piano_dac_dai),
  5228. +};
  5229. +
  5230. +static int snd_allo_piano_dac_probe(struct platform_device *pdev)
  5231. +{
  5232. + int ret = 0;
  5233. +
  5234. + snd_allo_piano_dac.dev = &pdev->dev;
  5235. +
  5236. + if (pdev->dev.of_node) {
  5237. + struct device_node *i2s_node;
  5238. + struct snd_soc_dai_link *dai;
  5239. +
  5240. + dai = &snd_allo_piano_dac_dai[0];
  5241. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  5242. + "i2s-controller", 0);
  5243. +
  5244. + if (i2s_node) {
  5245. + dai->cpus->dai_name = NULL;
  5246. + dai->cpus->of_node = i2s_node;
  5247. + dai->platforms->name = NULL;
  5248. + dai->platforms->of_node = i2s_node;
  5249. + }
  5250. +
  5251. + digital_gain_0db_limit = !of_property_read_bool(
  5252. + pdev->dev.of_node, "allo,24db_digital_gain");
  5253. + }
  5254. +
  5255. + ret = devm_snd_soc_register_card(&pdev->dev, &snd_allo_piano_dac);
  5256. + if (ret && ret != -EPROBE_DEFER)
  5257. + dev_err(&pdev->dev,
  5258. + "snd_soc_register_card() failed: %d\n", ret);
  5259. +
  5260. + return ret;
  5261. +}
  5262. +
  5263. +static const struct of_device_id snd_allo_piano_dac_of_match[] = {
  5264. + { .compatible = "allo,piano-dac", },
  5265. + { /* sentinel */ },
  5266. +};
  5267. +MODULE_DEVICE_TABLE(of, snd_allo_piano_dac_of_match);
  5268. +
  5269. +static struct platform_driver snd_allo_piano_dac_driver = {
  5270. + .driver = {
  5271. + .name = "snd-allo-piano-dac",
  5272. + .owner = THIS_MODULE,
  5273. + .of_match_table = snd_allo_piano_dac_of_match,
  5274. + },
  5275. + .probe = snd_allo_piano_dac_probe,
  5276. +};
  5277. +
  5278. +module_platform_driver(snd_allo_piano_dac_driver);
  5279. +
  5280. +MODULE_AUTHOR("Baswaraj K <[email protected]>");
  5281. +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC");
  5282. +MODULE_LICENSE("GPL v2");
  5283. --- /dev/null
  5284. +++ b/sound/soc/bcm/audioinjector-isolated-soundcard.c
  5285. @@ -0,0 +1,183 @@
  5286. +/*
  5287. + * ASoC Driver for AudioInjector.net isolated soundcard
  5288. + *
  5289. + * Created on: 20-February-2020
  5290. + * Author: [email protected]
  5291. + * based on audioinjector-octo-soundcard.c
  5292. + *
  5293. + * Copyright (C) 2020 Flatmax Pty. Ltd.
  5294. + *
  5295. + * This program is free software; you can redistribute it and/or
  5296. + * modify it under the terms of the GNU General Public License
  5297. + * version 2 as published by the Free Software Foundation.
  5298. + *
  5299. + * This program is distributed in the hope that it will be useful, but
  5300. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  5301. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  5302. + * General Public License for more details.
  5303. + */
  5304. +
  5305. +#include <linux/module.h>
  5306. +#include <linux/types.h>
  5307. +#include <linux/gpio/consumer.h>
  5308. +
  5309. +#include <sound/core.h>
  5310. +#include <sound/soc.h>
  5311. +#include <sound/pcm_params.h>
  5312. +#include <sound/control.h>
  5313. +
  5314. +static struct gpio_desc *mute_gpio;
  5315. +
  5316. +static const unsigned int audioinjector_isolated_rates[] = {
  5317. + 192000, 96000, 48000, 32000, 24000, 16000, 8000
  5318. +};
  5319. +
  5320. +static struct snd_pcm_hw_constraint_list audioinjector_isolated_constraints = {
  5321. + .list = audioinjector_isolated_rates,
  5322. + .count = ARRAY_SIZE(audioinjector_isolated_rates),
  5323. +};
  5324. +
  5325. +static int audioinjector_isolated_dai_init(struct snd_soc_pcm_runtime *rtd)
  5326. +{
  5327. + int ret=snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 24576000, 0);
  5328. + if (ret)
  5329. + return ret;
  5330. +
  5331. + return snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), 64);
  5332. +}
  5333. +
  5334. +static int audioinjector_isolated_startup(struct snd_pcm_substream *substream)
  5335. +{
  5336. + snd_pcm_hw_constraint_list(substream->runtime, 0,
  5337. + SNDRV_PCM_HW_PARAM_RATE, &audioinjector_isolated_constraints);
  5338. +
  5339. + return 0;
  5340. +}
  5341. +
  5342. +static int audioinjector_isolated_trigger(struct snd_pcm_substream *substream,
  5343. + int cmd){
  5344. +
  5345. + switch (cmd) {
  5346. + case SNDRV_PCM_TRIGGER_STOP:
  5347. + case SNDRV_PCM_TRIGGER_SUSPEND:
  5348. + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  5349. + gpiod_set_value(mute_gpio, 0);
  5350. + break;
  5351. + case SNDRV_PCM_TRIGGER_START:
  5352. + case SNDRV_PCM_TRIGGER_RESUME:
  5353. + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  5354. + gpiod_set_value(mute_gpio, 1);
  5355. + break;
  5356. + default:
  5357. + return -EINVAL;
  5358. + }
  5359. + return 0;
  5360. +}
  5361. +
  5362. +static struct snd_soc_ops audioinjector_isolated_ops = {
  5363. + .startup = audioinjector_isolated_startup,
  5364. + .trigger = audioinjector_isolated_trigger,
  5365. +};
  5366. +
  5367. +SND_SOC_DAILINK_DEFS(audioinjector_isolated,
  5368. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  5369. + DAILINK_COMP_ARRAY(COMP_CODEC("cs4271.1-0010", "cs4271-hifi")),
  5370. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  5371. +
  5372. +static struct snd_soc_dai_link audioinjector_isolated_dai[] = {
  5373. + {
  5374. + .name = "AudioInjector ISO",
  5375. + .stream_name = "AI-HIFI",
  5376. + .ops = &audioinjector_isolated_ops,
  5377. + .init = audioinjector_isolated_dai_init,
  5378. + .symmetric_rate = 1,
  5379. + .symmetric_channels = 1,
  5380. + .dai_fmt = SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF,
  5381. + SND_SOC_DAILINK_REG(audioinjector_isolated),
  5382. + }
  5383. +};
  5384. +
  5385. +static const struct snd_soc_dapm_widget audioinjector_isolated_widgets[] = {
  5386. + SND_SOC_DAPM_OUTPUT("OUTPUTS"),
  5387. + SND_SOC_DAPM_INPUT("INPUTS"),
  5388. +};
  5389. +
  5390. +static const struct snd_soc_dapm_route audioinjector_isolated_route[] = {
  5391. + /* Balanced outputs */
  5392. + {"OUTPUTS", NULL, "AOUTA+"},
  5393. + {"OUTPUTS", NULL, "AOUTA-"},
  5394. + {"OUTPUTS", NULL, "AOUTB+"},
  5395. + {"OUTPUTS", NULL, "AOUTB-"},
  5396. +
  5397. + /* Balanced inputs */
  5398. + {"AINA", NULL, "INPUTS"},
  5399. + {"AINB", NULL, "INPUTS"},
  5400. +};
  5401. +
  5402. +static struct snd_soc_card snd_soc_audioinjector_isolated = {
  5403. + .name = "audioinjector-isolated-soundcard",
  5404. + .dai_link = audioinjector_isolated_dai,
  5405. + .num_links = ARRAY_SIZE(audioinjector_isolated_dai),
  5406. +
  5407. + .dapm_widgets = audioinjector_isolated_widgets,
  5408. + .num_dapm_widgets = ARRAY_SIZE(audioinjector_isolated_widgets),
  5409. + .dapm_routes = audioinjector_isolated_route,
  5410. + .num_dapm_routes = ARRAY_SIZE(audioinjector_isolated_route),
  5411. +};
  5412. +
  5413. +static int audioinjector_isolated_probe(struct platform_device *pdev)
  5414. +{
  5415. + struct snd_soc_card *card = &snd_soc_audioinjector_isolated;
  5416. + int ret;
  5417. +
  5418. + card->dev = &pdev->dev;
  5419. +
  5420. + if (pdev->dev.of_node) {
  5421. + struct snd_soc_dai_link *dai = &audioinjector_isolated_dai[0];
  5422. + struct device_node *i2s_node =
  5423. + of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0);
  5424. +
  5425. + if (i2s_node) {
  5426. + dai->cpus->dai_name = NULL;
  5427. + dai->cpus->of_node = i2s_node;
  5428. + dai->platforms->name = NULL;
  5429. + dai->platforms->of_node = i2s_node;
  5430. + } else {
  5431. + dev_err(&pdev->dev,
  5432. + "i2s-controller missing or invalid in DT\n");
  5433. + return -EINVAL;
  5434. + }
  5435. +
  5436. + mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_LOW);
  5437. + if (IS_ERR(mute_gpio)){
  5438. + dev_err(&pdev->dev, "mute gpio not found in dt overlay\n");
  5439. + return PTR_ERR(mute_gpio);
  5440. + }
  5441. + }
  5442. +
  5443. + ret = devm_snd_soc_register_card(&pdev->dev, card);
  5444. + if (ret && ret != -EPROBE_DEFER)
  5445. + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
  5446. + return ret;
  5447. +}
  5448. +
  5449. +static const struct of_device_id audioinjector_isolated_of_match[] = {
  5450. + { .compatible = "ai,audioinjector-isolated-soundcard", },
  5451. + {},
  5452. +};
  5453. +MODULE_DEVICE_TABLE(of, audioinjector_isolated_of_match);
  5454. +
  5455. +static struct platform_driver audioinjector_isolated_driver = {
  5456. + .driver = {
  5457. + .name = "audioinjector-isolated",
  5458. + .owner = THIS_MODULE,
  5459. + .of_match_table = audioinjector_isolated_of_match,
  5460. + },
  5461. + .probe = audioinjector_isolated_probe,
  5462. +};
  5463. +
  5464. +module_platform_driver(audioinjector_isolated_driver);
  5465. +MODULE_AUTHOR("Matt Flax <[email protected]>");
  5466. +MODULE_DESCRIPTION("AudioInjector.net isolated Soundcard");
  5467. +MODULE_LICENSE("GPL v2");
  5468. +MODULE_ALIAS("platform:audioinjector-isolated-soundcard");
  5469. --- /dev/null
  5470. +++ b/sound/soc/bcm/audioinjector-octo-soundcard.c
  5471. @@ -0,0 +1,346 @@
  5472. +/*
  5473. + * ASoC Driver for AudioInjector Pi octo channel soundcard (hat)
  5474. + *
  5475. + * Created on: 27-October-2016
  5476. + * Author: [email protected]
  5477. + * based on audioinjector-pi-soundcard.c
  5478. + *
  5479. + * Copyright (C) 2016 Flatmax Pty. Ltd.
  5480. + *
  5481. + * This program is free software; you can redistribute it and/or
  5482. + * modify it under the terms of the GNU General Public License
  5483. + * version 2 as published by the Free Software Foundation.
  5484. + *
  5485. + * This program is distributed in the hope that it will be useful, but
  5486. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  5487. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  5488. + * General Public License for more details.
  5489. + */
  5490. +
  5491. +#include <linux/module.h>
  5492. +#include <linux/types.h>
  5493. +#include <linux/gpio/consumer.h>
  5494. +
  5495. +#include <sound/core.h>
  5496. +#include <sound/soc.h>
  5497. +#include <sound/pcm_params.h>
  5498. +#include <sound/control.h>
  5499. +
  5500. +static struct gpio_descs *mult_gpios;
  5501. +static struct gpio_desc *codec_rst_gpio;
  5502. +static unsigned int audioinjector_octo_rate;
  5503. +static bool non_stop_clocks;
  5504. +
  5505. +static const unsigned int audioinjector_octo_rates[] = {
  5506. + 96000, 48000, 32000, 24000, 16000, 8000, 88200, 44100, 29400, 22050, 14700,
  5507. +};
  5508. +
  5509. +static struct snd_pcm_hw_constraint_list audioinjector_octo_constraints = {
  5510. + .list = audioinjector_octo_rates,
  5511. + .count = ARRAY_SIZE(audioinjector_octo_rates),
  5512. +};
  5513. +
  5514. +static int audioinjector_octo_dai_init(struct snd_soc_pcm_runtime *rtd)
  5515. +{
  5516. + return snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), 64);
  5517. +}
  5518. +
  5519. +static int audioinjector_octo_startup(struct snd_pcm_substream *substream)
  5520. +{
  5521. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  5522. + asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = 8;
  5523. + asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = 8;
  5524. + asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = 8;
  5525. + asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = 8;
  5526. + asoc_rtd_to_codec(rtd, 0)->driver->capture.channels_max = 8;
  5527. +
  5528. + snd_pcm_hw_constraint_list(substream->runtime, 0,
  5529. + SNDRV_PCM_HW_PARAM_RATE,
  5530. + &audioinjector_octo_constraints);
  5531. +
  5532. + return 0;
  5533. +}
  5534. +
  5535. +static void audioinjector_octo_shutdown(struct snd_pcm_substream *substream)
  5536. +{
  5537. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  5538. + asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = 2;
  5539. + asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = 2;
  5540. + asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = 2;
  5541. + asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = 2;
  5542. + asoc_rtd_to_codec(rtd, 0)->driver->capture.channels_max = 6;
  5543. +}
  5544. +
  5545. +static int audioinjector_octo_hw_params(struct snd_pcm_substream *substream,
  5546. + struct snd_pcm_hw_params *params)
  5547. +{
  5548. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  5549. +
  5550. + // set codec DAI configuration
  5551. + int ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0),
  5552. + SND_SOC_DAIFMT_CBS_CFS|SND_SOC_DAIFMT_DSP_A|
  5553. + SND_SOC_DAIFMT_NB_NF);
  5554. + if (ret < 0)
  5555. + return ret;
  5556. +
  5557. + // set cpu DAI configuration
  5558. + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
  5559. + SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|
  5560. + SND_SOC_DAIFMT_NB_NF);
  5561. + if (ret < 0)
  5562. + return ret;
  5563. +
  5564. + audioinjector_octo_rate = params_rate(params);
  5565. +
  5566. + // Set the correct sysclock for the codec
  5567. + switch (audioinjector_octo_rate) {
  5568. + case 96000:
  5569. + case 48000:
  5570. + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 49152000,
  5571. + 0);
  5572. + break;
  5573. + case 24000:
  5574. + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 49152000/2,
  5575. + 0);
  5576. + break;
  5577. + case 32000:
  5578. + case 16000:
  5579. + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 49152000/3,
  5580. + 0);
  5581. + break;
  5582. + case 8000:
  5583. + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 49152000/6,
  5584. + 0);
  5585. + break;
  5586. + case 88200:
  5587. + case 44100:
  5588. + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 45185400,
  5589. + 0);
  5590. + break;
  5591. + case 22050:
  5592. + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 45185400/2,
  5593. + 0);
  5594. + break;
  5595. + case 29400:
  5596. + case 14700:
  5597. + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), 0, 45185400/3,
  5598. + 0);
  5599. + break;
  5600. + default:
  5601. + return -EINVAL;
  5602. + }
  5603. +}
  5604. +
  5605. +static int audioinjector_octo_trigger(struct snd_pcm_substream *substream,
  5606. + int cmd){
  5607. + DECLARE_BITMAP(mult, 4);
  5608. +
  5609. + memset(mult, 0, sizeof(mult));
  5610. +
  5611. + switch (cmd) {
  5612. + case SNDRV_PCM_TRIGGER_STOP:
  5613. + case SNDRV_PCM_TRIGGER_SUSPEND:
  5614. + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  5615. + if (!non_stop_clocks)
  5616. + break;
  5617. + fallthrough;
  5618. + case SNDRV_PCM_TRIGGER_START:
  5619. + case SNDRV_PCM_TRIGGER_RESUME:
  5620. + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  5621. + switch (audioinjector_octo_rate) {
  5622. + case 96000:
  5623. + __assign_bit(3, mult, 1);
  5624. + fallthrough;
  5625. + case 88200:
  5626. + __assign_bit(1, mult, 1);
  5627. + __assign_bit(2, mult, 1);
  5628. + break;
  5629. + case 48000:
  5630. + __assign_bit(3, mult, 1);
  5631. + fallthrough;
  5632. + case 44100:
  5633. + __assign_bit(2, mult, 1);
  5634. + break;
  5635. + case 32000:
  5636. + __assign_bit(3, mult, 1);
  5637. + fallthrough;
  5638. + case 29400:
  5639. + __assign_bit(0, mult, 1);
  5640. + __assign_bit(1, mult, 1);
  5641. + break;
  5642. + case 24000:
  5643. + __assign_bit(3, mult, 1);
  5644. + fallthrough;
  5645. + case 22050:
  5646. + __assign_bit(1, mult, 1);
  5647. + break;
  5648. + case 16000:
  5649. + __assign_bit(3, mult, 1);
  5650. + fallthrough;
  5651. + case 14700:
  5652. + __assign_bit(0, mult, 1);
  5653. + break;
  5654. + case 8000:
  5655. + __assign_bit(3, mult, 1);
  5656. + break;
  5657. + default:
  5658. + return -EINVAL;
  5659. + }
  5660. + break;
  5661. + default:
  5662. + return -EINVAL;
  5663. + }
  5664. + gpiod_set_array_value_cansleep(mult_gpios->ndescs, mult_gpios->desc,
  5665. + NULL, mult);
  5666. +
  5667. + return 0;
  5668. +}
  5669. +
  5670. +static struct snd_soc_ops audioinjector_octo_ops = {
  5671. + .startup = audioinjector_octo_startup,
  5672. + .shutdown = audioinjector_octo_shutdown,
  5673. + .hw_params = audioinjector_octo_hw_params,
  5674. + .trigger = audioinjector_octo_trigger,
  5675. +};
  5676. +
  5677. +SND_SOC_DAILINK_DEFS(audioinjector_octo,
  5678. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  5679. + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42448")),
  5680. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  5681. +
  5682. +static struct snd_soc_dai_link audioinjector_octo_dai[] = {
  5683. + {
  5684. + .name = "AudioInjector Octo",
  5685. + .stream_name = "AudioInject-HIFI",
  5686. + .ops = &audioinjector_octo_ops,
  5687. + .init = audioinjector_octo_dai_init,
  5688. + .symmetric_rate = 1,
  5689. + .symmetric_channels = 1,
  5690. + SND_SOC_DAILINK_REG(audioinjector_octo),
  5691. + },
  5692. +};
  5693. +
  5694. +static const struct snd_soc_dapm_widget audioinjector_octo_widgets[] = {
  5695. + SND_SOC_DAPM_OUTPUT("OUTPUTS0"),
  5696. + SND_SOC_DAPM_OUTPUT("OUTPUTS1"),
  5697. + SND_SOC_DAPM_OUTPUT("OUTPUTS2"),
  5698. + SND_SOC_DAPM_OUTPUT("OUTPUTS3"),
  5699. + SND_SOC_DAPM_INPUT("INPUTS0"),
  5700. + SND_SOC_DAPM_INPUT("INPUTS1"),
  5701. + SND_SOC_DAPM_INPUT("INPUTS2"),
  5702. +};
  5703. +
  5704. +static const struct snd_soc_dapm_route audioinjector_octo_route[] = {
  5705. + /* Balanced outputs */
  5706. + {"OUTPUTS0", NULL, "AOUT1L"},
  5707. + {"OUTPUTS0", NULL, "AOUT1R"},
  5708. + {"OUTPUTS1", NULL, "AOUT2L"},
  5709. + {"OUTPUTS1", NULL, "AOUT2R"},
  5710. + {"OUTPUTS2", NULL, "AOUT3L"},
  5711. + {"OUTPUTS2", NULL, "AOUT3R"},
  5712. + {"OUTPUTS3", NULL, "AOUT4L"},
  5713. + {"OUTPUTS3", NULL, "AOUT4R"},
  5714. +
  5715. + /* Balanced inputs */
  5716. + {"AIN1L", NULL, "INPUTS0"},
  5717. + {"AIN1R", NULL, "INPUTS0"},
  5718. + {"AIN2L", NULL, "INPUTS1"},
  5719. + {"AIN2R", NULL, "INPUTS1"},
  5720. + {"AIN3L", NULL, "INPUTS2"},
  5721. + {"AIN3R", NULL, "INPUTS2"},
  5722. +};
  5723. +
  5724. +static struct snd_soc_card snd_soc_audioinjector_octo = {
  5725. + .name = "audioinjector-octo-soundcard",
  5726. + .dai_link = audioinjector_octo_dai,
  5727. + .num_links = ARRAY_SIZE(audioinjector_octo_dai),
  5728. +
  5729. + .dapm_widgets = audioinjector_octo_widgets,
  5730. + .num_dapm_widgets = ARRAY_SIZE(audioinjector_octo_widgets),
  5731. + .dapm_routes = audioinjector_octo_route,
  5732. + .num_dapm_routes = ARRAY_SIZE(audioinjector_octo_route),
  5733. +};
  5734. +
  5735. +static int audioinjector_octo_probe(struct platform_device *pdev)
  5736. +{
  5737. + struct snd_soc_card *card = &snd_soc_audioinjector_octo;
  5738. + int ret;
  5739. +
  5740. + card->dev = &pdev->dev;
  5741. +
  5742. + if (pdev->dev.of_node) {
  5743. + struct snd_soc_dai_link *dai = &audioinjector_octo_dai[0];
  5744. + struct device_node *i2s_node =
  5745. + of_parse_phandle(pdev->dev.of_node,
  5746. + "i2s-controller", 0);
  5747. + struct device_node *codec_node =
  5748. + of_parse_phandle(pdev->dev.of_node,
  5749. + "codec", 0);
  5750. +
  5751. + mult_gpios = devm_gpiod_get_array_optional(&pdev->dev, "mult",
  5752. + GPIOD_OUT_LOW);
  5753. + if (IS_ERR(mult_gpios))
  5754. + return PTR_ERR(mult_gpios);
  5755. +
  5756. + codec_rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
  5757. + GPIOD_OUT_LOW);
  5758. + if (IS_ERR(codec_rst_gpio))
  5759. + return PTR_ERR(codec_rst_gpio);
  5760. +
  5761. + non_stop_clocks = of_property_read_bool(pdev->dev.of_node, "non-stop-clocks");
  5762. +
  5763. + if (codec_rst_gpio)
  5764. + gpiod_set_value(codec_rst_gpio, 1);
  5765. + msleep(500);
  5766. + if (codec_rst_gpio)
  5767. + gpiod_set_value(codec_rst_gpio, 0);
  5768. + msleep(500);
  5769. + if (codec_rst_gpio)
  5770. + gpiod_set_value(codec_rst_gpio, 1);
  5771. + msleep(500);
  5772. +
  5773. + if (i2s_node && codec_node) {
  5774. + dai->cpus->dai_name = NULL;
  5775. + dai->cpus->of_node = i2s_node;
  5776. + dai->platforms->name = NULL;
  5777. + dai->platforms->of_node = i2s_node;
  5778. + dai->codecs->name = NULL;
  5779. + dai->codecs->of_node = codec_node;
  5780. + } else
  5781. + if (!i2s_node) {
  5782. + dev_err(&pdev->dev,
  5783. + "i2s-controller missing or invalid in DT\n");
  5784. + return -EINVAL;
  5785. + } else {
  5786. + dev_err(&pdev->dev,
  5787. + "Property 'codec' missing or invalid\n");
  5788. + return -EINVAL;
  5789. + }
  5790. + }
  5791. +
  5792. + ret = devm_snd_soc_register_card(&pdev->dev, card);
  5793. + if (ret != 0)
  5794. + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
  5795. + return ret;
  5796. +}
  5797. +
  5798. +static const struct of_device_id audioinjector_octo_of_match[] = {
  5799. + { .compatible = "ai,audioinjector-octo-soundcard", },
  5800. + {},
  5801. +};
  5802. +MODULE_DEVICE_TABLE(of, audioinjector_octo_of_match);
  5803. +
  5804. +static struct platform_driver audioinjector_octo_driver = {
  5805. + .driver = {
  5806. + .name = "audioinjector-octo",
  5807. + .owner = THIS_MODULE,
  5808. + .of_match_table = audioinjector_octo_of_match,
  5809. + },
  5810. + .probe = audioinjector_octo_probe,
  5811. +};
  5812. +
  5813. +module_platform_driver(audioinjector_octo_driver);
  5814. +MODULE_AUTHOR("Matt Flax <[email protected]>");
  5815. +MODULE_DESCRIPTION("AudioInjector.net octo Soundcard");
  5816. +MODULE_LICENSE("GPL v2");
  5817. +MODULE_ALIAS("platform:audioinjector-octo-soundcard");
  5818. --- /dev/null
  5819. +++ b/sound/soc/bcm/audioinjector-pi-soundcard.c
  5820. @@ -0,0 +1,189 @@
  5821. +/*
  5822. + * ASoC Driver for AudioInjector Pi add on soundcard
  5823. + *
  5824. + * Created on: 13-May-2016
  5825. + * Author: [email protected]
  5826. + * based on code by Cliff Cai <[email protected]> for the ssm2602 machine blackfin.
  5827. + * with help from Lars-Peter Clausen for simplifying the original code to use the dai_fmt field.
  5828. + * i2s_node code taken from the other sound/soc/bcm machine drivers.
  5829. + *
  5830. + * Copyright (C) 2016 Flatmax Pty. Ltd.
  5831. + *
  5832. + * This program is free software; you can redistribute it and/or
  5833. + * modify it under the terms of the GNU General Public License
  5834. + * version 2 as published by the Free Software Foundation.
  5835. + *
  5836. + * This program is distributed in the hope that it will be useful, but
  5837. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  5838. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  5839. + * General Public License for more details.
  5840. + */
  5841. +
  5842. +#include <linux/module.h>
  5843. +#include <linux/types.h>
  5844. +
  5845. +#include <sound/core.h>
  5846. +#include <sound/soc.h>
  5847. +#include <sound/pcm_params.h>
  5848. +#include <sound/control.h>
  5849. +
  5850. +#include "../codecs/wm8731.h"
  5851. +
  5852. +static const unsigned int bcm2835_rates_12000000[] = {
  5853. + 8000, 16000, 32000, 44100, 48000, 96000, 88200,
  5854. +};
  5855. +
  5856. +static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = {
  5857. + .list = bcm2835_rates_12000000,
  5858. + .count = ARRAY_SIZE(bcm2835_rates_12000000),
  5859. +};
  5860. +
  5861. +static int snd_audioinjector_pi_soundcard_startup(struct snd_pcm_substream *substream)
  5862. +{
  5863. + /* Setup constraints, because there is a 12 MHz XTAL on the board */
  5864. + snd_pcm_hw_constraint_list(substream->runtime, 0,
  5865. + SNDRV_PCM_HW_PARAM_RATE,
  5866. + &bcm2835_constraints_12000000);
  5867. + return 0;
  5868. +}
  5869. +
  5870. +static int snd_audioinjector_pi_soundcard_hw_params(struct snd_pcm_substream *substream,
  5871. + struct snd_pcm_hw_params *params)
  5872. +{
  5873. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  5874. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  5875. +
  5876. + switch (params_rate(params)){
  5877. + case 8000:
  5878. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 1);
  5879. + case 16000:
  5880. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 750);
  5881. + case 32000:
  5882. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 375);
  5883. + case 44100:
  5884. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 272);
  5885. + case 48000:
  5886. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 250);
  5887. + case 88200:
  5888. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 136);
  5889. + case 96000:
  5890. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 125);
  5891. + default:
  5892. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 125);
  5893. + }
  5894. +}
  5895. +
  5896. +/* machine stream operations */
  5897. +static struct snd_soc_ops snd_audioinjector_pi_soundcard_ops = {
  5898. + .startup = snd_audioinjector_pi_soundcard_startup,
  5899. + .hw_params = snd_audioinjector_pi_soundcard_hw_params,
  5900. +};
  5901. +
  5902. +static int audioinjector_pi_soundcard_dai_init(struct snd_soc_pcm_runtime *rtd)
  5903. +{
  5904. + return snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), WM8731_SYSCLK_XTAL, 12000000, SND_SOC_CLOCK_IN);
  5905. +}
  5906. +
  5907. +SND_SOC_DAILINK_DEFS(audioinjector_pi,
  5908. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  5909. + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.1-001a", "wm8731-hifi")),
  5910. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2835-i2s.0")));
  5911. +
  5912. +static struct snd_soc_dai_link audioinjector_pi_soundcard_dai[] = {
  5913. + {
  5914. + .name = "AudioInjector audio",
  5915. + .stream_name = "AudioInjector audio",
  5916. + .ops = &snd_audioinjector_pi_soundcard_ops,
  5917. + .init = audioinjector_pi_soundcard_dai_init,
  5918. + .dai_fmt = SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF,
  5919. + SND_SOC_DAILINK_REG(audioinjector_pi),
  5920. + },
  5921. +};
  5922. +
  5923. +static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
  5924. + SND_SOC_DAPM_HP("Headphone Jack", NULL),
  5925. + SND_SOC_DAPM_SPK("Ext Spk", NULL),
  5926. + SND_SOC_DAPM_LINE("Line In Jacks", NULL),
  5927. + SND_SOC_DAPM_MIC("Microphone", NULL),
  5928. +};
  5929. +
  5930. +static const struct snd_soc_dapm_route audioinjector_audio_map[] = {
  5931. + /* headphone connected to LHPOUT, RHPOUT */
  5932. + {"Headphone Jack", NULL, "LHPOUT"},
  5933. + {"Headphone Jack", NULL, "RHPOUT"},
  5934. +
  5935. + /* speaker connected to LOUT, ROUT */
  5936. + {"Ext Spk", NULL, "ROUT"},
  5937. + {"Ext Spk", NULL, "LOUT"},
  5938. +
  5939. + /* line inputs */
  5940. + {"Line In Jacks", NULL, "Line Input"},
  5941. +
  5942. + /* mic is connected to Mic Jack, with WM8731 Mic Bias */
  5943. + {"Microphone", NULL, "Mic Bias"},
  5944. +};
  5945. +
  5946. +static struct snd_soc_card snd_soc_audioinjector = {
  5947. + .name = "audioinjector-pi-soundcard",
  5948. + .dai_link = audioinjector_pi_soundcard_dai,
  5949. + .num_links = ARRAY_SIZE(audioinjector_pi_soundcard_dai),
  5950. +
  5951. + .dapm_widgets = wm8731_dapm_widgets,
  5952. + .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
  5953. + .dapm_routes = audioinjector_audio_map,
  5954. + .num_dapm_routes = ARRAY_SIZE(audioinjector_audio_map),
  5955. +};
  5956. +
  5957. +static int audioinjector_pi_soundcard_probe(struct platform_device *pdev)
  5958. +{
  5959. + struct snd_soc_card *card = &snd_soc_audioinjector;
  5960. + int ret;
  5961. +
  5962. + card->dev = &pdev->dev;
  5963. +
  5964. + if (pdev->dev.of_node) {
  5965. + struct snd_soc_dai_link *dai = &audioinjector_pi_soundcard_dai[0];
  5966. + struct device_node *i2s_node = of_parse_phandle(pdev->dev.of_node,
  5967. + "i2s-controller", 0);
  5968. +
  5969. + if (i2s_node) {
  5970. + dai->cpus->dai_name = NULL;
  5971. + dai->cpus->of_node = i2s_node;
  5972. + dai->platforms->name = NULL;
  5973. + dai->platforms->of_node = i2s_node;
  5974. + } else
  5975. + if (!dai->cpus->of_node) {
  5976. + dev_err(&pdev->dev, "Property 'i2s-controller' missing or invalid\n");
  5977. + return -EINVAL;
  5978. + }
  5979. + }
  5980. +
  5981. + if ((ret = devm_snd_soc_register_card(&pdev->dev, card)))
  5982. + return dev_err_probe(&pdev->dev, ret, "%s\n", __func__);
  5983. +
  5984. + dev_info(&pdev->dev, "successfully loaded\n");
  5985. +
  5986. + return ret;
  5987. +}
  5988. +
  5989. +static const struct of_device_id audioinjector_pi_soundcard_of_match[] = {
  5990. + { .compatible = "ai,audioinjector-pi-soundcard", },
  5991. + {},
  5992. +};
  5993. +MODULE_DEVICE_TABLE(of, audioinjector_pi_soundcard_of_match);
  5994. +
  5995. +static struct platform_driver audioinjector_pi_soundcard_driver = {
  5996. + .driver = {
  5997. + .name = "audioinjector-stereo",
  5998. + .owner = THIS_MODULE,
  5999. + .of_match_table = audioinjector_pi_soundcard_of_match,
  6000. + },
  6001. + .probe = audioinjector_pi_soundcard_probe,
  6002. +};
  6003. +
  6004. +module_platform_driver(audioinjector_pi_soundcard_driver);
  6005. +MODULE_AUTHOR("Matt Flax <[email protected]>");
  6006. +MODULE_DESCRIPTION("AudioInjector.net Pi Soundcard");
  6007. +MODULE_LICENSE("GPL v2");
  6008. +MODULE_ALIAS("platform:audioinjector-pi-soundcard");
  6009. +
  6010. --- /dev/null
  6011. +++ b/sound/soc/bcm/audiosense-pi.c
  6012. @@ -0,0 +1,248 @@
  6013. +/*
  6014. + * ASoC Driver for AudioSense add on soundcard
  6015. + * Author:
  6016. + * Bhargav A K <[email protected]>
  6017. + * Copyright 2017
  6018. + *
  6019. + * This program is free software; you can redistribute it and/or
  6020. + * modify it under the terms of the GNU General Public License
  6021. + * version 2 as published by the Free Software Foundation.
  6022. + *
  6023. + * This program is distributed in the hope that it will be useful, but
  6024. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  6025. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  6026. + * General Public License for more details.
  6027. + */
  6028. +
  6029. +#include <linux/module.h>
  6030. +#include <linux/platform_device.h>
  6031. +#include <linux/clk.h>
  6032. +#include <linux/i2c.h>
  6033. +#include <sound/core.h>
  6034. +#include <sound/pcm.h>
  6035. +#include <sound/pcm_params.h>
  6036. +#include <sound/soc.h>
  6037. +#include <sound/jack.h>
  6038. +#include <sound/control.h>
  6039. +
  6040. +#include <sound/tlv320aic32x4.h>
  6041. +#include "../codecs/tlv320aic32x4.h"
  6042. +
  6043. +#define AIC32X4_SYSCLK_XTAL 0x00
  6044. +
  6045. +/*
  6046. + * Setup Codec Sample Rates and Channels
  6047. + * Supported Rates:
  6048. + * 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000,
  6049. + */
  6050. +static const unsigned int audiosense_pi_rate[] = {
  6051. + 48000,
  6052. +};
  6053. +
  6054. +static struct snd_pcm_hw_constraint_list audiosense_constraints_rates = {
  6055. + .list = audiosense_pi_rate,
  6056. + .count = ARRAY_SIZE(audiosense_pi_rate),
  6057. +};
  6058. +
  6059. +static const unsigned int audiosense_pi_channels[] = {
  6060. + 2,
  6061. +};
  6062. +
  6063. +static struct snd_pcm_hw_constraint_list audiosense_constraints_ch = {
  6064. + .count = ARRAY_SIZE(audiosense_pi_channels),
  6065. + .list = audiosense_pi_channels,
  6066. + .mask = 0,
  6067. +};
  6068. +
  6069. +/* Setup DAPM widgets and paths */
  6070. +static const struct snd_soc_dapm_widget audiosense_pi_dapm_widgets[] = {
  6071. + SND_SOC_DAPM_HP("Headphone Jack", NULL),
  6072. + SND_SOC_DAPM_LINE("Line Out", NULL),
  6073. + SND_SOC_DAPM_LINE("Line In", NULL),
  6074. + SND_SOC_DAPM_INPUT("CM_L"),
  6075. + SND_SOC_DAPM_INPUT("CM_R"),
  6076. +};
  6077. +
  6078. +static const struct snd_soc_dapm_route audiosense_pi_audio_map[] = {
  6079. + /* Line Inputs are connected to
  6080. + * (IN1_L | IN1_R)
  6081. + * (IN2_L | IN2_R)
  6082. + * (IN3_L | IN3_R)
  6083. + */
  6084. + {"IN1_L", NULL, "Line In"},
  6085. + {"IN1_R", NULL, "Line In"},
  6086. + {"IN2_L", NULL, "Line In"},
  6087. + {"IN2_R", NULL, "Line In"},
  6088. + {"IN3_L", NULL, "Line In"},
  6089. + {"IN3_R", NULL, "Line In"},
  6090. +
  6091. + /* Mic is connected to IN2_L and IN2_R */
  6092. + {"Left ADC", NULL, "Mic Bias"},
  6093. + {"Right ADC", NULL, "Mic Bias"},
  6094. +
  6095. + /* Headphone connected to HPL, HPR */
  6096. + {"Headphone Jack", NULL, "HPL"},
  6097. + {"Headphone Jack", NULL, "HPR"},
  6098. +
  6099. + /* Speakers connected to LOL and LOR */
  6100. + {"Line Out", NULL, "LOL"},
  6101. + {"Line Out", NULL, "LOR"},
  6102. +};
  6103. +
  6104. +static int audiosense_pi_card_init(struct snd_soc_pcm_runtime *rtd)
  6105. +{
  6106. + /* TODO: init of the codec specific dapm data, ignore suspend/resume */
  6107. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  6108. +
  6109. + snd_soc_component_update_bits(component, AIC32X4_MICBIAS, 0x78,
  6110. + AIC32X4_MICBIAS_LDOIN |
  6111. + AIC32X4_MICBIAS_2075V);
  6112. + snd_soc_component_update_bits(component, AIC32X4_PWRCFG, 0x08,
  6113. + AIC32X4_AVDDWEAKDISABLE);
  6114. + snd_soc_component_update_bits(component, AIC32X4_LDOCTL, 0x01,
  6115. + AIC32X4_LDOCTLEN);
  6116. +
  6117. + return 0;
  6118. +}
  6119. +
  6120. +static int audiosense_pi_card_hw_params(
  6121. + struct snd_pcm_substream *substream,
  6122. + struct snd_pcm_hw_params *params)
  6123. +{
  6124. + int ret = 0;
  6125. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  6126. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  6127. +
  6128. + /* Set the codec system clock, there is a 12 MHz XTAL on the board */
  6129. + ret = snd_soc_dai_set_sysclk(codec_dai, AIC32X4_SYSCLK_XTAL,
  6130. + 12000000, SND_SOC_CLOCK_IN);
  6131. + if (ret) {
  6132. + dev_err(rtd->card->dev,
  6133. + "could not set codec driver clock params\n");
  6134. + return ret;
  6135. + }
  6136. + return 0;
  6137. +}
  6138. +
  6139. +static int audiosense_pi_card_startup(struct snd_pcm_substream *substream)
  6140. +{
  6141. + struct snd_pcm_runtime *runtime = substream->runtime;
  6142. +
  6143. + /*
  6144. + * Set codec to 48Khz Sampling, Stereo I/O and 16 bit audio
  6145. + */
  6146. + runtime->hw.channels_max = 2;
  6147. + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
  6148. + &audiosense_constraints_ch);
  6149. +
  6150. + runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
  6151. + snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
  6152. +
  6153. +
  6154. + snd_pcm_hw_constraint_list(substream->runtime, 0,
  6155. + SNDRV_PCM_HW_PARAM_RATE,
  6156. + &audiosense_constraints_rates);
  6157. + return 0;
  6158. +}
  6159. +
  6160. +static struct snd_soc_ops audiosense_pi_card_ops = {
  6161. + .startup = audiosense_pi_card_startup,
  6162. + .hw_params = audiosense_pi_card_hw_params,
  6163. +};
  6164. +
  6165. +SND_SOC_DAILINK_DEFS(audiosense_pi,
  6166. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  6167. + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic32x4.1-0018", "tlv320aic32x4-hifi")),
  6168. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  6169. +
  6170. +static struct snd_soc_dai_link audiosense_pi_card_dai[] = {
  6171. + {
  6172. + .name = "TLV320AIC3204 Audio",
  6173. + .stream_name = "TLV320AIC3204 Hifi Audio",
  6174. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  6175. + SND_SOC_DAIFMT_CBM_CFM,
  6176. + .ops = &audiosense_pi_card_ops,
  6177. + .init = audiosense_pi_card_init,
  6178. + SND_SOC_DAILINK_REG(audiosense_pi),
  6179. + },
  6180. +};
  6181. +
  6182. +static struct snd_soc_card audiosense_pi_card = {
  6183. + .name = "audiosense-pi",
  6184. + .driver_name = "audiosense-pi",
  6185. + .dai_link = audiosense_pi_card_dai,
  6186. + .owner = THIS_MODULE,
  6187. + .num_links = ARRAY_SIZE(audiosense_pi_card_dai),
  6188. + .dapm_widgets = audiosense_pi_dapm_widgets,
  6189. + .num_dapm_widgets = ARRAY_SIZE(audiosense_pi_dapm_widgets),
  6190. + .dapm_routes = audiosense_pi_audio_map,
  6191. + .num_dapm_routes = ARRAY_SIZE(audiosense_pi_audio_map),
  6192. +};
  6193. +
  6194. +static int audiosense_pi_card_probe(struct platform_device *pdev)
  6195. +{
  6196. + int ret = 0;
  6197. + struct snd_soc_card *card = &audiosense_pi_card;
  6198. + struct snd_soc_dai_link *dai = &audiosense_pi_card_dai[0];
  6199. + struct device_node *i2s_node = pdev->dev.of_node;
  6200. +
  6201. + card->dev = &pdev->dev;
  6202. +
  6203. + if (!dai) {
  6204. + dev_err(&pdev->dev, "DAI not found. Missing or Invalid\n");
  6205. + return -EINVAL;
  6206. + }
  6207. +
  6208. + i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0);
  6209. + if (!i2s_node) {
  6210. + dev_err(&pdev->dev,
  6211. + "Property 'i2s-controller' missing or invalid\n");
  6212. + return -EINVAL;
  6213. + }
  6214. +
  6215. + dai->cpus->dai_name = NULL;
  6216. + dai->cpus->of_node = i2s_node;
  6217. + dai->platforms->name = NULL;
  6218. + dai->platforms->of_node = i2s_node;
  6219. +
  6220. + of_node_put(i2s_node);
  6221. +
  6222. + ret = snd_soc_register_card(card);
  6223. + if (ret && ret != -EPROBE_DEFER)
  6224. + dev_err(&pdev->dev,
  6225. + "snd_soc_register_card() failed: %d\n", ret);
  6226. +
  6227. + return ret;
  6228. +}
  6229. +
  6230. +static int audiosense_pi_card_remove(struct platform_device *pdev)
  6231. +{
  6232. + struct snd_soc_card *card = platform_get_drvdata(pdev);
  6233. +
  6234. + snd_soc_unregister_card(card);
  6235. + return 0;
  6236. +}
  6237. +
  6238. +static const struct of_device_id audiosense_pi_card_of_match[] = {
  6239. + { .compatible = "as,audiosense-pi", },
  6240. + {},
  6241. +};
  6242. +MODULE_DEVICE_TABLE(of, audiosense_pi_card_of_match);
  6243. +
  6244. +static struct platform_driver audiosense_pi_card_driver = {
  6245. + .driver = {
  6246. + .name = "audiosense-snd-card",
  6247. + .owner = THIS_MODULE,
  6248. + .of_match_table = audiosense_pi_card_of_match,
  6249. + },
  6250. + .probe = audiosense_pi_card_probe,
  6251. + .remove = audiosense_pi_card_remove,
  6252. +};
  6253. +
  6254. +module_platform_driver(audiosense_pi_card_driver);
  6255. +
  6256. +MODULE_AUTHOR("Bhargav AK <[email protected]>");
  6257. +MODULE_DESCRIPTION("ASoC Driver for TLV320AIC3204 Audio");
  6258. +MODULE_LICENSE("GPL v2");
  6259. +MODULE_ALIAS("platform:audiosense-pi");
  6260. +
  6261. --- a/sound/soc/bcm/bcm2835-i2s.c
  6262. +++ b/sound/soc/bcm/bcm2835-i2s.c
  6263. @@ -30,7 +30,6 @@
  6264. #include <linux/init.h>
  6265. #include <linux/io.h>
  6266. #include <linux/module.h>
  6267. -#include <linux/of_address.h>
  6268. #include <linux/slab.h>
  6269. #include <sound/core.h>
  6270. @@ -830,8 +829,7 @@ static int bcm2835_i2s_probe(struct plat
  6271. struct bcm2835_i2s_dev *dev;
  6272. int ret;
  6273. void __iomem *base;
  6274. - const __be32 *addr;
  6275. - dma_addr_t dma_base;
  6276. + struct resource *res;
  6277. dev = devm_kzalloc(&pdev->dev, sizeof(*dev),
  6278. GFP_KERNEL);
  6279. @@ -846,7 +844,7 @@ static int bcm2835_i2s_probe(struct plat
  6280. "could not get clk\n");
  6281. /* Request ioarea */
  6282. - base = devm_platform_ioremap_resource(pdev, 0);
  6283. + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
  6284. if (IS_ERR(base))
  6285. return PTR_ERR(base);
  6286. @@ -855,19 +853,11 @@ static int bcm2835_i2s_probe(struct plat
  6287. if (IS_ERR(dev->i2s_regmap))
  6288. return PTR_ERR(dev->i2s_regmap);
  6289. - /* Set the DMA address - we have to parse DT ourselves */
  6290. - addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL);
  6291. - if (!addr) {
  6292. - dev_err(&pdev->dev, "could not get DMA-register address\n");
  6293. - return -EINVAL;
  6294. - }
  6295. - dma_base = be32_to_cpup(addr);
  6296. -
  6297. dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr =
  6298. - dma_base + BCM2835_I2S_FIFO_A_REG;
  6299. + res->start + BCM2835_I2S_FIFO_A_REG;
  6300. dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr =
  6301. - dma_base + BCM2835_I2S_FIFO_A_REG;
  6302. + res->start + BCM2835_I2S_FIFO_A_REG;
  6303. /* Set the bus width */
  6304. dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width =
  6305. --- /dev/null
  6306. +++ b/sound/soc/bcm/chipdip-dac.c
  6307. @@ -0,0 +1,275 @@
  6308. +/*
  6309. + * ASoC Driver for ChipDip DAC
  6310. + *
  6311. + * Author: Evgenij Sapunov
  6312. + * Copyright 2021
  6313. + * based on code by Milan Neskovic <[email protected]>
  6314. + * based on code by Jaikumar <[email protected]>
  6315. + *
  6316. + * Thanks to Phil Elwell (pelwell) for help.
  6317. + *
  6318. + * This program is free software; you can redistribute it and/or
  6319. + * modify it under the terms of the GNU General Public License
  6320. + * version 2 as published by the Free Software Foundation.
  6321. + *
  6322. + * This program is distributed in the hope that it will be useful, but
  6323. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  6324. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  6325. + * General Public License for more details.
  6326. + */
  6327. +
  6328. +#include <linux/module.h>
  6329. +#include <linux/gpio/consumer.h>
  6330. +#include <linux/platform_device.h>
  6331. +#include <linux/delay.h>
  6332. +
  6333. +#include <sound/core.h>
  6334. +#include <sound/pcm.h>
  6335. +#include <sound/pcm_params.h>
  6336. +#include <sound/soc.h>
  6337. +#include <sound/jack.h>
  6338. +
  6339. +#define SR_BIT_0 0 //sample rate bits
  6340. +#define SR_BIT_1 1
  6341. +#define SR_BIT_2 2
  6342. +#define BD_BIT_0 3 //bit depth bits
  6343. +#define BD_BIT_1 4
  6344. +
  6345. +#define SAMPLE_RATE_MASK_44_1 0
  6346. +#define SAMPLE_RATE_MASK_48 (1 << SR_BIT_0)
  6347. +#define SAMPLE_RATE_MASK_88_2 ((1 << SR_BIT_2) | (1 << SR_BIT_1))
  6348. +#define SAMPLE_RATE_MASK_96 (1 << SR_BIT_1)
  6349. +#define SAMPLE_RATE_MASK_176_4 ((1 << SR_BIT_2) | (1 << SR_BIT_1) | (1 << SR_BIT_0))
  6350. +#define SAMPLE_RATE_MASK_192 ((1 << SR_BIT_1) | (1 << SR_BIT_0))
  6351. +#define SAMPLE_RATE_MASK ((1 << SR_BIT_2) | (1 << SR_BIT_1) | (1 << SR_BIT_0))
  6352. +
  6353. +#define BIT_DEPTH_MASK_16 0
  6354. +#define BIT_DEPTH_MASK_24 (1 << BD_BIT_0)
  6355. +#define BIT_DEPTH_MASK_32 (1 << BD_BIT_1)
  6356. +#define BIT_DEPTH_MASK ((1 << BD_BIT_1) | (1 << BD_BIT_0))
  6357. +
  6358. +#define MUTE_ACTIVE 0
  6359. +#define MUTE_NOT_ACTIVE 1
  6360. +
  6361. +#define HW_PARAMS_GPIO_COUNT 5
  6362. +
  6363. +static struct gpio_desc *mute_gpio;
  6364. +static struct gpio_desc *sdwn_gpio;
  6365. +static struct gpio_desc *hw_params_gpios[HW_PARAMS_GPIO_COUNT];
  6366. +static int current_width;
  6367. +static int current_rate;
  6368. +
  6369. +static void snd_rpi_chipdip_dac_gpio_array_set(int value);
  6370. +static void snd_rpi_chipdip_dac_gpio_set(struct gpio_desc *gpio_item, int value);
  6371. +
  6372. +static void snd_rpi_chipdip_dac_gpio_array_set(int value)
  6373. +{
  6374. + int i = 0;
  6375. +
  6376. + for (i = 0; i < HW_PARAMS_GPIO_COUNT; i++)
  6377. + snd_rpi_chipdip_dac_gpio_set(hw_params_gpios[i], ((value >> i) & 1));
  6378. +}
  6379. +
  6380. +static void snd_rpi_chipdip_dac_gpio_set(struct gpio_desc *gpio_item, int value)
  6381. +{
  6382. + if (gpio_item)
  6383. + gpiod_set_value_cansleep(gpio_item, value);
  6384. +}
  6385. +
  6386. +static int snd_rpi_chipdip_dac_init(struct snd_soc_pcm_runtime *rtd)
  6387. +{
  6388. + return 0;
  6389. +}
  6390. +
  6391. +static int snd_rpi_chipdip_dac_hw_params(struct snd_pcm_substream *substream,
  6392. + struct snd_pcm_hw_params *params)
  6393. +{
  6394. + int ret = 0;
  6395. + int gpio_change_pending = 0;
  6396. + int sample_rate_state = 0;
  6397. + int bit_depth_state = 0;
  6398. + int param_value = params_width(params);
  6399. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  6400. +
  6401. + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), 2 * 32);
  6402. +
  6403. + if (current_width != param_value) {
  6404. + current_width = param_value;
  6405. + gpio_change_pending = 1;
  6406. +
  6407. + switch (param_value) {
  6408. + case 16:
  6409. + bit_depth_state = BIT_DEPTH_MASK_16;
  6410. + break;
  6411. + case 24:
  6412. + bit_depth_state = BIT_DEPTH_MASK_24;
  6413. + break;
  6414. + case 32:
  6415. + bit_depth_state = BIT_DEPTH_MASK_32;
  6416. + break;
  6417. + default:
  6418. + return -EINVAL;
  6419. + }
  6420. + }
  6421. +
  6422. + param_value = params_rate(params);
  6423. + if (current_rate != param_value) {
  6424. + current_rate = param_value;
  6425. + gpio_change_pending = 1;
  6426. +
  6427. + switch (param_value) {
  6428. + case 44100:
  6429. + sample_rate_state = SAMPLE_RATE_MASK_44_1;
  6430. + break;
  6431. + case 48000:
  6432. + sample_rate_state = SAMPLE_RATE_MASK_48;
  6433. + break;
  6434. + case 88200:
  6435. + sample_rate_state = SAMPLE_RATE_MASK_88_2;
  6436. + break;
  6437. + case 96000:
  6438. + sample_rate_state = SAMPLE_RATE_MASK_96;
  6439. + break;
  6440. + case 176400:
  6441. + sample_rate_state = SAMPLE_RATE_MASK_176_4;
  6442. + break;
  6443. + case 192000:
  6444. + sample_rate_state = SAMPLE_RATE_MASK_192;
  6445. + break;
  6446. + default:
  6447. + return -EINVAL;
  6448. + }
  6449. + }
  6450. +
  6451. + if (gpio_change_pending) {
  6452. + snd_rpi_chipdip_dac_gpio_set(mute_gpio, MUTE_ACTIVE);
  6453. + snd_rpi_chipdip_dac_gpio_array_set(bit_depth_state | sample_rate_state);
  6454. + msleep(300);
  6455. + snd_rpi_chipdip_dac_gpio_set(mute_gpio, MUTE_NOT_ACTIVE);
  6456. + }
  6457. +
  6458. + return ret;
  6459. +}
  6460. +
  6461. +static int snd_rpi_chipdip_dac_startup(struct snd_pcm_substream *substream)
  6462. +{
  6463. + return 0;
  6464. +}
  6465. +
  6466. +static void snd_rpi_chipdip_dac_shutdown(struct snd_pcm_substream *substream)
  6467. +{
  6468. +
  6469. +}
  6470. +
  6471. +/* machine stream operations */
  6472. +static struct snd_soc_ops snd_rpi_chipdip_dac_ops = {
  6473. + .hw_params = snd_rpi_chipdip_dac_hw_params,
  6474. + .startup = snd_rpi_chipdip_dac_startup,
  6475. + .shutdown = snd_rpi_chipdip_dac_shutdown,
  6476. +};
  6477. +
  6478. +SND_SOC_DAILINK_DEFS(hifi,
  6479. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  6480. + DAILINK_COMP_ARRAY(COMP_CODEC("spdif-transmitter", "dit-hifi")),
  6481. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  6482. +
  6483. +static struct snd_soc_dai_link snd_rpi_chipdip_dac_dai[] = {
  6484. +{
  6485. + .name = "ChipDip DAC",
  6486. + .stream_name = "ChipDip DAC HiFi",
  6487. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  6488. + SND_SOC_DAIFMT_CBM_CFM,
  6489. + .ops = &snd_rpi_chipdip_dac_ops,
  6490. + .init = snd_rpi_chipdip_dac_init,
  6491. + SND_SOC_DAILINK_REG(hifi),
  6492. +},
  6493. +};
  6494. +
  6495. +/* audio machine driver */
  6496. +static struct snd_soc_card snd_rpi_chipdip_dac = {
  6497. + .name = "ChipDipDAC",
  6498. + .driver_name = "ChipdipDac",
  6499. + .owner = THIS_MODULE,
  6500. + .dai_link = snd_rpi_chipdip_dac_dai,
  6501. + .num_links = ARRAY_SIZE(snd_rpi_chipdip_dac_dai),
  6502. +};
  6503. +
  6504. +static int snd_rpi_chipdip_dac_probe(struct platform_device *pdev)
  6505. +{
  6506. + int ret = 0;
  6507. + int i = 0;
  6508. +
  6509. + snd_rpi_chipdip_dac.dev = &pdev->dev;
  6510. +
  6511. + if (pdev->dev.of_node) {
  6512. + struct device_node *i2s_node;
  6513. + struct snd_soc_dai_link *dai = &snd_rpi_chipdip_dac_dai[0];
  6514. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  6515. + "i2s-controller", 0);
  6516. +
  6517. + if (i2s_node) {
  6518. + dai->cpus->dai_name = NULL;
  6519. + dai->cpus->of_node = i2s_node;
  6520. + dai->platforms->name = NULL;
  6521. + dai->platforms->of_node = i2s_node;
  6522. + }
  6523. + }
  6524. +
  6525. + hw_params_gpios[SR_BIT_0] = devm_gpiod_get_optional(&pdev->dev, "sr0", GPIOD_OUT_LOW);
  6526. + hw_params_gpios[SR_BIT_1] = devm_gpiod_get_optional(&pdev->dev, "sr1", GPIOD_OUT_LOW);
  6527. + hw_params_gpios[SR_BIT_2] = devm_gpiod_get_optional(&pdev->dev, "sr2", GPIOD_OUT_LOW);
  6528. + hw_params_gpios[BD_BIT_0] = devm_gpiod_get_optional(&pdev->dev, "res0", GPIOD_OUT_LOW);
  6529. + hw_params_gpios[BD_BIT_1] = devm_gpiod_get_optional(&pdev->dev, "res1", GPIOD_OUT_LOW);
  6530. + mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_LOW);
  6531. + sdwn_gpio = devm_gpiod_get_optional(&pdev->dev, "sdwn", GPIOD_OUT_HIGH);
  6532. +
  6533. + for (i = 0; i < HW_PARAMS_GPIO_COUNT; i++) {
  6534. + if (IS_ERR(hw_params_gpios[i])) {
  6535. + ret = PTR_ERR(hw_params_gpios[i]);
  6536. + dev_err(&pdev->dev, "failed to get hw_params gpio: %d\n", ret);
  6537. + return ret;
  6538. + }
  6539. + }
  6540. +
  6541. + if (IS_ERR(mute_gpio)) {
  6542. + ret = PTR_ERR(mute_gpio);
  6543. + dev_err(&pdev->dev, "failed to get mute gpio: %d\n", ret);
  6544. + return ret;
  6545. + }
  6546. +
  6547. + if (IS_ERR(sdwn_gpio)) {
  6548. + ret = PTR_ERR(sdwn_gpio);
  6549. + dev_err(&pdev->dev, "failed to get sdwn gpio: %d\n", ret);
  6550. + return ret;
  6551. + }
  6552. +
  6553. + snd_rpi_chipdip_dac_gpio_set(sdwn_gpio, 1);
  6554. +
  6555. + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_chipdip_dac);
  6556. + if (ret && ret != -EPROBE_DEFER)
  6557. + dev_err(&pdev->dev,
  6558. + "snd_soc_register_card() failed: %d\n", ret);
  6559. +
  6560. + return ret;
  6561. +}
  6562. +
  6563. +static const struct of_device_id snd_rpi_chipdip_dac_of_match[] = {
  6564. + { .compatible = "chipdip,chipdip-dac", },
  6565. + {},
  6566. +};
  6567. +MODULE_DEVICE_TABLE(of, snd_rpi_chipdip_dac_of_match);
  6568. +
  6569. +static struct platform_driver snd_rpi_chipdip_dac_driver = {
  6570. + .driver = {
  6571. + .name = "snd-rpi-chipdip-dac",
  6572. + .owner = THIS_MODULE,
  6573. + .of_match_table = snd_rpi_chipdip_dac_of_match,
  6574. + },
  6575. + .probe = snd_rpi_chipdip_dac_probe,
  6576. +};
  6577. +
  6578. +module_platform_driver(snd_rpi_chipdip_dac_driver);
  6579. +
  6580. +MODULE_AUTHOR("Evgenij Sapunov <[email protected]>");
  6581. +MODULE_DESCRIPTION("ASoC Driver for ChipDip DAC");
  6582. +MODULE_LICENSE("GPL v2");
  6583. --- /dev/null
  6584. +++ b/sound/soc/bcm/dacberry400.c
  6585. @@ -0,0 +1,259 @@
  6586. +/*
  6587. + * ASoC Driver for Dacberry400 soundcard
  6588. + * Author:
  6589. + * Ashish Vara<[email protected]>
  6590. + * Copyright 2022
  6591. + *
  6592. + * This program is free software; you can redistribute it and/or
  6593. + * modify it under the terms of the GNU General Public License
  6594. + * version 2 as published by the Free Software Foundation.
  6595. + *
  6596. + * This program is distributed in the hope that it will be useful, but
  6597. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  6598. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  6599. + * General Public License for more details.
  6600. + */
  6601. +
  6602. +#include <linux/module.h>
  6603. +#include <linux/gpio/consumer.h>
  6604. +#include <linux/platform_device.h>
  6605. +#include <sound/core.h>
  6606. +#include <sound/pcm.h>
  6607. +#include <sound/pcm_params.h>
  6608. +#include <sound/soc.h>
  6609. +#include <sound/jack.h>
  6610. +#include <linux/i2c.h>
  6611. +#include <linux/acpi.h>
  6612. +#include <linux/slab.h>
  6613. +#include "../sound/soc/codecs/tlv320aic3x.h"
  6614. +
  6615. +static const struct snd_kcontrol_new dacberry400_controls[] = {
  6616. + SOC_DAPM_PIN_SWITCH("MIC Jack"),
  6617. + SOC_DAPM_PIN_SWITCH("Line In"),
  6618. + SOC_DAPM_PIN_SWITCH("Line Out"),
  6619. + SOC_DAPM_PIN_SWITCH("Headphone Jack"),
  6620. +};
  6621. +
  6622. +static const struct snd_soc_dapm_widget dacberry400_widgets[] = {
  6623. + SND_SOC_DAPM_HP("Headphone Jack", NULL),
  6624. + SND_SOC_DAPM_MIC("MIC Jack", NULL),
  6625. + SND_SOC_DAPM_LINE("Line In", NULL),
  6626. + SND_SOC_DAPM_LINE("Line Out", NULL),
  6627. +};
  6628. +
  6629. +static const struct snd_soc_dapm_route dacberry400_audio_map[] = {
  6630. + {"Headphone Jack", NULL, "HPLOUT"},
  6631. + {"Headphone Jack", NULL, "HPROUT"},
  6632. +
  6633. + {"LINE1L", NULL, "Line In"},
  6634. + {"LINE1R", NULL, "Line In"},
  6635. +
  6636. + {"Line Out", NULL, "LLOUT"},
  6637. + {"Line Out", NULL, "RLOUT"},
  6638. +
  6639. + {"MIC3L", NULL, "MIC Jack"},
  6640. + {"MIC3R", NULL, "MIC Jack"},
  6641. +};
  6642. +
  6643. +static int snd_rpi_dacberry400_init(struct snd_soc_pcm_runtime *rtd)
  6644. +{
  6645. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  6646. + struct snd_soc_component *component = codec_dai->component;
  6647. + int ret;
  6648. +
  6649. + ret = snd_soc_dai_set_sysclk(codec_dai, 2, 12000000,
  6650. + SND_SOC_CLOCK_OUT);
  6651. +
  6652. + if (ret && ret != -ENOTSUPP)
  6653. + goto err;
  6654. +
  6655. + snd_soc_component_write(component, HPRCOM_CFG, 0x20);
  6656. + snd_soc_component_write(component, DACL1_2_HPLOUT_VOL, 0x80);
  6657. + snd_soc_component_write(component, DACR1_2_HPROUT_VOL, 0x80);
  6658. +err:
  6659. + return ret;
  6660. +}
  6661. +
  6662. +static int snd_rpi_dacberry400_set_bias_level(struct snd_soc_card *card,
  6663. + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
  6664. +{
  6665. + struct snd_soc_pcm_runtime *rtd;
  6666. + struct snd_soc_dai *codec_dai;
  6667. + struct snd_soc_component *component;
  6668. + struct dacberry_priv *aic3x;
  6669. + u8 hpcom_reg = 0;
  6670. +
  6671. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  6672. + codec_dai = asoc_rtd_to_codec(rtd, 0);
  6673. + component = codec_dai->component;
  6674. + aic3x = snd_soc_component_get_drvdata(component);
  6675. + if (dapm->dev != codec_dai->dev)
  6676. + return 0;
  6677. +
  6678. + switch (level) {
  6679. + case SND_SOC_BIAS_PREPARE:
  6680. + if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
  6681. + break;
  6682. + /* UNMUTE ADC/DAC */
  6683. + hpcom_reg = snd_soc_component_read(component, HPLCOM_CFG);
  6684. + snd_soc_component_write(component, HPLCOM_CFG, hpcom_reg | 0x20);
  6685. + snd_soc_component_write(component, LINE1R_2_RADC_CTRL, 0x04);
  6686. + snd_soc_component_write(component, LINE1L_2_LADC_CTRL, 0x04);
  6687. + snd_soc_component_write(component, LADC_VOL, 0x00);
  6688. + snd_soc_component_write(component, RADC_VOL, 0x00);
  6689. + pr_info("%s: unmute ADC/DAC\n", __func__);
  6690. + break;
  6691. +
  6692. + case SND_SOC_BIAS_STANDBY:
  6693. + if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
  6694. + break;
  6695. + /* MUTE ADC/DAC */
  6696. + snd_soc_component_write(component, LDAC_VOL, 0x80);
  6697. + snd_soc_component_write(component, RDAC_VOL, 0x80);
  6698. + snd_soc_component_write(component, LADC_VOL, 0x80);
  6699. + snd_soc_component_write(component, RADC_VOL, 0x80);
  6700. + snd_soc_component_write(component, LINE1R_2_RADC_CTRL, 0x00);
  6701. + snd_soc_component_write(component, LINE1L_2_LADC_CTRL, 0x00);
  6702. + snd_soc_component_write(component, HPLCOM_CFG, 0x00);
  6703. + pr_info("%s: mute ADC/DAC\n", __func__);
  6704. + break;
  6705. + default:
  6706. + break;
  6707. + }
  6708. +
  6709. + return 0;
  6710. +}
  6711. +
  6712. +static int snd_rpi_dacberry400_hw_params(struct snd_pcm_substream *substream,
  6713. + struct snd_pcm_hw_params *params)
  6714. +{
  6715. + int ret = 0;
  6716. + u8 data;
  6717. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  6718. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  6719. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  6720. + struct snd_soc_component *component = codec_dai->component;
  6721. + int fsref = (params_rate(params) % 11025 == 0) ? 44100 : 48000;
  6722. + int channels = params_channels(params);
  6723. + int width = 32;
  6724. + u8 clock = 0;
  6725. +
  6726. + data = (LDAC2LCH | RDAC2RCH);
  6727. + data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000;
  6728. + if (params_rate(params) >= 64000)
  6729. + data |= DUAL_RATE_MODE;
  6730. + ret = snd_soc_component_write(component, 0x7, data);
  6731. + width = params_width(params);
  6732. +
  6733. + clock = snd_soc_component_read(component, 2);
  6734. +
  6735. + ret = snd_soc_dai_set_bclk_ratio(cpu_dai, channels*width);
  6736. +
  6737. + return ret;
  6738. +}
  6739. +
  6740. +static const struct snd_soc_ops snd_rpi_dacberry400_ops = {
  6741. + .hw_params = snd_rpi_dacberry400_hw_params,
  6742. +};
  6743. +
  6744. +
  6745. +SND_SOC_DAILINK_DEFS(rpi_dacberry400,
  6746. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2835-i2s.0")),
  6747. + DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x.1-0018", "tlv320aic3x-hifi")),
  6748. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2835-i2s.0")));
  6749. +
  6750. +static struct snd_soc_dai_link snd_rpi_dacberry400_dai[] = {
  6751. +{
  6752. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  6753. + SND_SOC_DAIFMT_CBS_CFS,
  6754. + .init = snd_rpi_dacberry400_init,
  6755. + .ops = &snd_rpi_dacberry400_ops,
  6756. + .symmetric_rate = 1,
  6757. + SND_SOC_DAILINK_REG(rpi_dacberry400),
  6758. +},
  6759. +};
  6760. +
  6761. +static struct snd_soc_card snd_rpi_dacberry400 = {
  6762. + .owner = THIS_MODULE,
  6763. + .dai_link = snd_rpi_dacberry400_dai,
  6764. + .num_links = ARRAY_SIZE(snd_rpi_dacberry400_dai),
  6765. + .controls = dacberry400_controls,
  6766. + .num_controls = ARRAY_SIZE(dacberry400_controls),
  6767. + .dapm_widgets = dacberry400_widgets,
  6768. + .num_dapm_widgets = ARRAY_SIZE(dacberry400_widgets),
  6769. + .dapm_routes = dacberry400_audio_map,
  6770. + .num_dapm_routes = ARRAY_SIZE(dacberry400_audio_map),
  6771. + .set_bias_level = snd_rpi_dacberry400_set_bias_level,
  6772. +};
  6773. +
  6774. +static int snd_rpi_dacberry400_probe(struct platform_device *pdev)
  6775. +{
  6776. + int ret = 0;
  6777. +
  6778. + snd_rpi_dacberry400.dev = &pdev->dev;
  6779. +
  6780. + if (pdev->dev.of_node) {
  6781. + struct device_node *i2s_node;
  6782. + struct snd_soc_card *card = &snd_rpi_dacberry400;
  6783. + struct snd_soc_dai_link *dai = &snd_rpi_dacberry400_dai[0];
  6784. +
  6785. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  6786. + "i2s-controller", 0);
  6787. + if (i2s_node) {
  6788. + dai->cpus->dai_name = NULL;
  6789. + dai->cpus->of_node = i2s_node;
  6790. + dai->platforms->name = NULL;
  6791. + dai->platforms->of_node = i2s_node;
  6792. + of_node_put(i2s_node);
  6793. + }
  6794. +
  6795. + if (of_property_read_string(pdev->dev.of_node, "card_name",
  6796. + &card->name))
  6797. + card->name = "tlvaudioCODEC";
  6798. +
  6799. + if (of_property_read_string(pdev->dev.of_node, "dai_name",
  6800. + &dai->name))
  6801. + dai->name = "tlvaudio CODEC";
  6802. +
  6803. + }
  6804. +
  6805. + ret = snd_soc_register_card(&snd_rpi_dacberry400);
  6806. + if (ret) {
  6807. + if (ret != -EPROBE_DEFER)
  6808. + dev_err(&pdev->dev,
  6809. + "snd_soc_register_card() failed: %d\n", ret);
  6810. + return ret;
  6811. + }
  6812. +
  6813. + return 0;
  6814. +}
  6815. +
  6816. +static int snd_rpi_dacberry400_remove(struct platform_device *pdev)
  6817. +{
  6818. + snd_soc_unregister_card(&snd_rpi_dacberry400);
  6819. + return 0;
  6820. +}
  6821. +
  6822. +static const struct of_device_id dacberry400_match_id[] = {
  6823. + { .compatible = "osaelectronics,dacberry400",},
  6824. + {},
  6825. +};
  6826. +MODULE_DEVICE_TABLE(of, dacberry400_match_id);
  6827. +
  6828. +static struct platform_driver snd_rpi_dacberry400_driver = {
  6829. + .driver = {
  6830. + .name = "snd-rpi-dacberry400",
  6831. + .owner = THIS_MODULE,
  6832. + .of_match_table = dacberry400_match_id,
  6833. + },
  6834. + .probe = snd_rpi_dacberry400_probe,
  6835. + .remove = snd_rpi_dacberry400_remove,
  6836. +};
  6837. +
  6838. +module_platform_driver(snd_rpi_dacberry400_driver);
  6839. +
  6840. +MODULE_AUTHOR("Ashish Vara");
  6841. +MODULE_DESCRIPTION("Dacberry400 sound card driver");
  6842. +MODULE_LICENSE("GPL");
  6843. +MODULE_ALIAS("platform:dacberry400");
  6844. +MODULE_SOFTDEP("pre: snd-soc-tlv320aic3x");
  6845. --- /dev/null
  6846. +++ b/sound/soc/bcm/digidac1-soundcard.c
  6847. @@ -0,0 +1,421 @@
  6848. +/*
  6849. + * ASoC Driver for RRA DigiDAC1
  6850. + * Copyright 2016
  6851. + * Author: José M. Tasende <[email protected]>
  6852. + * based on the HifiBerry DAC driver by Florian Meier <[email protected]>
  6853. + * and the Wolfson card driver by Nikesh Oswal, <[email protected]>
  6854. + * This program is free software; you can redistribute it and/or
  6855. + * modify it under the terms of the GNU General Public License
  6856. + * version 2 as published by the Free Software Foundation.
  6857. + *
  6858. + * This program is distributed in the hope that it will be useful, but
  6859. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  6860. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  6861. + * General Public License for more details.
  6862. + */
  6863. +
  6864. +#include <linux/module.h>
  6865. +#include <linux/platform_device.h>
  6866. +#include <linux/i2c.h>
  6867. +#include <sound/core.h>
  6868. +#include <sound/pcm.h>
  6869. +#include <sound/pcm_params.h>
  6870. +#include <sound/soc.h>
  6871. +#include <sound/jack.h>
  6872. +#include <sound/soc-dapm.h>
  6873. +#include <sound/tlv.h>
  6874. +#include <linux/regulator/consumer.h>
  6875. +
  6876. +#include "../codecs/wm8804.h"
  6877. +#include "../codecs/wm8741.h"
  6878. +
  6879. +#define WM8741_NUM_SUPPLIES 2
  6880. +
  6881. +/* codec private data */
  6882. +struct wm8741_priv {
  6883. + struct wm8741_platform_data pdata;
  6884. + struct regmap *regmap;
  6885. + struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
  6886. + unsigned int sysclk;
  6887. + const struct snd_pcm_hw_constraint_list *sysclk_constraints;
  6888. +};
  6889. +
  6890. +static int samplerate = 44100;
  6891. +
  6892. +/* New Alsa Controls not exposed by original wm8741 codec driver */
  6893. +/* in actual driver the att. adjustment is wrong because */
  6894. +/* this DAC has a coarse attenuation register with 4dB steps */
  6895. +/* and a fine level register with 0.125dB steps */
  6896. +/* each register has 32 steps so combining both we have 1024 steps */
  6897. +/* of 0.125 dB. */
  6898. +/* The original level controls from driver are removed at startup */
  6899. +/* and replaced by the corrected ones. */
  6900. +/* The same wm8741 driver can be used for wm8741 and wm8742 devices */
  6901. +
  6902. +static const DECLARE_TLV_DB_SCALE(dac_tlv_fine, 0, 13, 0);
  6903. +static const DECLARE_TLV_DB_SCALE(dac_tlv_coarse, -12700, 400, 1);
  6904. +static const char *w8741_dither[4] = {"Off", "RPDF", "TPDF", "HPDF"};
  6905. +static const char *w8741_filter[5] = {
  6906. + "Type 1", "Type 2", "Type 3", "Type 4", "Type 5"};
  6907. +static const char *w8741_switch[2] = {"Off", "On"};
  6908. +static const struct soc_enum w8741_enum[] = {
  6909. +SOC_ENUM_SINGLE(WM8741_MODE_CONTROL_2, 0, 4, w8741_dither),/* dithering type */
  6910. +SOC_ENUM_SINGLE(WM8741_FILTER_CONTROL, 0, 5, w8741_filter),/* filter type */
  6911. +SOC_ENUM_SINGLE(WM8741_FORMAT_CONTROL, 6, 2, w8741_switch),/* phase invert */
  6912. +SOC_ENUM_SINGLE(WM8741_VOLUME_CONTROL, 0, 2, w8741_switch),/* volume ramp */
  6913. +SOC_ENUM_SINGLE(WM8741_VOLUME_CONTROL, 3, 2, w8741_switch),/* soft mute */
  6914. +};
  6915. +
  6916. +static const struct snd_kcontrol_new w8741_snd_controls_stereo[] = {
  6917. +SOC_DOUBLE_R_TLV("DAC Fine Playback Volume", WM8741_DACLLSB_ATTENUATION,
  6918. + WM8741_DACRLSB_ATTENUATION, 0, 31, 1, dac_tlv_fine),
  6919. +SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8741_DACLMSB_ATTENUATION,
  6920. + WM8741_DACRMSB_ATTENUATION, 0, 31, 1, dac_tlv_coarse),
  6921. +SOC_ENUM("DAC Dither", w8741_enum[0]),
  6922. +SOC_ENUM("DAC Digital Filter", w8741_enum[1]),
  6923. +SOC_ENUM("DAC Phase Invert", w8741_enum[2]),
  6924. +SOC_ENUM("DAC Volume Ramp", w8741_enum[3]),
  6925. +SOC_ENUM("DAC Soft Mute", w8741_enum[4]),
  6926. +};
  6927. +
  6928. +static const struct snd_kcontrol_new w8741_snd_controls_mono_left[] = {
  6929. +SOC_SINGLE_TLV("DAC Fine Playback Volume", WM8741_DACLLSB_ATTENUATION,
  6930. + 0, 31, 0, dac_tlv_fine),
  6931. +SOC_SINGLE_TLV("Digital Playback Volume", WM8741_DACLMSB_ATTENUATION,
  6932. + 0, 31, 1, dac_tlv_coarse),
  6933. +SOC_ENUM("DAC Dither", w8741_enum[0]),
  6934. +SOC_ENUM("DAC Digital Filter", w8741_enum[1]),
  6935. +SOC_ENUM("DAC Phase Invert", w8741_enum[2]),
  6936. +SOC_ENUM("DAC Volume Ramp", w8741_enum[3]),
  6937. +SOC_ENUM("DAC Soft Mute", w8741_enum[4]),
  6938. +};
  6939. +
  6940. +static const struct snd_kcontrol_new w8741_snd_controls_mono_right[] = {
  6941. +SOC_SINGLE_TLV("DAC Fine Playback Volume", WM8741_DACRLSB_ATTENUATION,
  6942. + 0, 31, 0, dac_tlv_fine),
  6943. +SOC_SINGLE_TLV("Digital Playback Volume", WM8741_DACRMSB_ATTENUATION,
  6944. + 0, 31, 1, dac_tlv_coarse),
  6945. +SOC_ENUM("DAC Dither", w8741_enum[0]),
  6946. +SOC_ENUM("DAC Digital Filter", w8741_enum[1]),
  6947. +SOC_ENUM("DAC Phase Invert", w8741_enum[2]),
  6948. +SOC_ENUM("DAC Volume Ramp", w8741_enum[3]),
  6949. +SOC_ENUM("DAC Soft Mute", w8741_enum[4]),
  6950. +};
  6951. +
  6952. +static int w8741_add_controls(struct snd_soc_component *component)
  6953. +{
  6954. + struct wm8741_priv *wm8741 = snd_soc_component_get_drvdata(component);
  6955. +
  6956. + switch (wm8741->pdata.diff_mode) {
  6957. + case WM8741_DIFF_MODE_STEREO:
  6958. + case WM8741_DIFF_MODE_STEREO_REVERSED:
  6959. + snd_soc_add_component_controls(component,
  6960. + w8741_snd_controls_stereo,
  6961. + ARRAY_SIZE(w8741_snd_controls_stereo));
  6962. + break;
  6963. + case WM8741_DIFF_MODE_MONO_LEFT:
  6964. + snd_soc_add_component_controls(component,
  6965. + w8741_snd_controls_mono_left,
  6966. + ARRAY_SIZE(w8741_snd_controls_mono_left));
  6967. + break;
  6968. + case WM8741_DIFF_MODE_MONO_RIGHT:
  6969. + snd_soc_add_component_controls(component,
  6970. + w8741_snd_controls_mono_right,
  6971. + ARRAY_SIZE(w8741_snd_controls_mono_right));
  6972. + break;
  6973. + default:
  6974. + return -EINVAL;
  6975. + }
  6976. +
  6977. + return 0;
  6978. +}
  6979. +
  6980. +static int digidac1_soundcard_init(struct snd_soc_pcm_runtime *rtd)
  6981. +{
  6982. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  6983. + struct snd_soc_card *card = rtd->card;
  6984. + struct snd_soc_pcm_runtime *wm8741_rtd;
  6985. + struct snd_soc_component *wm8741_component;
  6986. + struct snd_card *sound_card = card->snd_card;
  6987. + struct snd_kcontrol *kctl;
  6988. + int ret;
  6989. +
  6990. + wm8741_rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[1]);
  6991. + if (!wm8741_rtd) {
  6992. + dev_warn(card->dev, "digidac1_soundcard_init: couldn't get wm8741 rtd\n");
  6993. + return -EFAULT;
  6994. + }
  6995. + wm8741_component = asoc_rtd_to_codec(wm8741_rtd, 0)->component;
  6996. + ret = w8741_add_controls(wm8741_component);
  6997. + if (ret < 0)
  6998. + dev_warn(card->dev, "Failed to add new wm8741 controls: %d\n",
  6999. + ret);
  7000. +
  7001. + /* enable TX output */
  7002. + snd_soc_component_update_bits(component, WM8804_PWRDN, 0x4, 0x0);
  7003. +
  7004. + kctl = snd_soc_card_get_kcontrol(card,
  7005. + "Playback Volume");
  7006. + if (kctl) {
  7007. + kctl->vd[0].access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
  7008. + snd_ctl_remove(sound_card, kctl);
  7009. + }
  7010. + kctl = snd_soc_card_get_kcontrol(card,
  7011. + "Fine Playback Volume");
  7012. + if (kctl) {
  7013. + kctl->vd[0].access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
  7014. + snd_ctl_remove(sound_card, kctl);
  7015. + }
  7016. + return 0;
  7017. +}
  7018. +
  7019. +static int digidac1_soundcard_startup(struct snd_pcm_substream *substream)
  7020. +{
  7021. + /* turn on wm8804 digital output */
  7022. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  7023. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  7024. + struct snd_soc_card *card = rtd->card;
  7025. + struct snd_soc_pcm_runtime *wm8741_rtd;
  7026. + struct snd_soc_component *wm8741_component;
  7027. +
  7028. + snd_soc_component_update_bits(component, WM8804_PWRDN, 0x3c, 0x00);
  7029. + wm8741_rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[1]);
  7030. + if (!wm8741_rtd) {
  7031. + dev_warn(card->dev, "digidac1_soundcard_startup: couldn't get WM8741 rtd\n");
  7032. + return -EFAULT;
  7033. + }
  7034. + wm8741_component = asoc_rtd_to_codec(wm8741_rtd, 0)->component;
  7035. +
  7036. + /* latch wm8741 level */
  7037. + snd_soc_component_update_bits(wm8741_component, WM8741_DACLLSB_ATTENUATION,
  7038. + WM8741_UPDATELL, WM8741_UPDATELL);
  7039. + snd_soc_component_update_bits(wm8741_component, WM8741_DACLMSB_ATTENUATION,
  7040. + WM8741_UPDATELM, WM8741_UPDATELM);
  7041. + snd_soc_component_update_bits(wm8741_component, WM8741_DACRLSB_ATTENUATION,
  7042. + WM8741_UPDATERL, WM8741_UPDATERL);
  7043. + snd_soc_component_update_bits(wm8741_component, WM8741_DACRMSB_ATTENUATION,
  7044. + WM8741_UPDATERM, WM8741_UPDATERM);
  7045. +
  7046. + return 0;
  7047. +}
  7048. +
  7049. +static void digidac1_soundcard_shutdown(struct snd_pcm_substream *substream)
  7050. +{
  7051. + /* turn off wm8804 digital output */
  7052. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  7053. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  7054. +
  7055. + snd_soc_component_update_bits(component, WM8804_PWRDN, 0x3c, 0x3c);
  7056. +}
  7057. +
  7058. +static int digidac1_soundcard_hw_params(struct snd_pcm_substream *substream,
  7059. + struct snd_pcm_hw_params *params)
  7060. +{
  7061. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  7062. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  7063. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  7064. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  7065. + struct snd_soc_card *card = rtd->card;
  7066. + struct snd_soc_pcm_runtime *wm8741_rtd;
  7067. + struct snd_soc_component *wm8741_component;
  7068. +
  7069. + int sysclk = 27000000;
  7070. + long mclk_freq = 0;
  7071. + int mclk_div = 1;
  7072. + int sampling_freq = 1;
  7073. + int ret;
  7074. +
  7075. + wm8741_rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[1]);
  7076. + if (!wm8741_rtd) {
  7077. + dev_warn(card->dev, "digidac1_soundcard_hw_params: couldn't get WM8741 rtd\n");
  7078. + return -EFAULT;
  7079. + }
  7080. + wm8741_component = asoc_rtd_to_codec(wm8741_rtd, 0)->component;
  7081. + samplerate = params_rate(params);
  7082. +
  7083. + if (samplerate <= 96000) {
  7084. + mclk_freq = samplerate*256;
  7085. + mclk_div = WM8804_MCLKDIV_256FS;
  7086. + } else {
  7087. + mclk_freq = samplerate*128;
  7088. + mclk_div = WM8804_MCLKDIV_128FS;
  7089. + }
  7090. +
  7091. + switch (samplerate) {
  7092. + case 32000:
  7093. + sampling_freq = 0x03;
  7094. + break;
  7095. + case 44100:
  7096. + sampling_freq = 0x00;
  7097. + break;
  7098. + case 48000:
  7099. + sampling_freq = 0x02;
  7100. + break;
  7101. + case 88200:
  7102. + sampling_freq = 0x08;
  7103. + break;
  7104. + case 96000:
  7105. + sampling_freq = 0x0a;
  7106. + break;
  7107. + case 176400:
  7108. + sampling_freq = 0x0c;
  7109. + break;
  7110. + case 192000:
  7111. + sampling_freq = 0x0e;
  7112. + break;
  7113. + default:
  7114. + dev_err(card->dev,
  7115. + "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n",
  7116. + samplerate);
  7117. + }
  7118. +
  7119. + snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div);
  7120. + snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq);
  7121. +
  7122. + ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
  7123. + sysclk, SND_SOC_CLOCK_OUT);
  7124. + if (ret < 0) {
  7125. + dev_err(card->dev,
  7126. + "Failed to set WM8804 SYSCLK: %d\n", ret);
  7127. + return ret;
  7128. + }
  7129. + /* Enable wm8804 TX output */
  7130. + snd_soc_component_update_bits(component, WM8804_PWRDN, 0x4, 0x0);
  7131. +
  7132. + /* wm8804 Power on */
  7133. + snd_soc_component_update_bits(component, WM8804_PWRDN, 0x9, 0);
  7134. +
  7135. + /* wm8804 set sampling frequency status bits */
  7136. + snd_soc_component_update_bits(component, WM8804_SPDTX4, 0x0f, sampling_freq);
  7137. +
  7138. + /* Now update wm8741 registers for the correct oversampling */
  7139. + if (samplerate <= 48000)
  7140. + snd_soc_component_update_bits(wm8741_component, WM8741_MODE_CONTROL_1,
  7141. + WM8741_OSR_MASK, 0x00);
  7142. + else if (samplerate <= 96000)
  7143. + snd_soc_component_update_bits(wm8741_component, WM8741_MODE_CONTROL_1,
  7144. + WM8741_OSR_MASK, 0x20);
  7145. + else
  7146. + snd_soc_component_update_bits(wm8741_component, WM8741_MODE_CONTROL_1,
  7147. + WM8741_OSR_MASK, 0x40);
  7148. +
  7149. + /* wm8741 bit size */
  7150. + switch (params_width(params)) {
  7151. + case 16:
  7152. + snd_soc_component_update_bits(wm8741_component, WM8741_FORMAT_CONTROL,
  7153. + WM8741_IWL_MASK, 0x00);
  7154. + break;
  7155. + case 20:
  7156. + snd_soc_component_update_bits(wm8741_component, WM8741_FORMAT_CONTROL,
  7157. + WM8741_IWL_MASK, 0x01);
  7158. + break;
  7159. + case 24:
  7160. + snd_soc_component_update_bits(wm8741_component, WM8741_FORMAT_CONTROL,
  7161. + WM8741_IWL_MASK, 0x02);
  7162. + break;
  7163. + case 32:
  7164. + snd_soc_component_update_bits(wm8741_component, WM8741_FORMAT_CONTROL,
  7165. + WM8741_IWL_MASK, 0x03);
  7166. + break;
  7167. + default:
  7168. + dev_dbg(card->dev, "wm8741_hw_params: Unsupported bit size param = %d",
  7169. + params_width(params));
  7170. + return -EINVAL;
  7171. + }
  7172. +
  7173. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
  7174. +}
  7175. +/* machine stream operations */
  7176. +static struct snd_soc_ops digidac1_soundcard_ops = {
  7177. + .hw_params = digidac1_soundcard_hw_params,
  7178. + .startup = digidac1_soundcard_startup,
  7179. + .shutdown = digidac1_soundcard_shutdown,
  7180. +};
  7181. +
  7182. +SND_SOC_DAILINK_DEFS(digidac1,
  7183. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  7184. + DAILINK_COMP_ARRAY(COMP_CODEC("wm8804.1-003b", "wm8804-spdif")),
  7185. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2835-i2s.0")));
  7186. +
  7187. +SND_SOC_DAILINK_DEFS(digidac11,
  7188. + DAILINK_COMP_ARRAY(COMP_CPU("wm8804-spdif")),
  7189. + DAILINK_COMP_ARRAY(COMP_CODEC("wm8741.1-001a", "wm8741")),
  7190. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  7191. +
  7192. +static struct snd_soc_dai_link digidac1_soundcard_dai[] = {
  7193. + {
  7194. + .name = "RRA DigiDAC1",
  7195. + .stream_name = "RRA DigiDAC1 HiFi",
  7196. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  7197. + SND_SOC_DAIFMT_CBM_CFM,
  7198. + .ops = &digidac1_soundcard_ops,
  7199. + .init = digidac1_soundcard_init,
  7200. + SND_SOC_DAILINK_REG(digidac1),
  7201. + },
  7202. + {
  7203. + .name = "RRA DigiDAC11",
  7204. + .stream_name = "RRA DigiDAC11 HiFi",
  7205. + .dai_fmt = SND_SOC_DAIFMT_I2S
  7206. + | SND_SOC_DAIFMT_NB_NF
  7207. + | SND_SOC_DAIFMT_CBS_CFS,
  7208. + SND_SOC_DAILINK_REG(digidac11),
  7209. + },
  7210. +};
  7211. +
  7212. +/* audio machine driver */
  7213. +static struct snd_soc_card digidac1_soundcard = {
  7214. + .name = "digidac1-soundcard",
  7215. + .owner = THIS_MODULE,
  7216. + .dai_link = digidac1_soundcard_dai,
  7217. + .num_links = ARRAY_SIZE(digidac1_soundcard_dai),
  7218. +};
  7219. +
  7220. +static int digidac1_soundcard_probe(struct platform_device *pdev)
  7221. +{
  7222. + int ret = 0;
  7223. +
  7224. + digidac1_soundcard.dev = &pdev->dev;
  7225. +
  7226. + if (pdev->dev.of_node) {
  7227. + struct device_node *i2s_node;
  7228. + struct snd_soc_dai_link *dai = &digidac1_soundcard_dai[0];
  7229. +
  7230. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  7231. + "i2s-controller", 0);
  7232. +
  7233. + if (i2s_node) {
  7234. + dai->cpus->dai_name = NULL;
  7235. + dai->cpus->of_node = i2s_node;
  7236. + dai->platforms->name = NULL;
  7237. + dai->platforms->of_node = i2s_node;
  7238. + }
  7239. + }
  7240. +
  7241. + ret = devm_snd_soc_register_card(&pdev->dev, &digidac1_soundcard);
  7242. + if (ret && ret != -EPROBE_DEFER)
  7243. + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
  7244. + ret);
  7245. +
  7246. + return ret;
  7247. +}
  7248. +
  7249. +static const struct of_device_id digidac1_soundcard_of_match[] = {
  7250. + { .compatible = "rra,digidac1-soundcard", },
  7251. + {},
  7252. +};
  7253. +MODULE_DEVICE_TABLE(of, digidac1_soundcard_of_match);
  7254. +
  7255. +static struct platform_driver digidac1_soundcard_driver = {
  7256. + .driver = {
  7257. + .name = "digidac1-audio",
  7258. + .owner = THIS_MODULE,
  7259. + .of_match_table = digidac1_soundcard_of_match,
  7260. + },
  7261. + .probe = digidac1_soundcard_probe,
  7262. +};
  7263. +
  7264. +module_platform_driver(digidac1_soundcard_driver);
  7265. +
  7266. +MODULE_AUTHOR("José M. Tasende <[email protected]>");
  7267. +MODULE_DESCRIPTION("ASoC Driver for RRA DigiDAC1");
  7268. +MODULE_LICENSE("GPL v2");
  7269. --- /dev/null
  7270. +++ b/sound/soc/bcm/dionaudio_loco-v2.c
  7271. @@ -0,0 +1,117 @@
  7272. +/*
  7273. + * ASoC Driver for Dion Audio LOCO-V2 DAC-AMP
  7274. + *
  7275. + * Author: Miquel Blauw <[email protected]>
  7276. + * Copyright 2017
  7277. + *
  7278. + * Based on the software of the RPi-DAC writen by Florian Meier
  7279. + *
  7280. + * This program is free software; you can redistribute it and/or
  7281. + * modify it under the terms of the GNU General Public License
  7282. + * version 2 as published by the Free Software Foundation.
  7283. + *
  7284. + * This program is distributed in the hope that it will be useful, but
  7285. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  7286. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  7287. + * General Public License for more details.
  7288. + */
  7289. +
  7290. +#include <linux/module.h>
  7291. +#include <linux/platform_device.h>
  7292. +
  7293. +#include <sound/core.h>
  7294. +#include <sound/pcm.h>
  7295. +#include <sound/pcm_params.h>
  7296. +#include <sound/soc.h>
  7297. +#include <sound/jack.h>
  7298. +
  7299. +static bool digital_gain_0db_limit = true;
  7300. +
  7301. +static int snd_rpi_dionaudio_loco_v2_init(struct snd_soc_pcm_runtime *rtd)
  7302. +{
  7303. + if (digital_gain_0db_limit) {
  7304. + int ret;
  7305. + struct snd_soc_card *card = rtd->card;
  7306. +
  7307. + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
  7308. + if (ret < 0)
  7309. + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
  7310. + }
  7311. +
  7312. + return 0;
  7313. +}
  7314. +
  7315. +SND_SOC_DAILINK_DEFS(dionaudio_loco_v2,
  7316. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  7317. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi")),
  7318. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  7319. +
  7320. +static struct snd_soc_dai_link snd_rpi_dionaudio_loco_v2_dai[] = {
  7321. +{
  7322. + .name = "DionAudio LOCO-V2",
  7323. + .stream_name = "DionAudio LOCO-V2 DAC-AMP",
  7324. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  7325. + SND_SOC_DAIFMT_CBS_CFS,
  7326. + .init = snd_rpi_dionaudio_loco_v2_init,
  7327. + SND_SOC_DAILINK_REG(dionaudio_loco_v2),
  7328. +},};
  7329. +
  7330. +/* audio machine driver */
  7331. +static struct snd_soc_card snd_rpi_dionaudio_loco_v2 = {
  7332. + .name = "Dion Audio LOCO-V2",
  7333. + .dai_link = snd_rpi_dionaudio_loco_v2_dai,
  7334. + .num_links = ARRAY_SIZE(snd_rpi_dionaudio_loco_v2_dai),
  7335. +};
  7336. +
  7337. +static int snd_rpi_dionaudio_loco_v2_probe(struct platform_device *pdev)
  7338. +{
  7339. + int ret = 0;
  7340. +
  7341. + snd_rpi_dionaudio_loco_v2.dev = &pdev->dev;
  7342. +
  7343. + if (pdev->dev.of_node) {
  7344. + struct device_node *i2s_node;
  7345. + struct snd_soc_dai_link *dai =
  7346. + &snd_rpi_dionaudio_loco_v2_dai[0];
  7347. +
  7348. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  7349. + "i2s-controller", 0);
  7350. + if (i2s_node) {
  7351. + dai->cpus->dai_name = NULL;
  7352. + dai->cpus->of_node = i2s_node;
  7353. + dai->platforms->name = NULL;
  7354. + dai->platforms->of_node = i2s_node;
  7355. + }
  7356. +
  7357. + digital_gain_0db_limit = !of_property_read_bool(
  7358. + pdev->dev.of_node, "dionaudio,24db_digital_gain");
  7359. + }
  7360. +
  7361. + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_dionaudio_loco_v2);
  7362. + if (ret)
  7363. + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
  7364. + ret);
  7365. +
  7366. + return ret;
  7367. +}
  7368. +
  7369. +static const struct of_device_id dionaudio_of_match[] = {
  7370. + { .compatible = "dionaudio,dionaudio-loco-v2", },
  7371. + {},
  7372. +};
  7373. +MODULE_DEVICE_TABLE(of, dionaudio_of_match);
  7374. +
  7375. +static struct platform_driver snd_rpi_dionaudio_loco_v2_driver = {
  7376. + .driver = {
  7377. + .name = "snd-rpi-dionaudio-loco-v2",
  7378. + .owner = THIS_MODULE,
  7379. + .of_match_table = dionaudio_of_match,
  7380. + },
  7381. + .probe = snd_rpi_dionaudio_loco_v2_probe,
  7382. +};
  7383. +
  7384. +module_platform_driver(snd_rpi_dionaudio_loco_v2_driver);
  7385. +
  7386. +MODULE_AUTHOR("Miquel Blauw <[email protected]>");
  7387. +MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO-V2");
  7388. +MODULE_LICENSE("GPL v2");
  7389. --- /dev/null
  7390. +++ b/sound/soc/bcm/dionaudio_loco.c
  7391. @@ -0,0 +1,117 @@
  7392. +/*
  7393. + * ASoC Driver for Dion Audio LOCO DAC-AMP
  7394. + *
  7395. + * Author: Miquel Blauw <[email protected]>
  7396. + * Copyright 2016
  7397. + *
  7398. + * Based on the software of the RPi-DAC writen by Florian Meier
  7399. + *
  7400. + * This program is free software; you can redistribute it and/or
  7401. + * modify it under the terms of the GNU General Public License
  7402. + * version 2 as published by the Free Software Foundation.
  7403. + *
  7404. + * This program is distributed in the hope that it will be useful, but
  7405. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  7406. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  7407. + * General Public License for more details.
  7408. + */
  7409. +
  7410. +#include <linux/module.h>
  7411. +#include <linux/platform_device.h>
  7412. +
  7413. +#include <sound/core.h>
  7414. +#include <sound/pcm.h>
  7415. +#include <sound/pcm_params.h>
  7416. +#include <sound/soc.h>
  7417. +#include <sound/jack.h>
  7418. +
  7419. +static int snd_rpi_dionaudio_loco_hw_params(
  7420. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  7421. +{
  7422. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  7423. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  7424. +
  7425. + unsigned int sample_bits =
  7426. + snd_pcm_format_physical_width(params_format(params));
  7427. +
  7428. + return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2);
  7429. +}
  7430. +
  7431. +/* machine stream operations */
  7432. +static struct snd_soc_ops snd_rpi_dionaudio_loco_ops = {
  7433. + .hw_params = snd_rpi_dionaudio_loco_hw_params,
  7434. +};
  7435. +
  7436. +SND_SOC_DAILINK_DEFS(dionaudio_loco,
  7437. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  7438. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm5102a-codec", "pcm5102a-hifi")),
  7439. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  7440. +
  7441. +static struct snd_soc_dai_link snd_rpi_dionaudio_loco_dai[] = {
  7442. +{
  7443. + .name = "DionAudio LOCO",
  7444. + .stream_name = "DionAudio LOCO DAC-AMP",
  7445. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  7446. + SND_SOC_DAIFMT_NB_NF |
  7447. + SND_SOC_DAIFMT_CBS_CFS,
  7448. + .ops = &snd_rpi_dionaudio_loco_ops,
  7449. + SND_SOC_DAILINK_REG(dionaudio_loco),
  7450. +},
  7451. +};
  7452. +
  7453. +/* audio machine driver */
  7454. +static struct snd_soc_card snd_rpi_dionaudio_loco = {
  7455. + .name = "snd_rpi_dionaudio_loco",
  7456. + .dai_link = snd_rpi_dionaudio_loco_dai,
  7457. + .num_links = ARRAY_SIZE(snd_rpi_dionaudio_loco_dai),
  7458. +};
  7459. +
  7460. +static int snd_rpi_dionaudio_loco_probe(struct platform_device *pdev)
  7461. +{
  7462. + struct device_node *np;
  7463. + int ret = 0;
  7464. +
  7465. + snd_rpi_dionaudio_loco.dev = &pdev->dev;
  7466. +
  7467. + np = pdev->dev.of_node;
  7468. + if (np) {
  7469. + struct snd_soc_dai_link *dai = &snd_rpi_dionaudio_loco_dai[0];
  7470. + struct device_node *i2s_np;
  7471. +
  7472. + i2s_np = of_parse_phandle(np, "i2s-controller", 0);
  7473. + if (i2s_np) {
  7474. + dai->cpus->dai_name = NULL;
  7475. + dai->cpus->of_node = i2s_np;
  7476. + dai->platforms->name = NULL;
  7477. + dai->platforms->of_node = i2s_np;
  7478. + }
  7479. + }
  7480. +
  7481. + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_dionaudio_loco);
  7482. + if (ret && ret != -EPROBE_DEFER)
  7483. + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
  7484. + ret);
  7485. +
  7486. + return ret;
  7487. +}
  7488. +
  7489. +static const struct of_device_id snd_rpi_dionaudio_loco_of_match[] = {
  7490. + { .compatible = "dionaudio,loco-pcm5242-tpa3118", },
  7491. + { /* sentinel */ },
  7492. +};
  7493. +MODULE_DEVICE_TABLE(of, snd_rpi_dionaudio_loco_of_match);
  7494. +
  7495. +static struct platform_driver snd_rpi_dionaudio_loco_driver = {
  7496. + .driver = {
  7497. + .name = "snd-dionaudio-loco",
  7498. + .owner = THIS_MODULE,
  7499. + .of_match_table = snd_rpi_dionaudio_loco_of_match,
  7500. + },
  7501. + .probe = snd_rpi_dionaudio_loco_probe,
  7502. +};
  7503. +
  7504. +module_platform_driver(snd_rpi_dionaudio_loco_driver);
  7505. +
  7506. +MODULE_AUTHOR("Miquel Blauw <[email protected]>");
  7507. +MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO");
  7508. +MODULE_LICENSE("GPL v2");
  7509. --- /dev/null
  7510. +++ b/sound/soc/bcm/fe-pi-audio.c
  7511. @@ -0,0 +1,154 @@
  7512. +/*
  7513. + * ASoC Driver for Fe-Pi Audio Sound Card
  7514. + *
  7515. + * Author: Henry Kupis <[email protected]>
  7516. + * Copyright 2016
  7517. + * based on code by Florian Meier <[email protected]>
  7518. + * based on code by Shawn Guo <[email protected]>
  7519. + *
  7520. + * This program is free software; you can redistribute it and/or
  7521. + * modify it under the terms of the GNU General Public License
  7522. + * version 2 as published by the Free Software Foundation.
  7523. + *
  7524. + * This program is distributed in the hope that it will be useful, but
  7525. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  7526. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  7527. + * General Public License for more details.
  7528. + */
  7529. +
  7530. +#include <linux/module.h>
  7531. +#include <linux/platform_device.h>
  7532. +#include <linux/io.h>
  7533. +
  7534. +#include <sound/core.h>
  7535. +#include <sound/pcm.h>
  7536. +#include <sound/pcm_params.h>
  7537. +#include <sound/soc.h>
  7538. +#include <sound/jack.h>
  7539. +
  7540. +#include "../codecs/sgtl5000.h"
  7541. +
  7542. +static int snd_fe_pi_audio_init(struct snd_soc_pcm_runtime *rtd)
  7543. +{
  7544. + struct snd_soc_card *card = rtd->card;
  7545. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  7546. +
  7547. + snd_soc_dapm_force_enable_pin(&card->dapm, "LO");
  7548. + snd_soc_dapm_force_enable_pin(&card->dapm, "ADC");
  7549. + snd_soc_dapm_force_enable_pin(&card->dapm, "DAC");
  7550. + snd_soc_dapm_force_enable_pin(&card->dapm, "HP");
  7551. + snd_soc_component_update_bits(component, SGTL5000_CHIP_ANA_POWER,
  7552. + SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
  7553. +
  7554. + return 0;
  7555. +}
  7556. +
  7557. +static int snd_fe_pi_audio_hw_params(struct snd_pcm_substream *substream,
  7558. + struct snd_pcm_hw_params *params)
  7559. +{
  7560. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  7561. + struct device *dev = rtd->card->dev;
  7562. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  7563. +
  7564. + int ret;
  7565. +
  7566. + /* Set SGTL5000's SYSCLK */
  7567. + ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, 12288000, SND_SOC_CLOCK_IN);
  7568. + if (ret) {
  7569. + dev_err(dev, "could not set codec driver clock params\n");
  7570. + return ret;
  7571. + }
  7572. +
  7573. + return 0;
  7574. +}
  7575. +
  7576. +
  7577. +static struct snd_soc_ops snd_fe_pi_audio_ops = {
  7578. + .hw_params = snd_fe_pi_audio_hw_params,
  7579. +};
  7580. +
  7581. +SND_SOC_DAILINK_DEFS(fe_pi,
  7582. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  7583. + DAILINK_COMP_ARRAY(COMP_CODEC("sgtl5000.1-000a", "sgtl5000")),
  7584. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  7585. +
  7586. +static struct snd_soc_dai_link snd_fe_pi_audio_dai[] = {
  7587. + {
  7588. + .name = "FE-PI",
  7589. + .stream_name = "Fe-Pi HiFi",
  7590. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  7591. + SND_SOC_DAIFMT_CBM_CFM,
  7592. + .ops = &snd_fe_pi_audio_ops,
  7593. + .init = snd_fe_pi_audio_init,
  7594. + SND_SOC_DAILINK_REG(fe_pi),
  7595. + },
  7596. +};
  7597. +
  7598. +static const struct snd_soc_dapm_route fe_pi_audio_dapm_routes[] = {
  7599. + {"ADC", NULL, "Mic Bias"},
  7600. +};
  7601. +
  7602. +
  7603. +static struct snd_soc_card fe_pi_audio = {
  7604. + .name = "Fe-Pi Audio",
  7605. + .owner = THIS_MODULE,
  7606. + .dai_link = snd_fe_pi_audio_dai,
  7607. + .num_links = ARRAY_SIZE(snd_fe_pi_audio_dai),
  7608. +
  7609. + .dapm_routes = fe_pi_audio_dapm_routes,
  7610. + .num_dapm_routes = ARRAY_SIZE(fe_pi_audio_dapm_routes),
  7611. +};
  7612. +
  7613. +static int snd_fe_pi_audio_probe(struct platform_device *pdev)
  7614. +{
  7615. + int ret = 0;
  7616. + struct snd_soc_card *card = &fe_pi_audio;
  7617. + struct device_node *np = pdev->dev.of_node;
  7618. + struct device_node *i2s_node;
  7619. + struct snd_soc_dai_link *dai = &snd_fe_pi_audio_dai[0];
  7620. +
  7621. + fe_pi_audio.dev = &pdev->dev;
  7622. +
  7623. + i2s_node = of_parse_phandle(np, "i2s-controller", 0);
  7624. + if (!i2s_node) {
  7625. + dev_err(&pdev->dev, "i2s_node phandle missing or invalid\n");
  7626. + return -EINVAL;
  7627. + }
  7628. +
  7629. + dai->cpus->dai_name = NULL;
  7630. + dai->cpus->of_node = i2s_node;
  7631. + dai->platforms->name = NULL;
  7632. + dai->platforms->of_node = i2s_node;
  7633. +
  7634. + of_node_put(i2s_node);
  7635. +
  7636. + card->dev = &pdev->dev;
  7637. + platform_set_drvdata(pdev, card);
  7638. +
  7639. + ret = devm_snd_soc_register_card(&pdev->dev, card);
  7640. + if (ret && ret != -EPROBE_DEFER)
  7641. + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret);
  7642. +
  7643. + return ret;
  7644. +}
  7645. +
  7646. +static const struct of_device_id snd_fe_pi_audio_of_match[] = {
  7647. + { .compatible = "fe-pi,fe-pi-audio", },
  7648. + {},
  7649. +};
  7650. +MODULE_DEVICE_TABLE(of, snd_fe_pi_audio_of_match);
  7651. +
  7652. +static struct platform_driver snd_fe_pi_audio_driver = {
  7653. + .driver = {
  7654. + .name = "snd-fe-pi-audio",
  7655. + .owner = THIS_MODULE,
  7656. + .of_match_table = snd_fe_pi_audio_of_match,
  7657. + },
  7658. + .probe = snd_fe_pi_audio_probe,
  7659. +};
  7660. +
  7661. +module_platform_driver(snd_fe_pi_audio_driver);
  7662. +
  7663. +MODULE_AUTHOR("Henry Kupis <[email protected]>");
  7664. +MODULE_DESCRIPTION("ASoC Driver for Fe-Pi Audio");
  7665. +MODULE_LICENSE("GPL v2");
  7666. --- /dev/null
  7667. +++ b/sound/soc/bcm/googlevoicehat-codec.c
  7668. @@ -0,0 +1,214 @@
  7669. +/*
  7670. + * Driver for the Google voiceHAT audio codec for Raspberry Pi.
  7671. + *
  7672. + * Author: Peter Malkin <[email protected]>
  7673. + * Copyright 2016
  7674. + *
  7675. + * This program is free software; you can redistribute it and/or
  7676. + * modify it under the terms of the GNU General Public License
  7677. + * version 2 as published by the Free Software Foundation.
  7678. + *
  7679. + * This program is distributed in the hope that it will be useful, but
  7680. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  7681. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  7682. + * General Public License for more details.
  7683. + */
  7684. +
  7685. +#include <linux/device.h>
  7686. +#include <linux/err.h>
  7687. +#include <linux/gpio.h>
  7688. +#include <linux/gpio/consumer.h>
  7689. +#include <linux/init.h>
  7690. +#include <linux/kernel.h>
  7691. +#include <linux/mod_devicetable.h>
  7692. +#include <linux/module.h>
  7693. +#include <linux/of.h>
  7694. +#include <linux/platform_device.h>
  7695. +#include <linux/version.h>
  7696. +#include <sound/pcm.h>
  7697. +#include <sound/soc.h>
  7698. +#include <sound/soc-dai.h>
  7699. +#include <sound/soc-dapm.h>
  7700. +
  7701. +#define ICS43432_RATE_MIN_HZ 7190 /* from data sheet */
  7702. +#define ICS43432_RATE_MAX_HZ 52800 /* from data sheet */
  7703. +/* Delay in enabling SDMODE after clock settles to remove pop */
  7704. +#define SDMODE_DELAY_MS 5
  7705. +
  7706. +struct voicehat_priv {
  7707. + struct delayed_work enable_sdmode_work;
  7708. + struct gpio_desc *sdmode_gpio;
  7709. + unsigned long sdmode_delay_jiffies;
  7710. +};
  7711. +
  7712. +static void voicehat_enable_sdmode_work(struct work_struct *work)
  7713. +{
  7714. + struct voicehat_priv *voicehat = container_of(work,
  7715. + struct voicehat_priv,
  7716. + enable_sdmode_work.work);
  7717. + gpiod_set_value(voicehat->sdmode_gpio, 1);
  7718. +}
  7719. +
  7720. +static int voicehat_component_probe(struct snd_soc_component *component)
  7721. +{
  7722. + struct voicehat_priv *voicehat =
  7723. + snd_soc_component_get_drvdata(component);
  7724. +
  7725. + voicehat->sdmode_gpio = devm_gpiod_get(component->dev, "sdmode",
  7726. + GPIOD_OUT_LOW);
  7727. + if (IS_ERR(voicehat->sdmode_gpio)) {
  7728. + dev_err(component->dev, "Unable to allocate GPIO pin\n");
  7729. + return PTR_ERR(voicehat->sdmode_gpio);
  7730. + }
  7731. +
  7732. + INIT_DELAYED_WORK(&voicehat->enable_sdmode_work,
  7733. + voicehat_enable_sdmode_work);
  7734. + return 0;
  7735. +}
  7736. +
  7737. +static void voicehat_component_remove(struct snd_soc_component *component)
  7738. +{
  7739. + struct voicehat_priv *voicehat =
  7740. + snd_soc_component_get_drvdata(component);
  7741. +
  7742. + cancel_delayed_work_sync(&voicehat->enable_sdmode_work);
  7743. +}
  7744. +
  7745. +static const struct snd_soc_dapm_widget voicehat_dapm_widgets[] = {
  7746. + SND_SOC_DAPM_OUTPUT("Speaker"),
  7747. +};
  7748. +
  7749. +static const struct snd_soc_dapm_route voicehat_dapm_routes[] = {
  7750. + {"Speaker", NULL, "HiFi Playback"},
  7751. +};
  7752. +
  7753. +static const struct snd_soc_component_driver voicehat_component_driver = {
  7754. + .probe = voicehat_component_probe,
  7755. + .remove = voicehat_component_remove,
  7756. + .dapm_widgets = voicehat_dapm_widgets,
  7757. + .num_dapm_widgets = ARRAY_SIZE(voicehat_dapm_widgets),
  7758. + .dapm_routes = voicehat_dapm_routes,
  7759. + .num_dapm_routes = ARRAY_SIZE(voicehat_dapm_routes),
  7760. +};
  7761. +
  7762. +static int voicehat_daiops_trigger(struct snd_pcm_substream *substream, int cmd,
  7763. + struct snd_soc_dai *dai)
  7764. +{
  7765. + struct snd_soc_component *component = dai->component;
  7766. + struct voicehat_priv *voicehat =
  7767. + snd_soc_component_get_drvdata(component);
  7768. +
  7769. + if (voicehat->sdmode_delay_jiffies == 0)
  7770. + return 0;
  7771. +
  7772. + dev_dbg(dai->dev, "CMD %d", cmd);
  7773. + dev_dbg(dai->dev, "Playback Active %d", dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active);
  7774. + dev_dbg(dai->dev, "Capture Active %d", dai->stream[SNDRV_PCM_STREAM_CAPTURE].active);
  7775. +
  7776. + switch (cmd) {
  7777. + case SNDRV_PCM_TRIGGER_START:
  7778. + case SNDRV_PCM_TRIGGER_RESUME:
  7779. + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  7780. + if (dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active) {
  7781. + dev_info(dai->dev, "Enabling audio amp...\n");
  7782. + queue_delayed_work(
  7783. + system_power_efficient_wq,
  7784. + &voicehat->enable_sdmode_work,
  7785. + voicehat->sdmode_delay_jiffies);
  7786. + }
  7787. + break;
  7788. + case SNDRV_PCM_TRIGGER_STOP:
  7789. + case SNDRV_PCM_TRIGGER_SUSPEND:
  7790. + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  7791. + if (dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active) {
  7792. + cancel_delayed_work(&voicehat->enable_sdmode_work);
  7793. + dev_info(dai->dev, "Disabling audio amp...\n");
  7794. + gpiod_set_value(voicehat->sdmode_gpio, 0);
  7795. + }
  7796. + break;
  7797. + }
  7798. + return 0;
  7799. +}
  7800. +
  7801. +static const struct snd_soc_dai_ops voicehat_dai_ops = {
  7802. + .trigger = voicehat_daiops_trigger,
  7803. +};
  7804. +
  7805. +static struct snd_soc_dai_driver voicehat_dai = {
  7806. + .name = "voicehat-hifi",
  7807. + .capture = {
  7808. + .stream_name = "HiFi Capture",
  7809. + .channels_min = 2,
  7810. + .channels_max = 2,
  7811. + .rates = SNDRV_PCM_RATE_48000,
  7812. + .formats = SNDRV_PCM_FMTBIT_S32_LE
  7813. + },
  7814. + .playback = {
  7815. + .stream_name = "HiFi Playback",
  7816. + .channels_min = 2,
  7817. + .channels_max = 2,
  7818. + .rates = SNDRV_PCM_RATE_48000,
  7819. + .formats = SNDRV_PCM_FMTBIT_S32_LE
  7820. + },
  7821. + .ops = &voicehat_dai_ops,
  7822. + .symmetric_rate = 1
  7823. +};
  7824. +
  7825. +#ifdef CONFIG_OF
  7826. +static const struct of_device_id voicehat_ids[] = {
  7827. + { .compatible = "google,voicehat", }, {}
  7828. + };
  7829. + MODULE_DEVICE_TABLE(of, voicehat_ids);
  7830. +#endif
  7831. +
  7832. +static int voicehat_platform_probe(struct platform_device *pdev)
  7833. +{
  7834. + struct voicehat_priv *voicehat;
  7835. + unsigned int sdmode_delay;
  7836. + int ret;
  7837. +
  7838. + voicehat = devm_kzalloc(&pdev->dev, sizeof(*voicehat), GFP_KERNEL);
  7839. + if (!voicehat)
  7840. + return -ENOMEM;
  7841. +
  7842. + ret = device_property_read_u32(&pdev->dev, "voicehat_sdmode_delay",
  7843. + &sdmode_delay);
  7844. +
  7845. + if (ret) {
  7846. + sdmode_delay = SDMODE_DELAY_MS;
  7847. + dev_info(&pdev->dev,
  7848. + "property 'voicehat_sdmode_delay' not found default 5 mS");
  7849. + } else {
  7850. + dev_info(&pdev->dev, "property 'voicehat_sdmode_delay' found delay= %d mS",
  7851. + sdmode_delay);
  7852. + }
  7853. + voicehat->sdmode_delay_jiffies = msecs_to_jiffies(sdmode_delay);
  7854. +
  7855. + dev_set_drvdata(&pdev->dev, voicehat);
  7856. +
  7857. + return snd_soc_register_component(&pdev->dev,
  7858. + &voicehat_component_driver,
  7859. + &voicehat_dai,
  7860. + 1);
  7861. +}
  7862. +
  7863. +static int voicehat_platform_remove(struct platform_device *pdev)
  7864. +{
  7865. + snd_soc_unregister_component(&pdev->dev);
  7866. + return 0;
  7867. +}
  7868. +
  7869. +static struct platform_driver voicehat_driver = {
  7870. + .driver = {
  7871. + .name = "voicehat-codec",
  7872. + .of_match_table = of_match_ptr(voicehat_ids),
  7873. + },
  7874. + .probe = voicehat_platform_probe,
  7875. + .remove = voicehat_platform_remove,
  7876. +};
  7877. +
  7878. +module_platform_driver(voicehat_driver);
  7879. +
  7880. +MODULE_DESCRIPTION("Google voiceHAT Codec driver");
  7881. +MODULE_AUTHOR("Peter Malkin <[email protected]>");
  7882. +MODULE_LICENSE("GPL v2");
  7883. --- /dev/null
  7884. +++ b/sound/soc/bcm/hifiberry_dacplus.c
  7885. @@ -0,0 +1,527 @@
  7886. +/*
  7887. + * ASoC Driver for HiFiBerry DAC+ / DAC Pro / AMP100
  7888. + *
  7889. + * Author: Daniel Matuschek, Stuart MacLean <[email protected]>
  7890. + * Copyright 2014-2015
  7891. + * based on code by Florian Meier <[email protected]>
  7892. + * Headphone/AMP100 Joerg Schambacher <[email protected]>
  7893. + *
  7894. + * This program is free software; you can redistribute it and/or
  7895. + * modify it under the terms of the GNU General Public License
  7896. + * version 2 as published by the Free Software Foundation.
  7897. + *
  7898. + * This program is distributed in the hope that it will be useful, but
  7899. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  7900. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  7901. + * General Public License for more details.
  7902. + */
  7903. +
  7904. +#include <linux/module.h>
  7905. +#include <linux/gpio/consumer.h>
  7906. +#include <../drivers/gpio/gpiolib.h>
  7907. +#include <linux/platform_device.h>
  7908. +#include <linux/kernel.h>
  7909. +#include <linux/clk.h>
  7910. +#include <linux/kernel.h>
  7911. +#include <linux/module.h>
  7912. +#include <linux/of.h>
  7913. +#include <linux/slab.h>
  7914. +#include <linux/delay.h>
  7915. +#include <linux/i2c.h>
  7916. +
  7917. +#include <sound/core.h>
  7918. +#include <sound/pcm.h>
  7919. +#include <sound/pcm_params.h>
  7920. +#include <sound/soc.h>
  7921. +#include <sound/jack.h>
  7922. +
  7923. +#include "../codecs/pcm512x.h"
  7924. +
  7925. +#define HIFIBERRY_DACPRO_NOCLOCK 0
  7926. +#define HIFIBERRY_DACPRO_CLK44EN 1
  7927. +#define HIFIBERRY_DACPRO_CLK48EN 2
  7928. +
  7929. +struct pcm512x_priv {
  7930. + struct regmap *regmap;
  7931. + struct clk *sclk;
  7932. +};
  7933. +
  7934. +/* Clock rate of CLK44EN attached to GPIO6 pin */
  7935. +#define CLK_44EN_RATE 22579200UL
  7936. +/* Clock rate of CLK48EN attached to GPIO3 pin */
  7937. +#define CLK_48EN_RATE 24576000UL
  7938. +
  7939. +static bool slave;
  7940. +static bool snd_rpi_hifiberry_is_dacpro;
  7941. +static bool digital_gain_0db_limit = true;
  7942. +static bool leds_off;
  7943. +static bool auto_mute;
  7944. +static int mute_ext_ctl;
  7945. +static int mute_ext;
  7946. +static struct gpio_desc *snd_mute_gpio;
  7947. +static struct gpio_desc *snd_reset_gpio;
  7948. +static struct snd_soc_card snd_rpi_hifiberry_dacplus;
  7949. +
  7950. +static int snd_rpi_hifiberry_dacplus_mute_set(int mute)
  7951. +{
  7952. + gpiod_set_value_cansleep(snd_mute_gpio, mute);
  7953. + return 1;
  7954. +}
  7955. +
  7956. +static int snd_rpi_hifiberry_dacplus_mute_get(struct snd_kcontrol *kcontrol,
  7957. + struct snd_ctl_elem_value *ucontrol)
  7958. +{
  7959. + ucontrol->value.integer.value[0] = mute_ext;
  7960. +
  7961. + return 0;
  7962. +}
  7963. +
  7964. +static int snd_rpi_hifiberry_dacplus_mute_put(struct snd_kcontrol *kcontrol,
  7965. + struct snd_ctl_elem_value *ucontrol)
  7966. +{
  7967. + if (mute_ext == ucontrol->value.integer.value[0])
  7968. + return 0;
  7969. +
  7970. + mute_ext = ucontrol->value.integer.value[0];
  7971. +
  7972. + return snd_rpi_hifiberry_dacplus_mute_set(mute_ext);
  7973. +}
  7974. +
  7975. +static const char * const mute_text[] = {"Play", "Mute"};
  7976. +static const struct soc_enum hb_dacplus_opt_mute_enum =
  7977. + SOC_ENUM_SINGLE_EXT(2, mute_text);
  7978. +
  7979. +static const struct snd_kcontrol_new hb_dacplus_opt_mute_controls[] = {
  7980. + SOC_ENUM_EXT("Mute(ext)", hb_dacplus_opt_mute_enum,
  7981. + snd_rpi_hifiberry_dacplus_mute_get,
  7982. + snd_rpi_hifiberry_dacplus_mute_put),
  7983. +};
  7984. +
  7985. +static void snd_rpi_hifiberry_dacplus_select_clk(struct snd_soc_component *component,
  7986. + int clk_id)
  7987. +{
  7988. + switch (clk_id) {
  7989. + case HIFIBERRY_DACPRO_NOCLOCK:
  7990. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
  7991. + break;
  7992. + case HIFIBERRY_DACPRO_CLK44EN:
  7993. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
  7994. + break;
  7995. + case HIFIBERRY_DACPRO_CLK48EN:
  7996. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
  7997. + break;
  7998. + }
  7999. + usleep_range(3000, 4000);
  8000. +}
  8001. +
  8002. +static void snd_rpi_hifiberry_dacplus_clk_gpio(struct snd_soc_component *component)
  8003. +{
  8004. + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
  8005. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
  8006. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
  8007. +}
  8008. +
  8009. +static bool snd_rpi_hifiberry_dacplus_is_sclk(struct snd_soc_component *component)
  8010. +{
  8011. + unsigned int sck;
  8012. +
  8013. + sck = snd_soc_component_read(component, PCM512x_RATE_DET_4);
  8014. + return (!(sck & 0x40));
  8015. +}
  8016. +
  8017. +static bool snd_rpi_hifiberry_dacplus_is_pro_card(struct snd_soc_component *component)
  8018. +{
  8019. + bool isClk44EN, isClk48En, isNoClk;
  8020. +
  8021. + snd_rpi_hifiberry_dacplus_clk_gpio(component);
  8022. +
  8023. + snd_rpi_hifiberry_dacplus_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
  8024. + isClk44EN = snd_rpi_hifiberry_dacplus_is_sclk(component);
  8025. +
  8026. + snd_rpi_hifiberry_dacplus_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
  8027. + isNoClk = snd_rpi_hifiberry_dacplus_is_sclk(component);
  8028. +
  8029. + snd_rpi_hifiberry_dacplus_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
  8030. + isClk48En = snd_rpi_hifiberry_dacplus_is_sclk(component);
  8031. +
  8032. + return (isClk44EN && isClk48En && !isNoClk);
  8033. +}
  8034. +
  8035. +static int snd_rpi_hifiberry_dacplus_clk_for_rate(int sample_rate)
  8036. +{
  8037. + int type;
  8038. +
  8039. + switch (sample_rate) {
  8040. + case 11025:
  8041. + case 22050:
  8042. + case 44100:
  8043. + case 88200:
  8044. + case 176400:
  8045. + case 352800:
  8046. + type = HIFIBERRY_DACPRO_CLK44EN;
  8047. + break;
  8048. + default:
  8049. + type = HIFIBERRY_DACPRO_CLK48EN;
  8050. + break;
  8051. + }
  8052. + return type;
  8053. +}
  8054. +
  8055. +static void snd_rpi_hifiberry_dacplus_set_sclk(struct snd_soc_component *component,
  8056. + int sample_rate)
  8057. +{
  8058. + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
  8059. +
  8060. + if (!IS_ERR(pcm512x->sclk)) {
  8061. + int ctype;
  8062. +
  8063. + ctype = snd_rpi_hifiberry_dacplus_clk_for_rate(sample_rate);
  8064. + clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
  8065. + ? CLK_44EN_RATE : CLK_48EN_RATE);
  8066. + snd_rpi_hifiberry_dacplus_select_clk(component, ctype);
  8067. + }
  8068. +}
  8069. +
  8070. +static int snd_rpi_hifiberry_dacplus_init(struct snd_soc_pcm_runtime *rtd)
  8071. +{
  8072. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  8073. + struct pcm512x_priv *priv;
  8074. + struct snd_soc_card *card = &snd_rpi_hifiberry_dacplus;
  8075. +
  8076. + if (slave)
  8077. + snd_rpi_hifiberry_is_dacpro = false;
  8078. + else
  8079. + snd_rpi_hifiberry_is_dacpro =
  8080. + snd_rpi_hifiberry_dacplus_is_pro_card(component);
  8081. +
  8082. + if (snd_rpi_hifiberry_is_dacpro) {
  8083. + struct snd_soc_dai_link *dai = rtd->dai_link;
  8084. +
  8085. + dai->name = "HiFiBerry DAC+ Pro";
  8086. + dai->stream_name = "HiFiBerry DAC+ Pro HiFi";
  8087. + dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
  8088. + | SND_SOC_DAIFMT_CBM_CFM;
  8089. +
  8090. + snd_soc_component_update_bits(component, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
  8091. + snd_soc_component_update_bits(component, PCM512x_MASTER_MODE, 0x03, 0x03);
  8092. + snd_soc_component_update_bits(component, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
  8093. + } else {
  8094. + priv = snd_soc_component_get_drvdata(component);
  8095. + priv->sclk = ERR_PTR(-ENOENT);
  8096. + }
  8097. +
  8098. + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
  8099. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
  8100. + if (leds_off)
  8101. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
  8102. + else
  8103. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
  8104. +
  8105. + if (digital_gain_0db_limit) {
  8106. + int ret;
  8107. + struct snd_soc_card *card = rtd->card;
  8108. +
  8109. + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
  8110. + if (ret < 0)
  8111. + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
  8112. + }
  8113. + if (snd_reset_gpio) {
  8114. + gpiod_set_value_cansleep(snd_reset_gpio, 0);
  8115. + msleep(1);
  8116. + gpiod_set_value_cansleep(snd_reset_gpio, 1);
  8117. + msleep(1);
  8118. + gpiod_set_value_cansleep(snd_reset_gpio, 0);
  8119. + }
  8120. +
  8121. + if (mute_ext_ctl)
  8122. + snd_soc_add_card_controls(card, hb_dacplus_opt_mute_controls,
  8123. + ARRAY_SIZE(hb_dacplus_opt_mute_controls));
  8124. +
  8125. + if (snd_mute_gpio)
  8126. + gpiod_set_value_cansleep(snd_mute_gpio, mute_ext);
  8127. +
  8128. + return 0;
  8129. +}
  8130. +
  8131. +static int snd_rpi_hifiberry_dacplus_update_rate_den(
  8132. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  8133. +{
  8134. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  8135. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  8136. + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
  8137. + struct snd_ratnum *rats_no_pll;
  8138. + unsigned int num = 0, den = 0;
  8139. + int err;
  8140. +
  8141. + rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
  8142. + if (!rats_no_pll)
  8143. + return -ENOMEM;
  8144. +
  8145. + rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
  8146. + rats_no_pll->den_min = 1;
  8147. + rats_no_pll->den_max = 128;
  8148. + rats_no_pll->den_step = 1;
  8149. +
  8150. + err = snd_interval_ratnum(hw_param_interval(params,
  8151. + SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
  8152. + if (err >= 0 && den) {
  8153. + params->rate_num = num;
  8154. + params->rate_den = den;
  8155. + }
  8156. +
  8157. + devm_kfree(rtd->dev, rats_no_pll);
  8158. + return 0;
  8159. +}
  8160. +
  8161. +static int snd_rpi_hifiberry_dacplus_hw_params(
  8162. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  8163. +{
  8164. + int ret = 0;
  8165. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  8166. + int channels = params_channels(params);
  8167. + int width = 32;
  8168. +
  8169. + if (snd_rpi_hifiberry_is_dacpro) {
  8170. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  8171. +
  8172. + width = snd_pcm_format_physical_width(params_format(params));
  8173. +
  8174. + snd_rpi_hifiberry_dacplus_set_sclk(component,
  8175. + params_rate(params));
  8176. +
  8177. + ret = snd_rpi_hifiberry_dacplus_update_rate_den(
  8178. + substream, params);
  8179. + }
  8180. +
  8181. + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), channels * width);
  8182. + if (ret)
  8183. + return ret;
  8184. + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), channels * width);
  8185. + return ret;
  8186. +}
  8187. +
  8188. +static int snd_rpi_hifiberry_dacplus_startup(
  8189. + struct snd_pcm_substream *substream)
  8190. +{
  8191. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  8192. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  8193. +
  8194. + if (auto_mute)
  8195. + gpiod_set_value_cansleep(snd_mute_gpio, 0);
  8196. + if (leds_off)
  8197. + return 0;
  8198. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
  8199. + return 0;
  8200. +}
  8201. +
  8202. +static void snd_rpi_hifiberry_dacplus_shutdown(
  8203. + struct snd_pcm_substream *substream)
  8204. +{
  8205. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  8206. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  8207. +
  8208. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
  8209. + if (auto_mute)
  8210. + gpiod_set_value_cansleep(snd_mute_gpio, 1);
  8211. +}
  8212. +
  8213. +/* machine stream operations */
  8214. +static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = {
  8215. + .hw_params = snd_rpi_hifiberry_dacplus_hw_params,
  8216. + .startup = snd_rpi_hifiberry_dacplus_startup,
  8217. + .shutdown = snd_rpi_hifiberry_dacplus_shutdown,
  8218. +};
  8219. +
  8220. +SND_SOC_DAILINK_DEFS(rpi_hifiberry_dacplus,
  8221. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  8222. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi")),
  8223. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  8224. +
  8225. +static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = {
  8226. +{
  8227. + .name = "HiFiBerry DAC+",
  8228. + .stream_name = "HiFiBerry DAC+ HiFi",
  8229. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  8230. + SND_SOC_DAIFMT_CBS_CFS,
  8231. + .ops = &snd_rpi_hifiberry_dacplus_ops,
  8232. + .init = snd_rpi_hifiberry_dacplus_init,
  8233. + SND_SOC_DAILINK_REG(rpi_hifiberry_dacplus),
  8234. +},
  8235. +};
  8236. +
  8237. +/* aux device for optional headphone amp */
  8238. +static struct snd_soc_aux_dev hifiberry_dacplus_aux_devs[] = {
  8239. + {
  8240. + .dlc = {
  8241. + .name = "tpa6130a2.1-0060",
  8242. + },
  8243. + },
  8244. +};
  8245. +
  8246. +/* audio machine driver */
  8247. +static struct snd_soc_card snd_rpi_hifiberry_dacplus = {
  8248. + .name = "snd_rpi_hifiberry_dacplus",
  8249. + .driver_name = "HifiberryDacp",
  8250. + .owner = THIS_MODULE,
  8251. + .dai_link = snd_rpi_hifiberry_dacplus_dai,
  8252. + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai),
  8253. +};
  8254. +
  8255. +static int hb_hp_detect(void)
  8256. +{
  8257. + struct i2c_adapter *adap = i2c_get_adapter(1);
  8258. + int ret;
  8259. + struct i2c_client tpa_i2c_client = {
  8260. + .addr = 0x60,
  8261. + .adapter = adap,
  8262. + };
  8263. +
  8264. + if (!adap)
  8265. + return -EPROBE_DEFER; /* I2C module not yet available */
  8266. +
  8267. + ret = i2c_smbus_read_byte(&tpa_i2c_client) >= 0;
  8268. + i2c_put_adapter(adap);
  8269. + return ret;
  8270. +};
  8271. +
  8272. +static struct property tpa_enable_prop = {
  8273. + .name = "status",
  8274. + .length = 4 + 1, /* length 'okay' + 1 */
  8275. + .value = "okay",
  8276. + };
  8277. +
  8278. +static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev)
  8279. +{
  8280. + int ret = 0;
  8281. + struct snd_soc_card *card = &snd_rpi_hifiberry_dacplus;
  8282. + int len;
  8283. + struct device_node *tpa_node;
  8284. + struct property *tpa_prop;
  8285. + struct of_changeset ocs;
  8286. + struct property *pp;
  8287. + int tmp;
  8288. +
  8289. + /* probe for head phone amp */
  8290. + ret = hb_hp_detect();
  8291. + if (ret < 0)
  8292. + return ret;
  8293. + if (ret) {
  8294. + card->aux_dev = hifiberry_dacplus_aux_devs;
  8295. + card->num_aux_devs =
  8296. + ARRAY_SIZE(hifiberry_dacplus_aux_devs);
  8297. + tpa_node = of_find_compatible_node(NULL, NULL, "ti,tpa6130a2");
  8298. + tpa_prop = of_find_property(tpa_node, "status", &len);
  8299. +
  8300. + if (strcmp((char *)tpa_prop->value, "okay")) {
  8301. + /* and activate headphone using change_sets */
  8302. + dev_info(&pdev->dev, "activating headphone amplifier");
  8303. + of_changeset_init(&ocs);
  8304. + ret = of_changeset_update_property(&ocs, tpa_node,
  8305. + &tpa_enable_prop);
  8306. + if (ret) {
  8307. + dev_err(&pdev->dev,
  8308. + "cannot activate headphone amplifier\n");
  8309. + return -ENODEV;
  8310. + }
  8311. + ret = of_changeset_apply(&ocs);
  8312. + if (ret) {
  8313. + dev_err(&pdev->dev,
  8314. + "cannot activate headphone amplifier\n");
  8315. + return -ENODEV;
  8316. + }
  8317. + }
  8318. + }
  8319. +
  8320. + snd_rpi_hifiberry_dacplus.dev = &pdev->dev;
  8321. + if (pdev->dev.of_node) {
  8322. + struct device_node *i2s_node;
  8323. + struct snd_soc_dai_link *dai;
  8324. +
  8325. + dai = &snd_rpi_hifiberry_dacplus_dai[0];
  8326. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  8327. + "i2s-controller", 0);
  8328. +
  8329. + if (i2s_node) {
  8330. + dai->cpus->dai_name = NULL;
  8331. + dai->cpus->of_node = i2s_node;
  8332. + dai->platforms->name = NULL;
  8333. + dai->platforms->of_node = i2s_node;
  8334. + }
  8335. +
  8336. + digital_gain_0db_limit = !of_property_read_bool(
  8337. + pdev->dev.of_node, "hifiberry,24db_digital_gain");
  8338. + slave = of_property_read_bool(pdev->dev.of_node,
  8339. + "hifiberry-dacplus,slave");
  8340. + leds_off = of_property_read_bool(pdev->dev.of_node,
  8341. + "hifiberry-dacplus,leds_off");
  8342. + auto_mute = of_property_read_bool(pdev->dev.of_node,
  8343. + "hifiberry-dacplus,auto_mute");
  8344. +
  8345. + /*
  8346. + * check for HW MUTE as defined in DT-overlay
  8347. + * active high, therefore default to HIGH to MUTE
  8348. + */
  8349. + snd_mute_gpio = devm_gpiod_get_optional(&pdev->dev,
  8350. + "mute", GPIOD_OUT_HIGH);
  8351. + if (IS_ERR(snd_mute_gpio)) {
  8352. + dev_err(&pdev->dev, "Can't allocate GPIO (HW-MUTE)");
  8353. + return PTR_ERR(snd_mute_gpio);
  8354. + }
  8355. +
  8356. + /* add ALSA control if requested in DT-overlay (AMP100) */
  8357. + pp = of_find_property(pdev->dev.of_node,
  8358. + "hifiberry-dacplus,mute_ext_ctl", &tmp);
  8359. + if (pp) {
  8360. + if (!of_property_read_u32(pdev->dev.of_node,
  8361. + "hifiberry-dacplus,mute_ext_ctl", &mute_ext)) {
  8362. + /* ALSA control will be used */
  8363. + mute_ext_ctl = 1;
  8364. + }
  8365. + }
  8366. +
  8367. + /* check for HW RESET (AMP100) */
  8368. + snd_reset_gpio = devm_gpiod_get_optional(&pdev->dev,
  8369. + "reset", GPIOD_OUT_HIGH);
  8370. + if (IS_ERR(snd_reset_gpio)) {
  8371. + dev_err(&pdev->dev, "Can't allocate GPIO (HW-RESET)");
  8372. + return PTR_ERR(snd_reset_gpio);
  8373. + }
  8374. +
  8375. + }
  8376. +
  8377. + ret = devm_snd_soc_register_card(&pdev->dev,
  8378. + &snd_rpi_hifiberry_dacplus);
  8379. + if (ret && ret != -EPROBE_DEFER)
  8380. + dev_err(&pdev->dev,
  8381. + "snd_soc_register_card() failed: %d\n", ret);
  8382. + if (!ret) {
  8383. + if (snd_mute_gpio)
  8384. + dev_info(&pdev->dev, "GPIO%i for HW-MUTE selected",
  8385. + gpio_chip_hwgpio(snd_mute_gpio));
  8386. + if (snd_reset_gpio)
  8387. + dev_info(&pdev->dev, "GPIO%i for HW-RESET selected",
  8388. + gpio_chip_hwgpio(snd_reset_gpio));
  8389. + }
  8390. + return ret;
  8391. +}
  8392. +
  8393. +static const struct of_device_id snd_rpi_hifiberry_dacplus_of_match[] = {
  8394. + { .compatible = "hifiberry,hifiberry-dacplus", },
  8395. + {},
  8396. +};
  8397. +MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplus_of_match);
  8398. +
  8399. +static struct platform_driver snd_rpi_hifiberry_dacplus_driver = {
  8400. + .driver = {
  8401. + .name = "snd-rpi-hifiberry-dacplus",
  8402. + .owner = THIS_MODULE,
  8403. + .of_match_table = snd_rpi_hifiberry_dacplus_of_match,
  8404. + },
  8405. + .probe = snd_rpi_hifiberry_dacplus_probe,
  8406. +};
  8407. +
  8408. +module_platform_driver(snd_rpi_hifiberry_dacplus_driver);
  8409. +
  8410. +MODULE_AUTHOR("Daniel Matuschek <[email protected]>");
  8411. +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+");
  8412. +MODULE_LICENSE("GPL v2");
  8413. --- /dev/null
  8414. +++ b/sound/soc/bcm/hifiberry_dacplusadc.c
  8415. @@ -0,0 +1,398 @@
  8416. +/*
  8417. + * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC
  8418. + *
  8419. + * Author: Daniel Matuschek, Stuart MacLean <[email protected]>
  8420. + * Copyright 2014-2015
  8421. + * based on code by Florian Meier <[email protected]>
  8422. + * ADC added by Joerg Schambacher <[email protected]>
  8423. + * Copyright 2018
  8424. + *
  8425. + * This program is free software; you can redistribute it and/or
  8426. + * modify it under the terms of the GNU General Public License
  8427. + * version 2 as published by the Free Software Foundation.
  8428. + *
  8429. + * This program is distributed in the hope that it will be useful, but
  8430. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  8431. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  8432. + * General Public License for more details.
  8433. + */
  8434. +
  8435. +#include <linux/module.h>
  8436. +#include <linux/platform_device.h>
  8437. +#include <linux/kernel.h>
  8438. +#include <linux/clk.h>
  8439. +#include <linux/kernel.h>
  8440. +#include <linux/module.h>
  8441. +#include <linux/of.h>
  8442. +#include <linux/slab.h>
  8443. +#include <linux/delay.h>
  8444. +
  8445. +#include <sound/core.h>
  8446. +#include <sound/pcm.h>
  8447. +#include <sound/pcm_params.h>
  8448. +#include <sound/soc.h>
  8449. +#include <sound/jack.h>
  8450. +
  8451. +#include "../codecs/pcm512x.h"
  8452. +
  8453. +#define HIFIBERRY_DACPRO_NOCLOCK 0
  8454. +#define HIFIBERRY_DACPRO_CLK44EN 1
  8455. +#define HIFIBERRY_DACPRO_CLK48EN 2
  8456. +
  8457. +struct platform_device *dmic_codec_dev;
  8458. +
  8459. +struct pcm512x_priv {
  8460. + struct regmap *regmap;
  8461. + struct clk *sclk;
  8462. +};
  8463. +
  8464. +/* Clock rate of CLK44EN attached to GPIO6 pin */
  8465. +#define CLK_44EN_RATE 22579200UL
  8466. +/* Clock rate of CLK48EN attached to GPIO3 pin */
  8467. +#define CLK_48EN_RATE 24576000UL
  8468. +
  8469. +static bool slave;
  8470. +static bool snd_rpi_hifiberry_is_dacpro;
  8471. +static bool digital_gain_0db_limit = true;
  8472. +static bool leds_off;
  8473. +
  8474. +static void snd_rpi_hifiberry_dacplusadc_select_clk(struct snd_soc_component *component,
  8475. + int clk_id)
  8476. +{
  8477. + switch (clk_id) {
  8478. + case HIFIBERRY_DACPRO_NOCLOCK:
  8479. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
  8480. + break;
  8481. + case HIFIBERRY_DACPRO_CLK44EN:
  8482. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
  8483. + break;
  8484. + case HIFIBERRY_DACPRO_CLK48EN:
  8485. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
  8486. + break;
  8487. + }
  8488. +}
  8489. +
  8490. +static void snd_rpi_hifiberry_dacplusadc_clk_gpio(struct snd_soc_component *component)
  8491. +{
  8492. + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
  8493. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
  8494. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
  8495. +}
  8496. +
  8497. +static bool snd_rpi_hifiberry_dacplusadc_is_sclk(struct snd_soc_component *component)
  8498. +{
  8499. + unsigned int sck;
  8500. +
  8501. + sck = snd_soc_component_read(component, PCM512x_RATE_DET_4);
  8502. + return (!(sck & 0x40));
  8503. +}
  8504. +
  8505. +static bool snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(
  8506. + struct snd_soc_component *component)
  8507. +{
  8508. + msleep(2);
  8509. + return snd_rpi_hifiberry_dacplusadc_is_sclk(component);
  8510. +}
  8511. +
  8512. +static bool snd_rpi_hifiberry_dacplusadc_is_pro_card(struct snd_soc_component *component)
  8513. +{
  8514. + bool isClk44EN, isClk48En, isNoClk;
  8515. +
  8516. + snd_rpi_hifiberry_dacplusadc_clk_gpio(component);
  8517. +
  8518. + snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
  8519. + isClk44EN = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
  8520. +
  8521. + snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
  8522. + isNoClk = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
  8523. +
  8524. + snd_rpi_hifiberry_dacplusadc_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
  8525. + isClk48En = snd_rpi_hifiberry_dacplusadc_is_sclk_sleep(component);
  8526. +
  8527. + return (isClk44EN && isClk48En && !isNoClk);
  8528. +}
  8529. +
  8530. +static int snd_rpi_hifiberry_dacplusadc_clk_for_rate(int sample_rate)
  8531. +{
  8532. + int type;
  8533. +
  8534. + switch (sample_rate) {
  8535. + case 11025:
  8536. + case 22050:
  8537. + case 44100:
  8538. + case 88200:
  8539. + case 176400:
  8540. + case 352800:
  8541. + type = HIFIBERRY_DACPRO_CLK44EN;
  8542. + break;
  8543. + default:
  8544. + type = HIFIBERRY_DACPRO_CLK48EN;
  8545. + break;
  8546. + }
  8547. + return type;
  8548. +}
  8549. +
  8550. +static void snd_rpi_hifiberry_dacplusadc_set_sclk(struct snd_soc_component *component,
  8551. + int sample_rate)
  8552. +{
  8553. + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
  8554. +
  8555. + if (!IS_ERR(pcm512x->sclk)) {
  8556. + int ctype;
  8557. +
  8558. + ctype = snd_rpi_hifiberry_dacplusadc_clk_for_rate(sample_rate);
  8559. + clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
  8560. + ? CLK_44EN_RATE : CLK_48EN_RATE);
  8561. + snd_rpi_hifiberry_dacplusadc_select_clk(component, ctype);
  8562. + }
  8563. +}
  8564. +
  8565. +static int snd_rpi_hifiberry_dacplusadc_init(struct snd_soc_pcm_runtime *rtd)
  8566. +{
  8567. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  8568. + struct pcm512x_priv *priv;
  8569. +
  8570. + if (slave)
  8571. + snd_rpi_hifiberry_is_dacpro = false;
  8572. + else
  8573. + snd_rpi_hifiberry_is_dacpro =
  8574. + snd_rpi_hifiberry_dacplusadc_is_pro_card(component);
  8575. +
  8576. + if (snd_rpi_hifiberry_is_dacpro) {
  8577. + struct snd_soc_dai_link *dai = rtd->dai_link;
  8578. +
  8579. + dai->name = "HiFiBerry ADCDAC+ Pro";
  8580. + dai->stream_name = "HiFiBerry ADCDAC+ Pro HiFi";
  8581. + dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
  8582. + | SND_SOC_DAIFMT_CBM_CFM;
  8583. +
  8584. + snd_soc_component_update_bits(component, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
  8585. + snd_soc_component_update_bits(component, PCM512x_MASTER_MODE, 0x03, 0x03);
  8586. + snd_soc_component_update_bits(component, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
  8587. + } else {
  8588. + priv = snd_soc_component_get_drvdata(component);
  8589. + priv->sclk = ERR_PTR(-ENOENT);
  8590. + }
  8591. +
  8592. + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
  8593. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
  8594. + if (leds_off)
  8595. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
  8596. + else
  8597. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
  8598. +
  8599. + if (digital_gain_0db_limit) {
  8600. + int ret;
  8601. + struct snd_soc_card *card = rtd->card;
  8602. +
  8603. + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
  8604. + if (ret < 0)
  8605. + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
  8606. + }
  8607. +
  8608. + return 0;
  8609. +}
  8610. +
  8611. +static int snd_rpi_hifiberry_dacplusadc_update_rate_den(
  8612. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  8613. +{
  8614. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  8615. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  8616. + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
  8617. + struct snd_ratnum *rats_no_pll;
  8618. + unsigned int num = 0, den = 0;
  8619. + int err;
  8620. +
  8621. + rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
  8622. + if (!rats_no_pll)
  8623. + return -ENOMEM;
  8624. +
  8625. + rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
  8626. + rats_no_pll->den_min = 1;
  8627. + rats_no_pll->den_max = 128;
  8628. + rats_no_pll->den_step = 1;
  8629. +
  8630. + err = snd_interval_ratnum(hw_param_interval(params,
  8631. + SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
  8632. + if (err >= 0 && den) {
  8633. + params->rate_num = num;
  8634. + params->rate_den = den;
  8635. + }
  8636. +
  8637. + devm_kfree(rtd->dev, rats_no_pll);
  8638. + return 0;
  8639. +}
  8640. +
  8641. +static int snd_rpi_hifiberry_dacplusadc_hw_params(
  8642. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  8643. +{
  8644. + int ret = 0;
  8645. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  8646. + int channels = params_channels(params);
  8647. + int width = 32;
  8648. +
  8649. + if (snd_rpi_hifiberry_is_dacpro) {
  8650. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  8651. +
  8652. + width = snd_pcm_format_physical_width(params_format(params));
  8653. +
  8654. + snd_rpi_hifiberry_dacplusadc_set_sclk(component,
  8655. + params_rate(params));
  8656. +
  8657. + ret = snd_rpi_hifiberry_dacplusadc_update_rate_den(
  8658. + substream, params);
  8659. + }
  8660. +
  8661. + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), channels * width);
  8662. + if (ret)
  8663. + return ret;
  8664. + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), channels * width);
  8665. + return ret;
  8666. +}
  8667. +
  8668. +static int hifiberry_dacplusadc_LED_cnt;
  8669. +
  8670. +static int snd_rpi_hifiberry_dacplusadc_startup(
  8671. + struct snd_pcm_substream *substream)
  8672. +{
  8673. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  8674. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  8675. +
  8676. + if (leds_off)
  8677. + return 0;
  8678. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
  8679. + 0x08, 0x08);
  8680. + hifiberry_dacplusadc_LED_cnt++;
  8681. + return 0;
  8682. +}
  8683. +
  8684. +static void snd_rpi_hifiberry_dacplusadc_shutdown(
  8685. + struct snd_pcm_substream *substream)
  8686. +{
  8687. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  8688. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  8689. +
  8690. + hifiberry_dacplusadc_LED_cnt--;
  8691. + if (!hifiberry_dacplusadc_LED_cnt)
  8692. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1,
  8693. + 0x08, 0x00);
  8694. +}
  8695. +
  8696. +/* machine stream operations */
  8697. +static struct snd_soc_ops snd_rpi_hifiberry_dacplusadc_ops = {
  8698. + .hw_params = snd_rpi_hifiberry_dacplusadc_hw_params,
  8699. + .startup = snd_rpi_hifiberry_dacplusadc_startup,
  8700. + .shutdown = snd_rpi_hifiberry_dacplusadc_shutdown,
  8701. +};
  8702. +
  8703. +SND_SOC_DAILINK_DEFS(hifi,
  8704. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  8705. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi"),
  8706. + COMP_CODEC("dmic-codec", "dmic-hifi")),
  8707. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  8708. +
  8709. +static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadc_dai[] = {
  8710. +{
  8711. + .name = "HiFiBerry DAC+ADC",
  8712. + .stream_name = "HiFiBerry DAC+ADC HiFi",
  8713. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  8714. + SND_SOC_DAIFMT_CBS_CFS,
  8715. + .ops = &snd_rpi_hifiberry_dacplusadc_ops,
  8716. + .init = snd_rpi_hifiberry_dacplusadc_init,
  8717. + SND_SOC_DAILINK_REG(hifi),
  8718. +},
  8719. +};
  8720. +
  8721. +/* audio machine driver */
  8722. +static struct snd_soc_card snd_rpi_hifiberry_dacplusadc = {
  8723. + .name = "snd_rpi_hifiberry_dacplusadc",
  8724. + .driver_name = "HifiberryDacpAdc",
  8725. + .owner = THIS_MODULE,
  8726. + .dai_link = snd_rpi_hifiberry_dacplusadc_dai,
  8727. + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadc_dai),
  8728. +};
  8729. +
  8730. +
  8731. +static int snd_rpi_hifiberry_dacplusadc_probe(struct platform_device *pdev)
  8732. +{
  8733. + int ret = 0;
  8734. +
  8735. + snd_rpi_hifiberry_dacplusadc.dev = &pdev->dev;
  8736. + if (pdev->dev.of_node) {
  8737. + struct device_node *i2s_node;
  8738. + struct snd_soc_dai_link *dai;
  8739. +
  8740. + dai = &snd_rpi_hifiberry_dacplusadc_dai[0];
  8741. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  8742. + "i2s-controller", 0);
  8743. + if (i2s_node) {
  8744. + dai->cpus->of_node = i2s_node;
  8745. + dai->platforms->of_node = i2s_node;
  8746. + dai->cpus->dai_name = NULL;
  8747. + dai->platforms->name = NULL;
  8748. + }
  8749. + }
  8750. + digital_gain_0db_limit = !of_property_read_bool(
  8751. + pdev->dev.of_node, "hifiberry,24db_digital_gain");
  8752. + slave = of_property_read_bool(pdev->dev.of_node,
  8753. + "hifiberry-dacplusadc,slave");
  8754. + leds_off = of_property_read_bool(pdev->dev.of_node,
  8755. + "hifiberry-dacplusadc,leds_off");
  8756. +
  8757. + ret = devm_snd_soc_register_card(&pdev->dev,
  8758. + &snd_rpi_hifiberry_dacplusadc);
  8759. + if (ret && ret != -EPROBE_DEFER)
  8760. + dev_err(&pdev->dev,
  8761. + "snd_soc_register_card() failed: %d\n", ret);
  8762. +
  8763. + return ret;
  8764. +}
  8765. +
  8766. +static const struct of_device_id snd_rpi_hifiberry_dacplusadc_of_match[] = {
  8767. + { .compatible = "hifiberry,hifiberry-dacplusadc", },
  8768. + {},
  8769. +};
  8770. +
  8771. +MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadc_of_match);
  8772. +
  8773. +static struct platform_driver snd_rpi_hifiberry_dacplusadc_driver = {
  8774. + .driver = {
  8775. + .name = "snd-rpi-hifiberry-dacplusadc",
  8776. + .owner = THIS_MODULE,
  8777. + .of_match_table = snd_rpi_hifiberry_dacplusadc_of_match,
  8778. + },
  8779. + .probe = snd_rpi_hifiberry_dacplusadc_probe,
  8780. +};
  8781. +
  8782. +static int __init hifiberry_dacplusadc_init(void)
  8783. +{
  8784. + int ret;
  8785. +
  8786. + dmic_codec_dev = platform_device_register_simple("dmic-codec", -1, NULL,
  8787. + 0);
  8788. + if (IS_ERR(dmic_codec_dev)) {
  8789. + pr_err("%s: dmic-codec device registration failed\n", __func__);
  8790. + return PTR_ERR(dmic_codec_dev);
  8791. + }
  8792. +
  8793. + ret = platform_driver_register(&snd_rpi_hifiberry_dacplusadc_driver);
  8794. + if (ret) {
  8795. + pr_err("%s: platform driver registration failed\n", __func__);
  8796. + platform_device_unregister(dmic_codec_dev);
  8797. + }
  8798. +
  8799. + return ret;
  8800. +}
  8801. +module_init(hifiberry_dacplusadc_init);
  8802. +
  8803. +static void __exit hifiberry_dacplusadc_exit(void)
  8804. +{
  8805. + platform_driver_unregister(&snd_rpi_hifiberry_dacplusadc_driver);
  8806. + platform_device_unregister(dmic_codec_dev);
  8807. +}
  8808. +module_exit(hifiberry_dacplusadc_exit);
  8809. +
  8810. +MODULE_AUTHOR("Joerg Schambacher <[email protected]>");
  8811. +MODULE_AUTHOR("Daniel Matuschek <[email protected]>");
  8812. +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
  8813. +MODULE_LICENSE("GPL v2");
  8814. --- /dev/null
  8815. +++ b/sound/soc/bcm/hifiberry_dacplusadcpro.c
  8816. @@ -0,0 +1,605 @@
  8817. +/*
  8818. + * ASoC Driver for HiFiBerry DAC+ / DAC Pro with ADC PRO Version (SW control)
  8819. + *
  8820. + * Author: Daniel Matuschek, Stuart MacLean <[email protected]>
  8821. + * Copyright 2014-2015
  8822. + * based on code by Florian Meier <[email protected]>
  8823. + * ADC, HP added by Joerg Schambacher <[email protected]>
  8824. + * Copyright 2018-21
  8825. + *
  8826. + * This program is free software; you can redistribute it and/or
  8827. + * modify it under the terms of the GNU General Public License
  8828. + * version 2 as published by the Free Software Foundation.
  8829. + *
  8830. + * This program is distributed in the hope that it will be useful, but
  8831. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  8832. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  8833. + * General Public License for more details.
  8834. + */
  8835. +
  8836. +#include <linux/module.h>
  8837. +#include <linux/platform_device.h>
  8838. +#include <linux/kernel.h>
  8839. +#include <linux/clk.h>
  8840. +#include <linux/kernel.h>
  8841. +#include <linux/module.h>
  8842. +#include <linux/of.h>
  8843. +#include <linux/slab.h>
  8844. +#include <linux/delay.h>
  8845. +#include <linux/i2c.h>
  8846. +
  8847. +#include <sound/core.h>
  8848. +#include <sound/pcm.h>
  8849. +#include <sound/pcm_params.h>
  8850. +#include <sound/soc.h>
  8851. +#include <sound/jack.h>
  8852. +#include <sound/tlv.h>
  8853. +
  8854. +#include "../codecs/pcm512x.h"
  8855. +#include "../codecs/pcm186x.h"
  8856. +
  8857. +#define HIFIBERRY_DACPRO_NOCLOCK 0
  8858. +#define HIFIBERRY_DACPRO_CLK44EN 1
  8859. +#define HIFIBERRY_DACPRO_CLK48EN 2
  8860. +
  8861. +struct pcm512x_priv {
  8862. + struct regmap *regmap;
  8863. + struct clk *sclk;
  8864. +};
  8865. +
  8866. +/* Clock rate of CLK44EN attached to GPIO6 pin */
  8867. +#define CLK_44EN_RATE 22579200UL
  8868. +/* Clock rate of CLK48EN attached to GPIO3 pin */
  8869. +#define CLK_48EN_RATE 24576000UL
  8870. +
  8871. +static bool slave;
  8872. +static bool snd_rpi_hifiberry_is_dacpro;
  8873. +static bool digital_gain_0db_limit = true;
  8874. +static bool leds_off;
  8875. +
  8876. +static const unsigned int pcm186x_adc_input_channel_sel_value[] = {
  8877. + 0x00, 0x01, 0x02, 0x03, 0x10
  8878. +};
  8879. +
  8880. +static const char * const pcm186x_adcl_input_channel_sel_text[] = {
  8881. + "No Select",
  8882. + "VINL1[SE]", /* Default for ADCL */
  8883. + "VINL2[SE]",
  8884. + "VINL2[SE] + VINL1[SE]",
  8885. + "{VIN1P, VIN1M}[DIFF]"
  8886. +};
  8887. +
  8888. +static const char * const pcm186x_adcr_input_channel_sel_text[] = {
  8889. + "No Select",
  8890. + "VINR1[SE]", /* Default for ADCR */
  8891. + "VINR2[SE]",
  8892. + "VINR2[SE] + VINR1[SE]",
  8893. + "{VIN2P, VIN2M}[DIFF]"
  8894. +};
  8895. +
  8896. +static const struct soc_enum pcm186x_adc_input_channel_sel[] = {
  8897. + SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_L, 0,
  8898. + PCM186X_ADC_INPUT_SEL_MASK,
  8899. + ARRAY_SIZE(pcm186x_adcl_input_channel_sel_text),
  8900. + pcm186x_adcl_input_channel_sel_text,
  8901. + pcm186x_adc_input_channel_sel_value),
  8902. + SOC_VALUE_ENUM_SINGLE(PCM186X_ADC1_INPUT_SEL_R, 0,
  8903. + PCM186X_ADC_INPUT_SEL_MASK,
  8904. + ARRAY_SIZE(pcm186x_adcr_input_channel_sel_text),
  8905. + pcm186x_adcr_input_channel_sel_text,
  8906. + pcm186x_adc_input_channel_sel_value),
  8907. +};
  8908. +
  8909. +static const unsigned int pcm186x_mic_bias_sel_value[] = {
  8910. + 0x00, 0x01, 0x11
  8911. +};
  8912. +
  8913. +static const char * const pcm186x_mic_bias_sel_text[] = {
  8914. + "Mic Bias off",
  8915. + "Mic Bias on",
  8916. + "Mic Bias with Bypass Resistor"
  8917. +};
  8918. +
  8919. +static const struct soc_enum pcm186x_mic_bias_sel[] = {
  8920. + SOC_VALUE_ENUM_SINGLE(PCM186X_MIC_BIAS_CTRL, 0,
  8921. + GENMASK(4, 0),
  8922. + ARRAY_SIZE(pcm186x_mic_bias_sel_text),
  8923. + pcm186x_mic_bias_sel_text,
  8924. + pcm186x_mic_bias_sel_value),
  8925. +};
  8926. +
  8927. +static const unsigned int pcm186x_gain_sel_value[] = {
  8928. + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
  8929. + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
  8930. + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
  8931. + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  8932. + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  8933. + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  8934. + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  8935. + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
  8936. + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
  8937. + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  8938. + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
  8939. + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
  8940. + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
  8941. + 0x50
  8942. +};
  8943. +
  8944. +static const char * const pcm186x_gain_sel_text[] = {
  8945. + "-12.0dB", "-11.5dB", "-11.0dB", "-10.5dB", "-10.0dB", "-9.5dB",
  8946. + "-9.0dB", "-8.5dB", "-8.0dB", "-7.5dB", "-7.0dB", "-6.5dB",
  8947. + "-6.0dB", "-5.5dB", "-5.0dB", "-4.5dB", "-4.0dB", "-3.5dB",
  8948. + "-3.0dB", "-2.5dB", "-2.0dB", "-1.5dB", "-1.0dB", "-0.5dB",
  8949. + "0.0dB", "0.5dB", "1.0dB", "1.5dB", "2.0dB", "2.5dB",
  8950. + "3.0dB", "3.5dB", "4.0dB", "4.5dB", "5.0dB", "5.5dB",
  8951. + "6.0dB", "6.5dB", "7.0dB", "7.5dB", "8.0dB", "8.5dB",
  8952. + "9.0dB", "9.5dB", "10.0dB", "10.5dB", "11.0dB", "11.5dB",
  8953. + "12.0dB", "12.5dB", "13.0dB", "13.5dB", "14.0dB", "14.5dB",
  8954. + "15.0dB", "15.5dB", "16.0dB", "16.5dB", "17.0dB", "17.5dB",
  8955. + "18.0dB", "18.5dB", "19.0dB", "19.5dB", "20.0dB", "20.5dB",
  8956. + "21.0dB", "21.5dB", "22.0dB", "22.5dB", "23.0dB", "23.5dB",
  8957. + "24.0dB", "24.5dB", "25.0dB", "25.5dB", "26.0dB", "26.5dB",
  8958. + "27.0dB", "27.5dB", "28.0dB", "28.5dB", "29.0dB", "29.5dB",
  8959. + "30.0dB", "30.5dB", "31.0dB", "31.5dB", "32.0dB", "32.5dB",
  8960. + "33.0dB", "33.5dB", "34.0dB", "34.5dB", "35.0dB", "35.5dB",
  8961. + "36.0dB", "36.5dB", "37.0dB", "37.5dB", "38.0dB", "38.5dB",
  8962. + "39.0dB", "39.5dB", "40.0dB"};
  8963. +
  8964. +static const struct soc_enum pcm186x_gain_sel[] = {
  8965. + SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_L, 0,
  8966. + 0xff,
  8967. + ARRAY_SIZE(pcm186x_gain_sel_text),
  8968. + pcm186x_gain_sel_text,
  8969. + pcm186x_gain_sel_value),
  8970. + SOC_VALUE_ENUM_SINGLE(PCM186X_PGA_VAL_CH1_R, 0,
  8971. + 0xff,
  8972. + ARRAY_SIZE(pcm186x_gain_sel_text),
  8973. + pcm186x_gain_sel_text,
  8974. + pcm186x_gain_sel_value),
  8975. +};
  8976. +
  8977. +static const struct snd_kcontrol_new pcm1863_snd_controls_card[] = {
  8978. + SOC_ENUM("ADC Left Input", pcm186x_adc_input_channel_sel[0]),
  8979. + SOC_ENUM("ADC Right Input", pcm186x_adc_input_channel_sel[1]),
  8980. + SOC_ENUM("ADC Mic Bias", pcm186x_mic_bias_sel),
  8981. + SOC_ENUM("PGA Gain Left", pcm186x_gain_sel[0]),
  8982. + SOC_ENUM("PGA Gain Right", pcm186x_gain_sel[1]),
  8983. +};
  8984. +
  8985. +static int pcm1863_add_controls(struct snd_soc_component *component)
  8986. +{
  8987. + snd_soc_add_component_controls(component,
  8988. + pcm1863_snd_controls_card,
  8989. + ARRAY_SIZE(pcm1863_snd_controls_card));
  8990. + return 0;
  8991. +}
  8992. +
  8993. +static void snd_rpi_hifiberry_dacplusadcpro_select_clk(
  8994. + struct snd_soc_component *component, int clk_id)
  8995. +{
  8996. + switch (clk_id) {
  8997. + case HIFIBERRY_DACPRO_NOCLOCK:
  8998. + snd_soc_component_update_bits(component,
  8999. + PCM512x_GPIO_CONTROL_1, 0x24, 0x00);
  9000. + break;
  9001. + case HIFIBERRY_DACPRO_CLK44EN:
  9002. + snd_soc_component_update_bits(component,
  9003. + PCM512x_GPIO_CONTROL_1, 0x24, 0x20);
  9004. + break;
  9005. + case HIFIBERRY_DACPRO_CLK48EN:
  9006. + snd_soc_component_update_bits(component,
  9007. + PCM512x_GPIO_CONTROL_1, 0x24, 0x04);
  9008. + break;
  9009. + }
  9010. + usleep_range(3000, 4000);
  9011. +}
  9012. +
  9013. +static void snd_rpi_hifiberry_dacplusadcpro_clk_gpio(struct snd_soc_component *component)
  9014. +{
  9015. + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x24, 0x24);
  9016. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02);
  9017. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02);
  9018. +}
  9019. +
  9020. +static bool snd_rpi_hifiberry_dacplusadcpro_is_sclk(struct snd_soc_component *component)
  9021. +{
  9022. + unsigned int sck;
  9023. +
  9024. + sck = snd_soc_component_read(component, PCM512x_RATE_DET_4);
  9025. + return (!(sck & 0x40));
  9026. +}
  9027. +
  9028. +static bool snd_rpi_hifiberry_dacplusadcpro_is_pro_card(struct snd_soc_component *component)
  9029. +{
  9030. + bool isClk44EN, isClk48En, isNoClk;
  9031. +
  9032. + snd_rpi_hifiberry_dacplusadcpro_clk_gpio(component);
  9033. +
  9034. + snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK44EN);
  9035. + isClk44EN = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
  9036. +
  9037. + snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_NOCLOCK);
  9038. + isNoClk = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
  9039. +
  9040. + snd_rpi_hifiberry_dacplusadcpro_select_clk(component, HIFIBERRY_DACPRO_CLK48EN);
  9041. + isClk48En = snd_rpi_hifiberry_dacplusadcpro_is_sclk(component);
  9042. +
  9043. + return (isClk44EN && isClk48En && !isNoClk);
  9044. +}
  9045. +
  9046. +static int snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(int sample_rate)
  9047. +{
  9048. + int type;
  9049. +
  9050. + switch (sample_rate) {
  9051. + case 11025:
  9052. + case 22050:
  9053. + case 44100:
  9054. + case 88200:
  9055. + case 176400:
  9056. + case 352800:
  9057. + type = HIFIBERRY_DACPRO_CLK44EN;
  9058. + break;
  9059. + default:
  9060. + type = HIFIBERRY_DACPRO_CLK48EN;
  9061. + break;
  9062. + }
  9063. + return type;
  9064. +}
  9065. +
  9066. +static void snd_rpi_hifiberry_dacplusadcpro_set_sclk(struct snd_soc_component *component,
  9067. + int sample_rate)
  9068. +{
  9069. + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
  9070. +
  9071. + if (!IS_ERR(pcm512x->sclk)) {
  9072. + int ctype;
  9073. +
  9074. + ctype = snd_rpi_hifiberry_dacplusadcpro_clk_for_rate(sample_rate);
  9075. + clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN)
  9076. + ? CLK_44EN_RATE : CLK_48EN_RATE);
  9077. + snd_rpi_hifiberry_dacplusadcpro_select_clk(component, ctype);
  9078. + }
  9079. +}
  9080. +
  9081. +static int snd_rpi_hifiberry_dacplusadcpro_init(struct snd_soc_pcm_runtime *rtd)
  9082. +{
  9083. + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
  9084. + struct snd_soc_component *adc = asoc_rtd_to_codec(rtd, 1)->component;
  9085. + struct snd_soc_dai_driver *adc_driver = asoc_rtd_to_codec(rtd, 1)->driver;
  9086. + struct pcm512x_priv *priv;
  9087. + int ret;
  9088. +
  9089. + if (slave)
  9090. + snd_rpi_hifiberry_is_dacpro = false;
  9091. + else
  9092. + snd_rpi_hifiberry_is_dacpro =
  9093. + snd_rpi_hifiberry_dacplusadcpro_is_pro_card(dac);
  9094. +
  9095. + if (snd_rpi_hifiberry_is_dacpro) {
  9096. + struct snd_soc_dai_link *dai = rtd->dai_link;
  9097. +
  9098. + dai->name = "HiFiBerry DAC+ADC Pro";
  9099. + dai->stream_name = "HiFiBerry DAC+ADC Pro HiFi";
  9100. + dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
  9101. + | SND_SOC_DAIFMT_CBM_CFM;
  9102. +
  9103. + // set DAC DAI configuration
  9104. + ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0),
  9105. + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
  9106. + | SND_SOC_DAIFMT_CBM_CFM);
  9107. + if (ret < 0)
  9108. + return ret;
  9109. +
  9110. + // set ADC DAI configuration
  9111. + ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 1),
  9112. + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
  9113. + | SND_SOC_DAIFMT_CBS_CFS);
  9114. + if (ret < 0)
  9115. + return ret;
  9116. +
  9117. + // set CPU DAI configuration
  9118. + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
  9119. + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
  9120. + if (ret < 0)
  9121. + return ret;
  9122. +
  9123. + snd_soc_component_update_bits(dac, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11);
  9124. + snd_soc_component_update_bits(dac, PCM512x_MASTER_MODE, 0x03, 0x03);
  9125. + snd_soc_component_update_bits(dac, PCM512x_MASTER_CLKDIV_2, 0x7f, 63);
  9126. + } else {
  9127. + priv = snd_soc_component_get_drvdata(dac);
  9128. + priv->sclk = ERR_PTR(-ENOENT);
  9129. + }
  9130. +
  9131. + /* disable 24bit mode as long as I2S module does not have sign extension fixed */
  9132. + adc_driver->capture.formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE;
  9133. +
  9134. + snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
  9135. + snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02);
  9136. + if (leds_off)
  9137. + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
  9138. + else
  9139. + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
  9140. +
  9141. + ret = pcm1863_add_controls(adc);
  9142. + if (ret < 0)
  9143. + dev_warn(rtd->dev, "Failed to add pcm1863 controls: %d\n",
  9144. + ret);
  9145. +
  9146. + /* set GPIO2 to output, GPIO3 input */
  9147. + snd_soc_component_write(adc, PCM186X_GPIO3_2_CTRL, 0x00);
  9148. + snd_soc_component_write(adc, PCM186X_GPIO3_2_DIR_CTRL, 0x04);
  9149. + if (leds_off)
  9150. + snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
  9151. + else
  9152. + snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
  9153. +
  9154. + if (digital_gain_0db_limit) {
  9155. + int ret;
  9156. + struct snd_soc_card *card = rtd->card;
  9157. +
  9158. + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
  9159. + if (ret < 0)
  9160. + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
  9161. + }
  9162. +
  9163. + return 0;
  9164. +}
  9165. +
  9166. +static int snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
  9167. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  9168. +{
  9169. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  9170. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; /* only use DAC */
  9171. + struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
  9172. + struct snd_ratnum *rats_no_pll;
  9173. + unsigned int num = 0, den = 0;
  9174. + int err;
  9175. +
  9176. + rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL);
  9177. + if (!rats_no_pll)
  9178. + return -ENOMEM;
  9179. +
  9180. + rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64;
  9181. + rats_no_pll->den_min = 1;
  9182. + rats_no_pll->den_max = 128;
  9183. + rats_no_pll->den_step = 1;
  9184. +
  9185. + err = snd_interval_ratnum(hw_param_interval(params,
  9186. + SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den);
  9187. + if (err >= 0 && den) {
  9188. + params->rate_num = num;
  9189. + params->rate_den = den;
  9190. + }
  9191. +
  9192. + devm_kfree(rtd->dev, rats_no_pll);
  9193. + return 0;
  9194. +}
  9195. +
  9196. +static int snd_rpi_hifiberry_dacplusadcpro_hw_params(
  9197. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  9198. +{
  9199. + int ret = 0;
  9200. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  9201. + int channels = params_channels(params);
  9202. + int width = 32;
  9203. + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
  9204. + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
  9205. + struct snd_soc_dai_driver *drv = dai->driver;
  9206. + const struct snd_soc_dai_ops *ops = drv->ops;
  9207. +
  9208. + if (snd_rpi_hifiberry_is_dacpro) {
  9209. + width = snd_pcm_format_physical_width(params_format(params));
  9210. +
  9211. + snd_rpi_hifiberry_dacplusadcpro_set_sclk(dac,
  9212. + params_rate(params));
  9213. +
  9214. + ret = snd_rpi_hifiberry_dacplusadcpro_update_rate_den(
  9215. + substream, params);
  9216. + if (ret)
  9217. + return ret;
  9218. + }
  9219. +
  9220. + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_cpu(rtd, 0), channels * width);
  9221. + if (ret)
  9222. + return ret;
  9223. + ret = snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), channels * width);
  9224. + if (ret)
  9225. + return ret;
  9226. + if (snd_rpi_hifiberry_is_dacpro && ops->hw_params)
  9227. + ret = ops->hw_params(substream, params, dai);
  9228. + return ret;
  9229. +}
  9230. +
  9231. +static int snd_rpi_hifiberry_dacplusadcpro_startup(
  9232. + struct snd_pcm_substream *substream)
  9233. +{
  9234. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  9235. + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
  9236. + struct snd_soc_component *adc = asoc_rtd_to_codec(rtd, 1)->component;
  9237. +
  9238. + if (leds_off)
  9239. + return 0;
  9240. + /* switch on respective LED */
  9241. + if (!substream->stream)
  9242. + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
  9243. + else
  9244. + snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x40);
  9245. + return 0;
  9246. +}
  9247. +
  9248. +static void snd_rpi_hifiberry_dacplusadcpro_shutdown(
  9249. + struct snd_pcm_substream *substream)
  9250. +{
  9251. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  9252. + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 0)->component;
  9253. + struct snd_soc_component *adc = asoc_rtd_to_codec(rtd, 1)->component;
  9254. +
  9255. + /* switch off respective LED */
  9256. + if (!substream->stream)
  9257. + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
  9258. + else
  9259. + snd_soc_component_update_bits(adc, PCM186X_GPIO_IN_OUT, 0x40, 0x00);
  9260. +}
  9261. +
  9262. +
  9263. +/* machine stream operations */
  9264. +static struct snd_soc_ops snd_rpi_hifiberry_dacplusadcpro_ops = {
  9265. + .hw_params = snd_rpi_hifiberry_dacplusadcpro_hw_params,
  9266. + .startup = snd_rpi_hifiberry_dacplusadcpro_startup,
  9267. + .shutdown = snd_rpi_hifiberry_dacplusadcpro_shutdown,
  9268. +};
  9269. +
  9270. +SND_SOC_DAILINK_DEFS(hifi,
  9271. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  9272. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi"),
  9273. + COMP_CODEC("pcm186x.1-004a", "pcm1863-aif")),
  9274. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  9275. +
  9276. +static struct snd_soc_dai_link snd_rpi_hifiberry_dacplusadcpro_dai[] = {
  9277. +{
  9278. + .name = "HiFiBerry DAC+ADC PRO",
  9279. + .stream_name = "HiFiBerry DAC+ADC PRO HiFi",
  9280. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  9281. + SND_SOC_DAIFMT_CBS_CFS,
  9282. + .ops = &snd_rpi_hifiberry_dacplusadcpro_ops,
  9283. + .init = snd_rpi_hifiberry_dacplusadcpro_init,
  9284. + SND_SOC_DAILINK_REG(hifi),
  9285. +},
  9286. +};
  9287. +
  9288. +/* aux device for optional headphone amp */
  9289. +static struct snd_soc_aux_dev hifiberry_dacplusadcpro_aux_devs[] = {
  9290. + {
  9291. + .dlc = {
  9292. + .name = "tpa6130a2.1-0060",
  9293. + },
  9294. + },
  9295. +};
  9296. +
  9297. +/* audio machine driver */
  9298. +static struct snd_soc_card snd_rpi_hifiberry_dacplusadcpro = {
  9299. + .name = "snd_rpi_hifiberry_dacplusadcpro",
  9300. + .driver_name = "HifiberryDacpAdcPro",
  9301. + .owner = THIS_MODULE,
  9302. + .dai_link = snd_rpi_hifiberry_dacplusadcpro_dai,
  9303. + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplusadcpro_dai),
  9304. +};
  9305. +
  9306. +static int hb_hp_detect(void)
  9307. +{
  9308. + struct i2c_adapter *adap = i2c_get_adapter(1);
  9309. + int ret;
  9310. + struct i2c_client tpa_i2c_client = {
  9311. + .addr = 0x60,
  9312. + .adapter = adap,
  9313. + };
  9314. +
  9315. + if (!adap)
  9316. + return -EPROBE_DEFER; /* I2C module not yet available */
  9317. +
  9318. + ret = i2c_smbus_read_byte(&tpa_i2c_client) >= 0;
  9319. + i2c_put_adapter(adap);
  9320. + return ret;
  9321. +};
  9322. +
  9323. +static struct property tpa_enable_prop = {
  9324. + .name = "status",
  9325. + .length = 4 + 1, /* length 'okay' + 1 */
  9326. + .value = "okay",
  9327. + };
  9328. +
  9329. +static int snd_rpi_hifiberry_dacplusadcpro_probe(struct platform_device *pdev)
  9330. +{
  9331. + int ret = 0, i = 0;
  9332. + struct snd_soc_card *card = &snd_rpi_hifiberry_dacplusadcpro;
  9333. + struct device_node *tpa_node;
  9334. + struct property *tpa_prop;
  9335. + struct of_changeset ocs;
  9336. + int len;
  9337. +
  9338. + /* probe for head phone amp */
  9339. + ret = hb_hp_detect();
  9340. + if (ret < 0)
  9341. + return ret;
  9342. + if (ret) {
  9343. + card->aux_dev = hifiberry_dacplusadcpro_aux_devs;
  9344. + card->num_aux_devs =
  9345. + ARRAY_SIZE(hifiberry_dacplusadcpro_aux_devs);
  9346. + tpa_node = of_find_compatible_node(NULL, NULL, "ti,tpa6130a2");
  9347. + tpa_prop = of_find_property(tpa_node, "status", &len);
  9348. +
  9349. + if (strcmp((char *)tpa_prop->value, "okay")) {
  9350. + /* and activate headphone using change_sets */
  9351. + dev_info(&pdev->dev, "activating headphone amplifier");
  9352. + of_changeset_init(&ocs);
  9353. + ret = of_changeset_update_property(&ocs, tpa_node,
  9354. + &tpa_enable_prop);
  9355. + if (ret) {
  9356. + dev_err(&pdev->dev,
  9357. + "cannot activate headphone amplifier\n");
  9358. + return -ENODEV;
  9359. + }
  9360. + ret = of_changeset_apply(&ocs);
  9361. + if (ret) {
  9362. + dev_err(&pdev->dev,
  9363. + "cannot activate headphone amplifier\n");
  9364. + return -ENODEV;
  9365. + }
  9366. + }
  9367. + }
  9368. +
  9369. + snd_rpi_hifiberry_dacplusadcpro.dev = &pdev->dev;
  9370. + if (pdev->dev.of_node) {
  9371. + struct device_node *i2s_node;
  9372. + struct snd_soc_dai_link *dai;
  9373. +
  9374. + dai = &snd_rpi_hifiberry_dacplusadcpro_dai[0];
  9375. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  9376. + "i2s-controller", 0);
  9377. + if (i2s_node) {
  9378. + for (i = 0; i < card->num_links; i++) {
  9379. + dai->cpus->dai_name = NULL;
  9380. + dai->cpus->of_node = i2s_node;
  9381. + dai->platforms->name = NULL;
  9382. + dai->platforms->of_node = i2s_node;
  9383. + }
  9384. + }
  9385. + }
  9386. + digital_gain_0db_limit = !of_property_read_bool(
  9387. + pdev->dev.of_node, "hifiberry-dacplusadcpro,24db_digital_gain");
  9388. + slave = of_property_read_bool(pdev->dev.of_node,
  9389. + "hifiberry-dacplusadcpro,slave");
  9390. + leds_off = of_property_read_bool(pdev->dev.of_node,
  9391. + "hifiberry-dacplusadcpro,leds_off");
  9392. + ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplusadcpro);
  9393. + if (ret && ret != -EPROBE_DEFER)
  9394. + dev_err(&pdev->dev,
  9395. + "snd_soc_register_card() failed: %d\n", ret);
  9396. +
  9397. + return ret;
  9398. +}
  9399. +
  9400. +static const struct of_device_id snd_rpi_hifiberry_dacplusadcpro_of_match[] = {
  9401. + { .compatible = "hifiberry,hifiberry-dacplusadcpro", },
  9402. + {},
  9403. +};
  9404. +
  9405. +MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplusadcpro_of_match);
  9406. +
  9407. +static struct platform_driver snd_rpi_hifiberry_dacplusadcpro_driver = {
  9408. + .driver = {
  9409. + .name = "snd-rpi-hifiberry-dacplusadcpro",
  9410. + .owner = THIS_MODULE,
  9411. + .of_match_table = snd_rpi_hifiberry_dacplusadcpro_of_match,
  9412. + },
  9413. + .probe = snd_rpi_hifiberry_dacplusadcpro_probe,
  9414. +};
  9415. +
  9416. +module_platform_driver(snd_rpi_hifiberry_dacplusadcpro_driver);
  9417. +
  9418. +MODULE_AUTHOR("Joerg Schambacher <[email protected]>");
  9419. +MODULE_AUTHOR("Daniel Matuschek <[email protected]>");
  9420. +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ADC");
  9421. +MODULE_LICENSE("GPL v2");
  9422. --- /dev/null
  9423. +++ b/sound/soc/bcm/hifiberry_dacplusdsp.c
  9424. @@ -0,0 +1,90 @@
  9425. +// SPDX-License-Identifier: GPL-2.0
  9426. +/*
  9427. + * ASoC Driver for HiFiBerry DAC + DSP
  9428. + *
  9429. + * Author: Joerg Schambacher <[email protected]>
  9430. + * Copyright 2018
  9431. + *
  9432. + * This program is free software; you can redistribute it and/or
  9433. + * modify it under the terms of the GNU General Public License
  9434. + * version 2 as published by the Free Software Foundation.
  9435. + *
  9436. + * This program is distributed in the hope that it will be useful, but
  9437. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  9438. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  9439. + * General Public License for more details.
  9440. + */
  9441. +
  9442. +#include <linux/init.h>
  9443. +#include <linux/module.h>
  9444. +#include <linux/of.h>
  9445. +#include <linux/platform_device.h>
  9446. +#include <sound/soc.h>
  9447. +
  9448. +static struct snd_soc_component_driver dacplusdsp_component_driver;
  9449. +
  9450. +static struct snd_soc_dai_driver dacplusdsp_dai = {
  9451. + .name = "dacplusdsp-hifi",
  9452. + .capture = {
  9453. + .stream_name = "DAC+DSP Capture",
  9454. + .channels_min = 2,
  9455. + .channels_max = 2,
  9456. + .rates = SNDRV_PCM_RATE_CONTINUOUS,
  9457. + .formats = SNDRV_PCM_FMTBIT_S16_LE |
  9458. + SNDRV_PCM_FMTBIT_S24_LE |
  9459. + SNDRV_PCM_FMTBIT_S32_LE,
  9460. + },
  9461. + .playback = {
  9462. + .stream_name = "DACP+DSP Playback",
  9463. + .channels_min = 2,
  9464. + .channels_max = 2,
  9465. + .rates = SNDRV_PCM_RATE_CONTINUOUS,
  9466. + .formats = SNDRV_PCM_FMTBIT_S16_LE |
  9467. + SNDRV_PCM_FMTBIT_S24_LE |
  9468. + SNDRV_PCM_FMTBIT_S32_LE,
  9469. + },
  9470. + .symmetric_rate = 1};
  9471. +
  9472. +#ifdef CONFIG_OF
  9473. +static const struct of_device_id dacplusdsp_ids[] = {
  9474. + {
  9475. + .compatible = "hifiberry,dacplusdsp",
  9476. + },
  9477. + {} };
  9478. +MODULE_DEVICE_TABLE(of, dacplusdsp_ids);
  9479. +#endif
  9480. +
  9481. +static int dacplusdsp_platform_probe(struct platform_device *pdev)
  9482. +{
  9483. + int ret;
  9484. +
  9485. + ret = snd_soc_register_component(&pdev->dev,
  9486. + &dacplusdsp_component_driver, &dacplusdsp_dai, 1);
  9487. + if (ret) {
  9488. + pr_alert("snd_soc_register_component failed\n");
  9489. + return ret;
  9490. + }
  9491. +
  9492. + return 0;
  9493. +}
  9494. +
  9495. +static int dacplusdsp_platform_remove(struct platform_device *pdev)
  9496. +{
  9497. + snd_soc_unregister_component(&pdev->dev);
  9498. + return 0;
  9499. +}
  9500. +
  9501. +static struct platform_driver dacplusdsp_driver = {
  9502. + .driver = {
  9503. + .name = "hifiberry-dacplusdsp-codec",
  9504. + .of_match_table = of_match_ptr(dacplusdsp_ids),
  9505. + },
  9506. + .probe = dacplusdsp_platform_probe,
  9507. + .remove = dacplusdsp_platform_remove,
  9508. +};
  9509. +
  9510. +module_platform_driver(dacplusdsp_driver);
  9511. +
  9512. +MODULE_AUTHOR("Joerg Schambacher <[email protected]>");
  9513. +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+DSP");
  9514. +MODULE_LICENSE("GPL v2");
  9515. --- /dev/null
  9516. +++ b/sound/soc/bcm/hifiberry_dacplushd.c
  9517. @@ -0,0 +1,238 @@
  9518. +// SPDX-License-Identifier: GPL-2.0
  9519. +/*
  9520. + * ASoC Driver for HiFiBerry DAC+ HD
  9521. + *
  9522. + * Author: Joerg Schambacher, i2Audio GmbH for HiFiBerry
  9523. + * Copyright 2020
  9524. + *
  9525. + * This program is free software; you can redistribute it and/or
  9526. + * modify it under the terms of the GNU General Public License
  9527. + * version 2 as published by the Free Software Foundation.
  9528. + *
  9529. + * This program is distributed in the hope that it will be useful, but
  9530. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  9531. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  9532. + * General Public License for more details.
  9533. + */
  9534. +
  9535. +#include <linux/module.h>
  9536. +#include <linux/platform_device.h>
  9537. +#include <linux/kernel.h>
  9538. +#include <linux/delay.h>
  9539. +#include <linux/module.h>
  9540. +#include <linux/of.h>
  9541. +#include <linux/delay.h>
  9542. +#include <linux/gpio.h>
  9543. +#include <linux/gpio/consumer.h>
  9544. +#include <sound/core.h>
  9545. +#include <sound/pcm.h>
  9546. +#include <sound/pcm_params.h>
  9547. +#include <sound/soc.h>
  9548. +#include <linux/i2c.h>
  9549. +#include <linux/clk.h>
  9550. +
  9551. +#include "../codecs/pcm179x.h"
  9552. +
  9553. +#define DEFAULT_RATE 44100
  9554. +
  9555. +struct brd_drv_data {
  9556. + struct regmap *regmap;
  9557. + struct clk *sclk;
  9558. +};
  9559. +
  9560. +static struct brd_drv_data drvdata;
  9561. +static struct gpio_desc *reset_gpio;
  9562. +static const unsigned int hb_dacplushd_rates[] = {
  9563. + 192000, 96000, 48000, 176400, 88200, 44100,
  9564. +};
  9565. +
  9566. +static struct snd_pcm_hw_constraint_list hb_dacplushd_constraints = {
  9567. + .list = hb_dacplushd_rates,
  9568. + .count = ARRAY_SIZE(hb_dacplushd_rates),
  9569. +};
  9570. +
  9571. +static int snd_rpi_hb_dacplushd_startup(struct snd_pcm_substream *substream)
  9572. +{
  9573. + /* constraints for standard sample rates */
  9574. + snd_pcm_hw_constraint_list(substream->runtime, 0,
  9575. + SNDRV_PCM_HW_PARAM_RATE,
  9576. + &hb_dacplushd_constraints);
  9577. + return 0;
  9578. +}
  9579. +
  9580. +static void snd_rpi_hifiberry_dacplushd_set_sclk(
  9581. + struct snd_soc_component *component,
  9582. + int sample_rate)
  9583. +{
  9584. + if (!IS_ERR(drvdata.sclk))
  9585. + clk_set_rate(drvdata.sclk, sample_rate);
  9586. +}
  9587. +
  9588. +static int snd_rpi_hifiberry_dacplushd_init(struct snd_soc_pcm_runtime *rtd)
  9589. +{
  9590. + struct snd_soc_dai_link *dai = rtd->dai_link;
  9591. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  9592. +
  9593. + dai->name = "HiFiBerry DAC+ HD";
  9594. + dai->stream_name = "HiFiBerry DAC+ HD HiFi";
  9595. + dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
  9596. + | SND_SOC_DAIFMT_CBM_CFM;
  9597. +
  9598. + /* allow only fixed 32 clock counts per channel */
  9599. + snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2);
  9600. +
  9601. + return 0;
  9602. +}
  9603. +
  9604. +static int snd_rpi_hifiberry_dacplushd_hw_params(
  9605. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  9606. +{
  9607. + int ret = 0;
  9608. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  9609. +
  9610. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  9611. +
  9612. + snd_rpi_hifiberry_dacplushd_set_sclk(component, params_rate(params));
  9613. + return ret;
  9614. +}
  9615. +
  9616. +/* machine stream operations */
  9617. +static struct snd_soc_ops snd_rpi_hifiberry_dacplushd_ops = {
  9618. + .startup = snd_rpi_hb_dacplushd_startup,
  9619. + .hw_params = snd_rpi_hifiberry_dacplushd_hw_params,
  9620. +};
  9621. +
  9622. +SND_SOC_DAILINK_DEFS(hifi,
  9623. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  9624. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm179x.1-004c", "pcm179x-hifi")),
  9625. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  9626. +
  9627. +
  9628. +static struct snd_soc_dai_link snd_rpi_hifiberry_dacplushd_dai[] = {
  9629. +{
  9630. + .name = "HiFiBerry DAC+ HD",
  9631. + .stream_name = "HiFiBerry DAC+ HD HiFi",
  9632. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  9633. + SND_SOC_DAIFMT_CBS_CFS,
  9634. + .ops = &snd_rpi_hifiberry_dacplushd_ops,
  9635. + .init = snd_rpi_hifiberry_dacplushd_init,
  9636. + SND_SOC_DAILINK_REG(hifi),
  9637. +},
  9638. +};
  9639. +
  9640. +/* audio machine driver */
  9641. +static struct snd_soc_card snd_rpi_hifiberry_dacplushd = {
  9642. + .name = "snd_rpi_hifiberry_dacplushd",
  9643. + .driver_name = "HifiberryDacplusHD",
  9644. + .owner = THIS_MODULE,
  9645. + .dai_link = snd_rpi_hifiberry_dacplushd_dai,
  9646. + .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplushd_dai),
  9647. +};
  9648. +
  9649. +static int snd_rpi_hifiberry_dacplushd_probe(struct platform_device *pdev)
  9650. +{
  9651. + int ret = 0;
  9652. + static int dac_reset_done;
  9653. + struct device *dev = &pdev->dev;
  9654. + struct device_node *dev_node = dev->of_node;
  9655. +
  9656. + snd_rpi_hifiberry_dacplushd.dev = &pdev->dev;
  9657. +
  9658. + /* get GPIO and release DAC from RESET */
  9659. + if (!dac_reset_done) {
  9660. + reset_gpio = gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
  9661. + if (IS_ERR(reset_gpio)) {
  9662. + dev_err(&pdev->dev, "gpiod_get() failed\n");
  9663. + return -EINVAL;
  9664. + }
  9665. + dac_reset_done = 1;
  9666. + }
  9667. + if (!IS_ERR(reset_gpio))
  9668. + gpiod_set_value(reset_gpio, 0);
  9669. + msleep(1);
  9670. + if (!IS_ERR(reset_gpio))
  9671. + gpiod_set_value(reset_gpio, 1);
  9672. + msleep(1);
  9673. + if (!IS_ERR(reset_gpio))
  9674. + gpiod_set_value(reset_gpio, 0);
  9675. +
  9676. + if (pdev->dev.of_node) {
  9677. + struct device_node *i2s_node;
  9678. + struct snd_soc_dai_link *dai;
  9679. +
  9680. + dai = &snd_rpi_hifiberry_dacplushd_dai[0];
  9681. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  9682. + "i2s-controller", 0);
  9683. +
  9684. + if (i2s_node) {
  9685. + dai->cpus->of_node = i2s_node;
  9686. + dai->platforms->of_node = i2s_node;
  9687. + dai->cpus->dai_name = NULL;
  9688. + dai->platforms->name = NULL;
  9689. + } else {
  9690. + return -EPROBE_DEFER;
  9691. + }
  9692. +
  9693. + }
  9694. +
  9695. + ret = devm_snd_soc_register_card(&pdev->dev,
  9696. + &snd_rpi_hifiberry_dacplushd);
  9697. + if (ret && ret != -EPROBE_DEFER) {
  9698. + dev_err(&pdev->dev,
  9699. + "snd_soc_register_card() failed: %d\n", ret);
  9700. + return ret;
  9701. + }
  9702. + if (ret == -EPROBE_DEFER)
  9703. + return ret;
  9704. +
  9705. + dev_set_drvdata(dev, &drvdata);
  9706. + if (dev_node == NULL) {
  9707. + dev_err(&pdev->dev, "Device tree node not found\n");
  9708. + return -ENODEV;
  9709. + }
  9710. +
  9711. + drvdata.sclk = devm_clk_get(dev, NULL);
  9712. + if (IS_ERR(drvdata.sclk)) {
  9713. + drvdata.sclk = ERR_PTR(-ENOENT);
  9714. + return -ENODEV;
  9715. + }
  9716. +
  9717. + clk_set_rate(drvdata.sclk, DEFAULT_RATE);
  9718. +
  9719. + return ret;
  9720. +}
  9721. +
  9722. +static int snd_rpi_hifiberry_dacplushd_remove(struct platform_device *pdev)
  9723. +{
  9724. + if (IS_ERR(reset_gpio))
  9725. + return -EINVAL;
  9726. +
  9727. + /* put DAC into RESET and release GPIO */
  9728. + gpiod_set_value(reset_gpio, 0);
  9729. + gpiod_put(reset_gpio);
  9730. +
  9731. + return 0;
  9732. +}
  9733. +
  9734. +static const struct of_device_id snd_rpi_hifiberry_dacplushd_of_match[] = {
  9735. + { .compatible = "hifiberry,hifiberry-dacplushd", },
  9736. + {},
  9737. +};
  9738. +
  9739. +MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplushd_of_match);
  9740. +
  9741. +static struct platform_driver snd_rpi_hifiberry_dacplushd_driver = {
  9742. + .driver = {
  9743. + .name = "snd-rpi-hifiberry-dacplushd",
  9744. + .owner = THIS_MODULE,
  9745. + .of_match_table = snd_rpi_hifiberry_dacplushd_of_match,
  9746. + },
  9747. + .probe = snd_rpi_hifiberry_dacplushd_probe,
  9748. + .remove = snd_rpi_hifiberry_dacplushd_remove,
  9749. +};
  9750. +
  9751. +module_platform_driver(snd_rpi_hifiberry_dacplushd_driver);
  9752. +
  9753. +MODULE_AUTHOR("Joerg Schambacher <[email protected]>");
  9754. +MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+ HD");
  9755. +MODULE_LICENSE("GPL v2");
  9756. --- /dev/null
  9757. +++ b/sound/soc/bcm/i-sabre-q2m.c
  9758. @@ -0,0 +1,159 @@
  9759. +/*
  9760. + * ASoC Driver for I-Sabre Q2M
  9761. + *
  9762. + * Author: Satoru Kawase
  9763. + * Modified by: Xiao Qingyong
  9764. + * Update kernel v4.18+ by : Audiophonics
  9765. + * Copyright 2018 Audiophonics
  9766. + *
  9767. + * This program is free software; you can redistribute it and/or
  9768. + * modify it under the terms of the GNU General Public License
  9769. + * version 2 as published by the Free Software Foundation.
  9770. + *
  9771. + * This program is distributed in the hope that it will be useful, but
  9772. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  9773. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  9774. + * General Public License for more details.
  9775. + */
  9776. +
  9777. +#include <linux/kernel.h>
  9778. +#include <linux/init.h>
  9779. +#include <linux/module.h>
  9780. +#include <linux/delay.h>
  9781. +#include <linux/fs.h>
  9782. +#include <asm/uaccess.h>
  9783. +#include <sound/core.h>
  9784. +#include <sound/soc.h>
  9785. +#include <sound/pcm.h>
  9786. +#include <sound/pcm_params.h>
  9787. +
  9788. +#include "../codecs/i-sabre-codec.h"
  9789. +
  9790. +
  9791. +static int snd_rpi_i_sabre_q2m_init(struct snd_soc_pcm_runtime *rtd)
  9792. +{
  9793. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  9794. + unsigned int value;
  9795. +
  9796. + /* Device ID */
  9797. + value = snd_soc_component_read(component, ISABRECODEC_REG_01);
  9798. + dev_info(component->card->dev, "Audiophonics Device ID : %02X\n", value);
  9799. +
  9800. + /* API revision */
  9801. + value = snd_soc_component_read(component, ISABRECODEC_REG_02);
  9802. + dev_info(component->card->dev, "Audiophonics API revision : %02X\n", value);
  9803. +
  9804. + return 0;
  9805. +}
  9806. +
  9807. +static int snd_rpi_i_sabre_q2m_hw_params(
  9808. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params)
  9809. +{
  9810. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  9811. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  9812. + int bclk_ratio;
  9813. +
  9814. + bclk_ratio = snd_pcm_format_physical_width(
  9815. + params_format(params)) * params_channels(params);
  9816. + return snd_soc_dai_set_bclk_ratio(cpu_dai, bclk_ratio);
  9817. +}
  9818. +
  9819. +/* machine stream operations */
  9820. +static struct snd_soc_ops snd_rpi_i_sabre_q2m_ops = {
  9821. + .hw_params = snd_rpi_i_sabre_q2m_hw_params,
  9822. +};
  9823. +
  9824. +SND_SOC_DAILINK_DEFS(rpi_i_sabre_q2m,
  9825. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  9826. + DAILINK_COMP_ARRAY(COMP_CODEC("i-sabre-codec-i2c.1-0048", "i-sabre-codec-dai")),
  9827. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  9828. +
  9829. +static struct snd_soc_dai_link snd_rpi_i_sabre_q2m_dai[] = {
  9830. + {
  9831. + .name = "I-Sabre Q2M",
  9832. + .stream_name = "I-Sabre Q2M DAC",
  9833. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
  9834. + | SND_SOC_DAIFMT_CBS_CFS,
  9835. + .init = snd_rpi_i_sabre_q2m_init,
  9836. + .ops = &snd_rpi_i_sabre_q2m_ops,
  9837. + SND_SOC_DAILINK_REG(rpi_i_sabre_q2m),
  9838. + }
  9839. +};
  9840. +
  9841. +/* audio machine driver */
  9842. +static struct snd_soc_card snd_rpi_i_sabre_q2m = {
  9843. + .name = "I-Sabre Q2M DAC",
  9844. + .owner = THIS_MODULE,
  9845. + .dai_link = snd_rpi_i_sabre_q2m_dai,
  9846. + .num_links = ARRAY_SIZE(snd_rpi_i_sabre_q2m_dai)
  9847. +};
  9848. +
  9849. +
  9850. +static int snd_rpi_i_sabre_q2m_probe(struct platform_device *pdev)
  9851. +{
  9852. + int ret = 0;
  9853. +
  9854. + snd_rpi_i_sabre_q2m.dev = &pdev->dev;
  9855. + if (pdev->dev.of_node) {
  9856. + struct device_node *i2s_node;
  9857. + struct snd_soc_dai_link *dai;
  9858. +
  9859. + dai = &snd_rpi_i_sabre_q2m_dai[0];
  9860. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  9861. + "i2s-controller", 0);
  9862. + if (i2s_node) {
  9863. + dai->cpus->dai_name = NULL;
  9864. + dai->cpus->of_node = i2s_node;
  9865. + dai->platforms->name = NULL;
  9866. + dai->platforms->of_node = i2s_node;
  9867. + } else {
  9868. + dev_err(&pdev->dev,
  9869. + "Property 'i2s-controller' missing or invalid\n");
  9870. + return (-EINVAL);
  9871. + }
  9872. +
  9873. + dai->name = "I-Sabre Q2M";
  9874. + dai->stream_name = "I-Sabre Q2M DAC";
  9875. + dai->dai_fmt = SND_SOC_DAIFMT_I2S
  9876. + | SND_SOC_DAIFMT_NB_NF
  9877. + | SND_SOC_DAIFMT_CBS_CFS;
  9878. + }
  9879. +
  9880. + /* Wait for registering codec driver */
  9881. + mdelay(50);
  9882. +
  9883. + ret = snd_soc_register_card(&snd_rpi_i_sabre_q2m);
  9884. + if (ret) {
  9885. + dev_err(&pdev->dev,
  9886. + "snd_soc_register_card() failed: %d\n", ret);
  9887. + }
  9888. +
  9889. + return ret;
  9890. +}
  9891. +
  9892. +static int snd_rpi_i_sabre_q2m_remove(struct platform_device *pdev)
  9893. +{
  9894. + snd_soc_unregister_card(&snd_rpi_i_sabre_q2m);
  9895. + return 0;
  9896. +}
  9897. +
  9898. +static const struct of_device_id snd_rpi_i_sabre_q2m_of_match[] = {
  9899. + { .compatible = "audiophonics,i-sabre-q2m", },
  9900. + {}
  9901. +};
  9902. +MODULE_DEVICE_TABLE(of, snd_rpi_i_sabre_q2m_of_match);
  9903. +
  9904. +static struct platform_driver snd_rpi_i_sabre_q2m_driver = {
  9905. + .driver = {
  9906. + .name = "snd-rpi-i-sabre-q2m",
  9907. + .owner = THIS_MODULE,
  9908. + .of_match_table = snd_rpi_i_sabre_q2m_of_match,
  9909. + },
  9910. + .probe = snd_rpi_i_sabre_q2m_probe,
  9911. + .remove = snd_rpi_i_sabre_q2m_remove,
  9912. +};
  9913. +module_platform_driver(snd_rpi_i_sabre_q2m_driver);
  9914. +
  9915. +MODULE_DESCRIPTION("ASoC Driver for I-Sabre Q2M");
  9916. +MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
  9917. +MODULE_LICENSE("GPL");
  9918. --- /dev/null
  9919. +++ b/sound/soc/bcm/iqaudio-codec.c
  9920. @@ -0,0 +1,278 @@
  9921. +/*
  9922. + * ASoC Driver for IQaudIO Raspberry Pi Codec board
  9923. + *
  9924. + * Author: Gordon Garrity <[email protected]>
  9925. + * (C) Copyright IQaudio Limited, 2017-2019
  9926. + *
  9927. + * This program is free software; you can redistribute it and/or
  9928. + * modify it under the terms of the GNU General Public License
  9929. + * version 2 as published by the Free Software Foundation.
  9930. + *
  9931. + * This program is distributed in the hope that it will be useful, but
  9932. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  9933. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  9934. + * General Public License for more details.
  9935. + */
  9936. +
  9937. +#include <linux/module.h>
  9938. +#include <linux/gpio/consumer.h>
  9939. +#include <linux/platform_device.h>
  9940. +
  9941. +#include <sound/core.h>
  9942. +#include <sound/pcm.h>
  9943. +#include <sound/pcm_params.h>
  9944. +#include <sound/soc.h>
  9945. +#include <sound/jack.h>
  9946. +
  9947. +#include <linux/acpi.h>
  9948. +#include <linux/slab.h>
  9949. +#include "../codecs/da7213.h"
  9950. +
  9951. +static int pll_out = DA7213_PLL_FREQ_OUT_90316800;
  9952. +
  9953. +static int snd_rpi_iqaudio_pll_control(struct snd_soc_dapm_widget *w,
  9954. + struct snd_kcontrol *k, int event)
  9955. +{
  9956. + int ret = 0;
  9957. + struct snd_soc_dapm_context *dapm = w->dapm;
  9958. + struct snd_soc_card *card = dapm->card;
  9959. + struct snd_soc_pcm_runtime *rtd =
  9960. + snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  9961. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  9962. +
  9963. + if (SND_SOC_DAPM_EVENT_OFF(event)) {
  9964. + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_MCLK, 0,
  9965. + 0);
  9966. + if (ret)
  9967. + dev_err(card->dev, "Failed to bypass PLL: %d\n", ret);
  9968. + /* Allow PLL time to bypass */
  9969. + msleep(100);
  9970. + } else if (SND_SOC_DAPM_EVENT_ON(event)) {
  9971. + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0,
  9972. + pll_out);
  9973. + if (ret)
  9974. + dev_err(card->dev, "Failed to enable PLL: %d\n", ret);
  9975. + /* Allow PLL time to lock */
  9976. + msleep(100);
  9977. + }
  9978. +
  9979. + return ret;
  9980. +}
  9981. +
  9982. +static int snd_rpi_iqaudio_post_dapm_event(struct snd_soc_dapm_widget *w,
  9983. + struct snd_kcontrol *kcontrol,
  9984. + int event)
  9985. +{
  9986. + switch (event) {
  9987. + case SND_SOC_DAPM_POST_PMU:
  9988. + /* Delay for mic bias ramp */
  9989. + msleep(1000);
  9990. + break;
  9991. + default:
  9992. + break;
  9993. + }
  9994. +
  9995. + return 0;
  9996. +}
  9997. +
  9998. +static const struct snd_kcontrol_new dapm_controls[] = {
  9999. + SOC_DAPM_PIN_SWITCH("HP Jack"),
  10000. + SOC_DAPM_PIN_SWITCH("MIC Jack"),
  10001. + SOC_DAPM_PIN_SWITCH("Onboard MIC"),
  10002. + SOC_DAPM_PIN_SWITCH("AUX Jack"),
  10003. +};
  10004. +
  10005. +static const struct snd_soc_dapm_widget dapm_widgets[] = {
  10006. + SND_SOC_DAPM_HP("HP Jack", NULL),
  10007. + SND_SOC_DAPM_MIC("MIC Jack", NULL),
  10008. + SND_SOC_DAPM_MIC("Onboard MIC", NULL),
  10009. + SND_SOC_DAPM_LINE("AUX Jack", NULL),
  10010. + SND_SOC_DAPM_SUPPLY("PLL Control", SND_SOC_NOPM, 0, 0,
  10011. + snd_rpi_iqaudio_pll_control,
  10012. + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  10013. + SND_SOC_DAPM_POST("Post Power Up Event", snd_rpi_iqaudio_post_dapm_event),
  10014. +};
  10015. +
  10016. +static const struct snd_soc_dapm_route audio_map[] = {
  10017. + {"HP Jack", NULL, "HPL"},
  10018. + {"HP Jack", NULL, "HPR"},
  10019. + {"HP Jack", NULL, "PLL Control"},
  10020. +
  10021. + {"AUXR", NULL, "AUX Jack"},
  10022. + {"AUXL", NULL, "AUX Jack"},
  10023. + {"AUX Jack", NULL, "PLL Control"},
  10024. +
  10025. + /* Assume Mic1 is linked to Headset and Mic2 to on-board mic */
  10026. + {"MIC1", NULL, "MIC Jack"},
  10027. + {"MIC Jack", NULL, "PLL Control"},
  10028. + {"MIC2", NULL, "Onboard MIC"},
  10029. + {"Onboard MIC", NULL, "PLL Control"},
  10030. +};
  10031. +
  10032. +/* machine stream operations */
  10033. +
  10034. +static int snd_rpi_iqaudio_codec_init(struct snd_soc_pcm_runtime *rtd)
  10035. +{
  10036. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  10037. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  10038. + int ret;
  10039. +
  10040. + /*
  10041. + * Disable AUX Jack Pin by default to prevent PLL being enabled at
  10042. + * startup. This avoids holding the PLL to a fixed SR config for
  10043. + * subsequent streams.
  10044. + *
  10045. + * This pin can still be enabled later, as required by user-space.
  10046. + */
  10047. + snd_soc_dapm_disable_pin(&rtd->card->dapm, "AUX Jack");
  10048. + snd_soc_dapm_sync(&rtd->card->dapm);
  10049. +
  10050. + /* Set bclk ratio to align with codec's BCLK rate */
  10051. + ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
  10052. + if (ret) {
  10053. + dev_err(rtd->dev, "Failed to set CPU BLCK ratio\n");
  10054. + return ret;
  10055. + }
  10056. +
  10057. + /* Set MCLK frequency to codec, onboard 11.2896MHz clock */
  10058. + return snd_soc_dai_set_sysclk(codec_dai, DA7213_CLKSRC_MCLK, 11289600,
  10059. + SND_SOC_CLOCK_OUT);
  10060. +}
  10061. +
  10062. +static int snd_rpi_iqaudio_codec_hw_params(struct snd_pcm_substream *substream,
  10063. + struct snd_pcm_hw_params *params)
  10064. +{
  10065. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  10066. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  10067. + unsigned int samplerate = params_rate(params);
  10068. +
  10069. + switch (samplerate) {
  10070. + case 8000:
  10071. + case 16000:
  10072. + case 32000:
  10073. + case 48000:
  10074. + case 96000:
  10075. + pll_out = DA7213_PLL_FREQ_OUT_98304000;
  10076. + break;
  10077. + case 44100:
  10078. + case 88200:
  10079. + pll_out = DA7213_PLL_FREQ_OUT_90316800;
  10080. + break;
  10081. + default:
  10082. + dev_err(rtd->dev,"Unsupported samplerate %d\n", samplerate);
  10083. + return -EINVAL;
  10084. + }
  10085. +
  10086. + return snd_soc_dai_set_pll(codec_dai, 0, DA7213_SYSCLK_PLL, 0, pll_out);
  10087. +}
  10088. +
  10089. +static const struct snd_soc_ops snd_rpi_iqaudio_codec_ops = {
  10090. + .hw_params = snd_rpi_iqaudio_codec_hw_params,
  10091. +};
  10092. +
  10093. +SND_SOC_DAILINK_DEFS(rpi_iqaudio,
  10094. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  10095. + DAILINK_COMP_ARRAY(COMP_CODEC("da7213.1-001a", "da7213-hifi")),
  10096. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2835-i2s.0")));
  10097. +
  10098. +static struct snd_soc_dai_link snd_rpi_iqaudio_codec_dai[] = {
  10099. +{
  10100. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  10101. + SND_SOC_DAIFMT_CBM_CFM,
  10102. + .init = snd_rpi_iqaudio_codec_init,
  10103. + .ops = &snd_rpi_iqaudio_codec_ops,
  10104. + .symmetric_rate = 1,
  10105. + .symmetric_channels = 1,
  10106. + .symmetric_sample_bits = 1,
  10107. + SND_SOC_DAILINK_REG(rpi_iqaudio),
  10108. +},
  10109. +};
  10110. +
  10111. +/* audio machine driver */
  10112. +static struct snd_soc_card snd_rpi_iqaudio_codec = {
  10113. + .owner = THIS_MODULE,
  10114. + .dai_link = snd_rpi_iqaudio_codec_dai,
  10115. + .num_links = ARRAY_SIZE(snd_rpi_iqaudio_codec_dai),
  10116. + .controls = dapm_controls,
  10117. + .num_controls = ARRAY_SIZE(dapm_controls),
  10118. + .dapm_widgets = dapm_widgets,
  10119. + .num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
  10120. + .dapm_routes = audio_map,
  10121. + .num_dapm_routes = ARRAY_SIZE(audio_map),
  10122. +};
  10123. +
  10124. +static int snd_rpi_iqaudio_codec_probe(struct platform_device *pdev)
  10125. +{
  10126. + int ret = 0;
  10127. +
  10128. + snd_rpi_iqaudio_codec.dev = &pdev->dev;
  10129. +
  10130. + if (pdev->dev.of_node) {
  10131. + struct device_node *i2s_node;
  10132. + struct snd_soc_card *card = &snd_rpi_iqaudio_codec;
  10133. + struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_codec_dai[0];
  10134. +
  10135. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  10136. + "i2s-controller", 0);
  10137. + if (i2s_node) {
  10138. + dai->cpus->dai_name = NULL;
  10139. + dai->cpus->of_node = i2s_node;
  10140. + dai->platforms->name = NULL;
  10141. + dai->platforms->of_node = i2s_node;
  10142. + }
  10143. +
  10144. + if (of_property_read_string(pdev->dev.of_node, "card_name",
  10145. + &card->name))
  10146. + card->name = "IQaudIOCODEC";
  10147. +
  10148. + if (of_property_read_string(pdev->dev.of_node, "dai_name",
  10149. + &dai->name))
  10150. + dai->name = "IQaudIO CODEC";
  10151. +
  10152. + if (of_property_read_string(pdev->dev.of_node,
  10153. + "dai_stream_name", &dai->stream_name))
  10154. + dai->stream_name = "IQaudIO CODEC HiFi v1.2";
  10155. +
  10156. + }
  10157. +
  10158. + ret = snd_soc_register_card(&snd_rpi_iqaudio_codec);
  10159. + if (ret) {
  10160. + if (ret != -EPROBE_DEFER)
  10161. + dev_err(&pdev->dev,
  10162. + "snd_soc_register_card() failed: %d\n", ret);
  10163. + return ret;
  10164. + }
  10165. +
  10166. + return 0;
  10167. +}
  10168. +
  10169. +static int snd_rpi_iqaudio_codec_remove(struct platform_device *pdev)
  10170. +{
  10171. + snd_soc_unregister_card(&snd_rpi_iqaudio_codec);
  10172. + return 0;
  10173. +}
  10174. +
  10175. +static const struct of_device_id iqaudio_of_match[] = {
  10176. + { .compatible = "iqaudio,iqaudio-codec", },
  10177. + {},
  10178. +};
  10179. +
  10180. +MODULE_DEVICE_TABLE(of, iqaudio_of_match);
  10181. +
  10182. +static struct platform_driver snd_rpi_iqaudio_codec_driver = {
  10183. + .driver = {
  10184. + .name = "snd-rpi-iqaudio-codec",
  10185. + .owner = THIS_MODULE,
  10186. + .of_match_table = iqaudio_of_match,
  10187. + },
  10188. + .probe = snd_rpi_iqaudio_codec_probe,
  10189. + .remove = snd_rpi_iqaudio_codec_remove,
  10190. +};
  10191. +
  10192. +
  10193. +
  10194. +module_platform_driver(snd_rpi_iqaudio_codec_driver);
  10195. +
  10196. +MODULE_AUTHOR("Gordon Garrity <[email protected]>");
  10197. +MODULE_DESCRIPTION("ASoC Driver for IQaudIO CODEC");
  10198. +MODULE_LICENSE("GPL v2");
  10199. --- /dev/null
  10200. +++ b/sound/soc/bcm/iqaudio-dac.c
  10201. @@ -0,0 +1,224 @@
  10202. +/*
  10203. + * ASoC Driver for IQaudIO DAC
  10204. + *
  10205. + * Author: Florian Meier <[email protected]>
  10206. + * Copyright 2013
  10207. + *
  10208. + * This program is free software; you can redistribute it and/or
  10209. + * modify it under the terms of the GNU General Public License
  10210. + * version 2 as published by the Free Software Foundation.
  10211. + *
  10212. + * This program is distributed in the hope that it will be useful, but
  10213. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  10214. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10215. + * General Public License for more details.
  10216. + */
  10217. +
  10218. +#include <linux/module.h>
  10219. +#include <linux/gpio/consumer.h>
  10220. +#include <linux/platform_device.h>
  10221. +
  10222. +#include <sound/core.h>
  10223. +#include <sound/pcm.h>
  10224. +#include <sound/pcm_params.h>
  10225. +#include <sound/soc.h>
  10226. +#include <sound/jack.h>
  10227. +
  10228. +static bool digital_gain_0db_limit = true;
  10229. +
  10230. +static struct gpio_desc *mute_gpio;
  10231. +
  10232. +static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd)
  10233. +{
  10234. + if (digital_gain_0db_limit)
  10235. + {
  10236. + int ret;
  10237. + struct snd_soc_card *card = rtd->card;
  10238. +
  10239. + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
  10240. + if (ret < 0)
  10241. + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
  10242. + }
  10243. +
  10244. + return 0;
  10245. +}
  10246. +
  10247. +static void snd_rpi_iqaudio_gpio_mute(struct snd_soc_card *card)
  10248. +{
  10249. + if (mute_gpio) {
  10250. + dev_info(card->dev, "%s: muting amp using GPIO22\n",
  10251. + __func__);
  10252. + gpiod_set_value_cansleep(mute_gpio, 0);
  10253. + }
  10254. +}
  10255. +
  10256. +static void snd_rpi_iqaudio_gpio_unmute(struct snd_soc_card *card)
  10257. +{
  10258. + if (mute_gpio) {
  10259. + dev_info(card->dev, "%s: un-muting amp using GPIO22\n",
  10260. + __func__);
  10261. + gpiod_set_value_cansleep(mute_gpio, 1);
  10262. + }
  10263. +}
  10264. +
  10265. +static int snd_rpi_iqaudio_set_bias_level(struct snd_soc_card *card,
  10266. + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
  10267. +{
  10268. + struct snd_soc_pcm_runtime *rtd;
  10269. + struct snd_soc_dai *codec_dai;
  10270. +
  10271. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  10272. + codec_dai = asoc_rtd_to_codec(rtd, 0);
  10273. +
  10274. + if (dapm->dev != codec_dai->dev)
  10275. + return 0;
  10276. +
  10277. + switch (level) {
  10278. + case SND_SOC_BIAS_PREPARE:
  10279. + if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
  10280. + break;
  10281. +
  10282. + /* UNMUTE AMP */
  10283. + snd_rpi_iqaudio_gpio_unmute(card);
  10284. +
  10285. + break;
  10286. + case SND_SOC_BIAS_STANDBY:
  10287. + if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
  10288. + break;
  10289. +
  10290. + /* MUTE AMP */
  10291. + snd_rpi_iqaudio_gpio_mute(card);
  10292. +
  10293. + break;
  10294. + default:
  10295. + break;
  10296. + }
  10297. +
  10298. + return 0;
  10299. +}
  10300. +
  10301. +SND_SOC_DAILINK_DEFS(hifi,
  10302. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  10303. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004c", "pcm512x-hifi")),
  10304. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  10305. +
  10306. +static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = {
  10307. +{
  10308. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  10309. + SND_SOC_DAIFMT_CBS_CFS,
  10310. + .init = snd_rpi_iqaudio_dac_init,
  10311. + SND_SOC_DAILINK_REG(hifi),
  10312. +},
  10313. +};
  10314. +
  10315. +/* audio machine driver */
  10316. +static struct snd_soc_card snd_rpi_iqaudio_dac = {
  10317. + .owner = THIS_MODULE,
  10318. + .dai_link = snd_rpi_iqaudio_dac_dai,
  10319. + .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai),
  10320. +};
  10321. +
  10322. +static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev)
  10323. +{
  10324. + int ret = 0;
  10325. + bool gpio_unmute = false;
  10326. +
  10327. + snd_rpi_iqaudio_dac.dev = &pdev->dev;
  10328. +
  10329. + if (pdev->dev.of_node) {
  10330. + struct device_node *i2s_node;
  10331. + struct snd_soc_card *card = &snd_rpi_iqaudio_dac;
  10332. + struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_dac_dai[0];
  10333. + bool auto_gpio_mute = false;
  10334. +
  10335. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  10336. + "i2s-controller", 0);
  10337. + if (i2s_node) {
  10338. + dai->cpus->dai_name = NULL;
  10339. + dai->cpus->of_node = i2s_node;
  10340. + dai->platforms->name = NULL;
  10341. + dai->platforms->of_node = i2s_node;
  10342. + }
  10343. +
  10344. + digital_gain_0db_limit = !of_property_read_bool(
  10345. + pdev->dev.of_node, "iqaudio,24db_digital_gain");
  10346. +
  10347. + if (of_property_read_string(pdev->dev.of_node, "card_name",
  10348. + &card->name))
  10349. + card->name = "IQaudIODAC";
  10350. +
  10351. + if (of_property_read_string(pdev->dev.of_node, "dai_name",
  10352. + &dai->name))
  10353. + dai->name = "IQaudIO DAC";
  10354. +
  10355. + if (of_property_read_string(pdev->dev.of_node,
  10356. + "dai_stream_name", &dai->stream_name))
  10357. + dai->stream_name = "IQaudIO DAC HiFi";
  10358. +
  10359. + /* gpio_unmute - one time unmute amp using GPIO */
  10360. + gpio_unmute = of_property_read_bool(pdev->dev.of_node,
  10361. + "iqaudio-dac,unmute-amp");
  10362. +
  10363. + /* auto_gpio_mute - mute/unmute amp using GPIO */
  10364. + auto_gpio_mute = of_property_read_bool(pdev->dev.of_node,
  10365. + "iqaudio-dac,auto-mute-amp");
  10366. +
  10367. + if (auto_gpio_mute || gpio_unmute) {
  10368. + mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute",
  10369. + GPIOD_OUT_LOW);
  10370. + if (IS_ERR(mute_gpio)) {
  10371. + ret = PTR_ERR(mute_gpio);
  10372. + dev_err(&pdev->dev,
  10373. + "Failed to get mute gpio: %d\n", ret);
  10374. + return ret;
  10375. + }
  10376. +
  10377. + if (auto_gpio_mute && mute_gpio)
  10378. + snd_rpi_iqaudio_dac.set_bias_level =
  10379. + snd_rpi_iqaudio_set_bias_level;
  10380. + }
  10381. + }
  10382. +
  10383. + ret = snd_soc_register_card(&snd_rpi_iqaudio_dac);
  10384. + if (ret) {
  10385. + if (ret != -EPROBE_DEFER)
  10386. + dev_err(&pdev->dev,
  10387. + "snd_soc_register_card() failed: %d\n", ret);
  10388. + return ret;
  10389. + }
  10390. +
  10391. + if (gpio_unmute && mute_gpio)
  10392. + snd_rpi_iqaudio_gpio_unmute(&snd_rpi_iqaudio_dac);
  10393. +
  10394. + return 0;
  10395. +}
  10396. +
  10397. +static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev)
  10398. +{
  10399. + snd_rpi_iqaudio_gpio_mute(&snd_rpi_iqaudio_dac);
  10400. +
  10401. + snd_soc_unregister_card(&snd_rpi_iqaudio_dac);
  10402. + return 0;
  10403. +}
  10404. +
  10405. +static const struct of_device_id iqaudio_of_match[] = {
  10406. + { .compatible = "iqaudio,iqaudio-dac", },
  10407. + {},
  10408. +};
  10409. +MODULE_DEVICE_TABLE(of, iqaudio_of_match);
  10410. +
  10411. +static struct platform_driver snd_rpi_iqaudio_dac_driver = {
  10412. + .driver = {
  10413. + .name = "snd-rpi-iqaudio-dac",
  10414. + .owner = THIS_MODULE,
  10415. + .of_match_table = iqaudio_of_match,
  10416. + },
  10417. + .probe = snd_rpi_iqaudio_dac_probe,
  10418. + .remove = snd_rpi_iqaudio_dac_remove,
  10419. +};
  10420. +
  10421. +module_platform_driver(snd_rpi_iqaudio_dac_driver);
  10422. +
  10423. +MODULE_AUTHOR("Florian Meier <[email protected]>");
  10424. +MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC");
  10425. +MODULE_LICENSE("GPL v2");
  10426. --- /dev/null
  10427. +++ b/sound/soc/bcm/justboom-both.c
  10428. @@ -0,0 +1,267 @@
  10429. +// SPDX-License-Identifier: GPL-2.0
  10430. +/*
  10431. + * rpi--wm8804.c -- ALSA SoC Raspberry Pi soundcard.
  10432. + *
  10433. + * Authors: Johannes Krude <[email protected]
  10434. + *
  10435. + * Driver for when connecting simultaneously justboom-digi and justboom-dac
  10436. + *
  10437. + * Based upon code from:
  10438. + * justboom-digi.c
  10439. + * by Milan Neskovic <[email protected]>
  10440. + * justboom-dac.c
  10441. + * by Milan Neskovic <[email protected]>
  10442. + *
  10443. + * This program is free software; you can redistribute it and/or
  10444. + * modify it under the terms of the GNU General Public License
  10445. + * version 2 as published by the Free Software Foundation.
  10446. + *
  10447. + * This program is distributed in the hope that it will be useful, but
  10448. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  10449. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10450. + * General Public License for more details.
  10451. + */
  10452. +
  10453. +#include <linux/module.h>
  10454. +#include <linux/platform_device.h>
  10455. +
  10456. +#include <sound/core.h>
  10457. +#include <sound/pcm.h>
  10458. +#include <sound/pcm_params.h>
  10459. +#include <sound/soc.h>
  10460. +#include <sound/jack.h>
  10461. +
  10462. +#include "../codecs/wm8804.h"
  10463. +#include "../codecs/pcm512x.h"
  10464. +
  10465. +
  10466. +static bool digital_gain_0db_limit = true;
  10467. +
  10468. +static int snd_rpi_justboom_both_init(struct snd_soc_pcm_runtime *rtd)
  10469. +{
  10470. + struct snd_soc_component *digi = asoc_rtd_to_codec(rtd, 0)->component;
  10471. + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 1)->component;
  10472. +
  10473. + /* enable TX output */
  10474. + snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
  10475. +
  10476. + snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
  10477. + snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02);
  10478. + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
  10479. +
  10480. + if (digital_gain_0db_limit) {
  10481. + int ret;
  10482. + struct snd_soc_card *card = rtd->card;
  10483. +
  10484. + ret = snd_soc_limit_volume(card, "Digital Playback Volume",
  10485. + 207);
  10486. + if (ret < 0)
  10487. + dev_warn(card->dev, "Failed to set volume limit: %d\n",
  10488. + ret);
  10489. + }
  10490. +
  10491. + return 0;
  10492. +}
  10493. +
  10494. +static int snd_rpi_justboom_both_hw_params(struct snd_pcm_substream *substream,
  10495. + struct snd_pcm_hw_params *params)
  10496. +{
  10497. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  10498. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  10499. + struct snd_soc_component *digi = asoc_rtd_to_codec(rtd, 0)->component;
  10500. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  10501. +
  10502. + int sysclk = 27000000; /* This is fixed on this board */
  10503. +
  10504. + long mclk_freq = 0;
  10505. + int mclk_div = 1;
  10506. + int sampling_freq = 1;
  10507. +
  10508. + int ret;
  10509. +
  10510. + int samplerate = params_rate(params);
  10511. +
  10512. + if (samplerate <= 96000) {
  10513. + mclk_freq = samplerate*256;
  10514. + mclk_div = WM8804_MCLKDIV_256FS;
  10515. + } else {
  10516. + mclk_freq = samplerate*128;
  10517. + mclk_div = WM8804_MCLKDIV_128FS;
  10518. + }
  10519. +
  10520. + switch (samplerate) {
  10521. + case 32000:
  10522. + sampling_freq = 0x03;
  10523. + break;
  10524. + case 44100:
  10525. + sampling_freq = 0x00;
  10526. + break;
  10527. + case 48000:
  10528. + sampling_freq = 0x02;
  10529. + break;
  10530. + case 88200:
  10531. + sampling_freq = 0x08;
  10532. + break;
  10533. + case 96000:
  10534. + sampling_freq = 0x0a;
  10535. + break;
  10536. + case 176400:
  10537. + sampling_freq = 0x0c;
  10538. + break;
  10539. + case 192000:
  10540. + sampling_freq = 0x0e;
  10541. + break;
  10542. + default:
  10543. + dev_err(rtd->card->dev,
  10544. + "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n",
  10545. + samplerate);
  10546. + }
  10547. +
  10548. + snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div);
  10549. + snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq);
  10550. +
  10551. + ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
  10552. + sysclk, SND_SOC_CLOCK_OUT);
  10553. + if (ret < 0) {
  10554. + dev_err(rtd->card->dev,
  10555. + "Failed to set WM8804 SYSCLK: %d\n", ret);
  10556. + return ret;
  10557. + }
  10558. +
  10559. + /* Enable TX output */
  10560. + snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
  10561. +
  10562. + /* Power on */
  10563. + snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x9, 0);
  10564. +
  10565. + /* set sampling frequency status bits */
  10566. + snd_soc_component_update_bits(digi, WM8804_SPDTX4, 0x0f, sampling_freq);
  10567. +
  10568. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
  10569. +}
  10570. +
  10571. +static int snd_rpi_justboom_both_startup(struct snd_pcm_substream *substream)
  10572. +{
  10573. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  10574. + struct snd_soc_component *digi = asoc_rtd_to_codec(rtd, 0)->component;
  10575. + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 1)->component;
  10576. +
  10577. + /* turn on digital output */
  10578. + snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x00);
  10579. +
  10580. + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
  10581. +
  10582. + return 0;
  10583. +}
  10584. +
  10585. +static void snd_rpi_justboom_both_shutdown(struct snd_pcm_substream *substream)
  10586. +{
  10587. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  10588. + struct snd_soc_component *digi = asoc_rtd_to_codec(rtd, 0)->component;
  10589. + struct snd_soc_component *dac = asoc_rtd_to_codec(rtd, 1)->component;
  10590. +
  10591. + snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
  10592. +
  10593. + /* turn off output */
  10594. + snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x3c);
  10595. +}
  10596. +
  10597. +/* machine stream operations */
  10598. +static struct snd_soc_ops snd_rpi_justboom_both_ops = {
  10599. + .hw_params = snd_rpi_justboom_both_hw_params,
  10600. + .startup = snd_rpi_justboom_both_startup,
  10601. + .shutdown = snd_rpi_justboom_both_shutdown,
  10602. +};
  10603. +
  10604. +SND_SOC_DAILINK_DEFS(rpi_justboom_both,
  10605. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  10606. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi"),
  10607. + COMP_CODEC("wm8804.1-003b", "wm8804-spdif")),
  10608. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  10609. +
  10610. +static struct snd_soc_dai_link snd_rpi_justboom_both_dai[] = {
  10611. +{
  10612. + .name = "JustBoom Digi",
  10613. + .stream_name = "JustBoom Digi HiFi",
  10614. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  10615. + SND_SOC_DAIFMT_CBM_CFM,
  10616. + .ops = &snd_rpi_justboom_both_ops,
  10617. + .init = snd_rpi_justboom_both_init,
  10618. + SND_SOC_DAILINK_REG(rpi_justboom_both),
  10619. +},
  10620. +};
  10621. +
  10622. +/* audio machine driver */
  10623. +static struct snd_soc_card snd_rpi_justboom_both = {
  10624. + .name = "snd_rpi_justboom_both",
  10625. + .driver_name = "JustBoomBoth",
  10626. + .owner = THIS_MODULE,
  10627. + .dai_link = snd_rpi_justboom_both_dai,
  10628. + .num_links = ARRAY_SIZE(snd_rpi_justboom_both_dai),
  10629. +};
  10630. +
  10631. +static int snd_rpi_justboom_both_probe(struct platform_device *pdev)
  10632. +{
  10633. + int ret = 0;
  10634. + struct snd_soc_card *card = &snd_rpi_justboom_both;
  10635. +
  10636. + snd_rpi_justboom_both.dev = &pdev->dev;
  10637. +
  10638. + if (pdev->dev.of_node) {
  10639. + struct device_node *i2s_node;
  10640. + struct snd_soc_dai_link *dai = &snd_rpi_justboom_both_dai[0];
  10641. +
  10642. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  10643. + "i2s-controller", 0);
  10644. +
  10645. + if (i2s_node) {
  10646. + int i;
  10647. +
  10648. + for (i = 0; i < card->num_links; i++) {
  10649. + dai->cpus->dai_name = NULL;
  10650. + dai->cpus->of_node = i2s_node;
  10651. + dai->platforms->name = NULL;
  10652. + dai->platforms->of_node = i2s_node;
  10653. + }
  10654. + }
  10655. +
  10656. + digital_gain_0db_limit = !of_property_read_bool(
  10657. + pdev->dev.of_node, "justboom,24db_digital_gain");
  10658. + }
  10659. +
  10660. + ret = snd_soc_register_card(card);
  10661. + if (ret && ret != -EPROBE_DEFER) {
  10662. + dev_err(&pdev->dev,
  10663. + "snd_soc_register_card() failed: %d\n", ret);
  10664. + }
  10665. +
  10666. + return ret;
  10667. +}
  10668. +
  10669. +static int snd_rpi_justboom_both_remove(struct platform_device *pdev)
  10670. +{
  10671. + snd_soc_unregister_card(&snd_rpi_justboom_both);
  10672. + return 0;
  10673. +}
  10674. +
  10675. +static const struct of_device_id snd_rpi_justboom_both_of_match[] = {
  10676. + { .compatible = "justboom,justboom-both", },
  10677. + {},
  10678. +};
  10679. +MODULE_DEVICE_TABLE(of, snd_rpi_justboom_both_of_match);
  10680. +
  10681. +static struct platform_driver snd_rpi_justboom_both_driver = {
  10682. + .driver = {
  10683. + .name = "snd-rpi-justboom-both",
  10684. + .owner = THIS_MODULE,
  10685. + .of_match_table = snd_rpi_justboom_both_of_match,
  10686. + },
  10687. + .probe = snd_rpi_justboom_both_probe,
  10688. + .remove = snd_rpi_justboom_both_remove,
  10689. +};
  10690. +
  10691. +module_platform_driver(snd_rpi_justboom_both_driver);
  10692. +
  10693. +MODULE_AUTHOR("Johannes Krude <[email protected]>");
  10694. +MODULE_DESCRIPTION("ASoC Driver for simultaneous use of JustBoom PI Digi & DAC HAT Sound Cards");
  10695. +MODULE_LICENSE("GPL v2");
  10696. --- /dev/null
  10697. +++ b/sound/soc/bcm/justboom-dac.c
  10698. @@ -0,0 +1,147 @@
  10699. +/*
  10700. + * ASoC Driver for JustBoom DAC Raspberry Pi HAT Sound Card
  10701. + *
  10702. + * Author: Milan Neskovic
  10703. + * Copyright 2016
  10704. + * based on code by Daniel Matuschek <[email protected]>
  10705. + * based on code by Florian Meier <[email protected]>
  10706. + *
  10707. + * This program is free software; you can redistribute it and/or
  10708. + * modify it under the terms of the GNU General Public License
  10709. + * version 2 as published by the Free Software Foundation.
  10710. + *
  10711. + * This program is distributed in the hope that it will be useful, but
  10712. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  10713. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10714. + * General Public License for more details.
  10715. + */
  10716. +
  10717. +#include <linux/module.h>
  10718. +#include <linux/platform_device.h>
  10719. +
  10720. +#include <sound/core.h>
  10721. +#include <sound/pcm.h>
  10722. +#include <sound/pcm_params.h>
  10723. +#include <sound/soc.h>
  10724. +#include <sound/jack.h>
  10725. +
  10726. +#include "../codecs/pcm512x.h"
  10727. +
  10728. +static bool digital_gain_0db_limit = true;
  10729. +
  10730. +static int snd_rpi_justboom_dac_init(struct snd_soc_pcm_runtime *rtd)
  10731. +{
  10732. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  10733. + snd_soc_component_update_bits(component, PCM512x_GPIO_EN, 0x08, 0x08);
  10734. + snd_soc_component_update_bits(component, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02);
  10735. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08,0x08);
  10736. +
  10737. + if (digital_gain_0db_limit)
  10738. + {
  10739. + int ret;
  10740. + struct snd_soc_card *card = rtd->card;
  10741. +
  10742. + ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207);
  10743. + if (ret < 0)
  10744. + dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
  10745. + }
  10746. +
  10747. + return 0;
  10748. +}
  10749. +
  10750. +static int snd_rpi_justboom_dac_startup(struct snd_pcm_substream *substream) {
  10751. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  10752. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  10753. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08,0x08);
  10754. + return 0;
  10755. +}
  10756. +
  10757. +static void snd_rpi_justboom_dac_shutdown(struct snd_pcm_substream *substream) {
  10758. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  10759. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  10760. + snd_soc_component_update_bits(component, PCM512x_GPIO_CONTROL_1, 0x08,0x00);
  10761. +}
  10762. +
  10763. +/* machine stream operations */
  10764. +static struct snd_soc_ops snd_rpi_justboom_dac_ops = {
  10765. + .startup = snd_rpi_justboom_dac_startup,
  10766. + .shutdown = snd_rpi_justboom_dac_shutdown,
  10767. +};
  10768. +
  10769. +SND_SOC_DAILINK_DEFS(hifi,
  10770. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  10771. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm512x.1-004d", "pcm512x-hifi")),
  10772. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  10773. +
  10774. +static struct snd_soc_dai_link snd_rpi_justboom_dac_dai[] = {
  10775. +{
  10776. + .name = "JustBoom DAC",
  10777. + .stream_name = "JustBoom DAC HiFi",
  10778. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  10779. + SND_SOC_DAIFMT_CBS_CFS,
  10780. + .ops = &snd_rpi_justboom_dac_ops,
  10781. + .init = snd_rpi_justboom_dac_init,
  10782. + SND_SOC_DAILINK_REG(hifi),
  10783. +},
  10784. +};
  10785. +
  10786. +/* audio machine driver */
  10787. +static struct snd_soc_card snd_rpi_justboom_dac = {
  10788. + .name = "snd_rpi_justboom_dac",
  10789. + .driver_name = "JustBoomDac",
  10790. + .owner = THIS_MODULE,
  10791. + .dai_link = snd_rpi_justboom_dac_dai,
  10792. + .num_links = ARRAY_SIZE(snd_rpi_justboom_dac_dai),
  10793. +};
  10794. +
  10795. +static int snd_rpi_justboom_dac_probe(struct platform_device *pdev)
  10796. +{
  10797. + int ret = 0;
  10798. +
  10799. + snd_rpi_justboom_dac.dev = &pdev->dev;
  10800. +
  10801. + if (pdev->dev.of_node) {
  10802. + struct device_node *i2s_node;
  10803. + struct snd_soc_dai_link *dai = &snd_rpi_justboom_dac_dai[0];
  10804. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  10805. + "i2s-controller", 0);
  10806. +
  10807. + if (i2s_node) {
  10808. + dai->cpus->dai_name = NULL;
  10809. + dai->cpus->of_node = i2s_node;
  10810. + dai->platforms->name = NULL;
  10811. + dai->platforms->of_node = i2s_node;
  10812. + }
  10813. +
  10814. + digital_gain_0db_limit = !of_property_read_bool(
  10815. + pdev->dev.of_node, "justboom,24db_digital_gain");
  10816. + }
  10817. +
  10818. + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_justboom_dac);
  10819. + if (ret && ret != -EPROBE_DEFER)
  10820. + dev_err(&pdev->dev,
  10821. + "snd_soc_register_card() failed: %d\n", ret);
  10822. +
  10823. + return ret;
  10824. +}
  10825. +
  10826. +static const struct of_device_id snd_rpi_justboom_dac_of_match[] = {
  10827. + { .compatible = "justboom,justboom-dac", },
  10828. + {},
  10829. +};
  10830. +MODULE_DEVICE_TABLE(of, snd_rpi_justboom_dac_of_match);
  10831. +
  10832. +static struct platform_driver snd_rpi_justboom_dac_driver = {
  10833. + .driver = {
  10834. + .name = "snd-rpi-justboom-dac",
  10835. + .owner = THIS_MODULE,
  10836. + .of_match_table = snd_rpi_justboom_dac_of_match,
  10837. + },
  10838. + .probe = snd_rpi_justboom_dac_probe,
  10839. +};
  10840. +
  10841. +module_platform_driver(snd_rpi_justboom_dac_driver);
  10842. +
  10843. +MODULE_AUTHOR("Milan Neskovic <[email protected]>");
  10844. +MODULE_DESCRIPTION("ASoC Driver for JustBoom PI DAC HAT Sound Card");
  10845. +MODULE_LICENSE("GPL v2");
  10846. --- /dev/null
  10847. +++ b/sound/soc/bcm/pifi-40.c
  10848. @@ -0,0 +1,284 @@
  10849. +// SPDX-License-Identifier: GPL-2.0-only
  10850. +/*
  10851. + * ALSA ASoC Machine Driver for PiFi-40
  10852. + *
  10853. + * Author: David Knell <[email protected])
  10854. + * based on code by Daniel Matuschek <[email protected]>
  10855. + * based on code by Florian Meier <[email protected]>
  10856. + * Copyright (C) 2020
  10857. + *
  10858. + * This program is free software; you can redistribute it and/or
  10859. + * modify it under the terms of the GNU General Public License
  10860. + * version 2 as published by the Free Software Foundation.
  10861. + *
  10862. + * This program is distributed in the hope that it will be useful, but
  10863. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  10864. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10865. + * General Public License for more details.
  10866. + */
  10867. +
  10868. +#include <linux/module.h>
  10869. +#include <linux/platform_device.h>
  10870. +#include <linux/gpio/consumer.h>
  10871. +#include <sound/core.h>
  10872. +#include <sound/pcm.h>
  10873. +#include <sound/pcm_params.h>
  10874. +#include <sound/soc.h>
  10875. +#include <linux/firmware.h>
  10876. +#include <linux/delay.h>
  10877. +#include <sound/tlv.h>
  10878. +
  10879. +static struct gpio_desc *pdn_gpio;
  10880. +static int vol = 0x30;
  10881. +
  10882. +// Volume control
  10883. +static int pifi_40_vol_get(struct snd_kcontrol *kcontrol,
  10884. + struct snd_ctl_elem_value *ucontrol)
  10885. +{
  10886. + ucontrol->value.integer.value[0] = vol;
  10887. + ucontrol->value.integer.value[1] = vol;
  10888. + return 0;
  10889. +}
  10890. +
  10891. +static int pifi_40_vol_set(struct snd_kcontrol *kcontrol,
  10892. + struct snd_ctl_elem_value *ucontrol)
  10893. +{
  10894. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  10895. + struct snd_soc_pcm_runtime *rtd;
  10896. + unsigned int v = ucontrol->value.integer.value[0];
  10897. + struct snd_soc_component *dac[2];
  10898. +
  10899. + rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
  10900. + dac[0] = asoc_rtd_to_codec(rtd, 0)->component;
  10901. + dac[1] = asoc_rtd_to_codec(rtd, 1)->component;
  10902. +
  10903. + snd_soc_component_write(dac[0], 0x07, 255 - v);
  10904. + snd_soc_component_write(dac[1], 0x07, 255 - v);
  10905. +
  10906. + vol = v;
  10907. + return 1;
  10908. +}
  10909. +
  10910. +static const DECLARE_TLV_DB_SCALE(digital_tlv_master, -10350, 50, 1);
  10911. +static const struct snd_kcontrol_new pifi_40_controls[] = {
  10912. + SOC_DOUBLE_R_EXT_TLV("Master Volume", 0x00, 0x01,
  10913. + 0x00, // Min
  10914. + 0xff, // Max
  10915. + 0x01, // Invert
  10916. + pifi_40_vol_get, pifi_40_vol_set,
  10917. + digital_tlv_master)
  10918. +};
  10919. +
  10920. +static const char * const codec_ctl_pfx[] = { "Left", "Right" };
  10921. +
  10922. +static const char * const codec_ctl_name[] = { "Master Volume",
  10923. + "Speaker Volume",
  10924. + "Speaker Switch" };
  10925. +
  10926. +static int snd_pifi_40_init(struct snd_soc_pcm_runtime *rtd)
  10927. +{
  10928. + struct snd_soc_card *card = rtd->card;
  10929. + struct snd_soc_component *dac[2];
  10930. + struct snd_kcontrol *kctl;
  10931. + int i, j;
  10932. +
  10933. + dac[0] = asoc_rtd_to_codec(rtd, 0)->component;
  10934. + dac[1] = asoc_rtd_to_codec(rtd, 1)->component;
  10935. +
  10936. +
  10937. + // Set up cards - pulse power down first
  10938. + gpiod_set_value_cansleep(pdn_gpio, 1);
  10939. + usleep_range(1000, 10000);
  10940. + gpiod_set_value_cansleep(pdn_gpio, 0);
  10941. + usleep_range(20000, 30000);
  10942. +
  10943. + // Oscillator trim
  10944. + snd_soc_component_write(dac[0], 0x1b, 0);
  10945. + snd_soc_component_write(dac[1], 0x1b, 0);
  10946. + usleep_range(60000, 80000);
  10947. +
  10948. + // Common setup
  10949. + for (i = 0; i < 2; i++) {
  10950. + // MCLK at 64fs, sample rate 44.1 or 48kHz
  10951. + snd_soc_component_write(dac[i], 0x00, 0x60);
  10952. +
  10953. + // Set up for PBTL
  10954. + snd_soc_component_write(dac[i], 0x19, 0x3A);
  10955. + snd_soc_component_write(dac[i], 0x25, 0x01103245);
  10956. +
  10957. + // Master vol to -10db
  10958. + snd_soc_component_write(dac[i], 0x07, 0x44);
  10959. + }
  10960. + // Inputs set to L and R respectively
  10961. + snd_soc_component_write(dac[0], 0x20, 0x00017772);
  10962. + snd_soc_component_write(dac[1], 0x20, 0x00107772);
  10963. +
  10964. + // Remove codec controls
  10965. + for (i = 0; i < 2; i++) {
  10966. + for (j = 0; j < 3; j++) {
  10967. + char cname[256];
  10968. +
  10969. + sprintf(cname, "%s %s", codec_ctl_pfx[i],
  10970. + codec_ctl_name[j]);
  10971. + kctl = snd_soc_card_get_kcontrol(card, cname);
  10972. + if (!kctl) {
  10973. + pr_info("Control %s not found\n",
  10974. + cname);
  10975. + } else {
  10976. + kctl->vd[0].access =
  10977. + SNDRV_CTL_ELEM_ACCESS_READWRITE;
  10978. + snd_ctl_remove(card->snd_card, kctl);
  10979. + }
  10980. + }
  10981. + }
  10982. +
  10983. + return 0;
  10984. +}
  10985. +
  10986. +static int snd_pifi_40_hw_params(struct snd_pcm_substream *substream,
  10987. + struct snd_pcm_hw_params *params)
  10988. +{
  10989. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  10990. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  10991. + unsigned int sample_bits;
  10992. +
  10993. + sample_bits = snd_pcm_format_physical_width(params_format(params));
  10994. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
  10995. +}
  10996. +
  10997. +static struct snd_soc_ops snd_pifi_40_ops = { .hw_params =
  10998. + snd_pifi_40_hw_params };
  10999. +
  11000. +static struct snd_soc_dai_link_component pifi_40_codecs[] = {
  11001. + {
  11002. + .dai_name = "tas571x-hifi",
  11003. + },
  11004. + {
  11005. + .dai_name = "tas571x-hifi",
  11006. + },
  11007. +};
  11008. +
  11009. +SND_SOC_DAILINK_DEFS(
  11010. + pifi_40_dai, DAILINK_COMP_ARRAY(COMP_EMPTY()),
  11011. + DAILINK_COMP_ARRAY(COMP_CODEC("tas571x.1-001a", "tas571x-hifi"),
  11012. + COMP_CODEC("tas571x.1-001b", "tas571x-hifi")),
  11013. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  11014. +
  11015. +static struct snd_soc_dai_link snd_pifi_40_dai[] = {
  11016. + {
  11017. + .name = "PiFi40",
  11018. + .stream_name = "PiFi40",
  11019. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  11020. + SND_SOC_DAIFMT_CBS_CFS,
  11021. + .ops = &snd_pifi_40_ops,
  11022. + .init = snd_pifi_40_init,
  11023. + SND_SOC_DAILINK_REG(pifi_40_dai),
  11024. + },
  11025. +};
  11026. +
  11027. +// Machine driver
  11028. +static struct snd_soc_card snd_pifi_40 = {
  11029. + .name = "PiFi40",
  11030. + .owner = THIS_MODULE,
  11031. + .dai_link = snd_pifi_40_dai,
  11032. + .num_links = ARRAY_SIZE(snd_pifi_40_dai),
  11033. + .controls = pifi_40_controls,
  11034. + .num_controls = ARRAY_SIZE(pifi_40_controls)
  11035. +};
  11036. +
  11037. +static void snd_pifi_40_pdn(struct snd_soc_card *card, int on)
  11038. +{
  11039. + if (pdn_gpio)
  11040. + gpiod_set_value_cansleep(pdn_gpio, on ? 0 : 1);
  11041. +}
  11042. +
  11043. +static int snd_pifi_40_probe(struct platform_device *pdev)
  11044. +{
  11045. + struct snd_soc_card *card = &snd_pifi_40;
  11046. + int ret = 0, i = 0;
  11047. +
  11048. + card->dev = &pdev->dev;
  11049. + platform_set_drvdata(pdev, &snd_pifi_40);
  11050. +
  11051. + if (pdev->dev.of_node) {
  11052. + struct device_node *i2s_node;
  11053. + struct snd_soc_dai_link *dai;
  11054. +
  11055. + dai = &snd_pifi_40_dai[0];
  11056. + i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller",
  11057. + 0);
  11058. + if (i2s_node) {
  11059. + for (i = 0; i < card->num_links; i++) {
  11060. + dai->cpus->dai_name = NULL;
  11061. + dai->cpus->of_node = i2s_node;
  11062. + dai->platforms->name = NULL;
  11063. + dai->platforms->of_node = i2s_node;
  11064. + }
  11065. + }
  11066. +
  11067. + pifi_40_codecs[0].of_node =
  11068. + of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
  11069. + pifi_40_codecs[1].of_node =
  11070. + of_parse_phandle(pdev->dev.of_node, "audio-codec", 1);
  11071. + if (!pifi_40_codecs[0].of_node || !pifi_40_codecs[1].of_node) {
  11072. + dev_err(&pdev->dev,
  11073. + "Property 'audio-codec' missing or invalid\n");
  11074. + return -EINVAL;
  11075. + }
  11076. +
  11077. + pdn_gpio = devm_gpiod_get_optional(&pdev->dev, "pdn",
  11078. + GPIOD_OUT_LOW);
  11079. + if (IS_ERR(pdn_gpio)) {
  11080. + ret = PTR_ERR(pdn_gpio);
  11081. + dev_err(&pdev->dev, "failed to get pdn gpio: %d\n",
  11082. + ret);
  11083. + return ret;
  11084. + }
  11085. +
  11086. + ret = snd_soc_register_card(&snd_pifi_40);
  11087. + if (ret < 0) {
  11088. + dev_err(&pdev->dev,
  11089. + "snd_soc_register_card() failed: %d\n", ret);
  11090. + return ret;
  11091. + }
  11092. +
  11093. + return 0;
  11094. + }
  11095. +
  11096. + return -EINVAL;
  11097. +}
  11098. +
  11099. +static int snd_pifi_40_remove(struct platform_device *pdev)
  11100. +{
  11101. + struct snd_soc_card *card = platform_get_drvdata(pdev);
  11102. +
  11103. + kfree(&card->drvdata);
  11104. + snd_pifi_40_pdn(&snd_pifi_40, 0);
  11105. + snd_soc_unregister_card(&snd_pifi_40);
  11106. + return 0;
  11107. +}
  11108. +
  11109. +static const struct of_device_id snd_pifi_40_of_match[] = {
  11110. + {
  11111. + .compatible = "pifi,pifi-40",
  11112. + },
  11113. + { /* sentinel */ },
  11114. +};
  11115. +
  11116. +MODULE_DEVICE_TABLE(of, snd_pifi_40_of_match);
  11117. +
  11118. +static struct platform_driver snd_pifi_40_driver = {
  11119. + .driver = {
  11120. + .name = "snd-pifi-40",
  11121. + .owner = THIS_MODULE,
  11122. + .of_match_table = snd_pifi_40_of_match,
  11123. + },
  11124. + .probe = snd_pifi_40_probe,
  11125. + .remove = snd_pifi_40_remove,
  11126. +};
  11127. +
  11128. +module_platform_driver(snd_pifi_40_driver);
  11129. +
  11130. +MODULE_AUTHOR("David Knell <[email protected]>");
  11131. +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for PiFi-40");
  11132. +MODULE_LICENSE("GPL v2");
  11133. --- /dev/null
  11134. +++ b/sound/soc/bcm/pisound.c
  11135. @@ -0,0 +1,1241 @@
  11136. +/*
  11137. + * Pisound Linux kernel module.
  11138. + * Copyright (C) 2016-2020 Vilniaus Blokas UAB, https://blokas.io/pisound
  11139. + *
  11140. + * This program is free software; you can redistribute it and/or
  11141. + * modify it under the terms of the GNU General Public License
  11142. + * as published by the Free Software Foundation; version 2 of the
  11143. + * License.
  11144. + *
  11145. + * This program is distributed in the hope that it will be useful,
  11146. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11147. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11148. + * GNU General Public License for more details.
  11149. + *
  11150. + * You should have received a copy of the GNU General Public License
  11151. + * along with this program; if not, write to the Free Software
  11152. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  11153. + * MA 02110-1301, USA.
  11154. + */
  11155. +
  11156. +#include <linux/init.h>
  11157. +#include <linux/module.h>
  11158. +#include <linux/platform_device.h>
  11159. +#include <linux/gpio.h>
  11160. +#include <linux/kobject.h>
  11161. +#include <linux/sysfs.h>
  11162. +#include <linux/delay.h>
  11163. +#include <linux/spi/spi.h>
  11164. +#include <linux/interrupt.h>
  11165. +#include <linux/kfifo.h>
  11166. +#include <linux/jiffies.h>
  11167. +
  11168. +#include <sound/core.h>
  11169. +#include <sound/pcm.h>
  11170. +#include <sound/pcm_params.h>
  11171. +#include <sound/soc.h>
  11172. +#include <sound/jack.h>
  11173. +#include <sound/rawmidi.h>
  11174. +#include <sound/asequencer.h>
  11175. +#include <sound/control.h>
  11176. +
  11177. +static int pisnd_spi_init(struct device *dev);
  11178. +static void pisnd_spi_uninit(void);
  11179. +
  11180. +static void pisnd_spi_flush(void);
  11181. +static void pisnd_spi_start(void);
  11182. +static uint8_t pisnd_spi_recv(uint8_t *buffer, uint8_t length);
  11183. +
  11184. +typedef void (*pisnd_spi_recv_cb)(void *data);
  11185. +static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb, void *data);
  11186. +
  11187. +static const char *pisnd_spi_get_serial(void);
  11188. +static const char *pisnd_spi_get_id(void);
  11189. +static const char *pisnd_spi_get_fw_version(void);
  11190. +static const char *pisnd_spi_get_hw_version(void);
  11191. +
  11192. +static int pisnd_midi_init(struct snd_card *card);
  11193. +static void pisnd_midi_uninit(void);
  11194. +
  11195. +enum task_e {
  11196. + TASK_PROCESS = 0,
  11197. +};
  11198. +
  11199. +static void pisnd_schedule_process(enum task_e task);
  11200. +
  11201. +#define PISOUND_LOG_PREFIX "pisound: "
  11202. +
  11203. +#ifdef PISOUND_DEBUG
  11204. +# define printd(...) pr_alert(PISOUND_LOG_PREFIX __VA_ARGS__)
  11205. +#else
  11206. +# define printd(...) do {} while (0)
  11207. +#endif
  11208. +
  11209. +#define printe(...) pr_err(PISOUND_LOG_PREFIX __VA_ARGS__)
  11210. +#define printi(...) pr_info(PISOUND_LOG_PREFIX __VA_ARGS__)
  11211. +
  11212. +static struct snd_rawmidi *g_rmidi;
  11213. +static struct snd_rawmidi_substream *g_midi_output_substream;
  11214. +
  11215. +static int pisnd_output_open(struct snd_rawmidi_substream *substream)
  11216. +{
  11217. + g_midi_output_substream = substream;
  11218. + return 0;
  11219. +}
  11220. +
  11221. +static int pisnd_output_close(struct snd_rawmidi_substream *substream)
  11222. +{
  11223. + g_midi_output_substream = NULL;
  11224. + return 0;
  11225. +}
  11226. +
  11227. +static void pisnd_output_trigger(
  11228. + struct snd_rawmidi_substream *substream,
  11229. + int up
  11230. + )
  11231. +{
  11232. + if (substream != g_midi_output_substream) {
  11233. + printe("MIDI output trigger called for an unexpected stream!");
  11234. + return;
  11235. + }
  11236. +
  11237. + if (!up)
  11238. + return;
  11239. +
  11240. + pisnd_spi_start();
  11241. +}
  11242. +
  11243. +static void pisnd_output_drain(struct snd_rawmidi_substream *substream)
  11244. +{
  11245. + pisnd_spi_flush();
  11246. +}
  11247. +
  11248. +static int pisnd_input_open(struct snd_rawmidi_substream *substream)
  11249. +{
  11250. + return 0;
  11251. +}
  11252. +
  11253. +static int pisnd_input_close(struct snd_rawmidi_substream *substream)
  11254. +{
  11255. + return 0;
  11256. +}
  11257. +
  11258. +static void pisnd_midi_recv_callback(void *substream)
  11259. +{
  11260. + uint8_t data[128];
  11261. + uint8_t n = 0;
  11262. +
  11263. + while ((n = pisnd_spi_recv(data, sizeof(data)))) {
  11264. + int res = snd_rawmidi_receive(substream, data, n);
  11265. + (void)res;
  11266. + printd("midi recv %u bytes, res = %d\n", n, res);
  11267. + }
  11268. +}
  11269. +
  11270. +static void pisnd_input_trigger(struct snd_rawmidi_substream *substream, int up)
  11271. +{
  11272. + if (up) {
  11273. + pisnd_spi_set_callback(pisnd_midi_recv_callback, substream);
  11274. + pisnd_schedule_process(TASK_PROCESS);
  11275. + } else {
  11276. + pisnd_spi_set_callback(NULL, NULL);
  11277. + }
  11278. +}
  11279. +
  11280. +static struct snd_rawmidi_ops pisnd_output_ops = {
  11281. + .open = pisnd_output_open,
  11282. + .close = pisnd_output_close,
  11283. + .trigger = pisnd_output_trigger,
  11284. + .drain = pisnd_output_drain,
  11285. +};
  11286. +
  11287. +static struct snd_rawmidi_ops pisnd_input_ops = {
  11288. + .open = pisnd_input_open,
  11289. + .close = pisnd_input_close,
  11290. + .trigger = pisnd_input_trigger,
  11291. +};
  11292. +
  11293. +static void pisnd_get_port_info(
  11294. + struct snd_rawmidi *rmidi,
  11295. + int number,
  11296. + struct snd_seq_port_info *seq_port_info
  11297. + )
  11298. +{
  11299. + seq_port_info->type =
  11300. + SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
  11301. + SNDRV_SEQ_PORT_TYPE_HARDWARE |
  11302. + SNDRV_SEQ_PORT_TYPE_PORT;
  11303. + seq_port_info->midi_voices = 0;
  11304. +}
  11305. +
  11306. +static struct snd_rawmidi_global_ops pisnd_global_ops = {
  11307. + .get_port_info = pisnd_get_port_info,
  11308. +};
  11309. +
  11310. +static int pisnd_midi_init(struct snd_card *card)
  11311. +{
  11312. + int err;
  11313. +
  11314. + g_midi_output_substream = NULL;
  11315. +
  11316. + err = snd_rawmidi_new(card, "pisound MIDI", 0, 1, 1, &g_rmidi);
  11317. +
  11318. + if (err < 0) {
  11319. + printe("snd_rawmidi_new failed: %d\n", err);
  11320. + return err;
  11321. + }
  11322. +
  11323. + strcpy(g_rmidi->name, "pisound MIDI ");
  11324. + strcat(g_rmidi->name, pisnd_spi_get_serial());
  11325. +
  11326. + g_rmidi->info_flags =
  11327. + SNDRV_RAWMIDI_INFO_OUTPUT |
  11328. + SNDRV_RAWMIDI_INFO_INPUT |
  11329. + SNDRV_RAWMIDI_INFO_DUPLEX;
  11330. +
  11331. + g_rmidi->ops = &pisnd_global_ops;
  11332. +
  11333. + g_rmidi->private_data = (void *)0;
  11334. +
  11335. + snd_rawmidi_set_ops(
  11336. + g_rmidi,
  11337. + SNDRV_RAWMIDI_STREAM_OUTPUT,
  11338. + &pisnd_output_ops
  11339. + );
  11340. +
  11341. + snd_rawmidi_set_ops(
  11342. + g_rmidi,
  11343. + SNDRV_RAWMIDI_STREAM_INPUT,
  11344. + &pisnd_input_ops
  11345. + );
  11346. +
  11347. + return 0;
  11348. +}
  11349. +
  11350. +static void pisnd_midi_uninit(void)
  11351. +{
  11352. +}
  11353. +
  11354. +static void *g_recvData;
  11355. +static pisnd_spi_recv_cb g_recvCallback;
  11356. +
  11357. +#define FIFO_SIZE 4096
  11358. +
  11359. +static char g_serial_num[11];
  11360. +static char g_id[25];
  11361. +enum { MAX_VERSION_STR_LEN = 6 };
  11362. +static char g_fw_version[MAX_VERSION_STR_LEN];
  11363. +static char g_hw_version[MAX_VERSION_STR_LEN];
  11364. +
  11365. +static uint8_t g_ledFlashDuration;
  11366. +static bool g_ledFlashDurationChanged;
  11367. +
  11368. +DEFINE_KFIFO(spi_fifo_in, uint8_t, FIFO_SIZE);
  11369. +DEFINE_KFIFO(spi_fifo_out, uint8_t, FIFO_SIZE);
  11370. +
  11371. +static struct gpio_desc *data_available;
  11372. +static struct gpio_desc *spi_reset;
  11373. +
  11374. +static struct spi_device *pisnd_spi_device;
  11375. +
  11376. +static struct workqueue_struct *pisnd_workqueue;
  11377. +static struct work_struct pisnd_work_process;
  11378. +
  11379. +static void pisnd_work_handler(struct work_struct *work);
  11380. +
  11381. +static void spi_transfer(const uint8_t *txbuf, uint8_t *rxbuf, int len);
  11382. +static uint16_t spi_transfer16(uint16_t val);
  11383. +
  11384. +static int pisnd_init_workqueues(void)
  11385. +{
  11386. + pisnd_workqueue = create_singlethread_workqueue("pisnd_workqueue");
  11387. + INIT_WORK(&pisnd_work_process, pisnd_work_handler);
  11388. +
  11389. + return 0;
  11390. +}
  11391. +
  11392. +static void pisnd_uninit_workqueues(void)
  11393. +{
  11394. + flush_workqueue(pisnd_workqueue);
  11395. + destroy_workqueue(pisnd_workqueue);
  11396. +
  11397. + pisnd_workqueue = NULL;
  11398. +}
  11399. +
  11400. +static bool pisnd_spi_has_more(void)
  11401. +{
  11402. + return gpiod_get_value(data_available);
  11403. +}
  11404. +
  11405. +static void pisnd_schedule_process(enum task_e task)
  11406. +{
  11407. + if (pisnd_spi_device != NULL &&
  11408. + pisnd_workqueue != NULL &&
  11409. + !work_pending(&pisnd_work_process)
  11410. + ) {
  11411. + printd("schedule: has more = %d\n", pisnd_spi_has_more());
  11412. + if (task == TASK_PROCESS)
  11413. + queue_work(pisnd_workqueue, &pisnd_work_process);
  11414. + }
  11415. +}
  11416. +
  11417. +static irqreturn_t data_available_interrupt_handler(int irq, void *dev_id)
  11418. +{
  11419. + if (irq == gpiod_to_irq(data_available) && pisnd_spi_has_more()) {
  11420. + printd("schedule from irq\n");
  11421. + pisnd_schedule_process(TASK_PROCESS);
  11422. + }
  11423. +
  11424. + return IRQ_HANDLED;
  11425. +}
  11426. +
  11427. +static uint16_t spi_transfer16(uint16_t val)
  11428. +{
  11429. + uint8_t txbuf[2];
  11430. + uint8_t rxbuf[2];
  11431. +
  11432. + if (!pisnd_spi_device) {
  11433. + printe("pisnd_spi_device null, returning\n");
  11434. + return 0;
  11435. + }
  11436. +
  11437. + txbuf[0] = val >> 8;
  11438. + txbuf[1] = val & 0xff;
  11439. +
  11440. + spi_transfer(txbuf, rxbuf, sizeof(txbuf));
  11441. +
  11442. + printd("received: %02x%02x\n", rxbuf[0], rxbuf[1]);
  11443. +
  11444. + return (rxbuf[0] << 8) | rxbuf[1];
  11445. +}
  11446. +
  11447. +static void spi_transfer(const uint8_t *txbuf, uint8_t *rxbuf, int len)
  11448. +{
  11449. + int err;
  11450. + struct spi_transfer transfer;
  11451. + struct spi_message msg;
  11452. +
  11453. + memset(rxbuf, 0, len);
  11454. +
  11455. + if (!pisnd_spi_device) {
  11456. + printe("pisnd_spi_device null, returning\n");
  11457. + return;
  11458. + }
  11459. +
  11460. + spi_message_init(&msg);
  11461. +
  11462. + memset(&transfer, 0, sizeof(transfer));
  11463. +
  11464. + transfer.tx_buf = txbuf;
  11465. + transfer.rx_buf = rxbuf;
  11466. + transfer.len = len;
  11467. + transfer.speed_hz = 150000;
  11468. + transfer.delay.value = 10;
  11469. + transfer.delay.unit = SPI_DELAY_UNIT_USECS;
  11470. +
  11471. + spi_message_add_tail(&transfer, &msg);
  11472. +
  11473. + err = spi_sync(pisnd_spi_device, &msg);
  11474. +
  11475. + if (err < 0) {
  11476. + printe("spi_sync error %d\n", err);
  11477. + return;
  11478. + }
  11479. +
  11480. + printd("hasMore %d\n", pisnd_spi_has_more());
  11481. +}
  11482. +
  11483. +static int spi_read_bytes(char *dst, size_t length, uint8_t *bytesRead)
  11484. +{
  11485. + uint16_t rx;
  11486. + uint8_t size;
  11487. + uint8_t i;
  11488. +
  11489. + memset(dst, 0, length);
  11490. + *bytesRead = 0;
  11491. +
  11492. + rx = spi_transfer16(0);
  11493. + if (!(rx >> 8))
  11494. + return -EINVAL;
  11495. +
  11496. + size = rx & 0xff;
  11497. +
  11498. + if (size > length)
  11499. + return -EINVAL;
  11500. +
  11501. + for (i = 0; i < size; ++i) {
  11502. + rx = spi_transfer16(0);
  11503. + if (!(rx >> 8))
  11504. + return -EINVAL;
  11505. +
  11506. + dst[i] = rx & 0xff;
  11507. + }
  11508. +
  11509. + *bytesRead = i;
  11510. +
  11511. + return 0;
  11512. +}
  11513. +
  11514. +static int spi_device_match(struct device *dev, const void *data)
  11515. +{
  11516. + struct spi_device *spi = container_of(dev, struct spi_device, dev);
  11517. +
  11518. + printd(" %s %s %dkHz %d bits mode=0x%02X\n",
  11519. + spi->modalias, dev_name(dev), spi->max_speed_hz/1000,
  11520. + spi->bits_per_word, spi->mode);
  11521. +
  11522. + if (strcmp("pisound-spi", spi->modalias) == 0) {
  11523. + printi("\tFound!\n");
  11524. + return 1;
  11525. + }
  11526. +
  11527. + printe("\tNot found!\n");
  11528. + return 0;
  11529. +}
  11530. +
  11531. +static struct spi_device *pisnd_spi_find_device(void)
  11532. +{
  11533. + struct device *dev;
  11534. +
  11535. + printi("Searching for spi device...\n");
  11536. + dev = bus_find_device(&spi_bus_type, NULL, NULL, spi_device_match);
  11537. + if (dev != NULL)
  11538. + return container_of(dev, struct spi_device, dev);
  11539. + else
  11540. + return NULL;
  11541. +}
  11542. +
  11543. +static void pisnd_work_handler(struct work_struct *work)
  11544. +{
  11545. + enum { TRANSFER_SIZE = 4 };
  11546. + enum { PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES = 127 * 1000 };
  11547. + enum { MIDI_MILLIBYTES_PER_JIFFIE = (3125 * 1000) / HZ };
  11548. + int out_buffer_used_millibytes = 0;
  11549. + unsigned long now;
  11550. + uint8_t val;
  11551. + uint8_t txbuf[TRANSFER_SIZE];
  11552. + uint8_t rxbuf[TRANSFER_SIZE];
  11553. + uint8_t midibuf[TRANSFER_SIZE];
  11554. + int i, n;
  11555. + bool had_data;
  11556. +
  11557. + unsigned long last_transfer_at = jiffies;
  11558. +
  11559. + if (work == &pisnd_work_process) {
  11560. + if (pisnd_spi_device == NULL)
  11561. + return;
  11562. +
  11563. + do {
  11564. + if (g_midi_output_substream &&
  11565. + kfifo_avail(&spi_fifo_out) >= sizeof(midibuf)) {
  11566. +
  11567. + n = snd_rawmidi_transmit_peek(
  11568. + g_midi_output_substream,
  11569. + midibuf, sizeof(midibuf)
  11570. + );
  11571. +
  11572. + if (n > 0) {
  11573. + for (i = 0; i < n; ++i)
  11574. + kfifo_put(
  11575. + &spi_fifo_out,
  11576. + midibuf[i]
  11577. + );
  11578. + snd_rawmidi_transmit_ack(
  11579. + g_midi_output_substream,
  11580. + i
  11581. + );
  11582. + }
  11583. + }
  11584. +
  11585. + had_data = false;
  11586. + memset(txbuf, 0, sizeof(txbuf));
  11587. + for (i = 0; i < sizeof(txbuf) &&
  11588. + ((out_buffer_used_millibytes+1000 <
  11589. + PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES) ||
  11590. + g_ledFlashDurationChanged);
  11591. + i += 2) {
  11592. +
  11593. + val = 0;
  11594. +
  11595. + if (g_ledFlashDurationChanged) {
  11596. + txbuf[i+0] = 0xf0;
  11597. + txbuf[i+1] = g_ledFlashDuration;
  11598. + g_ledFlashDuration = 0;
  11599. + g_ledFlashDurationChanged = false;
  11600. + } else if (kfifo_get(&spi_fifo_out, &val)) {
  11601. + txbuf[i+0] = 0x0f;
  11602. + txbuf[i+1] = val;
  11603. + out_buffer_used_millibytes += 1000;
  11604. + }
  11605. + }
  11606. +
  11607. + spi_transfer(txbuf, rxbuf, sizeof(txbuf));
  11608. + /* Estimate the Pisound's MIDI output buffer usage, so
  11609. + * that we don't overflow it. Space in the buffer should
  11610. + * be becoming available at the UART MIDI byte transfer
  11611. + * rate.
  11612. + */
  11613. + now = jiffies;
  11614. + if (now != last_transfer_at) {
  11615. + out_buffer_used_millibytes -=
  11616. + (now - last_transfer_at) *
  11617. + MIDI_MILLIBYTES_PER_JIFFIE;
  11618. + if (out_buffer_used_millibytes < 0)
  11619. + out_buffer_used_millibytes = 0;
  11620. + last_transfer_at = now;
  11621. + }
  11622. +
  11623. + for (i = 0; i < sizeof(rxbuf); i += 2) {
  11624. + if (rxbuf[i]) {
  11625. + kfifo_put(&spi_fifo_in, rxbuf[i+1]);
  11626. + if (kfifo_len(&spi_fifo_in) > 16 &&
  11627. + g_recvCallback)
  11628. + g_recvCallback(g_recvData);
  11629. + had_data = true;
  11630. + }
  11631. + }
  11632. + } while (had_data
  11633. + || !kfifo_is_empty(&spi_fifo_out)
  11634. + || pisnd_spi_has_more()
  11635. + || g_ledFlashDurationChanged
  11636. + || out_buffer_used_millibytes != 0
  11637. + );
  11638. +
  11639. + if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback)
  11640. + g_recvCallback(g_recvData);
  11641. + }
  11642. +}
  11643. +
  11644. +static int pisnd_spi_gpio_init(struct device *dev)
  11645. +{
  11646. + spi_reset = gpiod_get_index(dev, "reset", 1, GPIOD_ASIS);
  11647. + data_available = gpiod_get_index(dev, "data_available", 0, GPIOD_ASIS);
  11648. +
  11649. + gpiod_direction_output(spi_reset, 1);
  11650. + gpiod_direction_input(data_available);
  11651. +
  11652. + /* Reset the slave. */
  11653. + gpiod_set_value(spi_reset, false);
  11654. + mdelay(1);
  11655. + gpiod_set_value(spi_reset, true);
  11656. +
  11657. + /* Give time for spi slave to start. */
  11658. + mdelay(64);
  11659. +
  11660. + return 0;
  11661. +}
  11662. +
  11663. +static void pisnd_spi_gpio_uninit(void)
  11664. +{
  11665. + gpiod_set_value(spi_reset, false);
  11666. + gpiod_put(spi_reset);
  11667. + spi_reset = NULL;
  11668. +
  11669. + gpiod_put(data_available);
  11670. + data_available = NULL;
  11671. +}
  11672. +
  11673. +static int pisnd_spi_gpio_irq_init(struct device *dev)
  11674. +{
  11675. + return request_threaded_irq(
  11676. + gpiod_to_irq(data_available), NULL,
  11677. + data_available_interrupt_handler,
  11678. + IRQF_TIMER | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  11679. + "data_available_int",
  11680. + NULL
  11681. + );
  11682. +}
  11683. +
  11684. +static void pisnd_spi_gpio_irq_uninit(void)
  11685. +{
  11686. + free_irq(gpiod_to_irq(data_available), NULL);
  11687. +}
  11688. +
  11689. +static int spi_read_info(void)
  11690. +{
  11691. + uint16_t tmp;
  11692. + uint8_t count;
  11693. + uint8_t n;
  11694. + uint8_t i;
  11695. + uint8_t j;
  11696. + char buffer[257];
  11697. + int ret;
  11698. + char *p;
  11699. +
  11700. + memset(g_serial_num, 0, sizeof(g_serial_num));
  11701. + memset(g_fw_version, 0, sizeof(g_fw_version));
  11702. + strcpy(g_hw_version, "1.0"); // Assume 1.0 hw version.
  11703. + memset(g_id, 0, sizeof(g_id));
  11704. +
  11705. + tmp = spi_transfer16(0);
  11706. +
  11707. + if (!(tmp >> 8))
  11708. + return -EINVAL;
  11709. +
  11710. + count = tmp & 0xff;
  11711. +
  11712. + for (i = 0; i < count; ++i) {
  11713. + memset(buffer, 0, sizeof(buffer));
  11714. + ret = spi_read_bytes(buffer, sizeof(buffer)-1, &n);
  11715. +
  11716. + if (ret < 0)
  11717. + return ret;
  11718. +
  11719. + switch (i) {
  11720. + case 0:
  11721. + if (n != 2)
  11722. + return -EINVAL;
  11723. +
  11724. + snprintf(
  11725. + g_fw_version,
  11726. + MAX_VERSION_STR_LEN,
  11727. + "%x.%02x",
  11728. + buffer[0],
  11729. + buffer[1]
  11730. + );
  11731. +
  11732. + g_fw_version[MAX_VERSION_STR_LEN-1] = '\0';
  11733. + break;
  11734. + case 3:
  11735. + if (n != 2)
  11736. + return -EINVAL;
  11737. +
  11738. + snprintf(
  11739. + g_hw_version,
  11740. + MAX_VERSION_STR_LEN,
  11741. + "%x.%x",
  11742. + buffer[0],
  11743. + buffer[1]
  11744. + );
  11745. +
  11746. + g_hw_version[MAX_VERSION_STR_LEN-1] = '\0';
  11747. + break;
  11748. + case 1:
  11749. + if (n >= sizeof(g_serial_num))
  11750. + return -EINVAL;
  11751. +
  11752. + memcpy(g_serial_num, buffer, sizeof(g_serial_num));
  11753. + break;
  11754. + case 2:
  11755. + {
  11756. + if (n*2 >= sizeof(g_id))
  11757. + return -EINVAL;
  11758. +
  11759. + p = g_id;
  11760. + for (j = 0; j < n; ++j)
  11761. + p += sprintf(p, "%02x", buffer[j]);
  11762. +
  11763. + *p = '\0';
  11764. + }
  11765. + break;
  11766. + default:
  11767. + break;
  11768. + }
  11769. + }
  11770. +
  11771. + return 0;
  11772. +}
  11773. +
  11774. +static int pisnd_spi_init(struct device *dev)
  11775. +{
  11776. + int ret;
  11777. + struct spi_device *spi;
  11778. +
  11779. + memset(g_serial_num, 0, sizeof(g_serial_num));
  11780. + memset(g_id, 0, sizeof(g_id));
  11781. + memset(g_fw_version, 0, sizeof(g_fw_version));
  11782. + memset(g_hw_version, 0, sizeof(g_hw_version));
  11783. +
  11784. + spi = pisnd_spi_find_device();
  11785. +
  11786. + if (spi != NULL) {
  11787. + printd("initializing spi!\n");
  11788. + pisnd_spi_device = spi;
  11789. + ret = spi_setup(pisnd_spi_device);
  11790. + } else {
  11791. + printe("SPI device not found, deferring!\n");
  11792. + return -EPROBE_DEFER;
  11793. + }
  11794. +
  11795. + ret = pisnd_spi_gpio_init(dev);
  11796. +
  11797. + if (ret < 0) {
  11798. + printe("SPI GPIO init failed: %d\n", ret);
  11799. + spi_dev_put(pisnd_spi_device);
  11800. + pisnd_spi_device = NULL;
  11801. + pisnd_spi_gpio_uninit();
  11802. + return ret;
  11803. + }
  11804. +
  11805. + ret = spi_read_info();
  11806. +
  11807. + if (ret < 0) {
  11808. + printe("Reading card info failed: %d\n", ret);
  11809. + spi_dev_put(pisnd_spi_device);
  11810. + pisnd_spi_device = NULL;
  11811. + pisnd_spi_gpio_uninit();
  11812. + return ret;
  11813. + }
  11814. +
  11815. + /* Flash the LEDs. */
  11816. + spi_transfer16(0xf008);
  11817. +
  11818. + ret = pisnd_spi_gpio_irq_init(dev);
  11819. + if (ret < 0) {
  11820. + printe("SPI irq request failed: %d\n", ret);
  11821. + spi_dev_put(pisnd_spi_device);
  11822. + pisnd_spi_device = NULL;
  11823. + pisnd_spi_gpio_irq_uninit();
  11824. + pisnd_spi_gpio_uninit();
  11825. + }
  11826. +
  11827. + ret = pisnd_init_workqueues();
  11828. + if (ret != 0) {
  11829. + printe("Workqueue initialization failed: %d\n", ret);
  11830. + spi_dev_put(pisnd_spi_device);
  11831. + pisnd_spi_device = NULL;
  11832. + pisnd_spi_gpio_irq_uninit();
  11833. + pisnd_spi_gpio_uninit();
  11834. + pisnd_uninit_workqueues();
  11835. + return ret;
  11836. + }
  11837. +
  11838. + if (pisnd_spi_has_more()) {
  11839. + printd("data is available, scheduling from init\n");
  11840. + pisnd_schedule_process(TASK_PROCESS);
  11841. + }
  11842. +
  11843. + return 0;
  11844. +}
  11845. +
  11846. +static void pisnd_spi_uninit(void)
  11847. +{
  11848. + pisnd_uninit_workqueues();
  11849. +
  11850. + spi_dev_put(pisnd_spi_device);
  11851. + pisnd_spi_device = NULL;
  11852. +
  11853. + pisnd_spi_gpio_irq_uninit();
  11854. + pisnd_spi_gpio_uninit();
  11855. +}
  11856. +
  11857. +static void pisnd_spi_flash_leds(uint8_t duration)
  11858. +{
  11859. + g_ledFlashDuration = duration;
  11860. + g_ledFlashDurationChanged = true;
  11861. + printd("schedule from spi_flash_leds\n");
  11862. + pisnd_schedule_process(TASK_PROCESS);
  11863. +}
  11864. +
  11865. +static void pisnd_spi_flush(void)
  11866. +{
  11867. + while (!kfifo_is_empty(&spi_fifo_out)) {
  11868. + pisnd_spi_start();
  11869. + flush_workqueue(pisnd_workqueue);
  11870. + }
  11871. +}
  11872. +
  11873. +static void pisnd_spi_start(void)
  11874. +{
  11875. + printd("schedule from spi_start\n");
  11876. + pisnd_schedule_process(TASK_PROCESS);
  11877. +}
  11878. +
  11879. +static uint8_t pisnd_spi_recv(uint8_t *buffer, uint8_t length)
  11880. +{
  11881. + return kfifo_out(&spi_fifo_in, buffer, length);
  11882. +}
  11883. +
  11884. +static void pisnd_spi_set_callback(pisnd_spi_recv_cb cb, void *data)
  11885. +{
  11886. + g_recvData = data;
  11887. + g_recvCallback = cb;
  11888. +}
  11889. +
  11890. +static const char *pisnd_spi_get_serial(void)
  11891. +{
  11892. + return g_serial_num;
  11893. +}
  11894. +
  11895. +static const char *pisnd_spi_get_id(void)
  11896. +{
  11897. + return g_id;
  11898. +}
  11899. +
  11900. +static const char *pisnd_spi_get_fw_version(void)
  11901. +{
  11902. + return g_fw_version;
  11903. +}
  11904. +
  11905. +static const char *pisnd_spi_get_hw_version(void)
  11906. +{
  11907. + return g_hw_version;
  11908. +}
  11909. +
  11910. +static const struct of_device_id pisound_of_match[] = {
  11911. + { .compatible = "blokaslabs,pisound", },
  11912. + { .compatible = "blokaslabs,pisound-spi", },
  11913. + {},
  11914. +};
  11915. +
  11916. +enum {
  11917. + SWITCH = 0,
  11918. + VOLUME = 1,
  11919. +};
  11920. +
  11921. +static int pisnd_ctl_info(struct snd_kcontrol *kcontrol,
  11922. + struct snd_ctl_elem_info *uinfo)
  11923. +{
  11924. + if (kcontrol->private_value == SWITCH) {
  11925. + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  11926. + uinfo->count = 1;
  11927. + uinfo->value.integer.min = 0;
  11928. + uinfo->value.integer.max = 1;
  11929. + return 0;
  11930. + } else if (kcontrol->private_value == VOLUME) {
  11931. + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  11932. + uinfo->count = 1;
  11933. + uinfo->value.integer.min = 0;
  11934. + uinfo->value.integer.max = 100;
  11935. + return 0;
  11936. + }
  11937. + return -EINVAL;
  11938. +}
  11939. +
  11940. +static int pisnd_ctl_get(struct snd_kcontrol *kcontrol,
  11941. + struct snd_ctl_elem_value *ucontrol)
  11942. +{
  11943. + if (kcontrol->private_value == SWITCH) {
  11944. + ucontrol->value.integer.value[0] = 1;
  11945. + return 0;
  11946. + } else if (kcontrol->private_value == VOLUME) {
  11947. + ucontrol->value.integer.value[0] = 100;
  11948. + return 0;
  11949. + }
  11950. +
  11951. + return -EINVAL;
  11952. +}
  11953. +
  11954. +static struct snd_kcontrol_new pisnd_ctl[] = {
  11955. + {
  11956. + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  11957. + .name = "PCM Playback Switch",
  11958. + .index = 0,
  11959. + .private_value = SWITCH,
  11960. + .access = SNDRV_CTL_ELEM_ACCESS_READ,
  11961. + .info = pisnd_ctl_info,
  11962. + .get = pisnd_ctl_get,
  11963. + },
  11964. + {
  11965. + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  11966. + .name = "PCM Playback Volume",
  11967. + .index = 0,
  11968. + .private_value = VOLUME,
  11969. + .access = SNDRV_CTL_ELEM_ACCESS_READ,
  11970. + .info = pisnd_ctl_info,
  11971. + .get = pisnd_ctl_get,
  11972. + },
  11973. +};
  11974. +
  11975. +static int pisnd_ctl_init(struct snd_card *card)
  11976. +{
  11977. + int err, i;
  11978. +
  11979. + for (i = 0; i < ARRAY_SIZE(pisnd_ctl); ++i) {
  11980. + err = snd_ctl_add(card, snd_ctl_new1(&pisnd_ctl[i], NULL));
  11981. + if (err < 0)
  11982. + return err;
  11983. + }
  11984. +
  11985. + return 0;
  11986. +}
  11987. +
  11988. +static int pisnd_ctl_uninit(void)
  11989. +{
  11990. + return 0;
  11991. +}
  11992. +
  11993. +static struct gpio_desc *osr0, *osr1, *osr2;
  11994. +static struct gpio_desc *reset;
  11995. +static struct gpio_desc *button;
  11996. +
  11997. +static int pisnd_hw_params(
  11998. + struct snd_pcm_substream *substream,
  11999. + struct snd_pcm_hw_params *params
  12000. + )
  12001. +{
  12002. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  12003. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  12004. +
  12005. + /* Pisound runs on fixed 32 clock counts per channel,
  12006. + * as generated by the master ADC.
  12007. + */
  12008. + snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2);
  12009. +
  12010. + printd("rate = %d\n", params_rate(params));
  12011. + printd("ch = %d\n", params_channels(params));
  12012. + printd("bits = %u\n",
  12013. + snd_pcm_format_physical_width(params_format(params)));
  12014. + printd("format = %d\n", params_format(params));
  12015. +
  12016. + gpiod_set_value(reset, false);
  12017. +
  12018. + switch (params_rate(params)) {
  12019. + case 48000:
  12020. + gpiod_set_value(osr0, true);
  12021. + gpiod_set_value(osr1, false);
  12022. + gpiod_set_value(osr2, false);
  12023. + break;
  12024. + case 96000:
  12025. + gpiod_set_value(osr0, true);
  12026. + gpiod_set_value(osr1, false);
  12027. + gpiod_set_value(osr2, true);
  12028. + break;
  12029. + case 192000:
  12030. + gpiod_set_value(osr0, true);
  12031. + gpiod_set_value(osr1, true);
  12032. + gpiod_set_value(osr2, true);
  12033. + break;
  12034. + default:
  12035. + printe("Unsupported rate %u!\n", params_rate(params));
  12036. + return -EINVAL;
  12037. + }
  12038. +
  12039. + gpiod_set_value(reset, true);
  12040. +
  12041. + return 0;
  12042. +}
  12043. +
  12044. +static unsigned int rates[3] = {
  12045. + 48000, 96000, 192000
  12046. +};
  12047. +
  12048. +static struct snd_pcm_hw_constraint_list constraints_rates = {
  12049. + .count = ARRAY_SIZE(rates),
  12050. + .list = rates,
  12051. + .mask = 0,
  12052. +};
  12053. +
  12054. +static int pisnd_startup(struct snd_pcm_substream *substream)
  12055. +{
  12056. + int err = snd_pcm_hw_constraint_list(
  12057. + substream->runtime,
  12058. + 0,
  12059. + SNDRV_PCM_HW_PARAM_RATE,
  12060. + &constraints_rates
  12061. + );
  12062. +
  12063. + if (err < 0)
  12064. + return err;
  12065. +
  12066. + err = snd_pcm_hw_constraint_single(
  12067. + substream->runtime,
  12068. + SNDRV_PCM_HW_PARAM_CHANNELS,
  12069. + 2
  12070. + );
  12071. +
  12072. + if (err < 0)
  12073. + return err;
  12074. +
  12075. + err = snd_pcm_hw_constraint_mask64(
  12076. + substream->runtime,
  12077. + SNDRV_PCM_HW_PARAM_FORMAT,
  12078. + SNDRV_PCM_FMTBIT_S16_LE |
  12079. + SNDRV_PCM_FMTBIT_S24_LE |
  12080. + SNDRV_PCM_FMTBIT_S32_LE
  12081. + );
  12082. +
  12083. + if (err < 0)
  12084. + return err;
  12085. +
  12086. + return 0;
  12087. +}
  12088. +
  12089. +static struct snd_soc_ops pisnd_ops = {
  12090. + .startup = pisnd_startup,
  12091. + .hw_params = pisnd_hw_params,
  12092. +};
  12093. +
  12094. +SND_SOC_DAILINK_DEFS(pisnd,
  12095. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  12096. + DAILINK_COMP_ARRAY(COMP_DUMMY()),
  12097. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  12098. +
  12099. +static struct snd_soc_dai_link pisnd_dai[] = {
  12100. + {
  12101. + .name = "pisound",
  12102. + .stream_name = "pisound",
  12103. + .dai_fmt =
  12104. + SND_SOC_DAIFMT_I2S |
  12105. + SND_SOC_DAIFMT_NB_NF |
  12106. + SND_SOC_DAIFMT_CBM_CFM,
  12107. + .ops = &pisnd_ops,
  12108. + SND_SOC_DAILINK_REG(pisnd),
  12109. + },
  12110. +};
  12111. +
  12112. +static int pisnd_card_probe(struct snd_soc_card *card)
  12113. +{
  12114. + int err = pisnd_midi_init(card->snd_card);
  12115. +
  12116. + if (err < 0) {
  12117. + printe("pisnd_midi_init failed: %d\n", err);
  12118. + return err;
  12119. + }
  12120. +
  12121. + err = pisnd_ctl_init(card->snd_card);
  12122. + if (err < 0) {
  12123. + printe("pisnd_ctl_init failed: %d\n", err);
  12124. + return err;
  12125. + }
  12126. +
  12127. + return 0;
  12128. +}
  12129. +
  12130. +static int pisnd_card_remove(struct snd_soc_card *card)
  12131. +{
  12132. + pisnd_ctl_uninit();
  12133. + pisnd_midi_uninit();
  12134. + return 0;
  12135. +}
  12136. +
  12137. +static struct snd_soc_card pisnd_card = {
  12138. + .name = "pisound",
  12139. + .owner = THIS_MODULE,
  12140. + .dai_link = pisnd_dai,
  12141. + .num_links = ARRAY_SIZE(pisnd_dai),
  12142. + .probe = pisnd_card_probe,
  12143. + .remove = pisnd_card_remove,
  12144. +};
  12145. +
  12146. +static int pisnd_init_gpio(struct device *dev)
  12147. +{
  12148. + osr0 = gpiod_get_index(dev, "osr", 0, GPIOD_ASIS);
  12149. + osr1 = gpiod_get_index(dev, "osr", 1, GPIOD_ASIS);
  12150. + osr2 = gpiod_get_index(dev, "osr", 2, GPIOD_ASIS);
  12151. +
  12152. + reset = gpiod_get_index(dev, "reset", 0, GPIOD_ASIS);
  12153. +
  12154. + button = gpiod_get_index(dev, "button", 0, GPIOD_ASIS);
  12155. +
  12156. + gpiod_direction_output(osr0, 1);
  12157. + gpiod_direction_output(osr1, 1);
  12158. + gpiod_direction_output(osr2, 1);
  12159. + gpiod_direction_output(reset, 1);
  12160. +
  12161. + gpiod_set_value(reset, false);
  12162. + gpiod_set_value(osr0, true);
  12163. + gpiod_set_value(osr1, false);
  12164. + gpiod_set_value(osr2, false);
  12165. + gpiod_set_value(reset, true);
  12166. +
  12167. + gpiod_export(button, false);
  12168. +
  12169. + return 0;
  12170. +}
  12171. +
  12172. +static int pisnd_uninit_gpio(void)
  12173. +{
  12174. + int i;
  12175. +
  12176. + struct gpio_desc **gpios[] = {
  12177. + &osr0, &osr1, &osr2, &reset, &button,
  12178. + };
  12179. +
  12180. + gpiod_unexport(button);
  12181. +
  12182. + for (i = 0; i < ARRAY_SIZE(gpios); ++i) {
  12183. + if (*gpios[i] == NULL) {
  12184. + printd("weird, GPIO[%d] is NULL already\n", i);
  12185. + continue;
  12186. + }
  12187. +
  12188. + gpiod_put(*gpios[i]);
  12189. + *gpios[i] = NULL;
  12190. + }
  12191. +
  12192. + return 0;
  12193. +}
  12194. +
  12195. +static struct kobject *pisnd_kobj;
  12196. +
  12197. +static ssize_t pisnd_serial_show(
  12198. + struct kobject *kobj,
  12199. + struct kobj_attribute *attr,
  12200. + char *buf
  12201. + )
  12202. +{
  12203. + return sprintf(buf, "%s\n", pisnd_spi_get_serial());
  12204. +}
  12205. +
  12206. +static ssize_t pisnd_id_show(
  12207. + struct kobject *kobj,
  12208. + struct kobj_attribute *attr,
  12209. + char *buf
  12210. + )
  12211. +{
  12212. + return sprintf(buf, "%s\n", pisnd_spi_get_id());
  12213. +}
  12214. +
  12215. +static ssize_t pisnd_fw_version_show(
  12216. + struct kobject *kobj,
  12217. + struct kobj_attribute *attr,
  12218. + char *buf
  12219. + )
  12220. +{
  12221. + return sprintf(buf, "%s\n", pisnd_spi_get_fw_version());
  12222. +}
  12223. +
  12224. +static ssize_t pisnd_hw_version_show(
  12225. + struct kobject *kobj,
  12226. + struct kobj_attribute *attr,
  12227. + char *buf
  12228. +)
  12229. +{
  12230. + return sprintf(buf, "%s\n", pisnd_spi_get_hw_version());
  12231. +}
  12232. +
  12233. +static ssize_t pisnd_led_store(
  12234. + struct kobject *kobj,
  12235. + struct kobj_attribute *attr,
  12236. + const char *buf,
  12237. + size_t length
  12238. + )
  12239. +{
  12240. + uint32_t timeout;
  12241. + int err;
  12242. +
  12243. + err = kstrtou32(buf, 10, &timeout);
  12244. +
  12245. + if (err == 0 && timeout <= 255)
  12246. + pisnd_spi_flash_leds(timeout);
  12247. +
  12248. + return length;
  12249. +}
  12250. +
  12251. +static struct kobj_attribute pisnd_serial_attribute =
  12252. + __ATTR(serial, 0444, pisnd_serial_show, NULL);
  12253. +static struct kobj_attribute pisnd_id_attribute =
  12254. + __ATTR(id, 0444, pisnd_id_show, NULL);
  12255. +static struct kobj_attribute pisnd_fw_version_attribute =
  12256. + __ATTR(version, 0444, pisnd_fw_version_show, NULL);
  12257. +static struct kobj_attribute pisnd_hw_version_attribute =
  12258. +__ATTR(hw_version, 0444, pisnd_hw_version_show, NULL);
  12259. +static struct kobj_attribute pisnd_led_attribute =
  12260. + __ATTR(led, 0644, NULL, pisnd_led_store);
  12261. +
  12262. +static struct attribute *attrs[] = {
  12263. + &pisnd_serial_attribute.attr,
  12264. + &pisnd_id_attribute.attr,
  12265. + &pisnd_fw_version_attribute.attr,
  12266. + &pisnd_hw_version_attribute.attr,
  12267. + &pisnd_led_attribute.attr,
  12268. + NULL
  12269. +};
  12270. +
  12271. +static struct attribute_group attr_group = { .attrs = attrs };
  12272. +
  12273. +static int pisnd_probe(struct platform_device *pdev)
  12274. +{
  12275. + int ret = 0;
  12276. + int i;
  12277. +
  12278. + ret = pisnd_spi_init(&pdev->dev);
  12279. + if (ret < 0) {
  12280. + printe("pisnd_spi_init failed: %d\n", ret);
  12281. + return ret;
  12282. + }
  12283. +
  12284. + printi("Detected Pisound card:\n");
  12285. + printi("\tSerial: %s\n", pisnd_spi_get_serial());
  12286. + printi("\tFirmware Version: %s\n", pisnd_spi_get_fw_version());
  12287. + printi("\tHardware Version: %s\n", pisnd_spi_get_hw_version());
  12288. + printi("\tId: %s\n", pisnd_spi_get_id());
  12289. +
  12290. + pisnd_kobj = kobject_create_and_add("pisound", kernel_kobj);
  12291. + if (!pisnd_kobj) {
  12292. + pisnd_spi_uninit();
  12293. + return -ENOMEM;
  12294. + }
  12295. +
  12296. + ret = sysfs_create_group(pisnd_kobj, &attr_group);
  12297. + if (ret < 0) {
  12298. + pisnd_spi_uninit();
  12299. + kobject_put(pisnd_kobj);
  12300. + return -ENOMEM;
  12301. + }
  12302. +
  12303. + pisnd_init_gpio(&pdev->dev);
  12304. + pisnd_card.dev = &pdev->dev;
  12305. +
  12306. + if (pdev->dev.of_node) {
  12307. + struct device_node *i2s_node;
  12308. +
  12309. + i2s_node = of_parse_phandle(
  12310. + pdev->dev.of_node,
  12311. + "i2s-controller",
  12312. + 0
  12313. + );
  12314. +
  12315. + for (i = 0; i < pisnd_card.num_links; ++i) {
  12316. + struct snd_soc_dai_link *dai = &pisnd_dai[i];
  12317. +
  12318. + if (i2s_node) {
  12319. + dai->cpus->dai_name = NULL;
  12320. + dai->cpus->of_node = i2s_node;
  12321. + dai->platforms->name = NULL;
  12322. + dai->platforms->of_node = i2s_node;
  12323. + dai->stream_name = pisnd_spi_get_serial();
  12324. + }
  12325. + }
  12326. + }
  12327. +
  12328. + ret = snd_soc_register_card(&pisnd_card);
  12329. +
  12330. + if (ret < 0) {
  12331. + if (ret != -EPROBE_DEFER)
  12332. + printe("snd_soc_register_card() failed: %d\n", ret);
  12333. + pisnd_uninit_gpio();
  12334. + kobject_put(pisnd_kobj);
  12335. + pisnd_spi_uninit();
  12336. + }
  12337. +
  12338. + return ret;
  12339. +}
  12340. +
  12341. +static int pisnd_remove(struct platform_device *pdev)
  12342. +{
  12343. + printi("Unloading.\n");
  12344. +
  12345. + if (pisnd_kobj) {
  12346. + kobject_put(pisnd_kobj);
  12347. + pisnd_kobj = NULL;
  12348. + }
  12349. +
  12350. + pisnd_spi_uninit();
  12351. +
  12352. + /* Turn off */
  12353. + gpiod_set_value(reset, false);
  12354. + pisnd_uninit_gpio();
  12355. +
  12356. + snd_soc_unregister_card(&pisnd_card);
  12357. + return 0;
  12358. +}
  12359. +
  12360. +MODULE_DEVICE_TABLE(of, pisound_of_match);
  12361. +
  12362. +static struct platform_driver pisnd_driver = {
  12363. + .driver = {
  12364. + .name = "snd-rpi-pisound",
  12365. + .owner = THIS_MODULE,
  12366. + .of_match_table = pisound_of_match,
  12367. + },
  12368. + .probe = pisnd_probe,
  12369. + .remove = pisnd_remove,
  12370. +};
  12371. +
  12372. +module_platform_driver(pisnd_driver);
  12373. +
  12374. +MODULE_AUTHOR("Giedrius Trainavicius <[email protected]>");
  12375. +MODULE_DESCRIPTION("ASoC Driver for Pisound, https://blokas.io/pisound");
  12376. +MODULE_LICENSE("GPL v2");
  12377. --- /dev/null
  12378. +++ b/sound/soc/bcm/rpi-cirrus.c
  12379. @@ -0,0 +1,1025 @@
  12380. +/*
  12381. + * ASoC machine driver for Cirrus Logic Audio Card
  12382. + * (with WM5102 and WM8804 codecs)
  12383. + *
  12384. + * Copyright 2015-2017 Matthias Reichl <[email protected]>
  12385. + *
  12386. + * Based on rpi-cirrus-sound-pi driver (c) Wolfson / Cirrus Logic Inc.
  12387. + *
  12388. + * This program is free software; you can redistribute it and/or modify
  12389. + * it under the terms of the GNU General Public License version 2 as
  12390. + * published by the Free Software Foundation.
  12391. + */
  12392. +
  12393. +#include <linux/module.h>
  12394. +#include <linux/mutex.h>
  12395. +#include <linux/slab.h>
  12396. +#include <linux/list.h>
  12397. +#include <linux/delay.h>
  12398. +#include <sound/pcm_params.h>
  12399. +
  12400. +#include <linux/mfd/arizona/registers.h>
  12401. +
  12402. +#include "../codecs/wm5102.h"
  12403. +#include "../codecs/wm8804.h"
  12404. +
  12405. +#define WM8804_CLKOUT_HZ 12000000
  12406. +
  12407. +#define RPI_CIRRUS_DEFAULT_RATE 44100
  12408. +#define WM5102_MAX_SYSCLK_1 49152000 /* max sysclk for 4K family */
  12409. +#define WM5102_MAX_SYSCLK_2 45158400 /* max sysclk for 11.025K family */
  12410. +
  12411. +static inline unsigned int calc_sysclk(unsigned int rate)
  12412. +{
  12413. + return (rate % 4000) ? WM5102_MAX_SYSCLK_2 : WM5102_MAX_SYSCLK_1;
  12414. +}
  12415. +
  12416. +enum {
  12417. + DAI_WM5102 = 0,
  12418. + DAI_WM8804,
  12419. +};
  12420. +
  12421. +struct rpi_cirrus_priv {
  12422. + /* mutex for synchronzing FLL1 access with DAPM */
  12423. + struct mutex lock;
  12424. + unsigned int card_rate;
  12425. + int sync_path_enable;
  12426. + int fll1_freq; /* negative means RefClock in spdif rx case */
  12427. +
  12428. + /* track hw params/free for substreams */
  12429. + unsigned int params_set;
  12430. + unsigned int min_rate_idx, max_rate_idx;
  12431. + unsigned char iec958_status[4];
  12432. +};
  12433. +
  12434. +/* helper functions */
  12435. +static inline struct snd_soc_pcm_runtime *get_wm5102_runtime(
  12436. + struct snd_soc_card *card) {
  12437. + return snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_WM5102]);
  12438. +}
  12439. +
  12440. +static inline struct snd_soc_pcm_runtime *get_wm8804_runtime(
  12441. + struct snd_soc_card *card) {
  12442. + return snd_soc_get_pcm_runtime(card, &card->dai_link[DAI_WM8804]);
  12443. +}
  12444. +
  12445. +
  12446. +struct rate_info {
  12447. + unsigned int value;
  12448. + char *text;
  12449. +};
  12450. +
  12451. +static struct rate_info min_rates[] = {
  12452. + { 0, "off"},
  12453. + { 32000, "32kHz"},
  12454. + { 44100, "44.1kHz"}
  12455. +};
  12456. +
  12457. +#define NUM_MIN_RATES ARRAY_SIZE(min_rates)
  12458. +
  12459. +static int rpi_cirrus_min_rate_info(struct snd_kcontrol *kcontrol,
  12460. + struct snd_ctl_elem_info *uinfo)
  12461. +{
  12462. + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  12463. + uinfo->count = 1;
  12464. + uinfo->value.enumerated.items = NUM_MIN_RATES;
  12465. +
  12466. + if (uinfo->value.enumerated.item >= NUM_MIN_RATES)
  12467. + uinfo->value.enumerated.item = NUM_MIN_RATES - 1;
  12468. + strcpy(uinfo->value.enumerated.name,
  12469. + min_rates[uinfo->value.enumerated.item].text);
  12470. + return 0;
  12471. +}
  12472. +
  12473. +static int rpi_cirrus_min_rate_get(struct snd_kcontrol *kcontrol,
  12474. + struct snd_ctl_elem_value *ucontrol)
  12475. +{
  12476. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  12477. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  12478. +
  12479. + ucontrol->value.enumerated.item[0] = priv->min_rate_idx;
  12480. + return 0;
  12481. +}
  12482. +
  12483. +static int rpi_cirrus_min_rate_put(struct snd_kcontrol *kcontrol,
  12484. + struct snd_ctl_elem_value *ucontrol)
  12485. +{
  12486. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  12487. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  12488. + int changed = 0;
  12489. +
  12490. + if (priv->min_rate_idx != ucontrol->value.enumerated.item[0]) {
  12491. + changed = 1;
  12492. + priv->min_rate_idx = ucontrol->value.enumerated.item[0];
  12493. + }
  12494. +
  12495. + return changed;
  12496. +}
  12497. +
  12498. +static struct rate_info max_rates[] = {
  12499. + { 0, "off"},
  12500. + { 48000, "48kHz"},
  12501. + { 96000, "96kHz"}
  12502. +};
  12503. +
  12504. +#define NUM_MAX_RATES ARRAY_SIZE(max_rates)
  12505. +
  12506. +static int rpi_cirrus_max_rate_info(struct snd_kcontrol *kcontrol,
  12507. + struct snd_ctl_elem_info *uinfo)
  12508. +{
  12509. + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  12510. + uinfo->count = 1;
  12511. + uinfo->value.enumerated.items = NUM_MAX_RATES;
  12512. + if (uinfo->value.enumerated.item >= NUM_MAX_RATES)
  12513. + uinfo->value.enumerated.item = NUM_MAX_RATES - 1;
  12514. + strcpy(uinfo->value.enumerated.name,
  12515. + max_rates[uinfo->value.enumerated.item].text);
  12516. + return 0;
  12517. +}
  12518. +
  12519. +static int rpi_cirrus_max_rate_get(struct snd_kcontrol *kcontrol,
  12520. + struct snd_ctl_elem_value *ucontrol)
  12521. +{
  12522. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  12523. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  12524. +
  12525. + ucontrol->value.enumerated.item[0] = priv->max_rate_idx;
  12526. + return 0;
  12527. +}
  12528. +
  12529. +static int rpi_cirrus_max_rate_put(struct snd_kcontrol *kcontrol,
  12530. + struct snd_ctl_elem_value *ucontrol)
  12531. +{
  12532. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  12533. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  12534. + int changed = 0;
  12535. +
  12536. + if (priv->max_rate_idx != ucontrol->value.enumerated.item[0]) {
  12537. + changed = 1;
  12538. + priv->max_rate_idx = ucontrol->value.enumerated.item[0];
  12539. + }
  12540. +
  12541. + return changed;
  12542. +}
  12543. +
  12544. +static int rpi_cirrus_spdif_info(struct snd_kcontrol *kcontrol,
  12545. + struct snd_ctl_elem_info *uinfo)
  12546. +{
  12547. + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
  12548. + uinfo->count = 1;
  12549. + return 0;
  12550. +}
  12551. +
  12552. +static int rpi_cirrus_spdif_playback_get(struct snd_kcontrol *kcontrol,
  12553. + struct snd_ctl_elem_value *ucontrol)
  12554. +{
  12555. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  12556. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  12557. + int i;
  12558. +
  12559. + for (i = 0; i < 4; i++)
  12560. + ucontrol->value.iec958.status[i] = priv->iec958_status[i];
  12561. +
  12562. + return 0;
  12563. +}
  12564. +
  12565. +static int rpi_cirrus_spdif_playback_put(struct snd_kcontrol *kcontrol,
  12566. + struct snd_ctl_elem_value *ucontrol)
  12567. +{
  12568. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  12569. + struct snd_soc_component *wm8804_component =
  12570. + asoc_rtd_to_codec(get_wm8804_runtime(card), 0)->component;
  12571. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  12572. + unsigned char *stat = priv->iec958_status;
  12573. + unsigned char *ctrl_stat = ucontrol->value.iec958.status;
  12574. + unsigned int mask;
  12575. + int i, changed = 0;
  12576. +
  12577. + for (i = 0; i < 4; i++) {
  12578. + mask = (i == 3) ? 0x3f : 0xff;
  12579. + if ((ctrl_stat[i] & mask) != (stat[i] & mask)) {
  12580. + changed = 1;
  12581. + stat[i] = ctrl_stat[i] & mask;
  12582. + snd_soc_component_update_bits(wm8804_component,
  12583. + WM8804_SPDTX1 + i, mask, stat[i]);
  12584. + }
  12585. + }
  12586. +
  12587. + return changed;
  12588. +}
  12589. +
  12590. +static int rpi_cirrus_spdif_mask_get(struct snd_kcontrol *kcontrol,
  12591. + struct snd_ctl_elem_value *ucontrol)
  12592. +{
  12593. + ucontrol->value.iec958.status[0] = 0xff;
  12594. + ucontrol->value.iec958.status[1] = 0xff;
  12595. + ucontrol->value.iec958.status[2] = 0xff;
  12596. + ucontrol->value.iec958.status[3] = 0x3f;
  12597. +
  12598. + return 0;
  12599. +}
  12600. +
  12601. +static int rpi_cirrus_spdif_capture_get(struct snd_kcontrol *kcontrol,
  12602. + struct snd_ctl_elem_value *ucontrol)
  12603. +{
  12604. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  12605. + struct snd_soc_component *wm8804_component =
  12606. + asoc_rtd_to_codec(get_wm8804_runtime(card), 0)->component;
  12607. + unsigned int val, mask;
  12608. + int i;
  12609. +
  12610. + for (i = 0; i < 4; i++) {
  12611. + val = snd_soc_component_read(wm8804_component,
  12612. + WM8804_RXCHAN1 + i);
  12613. + mask = (i == 3) ? 0x3f : 0xff;
  12614. + ucontrol->value.iec958.status[i] = val & mask;
  12615. + }
  12616. +
  12617. + return 0;
  12618. +}
  12619. +
  12620. +#define SPDIF_FLAG_CTRL(desc, reg, bit, invert) \
  12621. +{ \
  12622. + .access = SNDRV_CTL_ELEM_ACCESS_READ \
  12623. + | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
  12624. + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
  12625. + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) \
  12626. + desc " Flag", \
  12627. + .info = snd_ctl_boolean_mono_info, \
  12628. + .get = rpi_cirrus_spdif_status_flag_get, \
  12629. + .private_value = \
  12630. + (bit) | ((reg) << 8) | ((invert) << 16) \
  12631. +}
  12632. +
  12633. +static int rpi_cirrus_spdif_status_flag_get(struct snd_kcontrol *kcontrol,
  12634. + struct snd_ctl_elem_value *ucontrol)
  12635. +{
  12636. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  12637. + struct snd_soc_component *wm8804_component =
  12638. + asoc_rtd_to_codec(get_wm8804_runtime(card), 0)->component;
  12639. +
  12640. + unsigned int bit = kcontrol->private_value & 0xff;
  12641. + unsigned int reg = (kcontrol->private_value >> 8) & 0xff;
  12642. + unsigned int invert = (kcontrol->private_value >> 16) & 0xff;
  12643. + unsigned int val;
  12644. + bool flag;
  12645. +
  12646. + val = snd_soc_component_read(wm8804_component, reg);
  12647. +
  12648. + flag = val & (1 << bit);
  12649. +
  12650. + ucontrol->value.integer.value[0] = invert ? !flag : flag;
  12651. +
  12652. + return 0;
  12653. +}
  12654. +
  12655. +static const char * const recovered_frequency_texts[] = {
  12656. + "176.4/192 kHz",
  12657. + "88.2/96 kHz",
  12658. + "44.1/48 kHz",
  12659. + "32 kHz"
  12660. +};
  12661. +
  12662. +#define NUM_RECOVERED_FREQUENCIES \
  12663. + ARRAY_SIZE(recovered_frequency_texts)
  12664. +
  12665. +static int rpi_cirrus_recovered_frequency_info(struct snd_kcontrol *kcontrol,
  12666. + struct snd_ctl_elem_info *uinfo)
  12667. +{
  12668. + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  12669. + uinfo->count = 1;
  12670. + uinfo->value.enumerated.items = NUM_RECOVERED_FREQUENCIES;
  12671. + if (uinfo->value.enumerated.item >= NUM_RECOVERED_FREQUENCIES)
  12672. + uinfo->value.enumerated.item = NUM_RECOVERED_FREQUENCIES - 1;
  12673. + strcpy(uinfo->value.enumerated.name,
  12674. + recovered_frequency_texts[uinfo->value.enumerated.item]);
  12675. + return 0;
  12676. +}
  12677. +
  12678. +static int rpi_cirrus_recovered_frequency_get(struct snd_kcontrol *kcontrol,
  12679. + struct snd_ctl_elem_value *ucontrol)
  12680. +{
  12681. + struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
  12682. + struct snd_soc_component *wm8804_component =
  12683. + asoc_rtd_to_codec(get_wm8804_runtime(card), 0)->component;
  12684. + unsigned int val;
  12685. +
  12686. + val = snd_soc_component_read(wm8804_component, WM8804_SPDSTAT);
  12687. +
  12688. + ucontrol->value.enumerated.item[0] = (val >> 4) & 0x03;
  12689. + return 0;
  12690. +}
  12691. +
  12692. +static const struct snd_kcontrol_new rpi_cirrus_controls[] = {
  12693. + {
  12694. + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  12695. + .name = "Min Sample Rate",
  12696. + .info = rpi_cirrus_min_rate_info,
  12697. + .get = rpi_cirrus_min_rate_get,
  12698. + .put = rpi_cirrus_min_rate_put,
  12699. + },
  12700. + {
  12701. + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  12702. + .name = "Max Sample Rate",
  12703. + .info = rpi_cirrus_max_rate_info,
  12704. + .get = rpi_cirrus_max_rate_get,
  12705. + .put = rpi_cirrus_max_rate_put,
  12706. + },
  12707. + {
  12708. + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  12709. + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
  12710. + .info = rpi_cirrus_spdif_info,
  12711. + .get = rpi_cirrus_spdif_playback_get,
  12712. + .put = rpi_cirrus_spdif_playback_put,
  12713. + },
  12714. + {
  12715. + .access = SNDRV_CTL_ELEM_ACCESS_READ
  12716. + | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
  12717. + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  12718. + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
  12719. + .info = rpi_cirrus_spdif_info,
  12720. + .get = rpi_cirrus_spdif_capture_get,
  12721. + },
  12722. + {
  12723. + .access = SNDRV_CTL_ELEM_ACCESS_READ,
  12724. + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  12725. + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
  12726. + .info = rpi_cirrus_spdif_info,
  12727. + .get = rpi_cirrus_spdif_mask_get,
  12728. + },
  12729. + {
  12730. + .access = SNDRV_CTL_ELEM_ACCESS_READ
  12731. + | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
  12732. + .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  12733. + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE)
  12734. + "Recovered Frequency",
  12735. + .info = rpi_cirrus_recovered_frequency_info,
  12736. + .get = rpi_cirrus_recovered_frequency_get,
  12737. + },
  12738. + SPDIF_FLAG_CTRL("Audio", WM8804_SPDSTAT, 0, 1),
  12739. + SPDIF_FLAG_CTRL("Non-PCM", WM8804_SPDSTAT, 1, 0),
  12740. + SPDIF_FLAG_CTRL("Copyright", WM8804_SPDSTAT, 2, 1),
  12741. + SPDIF_FLAG_CTRL("De-Emphasis", WM8804_SPDSTAT, 3, 0),
  12742. + SPDIF_FLAG_CTRL("Lock", WM8804_SPDSTAT, 6, 1),
  12743. + SPDIF_FLAG_CTRL("Invalid", WM8804_INTSTAT, 1, 0),
  12744. + SPDIF_FLAG_CTRL("TransErr", WM8804_INTSTAT, 3, 0),
  12745. +};
  12746. +
  12747. +static const char * const linein_micbias_texts[] = {
  12748. + "off", "on",
  12749. +};
  12750. +
  12751. +static SOC_ENUM_SINGLE_VIRT_DECL(linein_micbias_enum,
  12752. + linein_micbias_texts);
  12753. +
  12754. +static const struct snd_kcontrol_new linein_micbias_mux =
  12755. + SOC_DAPM_ENUM("Route", linein_micbias_enum);
  12756. +
  12757. +static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w,
  12758. + struct snd_kcontrol *kcontrol, int event);
  12759. +
  12760. +const struct snd_soc_dapm_widget rpi_cirrus_dapm_widgets[] = {
  12761. + SND_SOC_DAPM_MIC("DMIC", NULL),
  12762. + SND_SOC_DAPM_MIC("Headset Mic", NULL),
  12763. + SND_SOC_DAPM_INPUT("Line Input"),
  12764. + SND_SOC_DAPM_MIC("Line Input with Micbias", NULL),
  12765. + SND_SOC_DAPM_MUX("Line Input Micbias", SND_SOC_NOPM, 0, 0,
  12766. + &linein_micbias_mux),
  12767. + SND_SOC_DAPM_INPUT("dummy SPDIF in"),
  12768. + SND_SOC_DAPM_PGA_E("dummy SPDIFRX", SND_SOC_NOPM, 0, 0, NULL, 0,
  12769. + rpi_cirrus_spdif_rx_enable_event,
  12770. + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
  12771. + SND_SOC_DAPM_INPUT("Dummy Input"),
  12772. + SND_SOC_DAPM_OUTPUT("Dummy Output"),
  12773. +};
  12774. +
  12775. +const struct snd_soc_dapm_route rpi_cirrus_dapm_routes[] = {
  12776. + { "IN1L", NULL, "Headset Mic" },
  12777. + { "IN1R", NULL, "Headset Mic" },
  12778. + { "Headset Mic", NULL, "MICBIAS1" },
  12779. +
  12780. + { "IN2L", NULL, "DMIC" },
  12781. + { "IN2R", NULL, "DMIC" },
  12782. + { "DMIC", NULL, "MICBIAS2" },
  12783. +
  12784. + { "IN3L", NULL, "Line Input Micbias" },
  12785. + { "IN3R", NULL, "Line Input Micbias" },
  12786. +
  12787. + { "Line Input Micbias", "off", "Line Input" },
  12788. + { "Line Input Micbias", "on", "Line Input with Micbias" },
  12789. +
  12790. + /* Make sure MICVDD is enabled, otherwise we get noise */
  12791. + { "Line Input", NULL, "MICVDD" },
  12792. + { "Line Input with Micbias", NULL, "MICBIAS3" },
  12793. +
  12794. + /* Dummy routes to check whether SPDIF RX is enabled or not */
  12795. + {"dummy SPDIFRX", NULL, "dummy SPDIF in"},
  12796. + {"AIFTX", NULL, "dummy SPDIFRX"},
  12797. +
  12798. + /*
  12799. + * Dummy routes to keep wm5102 from staying off on
  12800. + * playback/capture if all mixers are off.
  12801. + */
  12802. + { "Dummy Output", NULL, "AIF1RX1" },
  12803. + { "Dummy Output", NULL, "AIF1RX2" },
  12804. + { "AIF1TX1", NULL, "Dummy Input" },
  12805. + { "AIF1TX2", NULL, "Dummy Input" },
  12806. +};
  12807. +
  12808. +static int rpi_cirrus_clear_flls(struct snd_soc_card *card,
  12809. + struct snd_soc_component *wm5102_component) {
  12810. +
  12811. + int ret1, ret2;
  12812. +
  12813. + ret1 = snd_soc_component_set_pll(wm5102_component,
  12814. + WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0);
  12815. + ret2 = snd_soc_component_set_pll(wm5102_component,
  12816. + WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0);
  12817. +
  12818. + if (ret1) {
  12819. + dev_warn(card->dev,
  12820. + "setting FLL1 to zero failed: %d\n", ret1);
  12821. + return ret1;
  12822. + }
  12823. + if (ret2) {
  12824. + dev_warn(card->dev,
  12825. + "setting FLL1_REFCLK to zero failed: %d\n", ret2);
  12826. + return ret2;
  12827. + }
  12828. + return 0;
  12829. +}
  12830. +
  12831. +static int rpi_cirrus_set_fll(struct snd_soc_card *card,
  12832. + struct snd_soc_component *wm5102_component, unsigned int clk_freq)
  12833. +{
  12834. + int ret = snd_soc_component_set_pll(wm5102_component,
  12835. + WM5102_FLL1,
  12836. + ARIZONA_CLK_SRC_MCLK1,
  12837. + WM8804_CLKOUT_HZ,
  12838. + clk_freq);
  12839. + if (ret)
  12840. + dev_err(card->dev, "Failed to set FLL1 to %d: %d\n",
  12841. + clk_freq, ret);
  12842. +
  12843. + usleep_range(1000, 2000);
  12844. + return ret;
  12845. +}
  12846. +
  12847. +static int rpi_cirrus_set_fll_refclk(struct snd_soc_card *card,
  12848. + struct snd_soc_component *wm5102_component,
  12849. + unsigned int clk_freq, unsigned int aif2_freq)
  12850. +{
  12851. + int ret = snd_soc_component_set_pll(wm5102_component,
  12852. + WM5102_FLL1_REFCLK,
  12853. + ARIZONA_CLK_SRC_MCLK1,
  12854. + WM8804_CLKOUT_HZ,
  12855. + clk_freq);
  12856. + if (ret) {
  12857. + dev_err(card->dev,
  12858. + "Failed to set FLL1_REFCLK to %d: %d\n",
  12859. + clk_freq, ret);
  12860. + return ret;
  12861. + }
  12862. +
  12863. + ret = snd_soc_component_set_pll(wm5102_component,
  12864. + WM5102_FLL1,
  12865. + ARIZONA_CLK_SRC_AIF2BCLK,
  12866. + aif2_freq, clk_freq);
  12867. + if (ret)
  12868. + dev_err(card->dev,
  12869. + "Failed to set FLL1 with Sync Clock %d to %d: %d\n",
  12870. + aif2_freq, clk_freq, ret);
  12871. +
  12872. + usleep_range(1000, 2000);
  12873. + return ret;
  12874. +}
  12875. +
  12876. +static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w,
  12877. + struct snd_kcontrol *kcontrol, int event)
  12878. +{
  12879. + struct snd_soc_card *card = w->dapm->card;
  12880. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  12881. + struct snd_soc_component *wm5102_component =
  12882. + asoc_rtd_to_codec(get_wm5102_runtime(card), 0)->component;
  12883. +
  12884. + unsigned int clk_freq, aif2_freq;
  12885. + int ret = 0;
  12886. +
  12887. + switch (event) {
  12888. + case SND_SOC_DAPM_POST_PMU:
  12889. + mutex_lock(&priv->lock);
  12890. +
  12891. + /* Enable sync path in case of SPDIF capture use case */
  12892. +
  12893. + clk_freq = calc_sysclk(priv->card_rate);
  12894. + aif2_freq = 64 * priv->card_rate;
  12895. +
  12896. + dev_dbg(card->dev,
  12897. + "spdif_rx: changing FLL1 to use Ref Clock clk: %d spdif: %d\n",
  12898. + clk_freq, aif2_freq);
  12899. +
  12900. + ret = rpi_cirrus_clear_flls(card, wm5102_component);
  12901. + if (ret) {
  12902. + dev_err(card->dev, "spdif_rx: failed to clear FLLs\n");
  12903. + goto out;
  12904. + }
  12905. +
  12906. + ret = rpi_cirrus_set_fll_refclk(card, wm5102_component,
  12907. + clk_freq, aif2_freq);
  12908. +
  12909. + if (ret) {
  12910. + dev_err(card->dev, "spdif_rx: failed to set FLLs\n");
  12911. + goto out;
  12912. + }
  12913. +
  12914. + /* set to negative to indicate we're doing spdif rx */
  12915. + priv->fll1_freq = -clk_freq;
  12916. + priv->sync_path_enable = 1;
  12917. + break;
  12918. +
  12919. + case SND_SOC_DAPM_POST_PMD:
  12920. + mutex_lock(&priv->lock);
  12921. + priv->sync_path_enable = 0;
  12922. + break;
  12923. +
  12924. + default:
  12925. + return 0;
  12926. + }
  12927. +
  12928. +out:
  12929. + mutex_unlock(&priv->lock);
  12930. + return ret;
  12931. +}
  12932. +
  12933. +static int rpi_cirrus_set_bias_level(struct snd_soc_card *card,
  12934. + struct snd_soc_dapm_context *dapm,
  12935. + enum snd_soc_bias_level level)
  12936. +{
  12937. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  12938. + struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card);
  12939. + struct snd_soc_component *wm5102_component =
  12940. + asoc_rtd_to_codec(wm5102_runtime, 0)->component;
  12941. +
  12942. + int ret = 0;
  12943. + unsigned int clk_freq;
  12944. +
  12945. + if (dapm->dev != asoc_rtd_to_codec(wm5102_runtime, 0)->dev)
  12946. + return 0;
  12947. +
  12948. + switch (level) {
  12949. + case SND_SOC_BIAS_PREPARE:
  12950. + if (dapm->bias_level == SND_SOC_BIAS_ON)
  12951. + break;
  12952. +
  12953. + mutex_lock(&priv->lock);
  12954. +
  12955. + if (!priv->sync_path_enable) {
  12956. + clk_freq = calc_sysclk(priv->card_rate);
  12957. +
  12958. + dev_dbg(card->dev,
  12959. + "set_bias: changing FLL1 from %d to %d\n",
  12960. + priv->fll1_freq, clk_freq);
  12961. +
  12962. + ret = rpi_cirrus_set_fll(card,
  12963. + wm5102_component, clk_freq);
  12964. + if (ret)
  12965. + dev_err(card->dev,
  12966. + "set_bias: Failed to set FLL1\n");
  12967. + else
  12968. + priv->fll1_freq = clk_freq;
  12969. + }
  12970. + mutex_unlock(&priv->lock);
  12971. + break;
  12972. + default:
  12973. + break;
  12974. + }
  12975. +
  12976. + return ret;
  12977. +}
  12978. +
  12979. +static int rpi_cirrus_set_bias_level_post(struct snd_soc_card *card,
  12980. + struct snd_soc_dapm_context *dapm,
  12981. + enum snd_soc_bias_level level)
  12982. +{
  12983. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  12984. + struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card);
  12985. + struct snd_soc_component *wm5102_component =
  12986. + asoc_rtd_to_codec(wm5102_runtime, 0)->component;
  12987. +
  12988. + if (dapm->dev != asoc_rtd_to_codec(wm5102_runtime, 0)->dev)
  12989. + return 0;
  12990. +
  12991. + switch (level) {
  12992. + case SND_SOC_BIAS_STANDBY:
  12993. + mutex_lock(&priv->lock);
  12994. +
  12995. + dev_dbg(card->dev,
  12996. + "set_bias_post: changing FLL1 from %d to off\n",
  12997. + priv->fll1_freq);
  12998. +
  12999. + if (rpi_cirrus_clear_flls(card, wm5102_component))
  13000. + dev_err(card->dev,
  13001. + "set_bias_post: failed to clear FLLs\n");
  13002. + else
  13003. + priv->fll1_freq = 0;
  13004. +
  13005. + mutex_unlock(&priv->lock);
  13006. +
  13007. + break;
  13008. + default:
  13009. + break;
  13010. + }
  13011. +
  13012. + return 0;
  13013. +}
  13014. +
  13015. +static int rpi_cirrus_set_wm8804_pll(struct snd_soc_card *card,
  13016. + struct snd_soc_dai *wm8804_dai, unsigned int rate)
  13017. +{
  13018. + int ret;
  13019. +
  13020. + /* use 256fs */
  13021. + unsigned int clk_freq = rate * 256;
  13022. +
  13023. + ret = snd_soc_dai_set_pll(wm8804_dai, 0, 0,
  13024. + WM8804_CLKOUT_HZ, clk_freq);
  13025. + if (ret) {
  13026. + dev_err(card->dev,
  13027. + "Failed to set WM8804 PLL to %d: %d\n", clk_freq, ret);
  13028. + return ret;
  13029. + }
  13030. +
  13031. + /* Set MCLK as PLL Output */
  13032. + ret = snd_soc_dai_set_sysclk(wm8804_dai,
  13033. + WM8804_TX_CLKSRC_PLL, clk_freq, 0);
  13034. + if (ret) {
  13035. + dev_err(card->dev,
  13036. + "Failed to set MCLK as PLL Output: %d\n", ret);
  13037. + return ret;
  13038. + }
  13039. +
  13040. + return ret;
  13041. +}
  13042. +
  13043. +static int rpi_cirrus_startup(struct snd_pcm_substream *substream)
  13044. +{
  13045. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  13046. + struct snd_soc_card *card = rtd->card;
  13047. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  13048. + unsigned int min_rate = min_rates[priv->min_rate_idx].value;
  13049. + unsigned int max_rate = max_rates[priv->max_rate_idx].value;
  13050. +
  13051. + if (min_rate || max_rate) {
  13052. + if (max_rate == 0)
  13053. + max_rate = UINT_MAX;
  13054. +
  13055. + dev_dbg(card->dev,
  13056. + "startup: limiting rate to %u-%u\n",
  13057. + min_rate, max_rate);
  13058. +
  13059. + snd_pcm_hw_constraint_minmax(substream->runtime,
  13060. + SNDRV_PCM_HW_PARAM_RATE, min_rate, max_rate);
  13061. + }
  13062. +
  13063. + return 0;
  13064. +}
  13065. +
  13066. +static struct snd_soc_pcm_stream rpi_cirrus_dai_link2_params = {
  13067. + .formats = SNDRV_PCM_FMTBIT_S24_LE,
  13068. + .channels_min = 2,
  13069. + .channels_max = 2,
  13070. + .rate_min = RPI_CIRRUS_DEFAULT_RATE,
  13071. + .rate_max = RPI_CIRRUS_DEFAULT_RATE,
  13072. +};
  13073. +
  13074. +static int rpi_cirrus_hw_params(struct snd_pcm_substream *substream,
  13075. + struct snd_pcm_hw_params *params)
  13076. +{
  13077. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  13078. + struct snd_soc_card *card = rtd->card;
  13079. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  13080. + struct snd_soc_dai *bcm_i2s_dai = asoc_rtd_to_cpu(rtd, 0);
  13081. + struct snd_soc_component *wm5102_component = asoc_rtd_to_codec(rtd, 0)->component;
  13082. + struct snd_soc_dai *wm8804_dai = asoc_rtd_to_codec(get_wm8804_runtime(card), 0);
  13083. +
  13084. + int ret;
  13085. +
  13086. + unsigned int width = snd_pcm_format_physical_width(
  13087. + params_format(params));
  13088. + unsigned int rate = params_rate(params);
  13089. + unsigned int clk_freq = calc_sysclk(rate);
  13090. +
  13091. + mutex_lock(&priv->lock);
  13092. +
  13093. + dev_dbg(card->dev, "hw_params: setting rate to %d\n", rate);
  13094. +
  13095. + ret = snd_soc_dai_set_bclk_ratio(bcm_i2s_dai, 2 * width);
  13096. + if (ret) {
  13097. + dev_err(card->dev, "set_bclk_ratio failed: %d\n", ret);
  13098. + goto out;
  13099. + }
  13100. +
  13101. + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0x03, 0x03, 2, width);
  13102. + if (ret) {
  13103. + dev_err(card->dev, "set_tdm_slot failed: %d\n", ret);
  13104. + goto out;
  13105. + }
  13106. +
  13107. + /* WM8804 supports sample rates from 32k only */
  13108. + if (rate >= 32000) {
  13109. + ret = rpi_cirrus_set_wm8804_pll(card, wm8804_dai, rate);
  13110. + if (ret)
  13111. + goto out;
  13112. + }
  13113. +
  13114. + ret = snd_soc_component_set_sysclk(wm5102_component,
  13115. + ARIZONA_CLK_SYSCLK,
  13116. + ARIZONA_CLK_SRC_FLL1,
  13117. + clk_freq,
  13118. + SND_SOC_CLOCK_IN);
  13119. + if (ret) {
  13120. + dev_err(card->dev, "Failed to set SYSCLK: %d\n", ret);
  13121. + goto out;
  13122. + }
  13123. +
  13124. + if ((priv->fll1_freq > 0) && (priv->fll1_freq != clk_freq)) {
  13125. + dev_dbg(card->dev,
  13126. + "hw_params: changing FLL1 from %d to %d\n",
  13127. + priv->fll1_freq, clk_freq);
  13128. +
  13129. + if (rpi_cirrus_clear_flls(card, wm5102_component)) {
  13130. + dev_err(card->dev, "hw_params: failed to clear FLLs\n");
  13131. + goto out;
  13132. + }
  13133. +
  13134. + if (rpi_cirrus_set_fll(card, wm5102_component, clk_freq)) {
  13135. + dev_err(card->dev, "hw_params: failed to set FLL\n");
  13136. + goto out;
  13137. + }
  13138. +
  13139. + priv->fll1_freq = clk_freq;
  13140. + }
  13141. +
  13142. + priv->card_rate = rate;
  13143. + rpi_cirrus_dai_link2_params.rate_min = rate;
  13144. + rpi_cirrus_dai_link2_params.rate_max = rate;
  13145. +
  13146. + priv->params_set |= 1 << substream->stream;
  13147. +
  13148. +out:
  13149. + mutex_unlock(&priv->lock);
  13150. +
  13151. + return ret;
  13152. +}
  13153. +
  13154. +static int rpi_cirrus_hw_free(struct snd_pcm_substream *substream)
  13155. +{
  13156. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  13157. + struct snd_soc_card *card = rtd->card;
  13158. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  13159. + struct snd_soc_component *wm5102_component = asoc_rtd_to_codec(rtd, 0)->component;
  13160. + int ret;
  13161. + unsigned int old_params_set = priv->params_set;
  13162. +
  13163. + priv->params_set &= ~(1 << substream->stream);
  13164. +
  13165. + /* disable sysclk if this was the last open stream */
  13166. + if (priv->params_set == 0 && old_params_set) {
  13167. + dev_dbg(card->dev,
  13168. + "hw_free: Setting SYSCLK to Zero\n");
  13169. +
  13170. + ret = snd_soc_component_set_sysclk(wm5102_component,
  13171. + ARIZONA_CLK_SYSCLK,
  13172. + ARIZONA_CLK_SRC_FLL1,
  13173. + 0,
  13174. + SND_SOC_CLOCK_IN);
  13175. + if (ret)
  13176. + dev_err(card->dev,
  13177. + "hw_free: Failed to set SYSCLK to Zero: %d\n",
  13178. + ret);
  13179. + }
  13180. + return 0;
  13181. +}
  13182. +
  13183. +static int rpi_cirrus_init_wm5102(struct snd_soc_pcm_runtime *rtd)
  13184. +{
  13185. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  13186. + int ret;
  13187. +
  13188. + /* no 32kHz input, derive it from sysclk if needed */
  13189. + snd_soc_component_update_bits(component,
  13190. + ARIZONA_CLOCK_32K_1, ARIZONA_CLK_32K_SRC_MASK, 2);
  13191. +
  13192. + if (rpi_cirrus_clear_flls(rtd->card, component))
  13193. + dev_warn(rtd->card->dev,
  13194. + "init_wm5102: failed to clear FLLs\n");
  13195. +
  13196. + ret = snd_soc_component_set_sysclk(component,
  13197. + ARIZONA_CLK_SYSCLK, ARIZONA_CLK_SRC_FLL1,
  13198. + 0, SND_SOC_CLOCK_IN);
  13199. + if (ret) {
  13200. + dev_err(rtd->card->dev,
  13201. + "Failed to set SYSCLK to Zero: %d\n", ret);
  13202. + return ret;
  13203. + }
  13204. +
  13205. + return 0;
  13206. +}
  13207. +
  13208. +static int rpi_cirrus_init_wm8804(struct snd_soc_pcm_runtime *rtd)
  13209. +{
  13210. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  13211. + struct snd_soc_component *component = codec_dai->component;
  13212. + struct snd_soc_card *card = rtd->card;
  13213. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  13214. + unsigned int val, mask;
  13215. + int i, ret;
  13216. +
  13217. + for (i = 0; i < 4; i++) {
  13218. + val = snd_soc_component_read(component,
  13219. + WM8804_SPDTX1 + i);
  13220. + mask = (i == 3) ? 0x3f : 0xff;
  13221. + priv->iec958_status[i] = val & mask;
  13222. + }
  13223. +
  13224. + /* Setup for 256fs */
  13225. + ret = snd_soc_dai_set_clkdiv(codec_dai,
  13226. + WM8804_MCLK_DIV, WM8804_MCLKDIV_256FS);
  13227. + if (ret) {
  13228. + dev_err(card->dev,
  13229. + "init_wm8804: Failed to set MCLK_DIV to 256fs: %d\n",
  13230. + ret);
  13231. + return ret;
  13232. + }
  13233. +
  13234. + /* Output OSC on CLKOUT */
  13235. + ret = snd_soc_dai_set_sysclk(codec_dai,
  13236. + WM8804_CLKOUT_SRC_OSCCLK, WM8804_CLKOUT_HZ, 0);
  13237. + if (ret)
  13238. + dev_err(card->dev,
  13239. + "init_wm8804: Failed to set CLKOUT as OSC Frequency: %d\n",
  13240. + ret);
  13241. +
  13242. + /* Init PLL with default samplerate */
  13243. + ret = rpi_cirrus_set_wm8804_pll(card, codec_dai,
  13244. + RPI_CIRRUS_DEFAULT_RATE);
  13245. + if (ret)
  13246. + dev_err(card->dev,
  13247. + "init_wm8804: Failed to setup PLL for %dHz: %d\n",
  13248. + RPI_CIRRUS_DEFAULT_RATE, ret);
  13249. +
  13250. + return ret;
  13251. +}
  13252. +
  13253. +static struct snd_soc_ops rpi_cirrus_ops = {
  13254. + .startup = rpi_cirrus_startup,
  13255. + .hw_params = rpi_cirrus_hw_params,
  13256. + .hw_free = rpi_cirrus_hw_free,
  13257. +};
  13258. +
  13259. +SND_SOC_DAILINK_DEFS(wm5102,
  13260. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  13261. + DAILINK_COMP_ARRAY(COMP_CODEC("wm5102-codec", "wm5102-aif1")),
  13262. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  13263. +
  13264. +SND_SOC_DAILINK_DEFS(wm8804,
  13265. + DAILINK_COMP_ARRAY(COMP_CPU("wm5102-aif2")),
  13266. + DAILINK_COMP_ARRAY(COMP_CODEC("wm8804.1-003b", "wm8804-spdif")));
  13267. +
  13268. +static struct snd_soc_dai_link rpi_cirrus_dai[] = {
  13269. + [DAI_WM5102] = {
  13270. + .name = "WM5102",
  13271. + .stream_name = "WM5102 AiFi",
  13272. + .dai_fmt = SND_SOC_DAIFMT_I2S
  13273. + | SND_SOC_DAIFMT_NB_NF
  13274. + | SND_SOC_DAIFMT_CBM_CFM,
  13275. + .ops = &rpi_cirrus_ops,
  13276. + .init = rpi_cirrus_init_wm5102,
  13277. + SND_SOC_DAILINK_REG(wm5102),
  13278. + },
  13279. + [DAI_WM8804] = {
  13280. + .name = "WM5102 SPDIF",
  13281. + .stream_name = "SPDIF Tx/Rx",
  13282. + .dai_fmt = SND_SOC_DAIFMT_I2S
  13283. + | SND_SOC_DAIFMT_NB_NF
  13284. + | SND_SOC_DAIFMT_CBM_CFM,
  13285. + .ignore_suspend = 1,
  13286. + .c2c_params = &rpi_cirrus_dai_link2_params,
  13287. + .init = rpi_cirrus_init_wm8804,
  13288. + SND_SOC_DAILINK_REG(wm8804),
  13289. + },
  13290. +};
  13291. +
  13292. +
  13293. +static int rpi_cirrus_late_probe(struct snd_soc_card *card)
  13294. +{
  13295. + struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card);
  13296. + struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card);
  13297. + struct snd_soc_pcm_runtime *wm8804_runtime = get_wm8804_runtime(card);
  13298. + int ret;
  13299. +
  13300. + dev_dbg(card->dev, "iec958_bits: %02x %02x %02x %02x\n",
  13301. + priv->iec958_status[0],
  13302. + priv->iec958_status[1],
  13303. + priv->iec958_status[2],
  13304. + priv->iec958_status[3]);
  13305. +
  13306. + ret = snd_soc_dai_set_sysclk(
  13307. + asoc_rtd_to_codec(wm5102_runtime, 0), ARIZONA_CLK_SYSCLK, 0, 0);
  13308. + if (ret) {
  13309. + dev_err(card->dev,
  13310. + "Failed to set WM5102 codec dai clk domain: %d\n", ret);
  13311. + return ret;
  13312. + }
  13313. +
  13314. + ret = snd_soc_dai_set_sysclk(
  13315. + asoc_rtd_to_cpu(wm8804_runtime, 0), ARIZONA_CLK_SYSCLK, 0, 0);
  13316. + if (ret)
  13317. + dev_err(card->dev,
  13318. + "Failed to set WM8804 codec dai clk domain: %d\n", ret);
  13319. +
  13320. + return ret;
  13321. +}
  13322. +
  13323. +/* audio machine driver */
  13324. +static struct snd_soc_card rpi_cirrus_card = {
  13325. + .name = "RPi-Cirrus",
  13326. + .driver_name = "RPiCirrus",
  13327. + .owner = THIS_MODULE,
  13328. + .dai_link = rpi_cirrus_dai,
  13329. + .num_links = ARRAY_SIZE(rpi_cirrus_dai),
  13330. + .late_probe = rpi_cirrus_late_probe,
  13331. + .controls = rpi_cirrus_controls,
  13332. + .num_controls = ARRAY_SIZE(rpi_cirrus_controls),
  13333. + .dapm_widgets = rpi_cirrus_dapm_widgets,
  13334. + .num_dapm_widgets = ARRAY_SIZE(rpi_cirrus_dapm_widgets),
  13335. + .dapm_routes = rpi_cirrus_dapm_routes,
  13336. + .num_dapm_routes = ARRAY_SIZE(rpi_cirrus_dapm_routes),
  13337. + .set_bias_level = rpi_cirrus_set_bias_level,
  13338. + .set_bias_level_post = rpi_cirrus_set_bias_level_post,
  13339. +};
  13340. +
  13341. +static int rpi_cirrus_probe(struct platform_device *pdev)
  13342. +{
  13343. + int ret = 0;
  13344. + struct rpi_cirrus_priv *priv;
  13345. + struct device_node *i2s_node;
  13346. +
  13347. + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  13348. + if (!priv)
  13349. + return -ENOMEM;
  13350. +
  13351. + priv->min_rate_idx = 1; /* min samplerate 32kHz */
  13352. + priv->card_rate = RPI_CIRRUS_DEFAULT_RATE;
  13353. +
  13354. + mutex_init(&priv->lock);
  13355. +
  13356. + snd_soc_card_set_drvdata(&rpi_cirrus_card, priv);
  13357. +
  13358. + if (!pdev->dev.of_node)
  13359. + return -ENODEV;
  13360. +
  13361. + i2s_node = of_parse_phandle(
  13362. + pdev->dev.of_node, "i2s-controller", 0);
  13363. + if (!i2s_node) {
  13364. + dev_err(&pdev->dev, "i2s-controller missing in DT\n");
  13365. + return -ENODEV;
  13366. + }
  13367. +
  13368. + rpi_cirrus_dai[DAI_WM5102].cpus->of_node = i2s_node;
  13369. + rpi_cirrus_dai[DAI_WM5102].platforms->of_node = i2s_node;
  13370. +
  13371. + rpi_cirrus_card.dev = &pdev->dev;
  13372. +
  13373. + ret = devm_snd_soc_register_card(&pdev->dev, &rpi_cirrus_card);
  13374. + if (ret) {
  13375. + if (ret == -EPROBE_DEFER)
  13376. + dev_dbg(&pdev->dev,
  13377. + "register card requested probe deferral\n");
  13378. + else
  13379. + dev_err(&pdev->dev,
  13380. + "Failed to register card: %d\n", ret);
  13381. + }
  13382. +
  13383. + return ret;
  13384. +}
  13385. +
  13386. +static const struct of_device_id rpi_cirrus_of_match[] = {
  13387. + { .compatible = "wlf,rpi-cirrus", },
  13388. + {},
  13389. +};
  13390. +MODULE_DEVICE_TABLE(of, rpi_cirrus_of_match);
  13391. +
  13392. +static struct platform_driver rpi_cirrus_driver = {
  13393. + .driver = {
  13394. + .name = "snd-rpi-cirrus",
  13395. + .of_match_table = of_match_ptr(rpi_cirrus_of_match),
  13396. + },
  13397. + .probe = rpi_cirrus_probe,
  13398. +};
  13399. +
  13400. +module_platform_driver(rpi_cirrus_driver);
  13401. +
  13402. +MODULE_AUTHOR("Matthias Reichl <[email protected]>");
  13403. +MODULE_DESCRIPTION("ASoC driver for Cirrus Logic Audio Card");
  13404. +MODULE_LICENSE("GPL");
  13405. --- /dev/null
  13406. +++ b/sound/soc/bcm/rpi-proto.c
  13407. @@ -0,0 +1,147 @@
  13408. +/*
  13409. + * ASoC driver for PROTO AudioCODEC (with a WM8731)
  13410. + * connected to a Raspberry Pi
  13411. + *
  13412. + * Author: Florian Meier, <[email protected]>
  13413. + * Copyright 2013
  13414. + *
  13415. + * This program is free software; you can redistribute it and/or modify
  13416. + * it under the terms of the GNU General Public License version 2 as
  13417. + * published by the Free Software Foundation.
  13418. + */
  13419. +
  13420. +#include <linux/module.h>
  13421. +#include <linux/platform_device.h>
  13422. +
  13423. +#include <sound/core.h>
  13424. +#include <sound/pcm.h>
  13425. +#include <sound/soc.h>
  13426. +#include <sound/jack.h>
  13427. +
  13428. +#include "../codecs/wm8731.h"
  13429. +
  13430. +static const unsigned int wm8731_rates_12288000[] = {
  13431. + 8000, 32000, 48000, 96000,
  13432. +};
  13433. +
  13434. +static struct snd_pcm_hw_constraint_list wm8731_constraints_12288000 = {
  13435. + .list = wm8731_rates_12288000,
  13436. + .count = ARRAY_SIZE(wm8731_rates_12288000),
  13437. +};
  13438. +
  13439. +static int snd_rpi_proto_startup(struct snd_pcm_substream *substream)
  13440. +{
  13441. + /* Setup constraints, because there is a 12.288 MHz XTAL on the board */
  13442. + snd_pcm_hw_constraint_list(substream->runtime, 0,
  13443. + SNDRV_PCM_HW_PARAM_RATE,
  13444. + &wm8731_constraints_12288000);
  13445. + return 0;
  13446. +}
  13447. +
  13448. +static int snd_rpi_proto_hw_params(struct snd_pcm_substream *substream,
  13449. + struct snd_pcm_hw_params *params)
  13450. +{
  13451. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  13452. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  13453. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  13454. + int sysclk = 12288000; /* This is fixed on this board */
  13455. +
  13456. + /* Set proto bclk */
  13457. + int ret = snd_soc_dai_set_bclk_ratio(cpu_dai,32*2);
  13458. + if (ret < 0){
  13459. + dev_err(rtd->card->dev,
  13460. + "Failed to set BCLK ratio %d\n", ret);
  13461. + return ret;
  13462. + }
  13463. +
  13464. + /* Set proto sysclk */
  13465. + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
  13466. + sysclk, SND_SOC_CLOCK_IN);
  13467. + if (ret < 0) {
  13468. + dev_err(rtd->card->dev,
  13469. + "Failed to set WM8731 SYSCLK: %d\n", ret);
  13470. + return ret;
  13471. + }
  13472. +
  13473. + return 0;
  13474. +}
  13475. +
  13476. +/* machine stream operations */
  13477. +static struct snd_soc_ops snd_rpi_proto_ops = {
  13478. + .startup = snd_rpi_proto_startup,
  13479. + .hw_params = snd_rpi_proto_hw_params,
  13480. +};
  13481. +
  13482. +SND_SOC_DAILINK_DEFS(rpi_proto,
  13483. + DAILINK_COMP_ARRAY(COMP_CPU("bcm2708-i2s.0")),
  13484. + DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.1-001a", "wm8731-hifi")),
  13485. + DAILINK_COMP_ARRAY(COMP_PLATFORM("bcm2708-i2s.0")));
  13486. +
  13487. +static struct snd_soc_dai_link snd_rpi_proto_dai[] = {
  13488. +{
  13489. + .name = "WM8731",
  13490. + .stream_name = "WM8731 HiFi",
  13491. + .dai_fmt = SND_SOC_DAIFMT_I2S
  13492. + | SND_SOC_DAIFMT_NB_NF
  13493. + | SND_SOC_DAIFMT_CBM_CFM,
  13494. + .ops = &snd_rpi_proto_ops,
  13495. + SND_SOC_DAILINK_REG(rpi_proto),
  13496. +},
  13497. +};
  13498. +
  13499. +/* audio machine driver */
  13500. +static struct snd_soc_card snd_rpi_proto = {
  13501. + .name = "snd_rpi_proto",
  13502. + .owner = THIS_MODULE,
  13503. + .dai_link = snd_rpi_proto_dai,
  13504. + .num_links = ARRAY_SIZE(snd_rpi_proto_dai),
  13505. +};
  13506. +
  13507. +static int snd_rpi_proto_probe(struct platform_device *pdev)
  13508. +{
  13509. + int ret = 0;
  13510. +
  13511. + snd_rpi_proto.dev = &pdev->dev;
  13512. +
  13513. + if (pdev->dev.of_node) {
  13514. + struct device_node *i2s_node;
  13515. + struct snd_soc_dai_link *dai = &snd_rpi_proto_dai[0];
  13516. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  13517. + "i2s-controller", 0);
  13518. +
  13519. + if (i2s_node) {
  13520. + dai->cpus->dai_name = NULL;
  13521. + dai->cpus->of_node = i2s_node;
  13522. + dai->platforms->name = NULL;
  13523. + dai->platforms->of_node = i2s_node;
  13524. + }
  13525. + }
  13526. +
  13527. + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_proto);
  13528. + if (ret && ret != -EPROBE_DEFER)
  13529. + dev_err(&pdev->dev,
  13530. + "snd_soc_register_card() failed: %d\n", ret);
  13531. +
  13532. + return ret;
  13533. +}
  13534. +
  13535. +static const struct of_device_id snd_rpi_proto_of_match[] = {
  13536. + { .compatible = "rpi,rpi-proto", },
  13537. + {},
  13538. +};
  13539. +MODULE_DEVICE_TABLE(of, snd_rpi_proto_of_match);
  13540. +
  13541. +static struct platform_driver snd_rpi_proto_driver = {
  13542. + .driver = {
  13543. + .name = "snd-rpi-proto",
  13544. + .owner = THIS_MODULE,
  13545. + .of_match_table = snd_rpi_proto_of_match,
  13546. + },
  13547. + .probe = snd_rpi_proto_probe,
  13548. +};
  13549. +
  13550. +module_platform_driver(snd_rpi_proto_driver);
  13551. +
  13552. +MODULE_AUTHOR("Florian Meier");
  13553. +MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)");
  13554. +MODULE_LICENSE("GPL");
  13555. --- /dev/null
  13556. +++ b/sound/soc/bcm/rpi-simple-soundcard.c
  13557. @@ -0,0 +1,487 @@
  13558. +// SPDX-License-Identifier: GPL-2.0
  13559. +/*
  13560. + * rpi-simple-soundcard.c -- ALSA SoC Raspberry Pi soundcard.
  13561. + *
  13562. + * Copyright (C) 2018 Raspberry Pi.
  13563. + *
  13564. + * Authors: Tim Gover <[email protected]>
  13565. + *
  13566. + * Based on code:
  13567. + * hifiberry_amp.c, hifiberry_dac.c, rpi-dac.c
  13568. + * by Florian Meier <[email protected]>
  13569. + *
  13570. + * googlevoicehat-soundcard.c
  13571. + * by Peter Malkin <[email protected]>
  13572. + *
  13573. + * adau1977-adc.c
  13574. + * by Andrey Grodzovsky <[email protected]>
  13575. + *
  13576. + * merus-amp.c
  13577. + * by Ariel Muszkat <[email protected]>
  13578. + * Jorgen Kragh Jakobsen <[email protected]>
  13579. + *
  13580. + * This program is free software; you can redistribute it and/or
  13581. + * modify it under the terms of the GNU General Public License
  13582. + * version 2 as published by the Free Software Foundation.
  13583. + *
  13584. + * This program is distributed in the hope that it will be useful, but
  13585. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  13586. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13587. + * General Public License for more details.
  13588. + */
  13589. +
  13590. +#include <linux/module.h>
  13591. +#include <linux/platform_device.h>
  13592. +#include <linux/gpio/consumer.h>
  13593. +
  13594. +#include <sound/core.h>
  13595. +#include <sound/pcm.h>
  13596. +#include <sound/pcm_params.h>
  13597. +#include <sound/soc.h>
  13598. +
  13599. +/* Parameters for generic RPI functions */
  13600. +struct snd_rpi_simple_drvdata {
  13601. + struct snd_soc_dai_link *dai;
  13602. + const char* card_name;
  13603. + unsigned int fixed_bclk_ratio;
  13604. +};
  13605. +
  13606. +static struct snd_soc_card snd_rpi_simple = {
  13607. + .driver_name = "RPi-simple",
  13608. + .owner = THIS_MODULE,
  13609. + .dai_link = NULL,
  13610. + .num_links = 1, /* Only a single DAI supported at the moment */
  13611. +};
  13612. +
  13613. +static int snd_rpi_simple_init(struct snd_soc_pcm_runtime *rtd)
  13614. +{
  13615. + struct snd_rpi_simple_drvdata *drvdata =
  13616. + snd_soc_card_get_drvdata(rtd->card);
  13617. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  13618. +
  13619. + if (drvdata->fixed_bclk_ratio > 0)
  13620. + return snd_soc_dai_set_bclk_ratio(cpu_dai,
  13621. + drvdata->fixed_bclk_ratio);
  13622. +
  13623. + return 0;
  13624. +}
  13625. +
  13626. +static int pifi_mini_210_init(struct snd_soc_pcm_runtime *rtd)
  13627. +{
  13628. + struct snd_soc_component *dac;
  13629. + struct gpio_desc *pdn_gpio, *rst_gpio;
  13630. + struct snd_soc_dai *codec_dai;
  13631. + int ret;
  13632. +
  13633. + snd_rpi_simple_init(rtd);
  13634. + codec_dai = asoc_rtd_to_codec(rtd, 0);
  13635. +
  13636. + dac = codec_dai[0].component;
  13637. +
  13638. + pdn_gpio = devm_gpiod_get_optional(snd_rpi_simple.dev, "pdn",
  13639. + GPIOD_OUT_LOW);
  13640. + if (IS_ERR(pdn_gpio)) {
  13641. + ret = PTR_ERR(pdn_gpio);
  13642. + dev_err(snd_rpi_simple.dev, "failed to get pdn gpio: %d\n", ret);
  13643. + return ret;
  13644. + }
  13645. +
  13646. + rst_gpio = devm_gpiod_get_optional(snd_rpi_simple.dev, "rst",
  13647. + GPIOD_OUT_LOW);
  13648. + if (IS_ERR(rst_gpio)) {
  13649. + ret = PTR_ERR(rst_gpio);
  13650. + dev_err(snd_rpi_simple.dev, "failed to get rst gpio: %d\n", ret);
  13651. + return ret;
  13652. + }
  13653. +
  13654. + // Set up cards - pulse power down and reset first, then
  13655. + // set up according to datasheet
  13656. + gpiod_set_value_cansleep(pdn_gpio, 1);
  13657. + gpiod_set_value_cansleep(rst_gpio, 1);
  13658. + usleep_range(1000, 10000);
  13659. + gpiod_set_value_cansleep(pdn_gpio, 0);
  13660. + usleep_range(20000, 30000);
  13661. + gpiod_set_value_cansleep(rst_gpio, 0);
  13662. + usleep_range(20000, 30000);
  13663. +
  13664. + // Oscillator trim
  13665. + snd_soc_component_write(dac, 0x1b, 0);
  13666. + usleep_range(60000, 80000);
  13667. +
  13668. + // MCLK at 64fs, sample rate 44.1 or 48kHz
  13669. + snd_soc_component_write(dac, 0x00, 0x60);
  13670. +
  13671. + // Set up for BTL - AD/BD mode - AD is 0x00107772, BD is 0x00987772
  13672. + snd_soc_component_write(dac, 0x20, 0x00107772);
  13673. +
  13674. + // End mute
  13675. + snd_soc_component_write(dac, 0x05, 0x00);
  13676. +
  13677. + return 0;
  13678. +}
  13679. +
  13680. +static int snd_rpi_simple_hw_params(struct snd_pcm_substream *substream,
  13681. + struct snd_pcm_hw_params *params)
  13682. +{
  13683. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  13684. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  13685. + struct snd_rpi_simple_drvdata *drvdata;
  13686. + unsigned int sample_bits;
  13687. +
  13688. + drvdata = snd_soc_card_get_drvdata(rtd->card);
  13689. +
  13690. + if (drvdata->fixed_bclk_ratio > 0)
  13691. + return 0; // BCLK is configured in .init
  13692. +
  13693. + /* The simple drivers just set the bclk_ratio to sample_bits * 2 so
  13694. + * hard-code this for now. More complex drivers could just replace
  13695. + * the hw_params routine.
  13696. + */
  13697. + sample_bits = snd_pcm_format_physical_width(params_format(params));
  13698. + return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2);
  13699. +}
  13700. +
  13701. +static struct snd_soc_ops snd_rpi_simple_ops = {
  13702. + .hw_params = snd_rpi_simple_hw_params,
  13703. +};
  13704. +
  13705. +static int snd_merus_amp_hw_params(struct snd_pcm_substream *substream,
  13706. + struct snd_pcm_hw_params *params)
  13707. +{
  13708. + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  13709. + int rate;
  13710. +
  13711. + rate = params_rate(params);
  13712. + if (rate > 48000) {
  13713. + dev_err(rtd->card->dev,
  13714. + "Unsupported samplerate %d\n",
  13715. + rate);
  13716. + return -EINVAL;
  13717. + }
  13718. + return 0;
  13719. +}
  13720. +
  13721. +static struct snd_soc_ops snd_merus_amp_ops = {
  13722. + .hw_params = snd_merus_amp_hw_params,
  13723. +};
  13724. +
  13725. +enum adau1977_clk_id {
  13726. + ADAU1977_SYSCLK,
  13727. +};
  13728. +
  13729. +enum adau1977_sysclk_src {
  13730. + ADAU1977_SYSCLK_SRC_MCLK,
  13731. + ADAU1977_SYSCLK_SRC_LRCLK,
  13732. +};
  13733. +
  13734. +static int adau1977_init(struct snd_soc_pcm_runtime *rtd)
  13735. +{
  13736. + int ret;
  13737. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  13738. +
  13739. + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0, 0, 0, 0);
  13740. + if (ret < 0)
  13741. + return ret;
  13742. +
  13743. + return snd_soc_component_set_sysclk(codec_dai->component,
  13744. + ADAU1977_SYSCLK, ADAU1977_SYSCLK_SRC_MCLK,
  13745. + 11289600, SND_SOC_CLOCK_IN);
  13746. +}
  13747. +
  13748. +SND_SOC_DAILINK_DEFS(adau1977,
  13749. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  13750. + DAILINK_COMP_ARRAY(COMP_CODEC("adau1977.1-0011", "adau1977-hifi")),
  13751. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  13752. +
  13753. +static struct snd_soc_dai_link snd_rpi_adau1977_dai[] = {
  13754. + {
  13755. + .name = "adau1977",
  13756. + .stream_name = "ADAU1977",
  13757. + .init = adau1977_init,
  13758. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  13759. + SND_SOC_DAIFMT_NB_NF |
  13760. + SND_SOC_DAIFMT_CBM_CFM,
  13761. + SND_SOC_DAILINK_REG(adau1977),
  13762. + },
  13763. +};
  13764. +
  13765. +static struct snd_rpi_simple_drvdata drvdata_adau1977 = {
  13766. + .card_name = "snd_rpi_adau1977_adc",
  13767. + .dai = snd_rpi_adau1977_dai,
  13768. +};
  13769. +
  13770. +SND_SOC_DAILINK_DEFS(gvchat,
  13771. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  13772. + DAILINK_COMP_ARRAY(COMP_CODEC("voicehat-codec", "voicehat-hifi")),
  13773. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  13774. +
  13775. +static struct snd_soc_dai_link snd_googlevoicehat_soundcard_dai[] = {
  13776. +{
  13777. + .name = "Google voiceHAT SoundCard",
  13778. + .stream_name = "Google voiceHAT SoundCard HiFi",
  13779. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  13780. + SND_SOC_DAIFMT_CBS_CFS,
  13781. + SND_SOC_DAILINK_REG(gvchat),
  13782. +},
  13783. +};
  13784. +
  13785. +static struct snd_rpi_simple_drvdata drvdata_googlevoicehat = {
  13786. + .card_name = "snd_rpi_googlevoicehat_soundcard",
  13787. + .dai = snd_googlevoicehat_soundcard_dai,
  13788. +};
  13789. +
  13790. +SND_SOC_DAILINK_DEFS(hifiberry_dacplusdsp,
  13791. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  13792. + DAILINK_COMP_ARRAY(COMP_CODEC("dacplusdsp-codec", "dacplusdsp-hifi")),
  13793. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  13794. +
  13795. +static struct snd_soc_dai_link snd_hifiberrydacplusdsp_soundcard_dai[] = {
  13796. +{
  13797. + .name = "Hifiberry DAC+DSP SoundCard",
  13798. + .stream_name = "Hifiberry DAC+DSP SoundCard HiFi",
  13799. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  13800. + SND_SOC_DAIFMT_NB_NF |
  13801. + SND_SOC_DAIFMT_CBS_CFS,
  13802. + SND_SOC_DAILINK_REG(hifiberry_dacplusdsp),
  13803. +},
  13804. +};
  13805. +
  13806. +static struct snd_rpi_simple_drvdata drvdata_hifiberrydacplusdsp = {
  13807. + .card_name = "snd_rpi_hifiberrydacplusdsp_soundcard",
  13808. + .dai = snd_hifiberrydacplusdsp_soundcard_dai,
  13809. +};
  13810. +
  13811. +SND_SOC_DAILINK_DEFS(hifiberry_amp,
  13812. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  13813. + DAILINK_COMP_ARRAY(COMP_CODEC("tas5713.1-001b", "tas5713-hifi")),
  13814. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  13815. +
  13816. +static struct snd_soc_dai_link snd_hifiberry_amp_dai[] = {
  13817. + {
  13818. + .name = "HifiBerry AMP",
  13819. + .stream_name = "HifiBerry AMP HiFi",
  13820. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  13821. + SND_SOC_DAIFMT_NB_NF |
  13822. + SND_SOC_DAIFMT_CBS_CFS,
  13823. + SND_SOC_DAILINK_REG(hifiberry_amp),
  13824. + },
  13825. +};
  13826. +
  13827. +static struct snd_rpi_simple_drvdata drvdata_hifiberry_amp = {
  13828. + .card_name = "snd_rpi_hifiberry_amp",
  13829. + .dai = snd_hifiberry_amp_dai,
  13830. + .fixed_bclk_ratio = 64,
  13831. +};
  13832. +
  13833. +SND_SOC_DAILINK_DEFS(hifiberry_amp3,
  13834. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  13835. + DAILINK_COMP_ARRAY(COMP_CODEC("ma120x0p.1-0020", "ma120x0p-amp")),
  13836. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  13837. +
  13838. +static struct snd_soc_dai_link snd_hifiberry_amp3_dai[] = {
  13839. + {
  13840. + .name = "HifiberryAmp3",
  13841. + .stream_name = "Hifiberry Amp3",
  13842. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  13843. + SND_SOC_DAIFMT_NB_NF |
  13844. + SND_SOC_DAIFMT_CBS_CFS,
  13845. + SND_SOC_DAILINK_REG(hifiberry_amp3),
  13846. + },
  13847. +};
  13848. +
  13849. +static struct snd_rpi_simple_drvdata drvdata_hifiberry_amp3 = {
  13850. + .card_name = "snd_rpi_hifiberry_amp3",
  13851. + .dai = snd_hifiberry_amp3_dai,
  13852. + .fixed_bclk_ratio = 64,
  13853. +};
  13854. +
  13855. +SND_SOC_DAILINK_DEFS(hifiberry_dac,
  13856. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  13857. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm5102a-codec", "pcm5102a-hifi")),
  13858. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  13859. +
  13860. +static struct snd_soc_dai_link snd_hifiberry_dac_dai[] = {
  13861. + {
  13862. + .name = "HifiBerry DAC",
  13863. + .stream_name = "HifiBerry DAC HiFi",
  13864. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  13865. + SND_SOC_DAIFMT_NB_NF |
  13866. + SND_SOC_DAIFMT_CBS_CFS,
  13867. + SND_SOC_DAILINK_REG(hifiberry_dac),
  13868. + },
  13869. +};
  13870. +
  13871. +static struct snd_rpi_simple_drvdata drvdata_hifiberry_dac = {
  13872. + .card_name = "snd_rpi_hifiberry_dac",
  13873. + .dai = snd_hifiberry_dac_dai,
  13874. +};
  13875. +
  13876. +SND_SOC_DAILINK_DEFS(dionaudio_kiwi,
  13877. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  13878. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm1794a-codec", "pcm1794a-hifi")),
  13879. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  13880. +
  13881. +static struct snd_soc_dai_link snd_dionaudio_kiwi_dai[] = {
  13882. +{
  13883. + .name = "DionAudio KIWI",
  13884. + .stream_name = "DionAudio KIWI STREAMER",
  13885. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  13886. + SND_SOC_DAIFMT_CBS_CFS,
  13887. + SND_SOC_DAILINK_REG(dionaudio_kiwi),
  13888. +},
  13889. +};
  13890. +
  13891. +static struct snd_rpi_simple_drvdata drvdata_dionaudio_kiwi = {
  13892. + .card_name = "snd_rpi_dionaudio_kiwi",
  13893. + .dai = snd_dionaudio_kiwi_dai,
  13894. + .fixed_bclk_ratio = 64,
  13895. +};
  13896. +
  13897. +SND_SOC_DAILINK_DEFS(rpi_dac,
  13898. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  13899. + DAILINK_COMP_ARRAY(COMP_CODEC("pcm1794a-codec", "pcm1794a-hifi")),
  13900. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  13901. +
  13902. +static struct snd_soc_dai_link snd_rpi_dac_dai[] = {
  13903. +{
  13904. + .name = "RPi-DAC",
  13905. + .stream_name = "RPi-DAC HiFi",
  13906. + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
  13907. + SND_SOC_DAIFMT_CBS_CFS,
  13908. + SND_SOC_DAILINK_REG(rpi_dac),
  13909. +},
  13910. +};
  13911. +
  13912. +static struct snd_rpi_simple_drvdata drvdata_rpi_dac = {
  13913. + .card_name = "snd_rpi_rpi_dac",
  13914. + .dai = snd_rpi_dac_dai,
  13915. + .fixed_bclk_ratio = 64,
  13916. +};
  13917. +
  13918. +SND_SOC_DAILINK_DEFS(merus_amp,
  13919. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  13920. + DAILINK_COMP_ARRAY(COMP_CODEC("ma120x0p.1-0020", "ma120x0p-amp")),
  13921. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  13922. +
  13923. +static struct snd_soc_dai_link snd_merus_amp_dai[] = {
  13924. + {
  13925. + .name = "MerusAmp",
  13926. + .stream_name = "Merus Audio Amp",
  13927. + .ops = &snd_merus_amp_ops,
  13928. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  13929. + SND_SOC_DAIFMT_NB_NF |
  13930. + SND_SOC_DAIFMT_CBS_CFS,
  13931. + SND_SOC_DAILINK_REG(merus_amp),
  13932. + },
  13933. +};
  13934. +
  13935. +static struct snd_rpi_simple_drvdata drvdata_merus_amp = {
  13936. + .card_name = "snd_rpi_merus_amp",
  13937. + .dai = snd_merus_amp_dai,
  13938. + .fixed_bclk_ratio = 64,
  13939. +};
  13940. +
  13941. +SND_SOC_DAILINK_DEFS(pifi_mini_210,
  13942. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  13943. + DAILINK_COMP_ARRAY(COMP_CODEC("tas571x.1-001a", "tas571x-hifi")),
  13944. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  13945. +
  13946. +static struct snd_soc_dai_link snd_pifi_mini_210_dai[] = {
  13947. + {
  13948. + .name = "PiFi Mini 210",
  13949. + .stream_name = "PiFi Mini 210 HiFi",
  13950. + .init = pifi_mini_210_init,
  13951. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  13952. + SND_SOC_DAIFMT_NB_NF |
  13953. + SND_SOC_DAIFMT_CBS_CFS,
  13954. + SND_SOC_DAILINK_REG(pifi_mini_210),
  13955. + },
  13956. +};
  13957. +
  13958. +static struct snd_rpi_simple_drvdata drvdata_pifi_mini_210 = {
  13959. + .card_name = "snd_pifi_mini_210",
  13960. + .dai = snd_pifi_mini_210_dai,
  13961. + .fixed_bclk_ratio = 64,
  13962. +};
  13963. +
  13964. +static const struct of_device_id snd_rpi_simple_of_match[] = {
  13965. + { .compatible = "adi,adau1977-adc",
  13966. + .data = (void *) &drvdata_adau1977 },
  13967. + { .compatible = "googlevoicehat,googlevoicehat-soundcard",
  13968. + .data = (void *) &drvdata_googlevoicehat },
  13969. + { .compatible = "hifiberrydacplusdsp,hifiberrydacplusdsp-soundcard",
  13970. + .data = (void *) &drvdata_hifiberrydacplusdsp },
  13971. + { .compatible = "hifiberry,hifiberry-amp",
  13972. + .data = (void *) &drvdata_hifiberry_amp },
  13973. + { .compatible = "hifiberry,hifiberry-amp3",
  13974. + .data = (void *) &drvdata_hifiberry_amp3 },
  13975. + { .compatible = "hifiberry,hifiberry-dac",
  13976. + .data = (void *) &drvdata_hifiberry_dac },
  13977. + { .compatible = "dionaudio,dionaudio-kiwi",
  13978. + .data = (void *) &drvdata_dionaudio_kiwi },
  13979. + { .compatible = "rpi,rpi-dac", &drvdata_rpi_dac},
  13980. + { .compatible = "merus,merus-amp",
  13981. + .data = (void *) &drvdata_merus_amp },
  13982. + { .compatible = "pifi,pifi-mini-210",
  13983. + .data = (void *) &drvdata_pifi_mini_210 },
  13984. + {},
  13985. +};
  13986. +
  13987. +static int snd_rpi_simple_probe(struct platform_device *pdev)
  13988. +{
  13989. + int ret = 0;
  13990. + const struct of_device_id *of_id;
  13991. +
  13992. + snd_rpi_simple.dev = &pdev->dev;
  13993. + of_id = of_match_node(snd_rpi_simple_of_match, pdev->dev.of_node);
  13994. +
  13995. + if (pdev->dev.of_node && of_id->data) {
  13996. + struct device_node *i2s_node;
  13997. + struct snd_rpi_simple_drvdata *drvdata =
  13998. + (struct snd_rpi_simple_drvdata *) of_id->data;
  13999. + struct snd_soc_dai_link *dai = drvdata->dai;
  14000. +
  14001. + snd_soc_card_set_drvdata(&snd_rpi_simple, drvdata);
  14002. +
  14003. + /* More complex drivers might override individual functions */
  14004. + if (!dai->init)
  14005. + dai->init = snd_rpi_simple_init;
  14006. + if (!dai->ops)
  14007. + dai->ops = &snd_rpi_simple_ops;
  14008. +
  14009. + snd_rpi_simple.name = drvdata->card_name;
  14010. +
  14011. + snd_rpi_simple.dai_link = dai;
  14012. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  14013. + "i2s-controller", 0);
  14014. + if (!i2s_node) {
  14015. + pr_err("Failed to find i2s-controller DT node\n");
  14016. + return -ENODEV;
  14017. + }
  14018. +
  14019. + dai->cpus->of_node = i2s_node;
  14020. + dai->platforms->of_node = i2s_node;
  14021. + }
  14022. +
  14023. + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_simple);
  14024. + if (ret && ret != -EPROBE_DEFER)
  14025. + dev_err(&pdev->dev, "Failed to register card %d\n", ret);
  14026. +
  14027. + return ret;
  14028. +}
  14029. +
  14030. +static struct platform_driver snd_rpi_simple_driver = {
  14031. + .driver = {
  14032. + .name = "snd-rpi-simple",
  14033. + .owner = THIS_MODULE,
  14034. + .of_match_table = snd_rpi_simple_of_match,
  14035. + },
  14036. + .probe = snd_rpi_simple_probe,
  14037. +};
  14038. +MODULE_DEVICE_TABLE(of, snd_rpi_simple_of_match);
  14039. +
  14040. +module_platform_driver(snd_rpi_simple_driver);
  14041. +
  14042. +MODULE_AUTHOR("Tim Gover <[email protected]>");
  14043. +MODULE_DESCRIPTION("ASoC Raspberry Pi simple soundcard driver ");
  14044. +MODULE_LICENSE("GPL v2");
  14045. --- /dev/null
  14046. +++ b/sound/soc/bcm/rpi-wm8804-soundcard.c
  14047. @@ -0,0 +1,410 @@
  14048. +// SPDX-License-Identifier: GPL-2.0
  14049. +/*
  14050. + * rpi--wm8804.c -- ALSA SoC Raspberry Pi soundcard.
  14051. + *
  14052. + * Copyright (C) 2018 Raspberry Pi.
  14053. + *
  14054. + * Authors: Tim Gover <[email protected]>
  14055. + *
  14056. + * Generic driver for Pi Hat WM8804 digi sounds cards
  14057. + *
  14058. + * Based upon code from:
  14059. + * justboom-digi.c
  14060. + * by Milan Neskovic <[email protected]>
  14061. + *
  14062. + * iqaudio_digi.c
  14063. + * by Daniel Matuschek <[email protected]>
  14064. + *
  14065. + * allo-digione.c
  14066. + * by Baswaraj <[email protected]>
  14067. + *
  14068. + * hifiberry-digi.c
  14069. + * Daniel Matuschek <[email protected]>
  14070. + *
  14071. + * This program is free software; you can redistribute it and/or
  14072. + * modify it under the terms of the GNU General Public License
  14073. + * version 2 as published by the Free Software Foundation.
  14074. + *
  14075. + * This program is distributed in the hope that it will be useful, but
  14076. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  14077. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14078. + * General Public License for more details.
  14079. + */
  14080. +
  14081. +#include <linux/gpio/consumer.h>
  14082. +#include <linux/platform_device.h>
  14083. +#include <linux/module.h>
  14084. +
  14085. +#include <sound/core.h>
  14086. +#include <sound/pcm.h>
  14087. +#include <sound/pcm_params.h>
  14088. +#include <sound/soc.h>
  14089. +
  14090. +#include "../codecs/wm8804.h"
  14091. +
  14092. +struct wm8804_clk_cfg {
  14093. + unsigned int sysclk_freq;
  14094. + unsigned int mclk_freq;
  14095. + unsigned int mclk_div;
  14096. +};
  14097. +
  14098. +/* Parameters for generic functions */
  14099. +struct snd_rpi_wm8804_drvdata {
  14100. + /* Required - pointer to the DAI structure */
  14101. + struct snd_soc_dai_link *dai;
  14102. + /* Required - snd_soc_card name */
  14103. + const char *card_name;
  14104. + /* Optional DT node names if card info is defined in DT */
  14105. + const char *card_name_dt;
  14106. + const char *dai_name_dt;
  14107. + const char *dai_stream_name_dt;
  14108. + /* Optional probe extension - called prior to register_card */
  14109. + int (*probe)(struct platform_device *pdev);
  14110. +};
  14111. +
  14112. +static struct gpio_desc *snd_clk44gpio;
  14113. +static struct gpio_desc *snd_clk48gpio;
  14114. +static int wm8804_samplerate = 0;
  14115. +
  14116. +/* Forward declarations */
  14117. +static struct snd_soc_dai_link snd_allo_digione_dai[];
  14118. +static struct snd_soc_card snd_rpi_wm8804;
  14119. +
  14120. +
  14121. +#define CLK_44EN_RATE 22579200UL
  14122. +#define CLK_48EN_RATE 24576000UL
  14123. +
  14124. +static unsigned int snd_rpi_wm8804_enable_clock(unsigned int samplerate)
  14125. +{
  14126. + switch (samplerate) {
  14127. + case 11025:
  14128. + case 22050:
  14129. + case 44100:
  14130. + case 88200:
  14131. + case 176400:
  14132. + gpiod_set_value_cansleep(snd_clk44gpio, 1);
  14133. + gpiod_set_value_cansleep(snd_clk48gpio, 0);
  14134. + return CLK_44EN_RATE;
  14135. + default:
  14136. + gpiod_set_value_cansleep(snd_clk48gpio, 1);
  14137. + gpiod_set_value_cansleep(snd_clk44gpio, 0);
  14138. + return CLK_48EN_RATE;
  14139. + }
  14140. +}
  14141. +
  14142. +static void snd_rpi_wm8804_clk_cfg(unsigned int samplerate,
  14143. + struct wm8804_clk_cfg *clk_cfg)
  14144. +{
  14145. + clk_cfg->sysclk_freq = 27000000;
  14146. +
  14147. + if (samplerate <= 96000 ||
  14148. + snd_rpi_wm8804.dai_link == snd_allo_digione_dai) {
  14149. + clk_cfg->mclk_freq = samplerate * 256;
  14150. + clk_cfg->mclk_div = WM8804_MCLKDIV_256FS;
  14151. + } else {
  14152. + clk_cfg->mclk_freq = samplerate * 128;
  14153. + clk_cfg->mclk_div = WM8804_MCLKDIV_128FS;
  14154. + }
  14155. +
  14156. + if (!(IS_ERR(snd_clk44gpio) || IS_ERR(snd_clk48gpio)))
  14157. + clk_cfg->sysclk_freq = snd_rpi_wm8804_enable_clock(samplerate);
  14158. +}
  14159. +
  14160. +static int snd_rpi_wm8804_hw_params(struct snd_pcm_substream *substream,
  14161. + struct snd_pcm_hw_params *params)
  14162. +{
  14163. + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  14164. + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
  14165. + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
  14166. + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  14167. + int sampling_freq = 1;
  14168. + int ret;
  14169. + struct wm8804_clk_cfg clk_cfg;
  14170. + int samplerate = params_rate(params);
  14171. +
  14172. + if (samplerate == wm8804_samplerate)
  14173. + return 0;
  14174. +
  14175. + /* clear until all clocks are setup properly */
  14176. + wm8804_samplerate = 0;
  14177. +
  14178. + snd_rpi_wm8804_clk_cfg(samplerate, &clk_cfg);
  14179. +
  14180. + pr_debug("%s samplerate: %d mclk_freq: %u mclk_div: %u sysclk: %u\n",
  14181. + __func__, samplerate, clk_cfg.mclk_freq,
  14182. + clk_cfg.mclk_div, clk_cfg.sysclk_freq);
  14183. +
  14184. + switch (samplerate) {
  14185. + case 32000:
  14186. + sampling_freq = 0x03;
  14187. + break;
  14188. + case 44100:
  14189. + sampling_freq = 0x00;
  14190. + break;
  14191. + case 48000:
  14192. + sampling_freq = 0x02;
  14193. + break;
  14194. + case 88200:
  14195. + sampling_freq = 0x08;
  14196. + break;
  14197. + case 96000:
  14198. + sampling_freq = 0x0a;
  14199. + break;
  14200. + case 176400:
  14201. + sampling_freq = 0x0c;
  14202. + break;
  14203. + case 192000:
  14204. + sampling_freq = 0x0e;
  14205. + break;
  14206. + default:
  14207. + dev_err(rtd->card->dev,
  14208. + "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n",
  14209. + samplerate);
  14210. + }
  14211. +
  14212. + snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, clk_cfg.mclk_div);
  14213. + snd_soc_dai_set_pll(codec_dai, 0, 0,
  14214. + clk_cfg.sysclk_freq, clk_cfg.mclk_freq);
  14215. +
  14216. + ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
  14217. + clk_cfg.sysclk_freq, SND_SOC_CLOCK_OUT);
  14218. + if (ret < 0) {
  14219. + dev_err(rtd->card->dev,
  14220. + "Failed to set WM8804 SYSCLK: %d\n", ret);
  14221. + return ret;
  14222. + }
  14223. +
  14224. + wm8804_samplerate = samplerate;
  14225. +
  14226. + /* set sampling frequency status bits */
  14227. + snd_soc_component_update_bits(component, WM8804_SPDTX4, 0x0f,
  14228. + sampling_freq);
  14229. +
  14230. + return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
  14231. +}
  14232. +
  14233. +static struct snd_soc_ops snd_rpi_wm8804_ops = {
  14234. + .hw_params = snd_rpi_wm8804_hw_params,
  14235. +};
  14236. +
  14237. +SND_SOC_DAILINK_DEFS(justboom_digi,
  14238. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  14239. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  14240. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  14241. +
  14242. +static struct snd_soc_dai_link snd_justboom_digi_dai[] = {
  14243. +{
  14244. + .name = "JustBoom Digi",
  14245. + .stream_name = "JustBoom Digi HiFi",
  14246. + SND_SOC_DAILINK_REG(justboom_digi),
  14247. +},
  14248. +};
  14249. +
  14250. +static struct snd_rpi_wm8804_drvdata drvdata_justboom_digi = {
  14251. + .card_name = "snd_rpi_justboom_digi",
  14252. + .dai = snd_justboom_digi_dai,
  14253. +};
  14254. +
  14255. +SND_SOC_DAILINK_DEFS(iqaudio_digi,
  14256. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  14257. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  14258. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  14259. +
  14260. +static struct snd_soc_dai_link snd_iqaudio_digi_dai[] = {
  14261. +{
  14262. + .name = "IQAudIO Digi",
  14263. + .stream_name = "IQAudIO Digi HiFi",
  14264. + SND_SOC_DAILINK_REG(iqaudio_digi),
  14265. +},
  14266. +};
  14267. +
  14268. +static struct snd_rpi_wm8804_drvdata drvdata_iqaudio_digi = {
  14269. + .card_name = "IQAudIODigi",
  14270. + .dai = snd_iqaudio_digi_dai,
  14271. + .card_name_dt = "wm8804-digi,card-name",
  14272. + .dai_name_dt = "wm8804-digi,dai-name",
  14273. + .dai_stream_name_dt = "wm8804-digi,dai-stream-name",
  14274. +};
  14275. +
  14276. +static int snd_allo_digione_probe(struct platform_device *pdev)
  14277. +{
  14278. + pr_debug("%s\n", __func__);
  14279. +
  14280. + if (IS_ERR(snd_clk44gpio) || IS_ERR(snd_clk48gpio)) {
  14281. + dev_err(&pdev->dev, "devm_gpiod_get() failed\n");
  14282. + return -EINVAL;
  14283. + }
  14284. + return 0;
  14285. +}
  14286. +
  14287. +SND_SOC_DAILINK_DEFS(allo_digione,
  14288. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  14289. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  14290. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  14291. +
  14292. +static struct snd_soc_dai_link snd_allo_digione_dai[] = {
  14293. +{
  14294. + .name = "Allo DigiOne",
  14295. + .stream_name = "Allo DigiOne HiFi",
  14296. + SND_SOC_DAILINK_REG(allo_digione),
  14297. +},
  14298. +};
  14299. +
  14300. +static struct snd_rpi_wm8804_drvdata drvdata_allo_digione = {
  14301. + .card_name = "snd_allo_digione",
  14302. + .dai = snd_allo_digione_dai,
  14303. + .probe = snd_allo_digione_probe,
  14304. +};
  14305. +
  14306. +SND_SOC_DAILINK_DEFS(hifiberry_digi,
  14307. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  14308. + DAILINK_COMP_ARRAY(COMP_EMPTY()),
  14309. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  14310. +
  14311. +static struct snd_soc_dai_link snd_hifiberry_digi_dai[] = {
  14312. +{
  14313. + .name = "HifiBerry Digi",
  14314. + .stream_name = "HifiBerry Digi HiFi",
  14315. + SND_SOC_DAILINK_REG(hifiberry_digi),
  14316. +},
  14317. +};
  14318. +
  14319. +static int snd_hifiberry_digi_probe(struct platform_device *pdev)
  14320. +{
  14321. + pr_debug("%s\n", __func__);
  14322. +
  14323. + if (IS_ERR(snd_clk44gpio) || IS_ERR(snd_clk48gpio))
  14324. + return 0;
  14325. +
  14326. + snd_hifiberry_digi_dai->name = "HiFiBerry Digi+ Pro";
  14327. + snd_hifiberry_digi_dai->stream_name = "HiFiBerry Digi+ Pro HiFi";
  14328. + return 0;
  14329. +}
  14330. +
  14331. +static struct snd_rpi_wm8804_drvdata drvdata_hifiberry_digi = {
  14332. + .card_name = "snd_rpi_hifiberry_digi",
  14333. + .dai = snd_hifiberry_digi_dai,
  14334. + .probe = snd_hifiberry_digi_probe,
  14335. +};
  14336. +
  14337. +static const struct of_device_id snd_rpi_wm8804_of_match[] = {
  14338. + { .compatible = "justboom,justboom-digi",
  14339. + .data = (void *) &drvdata_justboom_digi },
  14340. + { .compatible = "iqaudio,wm8804-digi",
  14341. + .data = (void *) &drvdata_iqaudio_digi },
  14342. + { .compatible = "allo,allo-digione",
  14343. + .data = (void *) &drvdata_allo_digione },
  14344. + { .compatible = "hifiberry,hifiberry-digi",
  14345. + .data = (void *) &drvdata_hifiberry_digi },
  14346. + {},
  14347. +};
  14348. +
  14349. +static struct snd_soc_card snd_rpi_wm8804 = {
  14350. + .driver_name = "RPi-WM8804",
  14351. + .owner = THIS_MODULE,
  14352. + .dai_link = NULL,
  14353. + .num_links = 1,
  14354. +};
  14355. +
  14356. +static int snd_rpi_wm8804_probe(struct platform_device *pdev)
  14357. +{
  14358. + int ret = 0;
  14359. + const struct of_device_id *of_id;
  14360. +
  14361. + snd_rpi_wm8804.dev = &pdev->dev;
  14362. + of_id = of_match_node(snd_rpi_wm8804_of_match, pdev->dev.of_node);
  14363. +
  14364. + if (pdev->dev.of_node && of_id->data) {
  14365. + struct device_node *i2s_node;
  14366. + struct snd_rpi_wm8804_drvdata *drvdata =
  14367. + (struct snd_rpi_wm8804_drvdata *) of_id->data;
  14368. + struct snd_soc_dai_link *dai = drvdata->dai;
  14369. +
  14370. + snd_soc_card_set_drvdata(&snd_rpi_wm8804, drvdata);
  14371. +
  14372. + if (!dai->ops)
  14373. + dai->ops = &snd_rpi_wm8804_ops;
  14374. + if (!dai->codecs->dai_name)
  14375. + dai->codecs->dai_name = "wm8804-spdif";
  14376. + if (!dai->codecs->name)
  14377. + dai->codecs->name = "wm8804.1-003b";
  14378. + if (!dai->dai_fmt)
  14379. + dai->dai_fmt = SND_SOC_DAIFMT_I2S |
  14380. + SND_SOC_DAIFMT_NB_NF |
  14381. + SND_SOC_DAIFMT_CBM_CFM;
  14382. +
  14383. + snd_rpi_wm8804.dai_link = dai;
  14384. + i2s_node = of_parse_phandle(pdev->dev.of_node,
  14385. + "i2s-controller", 0);
  14386. + if (!i2s_node) {
  14387. + pr_err("Failed to find i2s-controller DT node\n");
  14388. + return -ENODEV;
  14389. + }
  14390. +
  14391. + snd_rpi_wm8804.name = drvdata->card_name;
  14392. +
  14393. + /* If requested by in drvdata get card & DAI names from DT */
  14394. + if (drvdata->card_name_dt)
  14395. + of_property_read_string(i2s_node,
  14396. + drvdata->card_name_dt,
  14397. + &snd_rpi_wm8804.name);
  14398. +
  14399. + if (drvdata->dai_name_dt)
  14400. + of_property_read_string(i2s_node,
  14401. + drvdata->dai_name_dt,
  14402. + &dai->name);
  14403. +
  14404. + if (drvdata->dai_stream_name_dt)
  14405. + of_property_read_string(i2s_node,
  14406. + drvdata->dai_stream_name_dt,
  14407. + &dai->stream_name);
  14408. +
  14409. + dai->cpus->of_node = i2s_node;
  14410. + dai->platforms->of_node = i2s_node;
  14411. +
  14412. + /*
  14413. + * clk44gpio and clk48gpio are not required by all cards so
  14414. + * don't check the error status.
  14415. + */
  14416. + snd_clk44gpio =
  14417. + devm_gpiod_get(&pdev->dev, "clock44", GPIOD_OUT_LOW);
  14418. +
  14419. + snd_clk48gpio =
  14420. + devm_gpiod_get(&pdev->dev, "clock48", GPIOD_OUT_LOW);
  14421. +
  14422. + if (drvdata->probe) {
  14423. + ret = drvdata->probe(pdev);
  14424. + if (ret < 0) {
  14425. + dev_err(&pdev->dev, "Custom probe failed %d\n",
  14426. + ret);
  14427. + return ret;
  14428. + }
  14429. + }
  14430. +
  14431. + pr_debug("%s card: %s dai: %s stream: %s\n", __func__,
  14432. + snd_rpi_wm8804.name,
  14433. + dai->name, dai->stream_name);
  14434. + }
  14435. +
  14436. + ret = devm_snd_soc_register_card(&pdev->dev, &snd_rpi_wm8804);
  14437. + if (ret && ret != -EPROBE_DEFER)
  14438. + dev_err(&pdev->dev, "Failed to register card %d\n", ret);
  14439. +
  14440. + return ret;
  14441. +}
  14442. +
  14443. +static struct platform_driver snd_rpi_wm8804_driver = {
  14444. + .driver = {
  14445. + .name = "snd-rpi-wm8804",
  14446. + .owner = THIS_MODULE,
  14447. + .of_match_table = snd_rpi_wm8804_of_match,
  14448. + },
  14449. + .probe = snd_rpi_wm8804_probe,
  14450. +};
  14451. +MODULE_DEVICE_TABLE(of, snd_rpi_wm8804_of_match);
  14452. +
  14453. +module_platform_driver(snd_rpi_wm8804_driver);
  14454. +
  14455. +MODULE_AUTHOR("Tim Gover <[email protected]>");
  14456. +MODULE_DESCRIPTION("ASoC Raspberry Pi Hat generic digi driver for WM8804 based cards");
  14457. +MODULE_LICENSE("GPL v2");
  14458. --- a/sound/soc/codecs/Kconfig
  14459. +++ b/sound/soc/codecs/Kconfig
  14460. @@ -119,6 +119,7 @@ config SND_SOC_ALL_CODECS
  14461. imply SND_SOC_IDT821034
  14462. imply SND_SOC_INNO_RK3036
  14463. imply SND_SOC_ISABELLE
  14464. + imply SND_SOC_I_SABRE_CODEC
  14465. imply SND_SOC_JZ4740_CODEC
  14466. imply SND_SOC_JZ4725B_CODEC
  14467. imply SND_SOC_JZ4760_CODEC
  14468. @@ -126,6 +127,7 @@ config SND_SOC_ALL_CODECS
  14469. imply SND_SOC_LM4857
  14470. imply SND_SOC_LM49453
  14471. imply SND_SOC_LOCHNAGAR_SC
  14472. + imply SND_SOC_MA120X0P
  14473. imply SND_SOC_MAX98088
  14474. imply SND_SOC_MAX98090
  14475. imply SND_SOC_MAX98095
  14476. @@ -168,6 +170,7 @@ config SND_SOC_ALL_CODECS
  14477. imply SND_SOC_PCM179X_SPI
  14478. imply SND_SOC_PCM186X_I2C
  14479. imply SND_SOC_PCM186X_SPI
  14480. + imply SND_SOC_PCM1794A
  14481. imply SND_SOC_PCM3008
  14482. imply SND_SOC_PCM3060_I2C
  14483. imply SND_SOC_PCM3060_SPI
  14484. @@ -255,6 +258,7 @@ config SND_SOC_ALL_CODECS
  14485. imply SND_SOC_TLV320ADCX140
  14486. imply SND_SOC_TLV320AIC23_I2C
  14487. imply SND_SOC_TLV320AIC23_SPI
  14488. + imply SND_SOC_TAS5713
  14489. imply SND_SOC_TLV320AIC26
  14490. imply SND_SOC_TLV320AIC31XX
  14491. imply SND_SOC_TLV320AIC32X4_I2C
  14492. @@ -410,12 +414,12 @@ config SND_SOC_AD193X
  14493. tristate
  14494. config SND_SOC_AD193X_SPI
  14495. - tristate
  14496. + tristate "Analog Devices AU193X CODEC - SPI"
  14497. depends on SPI_MASTER
  14498. select SND_SOC_AD193X
  14499. config SND_SOC_AD193X_I2C
  14500. - tristate
  14501. + tristate "Analog Devices AU193X CODEC - I2C"
  14502. depends on I2C
  14503. select SND_SOC_AD193X
  14504. @@ -1126,6 +1130,13 @@ config SND_SOC_LOCHNAGAR_SC
  14505. This driver support the sound card functionality of the Cirrus
  14506. Logic Lochnagar audio development board.
  14507. +config SND_SOC_MA120X0P
  14508. + tristate "Infineon Merus(TM) MA120X0P Multilevel Class-D Audio amplifiers"
  14509. + depends on I2C
  14510. + help
  14511. + Enable support for Infineon MA120X0P Multilevel Class-D audio power
  14512. + amplifiers.
  14513. +
  14514. config SND_SOC_MADERA
  14515. tristate
  14516. default y if SND_SOC_CS47L15=y
  14517. @@ -1503,6 +1514,10 @@ config SND_SOC_RT5616
  14518. tristate "Realtek RT5616 CODEC"
  14519. depends on I2C
  14520. +config SND_SOC_PCM1794A
  14521. + tristate
  14522. + depends on I2C
  14523. +
  14524. config SND_SOC_RT5631
  14525. tristate "Realtek ALC5631/RT5631 CODEC"
  14526. depends on I2C
  14527. @@ -1846,6 +1861,9 @@ config SND_SOC_TFA9879
  14528. tristate "NXP Semiconductors TFA9879 amplifier"
  14529. depends on I2C
  14530. +config SND_SOC_TAS5713
  14531. + tristate
  14532. +
  14533. config SND_SOC_TFA989X
  14534. tristate "NXP/Goodix TFA989X (TFA1) amplifiers"
  14535. depends on I2C
  14536. @@ -2404,4 +2422,8 @@ config SND_SOC_LPASS_TX_MACRO
  14537. select SND_SOC_LPASS_MACRO_COMMON
  14538. tristate "Qualcomm TX Macro in LPASS(Low Power Audio SubSystem)"
  14539. +config SND_SOC_I_SABRE_CODEC
  14540. + tristate "Audiophonics I-SABRE Codec"
  14541. + depends on I2C
  14542. +
  14543. endmenu
  14544. --- a/sound/soc/codecs/Makefile
  14545. +++ b/sound/soc/codecs/Makefile
  14546. @@ -127,6 +127,7 @@ snd-soc-ics43432-objs := ics43432.o
  14547. snd-soc-idt821034-objs := idt821034.o
  14548. snd-soc-inno-rk3036-objs := inno_rk3036.o
  14549. snd-soc-isabelle-objs := isabelle.o
  14550. +snd-soc-i-sabre-codec-objs := i-sabre-codec.o
  14551. snd-soc-jz4740-codec-objs := jz4740.o
  14552. snd-soc-jz4725b-codec-objs := jz4725b.o
  14553. snd-soc-jz4760-codec-objs := jz4760.o
  14554. @@ -139,6 +140,7 @@ snd-soc-lpass-rx-macro-objs := lpass-rx-
  14555. snd-soc-lpass-tx-macro-objs := lpass-tx-macro.o
  14556. snd-soc-lpass-wsa-macro-objs := lpass-wsa-macro.o
  14557. snd-soc-lpass-va-macro-objs := lpass-va-macro.o
  14558. +snd-soc-ma120x0p-objs := ma120x0p.o
  14559. snd-soc-madera-objs := madera.o
  14560. snd-soc-max9759-objs := max9759.o
  14561. snd-soc-max9768-objs := max9768.o
  14562. @@ -187,6 +189,7 @@ snd-soc-pcm179x-spi-objs := pcm179x-spi.
  14563. snd-soc-pcm186x-objs := pcm186x.o
  14564. snd-soc-pcm186x-i2c-objs := pcm186x-i2c.o
  14565. snd-soc-pcm186x-spi-objs := pcm186x-spi.o
  14566. +snd-soc-pcm1794a-objs := pcm1794a.o
  14567. snd-soc-pcm3008-objs := pcm3008.o
  14568. snd-soc-pcm3060-objs := pcm3060.o
  14569. snd-soc-pcm3060-i2c-objs := pcm3060-i2c.o
  14570. @@ -271,6 +274,7 @@ snd-soc-sta529-objs := sta529.o
  14571. snd-soc-stac9766-objs := stac9766.o
  14572. snd-soc-sti-sas-objs := sti-sas.o
  14573. snd-soc-tas5086-objs := tas5086.o
  14574. +snd-soc-tas5713-objs := tas5713.o
  14575. snd-soc-tas571x-objs := tas571x.o
  14576. snd-soc-tas5720-objs := tas5720.o
  14577. snd-soc-tas5805m-objs := tas5805m.o
  14578. @@ -513,6 +517,7 @@ obj-$(CONFIG_SND_SOC_ICS43432) += snd-so
  14579. obj-$(CONFIG_SND_SOC_IDT821034) += snd-soc-idt821034.o
  14580. obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o
  14581. obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
  14582. +obj-$(CONFIG_SND_SOC_I_SABRE_CODEC) += snd-soc-i-sabre-codec.o
  14583. obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
  14584. obj-$(CONFIG_SND_SOC_JZ4725B_CODEC) += snd-soc-jz4725b-codec.o
  14585. obj-$(CONFIG_SND_SOC_JZ4760_CODEC) += snd-soc-jz4760-codec.o
  14586. @@ -520,6 +525,7 @@ obj-$(CONFIG_SND_SOC_JZ4770_CODEC) += sn
  14587. obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
  14588. obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o
  14589. obj-$(CONFIG_SND_SOC_LOCHNAGAR_SC) += snd-soc-lochnagar-sc.o
  14590. +obj-$(CONFIG_SND_SOC_MA120X0P) += snd-soc-ma120x0p.o
  14591. obj-$(CONFIG_SND_SOC_MADERA) += snd-soc-madera.o
  14592. obj-$(CONFIG_SND_SOC_MAX9759) += snd-soc-max9759.o
  14593. obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
  14594. @@ -563,6 +569,7 @@ obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc
  14595. obj-$(CONFIG_SND_SOC_PCM179X) += snd-soc-pcm179x-codec.o
  14596. obj-$(CONFIG_SND_SOC_PCM1789_I2C) += snd-soc-pcm1789-i2c.o
  14597. obj-$(CONFIG_SND_SOC_PCM1789) += snd-soc-pcm1789-codec.o
  14598. +obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o
  14599. obj-$(CONFIG_SND_SOC_PCM179X_I2C) += snd-soc-pcm179x-i2c.o
  14600. obj-$(CONFIG_SND_SOC_PCM179X_SPI) += snd-soc-pcm179x-spi.o
  14601. obj-$(CONFIG_SND_SOC_PCM186X) += snd-soc-pcm186x.o
  14602. @@ -663,6 +670,7 @@ obj-$(CONFIG_SND_SOC_TAS5805M) += snd-so
  14603. obj-$(CONFIG_SND_SOC_TAS6424) += snd-soc-tas6424.o
  14604. obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o
  14605. obj-$(CONFIG_SND_SOC_TAS2770) += snd-soc-tas2770.o
  14606. +obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o
  14607. obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
  14608. obj-$(CONFIG_SND_SOC_TFA989X) += snd-soc-tfa989x.o
  14609. obj-$(CONFIG_SND_SOC_TLV320ADC3XXX) += snd-soc-tlv320adc3xxx.o
  14610. --- a/sound/soc/codecs/adau1977-i2c.c
  14611. +++ b/sound/soc/codecs/adau1977-i2c.c
  14612. @@ -38,9 +38,19 @@ static const struct i2c_device_id adau19
  14613. };
  14614. MODULE_DEVICE_TABLE(i2c, adau1977_i2c_ids);
  14615. +static const struct of_device_id adau1977_of_ids[] = {
  14616. + { .compatible = "adi,adau1977", },
  14617. + { .compatible = "adi,adau1978", },
  14618. + { .compatible = "adi,adau1979", },
  14619. + { }
  14620. +};
  14621. +MODULE_DEVICE_TABLE(of, adau1977_of_ids);
  14622. +
  14623. +
  14624. static struct i2c_driver adau1977_i2c_driver = {
  14625. .driver = {
  14626. .name = "adau1977",
  14627. + .of_match_table = adau1977_of_ids,
  14628. },
  14629. .probe = adau1977_i2c_probe,
  14630. .id_table = adau1977_i2c_ids,
  14631. --- a/sound/soc/codecs/cs42xx8-i2c.c
  14632. +++ b/sound/soc/codecs/cs42xx8-i2c.c
  14633. @@ -64,11 +64,18 @@ static const struct i2c_device_id cs42xx
  14634. };
  14635. MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id);
  14636. +const struct of_device_id cs42xx8_i2c_of_match[] = {
  14637. + { .compatible = "cirrus,cs42448", .data = &cs42448_data, },
  14638. + { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
  14639. + { /* sentinel */ }
  14640. +};
  14641. +MODULE_DEVICE_TABLE(of, cs42xx8_i2c_of_match);
  14642. +
  14643. static struct i2c_driver cs42xx8_i2c_driver = {
  14644. .driver = {
  14645. .name = "cs42xx8",
  14646. .pm = &cs42xx8_pm,
  14647. - .of_match_table = cs42xx8_of_match,
  14648. + .of_match_table = cs42xx8_i2c_of_match,
  14649. },
  14650. .probe = cs42xx8_i2c_probe,
  14651. .remove = cs42xx8_i2c_remove,
  14652. --- a/sound/soc/codecs/cs42xx8.c
  14653. +++ b/sound/soc/codecs/cs42xx8.c
  14654. @@ -510,6 +510,16 @@ const struct cs42xx8_driver_data cs42888
  14655. };
  14656. EXPORT_SYMBOL_GPL(cs42888_data);
  14657. +const struct of_device_id cs42xx8_of_match[] = {
  14658. + { .compatible = "cirrus,cs42448", .data = &cs42448_data, },
  14659. + { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
  14660. + { /* sentinel */ }
  14661. +};
  14662. +#if !IS_ENABLED(CONFIG_SND_SOC_CS42XX8_I2C)
  14663. +MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
  14664. +EXPORT_SYMBOL_GPL(cs42xx8_of_match);
  14665. +#endif
  14666. +
  14667. int cs42xx8_probe(struct device *dev, struct regmap *regmap, struct cs42xx8_driver_data *drvdata)
  14668. {
  14669. struct cs42xx8_priv *cs42xx8;
  14670. --- /dev/null
  14671. +++ b/sound/soc/codecs/i-sabre-codec.c
  14672. @@ -0,0 +1,389 @@
  14673. +/*
  14674. + * Driver for I-Sabre Q2M
  14675. + *
  14676. + * Author: Satoru Kawase
  14677. + * Modified by: Xiao Qingyong
  14678. + * Modified by: JC BARBAUD (Mute)
  14679. + * Update kernel v4.18+ by : Audiophonics
  14680. + * Copyright 2018 Audiophonics
  14681. + *
  14682. + * This program is free software; you can redistribute it and/or
  14683. + * modify it under the terms of the GNU General Public License
  14684. + * version 2 as published by the Free Software Foundation.
  14685. + *
  14686. + * This program is distributed in the hope that it will be useful, but
  14687. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  14688. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14689. + * General Public License for more details.
  14690. + */
  14691. +
  14692. +
  14693. +#include <linux/init.h>
  14694. +#include <linux/module.h>
  14695. +#include <linux/regmap.h>
  14696. +#include <linux/i2c.h>
  14697. +#include <sound/soc.h>
  14698. +#include <sound/pcm_params.h>
  14699. +#include <sound/tlv.h>
  14700. +
  14701. +#include "i-sabre-codec.h"
  14702. +
  14703. +
  14704. +/* I-Sabre Q2M Codec Private Data */
  14705. +struct i_sabre_codec_priv {
  14706. + struct regmap *regmap;
  14707. + unsigned int fmt;
  14708. +};
  14709. +
  14710. +
  14711. +/* I-Sabre Q2M Codec Default Register Value */
  14712. +static const struct reg_default i_sabre_codec_reg_defaults[] = {
  14713. + { ISABRECODEC_REG_10, 0x00 },
  14714. + { ISABRECODEC_REG_20, 0x00 },
  14715. + { ISABRECODEC_REG_21, 0x00 },
  14716. + { ISABRECODEC_REG_22, 0x00 },
  14717. + { ISABRECODEC_REG_24, 0x00 },
  14718. +};
  14719. +
  14720. +
  14721. +static bool i_sabre_codec_writeable(struct device *dev, unsigned int reg)
  14722. +{
  14723. + switch (reg) {
  14724. + case ISABRECODEC_REG_10:
  14725. + case ISABRECODEC_REG_20:
  14726. + case ISABRECODEC_REG_21:
  14727. + case ISABRECODEC_REG_22:
  14728. + case ISABRECODEC_REG_24:
  14729. + return true;
  14730. +
  14731. + default:
  14732. + return false;
  14733. + }
  14734. +}
  14735. +
  14736. +static bool i_sabre_codec_readable(struct device *dev, unsigned int reg)
  14737. +{
  14738. + switch (reg) {
  14739. + case ISABRECODEC_REG_01:
  14740. + case ISABRECODEC_REG_02:
  14741. + case ISABRECODEC_REG_10:
  14742. + case ISABRECODEC_REG_20:
  14743. + case ISABRECODEC_REG_21:
  14744. + case ISABRECODEC_REG_22:
  14745. + case ISABRECODEC_REG_24:
  14746. + return true;
  14747. +
  14748. + default:
  14749. + return false;
  14750. + }
  14751. +}
  14752. +
  14753. +static bool i_sabre_codec_volatile(struct device *dev, unsigned int reg)
  14754. +{
  14755. + switch (reg) {
  14756. + case ISABRECODEC_REG_01:
  14757. + case ISABRECODEC_REG_02:
  14758. + return true;
  14759. +
  14760. + default:
  14761. + return false;
  14762. + }
  14763. +}
  14764. +
  14765. +
  14766. +/* Volume Scale */
  14767. +static const DECLARE_TLV_DB_SCALE(volume_tlv, -10000, 100, 0);
  14768. +
  14769. +
  14770. +/* Filter Type */
  14771. +static const char * const fir_filter_type_texts[] = {
  14772. + "brick wall",
  14773. + "corrected minimum phase fast",
  14774. + "minimum phase slow",
  14775. + "minimum phase fast",
  14776. + "linear phase slow",
  14777. + "linear phase fast",
  14778. + "apodizing fast",
  14779. +};
  14780. +
  14781. +static SOC_ENUM_SINGLE_DECL(i_sabre_fir_filter_type_enum,
  14782. + ISABRECODEC_REG_22, 0, fir_filter_type_texts);
  14783. +
  14784. +
  14785. +/* I2S / SPDIF Select */
  14786. +static const char * const iis_spdif_sel_texts[] = {
  14787. + "I2S",
  14788. + "SPDIF",
  14789. +};
  14790. +
  14791. +static SOC_ENUM_SINGLE_DECL(i_sabre_iis_spdif_sel_enum,
  14792. + ISABRECODEC_REG_24, 0, iis_spdif_sel_texts);
  14793. +
  14794. +
  14795. +/* Control */
  14796. +static const struct snd_kcontrol_new i_sabre_codec_controls[] = {
  14797. +SOC_SINGLE_RANGE_TLV("Digital Playback Volume", ISABRECODEC_REG_20, 0, 0, 100, 1, volume_tlv),
  14798. +SOC_SINGLE("Digital Playback Switch", ISABRECODEC_REG_21, 0, 1, 1),
  14799. +SOC_ENUM("FIR Filter Type", i_sabre_fir_filter_type_enum),
  14800. +SOC_ENUM("I2S/SPDIF Select", i_sabre_iis_spdif_sel_enum),
  14801. +};
  14802. +
  14803. +
  14804. +static const u32 i_sabre_codec_dai_rates_slave[] = {
  14805. + 8000, 11025, 16000, 22050, 32000,
  14806. + 44100, 48000, 64000, 88200, 96000,
  14807. + 176400, 192000, 352800, 384000,
  14808. + 705600, 768000, 1411200, 1536000
  14809. +};
  14810. +
  14811. +static const struct snd_pcm_hw_constraint_list constraints_slave = {
  14812. + .list = i_sabre_codec_dai_rates_slave,
  14813. + .count = ARRAY_SIZE(i_sabre_codec_dai_rates_slave),
  14814. +};
  14815. +
  14816. +static int i_sabre_codec_dai_startup_slave(
  14817. + struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
  14818. +{
  14819. + struct snd_soc_component *component = dai->component;
  14820. + int ret;
  14821. +
  14822. + ret = snd_pcm_hw_constraint_list(substream->runtime,
  14823. + 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_slave);
  14824. + if (ret != 0) {
  14825. + dev_err(component->card->dev, "Failed to setup rates constraints: %d\n", ret);
  14826. + }
  14827. +
  14828. + return ret;
  14829. +}
  14830. +
  14831. +static int i_sabre_codec_dai_startup(
  14832. + struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
  14833. +{
  14834. + struct snd_soc_component *component = dai->component;
  14835. + struct i_sabre_codec_priv *i_sabre_codec
  14836. + = snd_soc_component_get_drvdata(component);
  14837. +
  14838. + switch (i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  14839. + case SND_SOC_DAIFMT_CBS_CFS:
  14840. + return i_sabre_codec_dai_startup_slave(substream, dai);
  14841. +
  14842. + default:
  14843. + return (-EINVAL);
  14844. + }
  14845. +}
  14846. +
  14847. +static int i_sabre_codec_hw_params(
  14848. + struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
  14849. + struct snd_soc_dai *dai)
  14850. +{
  14851. + struct snd_soc_component *component = dai->component;
  14852. + struct i_sabre_codec_priv *i_sabre_codec
  14853. + = snd_soc_component_get_drvdata(component);
  14854. + unsigned int daifmt;
  14855. + int format_width;
  14856. +
  14857. + dev_dbg(component->card->dev, "hw_params %u Hz, %u channels\n",
  14858. + params_rate(params), params_channels(params));
  14859. +
  14860. + /* Check I2S Format (Bit Size) */
  14861. + format_width = snd_pcm_format_width(params_format(params));
  14862. + if ((format_width != 32) && (format_width != 16)) {
  14863. + dev_err(component->card->dev, "Bad frame size: %d\n",
  14864. + snd_pcm_format_width(params_format(params)));
  14865. + return (-EINVAL);
  14866. + }
  14867. +
  14868. + /* Check Slave Mode */
  14869. + daifmt = i_sabre_codec->fmt & SND_SOC_DAIFMT_MASTER_MASK;
  14870. + if (daifmt != SND_SOC_DAIFMT_CBS_CFS) {
  14871. + return (-EINVAL);
  14872. + }
  14873. +
  14874. + /* Notify Sampling Frequency */
  14875. + switch (params_rate(params))
  14876. + {
  14877. + case 44100:
  14878. + case 48000:
  14879. + case 88200:
  14880. + case 96000:
  14881. + case 176400:
  14882. + case 192000:
  14883. + snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x00);
  14884. + break;
  14885. +
  14886. + case 352800:
  14887. + case 384000:
  14888. + case 705600:
  14889. + case 768000:
  14890. + case 1411200:
  14891. + case 1536000:
  14892. + snd_soc_component_update_bits(component, ISABRECODEC_REG_10, 0x01, 0x01);
  14893. + break;
  14894. + }
  14895. +
  14896. + return 0;
  14897. +}
  14898. +
  14899. +static int i_sabre_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  14900. +{
  14901. + struct snd_soc_component *component = dai->component;
  14902. + struct i_sabre_codec_priv *i_sabre_codec
  14903. + = snd_soc_component_get_drvdata(component);
  14904. +
  14905. + /* interface format */
  14906. + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  14907. + case SND_SOC_DAIFMT_I2S:
  14908. + break;
  14909. +
  14910. + case SND_SOC_DAIFMT_RIGHT_J:
  14911. + case SND_SOC_DAIFMT_LEFT_J:
  14912. + default:
  14913. + return (-EINVAL);
  14914. + }
  14915. +
  14916. + /* clock inversion */
  14917. + if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
  14918. + return (-EINVAL);
  14919. + }
  14920. +
  14921. + /* Set Audio Data Format */
  14922. + i_sabre_codec->fmt = fmt;
  14923. +
  14924. + return 0;
  14925. +}
  14926. +
  14927. +static int i_sabre_codec_dac_mute(struct snd_soc_dai *dai, int mute, int direction)
  14928. +{
  14929. + struct snd_soc_component *component = dai->component;
  14930. +
  14931. + if (mute) {
  14932. + snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x01);
  14933. + } else {
  14934. + snd_soc_component_update_bits(component, ISABRECODEC_REG_21, 0x01, 0x00);
  14935. + }
  14936. +
  14937. + return 0;
  14938. +}
  14939. +
  14940. +
  14941. +static const struct snd_soc_dai_ops i_sabre_codec_dai_ops = {
  14942. + .startup = i_sabre_codec_dai_startup,
  14943. + .hw_params = i_sabre_codec_hw_params,
  14944. + .set_fmt = i_sabre_codec_set_fmt,
  14945. + .mute_stream = i_sabre_codec_dac_mute,
  14946. +};
  14947. +
  14948. +static struct snd_soc_dai_driver i_sabre_codec_dai = {
  14949. + .name = "i-sabre-codec-dai",
  14950. + .playback = {
  14951. + .stream_name = "Playback",
  14952. + .channels_min = 2,
  14953. + .channels_max = 2,
  14954. + .rates = SNDRV_PCM_RATE_CONTINUOUS,
  14955. + .rate_min = 8000,
  14956. + .rate_max = 1536000,
  14957. + .formats = SNDRV_PCM_FMTBIT_S16_LE
  14958. + | SNDRV_PCM_FMTBIT_S32_LE,
  14959. + },
  14960. + .ops = &i_sabre_codec_dai_ops,
  14961. +};
  14962. +
  14963. +static struct snd_soc_component_driver i_sabre_codec_codec_driver = {
  14964. + .controls = i_sabre_codec_controls,
  14965. + .num_controls = ARRAY_SIZE(i_sabre_codec_controls),
  14966. +};
  14967. +
  14968. +
  14969. +static const struct regmap_config i_sabre_codec_regmap = {
  14970. + .reg_bits = 8,
  14971. + .val_bits = 8,
  14972. + .max_register = ISABRECODEC_MAX_REG,
  14973. +
  14974. + .reg_defaults = i_sabre_codec_reg_defaults,
  14975. + .num_reg_defaults = ARRAY_SIZE(i_sabre_codec_reg_defaults),
  14976. +
  14977. + .writeable_reg = i_sabre_codec_writeable,
  14978. + .readable_reg = i_sabre_codec_readable,
  14979. + .volatile_reg = i_sabre_codec_volatile,
  14980. +
  14981. + .cache_type = REGCACHE_RBTREE,
  14982. +};
  14983. +
  14984. +
  14985. +static int i_sabre_codec_probe(struct device *dev, struct regmap *regmap)
  14986. +{
  14987. + struct i_sabre_codec_priv *i_sabre_codec;
  14988. + int ret;
  14989. +
  14990. + i_sabre_codec = devm_kzalloc(dev, sizeof(*i_sabre_codec), GFP_KERNEL);
  14991. + if (!i_sabre_codec) {
  14992. + dev_err(dev, "devm_kzalloc");
  14993. + return (-ENOMEM);
  14994. + }
  14995. +
  14996. + i_sabre_codec->regmap = regmap;
  14997. +
  14998. + dev_set_drvdata(dev, i_sabre_codec);
  14999. +
  15000. + ret = snd_soc_register_component(dev,
  15001. + &i_sabre_codec_codec_driver, &i_sabre_codec_dai, 1);
  15002. + if (ret != 0) {
  15003. + dev_err(dev, "Failed to register CODEC: %d\n", ret);
  15004. + return ret;
  15005. + }
  15006. +
  15007. + return 0;
  15008. +}
  15009. +
  15010. +static void i_sabre_codec_remove(struct device *dev)
  15011. +{
  15012. + snd_soc_unregister_component(dev);
  15013. +}
  15014. +
  15015. +
  15016. +static int i_sabre_codec_i2c_probe(struct i2c_client *i2c)
  15017. +{
  15018. + struct regmap *regmap;
  15019. +
  15020. + regmap = devm_regmap_init_i2c(i2c, &i_sabre_codec_regmap);
  15021. + if (IS_ERR(regmap)) {
  15022. + return PTR_ERR(regmap);
  15023. + }
  15024. +
  15025. + return i_sabre_codec_probe(&i2c->dev, regmap);
  15026. +}
  15027. +
  15028. +static void i_sabre_codec_i2c_remove(struct i2c_client *i2c)
  15029. +{
  15030. + i_sabre_codec_remove(&i2c->dev);
  15031. +}
  15032. +
  15033. +
  15034. +static const struct i2c_device_id i_sabre_codec_i2c_id[] = {
  15035. + { "i-sabre-codec", },
  15036. + { }
  15037. +};
  15038. +MODULE_DEVICE_TABLE(i2c, i_sabre_codec_i2c_id);
  15039. +
  15040. +static const struct of_device_id i_sabre_codec_of_match[] = {
  15041. + { .compatible = "audiophonics,i-sabre-codec", },
  15042. + { }
  15043. +};
  15044. +MODULE_DEVICE_TABLE(of, i_sabre_codec_of_match);
  15045. +
  15046. +static struct i2c_driver i_sabre_codec_i2c_driver = {
  15047. + .driver = {
  15048. + .name = "i-sabre-codec-i2c",
  15049. + .owner = THIS_MODULE,
  15050. + .of_match_table = of_match_ptr(i_sabre_codec_of_match),
  15051. + },
  15052. + .probe = i_sabre_codec_i2c_probe,
  15053. + .remove = i_sabre_codec_i2c_remove,
  15054. + .id_table = i_sabre_codec_i2c_id,
  15055. +};
  15056. +module_i2c_driver(i_sabre_codec_i2c_driver);
  15057. +
  15058. +
  15059. +MODULE_DESCRIPTION("ASoC I-Sabre Q2M codec driver");
  15060. +MODULE_AUTHOR("Audiophonics <http://www.audiophonics.fr>");
  15061. +MODULE_LICENSE("GPL");
  15062. --- /dev/null
  15063. +++ b/sound/soc/codecs/i-sabre-codec.h
  15064. @@ -0,0 +1,42 @@
  15065. +/*
  15066. + * Driver for I-Sabre Q2M
  15067. + *
  15068. + * Author: Satoru Kawase
  15069. + * Modified by: Xiao Qingyong
  15070. + * Copyright 2018 Audiophonics
  15071. + *
  15072. + * This program is free software; you can redistribute it and/or
  15073. + * modify it under the terms of the GNU General Public License
  15074. + * version 2 as published by the Free Software Foundation.
  15075. + *
  15076. + * This program is distributed in the hope that it will be useful, but
  15077. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  15078. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15079. + * General Public License for more details.
  15080. + */
  15081. +
  15082. +#ifndef _SND_SOC_ISABRECODEC
  15083. +#define _SND_SOC_ISABRECODEC
  15084. +
  15085. +
  15086. +/* ISABRECODEC Register Address */
  15087. +#define ISABRECODEC_REG_01 0x01 /* Virtual Device ID : 0x01 = es9038q2m */
  15088. +#define ISABRECODEC_REG_02 0x02 /* API revision : 0x01 = Revision 01 */
  15089. +#define ISABRECODEC_REG_10 0x10 /* 0x01 = above 192kHz, 0x00 = otherwise */
  15090. +#define ISABRECODEC_REG_20 0x20 /* 0 - 100 (decimal value, 0 = min., 100 = max.) */
  15091. +#define ISABRECODEC_REG_21 0x21 /* 0x00 = Mute OFF, 0x01 = Mute ON */
  15092. +#define ISABRECODEC_REG_22 0x22
  15093. +/*
  15094. + 0x00 = brick wall,
  15095. + 0x01 = corrected minimum phase fast,
  15096. + 0x02 = minimum phase slow,
  15097. + 0x03 = minimum phase fast,
  15098. + 0x04 = linear phase slow,
  15099. + 0x05 = linear phase fast,
  15100. + 0x06 = apodizing fast,
  15101. +*/
  15102. +//#define ISABRECODEC_REG_23 0x23 /* reserved */
  15103. +#define ISABRECODEC_REG_24 0x24 /* 0x00 = I2S, 0x01 = SPDIF */
  15104. +#define ISABRECODEC_MAX_REG 0x24 /* Maximum Register Number */
  15105. +
  15106. +#endif /* _SND_SOC_ISABRECODEC */
  15107. --- /dev/null
  15108. +++ b/sound/soc/codecs/ma120x0p.c
  15109. @@ -0,0 +1,1380 @@
  15110. +// SPDX-License-Identifier: GPL-2.0-or-later
  15111. +/*
  15112. + * ASoC Driver for Infineon Merus(TM) ma120x0p multi-level class-D amplifier
  15113. + *
  15114. + * Authors: Ariel Muszkat <[email protected]>
  15115. + * Jorgen Kragh Jakobsen <[email protected]>
  15116. + *
  15117. + * Copyright (C) 2019 Infineon Technologies AG
  15118. + *
  15119. + */
  15120. +#include <linux/module.h>
  15121. +#include <linux/moduleparam.h>
  15122. +#include <linux/init.h>
  15123. +#include <linux/delay.h>
  15124. +#include <linux/pm_runtime.h>
  15125. +#include <linux/i2c.h>
  15126. +#include <linux/of_device.h>
  15127. +#include <linux/spi/spi.h>
  15128. +#include <linux/regmap.h>
  15129. +#include <linux/regulator/consumer.h>
  15130. +#include <linux/slab.h>
  15131. +#include <linux/gpio/consumer.h>
  15132. +#include <linux/gpio.h>
  15133. +#include <sound/core.h>
  15134. +#include <sound/pcm.h>
  15135. +#include <sound/pcm_params.h>
  15136. +#include <sound/soc.h>
  15137. +#include <sound/soc-dapm.h>
  15138. +#include <sound/initval.h>
  15139. +#include <sound/tlv.h>
  15140. +#include <linux/interrupt.h>
  15141. +
  15142. +#include <linux/kernel.h>
  15143. +#include <linux/string.h>
  15144. +#include <linux/fs.h>
  15145. +#include <linux/uaccess.h>
  15146. +
  15147. +#ifndef _MA120X0P_
  15148. +#define _MA120X0P_
  15149. +//------------------------------------------------------------------manualPM---
  15150. +// Select Manual PowerMode control
  15151. +#define ma_manualpm__a 0
  15152. +#define ma_manualpm__len 1
  15153. +#define ma_manualpm__mask 0x40
  15154. +#define ma_manualpm__shift 0x06
  15155. +#define ma_manualpm__reset 0x00
  15156. +//--------------------------------------------------------------------pm_man---
  15157. +// manual selected power mode
  15158. +#define ma_pm_man__a 0
  15159. +#define ma_pm_man__len 2
  15160. +#define ma_pm_man__mask 0x30
  15161. +#define ma_pm_man__shift 0x04
  15162. +#define ma_pm_man__reset 0x03
  15163. +//------------------------------------------ ----------------------mthr_1to2---
  15164. +// mod. index threshold value for pm1=>pm2 change.
  15165. +#define ma_mthr_1to2__a 1
  15166. +#define ma_mthr_1to2__len 8
  15167. +#define ma_mthr_1to2__mask 0xff
  15168. +#define ma_mthr_1to2__shift 0x00
  15169. +#define ma_mthr_1to2__reset 0x3c
  15170. +//-----------------------------------------------------------------mthr_2to1---
  15171. +// mod. index threshold value for pm2=>pm1 change.
  15172. +#define ma_mthr_2to1__a 2
  15173. +#define ma_mthr_2to1__len 8
  15174. +#define ma_mthr_2to1__mask 0xff
  15175. +#define ma_mthr_2to1__shift 0x00
  15176. +#define ma_mthr_2to1__reset 0x32
  15177. +//-----------------------------------------------------------------mthr_2to3---
  15178. +// mod. index threshold value for pm2=>pm3 change.
  15179. +#define ma_mthr_2to3__a 3
  15180. +#define ma_mthr_2to3__len 8
  15181. +#define ma_mthr_2to3__mask 0xff
  15182. +#define ma_mthr_2to3__shift 0x00
  15183. +#define ma_mthr_2to3__reset 0x5a
  15184. +//-----------------------------------------------------------------mthr_3to2---
  15185. +// mod. index threshold value for pm3=>pm2 change.
  15186. +#define ma_mthr_3to2__a 4
  15187. +#define ma_mthr_3to2__len 8
  15188. +#define ma_mthr_3to2__mask 0xff
  15189. +#define ma_mthr_3to2__shift 0x00
  15190. +#define ma_mthr_3to2__reset 0x50
  15191. +//-------------------------------------------------------------pwmclkdiv_nom---
  15192. +// pwm default clock divider value
  15193. +#define ma_pwmclkdiv_nom__a 8
  15194. +#define ma_pwmclkdiv_nom__len 8
  15195. +#define ma_pwmclkdiv_nom__mask 0xff
  15196. +#define ma_pwmclkdiv_nom__shift 0x00
  15197. +#define ma_pwmclkdiv_nom__reset 0x26
  15198. +//--------- ----------------------------------------------------ocp_latch_en---
  15199. +// high to use permanently latching level-2 ocp
  15200. +#define ma_ocp_latch_en__a 10
  15201. +#define ma_ocp_latch_en__len 1
  15202. +#define ma_ocp_latch_en__mask 0x02
  15203. +#define ma_ocp_latch_en__shift 0x01
  15204. +#define ma_ocp_latch_en__reset 0x00
  15205. +//---------------------------------------------------------------lf_clamp_en---
  15206. +// high (default) to enable lf int2+3 clamping on clip
  15207. +#define ma_lf_clamp_en__a 10
  15208. +#define ma_lf_clamp_en__len 1
  15209. +#define ma_lf_clamp_en__mask 0x80
  15210. +#define ma_lf_clamp_en__shift 0x07
  15211. +#define ma_lf_clamp_en__reset 0x00
  15212. +//-------------------------------------------------------pmcfg_btl_b.modtype---
  15213. +//
  15214. +#define ma_pmcfg_btl_b__modtype__a 18
  15215. +#define ma_pmcfg_btl_b__modtype__len 2
  15216. +#define ma_pmcfg_btl_b__modtype__mask 0x18
  15217. +#define ma_pmcfg_btl_b__modtype__shift 0x03
  15218. +#define ma_pmcfg_btl_b__modtype__reset 0x02
  15219. +//-------------------------------------------------------pmcfg_btl_b.freqdiv---
  15220. +#define ma_pmcfg_btl_b__freqdiv__a 18
  15221. +#define ma_pmcfg_btl_b__freqdiv__len 2
  15222. +#define ma_pmcfg_btl_b__freqdiv__mask 0x06
  15223. +#define ma_pmcfg_btl_b__freqdiv__shift 0x01
  15224. +#define ma_pmcfg_btl_b__freqdiv__reset 0x01
  15225. +//----------------------------------------------------pmcfg_btl_b.lf_gain_ol---
  15226. +//
  15227. +#define ma_pmcfg_btl_b__lf_gain_ol__a 18
  15228. +#define ma_pmcfg_btl_b__lf_gain_ol__len 1
  15229. +#define ma_pmcfg_btl_b__lf_gain_ol__mask 0x01
  15230. +#define ma_pmcfg_btl_b__lf_gain_ol__shift 0x00
  15231. +#define ma_pmcfg_btl_b__lf_gain_ol__reset 0x01
  15232. +//-------------------------------------------------------pmcfg_btl_c.freqdiv---
  15233. +//
  15234. +#define ma_pmcfg_btl_c__freqdiv__a 19
  15235. +#define ma_pmcfg_btl_c__freqdiv__len 2
  15236. +#define ma_pmcfg_btl_c__freqdiv__mask 0x06
  15237. +#define ma_pmcfg_btl_c__freqdiv__shift 0x01
  15238. +#define ma_pmcfg_btl_c__freqdiv__reset 0x01
  15239. +//-------------------------------------------------------pmcfg_btl_c.modtype---
  15240. +//
  15241. +#define ma_pmcfg_btl_c__modtype__a 19
  15242. +#define ma_pmcfg_btl_c__modtype__len 2
  15243. +#define ma_pmcfg_btl_c__modtype__mask 0x18
  15244. +#define ma_pmcfg_btl_c__modtype__shift 0x03
  15245. +#define ma_pmcfg_btl_c__modtype__reset 0x01
  15246. +//----------------------------------------------------pmcfg_btl_c.lf_gain_ol---
  15247. +//
  15248. +#define ma_pmcfg_btl_c__lf_gain_ol__a 19
  15249. +#define ma_pmcfg_btl_c__lf_gain_ol__len 1
  15250. +#define ma_pmcfg_btl_c__lf_gain_ol__mask 0x01
  15251. +#define ma_pmcfg_btl_c__lf_gain_ol__shift 0x00
  15252. +#define ma_pmcfg_btl_c__lf_gain_ol__reset 0x00
  15253. +//-------------------------------------------------------pmcfg_btl_d.modtype---
  15254. +//
  15255. +#define ma_pmcfg_btl_d__modtype__a 20
  15256. +#define ma_pmcfg_btl_d__modtype__len 2
  15257. +#define ma_pmcfg_btl_d__modtype__mask 0x18
  15258. +#define ma_pmcfg_btl_d__modtype__shift 0x03
  15259. +#define ma_pmcfg_btl_d__modtype__reset 0x02
  15260. +//-------------------------------------------------------pmcfg_btl_d.freqdiv---
  15261. +//
  15262. +#define ma_pmcfg_btl_d__freqdiv__a 20
  15263. +#define ma_pmcfg_btl_d__freqdiv__len 2
  15264. +#define ma_pmcfg_btl_d__freqdiv__mask 0x06
  15265. +#define ma_pmcfg_btl_d__freqdiv__shift 0x01
  15266. +#define ma_pmcfg_btl_d__freqdiv__reset 0x02
  15267. +//----------------------------------------------------pmcfg_btl_d.lf_gain_ol---
  15268. +//
  15269. +#define ma_pmcfg_btl_d__lf_gain_ol__a 20
  15270. +#define ma_pmcfg_btl_d__lf_gain_ol__len 1
  15271. +#define ma_pmcfg_btl_d__lf_gain_ol__mask 0x01
  15272. +#define ma_pmcfg_btl_d__lf_gain_ol__shift 0x00
  15273. +#define ma_pmcfg_btl_d__lf_gain_ol__reset 0x00
  15274. +//------------ -------------------------------------------pmcfg_se_a.modtype---
  15275. +//
  15276. +#define ma_pmcfg_se_a__modtype__a 21
  15277. +#define ma_pmcfg_se_a__modtype__len 2
  15278. +#define ma_pmcfg_se_a__modtype__mask 0x18
  15279. +#define ma_pmcfg_se_a__modtype__shift 0x03
  15280. +#define ma_pmcfg_se_a__modtype__reset 0x01
  15281. +//--------------------------------------------------------pmcfg_se_a.freqdiv---
  15282. +//
  15283. +#define ma_pmcfg_se_a__freqdiv__a 21
  15284. +#define ma_pmcfg_se_a__freqdiv__len 2
  15285. +#define ma_pmcfg_se_a__freqdiv__mask 0x06
  15286. +#define ma_pmcfg_se_a__freqdiv__shift 0x01
  15287. +#define ma_pmcfg_se_a__freqdiv__reset 0x00
  15288. +//-----------------------------------------------------pmcfg_se_a.lf_gain_ol---
  15289. +//
  15290. +#define ma_pmcfg_se_a__lf_gain_ol__a 21
  15291. +#define ma_pmcfg_se_a__lf_gain_ol__len 1
  15292. +#define ma_pmcfg_se_a__lf_gain_ol__mask 0x01
  15293. +#define ma_pmcfg_se_a__lf_gain_ol__shift 0x00
  15294. +#define ma_pmcfg_se_a__lf_gain_ol__reset 0x01
  15295. +//-----------------------------------------------------pmcfg_se_b.lf_gain_ol---
  15296. +//
  15297. +#define ma_pmcfg_se_b__lf_gain_ol__a 22
  15298. +#define ma_pmcfg_se_b__lf_gain_ol__len 1
  15299. +#define ma_pmcfg_se_b__lf_gain_ol__mask 0x01
  15300. +#define ma_pmcfg_se_b__lf_gain_ol__shift 0x00
  15301. +#define ma_pmcfg_se_b__lf_gain_ol__reset 0x00
  15302. +//--------------------------------------------------------pmcfg_se_b.freqdiv---
  15303. +//
  15304. +#define ma_pmcfg_se_b__freqdiv__a 22
  15305. +#define ma_pmcfg_se_b__freqdiv__len 2
  15306. +#define ma_pmcfg_se_b__freqdiv__mask 0x06
  15307. +#define ma_pmcfg_se_b__freqdiv__shift 0x01
  15308. +#define ma_pmcfg_se_b__freqdiv__reset 0x01
  15309. +//--------------------------------------------------------pmcfg_se_b.modtype---
  15310. +//
  15311. +#define ma_pmcfg_se_b__modtype__a 22
  15312. +#define ma_pmcfg_se_b__modtype__len 2
  15313. +#define ma_pmcfg_se_b__modtype__mask 0x18
  15314. +#define ma_pmcfg_se_b__modtype__shift 0x03
  15315. +#define ma_pmcfg_se_b__modtype__reset 0x01
  15316. +//----------------------------------------------------------balwaitcount_pm1---
  15317. +// pm1 balancing period.
  15318. +#define ma_balwaitcount_pm1__a 23
  15319. +#define ma_balwaitcount_pm1__len 8
  15320. +#define ma_balwaitcount_pm1__mask 0xff
  15321. +#define ma_balwaitcount_pm1__shift 0x00
  15322. +#define ma_balwaitcount_pm1__reset 0x14
  15323. +//----------------------------------------------------------balwaitcount_pm2---
  15324. +// pm2 balancing period.
  15325. +#define ma_balwaitcount_pm2__a 24
  15326. +#define ma_balwaitcount_pm2__len 8
  15327. +#define ma_balwaitcount_pm2__mask 0xff
  15328. +#define ma_balwaitcount_pm2__shift 0x00
  15329. +#define ma_balwaitcount_pm2__reset 0x14
  15330. +//----------------------------------------------------------balwaitcount_pm3---
  15331. +// pm3 balancing period.
  15332. +#define ma_balwaitcount_pm3__a 25
  15333. +#define ma_balwaitcount_pm3__len 8
  15334. +#define ma_balwaitcount_pm3__mask 0xff
  15335. +#define ma_balwaitcount_pm3__shift 0x00
  15336. +#define ma_balwaitcount_pm3__reset 0x1a
  15337. +//-------------------------------------------------------------usespread_pm1---
  15338. +// pm1 pwm spread-spectrum mode on/off.
  15339. +#define ma_usespread_pm1__a 26
  15340. +#define ma_usespread_pm1__len 1
  15341. +#define ma_usespread_pm1__mask 0x40
  15342. +#define ma_usespread_pm1__shift 0x06
  15343. +#define ma_usespread_pm1__reset 0x00
  15344. +//---------------------------------------------------------------dtsteps_pm1---
  15345. +// pm1 dead time setting [10ns steps].
  15346. +#define ma_dtsteps_pm1__a 26
  15347. +#define ma_dtsteps_pm1__len 3
  15348. +#define ma_dtsteps_pm1__mask 0x38
  15349. +#define ma_dtsteps_pm1__shift 0x03
  15350. +#define ma_dtsteps_pm1__reset 0x04
  15351. +//---------------------------------------------------------------baltype_pm1---
  15352. +// pm1 balancing sensor scheme.
  15353. +#define ma_baltype_pm1__a 26
  15354. +#define ma_baltype_pm1__len 3
  15355. +#define ma_baltype_pm1__mask 0x07
  15356. +#define ma_baltype_pm1__shift 0x00
  15357. +#define ma_baltype_pm1__reset 0x00
  15358. +//-------------------------------------------------------------usespread_pm2---
  15359. +// pm2 pwm spread-spectrum mode on/off.
  15360. +#define ma_usespread_pm2__a 27
  15361. +#define ma_usespread_pm2__len 1
  15362. +#define ma_usespread_pm2__mask 0x40
  15363. +#define ma_usespread_pm2__shift 0x06
  15364. +#define ma_usespread_pm2__reset 0x00
  15365. +//---------------------------------------------------------------dtsteps_pm2---
  15366. +// pm2 dead time setting [10ns steps].
  15367. +#define ma_dtsteps_pm2__a 27
  15368. +#define ma_dtsteps_pm2__len 3
  15369. +#define ma_dtsteps_pm2__mask 0x38
  15370. +#define ma_dtsteps_pm2__shift 0x03
  15371. +#define ma_dtsteps_pm2__reset 0x03
  15372. +//---------------------------------------------------------------baltype_pm2---
  15373. +// pm2 balancing sensor scheme.
  15374. +#define ma_baltype_pm2__a 27
  15375. +#define ma_baltype_pm2__len 3
  15376. +#define ma_baltype_pm2__mask 0x07
  15377. +#define ma_baltype_pm2__shift 0x00
  15378. +#define ma_baltype_pm2__reset 0x01
  15379. +//-------------------------------------------------------------usespread_pm3---
  15380. +// pm3 pwm spread-spectrum mode on/off.
  15381. +#define ma_usespread_pm3__a 28
  15382. +#define ma_usespread_pm3__len 1
  15383. +#define ma_usespread_pm3__mask 0x40
  15384. +#define ma_usespread_pm3__shift 0x06
  15385. +#define ma_usespread_pm3__reset 0x00
  15386. +//---------------------------------------------------------------dtsteps_pm3---
  15387. +// pm3 dead time setting [10ns steps].
  15388. +#define ma_dtsteps_pm3__a 28
  15389. +#define ma_dtsteps_pm3__len 3
  15390. +#define ma_dtsteps_pm3__mask 0x38
  15391. +#define ma_dtsteps_pm3__shift 0x03
  15392. +#define ma_dtsteps_pm3__reset 0x01
  15393. +//---------------------------------------------------------------baltype_pm3---
  15394. +// pm3 balancing sensor scheme.
  15395. +#define ma_baltype_pm3__a 28
  15396. +#define ma_baltype_pm3__len 3
  15397. +#define ma_baltype_pm3__mask 0x07
  15398. +#define ma_baltype_pm3__shift 0x00
  15399. +#define ma_baltype_pm3__reset 0x03
  15400. +//-----------------------------------------------------------------pmprofile---
  15401. +// pm profile select. valid presets: 0-1-2-3-4. 5=> custom profile.
  15402. +#define ma_pmprofile__a 29
  15403. +#define ma_pmprofile__len 3
  15404. +#define ma_pmprofile__mask 0x07
  15405. +#define ma_pmprofile__shift 0x00
  15406. +#define ma_pmprofile__reset 0x00
  15407. +//-------------------------------------------------------------------pm3_man---
  15408. +// custom profile pm3 contents. 0=>a, 1=>b, 2=>c, 3=>d
  15409. +#define ma_pm3_man__a 30
  15410. +#define ma_pm3_man__len 2
  15411. +#define ma_pm3_man__mask 0x30
  15412. +#define ma_pm3_man__shift 0x04
  15413. +#define ma_pm3_man__reset 0x02
  15414. +//-------------------------------------------------------------------pm2_man---
  15415. +// custom profile pm2 contents. 0=>a, 1=>b, 2=>c, 3=>d
  15416. +#define ma_pm2_man__a 30
  15417. +#define ma_pm2_man__len 2
  15418. +#define ma_pm2_man__mask 0x0c
  15419. +#define ma_pm2_man__shift 0x02
  15420. +#define ma_pm2_man__reset 0x03
  15421. +//-------------------------------------------------------------------pm1_man---
  15422. +// custom profile pm1 contents. 0=>a, 1=>b, 2=>c, 3=>d
  15423. +#define ma_pm1_man__a 30
  15424. +#define ma_pm1_man__len 2
  15425. +#define ma_pm1_man__mask 0x03
  15426. +#define ma_pm1_man__shift 0x00
  15427. +#define ma_pm1_man__reset 0x03
  15428. +//-----------------------------------------------------------ocp_latch_clear---
  15429. +// low-high clears current ocp latched condition.
  15430. +#define ma_ocp_latch_clear__a 32
  15431. +#define ma_ocp_latch_clear__len 1
  15432. +#define ma_ocp_latch_clear__mask 0x80
  15433. +#define ma_ocp_latch_clear__shift 0x07
  15434. +#define ma_ocp_latch_clear__reset 0x00
  15435. +//-------------------------------------------------------------audio_in_mode---
  15436. +// audio input mode; 0-1-2-3-4-5
  15437. +#define ma_audio_in_mode__a 37
  15438. +#define ma_audio_in_mode__len 3
  15439. +#define ma_audio_in_mode__mask 0xe0
  15440. +#define ma_audio_in_mode__shift 0x05
  15441. +#define ma_audio_in_mode__reset 0x00
  15442. +//-----------------------------------------------------------------eh_dcshdn---
  15443. +// high to enable dc protection
  15444. +#define ma_eh_dcshdn__a 38
  15445. +#define ma_eh_dcshdn__len 1
  15446. +#define ma_eh_dcshdn__mask 0x04
  15447. +#define ma_eh_dcshdn__shift 0x02
  15448. +#define ma_eh_dcshdn__reset 0x01
  15449. +//---------------------------------------------------------audio_in_mode_ext---
  15450. +// if set, audio_in_mode is controlled from audio_in_mode register. if not set
  15451. +//audio_in_mode is set from fuse bank setting
  15452. +#define ma_audio_in_mode_ext__a 39
  15453. +#define ma_audio_in_mode_ext__len 1
  15454. +#define ma_audio_in_mode_ext__mask 0x20
  15455. +#define ma_audio_in_mode_ext__shift 0x05
  15456. +#define ma_audio_in_mode_ext__reset 0x00
  15457. +//------------------------------------------------------------------eh_clear---
  15458. +// flip to clear error registers
  15459. +#define ma_eh_clear__a 45
  15460. +#define ma_eh_clear__len 1
  15461. +#define ma_eh_clear__mask 0x04
  15462. +#define ma_eh_clear__shift 0x02
  15463. +#define ma_eh_clear__reset 0x00
  15464. +//----------------------------------------------------------thermal_compr_en---
  15465. +// enable otw-contr. input compression?
  15466. +#define ma_thermal_compr_en__a 45
  15467. +#define ma_thermal_compr_en__len 1
  15468. +#define ma_thermal_compr_en__mask 0x20
  15469. +#define ma_thermal_compr_en__shift 0x05
  15470. +#define ma_thermal_compr_en__reset 0x01
  15471. +//---------------------------------------------------------------system_mute---
  15472. +// 1 = mute system, 0 = normal operation
  15473. +#define ma_system_mute__a 45
  15474. +#define ma_system_mute__len 1
  15475. +#define ma_system_mute__mask 0x40
  15476. +#define ma_system_mute__shift 0x06
  15477. +#define ma_system_mute__reset 0x00
  15478. +//------------------------------------------------------thermal_compr_max_db---
  15479. +// audio limiter max thermal reduction
  15480. +#define ma_thermal_compr_max_db__a 46
  15481. +#define ma_thermal_compr_max_db__len 3
  15482. +#define ma_thermal_compr_max_db__mask 0x07
  15483. +#define ma_thermal_compr_max_db__shift 0x00
  15484. +#define ma_thermal_compr_max_db__reset 0x04
  15485. +//---------------------------------------------------------audio_proc_enable---
  15486. +// enable audio proc, bypass if not enabled
  15487. +#define ma_audio_proc_enable__a 53
  15488. +#define ma_audio_proc_enable__len 1
  15489. +#define ma_audio_proc_enable__mask 0x08
  15490. +#define ma_audio_proc_enable__shift 0x03
  15491. +#define ma_audio_proc_enable__reset 0x00
  15492. +//--------------------------------------------------------audio_proc_release---
  15493. +// 00:slow, 01:normal, 10:fast
  15494. +#define ma_audio_proc_release__a 53
  15495. +#define ma_audio_proc_release__len 2
  15496. +#define ma_audio_proc_release__mask 0x30
  15497. +#define ma_audio_proc_release__shift 0x04
  15498. +#define ma_audio_proc_release__reset 0x00
  15499. +//---------------------------------------------------------audio_proc_attack---
  15500. +// 00:slow, 01:normal, 10:fast
  15501. +#define ma_audio_proc_attack__a 53
  15502. +#define ma_audio_proc_attack__len 2
  15503. +#define ma_audio_proc_attack__mask 0xc0
  15504. +#define ma_audio_proc_attack__shift 0x06
  15505. +#define ma_audio_proc_attack__reset 0x00
  15506. +//----------------------------------------------------------------i2s_format---
  15507. +// i2s basic data format, 000 = std. i2s, 001 = left justified (default)
  15508. +#define ma_i2s_format__a 53
  15509. +#define ma_i2s_format__len 3
  15510. +#define ma_i2s_format__mask 0x07
  15511. +#define ma_i2s_format__shift 0x00
  15512. +#define ma_i2s_format__reset 0x01
  15513. +//--------------------------------------------------audio_proc_limiterenable---
  15514. +// 1: enable limiter, 0: disable limiter
  15515. +#define ma_audio_proc_limiterenable__a 54
  15516. +#define ma_audio_proc_limiterenable__len 1
  15517. +#define ma_audio_proc_limiterenable__mask 0x40
  15518. +#define ma_audio_proc_limiterenable__shift 0x06
  15519. +#define ma_audio_proc_limiterenable__reset 0x00
  15520. +//-----------------------------------------------------------audio_proc_mute---
  15521. +// 1: mute, 0: unmute
  15522. +#define ma_audio_proc_mute__a 54
  15523. +#define ma_audio_proc_mute__len 1
  15524. +#define ma_audio_proc_mute__mask 0x80
  15525. +#define ma_audio_proc_mute__shift 0x07
  15526. +#define ma_audio_proc_mute__reset 0x00
  15527. +//---------------------------------------------------------------i2s_sck_pol---
  15528. +// i2s sck polarity cfg. 0 = rising edge data change
  15529. +#define ma_i2s_sck_pol__a 54
  15530. +#define ma_i2s_sck_pol__len 1
  15531. +#define ma_i2s_sck_pol__mask 0x01
  15532. +#define ma_i2s_sck_pol__shift 0x00
  15533. +#define ma_i2s_sck_pol__reset 0x01
  15534. +//-------------------------------------------------------------i2s_framesize---
  15535. +// i2s word length. 00 = 32bit, 01 = 24bit
  15536. +#define ma_i2s_framesize__a 54
  15537. +#define ma_i2s_framesize__len 2
  15538. +#define ma_i2s_framesize__mask 0x18
  15539. +#define ma_i2s_framesize__shift 0x03
  15540. +#define ma_i2s_framesize__reset 0x00
  15541. +//----------------------------------------------------------------i2s_ws_pol---
  15542. +// i2s ws polarity. 0 = low first
  15543. +#define ma_i2s_ws_pol__a 54
  15544. +#define ma_i2s_ws_pol__len 1
  15545. +#define ma_i2s_ws_pol__mask 0x02
  15546. +#define ma_i2s_ws_pol__shift 0x01
  15547. +#define ma_i2s_ws_pol__reset 0x00
  15548. +//-----------------------------------------------------------------i2s_order---
  15549. +// i2s word bit order. 0 = msb first
  15550. +#define ma_i2s_order__a 54
  15551. +#define ma_i2s_order__len 1
  15552. +#define ma_i2s_order__mask 0x04
  15553. +#define ma_i2s_order__shift 0x02
  15554. +#define ma_i2s_order__reset 0x00
  15555. +//------------------------------------------------------------i2s_rightfirst---
  15556. +// i2s l/r word order; 0 = left first
  15557. +#define ma_i2s_rightfirst__a 54
  15558. +#define ma_i2s_rightfirst__len 1
  15559. +#define ma_i2s_rightfirst__mask 0x20
  15560. +#define ma_i2s_rightfirst__shift 0x05
  15561. +#define ma_i2s_rightfirst__reset 0x00
  15562. +//-------------------------------------------------------------vol_db_master---
  15563. +// master volume db
  15564. +#define ma_vol_db_master__a 64
  15565. +#define ma_vol_db_master__len 8
  15566. +#define ma_vol_db_master__mask 0xff
  15567. +#define ma_vol_db_master__shift 0x00
  15568. +#define ma_vol_db_master__reset 0x18
  15569. +//------------------------------------------------------------vol_lsb_master---
  15570. +// master volume lsb 1/4 steps
  15571. +#define ma_vol_lsb_master__a 65
  15572. +#define ma_vol_lsb_master__len 2
  15573. +#define ma_vol_lsb_master__mask 0x03
  15574. +#define ma_vol_lsb_master__shift 0x00
  15575. +#define ma_vol_lsb_master__reset 0x00
  15576. +//----------------------------------------------------------------vol_db_ch0---
  15577. +// volume channel 0
  15578. +#define ma_vol_db_ch0__a 66
  15579. +#define ma_vol_db_ch0__len 8
  15580. +#define ma_vol_db_ch0__mask 0xff
  15581. +#define ma_vol_db_ch0__shift 0x00
  15582. +#define ma_vol_db_ch0__reset 0x18
  15583. +//----------------------------------------------------------------vol_db_ch1---
  15584. +// volume channel 1
  15585. +#define ma_vol_db_ch1__a 67
  15586. +#define ma_vol_db_ch1__len 8
  15587. +#define ma_vol_db_ch1__mask 0xff
  15588. +#define ma_vol_db_ch1__shift 0x00
  15589. +#define ma_vol_db_ch1__reset 0x18
  15590. +//----------------------------------------------------------------vol_db_ch2---
  15591. +// volume channel 2
  15592. +#define ma_vol_db_ch2__a 68
  15593. +#define ma_vol_db_ch2__len 8
  15594. +#define ma_vol_db_ch2__mask 0xff
  15595. +#define ma_vol_db_ch2__shift 0x00
  15596. +#define ma_vol_db_ch2__reset 0x18
  15597. +//----------------------------------------------------------------vol_db_ch3---
  15598. +// volume channel 3
  15599. +#define ma_vol_db_ch3__a 69
  15600. +#define ma_vol_db_ch3__len 8
  15601. +#define ma_vol_db_ch3__mask 0xff
  15602. +#define ma_vol_db_ch3__shift 0x00
  15603. +#define ma_vol_db_ch3__reset 0x18
  15604. +//---------------------------------------------------------------vol_lsb_ch0---
  15605. +// volume channel 1 - 1/4 steps
  15606. +#define ma_vol_lsb_ch0__a 70
  15607. +#define ma_vol_lsb_ch0__len 2
  15608. +#define ma_vol_lsb_ch0__mask 0x03
  15609. +#define ma_vol_lsb_ch0__shift 0x00
  15610. +#define ma_vol_lsb_ch0__reset 0x00
  15611. +//---------------------------------------------------------------vol_lsb_ch1---
  15612. +// volume channel 3 - 1/4 steps
  15613. +#define ma_vol_lsb_ch1__a 70
  15614. +#define ma_vol_lsb_ch1__len 2
  15615. +#define ma_vol_lsb_ch1__mask 0x0c
  15616. +#define ma_vol_lsb_ch1__shift 0x02
  15617. +#define ma_vol_lsb_ch1__reset 0x00
  15618. +//---------------------------------------------------------------vol_lsb_ch2---
  15619. +// volume channel 2 - 1/4 steps
  15620. +#define ma_vol_lsb_ch2__a 70
  15621. +#define ma_vol_lsb_ch2__len 2
  15622. +#define ma_vol_lsb_ch2__mask 0x30
  15623. +#define ma_vol_lsb_ch2__shift 0x04
  15624. +#define ma_vol_lsb_ch2__reset 0x00
  15625. +//---------------------------------------------------------------vol_lsb_ch3---
  15626. +// volume channel 3 - 1/4 steps
  15627. +#define ma_vol_lsb_ch3__a 70
  15628. +#define ma_vol_lsb_ch3__len 2
  15629. +#define ma_vol_lsb_ch3__mask 0xc0
  15630. +#define ma_vol_lsb_ch3__shift 0x06
  15631. +#define ma_vol_lsb_ch3__reset 0x00
  15632. +//----------------------------------------------------------------thr_db_ch0---
  15633. +// thr_db channel 0
  15634. +#define ma_thr_db_ch0__a 71
  15635. +#define ma_thr_db_ch0__len 8
  15636. +#define ma_thr_db_ch0__mask 0xff
  15637. +#define ma_thr_db_ch0__shift 0x00
  15638. +#define ma_thr_db_ch0__reset 0x18
  15639. +//----------------------------------------------------------------thr_db_ch1---
  15640. +// thr db ch1
  15641. +#define ma_thr_db_ch1__a 72
  15642. +#define ma_thr_db_ch1__len 8
  15643. +#define ma_thr_db_ch1__mask 0xff
  15644. +#define ma_thr_db_ch1__shift 0x00
  15645. +#define ma_thr_db_ch1__reset 0x18
  15646. +//----------------------------------------------------------------thr_db_ch2---
  15647. +// thr db ch2
  15648. +#define ma_thr_db_ch2__a 73
  15649. +#define ma_thr_db_ch2__len 8
  15650. +#define ma_thr_db_ch2__mask 0xff
  15651. +#define ma_thr_db_ch2__shift 0x00
  15652. +#define ma_thr_db_ch2__reset 0x18
  15653. +//----------------------------------------------------------------thr_db_ch3---
  15654. +// threshold db ch3
  15655. +#define ma_thr_db_ch3__a 74
  15656. +#define ma_thr_db_ch3__len 8
  15657. +#define ma_thr_db_ch3__mask 0xff
  15658. +#define ma_thr_db_ch3__shift 0x00
  15659. +#define ma_thr_db_ch3__reset 0x18
  15660. +//---------------------------------------------------------------thr_lsb_ch0---
  15661. +// thr lsb ch0
  15662. +#define ma_thr_lsb_ch0__a 75
  15663. +#define ma_thr_lsb_ch0__len 2
  15664. +#define ma_thr_lsb_ch0__mask 0x03
  15665. +#define ma_thr_lsb_ch0__shift 0x00
  15666. +#define ma_thr_lsb_ch0__reset 0x00
  15667. +//---------------------------------------------------------------thr_lsb_ch1---
  15668. +// thr lsb ch1
  15669. +#define ma_thr_lsb_ch1__a 75
  15670. +#define ma_thr_lsb_ch1__len 2
  15671. +#define ma_thr_lsb_ch1__mask 0x0c
  15672. +#define ma_thr_lsb_ch1__shift 0x02
  15673. +#define ma_thr_lsb_ch1__reset 0x00
  15674. +//---------------------------------------------------------------thr_lsb_ch2---
  15675. +// thr lsb ch2 1/4 db step
  15676. +#define ma_thr_lsb_ch2__a 75
  15677. +#define ma_thr_lsb_ch2__len 2
  15678. +#define ma_thr_lsb_ch2__mask 0x30
  15679. +#define ma_thr_lsb_ch2__shift 0x04
  15680. +#define ma_thr_lsb_ch2__reset 0x00
  15681. +//---------------------------------------------------------------thr_lsb_ch3---
  15682. +// threshold lsb ch3
  15683. +#define ma_thr_lsb_ch3__a 75
  15684. +#define ma_thr_lsb_ch3__len 2
  15685. +#define ma_thr_lsb_ch3__mask 0xc0
  15686. +#define ma_thr_lsb_ch3__shift 0x06
  15687. +#define ma_thr_lsb_ch3__reset 0x00
  15688. +//-----------------------------------------------------------dcu_mon0.pm_mon---
  15689. +// power mode monitor channel 0
  15690. +#define ma_dcu_mon0__pm_mon__a 96
  15691. +#define ma_dcu_mon0__pm_mon__len 2
  15692. +#define ma_dcu_mon0__pm_mon__mask 0x03
  15693. +#define ma_dcu_mon0__pm_mon__shift 0x00
  15694. +#define ma_dcu_mon0__pm_mon__reset 0x00
  15695. +//-----------------------------------------------------dcu_mon0.freqmode_mon---
  15696. +// frequence mode monitor channel 0
  15697. +#define ma_dcu_mon0__freqmode_mon__a 96
  15698. +#define ma_dcu_mon0__freqmode_mon__len 3
  15699. +#define ma_dcu_mon0__freqmode_mon__mask 0x70
  15700. +#define ma_dcu_mon0__freqmode_mon__shift 0x04
  15701. +#define ma_dcu_mon0__freqmode_mon__reset 0x00
  15702. +//-------------------------------------------------------dcu_mon0.pps_passed---
  15703. +// dcu0 pps completion indicator
  15704. +#define ma_dcu_mon0__pps_passed__a 96
  15705. +#define ma_dcu_mon0__pps_passed__len 1
  15706. +#define ma_dcu_mon0__pps_passed__mask 0x80
  15707. +#define ma_dcu_mon0__pps_passed__shift 0x07
  15708. +#define ma_dcu_mon0__pps_passed__reset 0x00
  15709. +//----------------------------------------------------------dcu_mon0.ocp_mon---
  15710. +// ocp monitor channel 0
  15711. +#define ma_dcu_mon0__ocp_mon__a 97
  15712. +#define ma_dcu_mon0__ocp_mon__len 1
  15713. +#define ma_dcu_mon0__ocp_mon__mask 0x01
  15714. +#define ma_dcu_mon0__ocp_mon__shift 0x00
  15715. +#define ma_dcu_mon0__ocp_mon__reset 0x00
  15716. +//--------------------------------------------------------dcu_mon0.vcfly1_ok---
  15717. +// cfly1 protection monitor channel 0.
  15718. +#define ma_dcu_mon0__vcfly1_ok__a 97
  15719. +#define ma_dcu_mon0__vcfly1_ok__len 1
  15720. +#define ma_dcu_mon0__vcfly1_ok__mask 0x02
  15721. +#define ma_dcu_mon0__vcfly1_ok__shift 0x01
  15722. +#define ma_dcu_mon0__vcfly1_ok__reset 0x00
  15723. +//--------------------------------------------------------dcu_mon0.vcfly2_ok---
  15724. +// cfly2 protection monitor channel 0.
  15725. +#define ma_dcu_mon0__vcfly2_ok__a 97
  15726. +#define ma_dcu_mon0__vcfly2_ok__len 1
  15727. +#define ma_dcu_mon0__vcfly2_ok__mask 0x04
  15728. +#define ma_dcu_mon0__vcfly2_ok__shift 0x02
  15729. +#define ma_dcu_mon0__vcfly2_ok__reset 0x00
  15730. +//----------------------------------------------------------dcu_mon0.pvdd_ok---
  15731. +// dcu0 pvdd monitor
  15732. +#define ma_dcu_mon0__pvdd_ok__a 97
  15733. +#define ma_dcu_mon0__pvdd_ok__len 1
  15734. +#define ma_dcu_mon0__pvdd_ok__mask 0x08
  15735. +#define ma_dcu_mon0__pvdd_ok__shift 0x03
  15736. +#define ma_dcu_mon0__pvdd_ok__reset 0x00
  15737. +//-----------------------------------------------------------dcu_mon0.vdd_ok---
  15738. +// dcu0 vdd monitor
  15739. +#define ma_dcu_mon0__vdd_ok__a 97
  15740. +#define ma_dcu_mon0__vdd_ok__len 1
  15741. +#define ma_dcu_mon0__vdd_ok__mask 0x10
  15742. +#define ma_dcu_mon0__vdd_ok__shift 0x04
  15743. +#define ma_dcu_mon0__vdd_ok__reset 0x00
  15744. +//-------------------------------------------------------------dcu_mon0.mute---
  15745. +// dcu0 mute monitor
  15746. +#define ma_dcu_mon0__mute__a 97
  15747. +#define ma_dcu_mon0__mute__len 1
  15748. +#define ma_dcu_mon0__mute__mask 0x20
  15749. +#define ma_dcu_mon0__mute__shift 0x05
  15750. +#define ma_dcu_mon0__mute__reset 0x00
  15751. +//------------------------------------------------------------dcu_mon0.m_mon---
  15752. +// m sense monitor channel 0
  15753. +#define ma_dcu_mon0__m_mon__a 98
  15754. +#define ma_dcu_mon0__m_mon__len 8
  15755. +#define ma_dcu_mon0__m_mon__mask 0xff
  15756. +#define ma_dcu_mon0__m_mon__shift 0x00
  15757. +#define ma_dcu_mon0__m_mon__reset 0x00
  15758. +//-----------------------------------------------------------dcu_mon1.pm_mon---
  15759. +// power mode monitor channel 1
  15760. +#define ma_dcu_mon1__pm_mon__a 100
  15761. +#define ma_dcu_mon1__pm_mon__len 2
  15762. +#define ma_dcu_mon1__pm_mon__mask 0x03
  15763. +#define ma_dcu_mon1__pm_mon__shift 0x00
  15764. +#define ma_dcu_mon1__pm_mon__reset 0x00
  15765. +//-----------------------------------------------------dcu_mon1.freqmode_mon---
  15766. +// frequence mode monitor channel 1
  15767. +#define ma_dcu_mon1__freqmode_mon__a 100
  15768. +#define ma_dcu_mon1__freqmode_mon__len 3
  15769. +#define ma_dcu_mon1__freqmode_mon__mask 0x70
  15770. +#define ma_dcu_mon1__freqmode_mon__shift 0x04
  15771. +#define ma_dcu_mon1__freqmode_mon__reset 0x00
  15772. +//-------------------------------------------------------dcu_mon1.pps_passed---
  15773. +// dcu1 pps completion indicator
  15774. +#define ma_dcu_mon1__pps_passed__a 100
  15775. +#define ma_dcu_mon1__pps_passed__len 1
  15776. +#define ma_dcu_mon1__pps_passed__mask 0x80
  15777. +#define ma_dcu_mon1__pps_passed__shift 0x07
  15778. +#define ma_dcu_mon1__pps_passed__reset 0x00
  15779. +//----------------------------------------------------------dcu_mon1.ocp_mon---
  15780. +// ocp monitor channel 1
  15781. +#define ma_dcu_mon1__ocp_mon__a 101
  15782. +#define ma_dcu_mon1__ocp_mon__len 1
  15783. +#define ma_dcu_mon1__ocp_mon__mask 0x01
  15784. +#define ma_dcu_mon1__ocp_mon__shift 0x00
  15785. +#define ma_dcu_mon1__ocp_mon__reset 0x00
  15786. +//--------------------------------------------------------dcu_mon1.vcfly1_ok---
  15787. +// cfly1 protcetion monitor channel 1
  15788. +#define ma_dcu_mon1__vcfly1_ok__a 101
  15789. +#define ma_dcu_mon1__vcfly1_ok__len 1
  15790. +#define ma_dcu_mon1__vcfly1_ok__mask 0x02
  15791. +#define ma_dcu_mon1__vcfly1_ok__shift 0x01
  15792. +#define ma_dcu_mon1__vcfly1_ok__reset 0x00
  15793. +//--------------------------------------------------------dcu_mon1.vcfly2_ok---
  15794. +// cfly2 protection monitor channel 1
  15795. +#define ma_dcu_mon1__vcfly2_ok__a 101
  15796. +#define ma_dcu_mon1__vcfly2_ok__len 1
  15797. +#define ma_dcu_mon1__vcfly2_ok__mask 0x04
  15798. +#define ma_dcu_mon1__vcfly2_ok__shift 0x02
  15799. +#define ma_dcu_mon1__vcfly2_ok__reset 0x00
  15800. +//----------------------------------------------------------dcu_mon1.pvdd_ok---
  15801. +// dcu1 pvdd monitor
  15802. +#define ma_dcu_mon1__pvdd_ok__a 101
  15803. +#define ma_dcu_mon1__pvdd_ok__len 1
  15804. +#define ma_dcu_mon1__pvdd_ok__mask 0x08
  15805. +#define ma_dcu_mon1__pvdd_ok__shift 0x03
  15806. +#define ma_dcu_mon1__pvdd_ok__reset 0x00
  15807. +//-----------------------------------------------------------dcu_mon1.vdd_ok---
  15808. +// dcu1 vdd monitor
  15809. +#define ma_dcu_mon1__vdd_ok__a 101
  15810. +#define ma_dcu_mon1__vdd_ok__len 1
  15811. +#define ma_dcu_mon1__vdd_ok__mask 0x10
  15812. +#define ma_dcu_mon1__vdd_ok__shift 0x04
  15813. +#define ma_dcu_mon1__vdd_ok__reset 0x00
  15814. +//-------------------------------------------------------------dcu_mon1.mute---
  15815. +// dcu1 mute monitor
  15816. +#define ma_dcu_mon1__mute__a 101
  15817. +#define ma_dcu_mon1__mute__len 1
  15818. +#define ma_dcu_mon1__mute__mask 0x20
  15819. +#define ma_dcu_mon1__mute__shift 0x05
  15820. +#define ma_dcu_mon1__mute__reset 0x00
  15821. +//------------------------------------------------------------dcu_mon1.m_mon---
  15822. +// m sense monitor channel 1
  15823. +#define ma_dcu_mon1__m_mon__a 102
  15824. +#define ma_dcu_mon1__m_mon__len 8
  15825. +#define ma_dcu_mon1__m_mon__mask 0xff
  15826. +#define ma_dcu_mon1__m_mon__shift 0x00
  15827. +#define ma_dcu_mon1__m_mon__reset 0x00
  15828. +//--------------------------------------------------------dcu_mon0.sw_enable---
  15829. +// dcu0 switch enable monitor
  15830. +#define ma_dcu_mon0__sw_enable__a 104
  15831. +#define ma_dcu_mon0__sw_enable__len 1
  15832. +#define ma_dcu_mon0__sw_enable__mask 0x40
  15833. +#define ma_dcu_mon0__sw_enable__shift 0x06
  15834. +#define ma_dcu_mon0__sw_enable__reset 0x00
  15835. +//--------------------------------------------------------dcu_mon1.sw_enable---
  15836. +// dcu1 switch enable monitor
  15837. +#define ma_dcu_mon1__sw_enable__a 104
  15838. +#define ma_dcu_mon1__sw_enable__len 1
  15839. +#define ma_dcu_mon1__sw_enable__mask 0x80
  15840. +#define ma_dcu_mon1__sw_enable__shift 0x07
  15841. +#define ma_dcu_mon1__sw_enable__reset 0x00
  15842. +//------------------------------------------------------------hvboot0_ok_mon---
  15843. +// hvboot0_ok for test/debug
  15844. +#define ma_hvboot0_ok_mon__a 105
  15845. +#define ma_hvboot0_ok_mon__len 1
  15846. +#define ma_hvboot0_ok_mon__mask 0x40
  15847. +#define ma_hvboot0_ok_mon__shift 0x06
  15848. +#define ma_hvboot0_ok_mon__reset 0x00
  15849. +//------------------------------------------------------------hvboot1_ok_mon---
  15850. +// hvboot1_ok for test/debug
  15851. +#define ma_hvboot1_ok_mon__a 105
  15852. +#define ma_hvboot1_ok_mon__len 1
  15853. +#define ma_hvboot1_ok_mon__mask 0x80
  15854. +#define ma_hvboot1_ok_mon__shift 0x07
  15855. +#define ma_hvboot1_ok_mon__reset 0x00
  15856. +//-----------------------------------------------------------------error_acc---
  15857. +// accumulated errors, at and after triggering
  15858. +#define ma_error_acc__a 109
  15859. +#define ma_error_acc__len 8
  15860. +#define ma_error_acc__mask 0xff
  15861. +#define ma_error_acc__shift 0x00
  15862. +#define ma_error_acc__reset 0x00
  15863. +//-------------------------------------------------------------i2s_data_rate---
  15864. +// detected i2s data rate: 00/01/10 = x1/x2/x4
  15865. +#define ma_i2s_data_rate__a 116
  15866. +#define ma_i2s_data_rate__len 2
  15867. +#define ma_i2s_data_rate__mask 0x03
  15868. +#define ma_i2s_data_rate__shift 0x00
  15869. +#define ma_i2s_data_rate__reset 0x00
  15870. +//---------------------------------------------------------audio_in_mode_mon---
  15871. +// audio input mode monitor
  15872. +#define ma_audio_in_mode_mon__a 116
  15873. +#define ma_audio_in_mode_mon__len 3
  15874. +#define ma_audio_in_mode_mon__mask 0x1c
  15875. +#define ma_audio_in_mode_mon__shift 0x02
  15876. +#define ma_audio_in_mode_mon__reset 0x00
  15877. +//------------------------------------------------------------------msel_mon---
  15878. +// msel[2:0] monitor register
  15879. +#define ma_msel_mon__a 117
  15880. +#define ma_msel_mon__len 3
  15881. +#define ma_msel_mon__mask 0x07
  15882. +#define ma_msel_mon__shift 0x00
  15883. +#define ma_msel_mon__reset 0x00
  15884. +//---------------------------------------------------------------------error---
  15885. +// current error flag monitor reg - for app. ctrl.
  15886. +#define ma_error__a 124
  15887. +#define ma_error__len 8
  15888. +#define ma_error__mask 0xff
  15889. +#define ma_error__shift 0x00
  15890. +#define ma_error__reset 0x00
  15891. +//----------------------------------------------------audio_proc_limiter_mon---
  15892. +// b7-b4: channel 3-0 limiter active
  15893. +#define ma_audio_proc_limiter_mon__a 126
  15894. +#define ma_audio_proc_limiter_mon__len 4
  15895. +#define ma_audio_proc_limiter_mon__mask 0xf0
  15896. +#define ma_audio_proc_limiter_mon__shift 0x04
  15897. +#define ma_audio_proc_limiter_mon__reset 0x00
  15898. +//-------------------------------------------------------audio_proc_clip_mon---
  15899. +// b3-b0: channel 3-0 clipping monitor
  15900. +#define ma_audio_proc_clip_mon__a 126
  15901. +#define ma_audio_proc_clip_mon__len 4
  15902. +#define ma_audio_proc_clip_mon__mask 0x0f
  15903. +#define ma_audio_proc_clip_mon__shift 0x00
  15904. +#define ma_audio_proc_clip_mon__reset 0x00
  15905. +#endif
  15906. +
  15907. +#define SOC_ENUM_ERR(xname, xenum)\
  15908. +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
  15909. + .access = SNDRV_CTL_ELEM_ACCESS_READ,\
  15910. + .info = snd_soc_info_enum_double,\
  15911. + .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double,\
  15912. + .private_value = (unsigned long)&(xenum) }
  15913. +
  15914. +static struct i2c_client *i2c;
  15915. +
  15916. +struct ma120x0p_priv {
  15917. + struct regmap *regmap;
  15918. + int mclk_div;
  15919. + struct snd_soc_component *component;
  15920. + struct gpio_desc *enable_gpio;
  15921. + struct gpio_desc *mute_gpio;
  15922. + struct gpio_desc *booster_gpio;
  15923. + struct gpio_desc *error_gpio;
  15924. +};
  15925. +
  15926. +static struct ma120x0p_priv *priv_data;
  15927. +
  15928. +//Used to share the IRQ number within this file
  15929. +static unsigned int irqNumber;
  15930. +
  15931. +// Function prototype for the custom IRQ handler function
  15932. +static irqreturn_t ma120x0p_irq_handler(int irq, void *data);
  15933. +
  15934. +//Alsa Controls
  15935. +static const char * const limenable_text[] = {"Bypassed", "Enabled"};
  15936. +static const char * const limatack_text[] = {"Slow", "Normal", "Fast"};
  15937. +static const char * const limrelease_text[] = {"Slow", "Normal", "Fast"};
  15938. +
  15939. +static const char * const err_flycap_text[] = {"Ok", "Error"};
  15940. +static const char * const err_overcurr_text[] = {"Ok", "Error"};
  15941. +static const char * const err_pllerr_text[] = {"Ok", "Error"};
  15942. +static const char * const err_pvddunder_text[] = {"Ok", "Error"};
  15943. +static const char * const err_overtempw_text[] = {"Ok", "Error"};
  15944. +static const char * const err_overtempe_text[] = {"Ok", "Error"};
  15945. +static const char * const err_pinlowimp_text[] = {"Ok", "Error"};
  15946. +static const char * const err_dcprot_text[] = {"Ok", "Error"};
  15947. +
  15948. +static const char * const pwr_mode_prof_text[] = {"PMF0", "PMF1", "PMF2",
  15949. +"PMF3", "PMF4"};
  15950. +
  15951. +static const struct soc_enum lim_enable_ctrl =
  15952. + SOC_ENUM_SINGLE(ma_audio_proc_limiterenable__a,
  15953. + ma_audio_proc_limiterenable__shift,
  15954. + ma_audio_proc_limiterenable__len + 1,
  15955. + limenable_text);
  15956. +static const struct soc_enum limatack_ctrl =
  15957. + SOC_ENUM_SINGLE(ma_audio_proc_attack__a,
  15958. + ma_audio_proc_attack__shift,
  15959. + ma_audio_proc_attack__len + 1,
  15960. + limatack_text);
  15961. +static const struct soc_enum limrelease_ctrl =
  15962. + SOC_ENUM_SINGLE(ma_audio_proc_release__a,
  15963. + ma_audio_proc_release__shift,
  15964. + ma_audio_proc_release__len + 1,
  15965. + limrelease_text);
  15966. +static const struct soc_enum err_flycap_ctrl =
  15967. + SOC_ENUM_SINGLE(ma_error__a, 0, 3, err_flycap_text);
  15968. +static const struct soc_enum err_overcurr_ctrl =
  15969. + SOC_ENUM_SINGLE(ma_error__a, 1, 3, err_overcurr_text);
  15970. +static const struct soc_enum err_pllerr_ctrl =
  15971. + SOC_ENUM_SINGLE(ma_error__a, 2, 3, err_pllerr_text);
  15972. +static const struct soc_enum err_pvddunder_ctrl =
  15973. + SOC_ENUM_SINGLE(ma_error__a, 3, 3, err_pvddunder_text);
  15974. +static const struct soc_enum err_overtempw_ctrl =
  15975. + SOC_ENUM_SINGLE(ma_error__a, 4, 3, err_overtempw_text);
  15976. +static const struct soc_enum err_overtempe_ctrl =
  15977. + SOC_ENUM_SINGLE(ma_error__a, 5, 3, err_overtempe_text);
  15978. +static const struct soc_enum err_pinlowimp_ctrl =
  15979. + SOC_ENUM_SINGLE(ma_error__a, 6, 3, err_pinlowimp_text);
  15980. +static const struct soc_enum err_dcprot_ctrl =
  15981. + SOC_ENUM_SINGLE(ma_error__a, 7, 3, err_dcprot_text);
  15982. +static const struct soc_enum pwr_mode_prof_ctrl =
  15983. + SOC_ENUM_SINGLE(ma_pmprofile__a, ma_pmprofile__shift, 5,
  15984. + pwr_mode_prof_text);
  15985. +
  15986. +static const char * const pwr_mode_texts[] = {
  15987. + "Dynamic power mode",
  15988. + "Power mode 1",
  15989. + "Power mode 2",
  15990. + "Power mode 3",
  15991. + };
  15992. +
  15993. +static const int pwr_mode_values[] = {
  15994. + 0x10,
  15995. + 0x50,
  15996. + 0x60,
  15997. + 0x70,
  15998. + };
  15999. +
  16000. +static SOC_VALUE_ENUM_SINGLE_DECL(pwr_mode_ctrl,
  16001. + ma_pm_man__a, 0, 0x70,
  16002. + pwr_mode_texts,
  16003. + pwr_mode_values);
  16004. +
  16005. +static const DECLARE_TLV_DB_SCALE(ma120x0p_vol_tlv, -14400, 100, 0);
  16006. +static const DECLARE_TLV_DB_SCALE(ma120x0p_lim_tlv, -5000, 100, 0);
  16007. +static const DECLARE_TLV_DB_SCALE(ma120x0p_lr_tlv, -5000, 100, 0);
  16008. +
  16009. +static const struct snd_kcontrol_new ma120x0p_snd_controls[] = {
  16010. + //Master Volume
  16011. + SOC_SINGLE_RANGE_TLV("A.Mstr Vol Volume",
  16012. + ma_vol_db_master__a, 0, 0x18, 0xa8, 1, ma120x0p_vol_tlv),
  16013. +
  16014. + //L-R Volume ch0
  16015. + SOC_SINGLE_RANGE_TLV("B.L Vol Volume",
  16016. + ma_vol_db_ch0__a, 0, 0x18, 0x4a, 1, ma120x0p_lr_tlv),
  16017. + SOC_SINGLE_RANGE_TLV("C.R Vol Volume",
  16018. + ma_vol_db_ch1__a, 0, 0x18, 0x4a, 1, ma120x0p_lr_tlv),
  16019. +
  16020. + //L-R Limiter Threshold ch0-ch1
  16021. + SOC_DOUBLE_R_RANGE_TLV("D.Lim thresh Volume",
  16022. + ma_thr_db_ch0__a, ma_thr_db_ch1__a, 0, 0x0e, 0x4a, 1,
  16023. + ma120x0p_lim_tlv),
  16024. +
  16025. + //Enum Switches/Selectors
  16026. + //SOC_ENUM("E.AudioProc Mute", audioproc_mute_ctrl),
  16027. + SOC_ENUM("F.Limiter Enable", lim_enable_ctrl),
  16028. + SOC_ENUM("G.Limiter Attck", limatack_ctrl),
  16029. + SOC_ENUM("H.Limiter Rls", limrelease_ctrl),
  16030. +
  16031. + //Enum Error Monitor (read-only)
  16032. + SOC_ENUM_ERR("I.Err flycap", err_flycap_ctrl),
  16033. + SOC_ENUM_ERR("J.Err overcurr", err_overcurr_ctrl),
  16034. + SOC_ENUM_ERR("K.Err pllerr", err_pllerr_ctrl),
  16035. + SOC_ENUM_ERR("L.Err pvddunder", err_pvddunder_ctrl),
  16036. + SOC_ENUM_ERR("M.Err overtempw", err_overtempw_ctrl),
  16037. + SOC_ENUM_ERR("N.Err overtempe", err_overtempe_ctrl),
  16038. + SOC_ENUM_ERR("O.Err pinlowimp", err_pinlowimp_ctrl),
  16039. + SOC_ENUM_ERR("P.Err dcprot", err_dcprot_ctrl),
  16040. +
  16041. + //Power modes profiles
  16042. + SOC_ENUM("Q.PM Prof", pwr_mode_prof_ctrl),
  16043. +
  16044. + // Power mode selection (Dynamic,1,2,3)
  16045. + SOC_ENUM("R.Power Mode", pwr_mode_ctrl),
  16046. +};
  16047. +
  16048. +//Machine Driver
  16049. +static int ma120x0p_hw_params(struct snd_pcm_substream *substream,
  16050. + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
  16051. +{
  16052. + u16 blen = 0x00;
  16053. +
  16054. + struct snd_soc_component *component = dai->component;
  16055. +
  16056. + priv_data->component = component;
  16057. +
  16058. + switch (params_format(params)) {
  16059. + case SNDRV_PCM_FORMAT_S16_LE:
  16060. + blen = 0x10;
  16061. + break;
  16062. + case SNDRV_PCM_FORMAT_S24_LE:
  16063. + blen = 0x00;
  16064. + break;
  16065. + case SNDRV_PCM_FORMAT_S32_LE:
  16066. + blen = 0x00;
  16067. + break;
  16068. + default:
  16069. + dev_err(dai->dev, "Unsupported word length: %u\n",
  16070. + params_format(params));
  16071. + return -EINVAL;
  16072. + }
  16073. +
  16074. + // set word length
  16075. + snd_soc_component_update_bits(component, ma_i2s_framesize__a,
  16076. + ma_i2s_framesize__mask, blen);
  16077. +
  16078. + return 0;
  16079. +}
  16080. +
  16081. +static int ma120x0p_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
  16082. +{
  16083. + int val = 0;
  16084. +
  16085. + struct ma120x0p_priv *ma120x0p;
  16086. +
  16087. + struct snd_soc_component *component = dai->component;
  16088. +
  16089. + ma120x0p = snd_soc_component_get_drvdata(component);
  16090. +
  16091. + if (mute)
  16092. + val = 0;
  16093. + else
  16094. + val = 1;
  16095. +
  16096. + gpiod_set_value_cansleep(priv_data->mute_gpio, val);
  16097. +
  16098. + return 0;
  16099. +}
  16100. +
  16101. +static const struct snd_soc_dai_ops ma120x0p_dai_ops = {
  16102. + .hw_params = ma120x0p_hw_params,
  16103. + .mute_stream = ma120x0p_mute_stream,
  16104. +};
  16105. +
  16106. +static struct snd_soc_dai_driver ma120x0p_dai = {
  16107. + .name = "ma120x0p-amp",
  16108. + .playback = {
  16109. + .stream_name = "Playback",
  16110. + .channels_min = 2,
  16111. + .channels_max = 2,
  16112. + .rates = SNDRV_PCM_RATE_CONTINUOUS,
  16113. + .rate_min = 44100,
  16114. + .rate_max = 192000,
  16115. + .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE
  16116. + },
  16117. + .ops = &ma120x0p_dai_ops,
  16118. +};
  16119. +
  16120. +//Codec Driver
  16121. +static int ma120x0p_clear_err(struct snd_soc_component *component)
  16122. +{
  16123. + int ret = 0;
  16124. +
  16125. + struct ma120x0p_priv *ma120x0p;
  16126. +
  16127. + ma120x0p = snd_soc_component_get_drvdata(component);
  16128. +
  16129. + ret = snd_soc_component_update_bits(component,
  16130. + ma_eh_clear__a, ma_eh_clear__mask, 0x00);
  16131. + if (ret < 0)
  16132. + return ret;
  16133. +
  16134. + ret = snd_soc_component_update_bits(component,
  16135. + ma_eh_clear__a, ma_eh_clear__mask, 0x04);
  16136. + if (ret < 0)
  16137. + return ret;
  16138. +
  16139. + ret = snd_soc_component_update_bits(component,
  16140. + ma_eh_clear__a, ma_eh_clear__mask, 0x00);
  16141. + if (ret < 0)
  16142. + return ret;
  16143. +
  16144. + return 0;
  16145. +}
  16146. +
  16147. +static void ma120x0p_remove(struct snd_soc_component *component)
  16148. +{
  16149. + struct ma120x0p_priv *ma120x0p;
  16150. +
  16151. + ma120x0p = snd_soc_component_get_drvdata(component);
  16152. +}
  16153. +
  16154. +static int ma120x0p_probe(struct snd_soc_component *component)
  16155. +{
  16156. + struct ma120x0p_priv *ma120x0p;
  16157. +
  16158. + int ret = 0;
  16159. +
  16160. + i2c = container_of(component->dev, struct i2c_client, dev);
  16161. +
  16162. + ma120x0p = snd_soc_component_get_drvdata(component);
  16163. +
  16164. + //Reset error
  16165. + ma120x0p_clear_err(component);
  16166. + if (ret < 0)
  16167. + return ret;
  16168. +
  16169. + // set serial audio format I2S and enable audio processor
  16170. + ret = snd_soc_component_write(component, ma_i2s_format__a, 0x08);
  16171. + if (ret < 0)
  16172. + return ret;
  16173. +
  16174. + // Enable audio limiter
  16175. + ret = snd_soc_component_update_bits(component,
  16176. + ma_audio_proc_limiterenable__a,
  16177. + ma_audio_proc_limiterenable__mask, 0x40);
  16178. + if (ret < 0)
  16179. + return ret;
  16180. +
  16181. + // Set lim attack to fast
  16182. + ret = snd_soc_component_update_bits(component,
  16183. + ma_audio_proc_attack__a, ma_audio_proc_attack__mask, 0x80);
  16184. + if (ret < 0)
  16185. + return ret;
  16186. +
  16187. + // Set lim attack to low
  16188. + ret = snd_soc_component_update_bits(component,
  16189. + ma_audio_proc_release__a, ma_audio_proc_release__mask, 0x00);
  16190. + if (ret < 0)
  16191. + return ret;
  16192. +
  16193. + // set volume to 0dB
  16194. + ret = snd_soc_component_write(component, ma_vol_db_master__a, 0x18);
  16195. + if (ret < 0)
  16196. + return ret;
  16197. +
  16198. + // set ch0 lim thresh to -15dB
  16199. + ret = snd_soc_component_write(component, ma_thr_db_ch0__a, 0x27);
  16200. + if (ret < 0)
  16201. + return ret;
  16202. +
  16203. + // set ch1 lim thresh to -15dB
  16204. + ret = snd_soc_component_write(component, ma_thr_db_ch1__a, 0x27);
  16205. + if (ret < 0)
  16206. + return ret;
  16207. +
  16208. + //Check for errors
  16209. + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x00, 0);
  16210. + if (ret < 0)
  16211. + return ret;
  16212. + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x01, 0);
  16213. + if (ret < 0)
  16214. + return ret;
  16215. + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x02, 0);
  16216. + if (ret < 0)
  16217. + return ret;
  16218. + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x08, 0);
  16219. + if (ret < 0)
  16220. + return ret;
  16221. + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x10, 0);
  16222. + if (ret < 0)
  16223. + return ret;
  16224. + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x20, 0);
  16225. + if (ret < 0)
  16226. + return ret;
  16227. + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x40, 0);
  16228. + if (ret < 0)
  16229. + return ret;
  16230. + ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x80, 0);
  16231. + if (ret < 0)
  16232. + return ret;
  16233. +
  16234. + return 0;
  16235. +}
  16236. +
  16237. +static int ma120x0p_set_bias_level(struct snd_soc_component *component,
  16238. + enum snd_soc_bias_level level)
  16239. +{
  16240. + int ret = 0;
  16241. +
  16242. + struct ma120x0p_priv *ma120x0p;
  16243. +
  16244. + ma120x0p = snd_soc_component_get_drvdata(component);
  16245. +
  16246. + switch (level) {
  16247. + case SND_SOC_BIAS_ON:
  16248. + break;
  16249. +
  16250. + case SND_SOC_BIAS_PREPARE:
  16251. + break;
  16252. +
  16253. + case SND_SOC_BIAS_STANDBY:
  16254. + ret = gpiod_get_value_cansleep(priv_data->enable_gpio);
  16255. + if (ret != 0) {
  16256. + dev_err(component->dev, "Device ma120x0p disabled in STANDBY BIAS: %d\n",
  16257. + ret);
  16258. + return ret;
  16259. + }
  16260. + break;
  16261. +
  16262. + case SND_SOC_BIAS_OFF:
  16263. + break;
  16264. + }
  16265. +
  16266. + return 0;
  16267. +}
  16268. +
  16269. +static const struct snd_soc_dapm_widget ma120x0p_dapm_widgets[] = {
  16270. + SND_SOC_DAPM_OUTPUT("OUT_A"),
  16271. + SND_SOC_DAPM_OUTPUT("OUT_B"),
  16272. +};
  16273. +
  16274. +static const struct snd_soc_dapm_route ma120x0p_dapm_routes[] = {
  16275. + { "OUT_B", NULL, "Playback" },
  16276. + { "OUT_A", NULL, "Playback" },
  16277. +};
  16278. +
  16279. +static const struct snd_soc_component_driver ma120x0p_component_driver = {
  16280. + .probe = ma120x0p_probe,
  16281. + .remove = ma120x0p_remove,
  16282. + .set_bias_level = ma120x0p_set_bias_level,
  16283. + .dapm_widgets = ma120x0p_dapm_widgets,
  16284. + .num_dapm_widgets = ARRAY_SIZE(ma120x0p_dapm_widgets),
  16285. + .dapm_routes = ma120x0p_dapm_routes,
  16286. + .num_dapm_routes = ARRAY_SIZE(ma120x0p_dapm_routes),
  16287. + .controls = ma120x0p_snd_controls,
  16288. + .num_controls = ARRAY_SIZE(ma120x0p_snd_controls),
  16289. + .use_pmdown_time = 1,
  16290. + .endianness = 1,
  16291. +};
  16292. +
  16293. +//I2C Driver
  16294. +static const struct reg_default ma120x0p_reg_defaults[] = {
  16295. + { 0x01, 0x3c },
  16296. +};
  16297. +
  16298. +static bool ma120x0p_reg_volatile(struct device *dev, unsigned int reg)
  16299. +{
  16300. + switch (reg) {
  16301. + case ma_error__a:
  16302. + return true;
  16303. + default:
  16304. + return false;
  16305. + }
  16306. +}
  16307. +
  16308. +static const struct of_device_id ma120x0p_of_match[] = {
  16309. + { .compatible = "ma,ma120x0p", },
  16310. + { }
  16311. +};
  16312. +
  16313. +MODULE_DEVICE_TABLE(of, ma120x0p_of_match);
  16314. +
  16315. +static struct regmap_config ma120x0p_regmap_config = {
  16316. + .reg_bits = 8,
  16317. + .val_bits = 8,
  16318. +
  16319. + .max_register = 255,
  16320. + .volatile_reg = ma120x0p_reg_volatile,
  16321. +
  16322. + .cache_type = REGCACHE_RBTREE,
  16323. + .reg_defaults = ma120x0p_reg_defaults,
  16324. + .num_reg_defaults = ARRAY_SIZE(ma120x0p_reg_defaults),
  16325. +};
  16326. +
  16327. +static int ma120x0p_i2c_probe(struct i2c_client *i2c)
  16328. +{
  16329. + int ret;
  16330. +
  16331. + priv_data = devm_kzalloc(&i2c->dev, sizeof(*priv_data), GFP_KERNEL);
  16332. + if (!priv_data)
  16333. + return -ENOMEM;
  16334. + i2c_set_clientdata(i2c, priv_data);
  16335. +
  16336. + priv_data->regmap = devm_regmap_init_i2c(i2c, &ma120x0p_regmap_config);
  16337. + if (IS_ERR(priv_data->regmap)) {
  16338. + ret = PTR_ERR(priv_data->regmap);
  16339. + return ret;
  16340. + }
  16341. +
  16342. + //Startup sequence
  16343. +
  16344. + //Make sure the device is muted
  16345. + priv_data->mute_gpio = devm_gpiod_get_optional(&i2c->dev, "mute_gp",
  16346. + GPIOD_OUT_LOW);
  16347. + if (IS_ERR(priv_data->mute_gpio)) {
  16348. + ret = PTR_ERR(priv_data->mute_gpio);
  16349. + dev_err(&i2c->dev, "Failed to get mute gpio line: %d\n", ret);
  16350. + return ret;
  16351. + }
  16352. + msleep(50);
  16353. +
  16354. +// MA120xx0P devices are usually powered by an integrated boost converter.
  16355. +// An option GPIO control line is provided to enable the booster properly and
  16356. +// in sync with the enable and mute GPIO lines.
  16357. + priv_data->booster_gpio = devm_gpiod_get_optional(&i2c->dev,
  16358. + "booster_gp", GPIOD_OUT_LOW);
  16359. + if (IS_ERR(priv_data->booster_gpio)) {
  16360. + ret = PTR_ERR(priv_data->booster_gpio);
  16361. + dev_err(&i2c->dev,
  16362. + "Failed to get booster enable gpio line: %d\n", ret);
  16363. + return ret;
  16364. + }
  16365. + msleep(50);
  16366. +
  16367. + //Enable booster and wait 200ms until stable PVDD
  16368. + gpiod_set_value_cansleep(priv_data->booster_gpio, 1);
  16369. + msleep(200);
  16370. +
  16371. + //Enable ma120x0pp
  16372. + priv_data->enable_gpio = devm_gpiod_get_optional(&i2c->dev,
  16373. + "enable_gp", GPIOD_OUT_LOW);
  16374. + if (IS_ERR(priv_data->enable_gpio)) {
  16375. + ret = PTR_ERR(priv_data->enable_gpio);
  16376. + dev_err(&i2c->dev,
  16377. + "Failed to get ma120x0p enable gpio line: %d\n", ret);
  16378. + return ret;
  16379. + }
  16380. + msleep(50);
  16381. +
  16382. + //Optional use of ma120x0pp error line as an interrupt trigger to
  16383. + //platform GPIO.
  16384. + //Get error input gpio ma120x0p
  16385. + priv_data->error_gpio = devm_gpiod_get_optional(&i2c->dev,
  16386. + "error_gp", GPIOD_IN);
  16387. + if (IS_ERR(priv_data->error_gpio)) {
  16388. + ret = PTR_ERR(priv_data->error_gpio);
  16389. + dev_err(&i2c->dev,
  16390. + "Failed to get ma120x0p error gpio line: %d\n", ret);
  16391. + return ret;
  16392. + }
  16393. +
  16394. + if (priv_data->error_gpio != NULL) {
  16395. + irqNumber = gpiod_to_irq(priv_data->error_gpio);
  16396. +
  16397. + ret = devm_request_threaded_irq(&i2c->dev,
  16398. + irqNumber, ma120x0p_irq_handler,
  16399. + NULL, IRQF_TRIGGER_FALLING,
  16400. + "ma120x0p", priv_data);
  16401. + if (ret != 0)
  16402. + dev_warn(&i2c->dev, "Failed to request IRQ: %d\n",
  16403. + ret);
  16404. + }
  16405. +
  16406. + ret = devm_snd_soc_register_component(&i2c->dev,
  16407. + &ma120x0p_component_driver, &ma120x0p_dai, 1);
  16408. +
  16409. + return ret;
  16410. +}
  16411. +
  16412. +static irqreturn_t ma120x0p_irq_handler(int irq, void *data)
  16413. +{
  16414. + gpiod_set_value_cansleep(priv_data->mute_gpio, 0);
  16415. + gpiod_set_value_cansleep(priv_data->enable_gpio, 1);
  16416. + return IRQ_HANDLED;
  16417. +}
  16418. +
  16419. +static void ma120x0p_i2c_remove(struct i2c_client *i2c)
  16420. +{
  16421. + snd_soc_unregister_component(&i2c->dev);
  16422. + i2c_set_clientdata(i2c, NULL);
  16423. +
  16424. + gpiod_set_value_cansleep(priv_data->mute_gpio, 0);
  16425. + msleep(30);
  16426. + gpiod_set_value_cansleep(priv_data->enable_gpio, 1);
  16427. + msleep(200);
  16428. + gpiod_set_value_cansleep(priv_data->booster_gpio, 0);
  16429. + msleep(200);
  16430. +
  16431. + kfree(priv_data);
  16432. +}
  16433. +
  16434. +static void ma120x0p_i2c_shutdown(struct i2c_client *i2c)
  16435. +{
  16436. + snd_soc_unregister_component(&i2c->dev);
  16437. + i2c_set_clientdata(i2c, NULL);
  16438. +
  16439. + gpiod_set_value_cansleep(priv_data->mute_gpio, 0);
  16440. + msleep(30);
  16441. + gpiod_set_value_cansleep(priv_data->enable_gpio, 1);
  16442. + msleep(200);
  16443. + gpiod_set_value_cansleep(priv_data->booster_gpio, 0);
  16444. + msleep(200);
  16445. +
  16446. + kfree(priv_data);
  16447. +}
  16448. +
  16449. +static const struct i2c_device_id ma120x0p_i2c_id[] = {
  16450. + { "ma120x0p", 0 },
  16451. + { }
  16452. +};
  16453. +
  16454. +MODULE_DEVICE_TABLE(i2c, ma120x0p_i2c_id);
  16455. +
  16456. +static struct i2c_driver ma120x0p_i2c_driver = {
  16457. + .driver = {
  16458. + .name = "ma120x0p",
  16459. + .owner = THIS_MODULE,
  16460. + .of_match_table = ma120x0p_of_match,
  16461. + },
  16462. + .probe = ma120x0p_i2c_probe,
  16463. + .remove = ma120x0p_i2c_remove,
  16464. + .shutdown = ma120x0p_i2c_shutdown,
  16465. + .id_table = ma120x0p_i2c_id
  16466. +};
  16467. +
  16468. +static int __init ma120x0p_modinit(void)
  16469. +{
  16470. + int ret = 0;
  16471. +
  16472. + ret = i2c_add_driver(&ma120x0p_i2c_driver);
  16473. + if (ret != 0) {
  16474. + pr_err("Failed to register MA120X0P I2C driver: %d\n", ret);
  16475. + return ret;
  16476. + }
  16477. + return ret;
  16478. +}
  16479. +module_init(ma120x0p_modinit);
  16480. +
  16481. +static void __exit ma120x0p_exit(void)
  16482. +{
  16483. + i2c_del_driver(&ma120x0p_i2c_driver);
  16484. +}
  16485. +module_exit(ma120x0p_exit);
  16486. +
  16487. +MODULE_AUTHOR("Ariel Muszkat [email protected]>");
  16488. +MODULE_DESCRIPTION("ASoC driver for ma120x0p");
  16489. +MODULE_LICENSE("GPL v2");
  16490. --- /dev/null
  16491. +++ b/sound/soc/codecs/pcm1794a.c
  16492. @@ -0,0 +1,69 @@
  16493. +/*
  16494. + * Driver for the PCM1794A codec
  16495. + *
  16496. + * Author: Florian Meier <[email protected]>
  16497. + * Copyright 2013
  16498. + *
  16499. + * This program is free software; you can redistribute it and/or
  16500. + * modify it under the terms of the GNU General Public License
  16501. + * version 2 as published by the Free Software Foundation.
  16502. + *
  16503. + * This program is distributed in the hope that it will be useful, but
  16504. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  16505. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16506. + * General Public License for more details.
  16507. + */
  16508. +
  16509. +
  16510. +#include <linux/init.h>
  16511. +#include <linux/module.h>
  16512. +#include <linux/platform_device.h>
  16513. +
  16514. +#include <sound/soc.h>
  16515. +
  16516. +static struct snd_soc_dai_driver pcm1794a_dai = {
  16517. + .name = "pcm1794a-hifi",
  16518. + .playback = {
  16519. + .channels_min = 2,
  16520. + .channels_max = 2,
  16521. + .rates = SNDRV_PCM_RATE_8000_192000,
  16522. + .formats = SNDRV_PCM_FMTBIT_S16_LE |
  16523. + SNDRV_PCM_FMTBIT_S24_LE
  16524. + },
  16525. +};
  16526. +
  16527. +static struct snd_soc_component_driver soc_component_dev_pcm1794a;
  16528. +
  16529. +static int pcm1794a_probe(struct platform_device *pdev)
  16530. +{
  16531. + return snd_soc_register_component(&pdev->dev, &soc_component_dev_pcm1794a,
  16532. + &pcm1794a_dai, 1);
  16533. +}
  16534. +
  16535. +static int pcm1794a_remove(struct platform_device *pdev)
  16536. +{
  16537. + snd_soc_unregister_component(&pdev->dev);
  16538. + return 0;
  16539. +}
  16540. +
  16541. +static const struct of_device_id pcm1794a_of_match[] = {
  16542. + { .compatible = "ti,pcm1794a", },
  16543. + { }
  16544. +};
  16545. +MODULE_DEVICE_TABLE(of, pcm1794a_of_match);
  16546. +
  16547. +static struct platform_driver pcm1794a_component_driver = {
  16548. + .probe = pcm1794a_probe,
  16549. + .remove = pcm1794a_remove,
  16550. + .driver = {
  16551. + .name = "pcm1794a-codec",
  16552. + .owner = THIS_MODULE,
  16553. + .of_match_table = of_match_ptr(pcm1794a_of_match),
  16554. + },
  16555. +};
  16556. +
  16557. +module_platform_driver(pcm1794a_component_driver);
  16558. +
  16559. +MODULE_DESCRIPTION("ASoC PCM1794A codec driver");
  16560. +MODULE_AUTHOR("Florian Meier <[email protected]>");
  16561. +MODULE_LICENSE("GPL v2");
  16562. --- a/sound/soc/codecs/pcm512x.c
  16563. +++ b/sound/soc/codecs/pcm512x.c
  16564. @@ -536,7 +536,7 @@ static unsigned long pcm512x_ncp_target(
  16565. static const u32 pcm512x_dai_rates[] = {
  16566. 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
  16567. - 88200, 96000, 176400, 192000, 384000,
  16568. + 88200, 96000, 176400, 192000, 352800, 384000,
  16569. };
  16570. static const struct snd_pcm_hw_constraint_list constraints_slave = {
  16571. --- /dev/null
  16572. +++ b/sound/soc/codecs/tas5713.c
  16573. @@ -0,0 +1,360 @@
  16574. +/*
  16575. + * ASoC Driver for TAS5713
  16576. + *
  16577. + * Author: Sebastian Eickhoff <[email protected]>
  16578. + * Copyright 2014
  16579. + *
  16580. + * This program is free software; you can redistribute it and/or
  16581. + * modify it under the terms of the GNU General Public License
  16582. + * version 2 as published by the Free Software Foundation.
  16583. + *
  16584. + * This program is distributed in the hope that it will be useful, but
  16585. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  16586. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16587. + * General Public License for more details.
  16588. + */
  16589. +
  16590. +#include <linux/module.h>
  16591. +#include <linux/moduleparam.h>
  16592. +#include <linux/init.h>
  16593. +#include <linux/delay.h>
  16594. +#include <linux/pm.h>
  16595. +#include <linux/i2c.h>
  16596. +#include <linux/of_device.h>
  16597. +#include <linux/spi/spi.h>
  16598. +#include <linux/regmap.h>
  16599. +#include <linux/regulator/consumer.h>
  16600. +#include <linux/slab.h>
  16601. +#include <sound/core.h>
  16602. +#include <sound/pcm.h>
  16603. +#include <sound/pcm_params.h>
  16604. +#include <sound/soc.h>
  16605. +#include <sound/initval.h>
  16606. +#include <sound/tlv.h>
  16607. +
  16608. +#include <linux/kernel.h>
  16609. +#include <linux/string.h>
  16610. +#include <linux/fs.h>
  16611. +#include <asm/uaccess.h>
  16612. +
  16613. +#include "tas5713.h"
  16614. +
  16615. +
  16616. +static struct i2c_client *i2c;
  16617. +
  16618. +struct tas5713_priv {
  16619. + struct regmap *regmap;
  16620. + int mclk_div;
  16621. + struct snd_soc_component *component;
  16622. +};
  16623. +
  16624. +static struct tas5713_priv *priv_data;
  16625. +
  16626. +
  16627. +
  16628. +
  16629. +/*
  16630. + * _ _ ___ _ ___ _ _
  16631. + * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___
  16632. + * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-<
  16633. + * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/
  16634. + *
  16635. + */
  16636. +
  16637. +static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1);
  16638. +
  16639. +
  16640. +static const struct snd_kcontrol_new tas5713_snd_controls[] = {
  16641. + SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv),
  16642. + SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv)
  16643. +};
  16644. +
  16645. +
  16646. +
  16647. +
  16648. +/*
  16649. + * __ __ _ _ ___ _
  16650. + * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _
  16651. + * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_|
  16652. + * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_|
  16653. + *
  16654. + */
  16655. +
  16656. +static int tas5713_hw_params(struct snd_pcm_substream *substream,
  16657. + struct snd_pcm_hw_params *params,
  16658. + struct snd_soc_dai *dai)
  16659. +{
  16660. + u16 blen = 0x00;
  16661. +
  16662. + struct snd_soc_component *component = dai->component;
  16663. + priv_data->component = component;
  16664. +
  16665. + switch (params_format(params)) {
  16666. + case SNDRV_PCM_FORMAT_S16_LE:
  16667. + blen = 0x03;
  16668. + break;
  16669. + case SNDRV_PCM_FORMAT_S20_3LE:
  16670. + blen = 0x1;
  16671. + break;
  16672. + case SNDRV_PCM_FORMAT_S24_LE:
  16673. + blen = 0x04;
  16674. + break;
  16675. + case SNDRV_PCM_FORMAT_S32_LE:
  16676. + blen = 0x05;
  16677. + break;
  16678. + default:
  16679. + dev_err(dai->dev, "Unsupported word length: %u\n",
  16680. + params_format(params));
  16681. + return -EINVAL;
  16682. + }
  16683. +
  16684. + // set word length
  16685. + snd_soc_component_update_bits(component, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen);
  16686. +
  16687. + return 0;
  16688. +}
  16689. +
  16690. +
  16691. +static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
  16692. +{
  16693. + unsigned int val = 0;
  16694. +
  16695. + struct tas5713_priv *tas5713;
  16696. + struct snd_soc_component *component = dai->component;
  16697. + tas5713 = snd_soc_component_get_drvdata(component);
  16698. +
  16699. + if (mute) {
  16700. + val = TAS5713_SOFT_MUTE_ALL;
  16701. + }
  16702. +
  16703. + return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val);
  16704. +}
  16705. +
  16706. +
  16707. +static const struct snd_soc_dai_ops tas5713_dai_ops = {
  16708. + .hw_params = tas5713_hw_params,
  16709. + .mute_stream = tas5713_mute_stream,
  16710. +};
  16711. +
  16712. +
  16713. +static struct snd_soc_dai_driver tas5713_dai = {
  16714. + .name = "tas5713-hifi",
  16715. + .playback = {
  16716. + .stream_name = "Playback",
  16717. + .channels_min = 2,
  16718. + .channels_max = 2,
  16719. + .rates = SNDRV_PCM_RATE_8000_48000,
  16720. + .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ),
  16721. + },
  16722. + .ops = &tas5713_dai_ops,
  16723. +};
  16724. +
  16725. +
  16726. +
  16727. +
  16728. +/*
  16729. + * ___ _ ___ _
  16730. + * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _
  16731. + * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_|
  16732. + * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_|
  16733. + *
  16734. + */
  16735. +
  16736. +static void tas5713_remove(struct snd_soc_component *component)
  16737. +{
  16738. + struct tas5713_priv *tas5713;
  16739. +
  16740. + tas5713 = snd_soc_component_get_drvdata(component);
  16741. +}
  16742. +
  16743. +
  16744. +static int tas5713_probe(struct snd_soc_component *component)
  16745. +{
  16746. + struct tas5713_priv *tas5713;
  16747. + int i, ret;
  16748. +
  16749. + i2c = container_of(component->dev, struct i2c_client, dev);
  16750. +
  16751. + tas5713 = snd_soc_component_get_drvdata(component);
  16752. +
  16753. + // Reset error
  16754. + ret = snd_soc_component_write(component, TAS5713_ERROR_STATUS, 0x00);
  16755. + if (ret < 0) return ret;
  16756. +
  16757. + // Trim oscillator
  16758. + ret = snd_soc_component_write(component, TAS5713_OSC_TRIM, 0x00);
  16759. + if (ret < 0) return ret;
  16760. + msleep(1000);
  16761. +
  16762. + // Reset error
  16763. + ret = snd_soc_component_write(component, TAS5713_ERROR_STATUS, 0x00);
  16764. + if (ret < 0) return ret;
  16765. +
  16766. + // I2S 24bit
  16767. + ret = snd_soc_component_write(component, TAS5713_SERIAL_DATA_INTERFACE, 0x05);
  16768. + if (ret < 0) return ret;
  16769. +
  16770. + // Unmute
  16771. + ret = snd_soc_component_write(component, TAS5713_SYSTEM_CTRL2, 0x00);
  16772. + if (ret < 0) return ret;
  16773. + ret = snd_soc_component_write(component, TAS5713_SOFT_MUTE, 0x00);
  16774. + if (ret < 0) return ret;
  16775. +
  16776. + // Set volume to 0db
  16777. + ret = snd_soc_component_write(component, TAS5713_VOL_MASTER, 0x00);
  16778. + if (ret < 0) return ret;
  16779. +
  16780. + // Now start programming the default initialization sequence
  16781. + for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) {
  16782. + ret = i2c_master_send(i2c,
  16783. + tas5713_init_sequence[i].data,
  16784. + tas5713_init_sequence[i].size);
  16785. + if (ret < 0) {
  16786. + printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret);
  16787. + }
  16788. + }
  16789. +
  16790. + // Unmute
  16791. + ret = snd_soc_component_write(component, TAS5713_SYSTEM_CTRL2, 0x00);
  16792. + if (ret < 0) return ret;
  16793. +
  16794. + return 0;
  16795. +}
  16796. +
  16797. +
  16798. +static struct snd_soc_component_driver soc_codec_dev_tas5713 = {
  16799. + .probe = tas5713_probe,
  16800. + .remove = tas5713_remove,
  16801. + .controls = tas5713_snd_controls,
  16802. + .num_controls = ARRAY_SIZE(tas5713_snd_controls),
  16803. +};
  16804. +
  16805. +
  16806. +
  16807. +
  16808. +/*
  16809. + * ___ ___ ___ ___ _
  16810. + * |_ _|_ ) __| | \ _ _(_)_ _____ _ _
  16811. + * | | / / (__ | |) | '_| \ V / -_) '_|
  16812. + * |___/___\___| |___/|_| |_|\_/\___|_|
  16813. + *
  16814. + */
  16815. +
  16816. +static const struct reg_default tas5713_reg_defaults[] = {
  16817. + { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB
  16818. + { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB
  16819. + { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB
  16820. + { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB
  16821. +};
  16822. +
  16823. +
  16824. +static bool tas5713_reg_volatile(struct device *dev, unsigned int reg)
  16825. +{
  16826. + switch (reg) {
  16827. + case TAS5713_DEVICE_ID:
  16828. + case TAS5713_ERROR_STATUS:
  16829. + case TAS5713_CLOCK_CTRL:
  16830. + return true;
  16831. + default:
  16832. + return false;
  16833. + }
  16834. +}
  16835. +
  16836. +
  16837. +static const struct of_device_id tas5713_of_match[] = {
  16838. + { .compatible = "ti,tas5713", },
  16839. + { }
  16840. +};
  16841. +MODULE_DEVICE_TABLE(of, tas5713_of_match);
  16842. +
  16843. +
  16844. +static struct regmap_config tas5713_regmap_config = {
  16845. + .reg_bits = 8,
  16846. + .val_bits = 8,
  16847. +
  16848. + .max_register = TAS5713_MAX_REGISTER,
  16849. + .volatile_reg = tas5713_reg_volatile,
  16850. +
  16851. + .cache_type = REGCACHE_RBTREE,
  16852. + .reg_defaults = tas5713_reg_defaults,
  16853. + .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults),
  16854. +};
  16855. +
  16856. +
  16857. +static int tas5713_i2c_probe(struct i2c_client *i2c)
  16858. +{
  16859. + int ret;
  16860. +
  16861. + priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL);
  16862. + if (!priv_data)
  16863. + return -ENOMEM;
  16864. +
  16865. + priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config);
  16866. + if (IS_ERR(priv_data->regmap)) {
  16867. + ret = PTR_ERR(priv_data->regmap);
  16868. + return ret;
  16869. + }
  16870. +
  16871. + i2c_set_clientdata(i2c, priv_data);
  16872. +
  16873. + ret = snd_soc_register_component(&i2c->dev,
  16874. + &soc_codec_dev_tas5713, &tas5713_dai, 1);
  16875. +
  16876. + return ret;
  16877. +}
  16878. +
  16879. +
  16880. +static void tas5713_i2c_remove(struct i2c_client *i2c)
  16881. +{
  16882. + snd_soc_unregister_component(&i2c->dev);
  16883. + i2c_set_clientdata(i2c, NULL);
  16884. +
  16885. + kfree(priv_data);
  16886. +}
  16887. +
  16888. +
  16889. +static const struct i2c_device_id tas5713_i2c_id[] = {
  16890. + { "tas5713", 0 },
  16891. + { }
  16892. +};
  16893. +
  16894. +MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id);
  16895. +
  16896. +
  16897. +static struct i2c_driver tas5713_i2c_driver = {
  16898. + .driver = {
  16899. + .name = "tas5713",
  16900. + .owner = THIS_MODULE,
  16901. + .of_match_table = tas5713_of_match,
  16902. + },
  16903. + .probe = tas5713_i2c_probe,
  16904. + .remove = tas5713_i2c_remove,
  16905. + .id_table = tas5713_i2c_id
  16906. +};
  16907. +
  16908. +
  16909. +static int __init tas5713_modinit(void)
  16910. +{
  16911. + int ret = 0;
  16912. +
  16913. + ret = i2c_add_driver(&tas5713_i2c_driver);
  16914. + if (ret) {
  16915. + printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n",
  16916. + ret);
  16917. + }
  16918. +
  16919. + return ret;
  16920. +}
  16921. +module_init(tas5713_modinit);
  16922. +
  16923. +
  16924. +static void __exit tas5713_exit(void)
  16925. +{
  16926. + i2c_del_driver(&tas5713_i2c_driver);
  16927. +}
  16928. +module_exit(tas5713_exit);
  16929. +
  16930. +
  16931. +MODULE_AUTHOR("Sebastian Eickhoff <[email protected]>");
  16932. +MODULE_DESCRIPTION("ASoC driver for TAS5713");
  16933. +MODULE_LICENSE("GPL v2");
  16934. --- /dev/null
  16935. +++ b/sound/soc/codecs/tas5713.h
  16936. @@ -0,0 +1,210 @@
  16937. +/*
  16938. + * ASoC Driver for TAS5713
  16939. + *
  16940. + * Author: Sebastian Eickhoff <[email protected]>
  16941. + * Copyright 2014
  16942. + *
  16943. + * This program is free software; you can redistribute it and/or
  16944. + * modify it under the terms of the GNU General Public License
  16945. + * version 2 as published by the Free Software Foundation.
  16946. + *
  16947. + * This program is distributed in the hope that it will be useful, but
  16948. + * WITHOUT ANY WARRANTY; without even the implied warranty of
  16949. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16950. + * General Public License for more details.
  16951. + */
  16952. +
  16953. +#ifndef _TAS5713_H
  16954. +#define _TAS5713_H
  16955. +
  16956. +
  16957. +// TAS5713 I2C-bus register addresses
  16958. +
  16959. +#define TAS5713_CLOCK_CTRL 0x00
  16960. +#define TAS5713_DEVICE_ID 0x01
  16961. +#define TAS5713_ERROR_STATUS 0x02
  16962. +#define TAS5713_SYSTEM_CTRL1 0x03
  16963. +#define TAS5713_SERIAL_DATA_INTERFACE 0x04
  16964. +#define TAS5713_SYSTEM_CTRL2 0x05
  16965. +#define TAS5713_SOFT_MUTE 0x06
  16966. +#define TAS5713_VOL_MASTER 0x07
  16967. +#define TAS5713_VOL_CH1 0x08
  16968. +#define TAS5713_VOL_CH2 0x09
  16969. +#define TAS5713_VOL_HEADPHONE 0x0A
  16970. +#define TAS5713_VOL_CONFIG 0x0E
  16971. +#define TAS5713_MODULATION_LIMIT 0x10
  16972. +#define TAS5713_IC_DLY_CH1 0x11
  16973. +#define TAS5713_IC_DLY_CH2 0x12
  16974. +#define TAS5713_IC_DLY_CH3 0x13
  16975. +#define TAS5713_IC_DLY_CH4 0x14
  16976. +
  16977. +#define TAS5713_START_STOP_PERIOD 0x1A
  16978. +#define TAS5713_OSC_TRIM 0x1B
  16979. +#define TAS5713_BKND_ERR 0x1C
  16980. +
  16981. +#define TAS5713_INPUT_MUX 0x20
  16982. +#define TAS5713_SRC_SELECT_CH4 0x21
  16983. +#define TAS5713_PWM_MUX 0x25
  16984. +
  16985. +#define TAS5713_CH1_BQ0 0x29
  16986. +#define TAS5713_CH1_BQ1 0x2A
  16987. +#define TAS5713_CH1_BQ2 0x2B
  16988. +#define TAS5713_CH1_BQ3 0x2C
  16989. +#define TAS5713_CH1_BQ4 0x2D
  16990. +#define TAS5713_CH1_BQ5 0x2E
  16991. +#define TAS5713_CH1_BQ6 0x2F
  16992. +#define TAS5713_CH1_BQ7 0x58
  16993. +#define TAS5713_CH1_BQ8 0x59
  16994. +
  16995. +#define TAS5713_CH2_BQ0 0x30
  16996. +#define TAS5713_CH2_BQ1 0x31
  16997. +#define TAS5713_CH2_BQ2 0x32
  16998. +#define TAS5713_CH2_BQ3 0x33
  16999. +#define TAS5713_CH2_BQ4 0x34
  17000. +#define TAS5713_CH2_BQ5 0x35
  17001. +#define TAS5713_CH2_BQ6 0x36
  17002. +#define TAS5713_CH2_BQ7 0x5C
  17003. +#define TAS5713_CH2_BQ8 0x5D
  17004. +
  17005. +#define TAS5713_CH4_BQ0 0x5A
  17006. +#define TAS5713_CH4_BQ1 0x5B
  17007. +#define TAS5713_CH3_BQ0 0x5E
  17008. +#define TAS5713_CH3_BQ1 0x5F
  17009. +
  17010. +#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B
  17011. +#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C
  17012. +#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E
  17013. +#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F
  17014. +#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40
  17015. +#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43
  17016. +#define TAS5713_DRC_CTRL 0x46
  17017. +
  17018. +#define TAS5713_BANK_SW_CTRL 0x50
  17019. +#define TAS5713_CH1_OUTPUT_MIXER 0x51
  17020. +#define TAS5713_CH2_OUTPUT_MIXER 0x52
  17021. +#define TAS5713_CH1_INPUT_MIXER 0x53
  17022. +#define TAS5713_CH2_INPUT_MIXER 0x54
  17023. +#define TAS5713_OUTPUT_POST_SCALE 0x56
  17024. +#define TAS5713_OUTPUT_PRESCALE 0x57
  17025. +
  17026. +#define TAS5713_IDF_POST_SCALE 0x62
  17027. +
  17028. +#define TAS5713_CH1_INLINE_MIXER 0x70
  17029. +#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71
  17030. +#define TAS5713_CH1_R_CHANNEL_MIXER 0x72
  17031. +#define TAS5713_CH1_L_CHANNEL_MIXER 0x73
  17032. +#define TAS5713_CH2_INLINE_MIXER 0x74
  17033. +#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75
  17034. +#define TAS5713_CH2_L_CHANNEL_MIXER 0x76
  17035. +#define TAS5713_CH2_R_CHANNEL_MIXER 0x77
  17036. +
  17037. +#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8
  17038. +#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9
  17039. +
  17040. +#define TAS5713_REGISTER_COUNT 0x46
  17041. +#define TAS5713_MAX_REGISTER 0xF9
  17042. +
  17043. +
  17044. +// Bitmasks for registers
  17045. +#define TAS5713_SOFT_MUTE_ALL 0x07
  17046. +
  17047. +
  17048. +
  17049. +struct tas5713_init_command {
  17050. + const int size;
  17051. + const char *const data;
  17052. +};
  17053. +
  17054. +static const struct tas5713_init_command tas5713_init_sequence[] = {
  17055. +
  17056. + // Trim oscillator
  17057. + { .size = 2, .data = "\x1B\x00" },
  17058. + // System control register 1 (0x03): block DC
  17059. + { .size = 2, .data = "\x03\x80" },
  17060. + // Mute everything
  17061. + { .size = 2, .data = "\x05\x40" },
  17062. + // Modulation limit register (0x10): 97.7%
  17063. + { .size = 2, .data = "\x10\x02" },
  17064. + // Interchannel delay registers
  17065. + // (0x11, 0x12, 0x13, and 0x14): BD mode
  17066. + { .size = 2, .data = "\x11\xB8" },
  17067. + { .size = 2, .data = "\x12\x60" },
  17068. + { .size = 2, .data = "\x13\xA0" },
  17069. + { .size = 2, .data = "\x14\x48" },
  17070. + // PWM shutdown group register (0x19): no shutdown
  17071. + { .size = 2, .data = "\x19\x00" },
  17072. + // Input multiplexer register (0x20): BD mode
  17073. + { .size = 2, .data = "\x20\x00\x89\x77\x72" },
  17074. + // PWM output mux register (0x25)
  17075. + // Channel 1 --> OUTA, channel 1 neg --> OUTB
  17076. + // Channel 2 --> OUTC, channel 2 neg --> OUTD
  17077. + { .size = 5, .data = "\x25\x01\x02\x13\x45" },
  17078. + // DRC control (0x46): DRC off
  17079. + { .size = 5, .data = "\x46\x00\x00\x00\x00" },
  17080. + // BKND_ERR register (0x1C): 299ms reset period
  17081. + { .size = 2, .data = "\x1C\x07" },
  17082. + // Mute channel 3
  17083. + { .size = 2, .data = "\x0A\xFF" },
  17084. + // Volume configuration register (0x0E): volume slew 512 steps
  17085. + { .size = 2, .data = "\x0E\x90" },
  17086. + // Clock control register (0x00): 44/48kHz, MCLK=64xfs
  17087. + { .size = 2, .data = "\x00\x60" },
  17088. + // Bank switch and eq control (0x50): no bank switching
  17089. + { .size = 5, .data = "\x50\x00\x00\x00\x00" },
  17090. + // Volume registers (0x07, 0x08, 0x09, 0x0A)
  17091. + { .size = 2, .data = "\x07\x20" },
  17092. + { .size = 2, .data = "\x08\x30" },
  17093. + { .size = 2, .data = "\x09\x30" },
  17094. + { .size = 2, .data = "\x0A\xFF" },
  17095. + // 0x72, 0x73, 0x76, 0x77 input mixer:
  17096. + // no intermix between channels
  17097. + { .size = 5, .data = "\x72\x00\x00\x00\x00" },
  17098. + { .size = 5, .data = "\x73\x00\x80\x00\x00" },
  17099. + { .size = 5, .data = "\x76\x00\x00\x00\x00" },
  17100. + { .size = 5, .data = "\x77\x00\x80\x00\x00" },
  17101. + // 0x70, 0x71, 0x74, 0x75 inline DRC mixer:
  17102. + // no inline DRC inmix
  17103. + { .size = 5, .data = "\x70\x00\x80\x00\x00" },
  17104. + { .size = 5, .data = "\x71\x00\x00\x00\x00" },
  17105. + { .size = 5, .data = "\x74\x00\x80\x00\x00" },
  17106. + { .size = 5, .data = "\x75\x00\x00\x00\x00" },
  17107. + // 0x56, 0x57 Output scale
  17108. + { .size = 5, .data = "\x56\x00\x80\x00\x00" },
  17109. + { .size = 5, .data = "\x57\x00\x02\x00\x00" },
  17110. + // 0x3B, 0x3c
  17111. + { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" },
  17112. + { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
  17113. + { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" },
  17114. + { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
  17115. + { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
  17116. + { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
  17117. + // 0x51, 0x52: output mixer
  17118. + { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" },
  17119. + { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" },
  17120. + // PEQ defaults
  17121. + { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17122. + { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17123. + { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17124. + { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17125. + { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17126. + { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17127. + { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17128. + { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17129. + { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17130. + { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17131. + { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17132. + { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17133. + { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17134. + { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17135. + { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17136. + { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17137. + { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17138. + { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17139. + { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17140. + { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17141. + { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17142. + { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
  17143. +};
  17144. +
  17145. +
  17146. +#endif /* _TAS5713_H */
  17147. --- a/sound/soc/soc-core.c
  17148. +++ b/sound/soc/soc-core.c
  17149. @@ -1316,7 +1316,15 @@ int snd_soc_runtime_set_dai_fmt(struct s
  17150. return 0;
  17151. for_each_rtd_codec_dais(rtd, i, codec_dai) {
  17152. - ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
  17153. + unsigned int codec_dai_fmt = dai_fmt;
  17154. +
  17155. + // there can only be one master when using multiple codecs
  17156. + if (i && (codec_dai_fmt & SND_SOC_DAIFMT_MASTER_MASK)) {
  17157. + codec_dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
  17158. + codec_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
  17159. + }
  17160. +
  17161. + ret = snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
  17162. if (ret != 0 && ret != -ENOTSUPP)
  17163. return ret;
  17164. }
  17165. --- a/sound/usb/card.c
  17166. +++ b/sound/usb/card.c
  17167. @@ -863,8 +863,14 @@ static int usb_audio_probe(struct usb_in
  17168. if (ignore_ctl_error)
  17169. chip->quirk_flags |= QUIRK_FLAG_IGNORE_CTL_ERROR;
  17170. - if (chip->quirk_flags & QUIRK_FLAG_DISABLE_AUTOSUSPEND)
  17171. + if (chip->quirk_flags & QUIRK_FLAG_DISABLE_AUTOSUSPEND) {
  17172. + /*
  17173. + * Grab the interface, because on a webcam uvcvideo may race
  17174. + * with snd-usb-audio during probe and re-enable autosuspend.
  17175. + */
  17176. + usb_autopm_get_interface(intf);
  17177. usb_disable_autosuspend(interface_to_usbdev(intf));
  17178. + }
  17179. /*
  17180. * For devices with more than one control interface, we assume the
  17181. --- a/sound/usb/quirks.c
  17182. +++ b/sound/usb/quirks.c
  17183. @@ -2249,6 +2249,8 @@ static const struct usb_audio_quirk_flag
  17184. QUIRK_FLAG_ALIGN_TRANSFER),
  17185. DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */
  17186. QUIRK_FLAG_ALIGN_TRANSFER),
  17187. + DEVICE_FLG(0x09da, 0x2695, /* A4Tech FHD 1080p webcam */
  17188. + QUIRK_FLAG_DISABLE_AUTOSUSPEND | QUIRK_FLAG_GET_SAMPLE_RATE),
  17189. /* Vendor matches */
  17190. VENDOR_FLG(0x045e, /* MS Lifecam */