| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979 |
- /*
- * Author: yucong xiong <yucong.xion@mediatek.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #include <linux/of.h>
- #include <linux/of_address.h>
- #include <linux/of_irq.h>
- #include <linux/gpio.h>
- #include "cust_alsps.h"
- #include "cm36652.h"
- #include "alsps.h"
- #ifdef CUSTOM_KERNEL_SENSORHUB
- #include <SCP_sensorHub.h>
- #endif
- /******************************************************************************
- * configuration
- *******************************************************************************/
- /*----------------------------------------------------------------------------*/
- #define CM36652_DEV_NAME "cm36652"
- /*----------------------------------------------------------------------------*/
- #define APS_TAG "[cm36652] "
- #define APS_ERR(fmt, args...) pr_err(APS_TAG fmt, ##args)
- #define APS_LOG(fmt, args...) pr_debug(APS_TAG fmt, ##args)
- #define APS_DBG(fmt, args...) pr_debug(APS_TAG fmt, ##args)
- #define I2C_FLAG_WRITE 0
- #define I2C_FLAG_READ 1
- /*----------------------------------------------------------------------------*/
- static int cm36652_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
- static int cm36652_i2c_remove(struct i2c_client *client);
- static int cm36652_i2c_detect(struct i2c_client *client, struct i2c_board_info *info);
- static int cm36652_i2c_suspend(struct i2c_client *client, pm_message_t msg);
- static int cm36652_i2c_resume(struct i2c_client *client);
- /*----------------------------------------------------------------------------*/
- static const struct i2c_device_id cm36652_i2c_id[] = {{CM36652_DEV_NAME, 0}, {} };
- /* static struct i2c_board_info __initdata i2c_cm36652={ I2C_BOARD_INFO(CM36652_DEV_NAME, 0x60)}; */
- static unsigned long long int_top_time;
- /* Maintain alsps cust info here */
- struct alsps_hw alsps_cust;
- static struct alsps_hw *hw = &alsps_cust;
- struct platform_device *alspsPltFmDev;
- /* For alsp driver get cust info */
- struct alsps_hw *get_cust_alsps(void)
- {
- return &alsps_cust;
- }
- /*----------------------------------------------------------------------------*/
- struct cm36652_priv {
- struct alsps_hw *hw;
- struct i2c_client *client;
- struct work_struct eint_work;
- #ifdef CUSTOM_KERNEL_SENSORHUB
- struct work_struct init_done_work;
- #endif
- /*misc*/
- u16 als_modulus;
- atomic_t i2c_retry;
- atomic_t als_suspend;
- atomic_t als_debounce; /*debounce time after enabling als*/
- atomic_t als_deb_on; /*indicates if the debounce is on*/
- atomic_t als_deb_end; /*the jiffies representing the end of debounce*/
- atomic_t ps_mask; /*mask ps: always return far away*/
- atomic_t ps_debounce; /*debounce time after enabling ps*/
- atomic_t ps_deb_on; /*indicates if the debounce is on*/
- atomic_t ps_deb_end; /*the jiffies representing the end of debounce*/
- atomic_t ps_suspend;
- atomic_t trace;
- atomic_t init_done;
- struct device_node *irq_node;
- int irq;
- /*data*/
- u16 als;
- u8 ps;
- u8 _align;
- u16 als_level_num;
- u16 als_value_num;
- u32 als_level[C_CUST_ALS_LEVEL-1];
- u32 als_value[C_CUST_ALS_LEVEL];
- int ps_cali;
- atomic_t als_cmd_val; /*the cmd value can't be read, stored in ram*/
- atomic_t ps_cmd_val; /*the cmd value can't be read, stored in ram*/
- atomic_t ps_thd_val_high; /*the cmd value can't be read, stored in ram*/
- atomic_t ps_thd_val_low; /*the cmd value can't be read, stored in ram*/
- atomic_t als_thd_val_high; /*the cmd value can't be read, stored in ram*/
- atomic_t als_thd_val_low; /*the cmd value can't be read, stored in ram*/
- atomic_t ps_thd_val;
- ulong enable; /*enable mask*/
- ulong pending_intr; /*pending interrupt*/
- };
- /*----------------------------------------------------------------------------*/
- #ifdef CONFIG_OF
- static const struct of_device_id alsps_of_match[] = {
- {.compatible = "mediatek,alsps"},
- {},
- };
- #endif
- static struct i2c_driver cm36652_i2c_driver = {
- .probe = cm36652_i2c_probe,
- .remove = cm36652_i2c_remove,
- .detect = cm36652_i2c_detect,
- .suspend = cm36652_i2c_suspend,
- .resume = cm36652_i2c_resume,
- .id_table = cm36652_i2c_id,
- .driver = {
- .name = CM36652_DEV_NAME,
- #ifdef CONFIG_OF
- .of_match_table = alsps_of_match,
- #endif
- },
- };
- /*----------------------------------------------------------------------------*/
- struct PS_CALI_DATA_STRUCT {
- int close;
- int far_away;
- int valid;
- };
- static struct i2c_client *cm36652_i2c_client;
- static struct cm36652_priv *cm36652_obj;
- /* static struct PS_CALI_DATA_STRUCT ps_cali={0,0,0}; */
- static int intr_flag = 1; /* hw default away after enable. */
- static int cm36652_local_init(void);
- static int cm36652_remove(void);
- static int cm36652_init_flag = -1;
- static struct alsps_init_info cm36652_init_info = {
- .name = "cm36652",
- .init = cm36652_local_init,
- .uninit = cm36652_remove,
- };
- static DEFINE_MUTEX(cm36652_mutex);
- enum {
- CMC_BIT_ALS = 1,
- CMC_BIT_PS = 2,
- } CMC_BIT;
- /*-----------------------------CMC for debugging-------------------------------*/
- enum {
- CMC_TRC_ALS_DATA = 0x0001,
- CMC_TRC_PS_DATA = 0x0002,
- CMC_TRC_EINT = 0x0004,
- CMC_TRC_IOCTL = 0x0008,
- CMC_TRC_I2C = 0x0010,
- CMC_TRC_CVT_ALS = 0x0020,
- CMC_TRC_CVT_PS = 0x0040,
- CMC_TRC_CVT_AAL = 0x0080,
- CMC_TRC_DEBUG = 0x8000,
- } CMC_TRC;
- int CM36652_i2c_master_operate(struct i2c_client *client, const char *buf, int count, int i2c_flag)
- {
- int res = 0;
- mutex_lock(&cm36652_mutex);
- switch (i2c_flag) {
- case I2C_FLAG_WRITE:
- client->addr &= I2C_MASK_FLAG;
- res = i2c_master_send(client, buf, count);
- client->addr &= I2C_MASK_FLAG;
- break;
- case I2C_FLAG_READ:
- client->addr &= I2C_MASK_FLAG;
- client->addr |= I2C_WR_FLAG;
- client->addr |= I2C_RS_FLAG;
- res = i2c_master_send(client, buf, count);
- client->addr &= I2C_MASK_FLAG;
- break;
- default:
- APS_LOG("CM36652_i2c_master_operate i2c_flag command not support!\n");
- break;
- }
- if (res < 0)
- goto EXIT_ERR;
- mutex_unlock(&cm36652_mutex);
- return res;
- EXIT_ERR:
- mutex_unlock(&cm36652_mutex);
- APS_ERR("CM36652_i2c_master_operate fail\n");
- return res;
- }
- /*----------------------------------------------------------------------------*/
- static void cm36652_power(struct alsps_hw *hw, unsigned int on)
- {
- }
- /********************************************************************/
- int cm36652_enable_ps(struct i2c_client *client, int enable)
- {
- struct cm36652_priv *obj = i2c_get_clientdata(client);
- int res;
- u8 databuf[3];
- if (enable == 1) {
- APS_LOG("cm36652_enable_ps enable_ps\n");
- databuf[0] = CM36652_REG_PS_CONF1_2;
- res = CM36652_i2c_master_operate(client, databuf, 0x201, I2C_FLAG_READ);
- if (res < 0) {
- APS_ERR("i2c_master_send function err\n");
- goto ENABLE_PS_EXIT_ERR;
- }
- APS_LOG("CM36652_REG_PS_CONF1_2 value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
- databuf[2] = databuf[1];
- databuf[1] = databuf[0]&0xFE;
- databuf[0] = CM36652_REG_PS_CONF1_2;
- res = CM36652_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
- if (res < 0) {
- APS_ERR("i2c_master_send function err\n");
- goto ENABLE_PS_EXIT_ERR;
- }
- atomic_set(&obj->ps_deb_on, 1);
- atomic_set(&obj->ps_deb_end, jiffies+atomic_read(&obj->ps_debounce)/(1000/HZ));
- intr_flag = 1; /* reset hw status to away after enable. */
- } else {
- APS_LOG("cm36652_enable_ps disable_ps\n");
- databuf[0] = CM36652_REG_PS_CONF1_2;
- res = CM36652_i2c_master_operate(client, databuf, 0x201, I2C_FLAG_READ);
- if (res < 0) {
- APS_ERR("i2c_master_send function err\n");
- goto ENABLE_PS_EXIT_ERR;
- }
- APS_LOG("CM36652_REG_PS_CONF1_2 value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
- databuf[2] = databuf[1];
- databuf[1] = databuf[0]|0x01;
- databuf[0] = CM36652_REG_PS_CONF1_2;
- res = CM36652_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
- if (res < 0) {
- APS_ERR("i2c_master_send function err\n");
- goto ENABLE_PS_EXIT_ERR;
- }
- atomic_set(&obj->ps_deb_on, 0);
- }
- return 0;
- ENABLE_PS_EXIT_ERR:
- return res;
- }
- /********************************************************************/
- int cm36652_enable_als(struct i2c_client *client, int enable)
- {
- struct cm36652_priv *obj = i2c_get_clientdata(client);
- int res;
- u8 databuf[3];
- if (enable == 1) {
- APS_LOG("cm36652_enable_als enable_als\n");
- databuf[0] = CM36652_REG_CS_CONF;
- res = CM36652_i2c_master_operate(client, databuf, 0x201, I2C_FLAG_READ);
- if (res < 0) {
- APS_ERR("i2c_master_send function err\n");
- goto ENABLE_ALS_EXIT_ERR;
- }
- APS_LOG("CM36652_REG_CS_CONF value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
- databuf[2] = databuf[1];
- databuf[1] = databuf[0]&0xFE;
- databuf[0] = CM36652_REG_CS_CONF;
- res = CM36652_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
- if (res < 0) {
- APS_ERR("i2c_master_send function err\n");
- goto ENABLE_ALS_EXIT_ERR;
- }
- atomic_set(&obj->als_deb_on, 1);
- atomic_set(&obj->als_deb_end, jiffies+atomic_read(&obj->als_debounce)/(1000/HZ));
- } else {
- APS_LOG("cm36652_enable_als disable_als\n");
- databuf[0] = CM36652_REG_CS_CONF;
- res = CM36652_i2c_master_operate(client, databuf, 0x201, I2C_FLAG_READ);
- if (res < 0) {
- APS_ERR("i2c_master_send function err\n");
- goto ENABLE_ALS_EXIT_ERR;
- }
- APS_LOG("CM36652_REG_CS_CONF value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
- databuf[2] = databuf[1];
- databuf[1] = databuf[0]|0x01;
- databuf[0] = CM36652_REG_CS_CONF;
- res = CM36652_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
- if (res < 0) {
- APS_ERR("i2c_master_send function err\n");
- goto ENABLE_ALS_EXIT_ERR;
- }
- atomic_set(&obj->als_deb_on, 0);
- }
- return 0;
- ENABLE_ALS_EXIT_ERR:
- return res;
- }
- /********************************************************************/
- long cm36652_read_ps(struct i2c_client *client, u8 *data)
- {
- long res;
- u8 databuf[2];
- struct cm36652_priv *obj = i2c_get_clientdata(client);
- databuf[0] = CM36652_REG_PS_DATA;
- res = CM36652_i2c_master_operate(client, databuf, 0x201, I2C_FLAG_READ);
- if (res < 0) {
- APS_ERR("i2c_master_send function err\n");
- goto READ_PS_EXIT_ERR;
- }
- if (atomic_read(&obj->trace) & CMC_TRC_DEBUG)
- APS_LOG("CM36652_REG_PS_DATA value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
- if (databuf[0] < obj->ps_cali)
- *data = 0;
- else
- *data = databuf[0] - obj->ps_cali;
- return 0;
- READ_PS_EXIT_ERR:
- return res;
- }
- /********************************************************************/
- long cm36652_read_als(struct i2c_client *client, u16 *data)
- {
- long res;
- u8 databuf[2];
- struct cm36652_priv *obj = i2c_get_clientdata(client);
- databuf[0] = CM36652_REG_ALS_DATA;
- res = CM36652_i2c_master_operate(client, databuf, 0x201, I2C_FLAG_READ);
- if (res < 0) {
- APS_ERR("i2c_master_send function err\n");
- goto READ_ALS_EXIT_ERR;
- }
- if (atomic_read(&obj->trace) & CMC_TRC_DEBUG)
- APS_LOG("CM36652_REG_ALS_DATA value: %d\n", ((databuf[1]<<8)|databuf[0]));
- *data = ((databuf[1]<<8)|databuf[0]);
- return 0;
- READ_ALS_EXIT_ERR:
- return res;
- }
- /********************************************************************/
- static int cm36652_get_ps_value(struct cm36652_priv *obj, u8 ps)
- {
- int val, mask = atomic_read(&obj->ps_mask);
- int invalid = 0;
- val = intr_flag; /* value between high/low threshold should sync. with hw status. */
- if (ps > atomic_read(&obj->ps_thd_val_high))
- val = 0; /*close*/
- else if (ps < atomic_read(&obj->ps_thd_val_low))
- val = 1; /*far away*/
- if (atomic_read(&obj->ps_suspend))
- invalid = 1;
- else if (1 == atomic_read(&obj->ps_deb_on)) {
- unsigned long endt = atomic_read(&obj->ps_deb_end);
- if (time_after(jiffies, endt))
- atomic_set(&obj->ps_deb_on, 0);
- if (1 == atomic_read(&obj->ps_deb_on))
- invalid = 1;
- }
- if (!invalid) {
- if (unlikely(atomic_read(&obj->trace) & CMC_TRC_CVT_PS)) {
- if (mask)
- APS_DBG("PS: %05d => %05d [M]\n", ps, val);
- else
- APS_DBG("PS: %05d => %05d\n", ps, val);
- }
- if ((0 == test_bit(CMC_BIT_PS, &obj->enable))) {
- APS_DBG("PS: not enable and do not report this value\n");
- return -1;
- } else
- return val;
- } else {
- if (unlikely(atomic_read(&obj->trace) & CMC_TRC_CVT_PS))
- APS_DBG("PS: %05d => %05d (-1)\n", ps, val);
- return -1;
- }
- }
- /********************************************************************/
- static int cm36652_get_als_value(struct cm36652_priv *obj, u16 als)
- {
- int idx = 0;
- int invalid = 0;
- int level_high = 0;
- int level_low = 0;
- int level_diff = 0;
- int value_high = 0;
- int value_low = 0;
- int value_diff = 0;
- int value = 0;
- if ((0 == obj->als_level_num) || (0 == obj->als_value_num)) {
- APS_ERR("invalid als_level_num = %d, als_value_num = %d\n", obj->als_level_num, obj->als_value_num);
- return -1;
- }
- if (1 == atomic_read(&obj->als_deb_on)) {
- unsigned long endt = atomic_read(&obj->als_deb_end);
- if (time_after(jiffies, endt))
- atomic_set(&obj->als_deb_on, 0);
- if (1 == atomic_read(&obj->als_deb_on))
- invalid = 1;
- }
- for (idx = 0; idx < obj->als_level_num; idx++) {
- if (als < obj->hw->als_level[idx])
- break;
- }
- if (idx >= obj->als_level_num || idx >= obj->als_value_num) {
- if (idx < obj->als_value_num)
- value = obj->hw->als_value[idx-1];
- else
- value = obj->hw->als_value[obj->als_value_num-1];
- } else {
- level_high = obj->hw->als_level[idx];
- level_low = (idx > 0) ? obj->hw->als_level[idx-1] : 0;
- level_diff = level_high - level_low;
- value_high = obj->hw->als_value[idx];
- value_low = (idx > 0) ? obj->hw->als_value[idx-1] : 0;
- value_diff = value_high - value_low;
- if ((level_low >= level_high) || (value_low >= value_high))
- value = value_low;
- else
- value = (level_diff * value_low + (als - level_low) * value_diff
- + ((level_diff + 1) >> 1)) / level_diff;
- }
- if (!invalid) {
- if (atomic_read(&obj->trace) & CMC_TRC_CVT_AAL)
- APS_DBG("ALS: %d [%d, %d] => %d [%d, %d]\n", als, level_low,
- level_high, value, value_low, value_high);
- } else {
- if (atomic_read(&obj->trace) & CMC_TRC_CVT_ALS)
- APS_DBG("ALS: %05d => %05d (-1)\n", als, value);
- return -1;
- }
- return value;
- }
- /*-------------------------------attribute file for debugging----------------------------------*/
- /******************************************************************************
- * Sysfs attributes
- *******************************************************************************/
- static ssize_t cm36652_show_config(struct device_driver *ddri, char *buf)
- {
- ssize_t res;
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- }
- res = snprintf(buf, PAGE_SIZE, "(%d %d %d %d %d)\n",
- atomic_read(&cm36652_obj->i2c_retry), atomic_read(&cm36652_obj->als_debounce),
- atomic_read(&cm36652_obj->ps_mask), atomic_read(&cm36652_obj->ps_thd_val),
- atomic_read(&cm36652_obj->ps_debounce));
- return res;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_store_config(struct device_driver *ddri, const char *buf, size_t count)
- {
- int retry, als_deb, ps_deb, mask, thres;
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- }
- if (5 == sscanf(buf, "%d %d %d %d %d", &retry, &als_deb, &mask, &thres, &ps_deb)) {
- atomic_set(&cm36652_obj->i2c_retry, retry);
- atomic_set(&cm36652_obj->als_debounce, als_deb);
- atomic_set(&cm36652_obj->ps_mask, mask);
- atomic_set(&cm36652_obj->ps_thd_val, thres);
- atomic_set(&cm36652_obj->ps_debounce, ps_deb);
- } else
- APS_ERR("invalid content: '%s', length = %zu\n", buf, count);
- return count;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_show_trace(struct device_driver *ddri, char *buf)
- {
- ssize_t res;
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- }
- res = snprintf(buf, PAGE_SIZE, "0x%04X\n", atomic_read(&cm36652_obj->trace));
- return res;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_store_trace(struct device_driver *ddri, const char *buf, size_t count)
- {
- int trace;
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- }
- if (1 == sscanf(buf, "0x%x", &trace))
- atomic_set(&cm36652_obj->trace, trace);
- else
- APS_ERR("invalid content: '%s', length = %zu\n", buf, count);
- return count;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_show_als(struct device_driver *ddri, char *buf)
- {
- int res;
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- }
- res = cm36652_read_als(cm36652_obj->client, &cm36652_obj->als);
- if (res)
- return snprintf(buf, PAGE_SIZE, "ERROR: %d\n", res);
- else
- return snprintf(buf, PAGE_SIZE, "0x%04X\n", cm36652_obj->als);
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_show_ps(struct device_driver *ddri, char *buf)
- {
- ssize_t res;
- if (!cm36652_obj) {
- APS_ERR("cm3623_obj is null!!\n");
- return 0;
- }
- res = cm36652_read_ps(cm36652_obj->client, &cm36652_obj->ps);
- if (res)
- return snprintf(buf, PAGE_SIZE, "ERROR: %d\n", (int)res);
- else
- return snprintf(buf, PAGE_SIZE, "0x%04X\n", cm36652_obj->ps);
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_show_reg(struct device_driver *ddri, char *buf)
- {
- u8 _bIndex = 0;
- u8 databuf[2] = {0};
- ssize_t _tLength = 0;
- if (!cm36652_obj) {
- APS_ERR("cm3623_obj is null!!\n");
- return 0;
- }
- for (_bIndex = 0; _bIndex < 0x0D; _bIndex++) {
- databuf[0] = _bIndex;
- CM36652_i2c_master_operate(cm36652_obj->client, databuf, 0x201, I2C_FLAG_READ);
- _tLength += snprintf((buf + _tLength), (PAGE_SIZE - _tLength),
- "Reg[0x%02X]: 0x%02X\n", _bIndex, databuf[0]);
- }
- return _tLength;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_show_send(struct device_driver *ddri, char *buf)
- {
- return 0;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_store_send(struct device_driver *ddri, const char *buf, size_t count)
- {
- int addr, cmd;
- u8 dat;
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- } else if (2 != sscanf(buf, "%x %x", &addr, &cmd)) {
- APS_ERR("invalid format: '%s'\n", buf);
- return 0;
- }
- dat = (u8)cmd;
- return count;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_show_recv(struct device_driver *ddri, char *buf)
- {
- return 0;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_store_recv(struct device_driver *ddri, const char *buf, size_t count)
- {
- int *addr = NULL;
- int ret;
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- }
- /*} else if (1 != sscanf(buf, "%x", &addr)) {*/
- ret = kstrtoint(buf, 16, addr);
- if (ret < 0) {
- APS_ERR("invalid format: '%s'\n", buf);
- return ret;
- }
- return count;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_show_status(struct device_driver *ddri, char *buf)
- {
- ssize_t len = 0;
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- }
- if (cm36652_obj->hw) {
- len += snprintf(buf+len, PAGE_SIZE-len, "CUST: %d, (%d %d)\n",
- cm36652_obj->hw->i2c_num, cm36652_obj->hw->power_id, cm36652_obj->hw->power_vol);
- } else
- len += snprintf(buf+len, PAGE_SIZE-len, "CUST: NULL\n");
- len += snprintf(buf+len, PAGE_SIZE-len, "REGS: %02X %02X %02X %02lX %02lX\n",
- atomic_read(&cm36652_obj->als_cmd_val), atomic_read(&cm36652_obj->ps_cmd_val),
- atomic_read(&cm36652_obj->ps_thd_val), cm36652_obj->enable, cm36652_obj->pending_intr);
- len += snprintf(buf+len, PAGE_SIZE-len, "MISC: %d %d\n",
- atomic_read(&cm36652_obj->als_suspend), atomic_read(&cm36652_obj->ps_suspend));
- return len;
- }
- /*----------------------------------------------------------------------------*/
- #define IS_SPACE(CH) (((CH) == ' ') || ((CH) == '\n'))
- /*----------------------------------------------------------------------------*/
- static int read_int_from_buf(struct cm36652_priv *obj, const char *buf, size_t count, u32 data[], int len)
- {
- int idx = 0;
- int ret;
- char *cur = (char *)buf, *end = (char *)(buf+count);
- while (idx < len) {
- while ((cur < end) && IS_SPACE(*cur))
- cur++;
- ret = kstrtoint(cur, 10, &data[idx]);
- if (ret < 0)
- break;
- idx++;
- while ((cur < end) && !IS_SPACE(*cur))
- cur++;
- }
- return idx;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_show_alslv(struct device_driver *ddri, char *buf)
- {
- ssize_t len = 0;
- int idx;
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- }
- for (idx = 0; idx < cm36652_obj->als_level_num; idx++)
- len += snprintf(buf+len, PAGE_SIZE-len, "%d ", cm36652_obj->hw->als_level[idx]);
- len += snprintf(buf+len, PAGE_SIZE-len, "\n");
- return len;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_store_alslv(struct device_driver *ddri, const char *buf, size_t count)
- {
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- } else if (!strcmp(buf, "def"))
- memcpy(cm36652_obj->als_level, cm36652_obj->hw->als_level, sizeof(cm36652_obj->als_level));
- else if (cm36652_obj->als_level_num != read_int_from_buf(cm36652_obj, buf, count,
- cm36652_obj->hw->als_level, cm36652_obj->als_level_num))
- APS_ERR("invalid format: '%s'\n", buf);
- return count;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_show_alsval(struct device_driver *ddri, char *buf)
- {
- ssize_t len = 0;
- int idx;
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- }
- for (idx = 0; idx < cm36652_obj->als_value_num; idx++)
- len += snprintf(buf+len, PAGE_SIZE-len, "%d ", cm36652_obj->hw->als_value[idx]);
- len += snprintf(buf+len, PAGE_SIZE-len, "\n");
- return len;
- }
- /*----------------------------------------------------------------------------*/
- static ssize_t cm36652_store_alsval(struct device_driver *ddri, const char *buf, size_t count)
- {
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return 0;
- } else if (!strcmp(buf, "def"))
- memcpy(cm36652_obj->als_value, cm36652_obj->hw->als_value, sizeof(cm36652_obj->als_value));
- else if (cm36652_obj->als_value_num != read_int_from_buf(cm36652_obj, buf, count,
- cm36652_obj->hw->als_value, cm36652_obj->als_value_num))
- APS_ERR("invalid format: '%s'\n", buf);
- return count;
- }
- /*---------------------------------------------------------------------------------------*/
- static DRIVER_ATTR(als, S_IWUSR | S_IRUGO, cm36652_show_als, NULL);
- static DRIVER_ATTR(ps, S_IWUSR | S_IRUGO, cm36652_show_ps, NULL);
- static DRIVER_ATTR(config, S_IWUSR | S_IRUGO, cm36652_show_config, cm36652_store_config);
- static DRIVER_ATTR(alslv, S_IWUSR | S_IRUGO, cm36652_show_alslv, cm36652_store_alslv);
- static DRIVER_ATTR(alsval, S_IWUSR | S_IRUGO, cm36652_show_alsval, cm36652_store_alsval);
- static DRIVER_ATTR(trace, S_IWUSR | S_IRUGO, cm36652_show_trace, cm36652_store_trace);
- static DRIVER_ATTR(status, S_IWUSR | S_IRUGO, cm36652_show_status, NULL);
- static DRIVER_ATTR(send, S_IWUSR | S_IRUGO, cm36652_show_send, cm36652_store_send);
- static DRIVER_ATTR(recv, S_IWUSR | S_IRUGO, cm36652_show_recv, cm36652_store_recv);
- static DRIVER_ATTR(reg, S_IWUSR | S_IRUGO, cm36652_show_reg, NULL);
- /*----------------------------------------------------------------------------*/
- static struct driver_attribute *cm36652_attr_list[] = {
- &driver_attr_als,
- &driver_attr_ps,
- &driver_attr_trace, /*trace log*/
- &driver_attr_config,
- &driver_attr_alslv,
- &driver_attr_alsval,
- &driver_attr_status,
- &driver_attr_send,
- &driver_attr_recv,
- &driver_attr_reg,
- };
- /*----------------------------------------------------------------------------*/
- static int cm36652_create_attr(struct device_driver *driver)
- {
- int idx, err = 0;
- int num = (int)(sizeof(cm36652_attr_list)/sizeof(cm36652_attr_list[0]));
- if (driver == NULL)
- return -EINVAL;
- for (idx = 0; idx < num; idx++) {
- err = driver_create_file(driver, cm36652_attr_list[idx]);
- if (err) {
- APS_ERR("driver_create_file (%s) = %d\n", cm36652_attr_list[idx]->attr.name, err);
- break;
- }
- }
- return err;
- }
- /*----------------------------------------------------------------------------*/
- static int cm36652_delete_attr(struct device_driver *driver)
- {
- int idx , err = 0;
- int num = (int)(sizeof(cm36652_attr_list)/sizeof(cm36652_attr_list[0]));
- if (!driver)
- return -EINVAL;
- for (idx = 0; idx < num; idx++)
- driver_remove_file(driver, cm36652_attr_list[idx]);
- return err;
- }
- /*----------------------------------------------------------------------------*/
- /*----------------------------------interrupt functions--------------------------------*/
- #ifndef CUSTOM_KERNEL_SENSORHUB
- static int cm36652_check_intr(struct i2c_client *client)
- {
- int res;
- u8 databuf[2];
- databuf[0] = CM36652_REG_PS_DATA;
- res = CM36652_i2c_master_operate(client, databuf, 0x201, I2C_FLAG_READ);
- if (res < 0) {
- APS_ERR("i2c_master_send function err res = %d\n", res);
- goto EXIT_ERR;
- }
- APS_LOG("CM36652_REG_PS_DATA value value_low = %x, value_reserve = %x\n", databuf[0], databuf[1]);
- databuf[0] = CM36652_REG_INT_FLAG;
- res = CM36652_i2c_master_operate(client, databuf, 0x201, I2C_FLAG_READ);
- if (res < 0) {
- APS_ERR("i2c_master_send function err res = %d\n", res);
- goto EXIT_ERR;
- }
- APS_LOG("CM36652_REG_INT_FLAG value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
- if (databuf[1]&0x02)
- intr_flag = 0;/* for close */
- else if (databuf[1]&0x01)
- intr_flag = 1;/* for away */
- else {
- res = -1;
- APS_ERR("cm36652_check_intr fail databuf[1]&0x01: %d\n", res);
- goto EXIT_ERR;
- }
- return 0;
- EXIT_ERR:
- APS_ERR("cm36652_check_intr dev: %d\n", res);
- return res;
- }
- #endif /* #ifndef CUSTOM_KERNEL_SENSORHUB */
- /*----------------------------------------------------------------------------*/
- static void cm36652_eint_work(struct work_struct *work)
- {
- #ifdef CUSTOM_KERNEL_SENSORHUB
- int res = 0;
- res = ps_report_interrupt_data(intr_flag);
- if (res != 0)
- APS_ERR("cm36652_eint_work err: %d\n", res);
- #else /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- struct cm36652_priv *obj = (struct cm36652_priv *)container_of(work, struct cm36652_priv, eint_work);
- int res = 0;
- APS_LOG("cm36652 int top half time = %lld\n", int_top_time);
- res = cm36652_check_intr(obj->client);
- if (res != 0)
- goto EXIT_INTR_ERR;
- else {
- APS_LOG("cm36652 interrupt value = %d\n", intr_flag);
- res = ps_report_interrupt_data(intr_flag);
- }
- #if defined(CONFIG_OF)
- enable_irq(obj->irq);
- #elif defined(CUST_EINT_ALS_TYPE)
- mt_eint_unmask(CUST_EINT_ALS_NUM);
- #else
- mt65xx_eint_unmask(CUST_EINT_ALS_NUM);
- #endif
- return;
- EXIT_INTR_ERR:
- #if defined(CONFIG_OF)
- enable_irq(obj->irq);
- #elif defined(CUST_EINT_ALS_TYPE)
- mt_eint_unmask(CUST_EINT_ALS_NUM);
- #else
- mt65xx_eint_unmask(CUST_EINT_ALS_NUM);
- #endif
- APS_ERR("cm36652_eint_work err: %d\n", res);
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- }
- /*----------------------------------------------------------------------------*/
- #ifdef CUSTOM_KERNEL_SENSORHUB
- static void cm36652_init_done_work(struct work_struct *work)
- {
- struct cm36652_priv *obj = cm36652_obj;
- struct CM36652_CUST_DATA *p_cust_data;
- SCP_SENSOR_HUB_DATA data;
- int max_cust_data_size_per_packet;
- int i;
- uint sizeOfCustData;
- uint len;
- char *p = (char *)obj->hw;
- APS_FUN();
- p_cust_data = (struct CM36652_CUST_DATA *)data.set_cust_req.custData;
- sizeOfCustData = sizeof(*(obj->hw));
- max_cust_data_size_per_packet = sizeof(data.set_cust_req.custData) - offsetof(struct CM36652_SET_CUST, data);
- for (i = 0; sizeOfCustData > 0; i++) {
- data.set_cust_req.sensorType = ID_PROXIMITY;
- data.set_cust_req.action = SENSOR_HUB_SET_CUST;
- p_cust_data->setCust.action = CM36652_CUST_ACTION_SET_CUST;
- p_cust_data->setCust.part = i;
- if (sizeOfCustData > max_cust_data_size_per_packet)
- len = max_cust_data_size_per_packet;
- else
- len = sizeOfCustData;
- memcpy(p_cust_data->setCust.data, p, len);
- sizeOfCustData -= len;
- p += len;
- len += offsetof(SCP_SENSOR_HUB_SET_CUST_REQ, custData) + offsetof(struct CM36652_SET_CUST, data);
- SCP_sensorHub_req_send(&data, &len, 1);
- }
- data.set_cust_req.sensorType = ID_PROXIMITY;
- data.set_cust_req.action = SENSOR_HUB_SET_CUST;
- p_cust_data->setEintInfo.action = CM36652_CUST_ACTION_SET_EINT_INFO;
- p_cust_data->setEintInfo.gpio_mode = GPIO_ALS_EINT_PIN_M_EINT;
- p_cust_data->setEintInfo.gpio_pin = GPIO_ALS_EINT_PIN;
- p_cust_data->setEintInfo.eint_num = CUST_EINT_ALS_NUM;
- p_cust_data->setEintInfo.eint_is_deb_en = CUST_EINT_ALS_DEBOUNCE_EN;
- p_cust_data->setEintInfo.eint_type = CUST_EINT_ALS_TYPE;
- len = offsetof(SCP_SENSOR_HUB_SET_CUST_REQ, custData) + sizeof(p_cust_data->setEintInfo);
- SCP_sensorHub_req_send(&data, &len, 1);
- mutex_lock(&cm36652_mutex);
- data.activate_req.sensorType = ID_PROXIMITY;
- data.activate_req.action = SENSOR_HUB_ACTIVATE;
- if (test_bit(CMC_BIT_PS, &obj->enable))
- data.activate_req.enable = 1;
- else
- data.activate_req.enable = 0;
- len = sizeof(data.activate_req);
- SCP_sensorHub_req_send(&data, &len, 1);
- data.activate_req.sensorType = ID_LIGHT;
- if (test_bit(CMC_BIT_ALS, &obj->enable))
- data.activate_req.enable = 1;
- else
- data.activate_req.enable = 0;
- len = sizeof(data.activate_req);
- SCP_sensorHub_req_send(&data, &len, 1);
- mutex_unlock(&cm36652_mutex);
- atomic_set(&obj->init_done, 1);
- }
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- /*----------------------------------------------------------------------------*/
- static void cm36652_eint_func(void)
- {
- struct cm36652_priv *obj = cm36652_obj;
- if (!obj)
- return;
- int_top_time = sched_clock();
- schedule_work(&obj->eint_work);
- }
- #if defined(CONFIG_OF)
- static irqreturn_t cm36652_eint_handler(int irq, void *desc)
- {
- cm36652_eint_func();
- disable_irq_nosync(cm36652_obj->irq);
- return IRQ_HANDLED;
- }
- #endif
- /*----------------------------------------------------------------------------*/
- #ifdef CUSTOM_KERNEL_SENSORHUB
- static int cm36652_irq_handler(void *data, uint len)
- {
- struct cm36652_priv *obj = cm36652_obj;
- SCP_SENSOR_HUB_DATA_P rsp = (SCP_SENSOR_HUB_DATA_P)data;
- if (!obj)
- return -1;
- APS_ERR("len = %d, type = %d, action = %d, errCode = %d\n",
- len, rsp->rsp.sensorType, rsp->rsp.action, rsp->rsp.errCode);
- switch (rsp->rsp.action) {
- case SENSOR_HUB_NOTIFY:
- switch (rsp->notify_rsp.event) {
- case SCP_INIT_DONE:
- schedule_work(&obj->init_done_work);
- /* schedule_delayed_work(&obj->init_done_work, HZ); */
- break;
- case SCP_NOTIFY:
- if (CM36652_NOTIFY_PROXIMITY_CHANGE == rsp->notify_rsp.data[0]) {
- intr_flag = rsp->notify_rsp.data[1];
- cm36652_eint_func();
- } else
- APS_ERR("Unknown notify");
- break;
- default:
- APS_ERR("Error sensor hub notify");
- break;
- }
- break;
- default:
- APS_ERR("Error sensor hub action");
- break;
- }
- return 0;
- }
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- /*----------------------------------------------------------------------------*/
- int cm36652_setup_eint(struct i2c_client *client)
- {
- #ifdef CUSTOM_KERNEL_SENSORHUB
- int err = 0;
- err = SCP_sensorHub_rsp_registration(ID_PROXIMITY, cm36652_irq_handler);
- #else /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- int ret;
- struct pinctrl *pinctrl;
- struct pinctrl_state *pins_default;
- struct pinctrl_state *pins_cfg;
- u32 ints[2] = {0, 0};
- alspsPltFmDev = get_alsps_platformdev();
- /* gpio setting */
- pinctrl = devm_pinctrl_get(&alspsPltFmDev->dev);
- if (IS_ERR(pinctrl)) {
- ret = PTR_ERR(pinctrl);
- APS_ERR("Cannot find alsps pinctrl!\n");
- }
- pins_default = pinctrl_lookup_state(pinctrl, "pin_default");
- if (IS_ERR(pins_default)) {
- ret = PTR_ERR(pins_default);
- APS_ERR("Cannot find alsps pinctrl default!\n");
- }
- pins_cfg = pinctrl_lookup_state(pinctrl, "pin_cfg");
- if (IS_ERR(pins_cfg)) {
- ret = PTR_ERR(pins_cfg);
- APS_ERR("Cannot find alsps pinctrl pin_cfg!\n");
- }
- /* eint request */
- if (cm36652_obj->irq_node) {
- of_property_read_u32_array(cm36652_obj->irq_node, "debounce", ints, ARRAY_SIZE(ints));
- gpio_request(ints[0], "p-sensor");
- gpio_set_debounce(ints[0], ints[1]);
- pinctrl_select_state(pinctrl, pins_cfg);
- APS_LOG("ints[0] = %d, ints[1] = %d!!\n", ints[0], ints[1]);
- cm36652_obj->irq = irq_of_parse_and_map(cm36652_obj->irq_node, 0);
- APS_LOG("cm36652_obj->irq = %d\n", cm36652_obj->irq);
- if (!cm36652_obj->irq) {
- APS_ERR("irq_of_parse_and_map fail!!\n");
- return -EINVAL;
- }
- if (request_irq(cm36652_obj->irq, cm36652_eint_handler, IRQF_TRIGGER_NONE, "ALS-eint", NULL)) {
- APS_ERR("IRQ LINE NOT AVAILABLE!!\n");
- return -EINVAL;
- }
- enable_irq(cm36652_obj->irq);
- } else {
- APS_ERR("null irq node!!\n");
- return -EINVAL;
- }
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- return 0;
- }
- /*-------------------------------MISC device related------------------------------------------*/
- /************************************************************/
- static int cm36652_open(struct inode *inode, struct file *file)
- {
- file->private_data = cm36652_i2c_client;
- if (!file->private_data) {
- APS_ERR("null pointer!!\n");
- return -EINVAL;
- }
- return nonseekable_open(inode, file);
- }
- /************************************************************/
- static int cm36652_release(struct inode *inode, struct file *file)
- {
- file->private_data = NULL;
- return 0;
- }
- /************************************************************/
- static int set_psensor_threshold(struct i2c_client *client)
- {
- struct cm36652_priv *obj = i2c_get_clientdata(client);
- int res = 0;
- #ifdef CUSTOM_KERNEL_SENSORHUB
- SCP_SENSOR_HUB_DATA data;
- struct CM36652_CUST_DATA *pCustData;
- int len;
- int32_t ps_thd_val_low, ps_thd_val_high;
- ps_thd_val_low = atomic_read(&obj->ps_thd_val_low);
- ps_thd_val_high = atomic_read(&obj->ps_thd_val_high);
- /* ps_cali would be add back in SCP side. */
- ps_thd_val_low -= obj->ps_cali;
- ps_thd_val_high -= obj->ps_cali;
- data.set_cust_req.sensorType = ID_PROXIMITY;
- data.set_cust_req.action = SENSOR_HUB_SET_CUST;
- pCustData = (struct CM36652_CUST_DATA *)(&data.set_cust_req.custData);
- pCustData->setPSThreshold.action = CM36652_CUST_ACTION_SET_PS_THRESHODL;
- pCustData->setPSThreshold.threshold[0] = ps_thd_val_low;
- pCustData->setPSThreshold.threshold[1] = ps_thd_val_high;
- len = offsetof(SCP_SENSOR_HUB_SET_CUST_REQ, custData) + sizeof(pCustData->setPSThreshold);
- res = SCP_sensorHub_req_send(&data, &len, 1);
- #else /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- u8 databuf[3];
- APS_ERR("set_psensor_threshold function high: 0x%x, low:0x%x\n",
- atomic_read(&obj->ps_thd_val_high), atomic_read(&obj->ps_thd_val_low));
- databuf[0] = CM36652_REG_PS_THD;
- databuf[1] = atomic_read(&obj->ps_thd_val_low);
- databuf[2] = atomic_read(&obj->ps_thd_val_high);/* threshold value need to confirm */
- res = CM36652_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
- if (res <= 0) {
- APS_ERR("i2c_master_send function err\n");
- return -1;
- }
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- return 0;
- }
- static long cm36652_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- {
- struct i2c_client *client = (struct i2c_client *)file->private_data;
- struct cm36652_priv *obj = i2c_get_clientdata(client);
- long err = 0;
- void __user *ptr = (void __user *) arg;
- int dat;
- uint32_t enable;
- int ps_result;
- int ps_cali;
- int threshold[2];
- #ifdef CUSTOM_KERNEL_SENSORHUB
- SCP_SENSOR_HUB_DATA data;
- struct CM36652_CUST_DATA *pCustData;
- int len;
- data.set_cust_req.sensorType = ID_PROXIMITY;
- data.set_cust_req.action = SENSOR_HUB_SET_CUST;
- pCustData = (struct CM36652_CUST_DATA *)(&data.set_cust_req.custData);
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- switch (cmd) {
- case ALSPS_SET_PS_MODE:
- if (copy_from_user(&enable, ptr, sizeof(enable))) {
- err = -EFAULT;
- goto err_out;
- }
- if (enable) {
- err = cm36652_enable_ps(obj->client, 1);
- if (err) {
- APS_ERR("enable ps fail: %ld\n", err);
- goto err_out;
- }
- set_bit(CMC_BIT_PS, &obj->enable);
- } else {
- err = cm36652_enable_ps(obj->client, 0);
- if (err) {
- APS_ERR("disable ps fail: %ld\n", err);
- goto err_out;
- }
- clear_bit(CMC_BIT_PS, &obj->enable);
- }
- break;
- case ALSPS_GET_PS_MODE:
- enable = test_bit(CMC_BIT_PS, &obj->enable) ? (1) : (0);
- if (copy_to_user(ptr, &enable, sizeof(enable))) {
- err = -EFAULT;
- goto err_out;
- }
- break;
- case ALSPS_GET_PS_DATA:
- err = cm36652_read_ps(obj->client, &obj->ps);
- if (err)
- goto err_out;
- dat = cm36652_get_ps_value(obj, obj->ps);
- if (copy_to_user(ptr, &dat, sizeof(dat))) {
- err = -EFAULT;
- goto err_out;
- }
- break;
- case ALSPS_GET_PS_RAW_DATA:
- err = cm36652_read_ps(obj->client, &obj->ps);
- if (err)
- goto err_out;
- dat = obj->ps;
- if (copy_to_user(ptr, &dat, sizeof(dat))) {
- err = -EFAULT;
- goto err_out;
- }
- break;
- case ALSPS_SET_ALS_MODE:
- if (copy_from_user(&enable, ptr, sizeof(enable))) {
- err = -EFAULT;
- goto err_out;
- }
- if (enable) {
- err = cm36652_enable_als(obj->client, 1);
- if (err) {
- APS_ERR("enable als fail: %ld\n", err);
- goto err_out;
- }
- set_bit(CMC_BIT_ALS, &obj->enable);
- } else {
- err = cm36652_enable_als(obj->client, 0);
- if (err) {
- APS_ERR("disable als fail: %ld\n", err);
- goto err_out;
- }
- clear_bit(CMC_BIT_ALS, &obj->enable);
- }
- break;
- case ALSPS_GET_ALS_MODE:
- enable = test_bit(CMC_BIT_ALS, &obj->enable) ? (1) : (0);
- if (copy_to_user(ptr, &enable, sizeof(enable))) {
- err = -EFAULT;
- goto err_out;
- }
- break;
- case ALSPS_GET_ALS_DATA:
- err = cm36652_read_als(obj->client, &obj->als);
- if (err)
- goto err_out;
- dat = cm36652_get_als_value(obj, obj->als);
- if (copy_to_user(ptr, &dat, sizeof(dat))) {
- err = -EFAULT;
- goto err_out;
- }
- break;
- case ALSPS_GET_ALS_RAW_DATA:
- err = cm36652_read_als(obj->client, &obj->als);
- if (err)
- goto err_out;
- dat = obj->als;
- if (copy_to_user(ptr, &dat, sizeof(dat))) {
- err = -EFAULT;
- goto err_out;
- }
- break;
- /*----------------------------------for factory mode test---------------------------------------*/
- case ALSPS_GET_PS_TEST_RESULT:
- err = cm36652_read_ps(obj->client, &obj->ps);
- if (err)
- goto err_out;
- if (obj->ps > atomic_read(&obj->ps_thd_val_low))
- ps_result = 0;
- else
- ps_result = 1;
- if (copy_to_user(ptr, &ps_result, sizeof(ps_result))) {
- err = -EFAULT;
- goto err_out;
- }
- break;
- case ALSPS_IOCTL_CLR_CALI:
- if (copy_from_user(&dat, ptr, sizeof(dat))) {
- err = -EFAULT;
- goto err_out;
- }
- if (dat == 0)
- obj->ps_cali = 0;
- #ifdef CUSTOM_KERNEL_SENSORHUB
- pCustData->clearCali.action = CM36652_CUST_ACTION_CLR_CALI;
- len = offsetof(SCP_SENSOR_HUB_SET_CUST_REQ, custData) + sizeof(pCustData->clearCali);
- err = SCP_sensorHub_req_send(&data, &len, 1);
- #endif
- break;
- case ALSPS_IOCTL_GET_CALI:
- ps_cali = obj->ps_cali;
- if (copy_to_user(ptr, &ps_cali, sizeof(ps_cali))) {
- err = -EFAULT;
- goto err_out;
- }
- break;
- case ALSPS_IOCTL_SET_CALI:
- if (copy_from_user(&ps_cali, ptr, sizeof(ps_cali))) {
- err = -EFAULT;
- goto err_out;
- }
- obj->ps_cali = ps_cali;
- #ifdef CUSTOM_KERNEL_SENSORHUB
- pCustData->setCali.action = CM36652_CUST_ACTION_SET_CALI;
- pCustData->setCali.cali = ps_cali;
- len = offsetof(SCP_SENSOR_HUB_SET_CUST_REQ, custData) + sizeof(pCustData->setCali);
- err = SCP_sensorHub_req_send(&data, &len, 1);
- #endif
- break;
- case ALSPS_SET_PS_THRESHOLD:
- if (copy_from_user(threshold, ptr, sizeof(threshold))) {
- err = -EFAULT;
- goto err_out;
- }
- APS_ERR("%s set threshold high: 0x%x, low: 0x%x\n", __func__, threshold[0], threshold[1]);
- atomic_set(&obj->ps_thd_val_high, (threshold[0]+obj->ps_cali));
- atomic_set(&obj->ps_thd_val_low, (threshold[1]+obj->ps_cali));/* need to confirm */
- set_psensor_threshold(obj->client);
- break;
- case ALSPS_GET_PS_THRESHOLD_HIGH:
- threshold[0] = atomic_read(&obj->ps_thd_val_high) - obj->ps_cali;
- APS_ERR("%s get threshold high: 0x%x\n", __func__, threshold[0]);
- if (copy_to_user(ptr, &threshold[0], sizeof(threshold[0]))) {
- err = -EFAULT;
- goto err_out;
- }
- break;
- case ALSPS_GET_PS_THRESHOLD_LOW:
- threshold[0] = atomic_read(&obj->ps_thd_val_low) - obj->ps_cali;
- APS_ERR("%s get threshold low: 0x%x\n", __func__, threshold[0]);
- if (copy_to_user(ptr, &threshold[0], sizeof(threshold[0]))) {
- err = -EFAULT;
- goto err_out;
- }
- break;
- default:
- APS_ERR("%s not supported = 0x%04x", __func__, cmd);
- err = -ENOIOCTLCMD;
- break;
- }
- err_out:
- return err;
- }
- /*------------------------------misc device related operation functions------------------------------------*/
- static const struct file_operations cm36652_fops = {
- .owner = THIS_MODULE,
- .open = cm36652_open,
- .release = cm36652_release,
- .unlocked_ioctl = cm36652_unlocked_ioctl,
- };
- static struct miscdevice cm36652_device = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "als_ps",
- .fops = &cm36652_fops,
- };
- /*--------------------------------------------------------------------------------*/
- static int cm36652_init_client(struct i2c_client *client)
- {
- struct cm36652_priv *obj = i2c_get_clientdata(client);
- u8 databuf[3];
- int res = 0;
- databuf[0] = CM36652_REG_CS_CONF;
- if (1 == obj->hw->polling_mode_als)
- databuf[1] = 0x11;
- else
- databuf[1] = 0x17;
- databuf[2] = 0x0;
- res = CM36652_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
- if (res <= 0) {
- APS_ERR("i2c_master_send function err\n");
- goto EXIT_ERR;
- }
- APS_LOG("cm36652 ps CM36652_REG_CS_CONF command!\n");
- databuf[0] = CM36652_REG_PS_CONF1_2;
- databuf[1] = 0x19;
- if (1 == obj->hw->polling_mode_ps)
- databuf[2] = 0x60;
- else
- databuf[2] = 0x62;
- res = CM36652_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
- if (res <= 0) {
- APS_ERR("i2c_master_send function err\n");
- goto EXIT_ERR;
- }
- APS_LOG("cm36652 ps CM36652_REG_PS_CONF1_2 command!\n");
- databuf[0] = CM36652_REG_PS_CANC;/* value need to confirm */
- databuf[1] = 0x00;
- databuf[2] = 0x00;
- res = CM36652_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
- if (res <= 0) {
- APS_ERR("i2c_master_send function err\n");
- goto EXIT_ERR;
- }
- APS_LOG("cm36652 ps CM36652_REG_PS_CANC command!\n");
- if (0 == obj->hw->polling_mode_als) {
- databuf[0] = CM36652_REG_ALS_THDH;
- databuf[1] = 0x00;
- databuf[2] = atomic_read(&obj->als_thd_val_high);
- res = CM36652_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
- if (res <= 0) {
- APS_ERR("i2c_master_send function err\n");
- goto EXIT_ERR;
- }
- databuf[0] = CM36652_REG_ALS_THDL;
- databuf[1] = 0x00;
- databuf[2] = atomic_read(&obj->als_thd_val_low);/* threshold value need to confirm */
- res = CM36652_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
- if (res <= 0) {
- APS_ERR("i2c_master_send function err\n");
- goto EXIT_ERR;
- }
- }
- if (0 == obj->hw->polling_mode_ps) {
- databuf[0] = CM36652_REG_PS_THD;
- databuf[1] = atomic_read(&obj->ps_thd_val_low);
- databuf[2] = atomic_read(&obj->ps_thd_val_high);/* threshold value need to confirm */
- res = CM36652_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
- if (res <= 0) {
- APS_ERR("i2c_master_send function err\n");
- goto EXIT_ERR;
- }
- }
- res = cm36652_setup_eint(client);
- if (res != 0) {
- APS_ERR("setup eint: %d\n", res);
- return res;
- }
- return CM36652_SUCCESS;
- EXIT_ERR:
- APS_ERR("init dev: %d\n", res);
- return res;
- }
- /*--------------------------------------------------------------------------------*/
- /* if use this typ of enable , Gsensor should report inputEvent(x, y, z ,stats, div) to HAL */
- static int als_open_report_data(int open)
- {
- /* should queuq work to report event if is_report_input_direct=true */
- return 0;
- }
- /* if use this typ of enable , Gsensor only enabled but not report inputEvent to HAL */
- static int als_enable_nodata(int en)
- {
- int res = 0;
- #ifdef CUSTOM_KERNEL_SENSORHUB
- SCP_SENSOR_HUB_DATA req;
- int len;
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- APS_LOG("cm36652_obj als enable value = %d\n", en);
- #ifdef CUSTOM_KERNEL_SENSORHUB
- if (atomic_read(&cm36652_obj->init_done)) {
- req.activate_req.sensorType = ID_LIGHT;
- req.activate_req.action = SENSOR_HUB_ACTIVATE;
- req.activate_req.enable = en;
- len = sizeof(req.activate_req);
- res = SCP_sensorHub_req_send(&req, &len, 1);
- } else
- APS_ERR("sensor hub has not been ready!!\n");
- mutex_lock(&cm36652_mutex);
- if (en)
- set_bit(CMC_BIT_ALS, &cm36652_obj->enable);
- else
- clear_bit(CMC_BIT_ALS, &cm36652_obj->enable);
- mutex_unlock(&cm36652_mutex);
- #else /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- mutex_lock(&cm36652_mutex);
- if (en)
- set_bit(CMC_BIT_ALS, &cm36652_obj->enable);
- else
- clear_bit(CMC_BIT_ALS, &cm36652_obj->enable);
- mutex_unlock(&cm36652_mutex);
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return -1;
- }
- res = cm36652_enable_als(cm36652_obj->client, en);
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- if (res) {
- APS_ERR("als_enable_nodata is failed!!\n");
- return -1;
- }
- return 0;
- }
- static int als_set_delay(u64 ns)
- {
- return 0;
- }
- static int als_get_data(int *value, int *status)
- {
- int err = 0;
- #ifdef CUSTOM_KERNEL_SENSORHUB
- SCP_SENSOR_HUB_DATA req;
- int len;
- #else
- struct cm36652_priv *obj = NULL;
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- #ifdef CUSTOM_KERNEL_SENSORHUB
- if (atomic_read(&cm36652_obj->init_done)) {
- req.get_data_req.sensorType = ID_LIGHT;
- req.get_data_req.action = SENSOR_HUB_GET_DATA;
- len = sizeof(req.get_data_req);
- err = SCP_sensorHub_req_send(&req, &len, 1);
- if (err)
- APS_ERR("SCP_sensorHub_req_send fail!\n");
- else {
- *value = req.get_data_rsp.int16_Data[0];
- *status = SENSOR_STATUS_ACCURACY_MEDIUM;
- }
- if (atomic_read(&cm36652_obj->trace) & CMC_TRC_PS_DATA)
- APS_LOG("value = %d\n", *value);
- else {
- APS_ERR("sensor hub hat not been ready!!\n");
- err = -1;
- }
- #else /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return -1;
- }
- obj = cm36652_obj;
- err = cm36652_read_als(obj->client, &obj->als);
- if (err)
- err = -1;
- else {
- *value = cm36652_get_als_value(obj, obj->als);
- if (*value < 0)
- err = -1;
- *status = SENSOR_STATUS_ACCURACY_MEDIUM;
- }
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- return err;
- }
- /* if use this typ of enable , Gsensor should report inputEvent(x, y, z ,stats, div) to HAL */
- static int ps_open_report_data(int open)
- {
- /* should queuq work to report event if is_report_input_direct=true */
- return 0;
- }
- /* if use this typ of enable , Gsensor only enabled but not report inputEvent to HAL */
- static int ps_enable_nodata(int en)
- {
- int res = 0;
- #ifdef CUSTOM_KERNEL_SENSORHUB
- SCP_SENSOR_HUB_DATA req;
- int len;
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- APS_LOG("cm36652_obj als enable value = %d\n", en);
- #ifdef CUSTOM_KERNEL_SENSORHUB
- if (atomic_read(&cm36652_obj->init_done)) {
- req.activate_req.sensorType = ID_PROXIMITY;
- req.activate_req.action = SENSOR_HUB_ACTIVATE;
- req.activate_req.enable = en;
- len = sizeof(req.activate_req);
- res = SCP_sensorHub_req_send(&req, &len, 1);
- } else
- APS_ERR("sensor hub has not been ready!!\n");
- mutex_lock(&cm36652_mutex);
- if (en)
- set_bit(CMC_BIT_PS, &cm36652_obj->enable);
- else
- clear_bit(CMC_BIT_PS, &cm36652_obj->enable);
- mutex_unlock(&cm36652_mutex);
- #else /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- mutex_lock(&cm36652_mutex);
- if (en)
- set_bit(CMC_BIT_PS, &cm36652_obj->enable);
- else
- clear_bit(CMC_BIT_PS, &cm36652_obj->enable);
- mutex_unlock(&cm36652_mutex);
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return -1;
- }
- res = cm36652_enable_ps(cm36652_obj->client, en);
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- if (res) {
- APS_ERR("als_enable_nodata is failed!!\n");
- return -1;
- }
- return 0;
- }
- static int ps_set_delay(u64 ns)
- {
- return 0;
- }
- static int ps_get_data(int *value, int *status)
- {
- int err = 0;
- #ifdef CUSTOM_KERNEL_SENSORHUB
- SCP_SENSOR_HUB_DATA req;
- int len;
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- #ifdef CUSTOM_KERNEL_SENSORHUB
- if (atomic_read(&cm36652_obj->init_done)) {
- req.get_data_req.sensorType = ID_PROXIMITY;
- req.get_data_req.action = SENSOR_HUB_GET_DATA;
- len = sizeof(req.get_data_req);
- err = SCP_sensorHub_req_send(&req, &len, 1);
- if (err) {
- APS_ERR("SCP_sensorHub_req_send fail!\n");
- *value = -1;
- err = -1;
- } else {
- *value = req.get_data_rsp.int16_Data[0];
- *status = SENSOR_STATUS_ACCURACY_MEDIUM;
- }
- if (atomic_read(&cm36652_obj->trace) & CMC_TRC_PS_DATA)
- APS_LOG("value = %d\n", *value)
- else {
- APS_ERR("sensor hub has not been ready!!\n");
- err = -1;
- }
- #else /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- if (!cm36652_obj) {
- APS_ERR("cm36652_obj is null!!\n");
- return -1;
- }
- err = cm36652_read_ps(cm36652_obj->client, &cm36652_obj->ps);
- if (err)
- err = -1;
- else {
- *value = cm36652_get_ps_value(cm36652_obj, cm36652_obj->ps);
- if (*value < 0)
- err = -1;
- *status = SENSOR_STATUS_ACCURACY_MEDIUM;
- }
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- return err;
- }
- /*-----------------------------------i2c operations----------------------------------*/
- static int cm36652_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
- {
- struct cm36652_priv *obj;
- struct als_control_path als_ctl = {0};
- struct als_data_path als_data = {0};
- struct ps_control_path ps_ctl = {0};
- struct ps_data_path ps_data = {0};
- int err = 0;
- APS_LOG("cm36652_i2c_probe\n");
- obj = kzalloc(sizeof(*obj), GFP_KERNEL);
- if (!obj) {
- err = -ENOMEM;
- goto exit;
- }
- memset(obj, 0, sizeof(*obj));
- cm36652_obj = obj;
- obj->hw = hw;
- INIT_WORK(&obj->eint_work, cm36652_eint_work);
- #ifdef CUSTOM_KERNEL_SENSORHUB
- INIT_WORK(&obj->init_done_work, cm36652_init_done_work);
- #endif /* #ifdef CUSTOM_KERNEL_SENSORHUB */
- obj->client = client;
- i2c_set_clientdata(client, obj);
- /*-----------------------------value need to be confirmed-----------------------------------------*/
- atomic_set(&obj->als_debounce, 200);
- atomic_set(&obj->als_deb_on, 0);
- atomic_set(&obj->als_deb_end, 0);
- atomic_set(&obj->ps_debounce, 200);
- atomic_set(&obj->ps_deb_on, 0);
- atomic_set(&obj->ps_deb_end, 0);
- atomic_set(&obj->ps_mask, 0);
- atomic_set(&obj->als_suspend, 0);
- atomic_set(&obj->als_cmd_val, 0xDF);
- atomic_set(&obj->ps_cmd_val, 0xC1);
- atomic_set(&obj->ps_thd_val_high, obj->hw->ps_threshold_high);
- atomic_set(&obj->ps_thd_val_low, obj->hw->ps_threshold_low);
- atomic_set(&obj->als_thd_val_high, obj->hw->als_threshold_high);
- atomic_set(&obj->als_thd_val_low, obj->hw->als_threshold_low);
- atomic_set(&obj->init_done, 0);
- obj->irq_node = of_find_compatible_node(NULL, NULL, "mediatek, als-eint");
- obj->enable = 0;
- obj->pending_intr = 0;
- obj->ps_cali = 0;
- obj->als_level_num = sizeof(obj->hw->als_level)/sizeof(obj->hw->als_level[0]);
- obj->als_value_num = sizeof(obj->hw->als_value)/sizeof(obj->hw->als_value[0]);
- /*-----------------------------value need to be confirmed-----------------------------------------*/
- BUG_ON(sizeof(obj->als_level) != sizeof(obj->hw->als_level));
- memcpy(obj->als_level, obj->hw->als_level, sizeof(obj->als_level));
- BUG_ON(sizeof(obj->als_value) != sizeof(obj->hw->als_value));
- memcpy(obj->als_value, obj->hw->als_value, sizeof(obj->als_value));
- atomic_set(&obj->i2c_retry, 3);
- clear_bit(CMC_BIT_ALS, &obj->enable);
- clear_bit(CMC_BIT_PS, &obj->enable);
- cm36652_i2c_client = client;
- err = cm36652_init_client(client);
- if (err)
- goto exit_init_failed;
- APS_LOG("cm36652_init_client() OK!\n");
- err = misc_register(&cm36652_device);
- if (err) {
- APS_ERR("cm36652_device register failed\n");
- goto exit_misc_device_register_failed;
- }
- als_ctl.is_use_common_factory = false;
- ps_ctl.is_use_common_factory = false;
- APS_LOG("cm36652_device misc_register OK!\n");
- /*------------------------cm36652 attribute file for debug--------------------------------------*/
- err = cm36652_create_attr(&(cm36652_init_info.platform_diver_addr->driver));
- if (err) {
- APS_ERR("create attribute err = %d\n", err);
- goto exit_create_attr_failed;
- }
- /*------------------------cm36652 attribute file for debug--------------------------------------*/
- als_ctl.open_report_data = als_open_report_data;
- als_ctl.enable_nodata = als_enable_nodata;
- als_ctl.set_delay = als_set_delay;
- als_ctl.is_report_input_direct = false;
- #ifdef CUSTOM_KERNEL_SENSORHUB
- als_ctl.is_support_batch = obj->hw->is_batch_supported_als;
- #else
- als_ctl.is_support_batch = false;
- #endif
- err = als_register_control_path(&als_ctl);
- if (err) {
- APS_ERR("register fail = %d\n", err);
- goto exit_sensor_obj_attach_fail;
- }
- als_data.get_data = als_get_data;
- als_data.vender_div = 100;
- err = als_register_data_path(&als_data);
- if (err) {
- APS_ERR("tregister fail = %d\n", err);
- goto exit_sensor_obj_attach_fail;
- }
- ps_ctl.open_report_data = ps_open_report_data;
- ps_ctl.enable_nodata = ps_enable_nodata;
- ps_ctl.set_delay = ps_set_delay;
- ps_ctl.is_report_input_direct = false;
- #ifdef CUSTOM_KERNEL_SENSORHUB
- ps_ctl.is_support_batch = obj->hw->is_batch_supported_ps;
- #else
- ps_ctl.is_support_batch = false;
- #endif
- err = ps_register_control_path(&ps_ctl);
- if (err) {
- APS_ERR("register fail = %d\n", err);
- goto exit_sensor_obj_attach_fail;
- }
- ps_data.get_data = ps_get_data;
- ps_data.vender_div = 100;
- err = ps_register_data_path(&ps_data);
- if (err) {
- APS_ERR("tregister fail = %d\n", err);
- goto exit_sensor_obj_attach_fail;
- }
- err = batch_register_support_info(ID_LIGHT, als_ctl.is_support_batch, 1, 0);
- if (err)
- APS_ERR("register light batch support err = %d\n", err);
- err = batch_register_support_info(ID_PROXIMITY, ps_ctl.is_support_batch, 1, 0);
- if (err)
- APS_ERR("register proximity batch support err = %d\n", err);
- cm36652_init_flag = 0;
- APS_LOG("%s: OK\n", __func__);
- return 0;
- exit_create_attr_failed:
- exit_sensor_obj_attach_fail:
- exit_misc_device_register_failed:
- misc_deregister(&cm36652_device);
- exit_init_failed:
- kfree(obj);
- exit:
- cm36652_i2c_client = NULL;
- APS_ERR("%s: err = %d\n", __func__, err);
- cm36652_init_flag = -1;
- return err;
- }
- static int cm36652_i2c_remove(struct i2c_client *client)
- {
- int err;
- err = cm36652_delete_attr(&(cm36652_init_info.platform_diver_addr->driver));
- if (err)
- APS_ERR("cm36652_delete_attr fail: %d\n", err);
- err = misc_deregister(&cm36652_device);
- if (err)
- APS_ERR("misc_deregister fail: %d\n", err);
- cm36652_i2c_client = NULL;
- i2c_unregister_device(client);
- kfree(i2c_get_clientdata(client));
- return 0;
- }
- static int cm36652_i2c_detect(struct i2c_client *client, struct i2c_board_info *info)
- {
- strcpy(info->type, CM36652_DEV_NAME);
- return 0;
- }
- static int cm36652_i2c_suspend(struct i2c_client *client, pm_message_t msg)
- {
- struct cm36652_priv *obj = i2c_get_clientdata(client);
- int err;
- APS_LOG("cm36652_i2c_suspend\n");
- if (!obj) {
- APS_ERR("null pointer!!\n");
- return 0;
- }
- atomic_set(&obj->als_suspend, 1);
- err = cm36652_enable_als(obj->client, 0);
- if (err)
- APS_ERR("disable als fail: %d\n", err);
- return 0;
- }
- static int cm36652_i2c_resume(struct i2c_client *client)
- {
- struct cm36652_priv *obj = i2c_get_clientdata(client);
- int err;
- struct hwm_sensor_data sensor_data;
- memset(&sensor_data, 0, sizeof(sensor_data));
- APS_LOG("cm36652_i2c_resume\n");
- if (!obj) {
- APS_ERR("null pointer!!\n");
- return 0;
- }
- atomic_set(&obj->als_suspend, 0);
- if (test_bit(CMC_BIT_ALS, &obj->enable)) {
- err = cm36652_enable_als(obj->client, 1);
- if (err)
- APS_ERR("enable als fail: %d\n", err);
- }
- return 0;
- }
- /*----------------------------------------------------------------------------*/
- /*----------------------------------------------------------------------------*/
- static int cm36652_remove(void)
- {
- cm36652_power(hw, 0);/* ***************** */
- i2c_del_driver(&cm36652_i2c_driver);
- return 0;
- }
- /*----------------------------------------------------------------------------*/
- static int cm36652_local_init(void)
- {
- /* printk("fwq loccal init+++\n"); */
- cm36652_power(hw, 1);
- if (i2c_add_driver(&cm36652_i2c_driver)) {
- APS_ERR("add driver error\n");
- return -1;
- }
- if (-1 == cm36652_init_flag)
- return -1;
- return 0;
- }
- /*----------------------------------------------------------------------------*/
- static int __init cm36652_init(void)
- {
- const char *name = "mediatek,cm36652";
- hw = get_alsps_dts_func(name, hw);
- if (!hw)
- APS_ERR("get dts info fail\n");
- alsps_driver_add(&cm36652_init_info);
- return 0;
- }
- /*----------------------------------------------------------------------------*/
- static void __exit cm36652_exit(void)
- {
- }
- /*----------------------------------------------------------------------------*/
- module_init(cm36652_init);
- module_exit(cm36652_exit);
- /*----------------------------------------------------------------------------*/
- MODULE_AUTHOR("yucong xiong");
- MODULE_DESCRIPTION("cm36652 driver");
- MODULE_LICENSE("GPL");
|