rn6752.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206
  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/init.h>
  4. #include <linux/interrupt.h>
  5. #include <linux/io.h>
  6. #include <linux/mm.h>
  7. #include <linux/slab.h>
  8. #include <linux/fs.h>
  9. #include <linux/i2c.h>
  10. #include <linux/errno.h>
  11. #include <asm/uaccess.h>
  12. #include <linux/delay.h>
  13. #include <linux/platform_device.h>
  14. #include <asm/setup.h>
  15. #include <linux/uaccess.h>
  16. #include <linux/gpio.h>
  17. #include <linux/of_gpio.h>
  18. #include <linux/of_device.h>
  19. #include "ark1668_itu656.h"
  20. #include "rn6752.h"
  21. //#define RN6752_USE_TIMER
  22. #define RN6752_LOW_POWER
  23. //extern int ark_sys_pad_config_gpio_mode(int gpio);
  24. //extern void dvr_set_sys_clk(int level);
  25. extern int dvr_get_pragressive(void);
  26. extern void dvr_restart(void);
  27. static void rn6752_reset(int gpio);
  28. static int rn6752_read_byte(unsigned char regaddr);
  29. static int rn6752_write_byte(unsigned char regaddr, unsigned char regval);
  30. static int rn6752_check_id(struct dvr_rn6752 *dvr_rn6752);
  31. #ifdef RN6752_USE_TIMER
  32. static void rn6752_start_timer(int timeout_100ms);
  33. #endif
  34. struct ark_private_data *g_itu656in_priv = NULL;
  35. struct i2c_client *g_itu656in_client = NULL;
  36. static struct dvr_rn6752 *g_dvr_rn6752 = NULL;
  37. //extern special_info_transfer specinfo_param;
  38. static struct ark_carback_effect_para rn6752_effect;
  39. static int enh_LFS = 1;
  40. static bool rn6752_dbg = false;
  41. /*****************************************************************************************************
  42. * Before use RN6752 driver, we should complete some function as forllows.
  43. */
  44. /* detect video signal */
  45. static int rn6752_detect_signal(void)
  46. {
  47. if(rn6752_dbg)
  48. printk(KERN_ALERT "### rn6752_detect_signal\n");
  49. if(g_dvr_rn6752)
  50. {
  51. #ifdef RN6752_USE_TIMER
  52. if(!g_dvr_rn6752->timer_start)
  53. {
  54. rn6752_start_timer(50);
  55. }
  56. #else
  57. queue_work(g_dvr_rn6752->eq_queue, &g_dvr_rn6752->eq_work);
  58. #endif
  59. return ((g_dvr_rn6752->mode != RN6752_MODE_NONE) ? 1 : 0);
  60. }
  61. else
  62. {
  63. return 0;
  64. }
  65. }
  66. //Select itu656 input channel
  67. static int rn6752_select_channel(int ch)
  68. {
  69. if((ch >= 0) && (ch <= 1))
  70. {
  71. if(g_dvr_rn6752)
  72. g_dvr_rn6752->curr_channel = ch;
  73. rn6752_write_byte(0xD3, ch);
  74. }
  75. return 0;
  76. }
  77. //confirm progressive or interlace based on in signal resolution.
  78. static int rn6752_get_progressive(void)
  79. {
  80. static int progressive = 1;
  81. if(g_dvr_rn6752)
  82. {
  83. #if 0
  84. int progressive = 1;
  85. if(g_dvr_rn6752->mode == RN6752_MODE_NONE)
  86. progressive = 1;
  87. else if(g_dvr_rn6752->mode < RN6752_MODE_720P_PAL)
  88. progressive = 0;
  89. //dvr_set_sys_clk(0);
  90. #else
  91. switch(g_dvr_rn6752->mode)
  92. {
  93. case RN6752_MODE_NONE:
  94. break;
  95. case RN6752_MODE_CVBS_PAL:
  96. case RN6752_MODE_CVBS_NTSC:
  97. progressive = 0;
  98. break;
  99. case RN6752_MODE_720P_PAL:
  100. case RN6752_MODE_720P_NTSC:
  101. progressive = 1;
  102. break;
  103. default:
  104. progressive = 1;
  105. break;
  106. }
  107. #endif
  108. }
  109. if(rn6752_dbg)
  110. printk(KERN_ALERT "### itu656 get rn6752 progressive:%d\n", progressive);
  111. return progressive;
  112. }
  113. static int rn6752_enter_carback_cb(void)
  114. {
  115. #ifdef RN6752_LOW_POWER
  116. rn6752_write_byte(0x80, 0x30); //set power mode
  117. if(g_dvr_rn6752)
  118. {
  119. g_dvr_rn6752->enter_carback = 1;
  120. queue_work(g_dvr_rn6752->eq_queue, &g_dvr_rn6752->eq_work);
  121. }
  122. if(rn6752_dbg)
  123. printk(KERN_ALERT "### rn6752 enter carback\n");
  124. #endif
  125. return 0;
  126. }
  127. static int rn6752_exit_carback_cb(void)
  128. {
  129. #ifdef RN6752_LOW_POWER
  130. rn6752_write_byte(0x80, 0x34); //set low power mode
  131. if(g_dvr_rn6752)
  132. {
  133. g_dvr_rn6752->enter_carback = 0;
  134. }
  135. if(rn6752_dbg)
  136. printk(KERN_ALERT "### rn6752 exit carback\n");
  137. #endif
  138. return 0;
  139. }
  140. static int rn6752_set_display_effect(int cmd, unsigned long arg)
  141. {
  142. int error = 0;
  143. switch(cmd)
  144. {
  145. case ARK_DVR_GET_BRIGHTNESS:
  146. {
  147. int brightness = rn6752_read_byte(RN6752_BRIGHTNESS_ADDR);
  148. if(brightness < 0)
  149. {
  150. error = brightness;
  151. break;
  152. }
  153. if(copy_to_user((void *)arg, &brightness, sizeof(int))){
  154. printk("%s: copy to carback_brightness error\n", __func__);
  155. error = -EFAULT;
  156. }
  157. break;
  158. }
  159. case ARK_DVR_SET_BRIGHTNESS:
  160. {
  161. int brightness;
  162. if(copy_from_user(&brightness, (void *)arg, sizeof(int))){
  163. printk("%s: copy from user frame error\n", __func__);
  164. error = -EFAULT;
  165. }
  166. else
  167. {
  168. brightness &= 0xFF;
  169. if(rn6752_write_byte(RN6752_BRIGHTNESS_ADDR, brightness) == 0)
  170. {
  171. rn6752_effect.carback_mask |= ARK_DVR_BRIGHTNESS_MASK;
  172. rn6752_effect.carback_brightness = brightness;
  173. }
  174. }
  175. break;
  176. }
  177. case ARK_DVR_GET_CONTRAST:
  178. {
  179. int contrast = rn6752_read_byte(RN6752_CONTRAST_ADDR);
  180. if(contrast < 0)
  181. {
  182. error = contrast;
  183. break;
  184. }
  185. if(copy_to_user((void *)arg, &contrast, sizeof(int))){
  186. printk("%s: copy to carback_contrast error\n", __func__);
  187. error = -EFAULT;
  188. }
  189. break;
  190. }
  191. case ARK_DVR_SET_CONTRAST:
  192. {
  193. int contrast;
  194. if(copy_from_user(&contrast, (void *)arg, sizeof(int))){
  195. printk("%s: copy from user frame error\n", __func__);
  196. error = -EFAULT;
  197. }
  198. else
  199. {
  200. contrast &= 0xFF;
  201. if(rn6752_write_byte(RN6752_CONTRAST_ADDR, contrast) == 0)
  202. {
  203. rn6752_effect.carback_mask |= ARK_DVR_CONTRAST_MASK;
  204. rn6752_effect.carback_contrast = contrast;
  205. }
  206. }
  207. break;
  208. }
  209. case ARK_DVR_GET_SATURATION:
  210. {
  211. int saturation = rn6752_read_byte(RN6752_SATURATION_ADDR);
  212. if(saturation < 0)
  213. {
  214. error = saturation;
  215. break;
  216. }
  217. if(copy_to_user((void *)arg, &saturation, sizeof(int))){
  218. printk("%s: copy to carback_saturation error\n", __func__);
  219. error = -EFAULT;
  220. }
  221. break;
  222. }
  223. case ARK_DVR_SET_SATURATION:
  224. {
  225. int saturation;
  226. if(copy_from_user(&saturation, (void *)arg, sizeof(int))){
  227. printk("%s: copy from user frame error\n", __func__);
  228. error = -EFAULT;
  229. }
  230. else
  231. {
  232. saturation &= 0xFF;
  233. if(rn6752_write_byte(RN6752_SATURATION_ADDR, saturation) == 0)
  234. {
  235. rn6752_effect.carback_mask |= ARK_DVR_SATURATION_MASK;
  236. rn6752_effect.carback_saturation = saturation;
  237. }
  238. }
  239. break;
  240. }
  241. case ARK_DVR_GET_HUE:
  242. {
  243. int hue = rn6752_read_byte(RN6752_HUE_ADDR);
  244. if(hue < 0)
  245. {
  246. error = hue;
  247. break;
  248. }
  249. if(copy_to_user((void *)arg, &hue, sizeof(int))){
  250. printk("%s: copy to carback_hue error\n", __func__);
  251. error = -EFAULT;
  252. }
  253. break;
  254. }
  255. case ARK_DVR_SET_HUE:
  256. {
  257. int hue;
  258. if(copy_from_user(&hue, (void *)arg, sizeof(int))){
  259. printk("%s: copy from user frame error\n", __func__);
  260. error = -EFAULT;
  261. }
  262. else
  263. {
  264. hue &= 0xFF;
  265. if(rn6752_write_byte(RN6752_HUE_ADDR, hue) == 0)
  266. {
  267. rn6752_effect.carback_mask |= ARK_DVR_HUE_MASK;
  268. rn6752_effect.carback_hue = hue;
  269. }
  270. }
  271. break;
  272. }
  273. case ARK_DVR_GET_SHARPNESS:
  274. {
  275. int shaprness = rn6752_read_byte(RN6752_SHARPNESS_ADDR);
  276. if(shaprness < 0)
  277. {
  278. error = shaprness;
  279. break;
  280. }
  281. shaprness &= 0x7F;
  282. if(copy_to_user((void *)arg, &shaprness, sizeof(int))){
  283. printk("%s: copy to carback_sharpness error\n", __func__);
  284. error = -EFAULT;
  285. }
  286. break;
  287. }
  288. case ARK_DVR_SET_SHARPNESS:
  289. {
  290. int sharpness;
  291. if(copy_from_user(&sharpness, (void *)arg, sizeof(int))){
  292. printk("%s: copy from user frame error\n", __func__);
  293. error = -EFAULT;
  294. }
  295. else
  296. {
  297. unsigned char tmp = (enh_LFS ? 0x80 : 0);
  298. sharpness &= 0x7F;
  299. if(rn6752_write_byte(RN6752_SHARPNESS_ADDR, (sharpness | tmp)) == 0)
  300. {
  301. rn6752_effect.carback_mask |= ARK_DVR_SHARPNESS_MASK;
  302. rn6752_effect.carback_sharpness = sharpness;
  303. }
  304. }
  305. break;
  306. }
  307. default:
  308. error = -EFAULT;
  309. break;
  310. }
  311. return error;
  312. }
  313. /******************************************************************************************************/
  314. static int rn6752_write_byte(unsigned char regaddr, unsigned char regval)
  315. {
  316. struct i2c_client *client;
  317. struct i2c_msg msg;
  318. s32 ret = -1;
  319. s32 retries = 0;
  320. u8 buf[2] = {0};
  321. if(!g_dvr_rn6752)
  322. return -ENODEV;
  323. client = g_dvr_rn6752->client;
  324. buf[0] = regaddr;
  325. buf[1] = regval;
  326. msg.flags = 0;
  327. msg.addr = client->addr;
  328. msg.len = 2;
  329. msg.buf = buf;
  330. while(retries < 5)
  331. {
  332. ret = i2c_transfer(client->adapter, &msg, 1);
  333. if (ret == 1)
  334. break;
  335. retries++;
  336. }
  337. if(retries >= 5)
  338. {
  339. printk(KERN_ALERT "### ERR: %s failure\n",__FUNCTION__);
  340. return -EBUSY;
  341. }
  342. return 0;
  343. }
  344. static int rn6752_read_byte(unsigned char regaddr)
  345. {
  346. struct i2c_client *client;
  347. struct i2c_msg read_msgs[2];
  348. s32 ret = -1;
  349. s32 retries = 0;
  350. u8 regValue = 0x00;
  351. if(!g_dvr_rn6752)
  352. return -ENODEV;
  353. client = g_dvr_rn6752->client;
  354. read_msgs[0].flags = !I2C_M_RD;
  355. read_msgs[0].addr = client->addr;
  356. read_msgs[0].len = 1;
  357. read_msgs[0].buf = &regaddr;
  358. read_msgs[1].flags = I2C_M_RD;
  359. read_msgs[1].addr = client->addr;
  360. read_msgs[1].len = 1;
  361. read_msgs[1].buf = &regValue;//low byte
  362. while(retries < 5)
  363. {
  364. ret = i2c_transfer(client->adapter, read_msgs, 2);
  365. if(ret == 2)
  366. break;
  367. retries++;
  368. }
  369. if((retries >= 5))
  370. {
  371. printk(KERN_ALERT "### ERR: %s failure\n",__FUNCTION__);
  372. return -EBUSY;
  373. }
  374. return regValue;
  375. }
  376. static void rn6752_set_display_effect_default(void)
  377. {
  378. unsigned int mask = rn6752_effect.carback_mask;
  379. if((mask & ARK_DVR_BRIGHTNESS_MASK))
  380. rn6752_write_byte(RN6752_BRIGHTNESS_ADDR, (rn6752_effect.carback_brightness & 0xFF));
  381. if((mask & ARK_DVR_CONTRAST_MASK))
  382. rn6752_write_byte(RN6752_CONTRAST_ADDR, (rn6752_effect.carback_contrast & 0xFF));
  383. if((mask & ARK_DVR_SATURATION_MASK))
  384. rn6752_write_byte(RN6752_SATURATION_ADDR, (rn6752_effect.carback_saturation & 0xFF));
  385. if((mask & ARK_DVR_HUE_MASK))
  386. rn6752_write_byte(RN6752_HUE_ADDR, (rn6752_effect.carback_hue & 0xFF));
  387. else
  388. rn6752_write_byte(RN6752_HUE_ADDR, 0x80); //set default hue
  389. if((mask & ARK_DVR_SHARPNESS_MASK))
  390. {
  391. if(enh_LFS)
  392. rn6752_write_byte(RN6752_SHARPNESS_ADDR, ((rn6752_effect.carback_sharpness | 0x80) & 0xFF));
  393. else
  394. rn6752_write_byte(RN6752_SHARPNESS_ADDR, (rn6752_effect.carback_sharpness & 0x7F));
  395. }
  396. else //set default sharpness
  397. {
  398. if(enh_LFS)
  399. rn6752_write_byte(RN6752_SHARPNESS_ADDR, 0x80);
  400. else
  401. rn6752_write_byte(RN6752_SHARPNESS_ADDR, 0x00);
  402. }
  403. }
  404. static void rn6752_write_reg(const char *buf, int len)
  405. {
  406. int i;
  407. for(i=0; i<len; i++)
  408. rn6752_write_byte(buf[2*i],buf[2*i+1]);
  409. rn6752_set_display_effect_default();
  410. }
  411. static char * rn6752_get_mode_string (int mode)
  412. {
  413. if(mode == RN6752_MODE_NONE)
  414. {
  415. return "NONE";
  416. }
  417. else if(mode == RN6752_MODE_CVBS_PAL)
  418. {
  419. return "CVBS_PAL";
  420. }
  421. else if(mode == RN6752_MODE_CVBS_NTSC)
  422. {
  423. return "CVBS_NTSC";
  424. }
  425. else if(mode == RN6752_MODE_720P_PAL)
  426. {
  427. return "720_PAL";
  428. }
  429. else if(mode == RN6752_MODE_720P_NTSC)
  430. {
  431. return "720_NTSC";
  432. }
  433. return "NONE";
  434. };
  435. static int rn6752_signal_check(void)
  436. {
  437. u8 signal_cnt = 0;
  438. u8 nosignal_cnt=0;
  439. u8 reg_0x75,reg_0x77, reg_0x78, reg_0x79;
  440. u16 counter1 = 0, counter2 = 0, counter3 = 0;
  441. int i;
  442. for(i=0; i<30; i++)
  443. {
  444. if((rn6752_read_byte(0x00)&0x10) == 0x00)
  445. {
  446. signal_cnt++;
  447. }
  448. else
  449. {
  450. nosignal_cnt++;
  451. }
  452. if(signal_cnt > 10)
  453. {
  454. //printk(KERN_ALERT "### >i:%d\r\n", i);
  455. reg_0x77 = rn6752_read_byte(0x77);
  456. reg_0x78 = rn6752_read_byte(0x78);
  457. reg_0x79 = rn6752_read_byte(0x79);
  458. reg_0x75 = rn6752_read_byte(0x75);
  459. //counter1 = 0;
  460. counter1 = reg_0x77&0x03;
  461. counter1 <<= 8;
  462. counter1 |= reg_0x78;
  463. //counter2 = 0;
  464. counter2 = reg_0x77&0xc;
  465. counter2 >>= 2;
  466. counter2 <<= 8;
  467. counter2 |= reg_0x79;
  468. counter3 = reg_0x75;
  469. //printk(KERN_ALERT ">reg 0x77:%x\r\n", reg_0x77);
  470. //printk(KERN_ALERT ">reg 0x78:%x\r\n", reg_0x78);
  471. //printk(KERN_ALERT ">reg 0x79:%x\r\n", reg_0x79);
  472. //printk(KERN_ALERT ">counter1:%d\r\n", counter1);
  473. //printk(KERN_ALERT ">counter2:%d\r\n", counter2);
  474. break;
  475. }
  476. if(nosignal_cnt > 20)
  477. {
  478. return RN6752_MODE_NONE;
  479. }
  480. msleep(1);
  481. }
  482. if( (counter1 > 700) ||(counter2 > 700))
  483. {
  484. //720p pal
  485. if(counter3 > 0x8c)
  486. return RN6752_MODE_720P_PAL;
  487. else
  488. return RN6752_MODE_720P_NTSC;
  489. }
  490. else if( ((counter1>330) && (counter1<550)) || ((counter2>330) && (counter2<550)) )
  491. {
  492. //cvbs pal
  493. return RN6752_MODE_CVBS_PAL;
  494. }
  495. else if( (counter1<330) && (counter2<330) )
  496. {
  497. //cvbs ntsc
  498. return RN6752_MODE_CVBS_NTSC;
  499. }
  500. return RN6752_MODE_NONE ;
  501. }
  502. static void rn6752_eq_work(struct work_struct *work)
  503. {
  504. //struct dvr_rn6752 *dvr_rn6752 = container_of(work, struct dvr_rn6752, eq_work);
  505. struct dvr_rn6752 *dvr_rn6752 = g_dvr_rn6752;
  506. static int mode_cfg = RN6752_MODE_NONE;
  507. if(!dvr_rn6752)
  508. return;
  509. //mutex_lock(&dvr_rn6752->eq_lock);
  510. if(mode_cfg == RN6752_MODE_NONE)
  511. {
  512. printk(KERN_ALERT "### rn6752_eq_work reset\n");
  513. //reset
  514. rn6752_reset(dvr_rn6752->gpio_reset);
  515. //check id
  516. if(rn6752_check_id(dvr_rn6752))
  517. return;
  518. //720p cfg: before auto match, we must config 720p mode, because the default clk config is based on 720P
  519. rn6752_write_reg(rn6752_tiu656_720p_pal, sizeof(rn6752_tiu656_720p_pal)/2);
  520. mode_cfg = RN6752_MODE_720P_PAL;
  521. #ifdef RN6752_LOW_POWER
  522. if(!g_dvr_rn6752->enter_carback)
  523. {
  524. rn6752_write_byte(0x80, 0x34); //low power mode
  525. }
  526. #endif
  527. return;
  528. }
  529. #ifdef RN6752_LOW_POWER
  530. if(!g_dvr_rn6752->enter_carback)
  531. {
  532. if(rn6752_dbg)
  533. printk(KERN_ALERT "### rn6752_eq_work return when exit carback\n");
  534. return;
  535. }
  536. #endif
  537. rn6752_write_byte(0x49, 0x81);
  538. rn6752_write_byte(0x33, 0x80);
  539. rn6752_write_byte(0x48, 0x1b);
  540. msleep(100);
  541. dvr_rn6752->mode = rn6752_signal_check();
  542. if(dvr_rn6752->mode == RN6752_MODE_NONE)
  543. {
  544. msleep(10);
  545. dvr_rn6752->mode = rn6752_signal_check();
  546. }
  547. rn6752_write_byte(0x48, 0x13);
  548. if(rn6752_dbg)
  549. printk(KERN_ALERT "### rn6752 mode:%s, mode_cfg:%s\n", rn6752_get_mode_string(dvr_rn6752->mode), rn6752_get_mode_string(mode_cfg));
  550. if((dvr_rn6752->mode == RN6752_MODE_NONE) || (mode_cfg != dvr_rn6752->mode))
  551. {
  552. if(rn6752_dbg)
  553. printk(KERN_ALERT "### rn6752 change mode to (%s)\n", rn6752_get_mode_string(dvr_rn6752->mode));
  554. switch(dvr_rn6752->mode)
  555. {
  556. case RN6752_MODE_CVBS_PAL:
  557. if(mode_cfg != RN6752_MODE_CVBS_PAL)
  558. {
  559. rn6752_write_reg(rn6752_tiu656_cvbs_pal, sizeof(rn6752_tiu656_cvbs_pal)/2);
  560. mode_cfg = RN6752_MODE_CVBS_PAL;
  561. }
  562. if(dvr_get_pragressive() == 1)
  563. dvr_restart();
  564. break;
  565. case RN6752_MODE_CVBS_NTSC:
  566. if(mode_cfg != RN6752_MODE_CVBS_NTSC)
  567. {
  568. rn6752_write_reg(rn6752_tiu656_cvbs_ntsc, sizeof(rn6752_tiu656_cvbs_ntsc)/2);
  569. mode_cfg = RN6752_MODE_CVBS_NTSC;
  570. }
  571. if(dvr_get_pragressive() == 1)
  572. dvr_restart();
  573. break;
  574. case RN6752_MODE_720P_NTSC:
  575. if(mode_cfg != RN6752_MODE_720P_NTSC)
  576. {
  577. rn6752_write_reg(rn6752_tiu656_720p_ntsc, sizeof(rn6752_tiu656_720p_ntsc)/2);
  578. mode_cfg = RN6752_MODE_720P_NTSC;
  579. }
  580. if(dvr_get_pragressive() == 0)
  581. dvr_restart();
  582. break;
  583. case RN6752_MODE_720P_PAL:
  584. if(mode_cfg != RN6752_MODE_720P_PAL)
  585. {
  586. rn6752_write_reg(rn6752_tiu656_720p_pal, sizeof(rn6752_tiu656_720p_pal)/2);
  587. mode_cfg = RN6752_MODE_720P_PAL;
  588. }
  589. if(dvr_get_pragressive() == 0)
  590. dvr_restart();
  591. break;
  592. case RN6752_MODE_NONE:
  593. default:
  594. if(mode_cfg != RN6752_MODE_720P_PAL)
  595. {
  596. rn6752_write_reg(rn6752_tiu656_720p_pal, sizeof(rn6752_tiu656_720p_pal)/2);
  597. mode_cfg = RN6752_MODE_720P_PAL;
  598. }
  599. break;
  600. }
  601. }
  602. else
  603. {
  604. int progressive = dvr_get_pragressive();
  605. int restart = 0;
  606. switch(dvr_rn6752->mode)
  607. {
  608. case RN6752_MODE_CVBS_PAL:
  609. case RN6752_MODE_CVBS_NTSC:
  610. if(progressive == 1)
  611. restart = 1;
  612. break;
  613. case RN6752_MODE_720P_PAL:
  614. case RN6752_MODE_720P_NTSC:
  615. if(progressive == 0)
  616. restart = 1;
  617. break;
  618. default:
  619. break;
  620. }
  621. if(restart)
  622. {
  623. if(rn6752_dbg)
  624. printk(KERN_ALERT "### mode(%s) progressive(%d) does not match, itu656 dvr_restart\n", rn6752_get_mode_string(dvr_rn6752->mode), progressive);
  625. dvr_restart();
  626. }
  627. }
  628. //mutex_unlock(&dvr_rn6752->eq_lock);
  629. }
  630. #ifdef RN6752_USE_TIMER
  631. static void rn6752_timeout_timer(struct timer_list *t)
  632. {
  633. struct dvr_rn6752 *dvr_rn6752 = from_timer(dvr_rn6752, t, timer);
  634. if(dvr_rn6752)
  635. {
  636. queue_work(dvr_rn6752->eq_queue, &dvr_rn6752->eq_work);
  637. if(dvr_rn6752->timer_timeout > 0)
  638. {
  639. dvr_rn6752->timer_timeout --;
  640. mod_timer(&dvr_rn6752->timer, jiffies + msecs_to_jiffies(100));
  641. }
  642. else
  643. {
  644. dvr_rn6752->timer_start = false;
  645. }
  646. }
  647. }
  648. static void rn6752_start_timer(int timeout_100ms)
  649. {
  650. //speed video recognise
  651. if(g_dvr_rn6752)
  652. {
  653. g_dvr_rn6752->timer_timeout = timeout_100ms;
  654. if(!g_dvr_rn6752->timer_start)
  655. {
  656. g_dvr_rn6752->timer_start = true;
  657. mod_timer(&g_dvr_rn6752->timer, jiffies + msecs_to_jiffies(10));
  658. }
  659. }
  660. }
  661. #endif
  662. static irqreturn_t rn6752_intr_handler(int irq, void *dev_id)
  663. {
  664. #if 0
  665. struct dvr_rn6752 *dvr_rn6752 = (struct dvr_rn6752 *)dev_id;
  666. unsigned long flags;
  667. spin_lock_irqsave(&dvr_rn6752->spin_lock, flags);
  668. spin_unlock_irqrestore(&dvr_rn6752->spin_lock, flags);
  669. #endif
  670. return IRQ_HANDLED;
  671. }
  672. static int rn6752_check_id(struct dvr_rn6752 *dvr_rn6752)
  673. {
  674. int id = -1;
  675. int ret;
  676. ret = rn6752_read_byte(0xfe);
  677. if(ret < 0)
  678. goto err_check_id;
  679. id = (ret<<8);
  680. ret = rn6752_read_byte(0xfd);
  681. if(ret < 0)
  682. goto err_check_id;
  683. id |= ret;
  684. if(id == 0x401) {
  685. dvr_rn6752->id = RN675X_ID_RN6752;
  686. } else if(id == 0x501) {
  687. dvr_rn6752->id = RN675X_ID_RN6752M;
  688. }
  689. return 0;
  690. err_check_id:
  691. printk(KERN_ERR "***ERR: %s failed, id:%d, ret:%d\n", __FUNCTION__, id, ret);
  692. dvr_rn6752->id = RN675X_ID_UNKNOWN;
  693. return -1;
  694. }
  695. static void rn6752_reset(int gpio)
  696. {
  697. if(gpio >= 0)
  698. {
  699. //hw reset
  700. gpio_direction_output(gpio,1);
  701. msleep(1);
  702. gpio_direction_output(gpio,0);
  703. msleep(10);
  704. gpio_direction_output(gpio,1);
  705. msleep(100);
  706. }
  707. else
  708. {
  709. //sw reset
  710. //rn6752_write_byte(0x80, 0x31); //soft reset
  711. //msleep(100);
  712. //rn6752_write_byte(0x80, 0x30); //reset complete
  713. }
  714. if(g_dvr_rn6752 && (g_dvr_rn6752->curr_channel >= 0))
  715. rn6752_write_byte(0xD3, g_dvr_rn6752->curr_channel);
  716. rn6752_write_byte(0x1A, 0x83); //disable blue screen
  717. }
  718. static void rn6752m_pre_init(void) {
  719. u8 rom_byte1, rom_byte2, rom_byte3, rom_byte4, rom_byte5, rom_byte6;
  720. rn6752_write_byte(0xE1, 0x80);
  721. rn6752_write_byte(0xFA, 0x81);
  722. rom_byte1=rn6752_read_byte (0xFB);
  723. rom_byte2=rn6752_read_byte (0xFB);
  724. rom_byte3=rn6752_read_byte (0xFB);
  725. rom_byte4=rn6752_read_byte (0xFB);
  726. rom_byte5=rn6752_read_byte (0xFB);
  727. rom_byte6=rn6752_read_byte (0xFB);
  728. // config. decoder accroding to rom_byte5 and rom_byte6
  729. if ((rom_byte6 == 0x00) && (rom_byte5 == 0x00)) {
  730. rn6752_write_byte(0xEF, 0xAA);
  731. rn6752_write_byte(0xE7, 0xFF);
  732. rn6752_write_byte(0xFF, 0x09);
  733. rn6752_write_byte(0x03, 0x0C);
  734. rn6752_write_byte(0xFF, 0x0B);
  735. rn6752_write_byte(0x03, 0x0C);
  736. }
  737. else if (((rom_byte6 == 0x34) && (rom_byte5 == 0xA9)) ||
  738. ((rom_byte6 == 0x2C) && (rom_byte5 == 0xA8))) {
  739. rn6752_write_byte(0xEF, 0xAA);
  740. rn6752_write_byte(0xE7, 0xFF);
  741. rn6752_write_byte(0xFC, 0x60);
  742. rn6752_write_byte(0xFF, 0x09);
  743. rn6752_write_byte(0x03, 0x18);
  744. rn6752_write_byte(0xFF, 0x0B);
  745. rn6752_write_byte(0x03, 0x18);
  746. }
  747. else {
  748. rn6752_write_byte(0xEF, 0xAA);
  749. rn6752_write_byte(0xFC, 0x60);
  750. rn6752_write_byte(0xFF, 0x09);
  751. rn6752_write_byte(0x03, 0x18);
  752. rn6752_write_byte(0xFF, 0x0B);
  753. rn6752_write_byte(0x03, 0x18);
  754. }
  755. }
  756. static ssize_t rn6752_get(struct device *dev,
  757. struct device_attribute *attr, char *buf)
  758. {
  759. int i;
  760. for(i=0; i<0xff; i++)
  761. {
  762. printk(KERN_ALERT "[0x%x]:0x%x\n",i,rn6752_read_byte(i));
  763. }
  764. return 0;
  765. }
  766. static ssize_t rn6752_set(struct device *dev,
  767. struct device_attribute *attr, const char *buf, size_t count)
  768. {
  769. if(!strncmp(buf, "write", 5))
  770. {
  771. unsigned int reg,val;
  772. sscanf(buf,"%*s%x%x",&reg,&val);
  773. rn6752_write_byte(reg,val);
  774. printk(KERN_ALERT "write reg[0x%02x]:0x%02x\n",reg,val);
  775. }
  776. if(!strncmp(buf, "read", 4))
  777. {
  778. unsigned int reg,val;
  779. sscanf(buf,"%*s%x",&reg);
  780. val = rn6752_read_byte(reg);
  781. printk(KERN_ALERT "read reg[0x%02x]:0x%02x\n",reg,val);
  782. }
  783. if(!strncmp(buf, "debug", 5))
  784. {
  785. unsigned int val;
  786. sscanf(buf,"%*s%x",&val);
  787. if(val)
  788. {
  789. rn6752_dbg = true;
  790. printk(KERN_ALERT "rn6752 debug on\n");
  791. }
  792. else
  793. {
  794. rn6752_dbg = false;
  795. printk(KERN_ALERT "rn6752 debug off\n");
  796. }
  797. }
  798. if(!strncmp(buf, "work", 4))
  799. {
  800. rn6752_eq_work(NULL);
  801. printk(KERN_ALERT "### eq_work\n");
  802. }
  803. return count;
  804. }
  805. static DEVICE_ATTR(rn6752, S_IWUSR | S_IRUGO,//static DEVICE_ATTR(dvr, S_IWUGO | S_IRUGO,
  806. rn6752_get, rn6752_set);
  807. static struct attribute *rn6752_sysfs_attrs[] = {
  808. &dev_attr_rn6752.attr,
  809. NULL
  810. };
  811. static const struct attribute_group rn6752_sysfs = {
  812. .attrs = rn6752_sysfs_attrs,
  813. };
  814. static const struct of_device_id rn6752_of_match[] = {
  815. { .compatible = "arkmicro,arkn141_rn6752"},
  816. { .compatible = "arkmicro,ark1668_rn6752"},
  817. { }
  818. };
  819. MODULE_DEVICE_TABLE(of, ark7116_of_match);
  820. static int dvr_rn6752_probe(struct i2c_client *client, const struct i2c_device_id *id)
  821. {
  822. struct dvr_rn6752 *dvr_rn6752;
  823. struct ark_private_data pdata;
  824. const struct of_device_id *match = NULL;
  825. int value;
  826. int ret = -1;
  827. dvr_rn6752 = devm_kzalloc(&client->dev, sizeof(struct dvr_rn6752), GFP_KERNEL);
  828. if (!dvr_rn6752)
  829. {
  830. printk(KERN_ERR "***ERR: %s %d: failed to allocate memory\n", __FUNCTION__, __LINE__);
  831. return -ENOMEM;
  832. }
  833. dvr_rn6752->gpio_reset = of_get_named_gpio(client->dev.of_node, "reset-gpio", 0);
  834. if (gpio_is_valid(dvr_rn6752->gpio_reset)) {
  835. //ark_sys_pad_config_gpio_mode(dvr_rn6752->gpio_reset);
  836. ret = devm_gpio_request_one(&client->dev, dvr_rn6752->gpio_reset, GPIOF_OUT_INIT_HIGH, "rn6752_reset");
  837. if (ret) {
  838. printk(KERN_ERR "***ERR: Failed to request rn6752 reset gpio:%d\n", dvr_rn6752->gpio_reset);
  839. return -EBUSY;
  840. }
  841. } else {
  842. dvr_rn6752->gpio_reset = -1;
  843. }
  844. dvr_rn6752->gpio_pdn = of_get_named_gpio(client->dev.of_node, "pdn-gpio", 0);
  845. if (gpio_is_valid(dvr_rn6752->gpio_pdn)) {
  846. //ark_sys_pad_config_gpio_mode(dvr_rn6752->gpio_pdn);
  847. ret = devm_gpio_request_one(&client->dev, dvr_rn6752->gpio_pdn, GPIOF_OUT_INIT_HIGH, "rn6752_pdn");
  848. if (ret) {
  849. printk(KERN_ERR "***ERR: Failed to request rn6752 pdn gpio:%d\n", dvr_rn6752->gpio_pdn);
  850. return -EBUSY;
  851. }
  852. } else {
  853. dvr_rn6752->gpio_pdn = -1;
  854. }
  855. dvr_rn6752->gpio_irq = of_get_named_gpio(client->dev.of_node, "irq-gpio", 0);
  856. if (gpio_is_valid(dvr_rn6752->gpio_irq)) {
  857. //ark_sys_pad_config_gpio_mode(dvr_rn6752->gpio_irq);
  858. ret = devm_gpio_request_one(&client->dev, dvr_rn6752->gpio_irq, GPIOF_OUT_INIT_HIGH, "rn6752_irq");
  859. if (ret) {
  860. printk(KERN_ERR "***ERR: Failed to request rn6752 pd gpio:%d\n", dvr_rn6752->gpio_irq);
  861. return -EBUSY;
  862. }
  863. } else {
  864. dvr_rn6752->gpio_irq = -1;
  865. }
  866. if(!of_property_read_u32(client->dev.of_node, "default-channel", &value)) {
  867. dvr_rn6752->curr_channel = value;
  868. } else {
  869. dvr_rn6752->curr_channel = 0;
  870. }
  871. if(!of_property_read_u32(client->dev.of_node, "camera-format", &value)) {
  872. dvr_rn6752->mode = value;
  873. } else {
  874. dvr_rn6752->mode = RN6752_MODE_NONE;
  875. }
  876. if(!of_property_read_u32(client->dev.of_node, "itu601in", &value)) {
  877. dvr_rn6752->itu601in = value;
  878. } else {
  879. dvr_rn6752->itu601in = 0;
  880. }
  881. dvr_rn6752->client = client;
  882. spin_lock_init(&dvr_rn6752->spin_lock);
  883. //mutex_init(&dvr_rn6752->mutex_lock);
  884. g_dvr_rn6752 = dvr_rn6752;
  885. //memcpy(&rn6752_effect, &specinfo_param.carback_mask, sizeof(struct ark_carback_effect_para));
  886. memset(&rn6752_effect, 0, sizeof(struct ark_carback_effect_para));
  887. match = of_match_device(&rn6752_of_match[0], &client->dev);
  888. if (match) {
  889. //match arkn141
  890. if(dvr_rn6752->mode != RN6752_MODE_NONE) { //using static mode
  891. //reset
  892. rn6752_reset(dvr_rn6752->gpio_reset);
  893. //check id
  894. if(rn6752_check_id(dvr_rn6752))
  895. {
  896. printk(KERN_ERR "***ERR: %s rn6752_check_id failed\n", __FUNCTION__);
  897. return EINVAL;
  898. }
  899. if(dvr_rn6752->id == RN675X_ID_RN6752M) {
  900. rn6752m_pre_init();
  901. }
  902. switch(dvr_rn6752->mode) {
  903. case RN6752_MODE_CVBS_PAL:
  904. if(dvr_rn6752->id == RN675X_ID_RN6752) {
  905. if(dvr_rn6752->itu601in == 0)
  906. rn6752_write_reg(rn6752_tiu656_cvbs_pal, sizeof(rn6752_tiu656_cvbs_pal)/2);
  907. } else if(dvr_rn6752->id == RN675X_ID_RN6752M) {
  908. if(dvr_rn6752->itu601in == 1)
  909. rn6752_write_reg(rn6752m_bt601_cvbs_pal, sizeof(rn6752m_bt601_cvbs_pal)/2);
  910. else
  911. rn6752_write_reg(rn6752m_bt656_cvbs_pal, sizeof(rn6752m_bt656_cvbs_pal)/2);
  912. }
  913. break;
  914. case RN6752_MODE_CVBS_NTSC:
  915. if(dvr_rn6752->id == RN675X_ID_RN6752) {
  916. if(dvr_rn6752->itu601in == 0)
  917. rn6752_write_reg(rn6752_tiu656_cvbs_ntsc, sizeof(rn6752_tiu656_cvbs_ntsc)/2);
  918. } else if(dvr_rn6752->id == RN675X_ID_RN6752M) {
  919. if(dvr_rn6752->itu601in == 1)
  920. rn6752_write_reg(rn6752m_bt601_cvbs_ntsc, sizeof(rn6752m_bt601_cvbs_ntsc)/2);
  921. else
  922. rn6752_write_reg(rn6752m_bt656_cvbs_ntsc, sizeof(rn6752m_bt656_cvbs_ntsc)/2);
  923. }
  924. break;
  925. case RN6752_MODE_720P_PAL:
  926. if(dvr_rn6752->id == RN675X_ID_RN6752) {
  927. if(dvr_rn6752->itu601in == 0)
  928. rn6752_write_reg(rn6752_tiu656_720p_pal, sizeof(rn6752_tiu656_720p_pal)/2);
  929. } else {
  930. if(dvr_rn6752->itu601in == 1)
  931. rn6752_write_reg(rn6752m_bt601_720p_25pfs, sizeof(rn6752m_bt601_720p_25pfs)/2);
  932. else
  933. rn6752_write_reg(rn6752m_bt656_720p_25pfs, sizeof(rn6752m_bt656_720p_25pfs)/2);
  934. }
  935. break;
  936. case RN6752_MODE_720P_NTSC:
  937. if(dvr_rn6752->id == RN675X_ID_RN6752) {
  938. if(dvr_rn6752->itu601in == 0)
  939. rn6752_write_reg(rn6752_tiu656_720p_ntsc, sizeof(rn6752_tiu656_720p_ntsc)/2);
  940. } else if(dvr_rn6752->id == RN675X_ID_RN6752M) {
  941. if(dvr_rn6752->itu601in == 1)
  942. rn6752_write_reg(rn6752m_bt601_720p_30pfs, sizeof(rn6752m_bt601_720p_30pfs)/2);
  943. else
  944. rn6752_write_reg(rn6752m_bt656_720p_30pfs, sizeof(rn6752m_bt656_720p_30pfs)/2);
  945. }
  946. break;
  947. case RN6752_MODE_1080P_25FPS:
  948. if(dvr_rn6752->id == RN675X_ID_RN6752) {
  949. } else if(dvr_rn6752->id == RN675X_ID_RN6752M) {
  950. if(dvr_rn6752->itu601in == 1)
  951. rn6752_write_reg(rn6752m_bt601_1080p_25pfs, sizeof(rn6752m_bt601_1080p_25pfs)/2);
  952. else
  953. rn6752_write_reg(rn6752m_bt656_1080p_25pfs, sizeof(rn6752m_bt656_1080p_25pfs)/2);
  954. }
  955. break;
  956. case RN6752_MODE_1080P_30FPS:
  957. if(dvr_rn6752->id == RN675X_ID_RN6752) {
  958. } else if(dvr_rn6752->id == RN675X_ID_RN6752M) {
  959. if(dvr_rn6752->itu601in == 1)
  960. rn6752_write_reg(rn6752m_bt601_1080p_30pfs, sizeof(rn6752m_bt601_1080p_30pfs)/2);
  961. else
  962. rn6752_write_reg(rn6752m_bt656_1080p_30pfs, sizeof(rn6752m_bt656_1080p_30pfs)/2);
  963. }
  964. break;
  965. default:
  966. break;
  967. }
  968. } else { //obtain mode by dynamic
  969. }
  970. }
  971. match = of_match_device(&rn6752_of_match[1], &client->dev);
  972. if (match) {
  973. memset(&pdata, 0, sizeof(struct ark_private_data));
  974. pdata.detect_signal = rn6752_detect_signal;
  975. pdata.get_progressive = rn6752_get_progressive;
  976. pdata.select_channel = rn6752_select_channel;
  977. pdata.display_effect = rn6752_set_display_effect;
  978. #ifdef RN6752_LOW_POWER
  979. pdata.enter_carback_cb = rn6752_enter_carback_cb;
  980. pdata.exit_carback_cb = rn6752_exit_carback_cb;
  981. #endif
  982. pdata.support_max_resolution = TYPE_720P;
  983. pdata.ic_type = IC_TYPE_RN6752;
  984. g_itu656in_priv = &pdata;
  985. g_itu656in_client = client;
  986. dvr_rn6752->eq_queue = create_singlethread_workqueue("rn6752_eq_queue");
  987. if(dvr_rn6752->eq_queue)
  988. {
  989. INIT_WORK(&dvr_rn6752->eq_work, rn6752_eq_work);
  990. }
  991. queue_work(dvr_rn6752->eq_queue, &dvr_rn6752->eq_work);
  992. gpio_direction_input(dvr_rn6752->gpio_irq);
  993. //gpio_set_debounce(dvr_rn6752->gpio_irq, 20);
  994. ret = devm_request_irq(&client->dev, gpio_to_irq(dvr_rn6752->gpio_irq), rn6752_intr_handler, IRQF_TRIGGER_FALLING, "rn6752", (void *)dvr_rn6752);
  995. if (ret)
  996. {
  997. printk(KERN_ERR "***ERR: %s: request irq error\n", __FUNCTION__);
  998. goto err_request_irq;
  999. }
  1000. #ifdef RN6752_USE_TIMER
  1001. dvr_rn6752->timer_start = false;
  1002. timer_setup(&dvr_rn6752->timer, rn6752_timeout_timer, 0);
  1003. mod_timer(&dvr_rn6752->timer, jiffies + msecs_to_jiffies(100));
  1004. #endif
  1005. }
  1006. ret = sysfs_create_group(&client->dev.kobj, &rn6752_sysfs);
  1007. if (ret) {
  1008. printk(KERN_ERR "***ERR: sysfs_create_group failed\n");
  1009. goto err_sysfs_create_group;
  1010. }
  1011. i2c_set_clientdata(client, dvr_rn6752);
  1012. printk("%s:init done\n", __FUNCTION__);
  1013. return 0;
  1014. err_sysfs_create_group:
  1015. #ifdef RN6752_USE_TIMER
  1016. del_timer(&dvr_rn6752->timer);
  1017. #endif
  1018. err_request_irq:
  1019. if(dvr_rn6752->eq_queue)
  1020. destroy_workqueue(dvr_rn6752->eq_queue);
  1021. g_dvr_rn6752 = NULL;
  1022. g_itu656in_priv = NULL;
  1023. g_itu656in_client = NULL;
  1024. dvr_rn6752->gpio_reset = -1;
  1025. dvr_rn6752->gpio_irq = -1;
  1026. dvr_rn6752->gpio_pdn = -1;
  1027. return ret;
  1028. }
  1029. static int dvr_rn6752_remove(struct i2c_client *client)
  1030. {
  1031. struct dvr_rn6752 *dvr_rn6752 = i2c_get_clientdata(client);
  1032. if (dvr_rn6752)
  1033. {
  1034. sysfs_remove_group(&client->dev.kobj, &rn6752_sysfs);
  1035. #ifdef RN6752_USE_TIMER
  1036. del_timer(&dvr_rn6752->timer);
  1037. #endif
  1038. dvr_rn6752->gpio_reset = -1;
  1039. dvr_rn6752->gpio_irq = -1;
  1040. dvr_rn6752->gpio_pdn = -1;
  1041. if(dvr_rn6752->eq_queue)
  1042. destroy_workqueue(dvr_rn6752->eq_queue);
  1043. //mutex_destroy(&dvr_rn6752->mutex_lock);
  1044. i2c_set_clientdata(client, NULL);
  1045. }
  1046. g_itu656in_priv = NULL;
  1047. g_itu656in_client = NULL;
  1048. g_dvr_rn6752 = NULL;
  1049. return 0;
  1050. }
  1051. static struct i2c_driver dvr_rn6752_driver = {
  1052. .driver = {
  1053. .name = "rn6752",
  1054. .owner = THIS_MODULE,
  1055. .of_match_table = of_match_ptr(rn6752_of_match),
  1056. },
  1057. .probe = dvr_rn6752_probe,
  1058. .remove = dvr_rn6752_remove,
  1059. };
  1060. static int __init dvr_rn6752_init(void)
  1061. {
  1062. return i2c_add_driver(&dvr_rn6752_driver);
  1063. }
  1064. static void __exit dvr_rn6752_exit(void)
  1065. {
  1066. i2c_del_driver(&dvr_rn6752_driver);
  1067. }
  1068. module_init(dvr_rn6752_init);
  1069. module_exit(dvr_rn6752_exit);
  1070. MODULE_AUTHOR("Arkmicro");
  1071. MODULE_DESCRIPTION("RN6752 Driver");
  1072. MODULE_LICENSE("GPL");