12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096 |
- /* drivers/input/misc/cm36283.c - cm36283 optical sensors driver
- *
- * Copyright (C) 2012 Capella Microsystems Inc.
- * Author: Frank Hsieh <pengyueh@gmail.com>
- *
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
- *
- * 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/delay.h>
- #include <linux/i2c.h>
- #include <linux/input.h>
- #include <linux/sensors.h>
- #include <linux/interrupt.h>
- #include <linux/module.h>
- #include <linux/platform_device.h>
- #include <linux/workqueue.h>
- #include <linux/irq.h>
- #include <linux/errno.h>
- #include <linux/err.h>
- #include <linux/gpio.h>
- #include <linux/miscdevice.h>
- #include <linux/slab.h>
- #include <linux/regulator/consumer.h>
- #include <linux/wakelock.h>
- #include <linux/jiffies.h>
- #include <linux/cm36283.h>
- #include <linux/of_gpio.h>
- #include <asm/uaccess.h>
- #include <asm/mach-types.h>
- #include <asm/setup.h>
- #define I2C_RETRY_COUNT 10
- #define NEAR_DELAY_TIME ((100 * HZ) / 1000)
- #define CONTROL_INT_ISR_REPORT 0x00
- #define CONTROL_ALS 0x01
- #define CONTROL_PS 0x02
- /* POWER SUPPLY VOLTAGE RANGE */
- #define CM36283_VDD_MIN_UV 2700000
- #define CM36283_VDD_MAX_UV 3300000
- #define CM36283_VI2C_MIN_UV 1750000
- #define CM36283_VI2C_MAX_UV 1950000
- /* cm36283 polling rate in ms */
- #define CM36283_LS_MIN_POLL_DELAY 1
- #define CM36283_LS_MAX_POLL_DELAY 1000
- #define CM36283_LS_DEFAULT_POLL_DELAY 100
- #define CM36283_PS_MIN_POLL_DELAY 1
- #define CM36283_PS_MAX_POLL_DELAY 1000
- #define CM36283_PS_DEFAULT_POLL_DELAY 100
- static struct sensors_classdev sensors_light_cdev = {
- .name = "cm36283-light",
- .vendor = "Capella",
- .version = 1,
- .handle = SENSORS_LIGHT_HANDLE,
- .type = SENSOR_TYPE_LIGHT,
- .max_range = "6553",
- .resolution = "0.0125",
- .sensor_power = "0.15",
- .min_delay = 0,
- .fifo_reserved_event_count = 0,
- .fifo_max_event_count = 0,
- .enabled = 0,
- .delay_msec = CM36283_LS_DEFAULT_POLL_DELAY,
- .sensors_enable = NULL,
- .sensors_poll_delay = NULL,
- };
- static struct sensors_classdev sensors_proximity_cdev = {
- .name = "cm36283-proximity",
- .vendor = "Capella",
- .version = 1,
- .handle = SENSORS_PROXIMITY_HANDLE,
- .type = SENSOR_TYPE_PROXIMITY,
- .max_range = "5.0",
- .resolution = "5.0",
- .sensor_power = "0.18",
- .min_delay = 0,
- .fifo_reserved_event_count = 0,
- .fifo_max_event_count = 0,
- .enabled = 0,
- .delay_msec = CM36283_PS_DEFAULT_POLL_DELAY,
- .sensors_enable = NULL,
- .sensors_poll_delay = NULL,
- };
- static const int als_range[] = {
- [CM36283_ALS_IT0] = 6554,
- [CM36283_ALS_IT1] = 3277,
- [CM36283_ALS_IT2] = 1638,
- [CM36283_ALS_IT3] = 819,
- };
- static const int als_sense[] = {
- [CM36283_ALS_IT0] = 10,
- [CM36283_ALS_IT1] = 20,
- [CM36283_ALS_IT2] = 40,
- [CM36283_ALS_IT3] = 80,
- };
- static void sensor_irq_do_work(struct work_struct *work);
- static DECLARE_WORK(sensor_irq_work, sensor_irq_do_work);
- struct cm36283_info {
- struct class *cm36283_class;
- struct device *ls_dev;
- struct device *ps_dev;
- struct input_dev *ls_input_dev;
- struct input_dev *ps_input_dev;
- struct i2c_client *i2c_client;
- struct workqueue_struct *lp_wq;
- int intr_pin;
- int als_enable;
- int ps_enable;
- int ps_irq_flag;
- uint16_t *adc_table;
- uint16_t cali_table[10];
- int irq;
- int ls_calibrate;
-
- int (*power)(int, uint8_t); /* power to the chip */
- uint32_t als_kadc;
- uint32_t als_gadc;
- uint16_t golden_adc;
- struct wake_lock ps_wake_lock;
- int psensor_opened;
- int lightsensor_opened;
- uint8_t slave_addr;
- uint8_t ps_close_thd_set;
- uint8_t ps_away_thd_set;
- int current_level;
- uint16_t current_adc;
- uint16_t ps_conf1_val;
- uint16_t ps_conf3_val;
- uint16_t ls_cmd;
- uint8_t record_clear_int_fail;
- bool polling;
- atomic_t ls_poll_delay;
- atomic_t ps_poll_delay;
- struct regulator *vdd;
- struct regulator *vio;
- struct delayed_work ldwork;
- struct delayed_work pdwork;
- struct sensors_classdev als_cdev;
- struct sensors_classdev ps_cdev;
- };
- struct cm36283_info *lp_info;
- int fLevel=-1;
- static struct mutex als_enable_mutex, als_disable_mutex, als_get_adc_mutex;
- static struct mutex ps_enable_mutex, ps_disable_mutex, ps_get_adc_mutex;
- static struct mutex CM36283_control_mutex;
- static struct mutex wq_lock;
- static int lightsensor_enable(struct cm36283_info *lpi);
- static int lightsensor_disable(struct cm36283_info *lpi);
- static int initial_cm36283(struct cm36283_info *lpi);
- static void psensor_initial_cmd(struct cm36283_info *lpi);
- static int cm36283_power_set(struct cm36283_info *info, bool on);
- int32_t als_kadc;
- static int control_and_report(struct cm36283_info *lpi, uint8_t mode,
- uint16_t param, int report);
- static int I2C_RxData(uint16_t slaveAddr, uint8_t cmd, uint8_t *rxData, int length)
- {
- uint8_t loop_i;
- struct cm36283_info *lpi = lp_info;
- uint8_t subaddr[1];
- struct i2c_msg msgs[] = {
- {
- .addr = slaveAddr,
- .flags = 0,
- .len = 1,
- .buf = subaddr,
- },
- {
- .addr = slaveAddr,
- .flags = I2C_M_RD,
- .len = length,
- .buf = rxData,
- },
- };
- subaddr[0] = cmd;
- for (loop_i = 0; loop_i < I2C_RETRY_COUNT; loop_i++) {
- if (i2c_transfer(lp_info->i2c_client->adapter, msgs, 2) > 0)
- break;
- dev_err(&lpi->i2c_client->dev, "%s: I2C error(%d). Retrying.\n",
- __func__, cmd);
- msleep(10);
- }
- if (loop_i >= I2C_RETRY_COUNT) {
- dev_err(&lpi->i2c_client->dev, "%s: Retry count exceeds %d.",
- __func__, I2C_RETRY_COUNT);
- return -EIO;
- }
- return 0;
- }
- static int I2C_TxData(uint16_t slaveAddr, uint8_t *txData, int length)
- {
- uint8_t loop_i;
- struct cm36283_info *lpi = lp_info;
- struct i2c_msg msg[] = {
- {
- .addr = slaveAddr,
- .flags = 0,
- .len = length,
- .buf = txData,
- },
- };
- for (loop_i = 0; loop_i < I2C_RETRY_COUNT; loop_i++) {
- if (i2c_transfer(lp_info->i2c_client->adapter, msg, 1) > 0)
- break;
- pr_err("%s: I2C error. Retrying...\n", __func__);
- msleep(10);
- }
- if (loop_i >= I2C_RETRY_COUNT) {
- dev_err(&lpi->i2c_client->dev, "%s: Retry count exceeds %d.",
- __func__, I2C_RETRY_COUNT);
- return -EIO;
- }
- return 0;
- }
- static int _cm36283_I2C_Read_Word(uint16_t slaveAddr, uint8_t cmd, uint16_t *pdata)
- {
- uint8_t buffer[2];
- int ret = 0;
- if (pdata == NULL)
- return -EFAULT;
- ret = I2C_RxData(slaveAddr, cmd, buffer, 2);
- if (ret < 0) {
- pr_err("%s: I2C RxData fail(%d).\n", __func__, cmd);
- return ret;
- }
- *pdata = (buffer[1]<<8)|buffer[0];
- return ret;
- }
- static int _cm36283_I2C_Write_Word(uint16_t SlaveAddress, uint8_t cmd, uint16_t data)
- {
- char buffer[3];
- int ret = 0;
- buffer[0] = cmd;
- buffer[1] = (uint8_t)(data&0xff);
- buffer[2] = (uint8_t)((data&0xff00)>>8);
-
- ret = I2C_TxData(SlaveAddress, buffer, 3);
- if (ret < 0) {
- pr_err("%s: I2C_TxData failed.\n", __func__);
- return -EIO;
- }
- return ret;
- }
- static int get_ls_adc_value(uint16_t *als_step, bool resume)
- {
- struct cm36283_info *lpi = lp_info;
- uint32_t tmp;
- int ret = 0;
- if (als_step == NULL)
- return -EFAULT;
- /* Read ALS data: */
- ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ALS_DATA, als_step);
- if (ret < 0) {
- dev_err(&lpi->i2c_client->dev, "%s: I2C read word failed.\n",
- __func__);
- return -EIO;
- }
- if (!lpi->ls_calibrate) {
- tmp = (uint32_t)(*als_step) * lpi->als_gadc / lpi->als_kadc;
- if (tmp > 0xFFFF)
- *als_step = 0xFFFF;
- else
- *als_step = tmp;
- }
- dev_dbg(&lpi->i2c_client->dev, "raw adc = 0x%x\n", *als_step);
- return ret;
- }
- static int set_lsensor_range(uint16_t low_thd, uint16_t high_thd)
- {
- int ret = 0;
- struct cm36283_info *lpi = lp_info;
- _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_THDH, high_thd);
- _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_THDL, low_thd);
- return ret;
- }
- static int get_ps_adc_value(uint16_t *data)
- {
- int ret = 0;
- struct cm36283_info *lpi = lp_info;
- if (data == NULL)
- return -EFAULT;
- ret = _cm36283_I2C_Read_Word(lpi->slave_addr, PS_DATA, data);
-
- if (ret < 0)
- return ret;
- (*data) &= 0xFF;
- return ret;
- }
- static uint16_t mid_value(uint16_t value[], uint8_t size)
- {
- int i = 0, j = 0;
- uint16_t temp = 0;
- if (size < 3)
- return 0;
- for (i = 0; i < (size - 1); i++)
- for (j = (i + 1); j < size; j++)
- if (value[i] > value[j]) {
- temp = value[i];
- value[i] = value[j];
- value[j] = temp;
- }
- return value[((size - 1) / 2)];
- }
- static int get_stable_ps_adc_value(uint16_t *ps_adc)
- {
- uint16_t value[3] = {0, 0, 0}, mid_val = 0;
- int ret = 0;
- int i = 0;
- int wait_count = 0;
- struct cm36283_info *lpi = lp_info;
- for (i = 0; i < 3; i++) {
- /*wait interrupt GPIO high*/
- while (gpio_get_value(lpi->intr_pin) == 0) {
- msleep(10);
- wait_count++;
- if (wait_count > 12) {
- dev_err(&lpi->i2c_client->dev, "%s: interrupt GPIO low\n",
- __func__);
- return -EIO;
- }
- }
- ret = get_ps_adc_value(&value[i]);
- if (ret < 0) {
- dev_err(&lpi->i2c_client->dev,
- "%s: error get ps value\n", __func__);
- return -EIO;
- }
- if (wait_count < 60/10) {/*wait gpio less than 60ms*/
- msleep(60 - (10*wait_count));
- }
- wait_count = 0;
- }
- mid_val = mid_value(value, 3);
- dev_dbg(&lpi->i2c_client->dev, "Sta_ps: After sort, value[0, 1, 2] = [0x%x, 0x%x, 0x%x]",
- value[0], value[1], value[2]);
- *ps_adc = (mid_val & 0xFF);
- return 0;
- }
- static void sensor_irq_do_work(struct work_struct *work)
- {
- struct cm36283_info *lpi = lp_info;
- uint16_t intFlag;
- _cm36283_I2C_Read_Word(lpi->slave_addr, INT_FLAG, &intFlag);
- control_and_report(lpi, CONTROL_INT_ISR_REPORT, intFlag, 1);
- enable_irq(lpi->irq);
- }
- static int get_als_range(void)
- {
- uint16_t ls_conf;
- int ret = 0;
- int index = 0;
- struct cm36283_info *lpi = lp_info;
- ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ALS_CONF, &ls_conf);
- if (ret) {
- dev_err(&lpi->i2c_client->dev, "read ALS_CONF from i2c error. %d\n",
- ret);
- return -EIO;
- }
- index = (ls_conf & 0xC0) >> 0x06;
- return als_range[index];
- }
- static int get_als_sense(void)
- {
- uint16_t ls_conf;
- int ret = 0;
- int index = 0;
- struct cm36283_info *lpi = lp_info;
- ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ALS_CONF, &ls_conf);
- if (ret) {
- dev_err(&lpi->i2c_client->dev, "read ALS_CONF from i2c error. %d\n",
- ret);
- return -EIO;
- }
- index = (ls_conf & 0xC0) >> 0x06;
- return als_sense[index];
- }
- static void psensor_delay_work_handler(struct work_struct *work)
- {
- struct cm36283_info *lpi = lp_info;
- uint16_t adc_value = 0;
- int ret;
- mutex_lock(&wq_lock);
- ret = get_ps_adc_value(&adc_value);
- mutex_unlock(&wq_lock);
- if (ret >= 0) {
- input_report_abs(lpi->ps_input_dev, ABS_DISTANCE,
- adc_value > lpi->ps_close_thd_set ? 0 : 1);
- input_sync(lpi->ps_input_dev);
- }
- schedule_delayed_work(&lpi->pdwork,
- msecs_to_jiffies(atomic_read(&lpi->ps_poll_delay)));
- }
- static void lsensor_delay_work_handler(struct work_struct *work)
- {
- struct cm36283_info *lpi = lp_info;
- uint16_t adc_value = 0;
- int sense;
- mutex_lock(&wq_lock);
- get_ls_adc_value(&adc_value, 0);
- sense = get_als_sense();
- mutex_unlock(&wq_lock);
- if (sense > 0) {
- lpi->current_adc = adc_value;
- input_report_abs(lpi->ls_input_dev, ABS_MISC, adc_value/sense);
- input_sync(lpi->ls_input_dev);
- }
- schedule_delayed_work(&lpi->ldwork,
- msecs_to_jiffies(atomic_read(&lpi->ls_poll_delay)));
- }
- static irqreturn_t cm36283_irq_handler(int irq, void *data)
- {
- struct cm36283_info *lpi = data;
- disable_irq_nosync(lpi->irq);
- queue_work(lpi->lp_wq, &sensor_irq_work);
- return IRQ_HANDLED;
- }
- static int als_power(int enable)
- {
- struct cm36283_info *lpi = lp_info;
- if (lpi->power)
- lpi->power(LS_PWR_ON, 1);
- return 0;
- }
- static void ls_initial_cmd(struct cm36283_info *lpi)
- {
- /*must disable l-sensor interrupt befrore IST create*//*disable ALS func*/
- lpi->ls_cmd &= CM36283_ALS_INT_MASK;
- lpi->ls_cmd |= CM36283_ALS_SD;
- _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
- }
- static void psensor_initial_cmd(struct cm36283_info *lpi)
- {
- /*must disable p-sensor interrupt befrore IST create*/
- lpi->ps_conf1_val |= CM36283_PS_SD;
- lpi->ps_conf1_val &= CM36283_PS_INT_MASK;
- _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);
- _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val);
- _cm36283_I2C_Write_Word(lpi->slave_addr, PS_THD,
- (lpi->ps_close_thd_set << 8) | lpi->ps_away_thd_set);
- dev_dbg(&lpi->i2c_client->dev,
- "%s:send psensor initial command finished\n", __func__);
- }
- static int psensor_enable(struct cm36283_info *lpi)
- {
- int ret = -EIO;
- unsigned int delay;
-
- mutex_lock(&ps_enable_mutex);
- dev_dbg(&lpi->i2c_client->dev, "psensor enable!\n");
- if (lpi->ps_enable) {
- dev_err(&lpi->i2c_client->dev, "already enabled\n");
- ret = 0;
- } else {
- ret = control_and_report(lpi, CONTROL_PS, 1, 0);
- }
- mutex_unlock(&ps_enable_mutex);
- delay = atomic_read(&lpi->ps_poll_delay);
- if (lpi->polling)
- schedule_delayed_work(&lpi->pdwork, msecs_to_jiffies(delay));
- return ret;
- }
- static int psensor_disable(struct cm36283_info *lpi)
- {
- int ret = -EIO;
- if (lpi->polling)
- cancel_delayed_work_sync(&lpi->pdwork);
- mutex_lock(&ps_disable_mutex);
- dev_dbg(&lpi->i2c_client->dev, "psensor disable!\n");
- if (lpi->ps_enable == 0) {
- dev_err(&lpi->i2c_client->dev, "already disabled\n");
- ret = 0;
- } else {
- ret = control_and_report(lpi, CONTROL_PS, 0, 0);
- }
- mutex_unlock(&ps_disable_mutex);
- return ret;
- }
- static int psensor_open(struct inode *inode, struct file *file)
- {
- struct cm36283_info *lpi = lp_info;
- dev_dbg(&lpi->i2c_client->dev, "psensor open!");
- if (lpi->psensor_opened)
- return -EBUSY;
- lpi->psensor_opened = 1;
- return 0;
- }
- static int psensor_release(struct inode *inode, struct file *file)
- {
- struct cm36283_info *lpi = lp_info;
- dev_dbg(&lpi->i2c_client->dev, "psensor release!");
- lpi->psensor_opened = 0;
- return psensor_disable(lpi);
- //return 0;
- }
- static long psensor_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
- {
- int val;
- struct cm36283_info *lpi = lp_info;
- dev_dbg(&lpi->i2c_client->dev, "%s cmd %d\n", __func__, _IOC_NR(cmd));
- switch (cmd) {
- case CAPELLA_CM3602_IOCTL_ENABLE:
- if (get_user(val, (unsigned long __user *)arg))
- return -EFAULT;
- if (val)
- return psensor_enable(lpi);
- else
- return psensor_disable(lpi);
- break;
- case CAPELLA_CM3602_IOCTL_GET_ENABLED:
- return put_user(lpi->ps_enable, (unsigned long __user *)arg);
- break;
- default:
- dev_err(&lpi->i2c_client->dev, "%s: invalid cmd %d\n",
- __func__, _IOC_NR(cmd));
- return -EINVAL;
- }
- }
- static const struct file_operations psensor_fops = {
- .owner = THIS_MODULE,
- .open = psensor_open,
- .release = psensor_release,
- .unlocked_ioctl = psensor_ioctl
- };
- void lightsensor_set_kvalue(struct cm36283_info *lpi)
- {
- if (!lpi) {
- pr_err("%s: ls_info is empty\n", __func__);
- return;
- }
- dev_dbg(&lpi->i2c_client->dev, "%s: ALS calibrated als_kadc=0x%x\n",
- __func__, als_kadc);
- if (als_kadc >> 16 == ALS_CALIBRATED)
- lpi->als_kadc = als_kadc & 0xFFFF;
- else {
- lpi->als_kadc = 0;
- dev_dbg(&lpi->i2c_client->dev, "%s: no ALS calibrated\n",
- __func__);
- }
- if (lpi->als_kadc && lpi->golden_adc > 0) {
- lpi->als_kadc = (lpi->als_kadc > 0 && lpi->als_kadc < 0x1000) ?
- lpi->als_kadc : lpi->golden_adc;
- lpi->als_gadc = lpi->golden_adc;
- } else {
- lpi->als_kadc = 1;
- lpi->als_gadc = 1;
- }
- dev_dbg(&lpi->i2c_client->dev, "%s: als_kadc=0x%x, als_gadc=0x%x\n",
- __func__, lpi->als_kadc, lpi->als_gadc);
- }
- static int lightsensor_update_table(struct cm36283_info *lpi)
- {
- uint32_t tmp_data[10];
- int i;
- for (i = 0; i < 10; i++) {
- tmp_data[i] = (uint32_t)(*(lpi->adc_table + i))
- * lpi->als_kadc / lpi->als_gadc;
- if (tmp_data[i] <= 0xFFFF)
- lpi->cali_table[i] = (uint16_t) tmp_data[i];
- else
- lpi->cali_table[i] = 0xFFFF;
- dev_dbg(&lpi->i2c_client->dev, "%s: Calibrated adc_table: data[%d], %x\n",
- __func__, i, lpi->cali_table[i]);
- }
- return 0;
- }
- static int lightsensor_enable(struct cm36283_info *lpi)
- {
- int ret = -EIO;
- unsigned int delay;
- mutex_lock(&als_enable_mutex);
- ret = control_and_report(lpi, CONTROL_ALS, 1, 0);
- mutex_unlock(&als_enable_mutex);
- delay = atomic_read(&lpi->ls_poll_delay);
- if (lpi->polling)
- schedule_delayed_work(&lpi->ldwork,
- msecs_to_jiffies(delay));
- return ret;
- }
- static int lightsensor_disable(struct cm36283_info *lpi)
- {
- int ret = -EIO;
- mutex_lock(&als_disable_mutex);
- dev_dbg(&lpi->i2c_client->dev, "disable lightsensor\n");
- if (lpi->polling)
- cancel_delayed_work_sync(&lpi->ldwork);
- if ( lpi->als_enable == 0 ) {
- dev_err(&lpi->i2c_client->dev, "already disabled\n");
- ret = 0;
- } else {
- ret = control_and_report(lpi, CONTROL_ALS, 0, 0);
- }
-
- mutex_unlock(&als_disable_mutex);
- return ret;
- }
- static int lightsensor_open(struct inode *inode, struct file *file)
- {
- struct cm36283_info *lpi = lp_info;
- int rc = 0;
- dev_dbg(&lpi->i2c_client->dev, "%s\n", __func__);
- if (lpi->lightsensor_opened) {
- dev_err(&lpi->i2c_client->dev, "%s: already opened\n",
- __func__);
- rc = -EBUSY;
- }
- lpi->lightsensor_opened = 1;
- return rc;
- }
- static int lightsensor_release(struct inode *inode, struct file *file)
- {
- struct cm36283_info *lpi = lp_info;
- dev_dbg(&lpi->i2c_client->dev, "%s\n", __func__);
- lpi->lightsensor_opened = 0;
- return 0;
- }
- static long lightsensor_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
- {
- int rc, val;
- struct cm36283_info *lpi = lp_info;
- switch (cmd) {
- case LIGHTSENSOR_IOCTL_ENABLE:
- if (get_user(val, (unsigned long __user *)arg)) {
- rc = -EFAULT;
- break;
- }
- rc = val ? lightsensor_enable(lpi) : lightsensor_disable(lpi);
- break;
- case LIGHTSENSOR_IOCTL_GET_ENABLED:
- val = lpi->als_enable;
- rc = put_user(val, (unsigned long __user *)arg);
- break;
- default:
- pr_err("[LS][CM36283 error]%s: invalid cmd %d\n",
- __func__, _IOC_NR(cmd));
- rc = -EINVAL;
- }
- return rc;
- }
- static const struct file_operations lightsensor_fops = {
- .owner = THIS_MODULE,
- .open = lightsensor_open,
- .release = lightsensor_release,
- .unlocked_ioctl = lightsensor_ioctl
- };
- static ssize_t ps_adc_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- uint16_t value;
- int ret;
- struct cm36283_info *lpi = lp_info;
- int intr_val = -1;
- get_ps_adc_value(&value);
- if (gpio_is_valid(lpi->intr_pin))
- intr_val = gpio_get_value(lpi->intr_pin);
- ret = snprintf(buf, PAGE_SIZE, "ADC[0x%04X], ENABLE=%d intr_pin=%d\n",
- value, lpi->ps_enable, intr_val);
- return ret;
- }
- static int ps_enable_set(struct sensors_classdev *sensors_cdev,
- unsigned int enable)
- {
- struct cm36283_info *lpi = container_of(sensors_cdev,
- struct cm36283_info, ps_cdev);
- int ret;
- if (enable)
- ret = psensor_enable(lpi);
- else
- ret = psensor_disable(lpi);
- return ret;
- }
- static ssize_t ps_enable_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- int ps_en;
- struct cm36283_info *lpi = lp_info;
- ps_en = -1;
- sscanf(buf, "%d", &ps_en);
- if (ps_en != 0 && ps_en != 1
- && ps_en != 10 && ps_en != 13 && ps_en != 16)
- return -EINVAL;
- dev_dbg(&lpi->i2c_client->dev, "%s: ps_en=%d\n",
- __func__, ps_en);
- if (ps_en)
- psensor_enable(lpi);
- else
- psensor_disable(lpi);
- return count;
- }
- static ssize_t ps_parameters_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int ret;
- struct cm36283_info *lpi = lp_info;
- ret = snprintf(buf, PAGE_SIZE,
- "PS_close_thd_set = 0x%x, PS_away_thd_set = 0x%x\n",
- lpi->ps_close_thd_set, lpi->ps_away_thd_set);
- return ret;
- }
- static ssize_t ps_parameters_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cm36283_info *lpi = lp_info;
- char *token[10];
- int i;
- unsigned long tmp;
- for (i = 0; i < 3; i++)
- token[i] = strsep((char **)&buf, " ");
- if (kstrtoul(token[0], 16, &tmp))
- return -EINVAL;
- lpi->ps_close_thd_set = tmp;
- if (kstrtoul(token[1], 16, &tmp))
- return -EINVAL;
- lpi->ps_away_thd_set = tmp;
- dev_dbg(&lpi->i2c_client->dev, "ps_close_thd_set:0x%x\n",
- lpi->ps_close_thd_set);
- dev_dbg(&lpi->i2c_client->dev, "ps_away_thd_set:0x%x\n",
- lpi->ps_away_thd_set);
- return count;
- }
- static ssize_t ps_conf_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cm36283_info *lpi = lp_info;
- return sprintf(buf, "PS_CONF1 = 0x%x, PS_CONF3 = 0x%x\n", lpi->ps_conf1_val, lpi->ps_conf3_val);
- }
- static ssize_t ps_conf_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- int code1, code2;
- struct cm36283_info *lpi = lp_info;
- sscanf(buf, "0x%x 0x%x", &code1, &code2);
- dev_dbg(&lpi->i2c_client->dev, "PS_CONF1:0x%x PS_CONF3:0x%x\n",
- code1, code2);
- lpi->ps_conf1_val = code1;
- lpi->ps_conf3_val = code2;
- _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val);
- _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);
- return count;
- }
- static ssize_t ps_thd_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int ret;
- struct cm36283_info *lpi = lp_info;
- ret = sprintf(buf, "%s ps_close_thd_set = 0x%x, ps_away_thd_set = 0x%x\n", __func__, lpi->ps_close_thd_set, lpi->ps_away_thd_set);
- return ret;
- }
- static ssize_t ps_thd_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- int code;
- struct cm36283_info *lpi = lp_info;
- sscanf(buf, "0x%x", &code);
- lpi->ps_away_thd_set = code &0xFF;
- lpi->ps_close_thd_set = (code & 0xFF00)>>8;
- dev_dbg(&lpi->i2c_client->dev, "ps_away_thd_set:0x%x\n",
- lpi->ps_away_thd_set);
- dev_dbg(&lpi->i2c_client->dev, "ps_close_thd_set:0x%x\n",
- lpi->ps_close_thd_set);
- return count;
- }
- static ssize_t ps_hw_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int ret = 0;
- struct cm36283_info *lpi = lp_info;
- ret = sprintf(buf, "PS1: reg = 0x%x, PS3: reg = 0x%x, ps_close_thd_set = 0x%x, ps_away_thd_set = 0x%x\n",
- lpi->ps_conf1_val, lpi->ps_conf3_val, lpi->ps_close_thd_set, lpi->ps_away_thd_set);
- return ret;
- }
- static ssize_t ps_hw_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- int code;
- sscanf(buf, "0x%x", &code);
- return count;
- }
- static ssize_t ls_adc_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int ret;
- struct cm36283_info *lpi = lp_info;
- ret = sprintf(buf, "ADC[0x%04X] => level %d\n",
- lpi->current_adc, lpi->current_level);
- return ret;
- }
- static int ls_enable_set(struct sensors_classdev *sensors_cdev,
- unsigned int enable)
- {
- struct cm36283_info *lpi = container_of(sensors_cdev,
- struct cm36283_info, als_cdev);
- int ret;
- if (enable)
- ret = lightsensor_enable(lpi);
- else
- ret = lightsensor_disable(lpi);
- if (ret < 0) {
- dev_err(&lpi->i2c_client->dev, "%s: set auto light sensor fail\n",
- __func__);
- return -EIO;
- }
- return 0;
- }
- static ssize_t ls_enable_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- int ret = 0;
- struct cm36283_info *lpi = lp_info;
- ret = sprintf(buf, "Light sensor Auto Enable = %d\n",
- lpi->als_enable);
- return ret;
- }
- static ssize_t ls_enable_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- int ret = 0;
- int ls_auto;
- struct cm36283_info *lpi = lp_info;
- ls_auto = -1;
- sscanf(buf, "%d", &ls_auto);
- if (ls_auto != 0 && ls_auto != 1 && ls_auto != 147)
- return -EINVAL;
- if (ls_auto) {
- lpi->ls_calibrate = (ls_auto == 147) ? 1 : 0;
- ret = lightsensor_enable(lpi);
- } else {
- lpi->ls_calibrate = 0;
- ret = lightsensor_disable(lpi);
- }
- dev_dbg(&lpi->i2c_client->dev, "als_enable:0x%x\n",
- lpi->als_enable);
- dev_dbg(&lpi->i2c_client->dev, "ls_calibrate:0x%x\n",
- lpi->ls_calibrate);
- dev_dbg(&lpi->i2c_client->dev, "ls_auto:0x%x\n", ls_auto);
- if (ret < 0) {
- dev_err(&lpi->i2c_client->dev, "%s: set auto light sensor fail\n",
- __func__);
- return ret;
- }
- return count;
- }
- static ssize_t ls_kadc_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cm36283_info *lpi = lp_info;
- int ret;
- ret = sprintf(buf, "kadc = 0x%x",
- lpi->als_kadc);
- return ret;
- }
- static ssize_t ls_kadc_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cm36283_info *lpi = lp_info;
- int kadc_temp = 0;
- sscanf(buf, "%d", &kadc_temp);
- mutex_lock(&als_get_adc_mutex);
- if (kadc_temp != 0) {
- lpi->als_kadc = kadc_temp;
- if (lpi->als_gadc != 0) {
- if (lightsensor_update_table(lpi) < 0)
- dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
- __func__);
- else
- dev_dbg(&lpi->i2c_client->dev, "%s: als_gadc =0x%x wait to be set\n",
- __func__, lpi->als_gadc);
- }
- } else {
- dev_err(&lpi->i2c_client->dev, "%s: als_kadc can't be set to zero\n",
- __func__);
- }
-
- mutex_unlock(&als_get_adc_mutex);
- return count;
- }
- static ssize_t ls_gadc_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cm36283_info *lpi = lp_info;
- int ret;
- ret = sprintf(buf, "gadc = 0x%x\n", lpi->als_gadc);
- return ret;
- }
- static ssize_t ls_gadc_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cm36283_info *lpi = lp_info;
- int gadc_temp = 0;
- sscanf(buf, "%d", &gadc_temp);
-
- mutex_lock(&als_get_adc_mutex);
- if (gadc_temp != 0) {
- lpi->als_gadc = gadc_temp;
- if (lpi->als_kadc != 0) {
- if (lightsensor_update_table(lpi) < 0)
- dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
- __func__);
- } else {
- dev_dbg(&lpi->i2c_client->dev, "als_kadc =0x%x wait to be set\n",
- lpi->als_kadc);
- }
- } else {
- dev_err(&lpi->i2c_client->dev, "als_gadc can't be set to zero\n");
- }
- mutex_unlock(&als_get_adc_mutex);
- return count;
- }
- static ssize_t ls_adc_table_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- unsigned length = 0;
- int i;
- for (i = 0; i < 10; i++) {
- length += sprintf(buf + length,
- "[CM36283]Get adc_table[%d] = 0x%x ; %d, Get cali_table[%d] = 0x%x ; %d, \n",
- i, *(lp_info->adc_table + i),
- *(lp_info->adc_table + i),
- i, *(lp_info->cali_table + i),
- *(lp_info->cali_table + i));
- }
- return length;
- }
- static ssize_t ls_adc_table_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cm36283_info *lpi = lp_info;
- char *token[10];
- uint16_t tempdata[10];
- int i;
- for (i = 0; i < 10; i++) {
- token[i] = strsep((char **)&buf, " ");
- tempdata[i] = simple_strtoul(token[i], NULL, 16);
- if (tempdata[i] < 1 || tempdata[i] > 0xffff) {
- dev_err(&lpi->i2c_client->dev,
- "adc_table[%d] = 0x%x error\n",
- i, tempdata[i]);
- return count;
- }
- }
- mutex_lock(&als_get_adc_mutex);
- for (i = 0; i < 10; i++)
- lpi->adc_table[i] = tempdata[i];
- if (lightsensor_update_table(lpi) < 0)
- dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
- __func__);
- mutex_unlock(&als_get_adc_mutex);
- return count;
- }
- static ssize_t ls_conf_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cm36283_info *lpi = lp_info;
- return sprintf(buf, "ALS_CONF = %x\n", lpi->ls_cmd);
- }
- static ssize_t ls_conf_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cm36283_info *lpi = lp_info;
- int value = 0;
- sscanf(buf, "0x%x", &value);
- lpi->ls_cmd = value;
- dev_dbg(&lpi->i2c_client->dev, "ALS_CONF:0x%x\n", lpi->ls_cmd);
- _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
- return count;
- }
- static ssize_t ls_poll_delay_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cm36283_info *lpi = lp_info;
- return snprintf(buf, PAGE_SIZE, "%d\n",
- atomic_read(&lpi->ls_poll_delay));
- }
- static ssize_t ls_poll_delay_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cm36283_info *lpi = lp_info;
- unsigned long interval_ms;
- if (kstrtoul(buf, 10, &interval_ms))
- return -EINVAL;
- if ((interval_ms < CM36283_LS_MIN_POLL_DELAY) ||
- (interval_ms > CM36283_LS_MAX_POLL_DELAY))
- return -EINVAL;
- atomic_set(&lpi->ls_poll_delay, (unsigned int) interval_ms);
- return count;
- }
- static int ls_poll_delay_set(struct sensors_classdev *sensors_cdev,
- unsigned int delay_msec)
- {
- struct cm36283_info *lpi = container_of(sensors_cdev,
- struct cm36283_info, als_cdev);
- if ((delay_msec < CM36283_LS_MIN_POLL_DELAY) ||
- (delay_msec > CM36283_LS_MAX_POLL_DELAY))
- return -EINVAL;
- atomic_set(&lpi->ls_poll_delay, delay_msec);
- return 0;
- }
- static ssize_t ps_poll_delay_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct cm36283_info *lpi = lp_info;
- return snprintf(buf, PAGE_SIZE, "%d\n",
- atomic_read(&lpi->ps_poll_delay));
- }
- static ssize_t ps_poll_delay_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct cm36283_info *lpi = lp_info;
- unsigned long interval_ms;
- if (kstrtoul(buf, 10, &interval_ms))
- return -EINVAL;
- if ((interval_ms < CM36283_PS_MIN_POLL_DELAY) ||
- (interval_ms > CM36283_PS_MAX_POLL_DELAY))
- return -EINVAL;
- atomic_set(&lpi->ps_poll_delay, (unsigned int) interval_ms);
- return count;
- }
- static int ps_poll_delay_set(struct sensors_classdev *sensors_cdev,
- unsigned int delay_msec)
- {
- struct cm36283_info *lpi = container_of(sensors_cdev,
- struct cm36283_info, als_cdev);
- if ((delay_msec < CM36283_PS_MIN_POLL_DELAY) ||
- (delay_msec > CM36283_PS_MAX_POLL_DELAY))
- return -EINVAL;
- atomic_set(&lpi->ps_poll_delay, delay_msec);
- return 0;
- }
- static ssize_t ls_fLevel_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- return sprintf(buf, "fLevel = %d\n", fLevel);
- }
- static ssize_t ls_fLevel_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
- struct cm36283_info *lpi = lp_info;
- int value=0;
- sscanf(buf, "%d", &value);
- (value>=0)?(value=min(value,10)):(value=max(value,-1));
- fLevel=value;
- input_report_abs(lpi->ls_input_dev, ABS_MISC, fLevel);
- input_sync(lpi->ls_input_dev);
- msleep(1000);
- fLevel=-1;
- return count;
- }
- static int lightsensor_setup(struct cm36283_info *lpi)
- {
- int ret;
- int range;
- lpi->ls_input_dev = input_allocate_device();
- if (!lpi->ls_input_dev) {
- pr_err(
- "[LS][CM36283 error]%s: could not allocate ls input device\n",
- __func__);
- return -ENOMEM;
- }
- lpi->ls_input_dev->name = "cm36283-ls";
- lpi->ls_input_dev->id.bustype = BUS_I2C;
- set_bit(EV_ABS, lpi->ls_input_dev->evbit);
- range = get_als_range();
- input_set_abs_params(lpi->ls_input_dev, ABS_MISC, 0, range, 0, 0);
- ret = input_register_device(lpi->ls_input_dev);
- if (ret < 0) {
- pr_err("[LS][CM36283 error]%s: can not register ls input device\n",
- __func__);
- goto err_free_ls_input_device;
- }
- return ret;
- err_free_ls_input_device:
- input_free_device(lpi->ls_input_dev);
- return ret;
- }
- static int psensor_setup(struct cm36283_info *lpi)
- {
- int ret;
- lpi->ps_input_dev = input_allocate_device();
- if (!lpi->ps_input_dev) {
- pr_err(
- "[PS][CM36283 error]%s: could not allocate ps input device\n",
- __func__);
- return -ENOMEM;
- }
- lpi->ps_input_dev->name = "cm36283-ps";
- lpi->ps_input_dev->id.bustype = BUS_I2C;
- set_bit(EV_ABS, lpi->ps_input_dev->evbit);
- input_set_abs_params(lpi->ps_input_dev, ABS_DISTANCE, 0, 1, 0, 0);
- ret = input_register_device(lpi->ps_input_dev);
- if (ret < 0) {
- pr_err(
- "[PS][CM36283 error]%s: could not register ps input device\n",
- __func__);
- goto err_free_ps_input_device;
- }
- return ret;
- err_free_ps_input_device:
- input_free_device(lpi->ps_input_dev);
- return ret;
- }
- static int initial_cm36283(struct cm36283_info *lpi)
- {
- int val, ret;
- uint16_t idReg;
- val = gpio_get_value(lpi->intr_pin);
- dev_dbg(&lpi->i2c_client->dev, "%s, INTERRUPT GPIO val = %d\n",
- __func__, val);
- ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ID_REG, &idReg);
- return ret;
- }
- static int cm36283_setup(struct cm36283_info *lpi)
- {
- int ret = 0;
- als_power(1);
- msleep(5);
- ret = gpio_request(lpi->intr_pin, "gpio_cm36283_intr");
- if (ret < 0) {
- pr_err("[PS][CM36283 error]%s: gpio %d request failed (%d)\n",
- __func__, lpi->intr_pin, ret);
- return ret;
- }
- ret = gpio_direction_input(lpi->intr_pin);
- if (ret < 0) {
- pr_err(
- "[PS][CM36283 error]%s: fail to set gpio %d as input (%d)\n",
- __func__, lpi->intr_pin, ret);
- goto fail_free_intr_pin;
- }
- ret = initial_cm36283(lpi);
- if (ret < 0) {
- pr_err(
- "[PS_ERR][CM36283 error]%s: fail to initial cm36283 (%d)\n",
- __func__, ret);
- goto fail_free_intr_pin;
- }
-
- /*Default disable P sensor and L sensor*/
- ls_initial_cmd(lpi);
- psensor_initial_cmd(lpi);
- if (!lpi->polling)
- ret = request_any_context_irq(lpi->irq,
- cm36283_irq_handler,
- IRQF_TRIGGER_LOW,
- "cm36283",
- lpi);
- if (ret < 0) {
- pr_err(
- "[PS][CM36283 error]%s: req_irq(%d) fail for gpio %d (%d)\n",
- __func__, lpi->irq,
- lpi->intr_pin, ret);
- goto fail_free_intr_pin;
- }
- return ret;
- fail_free_intr_pin:
- gpio_free(lpi->intr_pin);
- return ret;
- }
- static int cm36283_parse_dt(struct device *dev,
- struct cm36283_platform_data *pdata)
- {
- struct device_node *np = dev->of_node;
- u32 levels[CM36283_LEVELS_SIZE], i;
- u32 temp_val;
- int rc;
- rc = of_get_named_gpio_flags(np, "capella,interrupt-gpio",
- 0, NULL);
- if (rc < 0) {
- dev_err(dev, "Unable to read interrupt pin number\n");
- return rc;
- } else {
- pdata->intr = rc;
- }
- rc = of_property_read_u32_array(np, "capella,levels", levels,
- CM36283_LEVELS_SIZE);
- if (rc) {
- dev_err(dev, "Unable to read levels data\n");
- return rc;
- } else {
- for (i = 0; i < CM36283_LEVELS_SIZE; i++)
- pdata->levels[i] = levels[i];
- }
- rc = of_property_read_u32(np, "capella,ps_close_thd_set", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read ps_close_thd_set\n");
- return rc;
- } else {
- pdata->ps_close_thd_set = (u8)temp_val;
- }
- rc = of_property_read_u32(np, "capella,ps_away_thd_set", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read ps_away_thd_set\n");
- return rc;
- } else {
- pdata->ps_away_thd_set = (u8)temp_val;
- }
- rc = of_property_read_u32(np, "capella,ls_cmd", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read ls_cmd\n");
- return rc;
- } else {
- pdata->ls_cmd = (u16)temp_val;
- }
- rc = of_property_read_u32(np, "capella,ps_conf1_val", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read ps_conf1_val\n");
- return rc;
- } else {
- pdata->ps_conf1_val = (u16)temp_val;
- }
- rc = of_property_read_u32(np, "capella,ps_conf3_val", &temp_val);
- if (rc) {
- dev_err(dev, "Unable to read ps_conf3_val\n");
- return rc;
- } else {
- pdata->ps_conf3_val = (u16)temp_val;
- }
- pdata->polling = of_property_read_bool(np, "capella,use-polling");
- return 0;
- }
- static int create_sysfs_interfaces(struct device *dev,
- struct device_attribute *attributes, int len)
- {
- int i;
- int err;
- for (i = 0; i < len; i++) {
- err = device_create_file(dev, attributes + i);
- if (err)
- goto error;
- }
- return 0;
- error:
- for (; i >= 0; i--)
- device_remove_file(dev, attributes + i);
- dev_err(dev, "%s:Unable to create interface\n", __func__);
- return err;
- }
- static int remove_sysfs_interfaces(struct device *dev,
- struct device_attribute *attributes, int len)
- {
- int i;
- for (i = 0; i < len; i++)
- device_remove_file(dev, attributes + i);
- return 0;
- }
- static struct device_attribute light_attr[] = {
- __ATTR(ls_adc, 0664, ls_adc_show, NULL),
- __ATTR(ls_kadc, 0664, ls_kadc_show, ls_kadc_store),
- __ATTR(ls_gadc, 0664, ls_gadc_show, ls_gadc_store),
- __ATTR(ls_conf, 0664, ls_conf_show, ls_conf_store),
- __ATTR(ls_adc_table, 0664,
- ls_adc_table_show, ls_adc_table_store),
- __ATTR(poll_delay, 0664, ls_poll_delay_show,
- ls_poll_delay_store),
- __ATTR(enable, 0664,
- ls_enable_show, ls_enable_store),
- };
- static struct device_attribute proximity_attr[] = {
- __ATTR(enable, 0664, ps_adc_show, ps_enable_store),
- __ATTR(ps_parameters, 0664,
- ps_parameters_show, ps_parameters_store),
- __ATTR(ps_conf, 0664, ps_conf_show, ps_conf_store),
- __ATTR(ps_hw, 0664, ps_hw_show, ps_hw_store),
- __ATTR(ps_thd, 0664, ps_thd_show, ps_thd_store),
- __ATTR(poll_delay, 0664, ps_poll_delay_show,
- ps_poll_delay_store),
- __ATTR(ls_flevel, 0664, ls_fLevel_show, ls_fLevel_store),
- };
- static int cm36283_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
- {
- int ret = 0;
- struct cm36283_info *lpi;
- struct cm36283_platform_data *pdata;
- lpi = kzalloc(sizeof(struct cm36283_info), GFP_KERNEL);
- if (!lpi)
- return -ENOMEM;
- lpi->i2c_client = client;
- if (client->dev.of_node) {
- pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- dev_err(&client->dev, "Failed to allocate memory for pdata\n");
- ret = -ENOMEM;
- goto err_platform_data_null;
- }
- ret = cm36283_parse_dt(&client->dev, pdata);
- pdata->slave_addr = client->addr;
- if (ret) {
- dev_err(&client->dev, "Failed to get pdata from device tree\n");
- goto err_parse_dt;
- }
- } else {
- pdata = client->dev.platform_data;
- if (!pdata) {
- dev_err(&client->dev, "%s: Assign platform_data error!!\n",
- __func__);
- ret = -EBUSY;
- goto err_platform_data_null;
- }
- }
- lpi->irq = client->irq;
- i2c_set_clientdata(client, lpi);
-
- lpi->intr_pin = pdata->intr;
- lpi->adc_table = pdata->levels;
- lpi->power = pdata->power;
-
- lpi->slave_addr = pdata->slave_addr;
-
- lpi->ps_away_thd_set = pdata->ps_away_thd_set;
- lpi->ps_close_thd_set = pdata->ps_close_thd_set;
- lpi->ps_conf1_val = pdata->ps_conf1_val;
- lpi->ps_conf3_val = pdata->ps_conf3_val;
- lpi->polling = pdata->polling;
- atomic_set(&lpi->ls_poll_delay,
- (unsigned int) CM36283_LS_DEFAULT_POLL_DELAY);
- atomic_set(&lpi->ps_poll_delay,
- (unsigned int) CM36283_PS_DEFAULT_POLL_DELAY);
-
- lpi->ls_cmd = pdata->ls_cmd;
-
- lpi->record_clear_int_fail=0;
-
- dev_dbg(&lpi->i2c_client->dev, "[PS][CM36283] %s: ls_cmd 0x%x\n",
- __func__, lpi->ls_cmd);
-
- if (pdata->ls_cmd == 0) {
- lpi->ls_cmd = CM36283_ALS_IT_80ms | CM36283_ALS_GAIN_2;
- }
- lp_info = lpi;
- mutex_init(&CM36283_control_mutex);
- mutex_init(&als_enable_mutex);
- mutex_init(&als_disable_mutex);
- mutex_init(&als_get_adc_mutex);
- mutex_init(&ps_enable_mutex);
- mutex_init(&ps_disable_mutex);
- mutex_init(&ps_get_adc_mutex);
- /*
- * SET LUX STEP FACTOR HERE
- * if adc raw value one step = 5/100 = 1/20 = 0.05 lux
- * the following will set the factor 0.05 = 1/20
- * and lpi->golden_adc = 1;
- * set als_kadc = (ALS_CALIBRATED << 16) | 20;
- */
- als_kadc = (ALS_CALIBRATED << 16) | 10;
- lpi->golden_adc = 100;
- lpi->ls_calibrate = 0;
- lightsensor_set_kvalue(lpi);
- ret = lightsensor_update_table(lpi);
- if (ret < 0) {
- pr_err("[LS][CM36283 error]%s: update ls table fail\n",
- __func__);
- goto err_lightsensor_update_table;
- }
- lpi->lp_wq = create_singlethread_workqueue("cm36283_wq");
- if (!lpi->lp_wq) {
- pr_err("[PS][CM36283 error]%s: can't create workqueue\n", __func__);
- ret = -ENOMEM;
- goto err_create_singlethread_workqueue;
- }
- wake_lock_init(&(lpi->ps_wake_lock), WAKE_LOCK_SUSPEND, "proximity");
- ret = cm36283_power_set(lpi, true);
- if (ret < 0) {
- dev_err(&client->dev, "%s:cm36283 power on error!\n", __func__);
- goto err_cm36283_power_on;
- }
- ret = cm36283_setup(lpi);
- if (ret < 0) {
- pr_err("[PS_ERR][CM36283 error]%s: cm36283_setup error!\n", __func__);
- goto err_cm36283_setup;
- }
- ret = lightsensor_setup(lpi);
- if (ret < 0) {
- pr_err("[LS][CM36283 error]%s: lightsensor_setup error!!\n",
- __func__);
- goto err_lightsensor_setup;
- }
- ret = psensor_setup(lpi);
- if (ret < 0) {
- pr_err("[PS][CM36283 error]%s: psensor_setup error!!\n",
- __func__);
- goto err_psensor_setup;
- }
- ret = create_sysfs_interfaces(&lpi->ls_input_dev->dev, light_attr,
- ARRAY_SIZE(light_attr));
- if (ret < 0) {
- dev_err(&client->dev, "failed to create sysfs\n");
- goto err_input_cleanup;
- }
- ret = create_sysfs_interfaces(&lpi->ps_input_dev->dev, proximity_attr,
- ARRAY_SIZE(proximity_attr));
- if (ret < 0) {
- dev_err(&client->dev, "failed to create sysfs\n");
- goto err_light_sysfs_cleanup;
- }
- lpi->als_cdev = sensors_light_cdev;
- lpi->als_cdev.sensors_enable = ls_enable_set;
- lpi->als_cdev.sensors_poll_delay = ls_poll_delay_set;
- lpi->als_cdev.min_delay = CM36283_LS_MIN_POLL_DELAY * 1000;
- lpi->ps_cdev = sensors_proximity_cdev;
- lpi->ps_cdev.sensors_enable = ps_enable_set;
- lpi->ps_cdev.sensors_poll_delay = ps_poll_delay_set;
- lpi->ps_cdev.min_delay = CM36283_PS_MIN_POLL_DELAY * 1000;
- ret = sensors_classdev_register(&client->dev, &lpi->als_cdev);
- if (ret)
- goto err_proximity_sysfs_cleanup;
- ret = sensors_classdev_register(&client->dev, &lpi->ps_cdev);
- if (ret)
- goto err_create_class_sysfs;
- mutex_init(&wq_lock);
- INIT_DELAYED_WORK(&lpi->ldwork, lsensor_delay_work_handler);
- INIT_DELAYED_WORK(&lpi->pdwork, psensor_delay_work_handler);
- dev_dbg(&lpi->i2c_client->dev, "%s: Probe success!\n", __func__);
- return ret;
- err_create_class_sysfs:
- sensors_classdev_unregister(&lpi->als_cdev);
- err_proximity_sysfs_cleanup:
- remove_sysfs_interfaces(&lpi->ps_input_dev->dev, proximity_attr,
- ARRAY_SIZE(proximity_attr));
- err_light_sysfs_cleanup:
- remove_sysfs_interfaces(&lpi->ls_input_dev->dev, light_attr,
- ARRAY_SIZE(light_attr));
- err_input_cleanup:
- input_unregister_device(lpi->ps_input_dev);
- input_free_device(lpi->ps_input_dev);
- err_psensor_setup:
- input_unregister_device(lpi->ls_input_dev);
- input_free_device(lpi->ls_input_dev);
- err_lightsensor_setup:
- err_cm36283_setup:
- cm36283_power_set(lpi, false);
- err_cm36283_power_on:
- wake_lock_destroy(&(lpi->ps_wake_lock));
- destroy_workqueue(lpi->lp_wq);
- err_create_singlethread_workqueue:
- err_lightsensor_update_table:
- mutex_destroy(&CM36283_control_mutex);
- mutex_destroy(&als_enable_mutex);
- mutex_destroy(&als_disable_mutex);
- mutex_destroy(&als_get_adc_mutex);
- mutex_destroy(&ps_enable_mutex);
- mutex_destroy(&ps_disable_mutex);
- mutex_destroy(&ps_get_adc_mutex);
- err_parse_dt:
- if (client->dev.of_node && (pdata != NULL))
- devm_kfree(&client->dev, pdata);
- err_platform_data_null:
- kfree(lpi);
- dev_err(&client->dev, "%s:error exit! ret = %d\n", __func__, ret);
- return ret;
- }
- static int control_and_report(struct cm36283_info *lpi, uint8_t mode,
- uint16_t param, int report)
- {
- int ret = 0;
- uint16_t adc_value = 0;
- uint16_t ps_data = 0;
- int level = 0, i, val;
-
- mutex_lock(&CM36283_control_mutex);
- if( mode == CONTROL_ALS ){
- if(param){
- lpi->ls_cmd &= CM36283_ALS_SD_MASK;
- } else {
- lpi->ls_cmd |= CM36283_ALS_SD;
- }
- _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
- lpi->als_enable=param;
- } else if( mode == CONTROL_PS ){
- if(param){
- lpi->ps_conf1_val &= CM36283_PS_SD_MASK;
- lpi->ps_conf1_val |= CM36283_PS_INT_IN_AND_OUT;
- } else {
- lpi->ps_conf1_val |= CM36283_PS_SD;
- lpi->ps_conf1_val &= CM36283_PS_INT_MASK;
- }
- _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);
- lpi->ps_enable=param;
- }
- if((mode == CONTROL_ALS)||(mode == CONTROL_PS)){
- if( param==1 ){
- msleep(100);
- }
- }
-
- if(lpi->als_enable){
- if( mode == CONTROL_ALS ||
- ( mode == CONTROL_INT_ISR_REPORT &&
- ((param&INT_FLAG_ALS_IF_L)||(param&INT_FLAG_ALS_IF_H)))){
-
- lpi->ls_cmd &= CM36283_ALS_INT_MASK;
- ret = _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
-
- get_ls_adc_value(&adc_value, 0);
-
- if( lpi->ls_calibrate ) {
- for (i = 0; i < 10; i++) {
- if (adc_value <= (*(lpi->cali_table + i))) {
- level = i;
- if (*(lpi->cali_table + i))
- break;
- }
- if ( i == 9) {/*avoid i = 10, because 'cali_table' of size is 10 */
- level = i;
- break;
- }
- }
- } else {
- for (i = 0; i < 10; i++) {
- if (adc_value <= (*(lpi->adc_table + i))) {
- level = i;
- if (*(lpi->adc_table + i))
- break;
- }
- if ( i == 9) {/*avoid i = 10, because 'cali_table' of size is 10 */
- level = i;
- break;
- }
- }
- }
- if (!lpi->polling) {
- ret = set_lsensor_range(((i == 0) ||
- (adc_value == 0)) ? 0 :
- *(lpi->cali_table + (i - 1)) + 1,
- *(lpi->cali_table + i));
- lpi->ls_cmd |= CM36283_ALS_INT_EN;
- }
- ret = _cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF,
- lpi->ls_cmd);
- if (report) {
- lpi->current_level = level;
- lpi->current_adc = adc_value;
- input_report_abs(lpi->ls_input_dev, ABS_MISC, level);
- input_sync(lpi->ls_input_dev);
- }
- }
- }
- #define PS_CLOSE 1
- #define PS_AWAY (1<<1)
- #define PS_CLOSE_AND_AWAY PS_CLOSE+PS_AWAY
- if (report && (lpi->ps_enable)) {
- int ps_status = 0;
- if (mode == CONTROL_PS)
- ps_status = PS_CLOSE_AND_AWAY;
- else if (mode == CONTROL_INT_ISR_REPORT) {
- if (param & INT_FLAG_PS_IF_CLOSE)
- ps_status |= PS_CLOSE;
- if (param & INT_FLAG_PS_IF_AWAY)
- ps_status |= PS_AWAY;
- }
- if (ps_status != 0) {
- switch (ps_status) {
- case PS_CLOSE_AND_AWAY:
- get_stable_ps_adc_value(&ps_data);
- val = (ps_data >= lpi->ps_close_thd_set)
- ? 0 : 1;
- break;
- case PS_AWAY:
- val = 1;
- break;
- case PS_CLOSE:
- val = 0;
- break;
- };
- input_report_abs(lpi->ps_input_dev, ABS_DISTANCE, val);
- input_sync(lpi->ps_input_dev);
- }
- }
- mutex_unlock(&CM36283_control_mutex);
- return ret;
- }
- static int cm36283_power_set(struct cm36283_info *info, bool on)
- {
- int rc;
- if (on) {
- info->vdd = regulator_get(&info->i2c_client->dev, "vdd");
- if (IS_ERR(info->vdd)) {
- rc = PTR_ERR(info->vdd);
- dev_err(&info->i2c_client->dev,
- "Regulator get failed vdd rc=%d\n", rc);
- goto err_vdd_get;
- }
- if (regulator_count_voltages(info->vdd) > 0) {
- rc = regulator_set_voltage(info->vdd,
- CM36283_VDD_MIN_UV, CM36283_VDD_MAX_UV);
- if (rc) {
- dev_err(&info->i2c_client->dev,
- "Regulator set failed vdd rc=%d\n", rc);
- goto err_vdd_set_vtg;
- }
- }
- info->vio = regulator_get(&info->i2c_client->dev, "vio");
- if (IS_ERR(info->vio)) {
- rc = PTR_ERR(info->vio);
- dev_err(&info->i2c_client->dev,
- "Regulator get failed vio rc=%d\n", rc);
- goto err_vio_get;
- }
- if (regulator_count_voltages(info->vio) > 0) {
- rc = regulator_set_voltage(info->vio,
- CM36283_VI2C_MIN_UV, CM36283_VI2C_MAX_UV);
- if (rc) {
- dev_err(&info->i2c_client->dev,
- "Regulator set failed vio rc=%d\n", rc);
- goto err_vio_set_vtg;
- }
- }
- rc = regulator_enable(info->vdd);
- if (rc) {
- dev_err(&info->i2c_client->dev,
- "Regulator vdd enable failed rc=%d\n", rc);
- goto err_vdd_ena;
- }
- rc = regulator_enable(info->vio);
- if (rc) {
- dev_err(&info->i2c_client->dev,
- "Regulator vio enable failed rc=%d\n", rc);
- goto err_vio_ena;
- }
- } else {
- rc = regulator_disable(info->vdd);
- if (rc) {
- dev_err(&info->i2c_client->dev,
- "Regulator vdd disable failed rc=%d\n", rc);
- return rc;
- }
- if (regulator_count_voltages(info->vdd) > 0)
- regulator_set_voltage(info->vdd, 0, CM36283_VDD_MAX_UV);
- regulator_put(info->vdd);
- rc = regulator_disable(info->vio);
- if (rc) {
- dev_err(&info->i2c_client->dev,
- "Regulator vio disable failed rc=%d\n", rc);
- return rc;
- }
- if (regulator_count_voltages(info->vio) > 0)
- regulator_set_voltage(info->vio, 0,
- CM36283_VI2C_MAX_UV);
- regulator_put(info->vio);
- }
- return 0;
- err_vio_ena:
- regulator_disable(info->vdd);
- err_vdd_ena:
- if (regulator_count_voltages(info->vio) > 0)
- regulator_set_voltage(info->vio, 0, CM36283_VI2C_MAX_UV);
- err_vio_set_vtg:
- regulator_put(info->vio);
- err_vio_get:
- if (regulator_count_voltages(info->vdd) > 0)
- regulator_set_voltage(info->vdd, 0, CM36283_VDD_MAX_UV);
- err_vdd_set_vtg:
- regulator_put(info->vdd);
- err_vdd_get:
- return rc;
- }
- #ifdef CONFIG_PM_SLEEP
- static int cm36283_suspend(struct device *dev)
- {
- struct cm36283_info *lpi = lp_info;
- if (lpi->als_enable) {
- if (lightsensor_disable(lpi))
- goto out;
- lpi->als_enable = 1;
- }
- if (cm36283_power_set(lpi, 0))
- goto out;
- return 0;
- out:
- dev_err(&lpi->i2c_client->dev, "%s:failed during resume operation.\n",
- __func__);
- return -EIO;
- }
- static int cm36283_resume(struct device *dev)
- {
- struct cm36283_info *lpi = lp_info;
- if (cm36283_power_set(lpi, 1))
- goto out;
- if (lpi->als_enable) {
- ls_initial_cmd(lpi);
- psensor_initial_cmd(lpi);
- if (lightsensor_enable(lpi))
- goto out;
- }
- return 0;
- out:
- dev_err(&lpi->i2c_client->dev, "%s:failed during resume operation.\n",
- __func__);
- return -EIO;
- }
- #endif
- static UNIVERSAL_DEV_PM_OPS(cm36283_pm, cm36283_suspend, cm36283_resume, NULL);
- static const struct i2c_device_id cm36283_i2c_id[] = {
- {CM36283_I2C_NAME, 0},
- {}
- };
- static struct of_device_id cm36283_match_table[] = {
- { .compatible = "capella,cm36283",},
- { },
- };
- static struct i2c_driver cm36283_driver = {
- .id_table = cm36283_i2c_id,
- .probe = cm36283_probe,
- .driver = {
- .name = CM36283_I2C_NAME,
- .owner = THIS_MODULE,
- .pm = &cm36283_pm,
- .of_match_table = cm36283_match_table,
- },
- };
- static int __init cm36283_init(void)
- {
- return i2c_add_driver(&cm36283_driver);
- }
- static void __exit cm36283_exit(void)
- {
- i2c_del_driver(&cm36283_driver);
- }
- module_init(cm36283_init);
- module_exit(cm36283_exit);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("CM36283 Driver");
- MODULE_AUTHOR("Frank Hsieh <pengyueh@gmail.com>");
|