12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156 |
- // SPDX-License-Identifier: GPL-2.0
- //
- // cs40l26-sysfs.c -- CS40L26 Boosted Haptic Driver with Integrated DSP and
- // Waveform Memory with Advanced Closed Loop Algorithms and LRA protection
- //
- // Copyright 2022 Cirrus Logic, Inc.
- //
- // Author: Fred Treven <[email protected]>
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License version 2 as
- // published by the Free Software Foundation.
- #ifdef CONFIG_CS40L26_SAMSUNG_FEATURE
- #include <linux/vibrator/cs40l26.h>
- #else
- #include <linux/mfd/cs40l26.h>
- #endif
- static ssize_t dsp_state_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u8 dsp_state;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = cs40l26_dsp_state_get(cs40l26, &dsp_state);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned int) (dsp_state & 0xFF));
- }
- static DEVICE_ATTR_RO(dsp_state);
- static ssize_t owt_lib_compat_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- return snprintf(buf, PAGE_SIZE, "1.0.0\n");
- }
- static DEVICE_ATTR_RO(owt_lib_compat);
- static ssize_t overprotection_gain_show(struct device *dev, struct device_attribute *attr,
- char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, op_gain;
- int error;
- if (!cl_dsp_algo_is_present(cs40l26->dsp, CS40L26_EP_ALGO_ID))
- return -EPERM;
- error = cl_dsp_get_reg(cs40l26->dsp, "PROTECTION_XM_OP_GAIN",
- CL_DSP_XM_UNPACKED_TYPE, CS40L26_EP_ALGO_ID, ®);
- if (error)
- return error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = regmap_read(cs40l26->regmap, reg, &op_gain);
- cs40l26_pm_exit(cs40l26->dev);
- return error ? error : snprintf(buf, PAGE_SIZE, "%d\n", op_gain);
- }
- static ssize_t overprotection_gain_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, op_gain;
- int error;
- if (!cl_dsp_algo_is_present(cs40l26->dsp, CS40L26_EP_ALGO_ID))
- return -EPERM;
- error = kstrtou32(buf, 10, &op_gain);
- if (error || op_gain < CS40L26_OVERPROTECTION_GAIN_MIN ||
- op_gain > CS40L26_UINT_24_BITS_MAX)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = cl_dsp_get_reg(cs40l26->dsp, "PROTECTION_XM_OP_GAIN",
- CL_DSP_XM_UNPACKED_TYPE, CS40L26_EP_ALGO_ID, ®);
- if (error)
- goto err_pm;
- error = regmap_write(cs40l26->regmap, reg, op_gain);
- err_pm:
- cs40l26_pm_exit(cs40l26->dev);
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(overprotection_gain);
- static ssize_t halo_heartbeat_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, halo_heartbeat;
- int error;
- error = cl_dsp_get_reg(cs40l26->dsp, "HALO_HEARTBEAT", CL_DSP_XM_UNPACKED_TYPE,
- cs40l26->fw_id, ®);
- if (error)
- return error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = regmap_read(cs40l26->regmap, reg, &halo_heartbeat);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- return snprintf(buf, PAGE_SIZE, "%d\n", halo_heartbeat);
- }
- static DEVICE_ATTR_RO(halo_heartbeat);
- static ssize_t pm_stdby_timeout_ms_show(struct device *dev, struct device_attribute *attr,
- char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 timeout_ms;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = cs40l26_pm_timeout_ms_get(cs40l26, CS40L26_DSP_STATE_STANDBY, &timeout_ms);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- return snprintf(buf, PAGE_SIZE, "%u\n", timeout_ms);
- }
- static ssize_t pm_stdby_timeout_ms_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 timeout_ms;
- int error;
- error = kstrtou32(buf, 10, &timeout_ms);
- if (error)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = cs40l26_pm_timeout_ms_set(cs40l26, CS40L26_DSP_STATE_STANDBY, timeout_ms);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- return count;
- }
- static DEVICE_ATTR_RW(pm_stdby_timeout_ms);
- static ssize_t pm_active_timeout_ms_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 timeout_ms;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = cs40l26_pm_timeout_ms_get(cs40l26, CS40L26_DSP_STATE_ACTIVE, &timeout_ms);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- return snprintf(buf, PAGE_SIZE, "%u\n", timeout_ms);
- }
- static ssize_t pm_active_timeout_ms_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 timeout_ms;
- int error;
- error = kstrtou32(buf, 10, &timeout_ms);
- if (error)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = cs40l26_pm_timeout_ms_set(cs40l26, CS40L26_DSP_STATE_ACTIVE, timeout_ms);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- return count;
- }
- static DEVICE_ATTR_RW(pm_active_timeout_ms);
- static ssize_t vibe_state_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- unsigned int state;
- if (!cs40l26->vibe_state_reporting) {
- dev_err(cs40l26->dev, "vibe_state not supported\n");
- return -EPERM;
- }
- mutex_lock(&cs40l26->lock);
- state = cs40l26->vibe_state;
- mutex_unlock(&cs40l26->lock);
- return snprintf(buf, PAGE_SIZE, "%u\n", state);
- }
- static DEVICE_ATTR_RO(vibe_state);
- static ssize_t power_on_seq_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- struct cs40l26_pseq_op *op;
- u32 addr, data, base;
- int error;
- mutex_lock(&cs40l26->lock);
- base = cs40l26->pseq_base;
- if (list_empty(&cs40l26->pseq_op_head)) {
- dev_err(cs40l26->dev, "Power on sequence is empty\n");
- error = -EINVAL;
- goto err_mutex;
- }
- list_for_each_entry_reverse(op, &cs40l26->pseq_op_head, list) {
- switch (op->operation) {
- case CS40L26_PSEQ_OP_WRITE_FULL:
- addr = ((op->words[0] & 0xFFFF) << 16) | ((op->words[1] & 0x00FFFF00) >> 8);
- data = ((op->words[1] & 0xFF) << 24) | (op->words[2] & 0xFFFFFF);
- break;
- case CS40L26_PSEQ_OP_WRITE_H16:
- case CS40L26_PSEQ_OP_WRITE_L16:
- addr = ((op->words[0] & 0xFFFF) << 8) | ((op->words[1] & 0xFF0000) >> 16);
- data = (op->words[1] & 0xFFFF);
- if (op->operation == CS40L26_PSEQ_OP_WRITE_H16)
- data <<= 16;
- break;
- case CS40L26_PSEQ_OP_WRITE_ADDR8:
- addr = (op->words[0] & 0xFF00) >> 8;
- data = ((op->words[0] & 0xFF) << 24) | (op->words[1] & 0xFFFFFF);
- break;
- case CS40L26_PSEQ_OP_END:
- addr = CS40L26_PSEQ_OP_END_ADDR;
- data = CS40L26_PSEQ_OP_END_DATA;
- break;
- default:
- dev_err(cs40l26->dev, "Unrecognized Op Code: 0x%02X\n", op->operation);
- error = -EINVAL;
- goto err_mutex;
- }
- dev_dbg(cs40l26->dev, "0x%08x: code = 0x%02X, Addr = 0x%08X, Data = 0x%08X\n",
- base + op->offset, op->operation, addr, data);
- }
- error = snprintf(buf, PAGE_SIZE, "%d\n", cs40l26->pseq_num_ops);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- return error;
- }
- static DEVICE_ATTR_RO(power_on_seq);
- static ssize_t owt_free_space_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, words;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = cl_dsp_get_reg(cs40l26->dsp, "OWT_SIZE_XM",
- CL_DSP_XM_UNPACKED_TYPE, CS40L26_VIBEGEN_ALGO_ID, ®);
- if (error)
- goto err_pm;
- error = regmap_read(cs40l26->regmap, reg, &words);
- if (error) {
- dev_err(cs40l26->dev, "Failed to get remaining OWT space\n");
- goto err_pm;
- }
- error = snprintf(buf, PAGE_SIZE, "%d\n", words * CL_DSP_BYTES_PER_WORD);
- err_pm:
- cs40l26_pm_exit(cs40l26->dev);
- return error;
- }
- static DEVICE_ATTR_RO(owt_free_space);
- static ssize_t die_temp_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- struct regmap *regmap = cs40l26->regmap;
- u16 die_temp;
- int error;
- u32 val;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = regmap_read(regmap, CS40L26_GLOBAL_ENABLES, &val);
- if (error) {
- dev_err(cs40l26->dev, "Failed to read GLOBAL_EN status\n");
- goto err_pm;
- }
- if (!(val & CS40L26_GLOBAL_EN_MASK)) {
- dev_err(cs40l26->dev, "Global enable must be set to get die temp.\n");
- error = -EPERM;
- goto err_pm;
- }
- error = regmap_read(regmap, CS40L26_ENABLES_AND_CODES_DIG, &val);
- if (error) {
- dev_err(cs40l26->dev, "Failed to get die temperature\n");
- goto err_pm;
- }
- die_temp = (val & CS40L26_TEMP_RESULT_FILT_MASK) >> CS40L26_TEMP_RESULT_FILT_SHIFT;
- error = snprintf(buf, PAGE_SIZE, "0x%03X\n", die_temp);
- err_pm:
- cs40l26_pm_exit(cs40l26->dev);
- return error;
- }
- static DEVICE_ATTR_RO(die_temp);
- static ssize_t num_waves_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 nwaves;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = cs40l26_get_num_waves(cs40l26, &nwaves);
- if (error)
- goto err_pm;
- error = snprintf(buf, PAGE_SIZE, "%u\n", nwaves);
- err_pm:
- cs40l26_pm_exit(cs40l26->dev);
- return error;
- }
- static DEVICE_ATTR_RO(num_waves);
- /* boost_disable_delay is in units of 125us, e.g. 8 -> 1ms */
- static ssize_t boost_disable_delay_show(struct device *dev, struct device_attribute *attr,
- char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, boost_disable_delay;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = cl_dsp_get_reg(cs40l26->dsp, "BOOST_DISABLE_DELAY",
- CL_DSP_XM_UNPACKED_TYPE, CS40L26_EXT_ALGO_ID, ®);
- if (error)
- goto err_pm;
- error = regmap_read(cs40l26->regmap, reg, &boost_disable_delay);
- if (error)
- goto err_pm;
- error = snprintf(buf, PAGE_SIZE, "%d\n", boost_disable_delay);
- err_pm:
- cs40l26_pm_exit(cs40l26->dev);
- return error;
- }
- static ssize_t boost_disable_delay_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, boost_disable_delay;
- int error;
- #ifdef CONFIG_CS40L26_SAMSUNG_FEATURE
- dev_info(cs40l26->dev, "%s: %s", __func__, buf);
- #else
- dev_dbg(cs40l26->dev, "%s: %s", __func__, buf);
- #endif
- error = kstrtou32(buf, 10, &boost_disable_delay);
- if (error || boost_disable_delay < CS40L26_BOOST_DISABLE_DELAY_MIN ||
- boost_disable_delay > CS40L26_BOOST_DISABLE_DELAY_MAX)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- error = cl_dsp_get_reg(cs40l26->dsp, "BOOST_DISABLE_DELAY",
- CL_DSP_XM_UNPACKED_TYPE, CS40L26_EXT_ALGO_ID, ®);
- if (error)
- goto err_pm;
- error = regmap_write(cs40l26->regmap, reg, boost_disable_delay);
- err_pm:
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return count;
- }
- static DEVICE_ATTR_RW(boost_disable_delay);
- static ssize_t f0_offset_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- unsigned int reg, val;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "F0_OFFSET", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_VIBEGEN_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &val);
- if (error)
- goto err_mutex;
- error = snprintf(buf, PAGE_SIZE, "%u\n", val);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error;
- }
- static ssize_t f0_offset_store(struct device *dev, struct device_attribute *attr, const char *buf,
- size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- unsigned int reg, val;
- int error;
- error = kstrtou32(buf, 10, &val);
- if (error)
- return -EINVAL;
- if (val > CS40L26_F0_OFFSET_MAX && val < CS40L26_F0_OFFSET_MIN)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "F0_OFFSET", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_VIBEGEN_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_write(cs40l26->regmap, reg, val);
- if (error)
- goto err_mutex;
- error = count;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error;
- }
- static DEVICE_ATTR_RW(f0_offset);
- static ssize_t delay_before_stop_playback_us_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error;
- mutex_lock(&cs40l26->lock);
- error = snprintf(buf, PAGE_SIZE, "%d\n", cs40l26->delay_before_stop_playback_us);
- mutex_unlock(&cs40l26->lock);
- return error;
- }
- static ssize_t delay_before_stop_playback_us_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 val;
- int error;
- error = kstrtou32(buf, 10, &val);
- if (error)
- return -EINVAL;
- mutex_lock(&cs40l26->lock);
- cs40l26->delay_before_stop_playback_us = val;
- mutex_unlock(&cs40l26->lock);
- return count;
- }
- static DEVICE_ATTR_RW(delay_before_stop_playback_us);
- static ssize_t f0_comp_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error;
- mutex_lock(&cs40l26->lock);
- if (cs40l26->fw_id == CS40L26_FW_CALIB_ID) {
- error = -EPERM;
- goto err_mutex;
- }
- if (cs40l26->comp_enable_pend) {
- error = -EIO;
- goto err_mutex;
- }
- error = snprintf(buf, PAGE_SIZE, "%d\n", cs40l26->comp_enable_f0);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- return error;
- }
- static ssize_t f0_comp_enable_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error;
- unsigned int val;
- u32 reg, value;
- error = kstrtou32(buf, 10, &val);
- if (error)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- cs40l26->comp_enable_pend = true;
- cs40l26->comp_enable_f0 = val > 0;
- value = (cs40l26->comp_enable_redc << CS40L26_COMP_EN_REDC_SHIFT) |
- (cs40l26->comp_enable_f0 << CS40L26_COMP_EN_F0_SHIFT);
- if (cs40l26->fw_id == CS40L26_FW_CALIB_ID) {
- error = -EPERM;
- } else {
- error = cl_dsp_get_reg(cs40l26->dsp, "COMPENSATION_ENABLE", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_VIBEGEN_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_write(cs40l26->regmap, reg, value);
- }
- if (error)
- goto err_mutex;
- error = count;
- err_mutex:
- cs40l26->comp_enable_pend = false;
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error;
- }
- static DEVICE_ATTR_RW(f0_comp_enable);
- static ssize_t redc_comp_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error;
- mutex_lock(&cs40l26->lock);
- if (cs40l26->fw_id == CS40L26_FW_CALIB_ID) {
- error = -EPERM;
- goto err_mutex;
- }
- if (cs40l26->comp_enable_pend) {
- error = -EIO;
- goto err_mutex;
- }
- error = snprintf(buf, PAGE_SIZE, "%d\n", cs40l26->comp_enable_redc);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- return error;
- }
- static ssize_t redc_comp_enable_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error;
- unsigned int val;
- u32 reg, value;
- error = kstrtou32(buf, 10, &val);
- if (error)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- cs40l26->comp_enable_pend = true;
- cs40l26->comp_enable_redc = val > 0;
- value = (cs40l26->comp_enable_redc << CS40L26_COMP_EN_REDC_SHIFT) |
- (cs40l26->comp_enable_f0 << CS40L26_COMP_EN_F0_SHIFT);
- if (cs40l26->fw_id == CS40L26_FW_CALIB_ID) {
- error = -EPERM;
- } else {
- error = cl_dsp_get_reg(cs40l26->dsp, "COMPENSATION_ENABLE", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_VIBEGEN_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_write(cs40l26->regmap, reg, value);
- }
- if (error)
- goto err_mutex;
- error = count;
- err_mutex:
- cs40l26->comp_enable_pend = false;
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error;
- }
- static DEVICE_ATTR_RW(redc_comp_enable);
- static ssize_t swap_firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error;
- mutex_lock(&cs40l26->lock);
- if (cs40l26->fw_id == CS40L26_FW_ID)
- error = snprintf(buf, PAGE_SIZE, "%d\n", 0);
- else if (cs40l26->fw_id == CS40L26_FW_CALIB_ID)
- error = snprintf(buf, PAGE_SIZE, "%d\n", 1);
- else
- error = -EINVAL;
- mutex_unlock(&cs40l26->lock);
- return error;
- }
- static ssize_t swap_firmware_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error;
- unsigned int variant;
- error = kstrtou32(buf, 10, &variant);
- if (error)
- return error;
- #ifdef CONFIG_CS40L26_SAMSUNG_FEATURE
- dev_info(cs40l26->dev, "%s %d\n", __func__, variant);
- #endif
- if (variant == 0)
- error = cs40l26_fw_swap(cs40l26, CS40L26_FW_ID);
- else if (variant == 1)
- error = cs40l26_fw_swap(cs40l26, CS40L26_FW_CALIB_ID);
- else
- error = -EINVAL;
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(swap_firmware);
- static struct attribute *cs40l26_dev_attrs[] = {
- &dev_attr_num_waves.attr,
- &dev_attr_die_temp.attr,
- &dev_attr_owt_free_space.attr,
- &dev_attr_power_on_seq.attr,
- &dev_attr_dsp_state.attr,
- &dev_attr_halo_heartbeat.attr,
- &dev_attr_pm_stdby_timeout_ms.attr,
- &dev_attr_pm_active_timeout_ms.attr,
- &dev_attr_vibe_state.attr,
- &dev_attr_boost_disable_delay.attr,
- &dev_attr_f0_offset.attr,
- &dev_attr_delay_before_stop_playback_us.attr,
- &dev_attr_f0_comp_enable.attr,
- &dev_attr_redc_comp_enable.attr,
- &dev_attr_swap_firmware.attr,
- &dev_attr_owt_lib_compat.attr,
- &dev_attr_overprotection_gain.attr,
- NULL,
- };
- struct attribute_group cs40l26_dev_attr_group = {
- .name = "default",
- .attrs = cs40l26_dev_attrs,
- };
- static ssize_t dbc_enable_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 val, reg;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "FLAGS", CL_DSP_XM_UNPACKED_TYPE, CS40L26_EXT_ALGO_ID,
- ®);
- if (error)
- goto err_pm;
- error = regmap_read(cs40l26->regmap, reg, &val);
- if (error) {
- dev_err(cs40l26->dev, "Failed to get FLAGS\n");
- goto err_pm;
- }
- val &= CS40L26_DBC_ENABLE_MASK;
- val >>= CS40L26_DBC_ENABLE_SHIFT;
- error = snprintf(buf, PAGE_SIZE, "%u\n", val);
- err_pm:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error;
- }
- static ssize_t dbc_enable_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error;
- u32 val;
- error = kstrtou32(buf, 10, &val);
- if (error)
- return error;
- if (val > 1)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cs40l26_dbc_enable(cs40l26, val);
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(dbc_enable);
- static ssize_t dbc_env_rel_coef_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- unsigned int val;
- int error;
- error = cs40l26_dbc_get(cs40l26, CS40L26_DBC_ENV_REL_COEF, &val);
- return error ? error : snprintf(buf, PAGE_SIZE, "%u\n", val);
- }
- static ssize_t dbc_env_rel_coef_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- struct device *cdev = cs40l26->dev;
- u32 val;
- int error;
- error = kstrtou32(buf, 10, &val);
- if (error)
- return error;
- error = cs40l26_pm_enter(cdev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cs40l26_dbc_set(cs40l26, CS40L26_DBC_ENV_REL_COEF, val);
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cdev);
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(dbc_env_rel_coef);
- static ssize_t dbc_rise_headroom_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- unsigned int val;
- int error;
- error = cs40l26_dbc_get(cs40l26, CS40L26_DBC_RISE_HEADROOM, &val);
- return error ? error : snprintf(buf, PAGE_SIZE, "%u\n", val);
- }
- static ssize_t dbc_rise_headroom_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- struct device *cdev = cs40l26->dev;
- u32 val;
- int error;
- error = kstrtou32(buf, 10, &val);
- if (error)
- return error;
- error = cs40l26_pm_enter(cdev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cs40l26_dbc_set(cs40l26, CS40L26_DBC_RISE_HEADROOM, val);
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cdev);
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(dbc_rise_headroom);
- static ssize_t dbc_fall_headroom_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- unsigned int val;
- int error;
- error = cs40l26_dbc_get(cs40l26, CS40L26_DBC_FALL_HEADROOM, &val);
- return error ? error : snprintf(buf, PAGE_SIZE, "%u\n", val);
- }
- static ssize_t dbc_fall_headroom_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- struct device *cdev = cs40l26->dev;
- u32 val;
- int error;
- error = kstrtou32(buf, 10, &val);
- if (error)
- return error;
- error = cs40l26_pm_enter(cdev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cs40l26_dbc_set(cs40l26, CS40L26_DBC_FALL_HEADROOM, val);
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cdev);
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(dbc_fall_headroom);
- static ssize_t dbc_tx_lvl_thresh_fs_show(struct device *dev, struct device_attribute *attr,
- char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- unsigned int val;
- int error;
- error = cs40l26_dbc_get(cs40l26, CS40L26_DBC_TX_LVL_THRESH_FS, &val);
- return error ? error : snprintf(buf, PAGE_SIZE, "%u\n", val);
- }
- static ssize_t dbc_tx_lvl_thresh_fs_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- struct device *cdev = cs40l26->dev;
- u32 val;
- int error;
- error = kstrtou32(buf, 10, &val);
- if (error)
- return error;
- error = cs40l26_pm_enter(cdev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cs40l26_dbc_set(cs40l26, CS40L26_DBC_TX_LVL_THRESH_FS, val);
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cdev);
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(dbc_tx_lvl_thresh_fs);
- static ssize_t dbc_tx_lvl_hold_off_ms_show(struct device *dev, struct device_attribute *attr,
- char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- unsigned int val;
- int error;
- error = cs40l26_dbc_get(cs40l26, CS40L26_DBC_TX_LVL_HOLD_OFF_MS, &val);
- return error ? error : snprintf(buf, PAGE_SIZE, "%u\n", val);
- }
- static ssize_t dbc_tx_lvl_hold_off_ms_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- struct device *cdev = cs40l26->dev;
- u32 val;
- int error;
- error = kstrtou32(buf, 10, &val);
- if (error)
- return error;
- error = cs40l26_pm_enter(cdev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cs40l26_dbc_set(cs40l26, CS40L26_DBC_TX_LVL_HOLD_OFF_MS, val);
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cdev);
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(dbc_tx_lvl_hold_off_ms);
- static struct attribute *cs40l26_dev_attrs_dbc[] = {
- &dev_attr_dbc_enable.attr,
- &dev_attr_dbc_env_rel_coef.attr,
- &dev_attr_dbc_rise_headroom.attr,
- &dev_attr_dbc_fall_headroom.attr,
- &dev_attr_dbc_tx_lvl_thresh_fs.attr,
- &dev_attr_dbc_tx_lvl_hold_off_ms.attr,
- NULL,
- };
- struct attribute_group cs40l26_dev_attr_dbc_group = {
- .name = "dbc",
- .attrs = cs40l26_dev_attrs_dbc,
- };
- static ssize_t trigger_calibration_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 mailbox_command, calibration_request_payload;
- int error;
- struct completion *completion;
- #ifdef CONFIG_CS40L26_SAMSUNG_FEATURE
- dev_info(cs40l26->dev, "%s: %s", __func__, buf);
- #else
- dev_dbg(cs40l26->dev, "%s: %s", __func__, buf);
- #endif
- if (!cs40l26->calib_fw) {
- dev_err(cs40l26->dev, "Must use calibration firmware\n");
- return -EPERM;
- }
- error = kstrtou32(buf, 16, &calibration_request_payload);
- if (error)
- return -EINVAL;
- switch (calibration_request_payload) {
- case CS40L26_CALIBRATION_CONTROL_REQUEST_F0_AND_Q:
- completion = &cs40l26->cal_f0_cont;
- break;
- case CS40L26_CALIBRATION_CONTROL_REQUEST_REDC:
- completion = &cs40l26->cal_redc_cont;
- break;
- case CS40L26_CALIBRATION_CONTROL_REQUEST_DVL_PEQ:
- completion = &cs40l26->cal_dvl_peq_cont;
- break;
- case CS40L26_CALIBRATION_CONTROL_REQUEST_LS_CALIBRATION:
- completion = &cs40l26->cal_ls_cont;
- break;
- default:
- return -EINVAL;
- }
- mailbox_command = ((CS40L26_DSP_MBOX_CMD_INDEX_CALIBRATION_CONTROL <<
- CS40L26_DSP_MBOX_CMD_INDEX_SHIFT) & CS40L26_DSP_MBOX_CMD_INDEX_MASK) |
- (calibration_request_payload & CS40L26_DSP_MBOX_CMD_PAYLOAD_MASK);
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- reinit_completion(completion);
- error = cs40l26_mailbox_write(cs40l26, mailbox_command);
- mutex_unlock(&cs40l26->lock);
- if (error) {
- dev_err(cs40l26->dev, "Failed to request calibration\n");
- goto err_pm;
- }
- if (!wait_for_completion_timeout(
- completion,
- msecs_to_jiffies(CS40L26_CALIBRATION_TIMEOUT_MS))) {
- error = -ETIME;
- dev_err(cs40l26->dev, "Failed to complete cal req, %d, err: %d",
- calibration_request_payload, error);
- goto err_pm;
- }
- mutex_lock(&cs40l26->lock);
- if (calibration_request_payload == CS40L26_CALIBRATION_CONTROL_REQUEST_F0_AND_Q)
- error = cs40l26_copy_f0_est_to_dvl(cs40l26);
- mutex_unlock(&cs40l26->lock);
- err_pm:
- cs40l26_pm_exit(cs40l26->dev);
- return error ? error : count;
- }
- static DEVICE_ATTR_WO(trigger_calibration);
- static ssize_t f0_measured_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, f0_measured;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "F0_EST", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_F0_EST_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &f0_measured);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return snprintf(buf, PAGE_SIZE, "%08X\n", f0_measured);
- }
- static DEVICE_ATTR_RO(f0_measured);
- static ssize_t q_measured_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, q_measured;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "Q_EST", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_F0_EST_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &q_measured);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return snprintf(buf, PAGE_SIZE, "%08X\n", q_measured);
- }
- static DEVICE_ATTR_RO(q_measured);
- static ssize_t redc_measured_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, redc_measured;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "RE_EST_STATUS", CL_DSP_YM_UNPACKED_TYPE,
- CS40L26_SVC_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &redc_measured);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return snprintf(buf, PAGE_SIZE, "%08X\n", redc_measured);
- }
- static DEVICE_ATTR_RO(redc_measured);
- static ssize_t redc_est_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, redc_est;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "REDC", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_F0_EST_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &redc_est);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return snprintf(buf, PAGE_SIZE, "%08X\n", redc_est);
- }
- static ssize_t redc_est_store(struct device *dev, struct device_attribute *attr, const char *buf,
- size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, redc_est;
- int error;
- #ifdef CONFIG_CS40L26_SAMSUNG_FEATURE
- dev_info(cs40l26->dev, "%s: %s", __func__, buf);
- #else
- dev_dbg(cs40l26->dev, "%s: %s", __func__, buf);
- #endif
- error = kstrtou32(buf, 16, &redc_est);
- if (error)
- return error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "REDC", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_F0_EST_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_write(cs40l26->regmap, reg, redc_est);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return count;
- }
- static DEVICE_ATTR_RW(redc_est);
- static ssize_t f0_stored_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, f0_stored;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "F0_OTP_STORED", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_VIBEGEN_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &f0_stored);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return snprintf(buf, PAGE_SIZE, "%08X\n", f0_stored);
- }
- static ssize_t f0_stored_store(struct device *dev, struct device_attribute *attr, const char *buf,
- size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, f0_stored;
- int error;
- #ifdef CONFIG_CS40L26_SAMSUNG_FEATURE
- dev_info(cs40l26->dev, "%s: %s", __func__, buf);
- #else
- dev_dbg(cs40l26->dev, "%s: %s", __func__, buf);
- #endif
- error = kstrtou32(buf, 16, &f0_stored);
- if (error || f0_stored < CS40L26_F0_EST_MIN || f0_stored > CS40L26_F0_EST_MAX)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "F0_OTP_STORED", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_VIBEGEN_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_write(cs40l26->regmap, reg, f0_stored);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return count;
- }
- static DEVICE_ATTR_RW(f0_stored);
- static ssize_t q_stored_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, q_stored;
- int error;
- if (cs40l26->revid == CS40L26_REVID_B2) {
- dev_err(cs40l26->dev, "q_stored not support for revision %02X\n", cs40l26->revid);
- return -EPERM;
- }
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "Q_STORED", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_VIBEGEN_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &q_stored);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return snprintf(buf, PAGE_SIZE, "%08X\n", q_stored);
- }
- static ssize_t q_stored_store(struct device *dev, struct device_attribute *attr, const char *buf,
- size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, q_stored;
- int error;
- if (cs40l26->revid == CS40L26_REVID_B2) {
- dev_err(cs40l26->dev, "q_stored not support for revision %02X\n", cs40l26->revid);
- return -EPERM;
- }
- #ifdef CONFIG_CS40L26_SAMSUNG_FEATURE
- dev_info(cs40l26->dev, "%s: %s", __func__, buf);
- #else
- dev_dbg(cs40l26->dev, "%s: %s", __func__, buf);
- #endif
- error = kstrtou32(buf, 16, &q_stored);
- if (error || q_stored < CS40L26_Q_EST_MIN || q_stored > CS40L26_Q_EST_MAX)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "Q_STORED", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_VIBEGEN_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_write(cs40l26->regmap, reg, q_stored);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return count;
- }
- static DEVICE_ATTR_RW(q_stored);
- static ssize_t redc_stored_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, redc_stored;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "REDC_OTP_STORED", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_VIBEGEN_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &redc_stored);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return snprintf(buf, PAGE_SIZE, "%08X\n", redc_stored);
- }
- static ssize_t redc_stored_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, redc_stored;
- int error;
- #ifdef CONFIG_CS40L26_SAMSUNG_FEATURE
- dev_info(cs40l26->dev, "%s: %s", __func__, buf);
- #else
- dev_dbg(cs40l26->dev, "%s: %s", __func__, buf);
- #endif
- error = kstrtou32(buf, 16, &redc_stored);
- if (error)
- return error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "REDC_OTP_STORED", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_VIBEGEN_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_write(cs40l26->regmap, reg, redc_stored);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return count;
- }
- static DEVICE_ATTR_RW(redc_stored);
- static ssize_t freq_centre_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 freq_centre, reg;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "FREQ_CENTRE", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_F0_EST_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &freq_centre);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error ? error : snprintf(buf, PAGE_SIZE, "%08X\n", freq_centre);
- }
- static ssize_t freq_centre_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 freq_centre, reg;
- int error;
- error = kstrtou32(buf, 16, &freq_centre);
- if (error)
- return error;
- if (freq_centre < CS40L26_F0_FREQ_CENTRE_MIN ||
- freq_centre > CS40L26_F0_FREQ_CENTRE_MAX)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "FREQ_CENTRE", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_F0_EST_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_write(cs40l26->regmap, reg, freq_centre);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(freq_centre);
- static ssize_t freq_span_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error, freq_span;
- u32 reg;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "FREQ_SPAN", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_F0_EST_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &freq_span);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error ? error : snprintf(buf, PAGE_SIZE, "%08X\n", freq_span);
- }
- static ssize_t freq_span_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error, s_freq_span;
- u32 freq_span, reg;
- error = kstrtou32(buf, 16, &freq_span);
- if (error)
- return error;
- freq_span &= GENMASK(23, 0);
- s_freq_span = (freq_span & BIT(23)) ? (freq_span | GENMASK(31, 24)) : freq_span;
- if (abs(s_freq_span) < CS40L26_F0_FREQ_SPAN_MIN ||
- abs(s_freq_span) > CS40L26_F0_FREQ_SPAN_MAX)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "FREQ_SPAN", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_F0_EST_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_write(cs40l26->regmap, reg, freq_span);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(freq_span);
- static ssize_t f0_and_q_cal_time_ms_show(struct device *dev, struct device_attribute *attr,
- char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, tone_dur_ms, freq_centre, freq_span;
- int error, f0_and_q_cal_time_ms;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "TONE_DURATION_MS", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_F0_EST_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &tone_dur_ms);
- if (error) {
- dev_err(cs40l26->dev, "Failed to get tone duration\n");
- goto err_mutex;
- }
- if (tone_dur_ms == 0) { /* Calculate value */
- error = cl_dsp_get_reg(cs40l26->dsp, "FREQ_SPAN", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_F0_EST_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &freq_span);
- if (error) {
- dev_err(cs40l26->dev, "Failed to get FREQ_SPAN\n");
- goto err_mutex;
- }
- error = cl_dsp_get_reg(cs40l26->dsp, "FREQ_CENTRE", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_F0_EST_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &freq_centre);
- if (error) {
- dev_err(cs40l26->dev, "Failed to get FREQ_CENTRE\n");
- goto err_mutex;
- }
- f0_and_q_cal_time_ms = ((CS40L26_F0_CHIRP_DURATION_FACTOR *
- (int) (freq_span >> CS40L26_F0_EST_FREQ_FRAC_BITS)) /
- (int) (freq_centre >> CS40L26_F0_EST_FREQ_FRAC_BITS));
- } else if (tone_dur_ms < CS40L26_F0_AND_Q_CALIBRATION_MIN_MS) {
- f0_and_q_cal_time_ms = CS40L26_F0_AND_Q_CALIBRATION_MIN_MS;
- } else if (tone_dur_ms > CS40L26_F0_AND_Q_CALIBRATION_MAX_MS) {
- f0_and_q_cal_time_ms = CS40L26_F0_AND_Q_CALIBRATION_MAX_MS;
- } else {
- f0_and_q_cal_time_ms = tone_dur_ms;
- }
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return snprintf(buf, PAGE_SIZE, "%d\n", f0_and_q_cal_time_ms);
- }
- static DEVICE_ATTR_RO(f0_and_q_cal_time_ms);
- static ssize_t redc_cal_time_ms_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- /* FIRMWARE_STUMPY_CALIB_REDC_PLAYTIME_MS + SVC_INIT + buffer */
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, redc_playtime_ms, redc_total_cal_time_ms;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "REDC_PLAYTIME_MS", CL_DSP_XM_UNPACKED_TYPE,
- cs40l26->fw_id, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &redc_playtime_ms);
- redc_total_cal_time_ms = redc_playtime_ms + CS40L26_SVC_INITIALIZATION_PERIOD_MS +
- CS40L26_REDC_CALIBRATION_BUFFER_MS;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- else
- return snprintf(buf, PAGE_SIZE, "%d\n", redc_total_cal_time_ms);
- }
- static DEVICE_ATTR_RO(redc_cal_time_ms);
- static ssize_t dvl_peq_coefficients_show(struct device *dev, struct device_attribute *attr,
- char *buf)
- {
- u32 reg, dvl_peq_coefficients[CS40L26_DVL_PEQ_COEFFICIENTS_NUM_REGS];
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "PEQ_COEF1_X", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_DVL_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_bulk_read(cs40l26->regmap, reg, dvl_peq_coefficients,
- CS40L26_DVL_PEQ_COEFFICIENTS_NUM_REGS);
- if (error)
- goto err_mutex;
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- return snprintf(buf, PAGE_SIZE, "%08X %08X %08X %08X %08X %08X\n",
- dvl_peq_coefficients[0], dvl_peq_coefficients[1], dvl_peq_coefficients[2],
- dvl_peq_coefficients[3], dvl_peq_coefficients[4], dvl_peq_coefficients[5]);
- }
- static ssize_t dvl_peq_coefficients_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- u32 reg, dvl_peq_coefficients[CS40L26_DVL_PEQ_COEFFICIENTS_NUM_REGS];
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- char *coeffs_str, *coeffs_str_temp, *coeff_str;
- int error, coeffs_found = 0;
- coeffs_str = kstrdup(buf, GFP_KERNEL);
- if (!coeffs_str)
- return -ENOMEM;
- coeffs_str_temp = coeffs_str;
- while ((coeff_str = strsep(&coeffs_str_temp, " ")) != NULL) {
- error = kstrtou32(coeff_str, 16, &dvl_peq_coefficients[coeffs_found++]);
- if (error)
- goto err_free;
- }
- if (coeffs_found != CS40L26_DVL_PEQ_COEFFICIENTS_NUM_REGS) {
- dev_err(cs40l26->dev, "Num DVL PEQ coeffs, %d, expecting %d\n",
- coeffs_found, CS40L26_DVL_PEQ_COEFFICIENTS_NUM_REGS);
- error = -EINVAL;
- goto err_free;
- }
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- goto err_free;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "PEQ_COEF1_X", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_DVL_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_bulk_write(cs40l26->regmap, reg, dvl_peq_coefficients,
- CS40L26_DVL_PEQ_COEFFICIENTS_NUM_REGS);
- if (error)
- dev_err(cs40l26->dev, "Failed to write DVL PEQ coefficients,%d", error);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- err_free:
- kfree(coeffs_str);
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(dvl_peq_coefficients);
- static ssize_t logging_en_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 reg, enable;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "ENABLE", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_LOGGER_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_read(cs40l26->regmap, reg, &enable);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error ? error : snprintf(buf, PAGE_SIZE, "%u\n", enable);
- }
- static ssize_t logging_en_store(struct device *dev, struct device_attribute *attr, const char *buf,
- size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 enable, reg;
- int error;
- error = kstrtou32(buf, 10, &enable);
- if (error)
- return error;
- enable &= CS40L26_LOGGER_EN_MASK;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cl_dsp_get_reg(cs40l26->dsp, "ENABLE", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_LOGGER_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- error = regmap_write(cs40l26->regmap, reg, enable);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error ? error : count;
- }
- static DEVICE_ATTR_RW(logging_en);
- static ssize_t logging_max_reset_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 rst;
- int error;
- error = kstrtou32(buf, 10, &rst);
- if (error)
- return error;
- if (rst != 1)
- return -EINVAL;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- cs40l26_mailbox_write(cs40l26, CS40L26_DSP_MBOX_CMD_LOGGER_MAX_RESET);
- cs40l26_pm_exit(cs40l26->dev);
- return count;
- }
- static DEVICE_ATTR_WO(logging_max_reset);
- static int cs40l26_logger_max_get(struct cs40l26_private *cs40l26, u32 src_id, u32 *max)
- {
- int error, reg, src_num;
- u32 offset;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- for (src_num = 0; src_num < cs40l26->num_log_srcs; src_num++) {
- if (cs40l26->log_srcs[src_num].id == src_id)
- break;
- }
- if (src_num == cs40l26->num_log_srcs) {
- error = -ENODEV;
- goto err_mutex;
- }
- error = cl_dsp_get_reg(cs40l26->dsp, "DATA", CL_DSP_XM_UNPACKED_TYPE,
- CS40L26_LOGGER_ALGO_ID, ®);
- if (error)
- goto err_mutex;
- offset = (src_num * CS40L26_LOGGER_DATA_MAX_STEP) + CS40L26_LOGGER_DATA_MAX_OFFSET;
- error = regmap_read(cs40l26->regmap, reg + offset, max);
- err_mutex:
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- return error;
- }
- static ssize_t max_bemf_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 max_bemf;
- int error;
- error = cs40l26_logger_max_get(cs40l26, CS40L26_LOGGER_SRC_ID_BEMF, &max_bemf);
- return error ? error : snprintf(buf, PAGE_SIZE, "0x%06X\n", max_bemf);
- }
- static DEVICE_ATTR_RO(max_bemf);
- static ssize_t max_vbst_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 max_vbst;
- int error;
- error = cs40l26_logger_max_get(cs40l26, CS40L26_LOGGER_SRC_ID_VBST, &max_vbst);
- return error ? error : snprintf(buf, PAGE_SIZE, "0x%06X\n", max_vbst);
- }
- static DEVICE_ATTR_RO(max_vbst);
- static ssize_t max_vmon_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 max_vmon;
- int error;
- error = cs40l26_logger_max_get(cs40l26, CS40L26_LOGGER_SRC_ID_VMON, &max_vmon);
- return error ? error : snprintf(buf, PAGE_SIZE, "0x%06X\n", max_vmon);
- }
- static DEVICE_ATTR_RO(max_vmon);
- static ssize_t max_excursion_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 max_excursion;
- int error;
- error = cs40l26_logger_max_get(cs40l26, CS40L26_LOGGER_SRC_ID_EP, &max_excursion);
- return error ? error : snprintf(buf, PAGE_SIZE, "0x%06X\n", max_excursion);
- }
- static DEVICE_ATTR_RO(max_excursion);
- static ssize_t svc_le_est_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- unsigned int le;
- int error;
- error = cs40l26_pm_enter(cs40l26->dev);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- error = cs40l26_svc_le_estimate(cs40l26, &le);
- mutex_unlock(&cs40l26->lock);
- cs40l26_pm_exit(cs40l26->dev);
- if (error)
- return error;
- return snprintf(buf, PAGE_SIZE, "%u\n", le);
- }
- static DEVICE_ATTR_RO(svc_le_est);
- static ssize_t svc_le_stored_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- int error;
- mutex_lock(&cs40l26->lock);
- error = snprintf(buf, PAGE_SIZE, "%d\n", cs40l26->svc_le_est_stored);
- mutex_unlock(&cs40l26->lock);
- return error;
- }
- static ssize_t svc_le_stored_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cs40l26_private *cs40l26 = dev_get_drvdata(dev);
- u32 svc_le_stored;
- int error;
- error = kstrtou32(buf, 10, &svc_le_stored);
- if (error)
- return error;
- mutex_lock(&cs40l26->lock);
- cs40l26->svc_le_est_stored = svc_le_stored;
- mutex_unlock(&cs40l26->lock);
- return count;
- }
- static DEVICE_ATTR_RW(svc_le_stored);
- static struct attribute *cs40l26_dev_attrs_cal[] = {
- &dev_attr_svc_le_est.attr,
- &dev_attr_svc_le_stored.attr,
- &dev_attr_max_vbst.attr,
- &dev_attr_max_bemf.attr,
- &dev_attr_max_vmon.attr,
- &dev_attr_max_excursion.attr,
- &dev_attr_logging_max_reset.attr,
- &dev_attr_logging_en.attr,
- &dev_attr_trigger_calibration.attr,
- &dev_attr_f0_measured.attr,
- &dev_attr_q_measured.attr,
- &dev_attr_redc_measured.attr,
- &dev_attr_dvl_peq_coefficients.attr,
- &dev_attr_redc_est.attr,
- &dev_attr_f0_stored.attr,
- &dev_attr_q_stored.attr,
- &dev_attr_redc_stored.attr,
- &dev_attr_freq_centre.attr,
- &dev_attr_freq_span.attr,
- &dev_attr_f0_and_q_cal_time_ms.attr,
- &dev_attr_redc_cal_time_ms.attr,
- NULL,
- };
- struct attribute_group cs40l26_dev_attr_cal_group = {
- .name = "calibration",
- .attrs = cs40l26_dev_attrs_cal,
- };
|