cm36558.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760
  1. /*
  2. * Author: yucong xiong <yucong.xion@mediatek.com>
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. */
  14. #include <linux/of.h>
  15. #include <linux/of_address.h>
  16. #include <linux/of_irq.h>
  17. #include <linux/gpio.h>
  18. #include "cust_alsps.h"
  19. #include "cm36558.h"
  20. #include "alsps.h"
  21. /******************************************************************************
  22. * configuration
  23. *******************************************************************************/
  24. /*----------------------------------------------------------------------------*/
  25. #define CM36558_DEV_NAME "CM36558"
  26. /*----------------------------------------------------------------------------*/
  27. #define APS_TAG "[ALS/PS] "
  28. #define APS_FUN(f) pr_debug(APS_TAG"%s\n", __func__)
  29. #define APS_ERR(fmt, args...) pr_err(APS_TAG"%s %d : "fmt, __func__, __LINE__, ##args)
  30. #define APS_LOG(fmt, args...) pr_debug(APS_TAG fmt, ##args)
  31. #define APS_DBG(fmt, args...) pr_debug(APS_TAG fmt, ##args)
  32. #define I2C_FLAG_WRITE 0
  33. #define I2C_FLAG_READ 1
  34. /*----------------------------------------------------------------------------*/
  35. static int CM36558_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
  36. static int CM36558_i2c_remove(struct i2c_client *client);
  37. static int CM36558_i2c_detect(struct i2c_client *client, struct i2c_board_info *info);
  38. static int CM36558_i2c_suspend(struct i2c_client *client, pm_message_t msg);
  39. static int CM36558_i2c_resume(struct i2c_client *client);
  40. /*----------------------------------------------------------------------------*/
  41. static const struct i2c_device_id CM36558_i2c_id[] = { {CM36558_DEV_NAME, 0}, {} };
  42. static unsigned long long int_top_time;
  43. /* Maintain alsps cust info here */
  44. struct alsps_hw alsps_cust;
  45. static struct alsps_hw *hw = &alsps_cust;
  46. struct platform_device *alspsPltFmDev;
  47. /* For alsp driver get cust info */
  48. struct alsps_hw *get_cust_alsps(void)
  49. {
  50. return &alsps_cust;
  51. }
  52. /*----------------------------------------------------------------------------*/
  53. struct CM36558_priv {
  54. struct alsps_hw *hw;
  55. struct i2c_client *client;
  56. struct work_struct eint_work;
  57. /*misc */
  58. u16 als_modulus;
  59. atomic_t i2c_retry;
  60. atomic_t als_suspend;
  61. atomic_t als_debounce; /*debounce time after enabling als */
  62. atomic_t als_deb_on; /*indicates if the debounce is on */
  63. atomic_t als_deb_end; /*the jiffies representing the end of debounce */
  64. atomic_t ps_mask; /*mask ps: always return far away */
  65. atomic_t ps_debounce; /*debounce time after enabling ps */
  66. atomic_t ps_deb_on; /*indicates if the debounce is on */
  67. atomic_t ps_deb_end; /*the jiffies representing the end of debounce */
  68. atomic_t ps_suspend;
  69. atomic_t trace;
  70. atomic_t init_done;
  71. struct device_node *irq_node;
  72. int irq;
  73. /*data */
  74. u16 als;
  75. u16 ps;
  76. u8 _align;
  77. u16 als_level_num;
  78. u16 als_value_num;
  79. u32 als_level[C_CUST_ALS_LEVEL - 1];
  80. u32 als_value[C_CUST_ALS_LEVEL];
  81. int ps_cali;
  82. atomic_t als_cmd_val; /*the cmd value can't be read, stored in ram */
  83. atomic_t ps_cmd_val; /*the cmd value can't be read, stored in ram */
  84. atomic_t ps_thd_val_high; /*the cmd value can't be read, stored in ram */
  85. atomic_t ps_thd_val_low; /*the cmd value can't be read, stored in ram */
  86. atomic_t als_thd_val_high; /*the cmd value can't be read, stored in ram */
  87. atomic_t als_thd_val_low; /*the cmd value can't be read, stored in ram */
  88. atomic_t ps_thd_val;
  89. ulong enable; /*enable mask */
  90. ulong pending_intr; /*pending interrupt */
  91. };
  92. /*----------------------------------------------------------------------------*/
  93. #ifdef CONFIG_OF
  94. static const struct of_device_id alsps_of_match[] = {
  95. {.compatible = "mediatek,alsps"},
  96. {},
  97. };
  98. #endif
  99. static struct i2c_driver CM36558_i2c_driver = {
  100. .probe = CM36558_i2c_probe,
  101. .remove = CM36558_i2c_remove,
  102. .detect = CM36558_i2c_detect,
  103. .suspend = CM36558_i2c_suspend,
  104. .resume = CM36558_i2c_resume,
  105. .id_table = CM36558_i2c_id,
  106. .driver = {
  107. .name = CM36558_DEV_NAME,
  108. #ifdef CONFIG_OF
  109. .of_match_table = alsps_of_match,
  110. #endif
  111. },
  112. };
  113. /*----------------------------------------------------------------------------*/
  114. struct PS_CALI_DATA_STRUCT {
  115. int close;
  116. int far_away;
  117. int valid;
  118. };
  119. /*----------------------------------------------------------------------------*/
  120. static struct i2c_client *CM36558_i2c_client;
  121. static struct CM36558_priv *CM36558_obj;
  122. static int CM36558_local_init(void);
  123. static int CM36558_remove(void);
  124. static int CM36558_init_flag = -1;
  125. static struct alsps_init_info CM36558_init_info = {
  126. .name = "CM36558",
  127. .init = CM36558_local_init,
  128. .uninit = CM36558_remove,
  129. };
  130. /*----------------------------------------------------------------------------*/
  131. static DEFINE_MUTEX(CM36558_mutex);
  132. /*----------------------------------------------------------------------------*/
  133. enum {
  134. CMC_BIT_ALS = 1,
  135. CMC_BIT_PS = 2,
  136. } CMC_BIT;
  137. /*-----------------------------CMC for debugging-------------------------------*/
  138. enum {
  139. CMC_TRC_ALS_DATA = 0x0001,
  140. CMC_TRC_PS_DATA = 0x0002,
  141. CMC_TRC_EINT = 0x0004,
  142. CMC_TRC_IOCTL = 0x0008,
  143. CMC_TRC_I2C = 0x0010,
  144. CMC_TRC_CVT_ALS = 0x0020,
  145. CMC_TRC_CVT_PS = 0x0040,
  146. CMC_TRC_CVT_AAL = 0x0080,
  147. CMC_TRC_DEBUG = 0x8000,
  148. } CMC_TRC;
  149. /*-----------------------------------------------------------------------------*/
  150. int CM36558_i2c_master_operate(struct i2c_client *client, char *buf, int count, int i2c_flag)
  151. {
  152. int res = 0;
  153. #ifndef CONFIG_MTK_I2C_EXTENSION
  154. struct i2c_msg msg[2];
  155. #endif
  156. mutex_lock(&CM36558_mutex);
  157. switch (i2c_flag) {
  158. case I2C_FLAG_WRITE:
  159. #ifdef CONFIG_MTK_I2C_EXTENSION
  160. client->addr &= I2C_MASK_FLAG;
  161. res = i2c_master_send(client, buf, count);
  162. client->addr &= I2C_MASK_FLAG;
  163. #else
  164. res = i2c_master_send(client, buf, count);
  165. #endif
  166. break;
  167. case I2C_FLAG_READ:
  168. #ifdef CONFIG_MTK_I2C_EXTENSION
  169. client->addr &= I2C_MASK_FLAG;
  170. client->addr |= I2C_WR_FLAG;
  171. client->addr |= I2C_RS_FLAG;
  172. res = i2c_master_send(client, buf, count);
  173. client->addr &= I2C_MASK_FLAG;
  174. #else
  175. msg[0].addr = client->addr;
  176. msg[0].flags = 0;
  177. msg[0].len = 1;
  178. msg[0].buf = buf;
  179. msg[1].addr = client->addr;
  180. msg[1].flags = I2C_M_RD;
  181. msg[1].len = count;
  182. msg[1].buf = buf;
  183. res = i2c_transfer(client->adapter, msg, sizeof(msg)/sizeof(msg[0]));
  184. #endif
  185. break;
  186. default:
  187. APS_LOG("CM36558_i2c_master_operate i2c_flag command not support!\n");
  188. break;
  189. }
  190. if (res < 0)
  191. goto EXIT_ERR;
  192. mutex_unlock(&CM36558_mutex);
  193. return res;
  194. EXIT_ERR:
  195. mutex_unlock(&CM36558_mutex);
  196. APS_ERR("CM36558_i2c_master_operate fail\n");
  197. return res;
  198. }
  199. /*----------------------------------------------------------------------------*/
  200. static void CM36558_power(struct alsps_hw *hw, unsigned int on)
  201. {
  202. }
  203. /********************************************************************/
  204. int CM36558_enable_ps(struct i2c_client *client, int enable)
  205. {
  206. struct CM36558_priv *obj = i2c_get_clientdata(client);
  207. int res = 0;
  208. u8 databuf[3];
  209. if (enable == 1) {
  210. APS_LOG("CM36558_enable_ps enable_ps\n");
  211. databuf[0] = CM36558_REG_PS_CONF1_2;
  212. res = CM36558_i2c_master_operate(client, databuf, 2, I2C_FLAG_READ);
  213. if (res < 0) {
  214. APS_ERR("i2c_master_send function err\n");
  215. goto ENABLE_PS_EXIT_ERR;
  216. }
  217. APS_LOG("CM36558_REG_PS_CONF1_2 value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
  218. databuf[2] = databuf[1];
  219. databuf[1] = databuf[0] & 0xFE;
  220. databuf[0] = CM36558_REG_PS_CONF1_2;
  221. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  222. if (res < 0) {
  223. APS_ERR("i2c_master_send function err\n");
  224. goto ENABLE_PS_EXIT_ERR;
  225. }
  226. atomic_set(&obj->ps_deb_on, 1);
  227. atomic_set(&obj->ps_deb_end, jiffies + atomic_read(&obj->ps_debounce) / (1000 / HZ));
  228. } else {
  229. APS_LOG("CM36558_enable_ps disable_ps\n");
  230. databuf[0] = CM36558_REG_PS_CONF1_2;
  231. res = CM36558_i2c_master_operate(client, databuf, 2, I2C_FLAG_READ);
  232. if (res < 0) {
  233. APS_ERR("i2c_master_send function err\n");
  234. goto ENABLE_PS_EXIT_ERR;
  235. }
  236. APS_LOG("CM36558_REG_PS_CONF1_2 value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
  237. databuf[2] = databuf[1];
  238. databuf[1] = databuf[0] | 0x01;
  239. databuf[0] = CM36558_REG_PS_CONF1_2;
  240. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  241. if (res < 0) {
  242. APS_ERR("i2c_master_send function err\n");
  243. goto ENABLE_PS_EXIT_ERR;
  244. }
  245. atomic_set(&obj->ps_deb_on, 0);
  246. }
  247. return 0;
  248. ENABLE_PS_EXIT_ERR:
  249. return res;
  250. }
  251. /********************************************************************/
  252. int CM36558_enable_als(struct i2c_client *client, int enable)
  253. {
  254. struct CM36558_priv *obj = i2c_get_clientdata(client);
  255. int res = 0;
  256. u8 databuf[3];
  257. if (enable == 1) {
  258. APS_LOG("CM36558_enable_als enable_als\n");
  259. databuf[0] = CM36558_REG_ALS_UV_CONF;
  260. res = CM36558_i2c_master_operate(client, databuf, 2, I2C_FLAG_READ);
  261. if (res < 0) {
  262. APS_ERR("i2c_master_send function err\n");
  263. goto ENABLE_ALS_EXIT_ERR;
  264. }
  265. APS_LOG("CM36558_REG_ALS_UV_CONF value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
  266. databuf[2] = databuf[1];
  267. databuf[1] = databuf[0] & 0xFE;
  268. databuf[0] = CM36558_REG_ALS_UV_CONF;
  269. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  270. if (res < 0) {
  271. APS_ERR("i2c_master_send function err\n");
  272. goto ENABLE_ALS_EXIT_ERR;
  273. }
  274. atomic_set(&obj->als_deb_on, 1);
  275. atomic_set(&obj->als_deb_end, jiffies + atomic_read(&obj->als_debounce) / (1000 / HZ));
  276. } else {
  277. APS_LOG("CM36558_enable_als disable_als\n");
  278. databuf[0] = CM36558_REG_ALS_UV_CONF;
  279. res = CM36558_i2c_master_operate(client, databuf, 2, I2C_FLAG_READ);
  280. if (res < 0) {
  281. APS_ERR("i2c_master_send function err\n");
  282. goto ENABLE_ALS_EXIT_ERR;
  283. }
  284. APS_LOG("CM36558_REG_ALS_UV_CONF value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
  285. databuf[2] = databuf[1];
  286. databuf[1] = databuf[0] | 0x01;
  287. databuf[0] = CM36558_REG_ALS_UV_CONF;
  288. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  289. if (res < 0) {
  290. APS_ERR("i2c_master_send function err\n");
  291. goto ENABLE_ALS_EXIT_ERR;
  292. }
  293. atomic_set(&obj->als_deb_on, 0);
  294. }
  295. return 0;
  296. ENABLE_ALS_EXIT_ERR:
  297. return res;
  298. }
  299. /********************************************************************/
  300. long CM36558_read_ps(struct i2c_client *client, u16 *data)
  301. {
  302. long res = 0;
  303. u8 databuf[2];
  304. struct CM36558_priv *obj = i2c_get_clientdata(client);
  305. databuf[0] = CM36558_REG_PS_DATA;
  306. res = CM36558_i2c_master_operate(client, databuf, 2, I2C_FLAG_READ);
  307. if (res < 0) {
  308. APS_ERR("i2c_master_send function err\n");
  309. goto READ_PS_EXIT_ERR;
  310. }
  311. if (atomic_read(&obj->trace) & CMC_TRC_DEBUG)
  312. APS_LOG("CM36558_REG_PS_DATA value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
  313. *data = ((databuf[1] << 8) | databuf[0]);
  314. if (*data < obj->ps_cali)
  315. *data = 0;
  316. else
  317. *data = *data - obj->ps_cali;
  318. return 0;
  319. READ_PS_EXIT_ERR:
  320. return res;
  321. }
  322. /********************************************************************/
  323. long CM36558_read_als(struct i2c_client *client, u16 *data)
  324. {
  325. long res = 0;
  326. u8 databuf[2];
  327. struct CM36558_priv *obj = i2c_get_clientdata(client);
  328. databuf[0] = CM36558_REG_ALS_DATA;
  329. res = CM36558_i2c_master_operate(client, databuf, 2, I2C_FLAG_READ);
  330. if (res < 0) {
  331. APS_ERR("i2c_master_send function err\n");
  332. goto READ_ALS_EXIT_ERR;
  333. }
  334. if (atomic_read(&obj->trace) & CMC_TRC_DEBUG)
  335. APS_LOG("CM36558_REG_ALS_DATA value: %d\n", ((databuf[1] << 8) | databuf[0]));
  336. *data = ((databuf[1] << 8) | databuf[0]);
  337. return 0;
  338. READ_ALS_EXIT_ERR:
  339. return res;
  340. }
  341. /********************************************************************/
  342. static int CM36558_get_ps_value(struct CM36558_priv *obj, u8 ps)
  343. {
  344. int val = 0, mask = atomic_read(&obj->ps_mask);
  345. int invalid = 0;
  346. val = 0;
  347. if (ps > atomic_read(&obj->ps_thd_val_high))
  348. val = 0;
  349. else if (ps < atomic_read(&obj->ps_thd_val_low))
  350. val = 1;
  351. if (atomic_read(&obj->ps_suspend)) {
  352. invalid = 1;
  353. } else if (1 == atomic_read(&obj->ps_deb_on)) {
  354. unsigned long endt = atomic_read(&obj->ps_deb_end);
  355. if (time_after(jiffies, endt))
  356. atomic_set(&obj->ps_deb_on, 0);
  357. if (1 == atomic_read(&obj->ps_deb_on))
  358. invalid = 1;
  359. }
  360. if (!invalid) {
  361. if (unlikely(atomic_read(&obj->trace) & CMC_TRC_CVT_PS)) {
  362. if (mask)
  363. APS_DBG("PS: %05d => %05d [M]\n", ps, val);
  364. else
  365. APS_DBG("PS: %05d => %05d\n", ps, val);
  366. }
  367. if (0 == test_bit(CMC_BIT_PS, &obj->enable)) {
  368. APS_DBG("PS: not enable and do not report this value\n");
  369. return -1;
  370. } else {
  371. return val;
  372. }
  373. } else {
  374. if (unlikely(atomic_read(&obj->trace) & CMC_TRC_CVT_PS))
  375. APS_DBG("PS: %05d => %05d (-1)\n", ps, val);
  376. return -1;
  377. }
  378. }
  379. /********************************************************************/
  380. static int CM36558_get_als_value(struct CM36558_priv *obj, u16 als)
  381. {
  382. int idx = 0;
  383. int invalid = 0;
  384. int level_high = 0;
  385. int level_low = 0;
  386. int level_diff = 0;
  387. int value_high = 0;
  388. int value_low = 0;
  389. int value_diff = 0;
  390. int value = 0;
  391. if ((0 == obj->als_level_num) || (0 == obj->als_value_num)) {
  392. APS_ERR("invalid als_level_num = %d, als_value_num = %d\n",
  393. obj->als_level_num, obj->als_value_num);
  394. return -1;
  395. }
  396. if (1 == atomic_read(&obj->als_deb_on)) {
  397. unsigned long endt = atomic_read(&obj->als_deb_end);
  398. if (time_after(jiffies, endt))
  399. atomic_set(&obj->als_deb_on, 0);
  400. if (1 == atomic_read(&obj->als_deb_on))
  401. invalid = 1;
  402. }
  403. for (idx = 0; idx < obj->als_level_num; idx++) {
  404. if (als < obj->hw->als_level[idx])
  405. break;
  406. }
  407. if (idx >= obj->als_level_num || idx >= obj->als_value_num) {
  408. if (idx < obj->als_value_num)
  409. value = obj->hw->als_value[idx-1];
  410. else
  411. value = obj->hw->als_value[obj->als_value_num-1];
  412. } else {
  413. level_high = obj->hw->als_level[idx];
  414. level_low = (idx > 0) ? obj->hw->als_level[idx-1] : 0;
  415. level_diff = level_high - level_low;
  416. value_high = obj->hw->als_value[idx];
  417. value_low = (idx > 0) ? obj->hw->als_value[idx-1] : 0;
  418. value_diff = value_high - value_low;
  419. if ((level_low >= level_high) || (value_low >= value_high))
  420. value = value_low;
  421. else
  422. value = (level_diff * value_low + (als - level_low) * value_diff
  423. + ((level_diff + 1) >> 1)) / level_diff;
  424. }
  425. if (!invalid) {
  426. if (atomic_read(&obj->trace) & CMC_TRC_CVT_AAL)
  427. APS_DBG("ALS: %d [%d, %d] => %d [%d, %d]\n", als, level_low,
  428. level_high, value, value_low, value_high);
  429. } else {
  430. if (atomic_read(&obj->trace) & CMC_TRC_CVT_ALS)
  431. APS_DBG("ALS: %05d => %05d (-1)\n", als, value);
  432. return -1;
  433. }
  434. return value;
  435. }
  436. /*-------------------------------attribute file for debugging----------------------------------*/
  437. /******************************************************************************
  438. * Sysfs attributes
  439. *******************************************************************************/
  440. static ssize_t CM36558_show_config(struct device_driver *ddri, char *buf)
  441. {
  442. ssize_t res = 0;
  443. if (!CM36558_obj) {
  444. APS_ERR("CM36558_obj is null!!\n");
  445. return 0;
  446. }
  447. res = snprintf(buf, PAGE_SIZE, "(%d %d %d %d %d\n)threadhold_low=%d threadhold_high=%d\n",
  448. atomic_read(&CM36558_obj->i2c_retry), atomic_read(&CM36558_obj->als_debounce),
  449. atomic_read(&CM36558_obj->ps_mask), atomic_read(&CM36558_obj->ps_thd_val),
  450. atomic_read(&CM36558_obj->ps_debounce), atomic_read(&CM36558_obj->ps_thd_val_low),
  451. atomic_read(&CM36558_obj->ps_thd_val_high));
  452. return res;
  453. }
  454. /*----------------------------------------------------------------------------*/
  455. static ssize_t CM36558_store_config(struct device_driver *ddri, const char *buf, size_t count)
  456. {
  457. int retry = 0, als_deb = 0, ps_deb = 0, mask = 0, thres = 0;
  458. if (!CM36558_obj) {
  459. APS_ERR("CM36558_obj is null!!\n");
  460. return 0;
  461. }
  462. if (5 == sscanf(buf, "%d %d %d %d %d", &retry, &als_deb, &mask, &thres, &ps_deb)) {
  463. atomic_set(&CM36558_obj->i2c_retry, retry);
  464. atomic_set(&CM36558_obj->als_debounce, als_deb);
  465. atomic_set(&CM36558_obj->ps_mask, mask);
  466. atomic_set(&CM36558_obj->ps_thd_val, thres);
  467. atomic_set(&CM36558_obj->ps_debounce, ps_deb);
  468. } else {
  469. APS_ERR("invalid content: '%s', length = %d\n", buf, (unsigned int)count);
  470. }
  471. return count;
  472. }
  473. /*----------------------------------------------------------------------------*/
  474. static ssize_t CM36558_show_trace(struct device_driver *ddri, char *buf)
  475. {
  476. ssize_t res = 0;
  477. if (!CM36558_obj) {
  478. APS_ERR("CM36558_obj is null!!\n");
  479. return 0;
  480. }
  481. res = snprintf(buf, PAGE_SIZE, "0x%04X\n", atomic_read(&CM36558_obj->trace));
  482. return res;
  483. }
  484. /*----------------------------------------------------------------------------*/
  485. static ssize_t CM36558_store_trace(struct device_driver *ddri, const char *buf, size_t count)
  486. {
  487. int trace = 0;
  488. if (!CM36558_obj) {
  489. APS_ERR("CM36558_obj is null!!\n");
  490. return 0;
  491. }
  492. if (1 == sscanf(buf, "0x%x", &trace))
  493. atomic_set(&CM36558_obj->trace, trace);
  494. else
  495. APS_ERR("invalid content: '%s', length = %d\n", buf, (unsigned int)count);
  496. return count;
  497. }
  498. /*----------------------------------------------------------------------------*/
  499. static ssize_t CM36558_show_als(struct device_driver *ddri, char *buf)
  500. {
  501. int res = 0;
  502. if (!CM36558_obj) {
  503. APS_ERR("CM36558_obj is null!!\n");
  504. return 0;
  505. }
  506. res = CM36558_read_als(CM36558_obj->client, &CM36558_obj->als);
  507. if (res)
  508. return snprintf(buf, PAGE_SIZE, "ERROR: %d\n", res);
  509. else
  510. return snprintf(buf, PAGE_SIZE, "0x%04X\n", CM36558_obj->als);
  511. }
  512. /*----------------------------------------------------------------------------*/
  513. static ssize_t CM36558_show_ps(struct device_driver *ddri, char *buf)
  514. {
  515. ssize_t res = 0;
  516. if (!CM36558_obj) {
  517. APS_ERR("cm3623_obj is null!!\n");
  518. return 0;
  519. }
  520. res = CM36558_read_ps(CM36558_obj->client, &CM36558_obj->ps);
  521. if (res)
  522. return snprintf(buf, PAGE_SIZE, "ERROR: %d\n", (unsigned int)res);
  523. else
  524. return snprintf(buf, PAGE_SIZE, "0x%04X\n", CM36558_obj->ps);
  525. }
  526. /*----------------------------------------------------------------------------*/
  527. static ssize_t CM36558_show_reg(struct device_driver *ddri, char *buf)
  528. {
  529. u8 _bIndex = 0;
  530. u8 databuf[2] = { 0 };
  531. ssize_t _tLength = 0;
  532. if (!CM36558_obj) {
  533. APS_ERR("CM36558_obj is null!!\n");
  534. return 0;
  535. }
  536. for (_bIndex = 0; _bIndex < 0x0E; _bIndex++) {
  537. databuf[0] = _bIndex;
  538. CM36558_i2c_master_operate(CM36558_obj->client, databuf, 2, I2C_FLAG_READ);
  539. _tLength +=
  540. snprintf((buf + _tLength), (PAGE_SIZE - _tLength), "Reg[0x%02X]: 0x%04X\n", _bIndex,
  541. databuf[0] | databuf[1] << 8);
  542. }
  543. return _tLength;
  544. }
  545. /*----------------------------------------------------------------------------*/
  546. static ssize_t CM36558_show_send(struct device_driver *ddri, char *buf)
  547. {
  548. return 0;
  549. }
  550. /*----------------------------------------------------------------------------*/
  551. static ssize_t CM36558_store_send(struct device_driver *ddri, const char *buf, size_t count)
  552. {
  553. int addr = 0, cmd = 0;
  554. u8 dat = 0;
  555. if (!CM36558_obj) {
  556. APS_ERR("CM36558_obj is null!!\n");
  557. return 0;
  558. } else if (2 != sscanf(buf, "%x %x", &addr, &cmd)) {
  559. APS_ERR("invalid format: '%s'\n", buf);
  560. return 0;
  561. }
  562. dat = (u8)cmd;
  563. return count;
  564. }
  565. /*----------------------------------------------------------------------------*/
  566. static ssize_t CM36558_show_recv(struct device_driver *ddri, char *buf)
  567. {
  568. return 0;
  569. }
  570. /*----------------------------------------------------------------------------*/
  571. static ssize_t CM36558_store_recv(struct device_driver *ddri, const char *buf, size_t count)
  572. {
  573. int addr = 0, err = 0;
  574. if (!CM36558_obj) {
  575. APS_ERR("CM36558_obj is null!!\n");
  576. return 0;
  577. }
  578. err = kstrtoint(buf, 16, &addr);
  579. if (err != 0) {
  580. APS_ERR("invalid format: '%s'\n", buf);
  581. return 0;
  582. }
  583. return count;
  584. }
  585. /*----------------------------------------------------------------------------*/
  586. static ssize_t CM36558_show_status(struct device_driver *ddri, char *buf)
  587. {
  588. ssize_t len = 0;
  589. if (!CM36558_obj) {
  590. APS_ERR("CM36558_obj is null!!\n");
  591. return 0;
  592. }
  593. if (CM36558_obj->hw)
  594. len += snprintf(buf + len, PAGE_SIZE - len, "CUST: %d, (%d %d)\n",
  595. CM36558_obj->hw->i2c_num, CM36558_obj->hw->power_id, CM36558_obj->hw->power_vol);
  596. else
  597. len += snprintf(buf + len, PAGE_SIZE - len, "CUST: NULL\n");
  598. len += snprintf(buf + len, PAGE_SIZE - len, "REGS: %02X %02X %02X %02lX %02lX\n",
  599. atomic_read(&CM36558_obj->als_cmd_val), atomic_read(&CM36558_obj->ps_cmd_val),
  600. atomic_read(&CM36558_obj->ps_thd_val), CM36558_obj->enable, CM36558_obj->pending_intr);
  601. len +=
  602. snprintf(buf + len, PAGE_SIZE - len, "MISC: %d %d\n", atomic_read(&CM36558_obj->als_suspend),
  603. atomic_read(&CM36558_obj->ps_suspend));
  604. return len;
  605. }
  606. /*----------------------------------------------------------------------------*/
  607. #define IS_SPACE(CH) (((CH) == ' ') || ((CH) == '\n'))
  608. /*----------------------------------------------------------------------------*/
  609. static int read_int_from_buf(struct CM36558_priv *obj, const char *buf, size_t count, u32 data[], int len)
  610. {
  611. int idx = 0, err = 0;
  612. char *cur = (char *)buf, *end = (char *)(buf + count);
  613. while (idx < len) {
  614. while ((cur < end) && IS_SPACE(*cur))
  615. cur++;
  616. err = kstrtoint(cur, 10, &data[idx]);
  617. if (err != 0)
  618. break;
  619. idx++;
  620. while ((cur < end) && !IS_SPACE(*cur))
  621. cur++;
  622. }
  623. return idx;
  624. }
  625. /*----------------------------------------------------------------------------*/
  626. static ssize_t CM36558_show_alslv(struct device_driver *ddri, char *buf)
  627. {
  628. ssize_t len = 0;
  629. int idx = 0;
  630. if (!CM36558_obj) {
  631. APS_ERR("CM36558_obj is null!!\n");
  632. return 0;
  633. }
  634. for (idx = 0; idx < CM36558_obj->als_level_num; idx++)
  635. len += snprintf(buf + len, PAGE_SIZE - len, "%d ", CM36558_obj->hw->als_level[idx]);
  636. len += snprintf(buf + len, PAGE_SIZE - len, "\n");
  637. return len;
  638. }
  639. /*----------------------------------------------------------------------------*/
  640. static ssize_t CM36558_store_alslv(struct device_driver *ddri, const char *buf, size_t count)
  641. {
  642. if (!CM36558_obj) {
  643. APS_ERR("CM36558_obj is null!!\n");
  644. return 0;
  645. } else if (!strcmp(buf, "def")) {
  646. memcpy(CM36558_obj->als_level, CM36558_obj->hw->als_level, sizeof(CM36558_obj->als_level));
  647. } else if (CM36558_obj->als_level_num != read_int_from_buf(CM36558_obj, buf, count,
  648. CM36558_obj->hw->als_level,
  649. CM36558_obj->als_level_num)) {
  650. APS_ERR("invalid format: '%s'\n", buf);
  651. }
  652. return count;
  653. }
  654. /*----------------------------------------------------------------------------*/
  655. static ssize_t CM36558_show_alsval(struct device_driver *ddri, char *buf)
  656. {
  657. ssize_t len = 0;
  658. int idx = 0;
  659. if (!CM36558_obj) {
  660. APS_ERR("CM36558_obj is null!!\n");
  661. return 0;
  662. }
  663. for (idx = 0; idx < CM36558_obj->als_value_num; idx++)
  664. len += snprintf(buf + len, PAGE_SIZE - len, "%d ", CM36558_obj->hw->als_value[idx]);
  665. len += snprintf(buf + len, PAGE_SIZE - len, "\n");
  666. return len;
  667. }
  668. /*----------------------------------------------------------------------------*/
  669. static ssize_t CM36558_store_alsval(struct device_driver *ddri, const char *buf, size_t count)
  670. {
  671. if (!CM36558_obj) {
  672. APS_ERR("CM36558_obj is null!!\n");
  673. return 0;
  674. } else if (!strcmp(buf, "def")) {
  675. memcpy(CM36558_obj->als_value, CM36558_obj->hw->als_value, sizeof(CM36558_obj->als_value));
  676. } else if (CM36558_obj->als_value_num != read_int_from_buf(CM36558_obj, buf, count,
  677. CM36558_obj->hw->als_value,
  678. CM36558_obj->als_value_num)) {
  679. APS_ERR("invalid format: '%s'\n", buf);
  680. }
  681. return count;
  682. }
  683. /*---------------------------------------------------------------------------------------*/
  684. static DRIVER_ATTR(als, S_IWUSR | S_IRUGO, CM36558_show_als, NULL);
  685. static DRIVER_ATTR(ps, S_IWUSR | S_IRUGO, CM36558_show_ps, NULL);
  686. static DRIVER_ATTR(config, S_IWUSR | S_IRUGO, CM36558_show_config, CM36558_store_config);
  687. static DRIVER_ATTR(alslv, S_IWUSR | S_IRUGO, CM36558_show_alslv, CM36558_store_alslv);
  688. static DRIVER_ATTR(alsval, S_IWUSR | S_IRUGO, CM36558_show_alsval, CM36558_store_alsval);
  689. static DRIVER_ATTR(trace, S_IWUSR | S_IRUGO, CM36558_show_trace, CM36558_store_trace);
  690. static DRIVER_ATTR(status, S_IWUSR | S_IRUGO, CM36558_show_status, NULL);
  691. static DRIVER_ATTR(send, S_IWUSR | S_IRUGO, CM36558_show_send, CM36558_store_send);
  692. static DRIVER_ATTR(recv, S_IWUSR | S_IRUGO, CM36558_show_recv, CM36558_store_recv);
  693. static DRIVER_ATTR(reg, S_IWUSR | S_IRUGO, CM36558_show_reg, NULL);
  694. /*----------------------------------------------------------------------------*/
  695. static struct driver_attribute *CM36558_attr_list[] = {
  696. &driver_attr_als,
  697. &driver_attr_ps,
  698. &driver_attr_trace, /*trace log */
  699. &driver_attr_config,
  700. &driver_attr_alslv,
  701. &driver_attr_alsval,
  702. &driver_attr_status,
  703. &driver_attr_send,
  704. &driver_attr_recv,
  705. &driver_attr_reg,
  706. };
  707. /*----------------------------------------------------------------------------*/
  708. static int CM36558_create_attr(struct device_driver *driver)
  709. {
  710. int idx = 0, err = 0;
  711. int num = (int)(sizeof(CM36558_attr_list) / sizeof(CM36558_attr_list[0]));
  712. if (driver == NULL)
  713. return -EINVAL;
  714. for (idx = 0; idx < num; idx++) {
  715. err = driver_create_file(driver, CM36558_attr_list[idx]);
  716. if (err) {
  717. APS_ERR("driver_create_file (%s) = %d\n", CM36558_attr_list[idx]->attr.name, err);
  718. break;
  719. }
  720. }
  721. return err;
  722. }
  723. /*----------------------------------------------------------------------------*/
  724. static int CM36558_delete_attr(struct device_driver *driver)
  725. {
  726. int idx = 0, err = 0;
  727. int num = (int)(sizeof(CM36558_attr_list) / sizeof(CM36558_attr_list[0]));
  728. if (!driver)
  729. return -EINVAL;
  730. for (idx = 0; idx < num; idx++)
  731. driver_remove_file(driver, CM36558_attr_list[idx]);
  732. return err;
  733. }
  734. static int intr_flag;
  735. /*----------------------------------------------------------------------------*/
  736. static int CM36558_check_intr(struct i2c_client *client)
  737. {
  738. int res = 0;
  739. u8 databuf[2];
  740. databuf[0] = CM36558_REG_PS_DATA;
  741. res = CM36558_i2c_master_operate(client, databuf, 2, I2C_FLAG_READ);
  742. if (res < 0) {
  743. APS_ERR("i2c_master_send function err res = %d\n", res);
  744. goto EXIT_ERR;
  745. }
  746. APS_LOG("CM36558_REG_PS_DATA value value_low = %x, value_reserve = %x\n", databuf[0], databuf[1]);
  747. databuf[0] = CM36558_REG_INT_FLAG;
  748. res = CM36558_i2c_master_operate(client, databuf, 2, I2C_FLAG_READ);
  749. if (res < 0) {
  750. APS_ERR("i2c_master_send function err res = %d\n", res);
  751. goto EXIT_ERR;
  752. }
  753. APS_LOG("CM36558_REG_INT_FLAG value value_low = %x, value_high = %x\n", databuf[0], databuf[1]);
  754. if (databuf[1] & 0x02) {
  755. intr_flag = 0;
  756. } else if (databuf[1] & 0x01) {
  757. intr_flag = 1;
  758. } else {
  759. res = -1;
  760. APS_ERR("CM36558_check_intr fail databuf[1]&0x01: %d\n", res);
  761. goto EXIT_ERR;
  762. }
  763. return 0;
  764. EXIT_ERR:
  765. APS_ERR("CM36558_check_intr dev: %d\n", res);
  766. return res;
  767. }
  768. /*----------------------------------interrupt functions--------------------------------*/
  769. static void CM36558_eint_work(struct work_struct *work)
  770. {
  771. struct CM36558_priv *obj = (struct CM36558_priv *)container_of(work, struct CM36558_priv, eint_work);
  772. int res = 0;
  773. APS_LOG("CM36558 int top half time = %lld\n", int_top_time);
  774. res = CM36558_check_intr(obj->client);
  775. if (res != 0) {
  776. goto EXIT_INTR_ERR;
  777. } else {
  778. APS_LOG("CM36558 interrupt value = %d\n", intr_flag);
  779. res = ps_report_interrupt_data(intr_flag);
  780. }
  781. #if defined(CONFIG_OF)
  782. enable_irq(obj->irq);
  783. #elif defined(CUST_EINT_ALS_TYPE)
  784. mt_eint_unmask(CUST_EINT_ALS_NUM);
  785. #else
  786. mt65xx_eint_unmask(CUST_EINT_ALS_NUM);
  787. #endif
  788. return;
  789. EXIT_INTR_ERR:
  790. #if defined(CONFIG_OF)
  791. enable_irq(obj->irq);
  792. #elif defined(CUST_EINT_ALS_TYPE)
  793. mt_eint_unmask(CUST_EINT_ALS_NUM);
  794. #else
  795. mt65xx_eint_unmask(CUST_EINT_ALS_NUM);
  796. #endif
  797. APS_ERR("CM36558_eint_work err: %d\n", res);
  798. }
  799. /*----------------------------------------------------------------------------*/
  800. static void CM36558_eint_func(void)
  801. {
  802. struct CM36558_priv *obj = CM36558_obj;
  803. if (!obj)
  804. return;
  805. int_top_time = sched_clock();
  806. schedule_work(&obj->eint_work);
  807. }
  808. #if defined(CONFIG_OF)
  809. static irqreturn_t CM36558_eint_handler(int irq, void *desc)
  810. {
  811. CM36558_eint_func();
  812. disable_irq_nosync(CM36558_obj->irq);
  813. return IRQ_HANDLED;
  814. }
  815. #endif
  816. /*----------------------------------------------------------------------------*/
  817. int CM36558_setup_eint(struct i2c_client *client)
  818. {
  819. int ret;
  820. struct pinctrl *pinctrl;
  821. struct pinctrl_state *pins_default;
  822. struct pinctrl_state *pins_cfg;
  823. u32 ints[2] = {0, 0};
  824. alspsPltFmDev = get_alsps_platformdev();
  825. /* gpio setting */
  826. pinctrl = devm_pinctrl_get(&alspsPltFmDev->dev);
  827. if (IS_ERR(pinctrl)) {
  828. ret = PTR_ERR(pinctrl);
  829. APS_ERR("Cannot find alsps pinctrl!\n");
  830. return ret;
  831. }
  832. pins_default = pinctrl_lookup_state(pinctrl, "pin_default");
  833. if (IS_ERR(pins_default)) {
  834. ret = PTR_ERR(pins_default);
  835. APS_ERR("Cannot find alsps pinctrl default!\n");
  836. }
  837. pins_cfg = pinctrl_lookup_state(pinctrl, "pin_cfg");
  838. if (IS_ERR(pins_cfg)) {
  839. ret = PTR_ERR(pins_cfg);
  840. APS_ERR("Cannot find alsps pinctrl pin_cfg!\n");
  841. return ret;
  842. }
  843. pinctrl_select_state(pinctrl, pins_cfg);
  844. /* eint request */
  845. if (CM36558_obj->irq_node) {
  846. of_property_read_u32_array(CM36558_obj->irq_node, "debounce", ints, ARRAY_SIZE(ints));
  847. gpio_request(ints[0], "p-sensor");
  848. gpio_set_debounce(ints[0], ints[1]);
  849. APS_LOG("ints[0] = %d, ints[1] = %d!!\n", ints[0], ints[1]);
  850. CM36558_obj->irq = irq_of_parse_and_map(CM36558_obj->irq_node, 0);
  851. APS_LOG("CM36558_obj->irq = %d\n", CM36558_obj->irq);
  852. if (!CM36558_obj->irq) {
  853. APS_ERR("irq_of_parse_and_map fail!!\n");
  854. return -EINVAL;
  855. }
  856. if (request_irq(CM36558_obj->irq, CM36558_eint_handler, IRQF_TRIGGER_NONE, "ALS-eint", NULL)) {
  857. APS_ERR("IRQ LINE NOT AVAILABLE!!\n");
  858. return -EINVAL;
  859. }
  860. enable_irq(CM36558_obj->irq);
  861. } else {
  862. APS_ERR("null irq node!!\n");
  863. return -EINVAL;
  864. }
  865. return 0;
  866. }
  867. /*-------------------------------MISC device related------------------------------------------*/
  868. /************************************************************/
  869. static int CM36558_open(struct inode *inode, struct file *file)
  870. {
  871. file->private_data = CM36558_i2c_client;
  872. if (!file->private_data) {
  873. APS_ERR("null pointer!!\n");
  874. return -EINVAL;
  875. }
  876. return nonseekable_open(inode, file);
  877. }
  878. /************************************************************/
  879. static int CM36558_release(struct inode *inode, struct file *file)
  880. {
  881. file->private_data = NULL;
  882. return 0;
  883. }
  884. /************************************************************/
  885. static int set_psensor_threshold(struct i2c_client *client)
  886. {
  887. struct CM36558_priv *obj = i2c_get_clientdata(client);
  888. int res = 0;
  889. u8 databuf[3];
  890. APS_ERR("set_psensor_threshold function high: 0x%x, low:0x%x\n", atomic_read(&obj->ps_thd_val_high),
  891. atomic_read(&obj->ps_thd_val_low));
  892. databuf[0] = CM36558_REG_PS_THDL;
  893. databuf[1] = (u8) (atomic_read(&obj->ps_thd_val_low) & 0xFF);
  894. databuf[2] = (u8) (atomic_read(&obj->ps_thd_val_low) >> 8);
  895. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  896. if (res <= 0) {
  897. APS_ERR("i2c_master_send function err\n");
  898. return -1;
  899. }
  900. databuf[0] = CM36558_REG_PS_THDH;
  901. databuf[1] = (u8) (atomic_read(&obj->ps_thd_val_high) & 0xFF);
  902. databuf[2] = (u8) (atomic_read(&obj->ps_thd_val_high) >> 8);
  903. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  904. if (res <= 0) {
  905. APS_ERR("i2c_master_send function err\n");
  906. return -1;
  907. }
  908. return 0;
  909. }
  910. static long CM36558_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  911. {
  912. struct i2c_client *client = (struct i2c_client *)file->private_data;
  913. struct CM36558_priv *obj = i2c_get_clientdata(client);
  914. long err = 0;
  915. void __user *ptr = (void __user *)arg;
  916. int dat;
  917. uint32_t enable;
  918. int ps_result;
  919. int ps_cali;
  920. int threshold[2];
  921. switch (cmd) {
  922. case ALSPS_SET_PS_MODE:
  923. if (copy_from_user(&enable, ptr, sizeof(enable))) {
  924. err = -EFAULT;
  925. goto err_out;
  926. }
  927. if (enable) {
  928. err = CM36558_enable_ps(obj->client, 1);
  929. if (err) {
  930. APS_ERR("enable ps fail: %ld\n", err);
  931. goto err_out;
  932. }
  933. set_bit(CMC_BIT_PS, &obj->enable);
  934. } else {
  935. err = CM36558_enable_ps(obj->client, 0);
  936. if (err) {
  937. APS_ERR("disable ps fail: %ld\n", err);
  938. goto err_out;
  939. }
  940. clear_bit(CMC_BIT_PS, &obj->enable);
  941. }
  942. break;
  943. case ALSPS_GET_PS_MODE:
  944. enable = test_bit(CMC_BIT_PS, &obj->enable) ? (1) : (0);
  945. if (copy_to_user(ptr, &enable, sizeof(enable))) {
  946. err = -EFAULT;
  947. goto err_out;
  948. }
  949. break;
  950. case ALSPS_GET_PS_DATA:
  951. err = CM36558_read_ps(obj->client, &obj->ps);
  952. if (err)
  953. goto err_out;
  954. dat = CM36558_get_ps_value(obj, obj->ps);
  955. if (copy_to_user(ptr, &dat, sizeof(dat))) {
  956. err = -EFAULT;
  957. goto err_out;
  958. }
  959. break;
  960. case ALSPS_GET_PS_RAW_DATA:
  961. err = CM36558_read_ps(obj->client, &obj->ps);
  962. if (err)
  963. goto err_out;
  964. dat = obj->ps;
  965. if (copy_to_user(ptr, &dat, sizeof(dat))) {
  966. err = -EFAULT;
  967. goto err_out;
  968. }
  969. break;
  970. case ALSPS_SET_ALS_MODE:
  971. if (copy_from_user(&enable, ptr, sizeof(enable))) {
  972. err = -EFAULT;
  973. goto err_out;
  974. }
  975. if (enable) {
  976. err = CM36558_enable_als(obj->client, 1);
  977. if (err) {
  978. APS_ERR("enable als fail: %ld\n", err);
  979. goto err_out;
  980. }
  981. set_bit(CMC_BIT_ALS, &obj->enable);
  982. } else {
  983. err = CM36558_enable_als(obj->client, 0);
  984. if (err) {
  985. APS_ERR("disable als fail: %ld\n", err);
  986. goto err_out;
  987. }
  988. clear_bit(CMC_BIT_ALS, &obj->enable);
  989. }
  990. break;
  991. case ALSPS_GET_ALS_MODE:
  992. enable = test_bit(CMC_BIT_ALS, &obj->enable) ? (1) : (0);
  993. if (copy_to_user(ptr, &enable, sizeof(enable))) {
  994. err = -EFAULT;
  995. goto err_out;
  996. }
  997. break;
  998. case ALSPS_GET_ALS_DATA:
  999. err = CM36558_read_als(obj->client, &obj->als);
  1000. if (err)
  1001. goto err_out;
  1002. dat = CM36558_get_als_value(obj, obj->als);
  1003. if (copy_to_user(ptr, &dat, sizeof(dat))) {
  1004. err = -EFAULT;
  1005. goto err_out;
  1006. }
  1007. break;
  1008. case ALSPS_GET_ALS_RAW_DATA:
  1009. err = CM36558_read_als(obj->client, &obj->als);
  1010. if (err)
  1011. goto err_out;
  1012. dat = obj->als;
  1013. if (copy_to_user(ptr, &dat, sizeof(dat))) {
  1014. err = -EFAULT;
  1015. goto err_out;
  1016. }
  1017. break;
  1018. case ALSPS_GET_PS_TEST_RESULT:
  1019. err = CM36558_read_ps(obj->client, &obj->ps);
  1020. if (err)
  1021. goto err_out;
  1022. if (obj->ps > atomic_read(&obj->ps_thd_val_high))
  1023. ps_result = 0;
  1024. else
  1025. ps_result = 1;
  1026. if (copy_to_user(ptr, &ps_result, sizeof(ps_result))) {
  1027. err = -EFAULT;
  1028. goto err_out;
  1029. }
  1030. break;
  1031. case ALSPS_IOCTL_CLR_CALI:
  1032. if (copy_from_user(&dat, ptr, sizeof(dat))) {
  1033. err = -EFAULT;
  1034. goto err_out;
  1035. }
  1036. if (dat == 0)
  1037. obj->ps_cali = 0;
  1038. break;
  1039. case ALSPS_IOCTL_GET_CALI:
  1040. ps_cali = obj->ps_cali;
  1041. if (copy_to_user(ptr, &ps_cali, sizeof(ps_cali))) {
  1042. err = -EFAULT;
  1043. goto err_out;
  1044. }
  1045. break;
  1046. case ALSPS_IOCTL_SET_CALI:
  1047. if (copy_from_user(&ps_cali, ptr, sizeof(ps_cali))) {
  1048. err = -EFAULT;
  1049. goto err_out;
  1050. }
  1051. obj->ps_cali = ps_cali;
  1052. break;
  1053. case ALSPS_SET_PS_THRESHOLD:
  1054. if (copy_from_user(threshold, ptr, sizeof(threshold))) {
  1055. err = -EFAULT;
  1056. goto err_out;
  1057. }
  1058. APS_ERR("%s set threshold high: 0x%x, low: 0x%x\n", __func__, threshold[0], threshold[1]);
  1059. atomic_set(&obj->ps_thd_val_high, (threshold[0] + obj->ps_cali));
  1060. atomic_set(&obj->ps_thd_val_low, (threshold[1] + obj->ps_cali));
  1061. set_psensor_threshold(obj->client);
  1062. break;
  1063. case ALSPS_GET_PS_THRESHOLD_HIGH:
  1064. threshold[0] = atomic_read(&obj->ps_thd_val_high) - obj->ps_cali;
  1065. APS_ERR("%s get threshold high: 0x%x\n", __func__, threshold[0]);
  1066. if (copy_to_user(ptr, &threshold[0], sizeof(threshold[0]))) {
  1067. err = -EFAULT;
  1068. goto err_out;
  1069. }
  1070. break;
  1071. case ALSPS_GET_PS_THRESHOLD_LOW:
  1072. threshold[0] = atomic_read(&obj->ps_thd_val_low) - obj->ps_cali;
  1073. APS_ERR("%s get threshold low: 0x%x\n", __func__, threshold[0]);
  1074. if (copy_to_user(ptr, &threshold[0], sizeof(threshold[0]))) {
  1075. err = -EFAULT;
  1076. goto err_out;
  1077. }
  1078. break;
  1079. /*------------------------------------------------------------------------------------------*/
  1080. default:
  1081. APS_ERR("%s not supported = 0x%04x", __func__, cmd);
  1082. err = -ENOIOCTLCMD;
  1083. break;
  1084. }
  1085. err_out:
  1086. return err;
  1087. }
  1088. /*------------------------------misc device related operation functions------------------------------------*/
  1089. static const struct file_operations CM36558_fops = {
  1090. .owner = THIS_MODULE,
  1091. .open = CM36558_open,
  1092. .release = CM36558_release,
  1093. .unlocked_ioctl = CM36558_unlocked_ioctl,
  1094. };
  1095. static struct miscdevice CM36558_device = {
  1096. .minor = MISC_DYNAMIC_MINOR,
  1097. .name = "als_ps",
  1098. .fops = &CM36558_fops,
  1099. };
  1100. /*--------------------------------------------------------------------------------------*/
  1101. static int CM36558_init_client(struct i2c_client *client)
  1102. {
  1103. struct CM36558_priv *obj = i2c_get_clientdata(client);
  1104. u8 databuf[3];
  1105. int res = 0;
  1106. APS_FUN();
  1107. databuf[0] = CM36558_REG_ALS_UV_CONF;
  1108. if (1 == obj->hw->polling_mode_als)
  1109. databuf[1] = 0x01;
  1110. else
  1111. databuf[1] = 0x03;
  1112. databuf[2] = 0x00;
  1113. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  1114. if (res <= 0) {
  1115. APS_ERR("i2c_master_send function err\n");
  1116. goto EXIT_ERR;
  1117. }
  1118. APS_LOG("CM36558 ps CM36558_REG_ALS_UV_CONF command!\n");
  1119. databuf[0] = CM36558_REG_PS_CONF1_2;
  1120. databuf[1] = 0x01;
  1121. if (1 == obj->hw->polling_mode_ps)
  1122. databuf[2] = 0x00;
  1123. else
  1124. databuf[2] = 0x03;
  1125. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  1126. if (res <= 0) {
  1127. APS_ERR("i2c_master_send function err\n");
  1128. goto EXIT_ERR;
  1129. }
  1130. APS_LOG("CM36558 ps CM36558_REG_PS_CONF1_2 command!\n");
  1131. databuf[0] = CM36558_REG_PS_CONF3_MS;
  1132. databuf[1] = 0b00110000;
  1133. databuf[2] = 0b00000010;
  1134. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  1135. if(res <= 0)
  1136. {
  1137. APS_ERR("i2c_master_send function err\n");
  1138. goto EXIT_ERR;
  1139. }
  1140. APS_LOG("CM36558 ps CM36558_REG_PS_CONF3_MS command!\n");
  1141. databuf[0] = CM36558_REG_PS_CANC;
  1142. databuf[1] = 0x00;
  1143. databuf[2] = 0x00;
  1144. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  1145. if (res <= 0) {
  1146. APS_ERR("i2c_master_send function err\n");
  1147. goto EXIT_ERR;
  1148. }
  1149. APS_LOG("CM36558 ps CM36558_REG_PS_CANC command!\n");
  1150. if (0 == obj->hw->polling_mode_als) {
  1151. databuf[0] = CM36558_REG_ALS_THDH;
  1152. databuf[1] = (u8) (atomic_read(&obj->als_thd_val_high) & 0xFF);
  1153. databuf[2] = (u8) (atomic_read(&obj->als_thd_val_high) >> 8);
  1154. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  1155. if (res <= 0) {
  1156. APS_ERR("i2c_master_send function err\n");
  1157. goto EXIT_ERR;
  1158. }
  1159. databuf[0] = CM36558_REG_ALS_THDL;
  1160. databuf[1] = (u8) (atomic_read(&obj->als_thd_val_low) & 0xFF);
  1161. databuf[2] = (u8) (atomic_read(&obj->als_thd_val_low) >> 8);
  1162. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  1163. if (res <= 0) {
  1164. APS_ERR("i2c_master_send function err\n");
  1165. goto EXIT_ERR;
  1166. }
  1167. }
  1168. if (0 == obj->hw->polling_mode_ps) {
  1169. databuf[0] = CM36558_REG_PS_THDL;
  1170. databuf[1] = (u8) (atomic_read(&obj->ps_thd_val_low) & 0xFF);
  1171. databuf[2] = (u8) (atomic_read(&obj->ps_thd_val_low) >> 8);
  1172. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  1173. if (res <= 0) {
  1174. APS_ERR("i2c_master_send function err\n");
  1175. goto EXIT_ERR;
  1176. }
  1177. databuf[0] = CM36558_REG_PS_THDH;
  1178. databuf[1] = (u8) (atomic_read(&obj->ps_thd_val_high) & 0xFF);
  1179. databuf[2] = (u8) (atomic_read(&obj->ps_thd_val_high) >> 8);
  1180. res = CM36558_i2c_master_operate(client, databuf, 0x3, I2C_FLAG_WRITE);
  1181. if (res <= 0) {
  1182. APS_ERR("i2c_master_send function err\n");
  1183. goto EXIT_ERR;
  1184. }
  1185. }
  1186. res = CM36558_setup_eint(client);
  1187. if (res != 0) {
  1188. APS_ERR("setup eint: %d\n", res);
  1189. return res;
  1190. }
  1191. return CM36558_SUCCESS;
  1192. EXIT_ERR:
  1193. APS_ERR("init dev: %d\n", res);
  1194. return res;
  1195. }
  1196. /*--------------------------------------------------------------------------------*/
  1197. static int als_open_report_data(int open)
  1198. {
  1199. return 0;
  1200. }
  1201. static int als_enable_nodata(int en)
  1202. {
  1203. int res = 0;
  1204. APS_LOG("CM36558_obj als enable value = %d\n", en);
  1205. mutex_lock(&CM36558_mutex);
  1206. if (en)
  1207. set_bit(CMC_BIT_ALS, &CM36558_obj->enable);
  1208. else
  1209. clear_bit(CMC_BIT_ALS, &CM36558_obj->enable);
  1210. mutex_unlock(&CM36558_mutex);
  1211. if (!CM36558_obj) {
  1212. APS_ERR("CM36558_obj is null!!\n");
  1213. return -1;
  1214. }
  1215. res = CM36558_enable_als(CM36558_obj->client, en);
  1216. if (res) {
  1217. APS_ERR("als_enable_nodata is failed!!\n");
  1218. return -1;
  1219. }
  1220. return 0;
  1221. }
  1222. static int als_set_delay(u64 ns)
  1223. {
  1224. return 0;
  1225. }
  1226. static int als_get_data(int *value, int *status)
  1227. {
  1228. int err = 0;
  1229. struct CM36558_priv *obj = NULL;
  1230. if (!CM36558_obj) {
  1231. APS_ERR("CM36558_obj is null!!\n");
  1232. return -1;
  1233. }
  1234. obj = CM36558_obj;
  1235. err = CM36558_read_als(obj->client, &obj->als);
  1236. if (err) {
  1237. err = -1;
  1238. } else {
  1239. *value = CM36558_get_als_value(obj, obj->als);
  1240. *status = SENSOR_STATUS_ACCURACY_MEDIUM;
  1241. }
  1242. return err;
  1243. }
  1244. static int ps_open_report_data(int open)
  1245. {
  1246. return 0;
  1247. }
  1248. static int ps_enable_nodata(int en)
  1249. {
  1250. int res = 0;
  1251. APS_LOG("CM36558_obj als enable value = %d\n", en);
  1252. mutex_lock(&CM36558_mutex);
  1253. if (en)
  1254. set_bit(CMC_BIT_PS, &CM36558_obj->enable);
  1255. else
  1256. clear_bit(CMC_BIT_PS, &CM36558_obj->enable);
  1257. mutex_unlock(&CM36558_mutex);
  1258. if (!CM36558_obj) {
  1259. APS_ERR("CM36558_obj is null!!\n");
  1260. return -1;
  1261. }
  1262. res = CM36558_enable_ps(CM36558_obj->client, en);
  1263. if (res) {
  1264. APS_ERR("als_enable_nodata is failed!!\n");
  1265. return -1;
  1266. }
  1267. return 0;
  1268. }
  1269. static int ps_set_delay(u64 ns)
  1270. {
  1271. return 0;
  1272. }
  1273. static int ps_get_data(int *value, int *status)
  1274. {
  1275. int err = 0;
  1276. if (!CM36558_obj) {
  1277. APS_ERR("CM36558_obj is null!!\n");
  1278. return -1;
  1279. }
  1280. err = CM36558_read_ps(CM36558_obj->client, &CM36558_obj->ps);
  1281. if (err) {
  1282. err = -1;
  1283. } else {
  1284. *value = CM36558_get_ps_value(CM36558_obj, CM36558_obj->ps);
  1285. *status = SENSOR_STATUS_ACCURACY_MEDIUM;
  1286. }
  1287. return 0;
  1288. }
  1289. /*-----------------------------------i2c operations----------------------------------*/
  1290. static int CM36558_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
  1291. {
  1292. struct CM36558_priv *obj;
  1293. int err = 0;
  1294. struct als_control_path als_ctl = { 0 };
  1295. struct als_data_path als_data = { 0 };
  1296. struct ps_control_path ps_ctl = { 0 };
  1297. struct ps_data_path ps_data = { 0 };
  1298. APS_FUN();
  1299. obj = kzalloc(sizeof(*obj), GFP_KERNEL);
  1300. if (!obj) {
  1301. err = -ENOMEM;
  1302. goto exit;
  1303. }
  1304. memset(obj, 0, sizeof(*obj));
  1305. CM36558_obj = obj;
  1306. obj->hw = hw;
  1307. INIT_WORK(&obj->eint_work, CM36558_eint_work);
  1308. obj->client = client;
  1309. i2c_set_clientdata(client, obj);
  1310. /*-----------------------------value need to be confirmed-----------------------------------------*/
  1311. atomic_set(&obj->als_debounce, 200);
  1312. atomic_set(&obj->als_deb_on, 0);
  1313. atomic_set(&obj->als_deb_end, 0);
  1314. atomic_set(&obj->ps_debounce, 200);
  1315. atomic_set(&obj->ps_deb_on, 0);
  1316. atomic_set(&obj->ps_deb_end, 0);
  1317. atomic_set(&obj->ps_mask, 0);
  1318. atomic_set(&obj->als_suspend, 0);
  1319. atomic_set(&obj->als_cmd_val, 0xDF);
  1320. atomic_set(&obj->ps_cmd_val, 0xC1);
  1321. atomic_set(&obj->ps_thd_val_high, obj->hw->ps_threshold_high);
  1322. atomic_set(&obj->ps_thd_val_low, obj->hw->ps_threshold_low);
  1323. atomic_set(&obj->als_thd_val_high, obj->hw->als_threshold_high);
  1324. atomic_set(&obj->als_thd_val_low, obj->hw->als_threshold_low);
  1325. atomic_set(&obj->init_done, 0);
  1326. obj->irq_node = of_find_compatible_node(NULL, NULL, "mediatek,als_ps");
  1327. obj->enable = 0;
  1328. obj->pending_intr = 0;
  1329. obj->ps_cali = 0;
  1330. obj->als_level_num = sizeof(obj->hw->als_level) / sizeof(obj->hw->als_level[0]);
  1331. obj->als_value_num = sizeof(obj->hw->als_value) / sizeof(obj->hw->als_value[0]);
  1332. /*-----------------------------value need to be confirmed-----------------------------------------*/
  1333. BUG_ON(sizeof(obj->als_level) != sizeof(obj->hw->als_level));
  1334. memcpy(obj->als_level, obj->hw->als_level, sizeof(obj->als_level));
  1335. BUG_ON(sizeof(obj->als_value) != sizeof(obj->hw->als_value));
  1336. memcpy(obj->als_value, obj->hw->als_value, sizeof(obj->als_value));
  1337. atomic_set(&obj->i2c_retry, 3);
  1338. clear_bit(CMC_BIT_ALS, &obj->enable);
  1339. clear_bit(CMC_BIT_PS, &obj->enable);
  1340. CM36558_i2c_client = client;
  1341. err = CM36558_init_client(client);
  1342. if (err)
  1343. goto exit_init_failed;
  1344. APS_LOG("CM36558_init_client() OK!\n");
  1345. err = misc_register(&CM36558_device);
  1346. if (err) {
  1347. APS_ERR("CM36558_device register failed\n");
  1348. goto exit_misc_device_register_failed;
  1349. }
  1350. als_ctl.is_use_common_factory = false;
  1351. ps_ctl.is_use_common_factory = false;
  1352. APS_LOG("CM36558_device misc_register OK!\n");
  1353. /*------------------------CM36558 attribute file for debug--------------------------------------*/
  1354. err = CM36558_create_attr(&(CM36558_init_info.platform_diver_addr->driver));
  1355. if (err) {
  1356. APS_ERR("create attribute err = %d\n", err);
  1357. goto exit_create_attr_failed;
  1358. }
  1359. /*------------------------CM36558 attribute file for debug--------------------------------------*/
  1360. als_ctl.open_report_data = als_open_report_data;
  1361. als_ctl.enable_nodata = als_enable_nodata;
  1362. als_ctl.set_delay = als_set_delay;
  1363. als_ctl.is_report_input_direct = false;
  1364. als_ctl.is_support_batch = false;
  1365. err = als_register_control_path(&als_ctl);
  1366. if (err) {
  1367. APS_ERR("register fail = %d\n", err);
  1368. goto exit_sensor_obj_attach_fail;
  1369. }
  1370. als_data.get_data = als_get_data;
  1371. als_data.vender_div = 100;
  1372. err = als_register_data_path(&als_data);
  1373. if (err) {
  1374. APS_ERR("tregister fail = %d\n", err);
  1375. goto exit_sensor_obj_attach_fail;
  1376. }
  1377. ps_ctl.open_report_data = ps_open_report_data;
  1378. ps_ctl.enable_nodata = ps_enable_nodata;
  1379. ps_ctl.set_delay = ps_set_delay;
  1380. ps_ctl.is_report_input_direct = false;
  1381. ps_ctl.is_support_batch = false;
  1382. err = ps_register_control_path(&ps_ctl);
  1383. if (err) {
  1384. APS_ERR("register fail = %d\n", err);
  1385. goto exit_sensor_obj_attach_fail;
  1386. }
  1387. ps_data.get_data = ps_get_data;
  1388. ps_data.vender_div = 100;
  1389. err = ps_register_data_path(&ps_data);
  1390. if (err) {
  1391. APS_ERR("tregister fail = %d\n", err);
  1392. goto exit_sensor_obj_attach_fail;
  1393. }
  1394. err = batch_register_support_info(ID_LIGHT, als_ctl.is_support_batch, 100, 0);
  1395. if (err) {
  1396. APS_ERR("register light batch support err = %d\n", err);
  1397. goto exit_sensor_obj_attach_fail;
  1398. }
  1399. err = batch_register_support_info(ID_PROXIMITY, ps_ctl.is_support_batch, 100, 0);
  1400. if (err) {
  1401. APS_ERR("register proximity batch support err = %d\n", err);
  1402. goto exit_sensor_obj_attach_fail;
  1403. }
  1404. CM36558_init_flag = 0;
  1405. APS_LOG("%s: OK\n", __func__);
  1406. return 0;
  1407. exit_create_attr_failed:
  1408. exit_sensor_obj_attach_fail:
  1409. exit_misc_device_register_failed:
  1410. misc_deregister(&CM36558_device);
  1411. exit_init_failed:
  1412. kfree(obj);
  1413. exit:
  1414. CM36558_i2c_client = NULL;
  1415. APS_ERR("%s: err = %d\n", __func__, err);
  1416. CM36558_init_flag = -1;
  1417. return err;
  1418. }
  1419. static int CM36558_i2c_remove(struct i2c_client *client)
  1420. {
  1421. int err = 0;
  1422. /*------------------------CM36558 attribute file for debug--------------------------------------*/
  1423. err = CM36558_delete_attr(&(CM36558_init_info.platform_diver_addr->driver));
  1424. if (err)
  1425. APS_ERR("CM36558_delete_attr fail: %d\n", err);
  1426. /*----------------------------------------------------------------------------------------*/
  1427. err = misc_deregister(&CM36558_device);
  1428. if (err)
  1429. APS_ERR("misc_deregister fail: %d\n", err);
  1430. CM36558_i2c_client = NULL;
  1431. i2c_unregister_device(client);
  1432. kfree(i2c_get_clientdata(client));
  1433. return 0;
  1434. }
  1435. static int CM36558_i2c_detect(struct i2c_client *client, struct i2c_board_info *info)
  1436. {
  1437. strcpy(info->type, CM36558_DEV_NAME);
  1438. return 0;
  1439. }
  1440. static int CM36558_i2c_suspend(struct i2c_client *client, pm_message_t msg)
  1441. {
  1442. struct CM36558_priv *obj = i2c_get_clientdata(client);
  1443. int err = 0;
  1444. APS_FUN();
  1445. if (!obj) {
  1446. APS_ERR("null pointer!!\n");
  1447. return 0;
  1448. }
  1449. atomic_set(&obj->als_suspend, 1);
  1450. err = CM36558_enable_als(obj->client, 0);
  1451. if (err)
  1452. APS_ERR("disable als fail: %d\n", err);
  1453. return 0;
  1454. }
  1455. static int CM36558_i2c_resume(struct i2c_client *client)
  1456. {
  1457. struct CM36558_priv *obj = i2c_get_clientdata(client);
  1458. int err = 0;
  1459. APS_FUN();
  1460. if (!obj) {
  1461. APS_ERR("null pointer!!\n");
  1462. return 0;
  1463. }
  1464. atomic_set(&obj->als_suspend, 0);
  1465. if (test_bit(CMC_BIT_ALS, &obj->enable)) {
  1466. err = CM36558_enable_als(obj->client, 1);
  1467. if (err)
  1468. APS_ERR("enable als fail: %d\n", err);
  1469. }
  1470. return 0;
  1471. }
  1472. /*----------------------------------------------------------------------------*/
  1473. /*----------------------------------------------------------------------------*/
  1474. static int CM36558_remove(void)
  1475. {
  1476. CM36558_power(hw, 0);
  1477. i2c_del_driver(&CM36558_i2c_driver);
  1478. return 0;
  1479. }
  1480. /*----------------------------------------------------------------------------*/
  1481. static int CM36558_local_init(void)
  1482. {
  1483. CM36558_power(hw, 1);
  1484. if (i2c_add_driver(&CM36558_i2c_driver)) {
  1485. APS_ERR("add driver error\n");
  1486. return -1;
  1487. }
  1488. if (-1 == CM36558_init_flag)
  1489. return -1;
  1490. return 0;
  1491. }
  1492. /*----------------------------------------------------------------------------*/
  1493. static int __init CM36558_init(void)
  1494. {
  1495. const char *name = "mediatek,cm36558";
  1496. hw = get_alsps_dts_func(name, hw);
  1497. if (!hw)
  1498. APS_ERR("get dts info fail\n");
  1499. alsps_driver_add(&CM36558_init_info);
  1500. return 0;
  1501. }
  1502. /*----------------------------------------------------------------------------*/
  1503. static void __exit CM36558_exit(void)
  1504. {
  1505. APS_FUN();
  1506. }
  1507. /*----------------------------------------------------------------------------*/
  1508. module_init(CM36558_init);
  1509. module_exit(CM36558_exit);
  1510. /*----------------------------------------------------------------------------*/
  1511. MODULE_AUTHOR("yucong xiong");
  1512. MODULE_DESCRIPTION("CM36558 driver");
  1513. MODULE_LICENSE("GPL");