ark1668ed_carback.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936
  1. /*
  2. * arkmicro carback driver
  3. *
  4. * Licensed under GPLv2 or later.
  5. */
  6. #include <linux/platform_device.h>
  7. #include <linux/err.h>
  8. #include <linux/init.h>
  9. #include <linux/gpio/consumer.h>
  10. #include <linux/of.h>
  11. #include <linux/of_device.h>
  12. #include <linux/of_address.h>
  13. #include <linux/of_irq.h>
  14. #include <linux/of_gpio.h>
  15. #include <linux/slab.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/io.h>
  18. #include <linux/irq.h>
  19. #include <linux/poll.h>
  20. #include <linux/wait.h>
  21. #include <linux/poll.h>
  22. #include <linux/cdev.h>
  23. #include <linux/device.h>
  24. #include <linux/fs.h>
  25. #include <linux/dma-mapping.h>
  26. #include <linux/errno.h>
  27. #include <asm/setup.h>
  28. #include <linux/spinlock.h>
  29. #include <ark1668ed_carback.h>
  30. #include <ark_track.h>
  31. #include <ark_mcu.h>
  32. #include <linux/delay.h>
  33. extern int vin_enter_carback(int sel);
  34. extern int vin_exit_carback(int sel);
  35. extern int ark_disp_set_layer_en(int layer_id, int enable);
  36. extern int get_bootanimation_status(void);
  37. struct carback_context* g_carback_context = NULL;
  38. #ifdef CONFIG_REVERSING_TRACK
  39. static int delay_show_track = 0;
  40. int first_draw_track = 1;
  41. #endif
  42. static void carback_filter_timer_irq(struct timer_list *t)
  43. {
  44. queue_work(g_carback_context->carback_queue, &g_carback_context->carback_work);
  45. }
  46. static void carback_int_work(struct work_struct *work)
  47. {
  48. struct carback_context *context = container_of(work, struct carback_context, carback_work);
  49. struct ark_carback *carback = container_of(context, struct ark_carback, context);
  50. int status = !gpiod_get_value(context->detect);
  51. int i = 0;
  52. printk(KERN_ALERT "carback_int_work in.status=%d.\n", status);
  53. if (status != context->carback_status) {
  54. if (!status) {
  55. #ifdef CONFIG_REVERSING_TRACK
  56. del_timer(&context->track_timer);
  57. msleep(10);
  58. ark_disp_set_layer_en(2, 0);
  59. #endif
  60. for (i = 0; i < VIN_MAX_DEV; i++)
  61. vin_exit_carback(i);
  62. }
  63. context->carback_status = status;
  64. //poll
  65. context->carback_changed = 1; //set flag to wakeup carback_waiq
  66. wake_up_interruptible(&context->carback_waiq);
  67. //async
  68. if (carback->context.async_queue_cb != NULL) {
  69. printk(KERN_ALERT "kill_fasync carback.\n");
  70. kill_fasync(&carback->context.async_queue_cb, SIGIO, POLL_IN);
  71. }
  72. if (status) {
  73. if (context->app_ready) {
  74. int ret = wait_event_interruptible_timeout(context->app_enter_waiq,
  75. context->app_enter_done, msecs_to_jiffies(500));
  76. if (ret == 0) {
  77. printk(KERN_ALERT "wait for app enter carback timeout.close fb0 by kernel.\n");
  78. ark_disp_set_layer_en(3, 0);
  79. }
  80. context->app_enter_done = 0;
  81. } else ark_disp_set_layer_en(3, 0);
  82. if (get_bootanimation_status())
  83. ark_disp_set_layer_en(0, 0); //close bootanmation
  84. context->track_data_status = 0;
  85. for (i = 0; i < VIN_MAX_DEV; i++)
  86. vin_enter_carback(i);
  87. #ifdef CONFIG_REVERSING_TRACK
  88. if (*(volatile unsigned int *)g_carback_context->track_data_virtaddr == MKTAG('R', 'S', 'T', 'K')) {
  89. first_draw_track = 1;
  90. delay_show_track = 0;
  91. mod_timer(&context->track_timer, jiffies + msecs_to_jiffies(1));
  92. }
  93. #endif
  94. } else {
  95. if (context->app_ready) {
  96. int ret = wait_event_interruptible_timeout(context->app_exit_waiq,
  97. context->app_exit_done, msecs_to_jiffies(500));
  98. if (ret == 0) {
  99. printk(KERN_ALERT "wait for app exit carback timeout.\n");
  100. ark_disp_set_layer_en(3, 1);
  101. }
  102. context->app_exit_done = 0;
  103. } else ark_disp_set_layer_en(3, 1);
  104. if (get_bootanimation_status())
  105. ark_disp_set_layer_en(0, 1); //open bootanmation
  106. #ifdef CONFIG_REVERSING_TRACK
  107. context->track_data_status = 1;
  108. ark_disp_set_layer_en(2, 0);
  109. #endif
  110. }
  111. }
  112. }
  113. #ifdef CONFIG_REVERSING_TRACK
  114. //static int carback_detect_count = 0;
  115. static void carback_signal_detect(void)
  116. {
  117. #if 0
  118. struct carback_context *context = g_carback_context;
  119. int status = !gpiod_get_value(context->detect);
  120. int temp_signal;
  121. if (status) {
  122. temp_signal = dvr_detect_carback_signal();
  123. if (temp_signal == 0) {
  124. carback_detect_count++;
  125. if (carback_detect_count == 10) {
  126. printk(KERN_ALERT "carback delect itu no signal\n");
  127. if (status)
  128. context->carback_signal = temp_signal;
  129. else
  130. context->carback_signal = 1;
  131. carback_detect_count = 0;
  132. }
  133. } else{
  134. context->carback_signal = temp_signal;
  135. context->carback_count = 0;
  136. carback_detect_count = 0;
  137. }
  138. }
  139. #endif
  140. }
  141. static void track_paint_work(struct work_struct *work)
  142. {
  143. struct carback_context *context = container_of(work, struct carback_context, track_work);
  144. struct ark_carback *carback = container_of(context, struct ark_carback, context);
  145. int delay_count, dst_phyaddr;
  146. void *dest;
  147. unsigned int dest_size;
  148. carback_signal_detect();
  149. //context->layer_status = dvr_get_layer_status();
  150. if (context->carback_signal == 0)
  151. set_disp_signal_id(SIGNAL_NORMAL_STATUS_ID);
  152. if (context->carback_signal == 1) {
  153. if (context->layer_status)
  154. set_disp_signal_id(IMAGE_ID_NONE);
  155. }
  156. if (context->carback_signal && !context->layer_status) {
  157. mod_timer(&context->track_timer, jiffies + msecs_to_jiffies(carback->context.track_frame_delay));
  158. return;
  159. }
  160. if (context && (!context->track_disp_width || !context->track_disp_height))
  161. return;
  162. if (first_draw_track) {
  163. ark_track_display_init(carback->context.screen_width, carback->context.screen_height);
  164. ark_track_alpha_blend();
  165. }
  166. dest = (void *)context->tdisplay_virtaddr[context->buffer_index];
  167. dst_phyaddr = context->tdisplay_phyaddr[context->buffer_index];
  168. dest_size = context->track_display_size;
  169. dest_size = track_paint_fill(dest, context->track_disp_width, context->track_disp_height);// need 30 ms
  170. if (dest_size > 0) {
  171. context->buffer_index = (context->buffer_index + 1) % TRACK_FRAME_NUM;
  172. ark_track_set_display_addr(dst_phyaddr);
  173. }
  174. if (first_draw_track) {
  175. first_draw_track = 0;
  176. }
  177. mod_timer(&context->track_timer, jiffies + msecs_to_jiffies(carback->context.track_frame_delay));// 1000/(100+30)=8 frame per sec
  178. delay_count = 260/(carback->context.track_frame_delay+30) ;//delay 200ms show
  179. if (delay_show_track >= delay_count)
  180. return;
  181. if (++delay_show_track == delay_count)
  182. {
  183. context->track_data_status = 1;
  184. ark_disp_set_layer_en(2, 1);
  185. }
  186. }
  187. static void track_timer_handler(struct timer_list *t)
  188. {
  189. struct carback_context *context = g_carback_context;
  190. queue_work(context->track_queue, &context->track_work);
  191. }
  192. #endif
  193. static int ark_carback_dev_init(struct carback_context *context)
  194. {
  195. context->carback_changed = 0;
  196. init_waitqueue_head(&context->carback_waiq);
  197. init_waitqueue_head(&context->app_enter_waiq);
  198. init_waitqueue_head(&context->app_exit_waiq);
  199. context->carback_queue = create_singlethread_workqueue("carback_queue");
  200. if (!context->carback_queue) {
  201. printk(KERN_ERR "%s %d: , create_singlethread_workqueue fail.\n", __func__, __LINE__);
  202. return -1;
  203. }
  204. INIT_WORK(&context->carback_work, carback_int_work);
  205. timer_setup(&context->carback_filter_timer, carback_filter_timer_irq, 0);
  206. return 0;
  207. }
  208. static int ark_carback_dev_uninit(struct carback_context *context)
  209. {
  210. del_timer(&context->carback_filter_timer);
  211. if (context->carback_queue)
  212. destroy_workqueue(context->carback_queue);
  213. gpio_free(context->gpio_id);
  214. return 0;
  215. }
  216. static irqreturn_t ark_carback_intr_handler(int irq, void *dev_id)
  217. {
  218. struct ark_carback *carback = (struct ark_carback *)dev_id;
  219. struct carback_context *context = &carback->context;
  220. mod_timer(&context->carback_filter_timer, jiffies + msecs_to_jiffies(50));
  221. return IRQ_HANDLED;
  222. }
  223. static ssize_t ark_carback_read(struct file *filp, char __user *user, size_t size, loff_t *ppos)
  224. {
  225. struct ark_carback *carback = (struct ark_carback *)filp->private_data;
  226. unsigned long flags;
  227. if (size != 1)
  228. return -EINVAL;
  229. // if backcar changed ,will enter ark_backcar_intr_handler, set carback_changed
  230. wait_event_interruptible(carback->context.carback_waiq, carback->context.carback_changed);
  231. if (copy_to_user(user, &carback->context.carback_status, 1)) {
  232. printk("%s %d: copy_to_user error\n", __func__, __LINE__);
  233. return -EFAULT;
  234. }
  235. spin_lock_irqsave(&carback->context.spin_lock, flags);
  236. /* clear backcar_changed*/
  237. carback->context.carback_changed = 0;
  238. spin_unlock_irqrestore(&carback->context.spin_lock, flags);
  239. return 1;
  240. }
  241. static unsigned int ark_carback_poll(struct file *filp, poll_table *wait)
  242. {
  243. struct ark_carback *carback = (struct ark_carback *)filp->private_data;
  244. unsigned int mask = 0;
  245. poll_wait(filp, &carback->context.carback_waiq, wait);
  246. // if backcar changed ,will enter ark_backcar_intr_handler, set carback_changed
  247. if (carback->context.carback_changed)
  248. {
  249. mask |= POLLIN | POLLRDNORM;
  250. }
  251. return mask;
  252. }
  253. static int ark_carback_open(struct inode *inode, struct file *filp)
  254. {
  255. struct ark_carback *dev;
  256. struct carback_context *context;
  257. dev = container_of(inode->i_cdev, struct ark_carback, cdev);
  258. context = &dev->context;
  259. filp->private_data = dev;
  260. return 0;
  261. }
  262. static int ark_carback_fasync(int fd, struct file *filp, int mode)
  263. {
  264. int ret;
  265. struct ark_carback *carback = (struct ark_carback *)filp->private_data;
  266. ret = fasync_helper(fd, filp, mode, &carback->context.async_queue_cb);
  267. return ret;
  268. }
  269. static int ark_carback_release(struct inode *inode, struct file *filp)
  270. {
  271. struct ark_carback *dev;
  272. dev = container_of(inode->i_cdev, struct ark_carback, cdev);
  273. if (filp->f_flags & FASYNC)
  274. {
  275. /* remove this filp from the asynchronusly notified filp's */
  276. ark_carback_fasync(-1, filp, 0);
  277. }
  278. return 0;
  279. }
  280. static long ark_carback_ioctl(struct file *filp,
  281. unsigned int cmd, unsigned long arg)
  282. {
  283. struct ark_carback *carback =
  284. (struct ark_carback *)filp->private_data;
  285. struct carback_context *context = &carback->context;
  286. switch (cmd)
  287. {
  288. case CARBACK_IOCTL_SET_APP_READY:
  289. context->app_ready = 1;
  290. break;
  291. case CARBACK_IOCTL_APP_ENTER_DONE:
  292. context->app_enter_done = 1;
  293. wake_up_interruptible(&context->app_enter_waiq);
  294. break;
  295. case CARBACK_IOCTL_APP_EXIT_DONE:
  296. context->app_exit_done = 1;
  297. wake_up_interruptible(&context->app_exit_waiq);
  298. break;
  299. case CARBACK_IOCTL_GET_STATUS:
  300. {
  301. int status = context->carback_status;
  302. if (copy_to_user((void *)arg, &status, sizeof(status))) {
  303. printk("cmd CARBACK_IOCTL_GET_STATUS %s %d: copy_to_user error\n",
  304. __func__, __LINE__);
  305. return -EFAULT;
  306. }
  307. }
  308. break;
  309. case CARBACK_IOCTL_DETECT_SIGNAL:
  310. {
  311. //int signal = dvr_detect_carback_signal();
  312. int signal = 1; //temp
  313. if (copy_to_user((void *)arg, &signal, sizeof(signal))) {
  314. printk("cmd CARBACK_IOCTL_DETECT_SIGNAL %s %d: copy_to_user error\n",
  315. __func__, __LINE__);
  316. return -EFAULT;
  317. }
  318. }
  319. break;
  320. case CARBACK_IOCTL_GET_HASTRACK:
  321. {
  322. #ifdef CONFIG_REVERSING_TRACK
  323. int track = 1;
  324. #else
  325. int track = 0;
  326. #endif
  327. if (copy_to_user((void *)arg, &track, sizeof(track))) {
  328. printk("cmd CARBACK_IOCTL_GET_HASTRACK %s %d: copy_to_user error\n",
  329. __func__, __LINE__);
  330. return -EFAULT;
  331. }
  332. }
  333. break;
  334. #ifdef CONFIG_REVERSING_TRACK
  335. case CARBACK_IOCTL_STRACK_INIT:
  336. {
  337. printk("vbox track paint init\n");
  338. ark_disp_set_layer_en(2, 0);
  339. context->track_frame_delay = 100;
  340. /*if(track_paint_init() < 0){
  341. printk(KERN_ERR "%s %d: ,track_paint_init fail.\n",__FUNCTION__, __LINE__);
  342. break;
  343. }
  344. INIT_WORK(&carback->context.track_work, track_paint_work);
  345. setup_timer(&carback->context.track_timer, track_timer_handler, (unsigned long)&carback->context);*/
  346. }
  347. break;
  348. case CARBACK_IOCTL_STRACK_START:
  349. {
  350. if (*(volatile unsigned int *)g_carback_context->track_data_virtaddr == MKTAG('R', 'S', 'T', 'K')) {
  351. first_draw_track = 1;
  352. delay_show_track = 0;
  353. mod_timer(&context->track_timer, jiffies + msecs_to_jiffies(1));
  354. }
  355. }
  356. break;
  357. case CARBACK_IOCTL_STRACK_STOP:
  358. {
  359. unsigned int ret;
  360. del_timer(&context->track_timer);
  361. msleep(10);
  362. ret = ark_disp_set_layer_en(2, 0);
  363. return ret;
  364. //delay_show_track = 0;
  365. }
  366. break;
  367. case CARBACK_IOCTL_SET_STRACKID:
  368. {
  369. unsigned int pic_id[4];
  370. if (copy_from_user(&pic_id, (void *)arg, sizeof(unsigned int)*4)) {
  371. printk(KERN_ALERT "CARBACK_IOCTL_SET_STRACKID error\n");
  372. return -EFAULT;
  373. }
  374. if (pic_id[3] == 0)
  375. pic_id[3] = 0xaaaaaaaa;
  376. set_disp_track_id(pic_id[0]);
  377. set_disp_car_id(pic_id[1]);
  378. set_disp_track2_id(pic_id[2]);
  379. set_disp_radar_id(pic_id[3]);
  380. //printk(KERN_ALERT "track_id=0x%0x,car_id=0x%0x,track2_id=0x%0x ,radar_id=0x%0x\n",pic_id[0],pic_id[1],pic_id[2],pic_id[3]);
  381. }
  382. break;
  383. case CARBACK_IOCTL_STRACK_SHOW:
  384. {
  385. printk("vbox track show\n");
  386. ark_disp_set_layer_en(2, 1);
  387. }
  388. break;
  389. case CARBACK_IOCTL_STRACK_CLOSE:
  390. {
  391. printk("vbox track close\n");
  392. ark_disp_set_layer_en(2, 0);
  393. }
  394. break;
  395. case CARBACK_IOCTL_STRACK_SETTING:
  396. {
  397. int set;
  398. if (copy_from_user(&set, (void *)arg, sizeof(int))) {
  399. printk(KERN_ALERT "CARBACK_IOCTL_STRACK_SETTING error\n");
  400. return -EFAULT;
  401. }
  402. if (set == 0 || set == 1) {
  403. context->track_setting = set;
  404. printk("track_setting=%d\n", set);
  405. }
  406. }
  407. break;
  408. case CARBACK_IOCTL_STRACK_FRAME_RATE:
  409. {
  410. int frame_rate;
  411. if (copy_from_user(&frame_rate, (void *)arg, sizeof(int))) {
  412. printk(KERN_ALERT "CARBACK_IOCTL_STRACK_SETTING error\n");
  413. return -EFAULT;
  414. }
  415. if (frame_rate > 0 && frame_rate < 100) {
  416. context->track_frame_delay = (1000/frame_rate);
  417. printk("set frame_rate=%d\n", frame_rate);
  418. }
  419. }
  420. break;
  421. case CARBACK_IOCTL_STRACK_SET_PARAM:
  422. {
  423. track_param_context track_param;
  424. track_param_context *p = &track_param;
  425. if (!context->ptrack_param) {
  426. printk(KERN_ALERT "ptrack_param == null,error.\n");
  427. return -EFAULT;
  428. }
  429. if (copy_from_user(&track_param, (void *)arg, sizeof(track_param_context))) {
  430. printk(KERN_ALERT "CARBACK_IOCTL_STRACK_SET_PARAM error.\n");
  431. return -EFAULT;
  432. }
  433. printk("%d %d %d %d.\n", p->track_rect.width, p->track_rect.height, p->car_rect.width, p->car_rect.height);
  434. if (track_param.track_rect.width == 0 || track_param.track_rect.height == 0) {
  435. printk(KERN_ALERT "set track_param data error.\n");
  436. return -EFAULT;
  437. }
  438. memcpy(context->ptrack_param, &track_param, sizeof(track_param_context));
  439. context->track_disp_width = track_param.track_rect.width;
  440. context->track_disp_height = track_param.track_rect.height;
  441. context->track_disp_xpos = track_param.track_rect.pos_x;
  442. context->track_disp_ypos = track_param.track_rect.pos_y;
  443. }
  444. break;
  445. case CARBACK_IOCTL_STRACK_GET_PARAM:
  446. {
  447. track_param_context *p = context->ptrack_param;
  448. if (!context->ptrack_param) {
  449. printk(KERN_ALERT "ptrack_param == null,error\n");
  450. return -EFAULT;
  451. }
  452. if (copy_to_user((void *)arg, context->ptrack_param, sizeof(track_param_context))) {
  453. printk(KERN_ALERT "CARBACK_IOCTL_STRACK_GET_PARAM error\n");
  454. return -EFAULT;
  455. }
  456. printk("%d %d %d %d.\n", p->track_rect.width, p->track_rect.height, p->car_rect.width, p->car_rect.height);
  457. }
  458. break;
  459. case CARBACK_IOCTL_STRACK_GET_FILETYPE:
  460. {
  461. unsigned int file_type = context->file_type & ~(HEADER2_FILE_FLAG);
  462. if (copy_to_user((void *)arg, &file_type, sizeof(unsigned int))) {
  463. printk(KERN_ALERT "CARBACK_IOCTL_STRACK_GET_FILETYPE error\n");
  464. return -EFAULT;
  465. }
  466. printk("reversingtrack file_type=%d.\n",file_type);
  467. }
  468. break;
  469. case CARBACK_IOCTL_STRACK_GET_IDENTITY:
  470. {
  471. unsigned int identity = *(volatile unsigned int*)g_carback_context->track_data_virtaddr;
  472. if (copy_to_user((void *)arg, &identity, sizeof(unsigned int))) {
  473. printk(KERN_ALERT "CARBACK_IOCTL_STRACK_GET_FILETYPE error\n");
  474. return -EFAULT;
  475. }
  476. printk("reversingtrack identity=0x%0x.\n",identity);
  477. }
  478. break;
  479. case CARBACK_IOCTL_MRADAR_SET_PARAM:
  480. {
  481. mradar_param_context mradar_param;
  482. mradar_param_context *p = &mradar_param;
  483. if (!context->pmradar_param) {
  484. //printk(KERN_ALERT "MRADAR SET PARAM, context->pmradar_param null, exit.\n");
  485. return -EFAULT;
  486. }
  487. if (copy_from_user(&mradar_param, (void *)arg, sizeof(mradar_param_context))) {
  488. printk(KERN_ALERT "CARBACK_IOCTL_STRACK_SET_PARAM error.\n");
  489. return -EFAULT;
  490. }
  491. printk("%d %d %d %d.\n", p->mradar_rect[0].pos_x, p->mradar_rect[0].pos_y, p->mradar_rect[0].width, p->mradar_rect[0].height);
  492. if (mradar_param.mradar_rect[0].width == 0 || mradar_param.mradar_rect[0].height == 0) {
  493. printk(KERN_ALERT "mradar set param error.\n");
  494. return -EFAULT;
  495. }
  496. memcpy(context->pmradar_param, &mradar_param, sizeof(mradar_param_context));
  497. }
  498. break;
  499. case CARBACK_IOCTL_MRADAR_GET_PARAM:
  500. {
  501. mradar_param_context *p = context->pmradar_param;
  502. if (!context->pmradar_param) {
  503. //printk(KERN_ALERT "MRADAR GET PARAM: context->pmradar_param null, exit\n");
  504. return -EFAULT;
  505. }
  506. if (copy_to_user((void *)arg, context->pmradar_param, sizeof(mradar_param_context))) {
  507. printk(KERN_ALERT "CARBACK_IOCTL_STRACK_GET_PARAM error\n");
  508. return -EFAULT;
  509. }
  510. printk("%d %d %d %d.\n", p->mradar_rect[0].pos_x, p->mradar_rect[0].pos_y, p->mradar_rect[0].width, p->mradar_rect[0].height);
  511. }
  512. break;
  513. case CARBACK_IOCTL_MRADAR_SET_ID:
  514. {
  515. unsigned char pic_id[MRADAR_MAX];
  516. if (!context->pmradar_param) {
  517. //printk(KERN_ALERT "MRADAR SET ID: context->pmradar_param null, exit\n");
  518. return -EFAULT;
  519. }
  520. if (copy_from_user(&pic_id, (void *)arg, MRADAR_MAX)) {
  521. printk(KERN_ALERT "CARBACK_IOCTL_MRADAR_SET_ID error\n");
  522. return -EFAULT;
  523. }
  524. set_disp_mradar_id(pic_id);
  525. }
  526. break;
  527. case CARBACK_IOCTL_GET_DATA_STATUS:
  528. {
  529. return context->track_data_status;
  530. }
  531. break;
  532. #endif
  533. default:
  534. printk("%s %d: undefined cmd (0x%2X)\n",
  535. __func__, __LINE__, cmd);
  536. return -EINVAL;
  537. }
  538. return 0;
  539. }
  540. static struct file_operations ark_carback_fops = {
  541. .owner = THIS_MODULE,
  542. .open = ark_carback_open,
  543. .unlocked_ioctl = ark_carback_ioctl,
  544. .release = ark_carback_release,
  545. .fasync = ark_carback_fasync,
  546. .read = ark_carback_read,
  547. .poll = ark_carback_poll,
  548. };
  549. /* This function is invoked when the device module is loaded into the
  550. * kernel. It allocates system resources for constructing driver control
  551. * data structures and initializes them accordingly.
  552. */
  553. static const struct of_device_id ark_carback_of_match[] = {
  554. { .compatible = "arkmicro,ark1668ed-carback", },
  555. { /* sentinel */ }
  556. };
  557. static int ark_carback_probe(struct platform_device *pdev)
  558. {
  559. struct ark_carback *carback;
  560. #ifdef CONFIG_REVERSING_TRACK
  561. struct resource *res;
  562. int i = 0;
  563. #endif
  564. dev_t dev;
  565. int error = 0;
  566. carback = devm_kzalloc(&pdev->dev, sizeof(*carback), GFP_KERNEL);
  567. if (!carback)
  568. return -ENOMEM;
  569. memset(carback, 0, sizeof(struct ark_carback));
  570. g_carback_context = &carback->context;
  571. carback->context.detect = devm_gpiod_get(&pdev->dev, "detect", GPIOD_IN);
  572. if (IS_ERR(carback->context.detect))
  573. return PTR_ERR(carback->context.detect);
  574. if (of_property_read_u32(pdev->dev.of_node, "debounce-detect", &carback->debounce_detect)) {
  575. carback->debounce_detect = 20;
  576. }
  577. carback->dynamic_track_config = 0;
  578. if (!of_property_read_u32(pdev->dev.of_node, "dynamic-track", &carback->dynamic_track_config)) {
  579. if (carback->dynamic_track_config < 0 && carback->dynamic_track_config > 1)
  580. carback->dynamic_track_config = 0;
  581. }
  582. gpiod_set_debounce(carback->context.detect, carback->debounce_detect);
  583. carback->irq = platform_get_irq(pdev, 0);
  584. if (carback->irq < 0)
  585. return carback->irq;
  586. carback->pdev = pdev;
  587. carback->driver_name = "ark_carback_drv";
  588. carback->name = "ark_carback";
  589. carback->major = 0; /* if 0, let system choose */
  590. carback->minor_start = 0;
  591. carback->minor_num = 1; /* one dev only */
  592. carback->num = 1;
  593. /* register char device */
  594. if (!carback->major) {
  595. error = alloc_chrdev_region(
  596. &dev,
  597. carback->minor_start,
  598. carback->num,
  599. carback->name
  600. );
  601. if (!error) {
  602. carback->major = MAJOR(dev);
  603. carback->minor_start = MINOR(dev);
  604. //printk(KERN_ERR "%s %d: allocate device major=%d minor=%d\n",
  605. // __FUNCTION__, __LINE__,
  606. // carback->major, carback->minor_start);
  607. }
  608. } else {
  609. dev = MKDEV(carback->major, carback->minor_start);
  610. // printk(KERN_ERR "%s %d: dev %d\n", __FUNCTION__, __LINE__, dev);
  611. error = register_chrdev_region(dev, carback->num,
  612. (char *)carback->name);
  613. }
  614. if (error < 0) {
  615. printk(KERN_ERR "%s %d: register driver error\n",
  616. __func__, __LINE__);
  617. goto err_driver_register;
  618. }
  619. /* associate the file operations */
  620. cdev_init(&carback->cdev, &ark_carback_fops);
  621. carback->cdev.owner = THIS_MODULE; //driver->owner;
  622. carback->cdev.ops = &ark_carback_fops;
  623. error = cdev_add(&carback->cdev, dev, carback->num);
  624. if (error) {
  625. printk(KERN_ERR "%s %d: cdev add error\n", __func__, __LINE__);
  626. goto err_cdev_add;
  627. }
  628. //printk(KERN_ERR "%s %d: cdev made, name: %s, major: %d, minor: %d \n",
  629. // __FUNCTION__, __LINE__, carback->name, carback->major,
  630. // carback->minor_start);
  631. carback->carback_class = class_create("carback_class");
  632. if (IS_ERR(carback->carback_class)) {
  633. printk(KERN_ERR "Err: failed in creating ark carback class.\n");
  634. carback->carback_class = NULL;
  635. goto err_cdev_add;
  636. }
  637. carback->carback_device = device_create(carback->carback_class, NULL, dev, NULL, "carback");
  638. if (IS_ERR(carback->carback_device)) {
  639. printk(KERN_ERR "Err: failed in creating ark carback device.\n");
  640. carback->carback_device = NULL;
  641. goto err_cdev_add;
  642. }
  643. #ifdef CONFIG_REVERSING_TRACK
  644. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  645. if (res == NULL) {
  646. printk(KERN_ALERT "platform_get_resource faild ...\n");
  647. return 0;
  648. }
  649. printk("res->start = %x,size = %x\n", res->start, resource_size(res));
  650. carback->context.track_data_phyaddr = res->start;
  651. carback->context.track_data_virtaddr = (unsigned int)ioremap(carback->context.track_data_phyaddr, resource_size(res));
  652. if (!carback->context.track_data_virtaddr) {
  653. printk(KERN_ALERT "track_data_virtaddr is null");
  654. goto err_irq;
  655. } else {
  656. printk("track_data_virtaddr = %x\n", carback->context.track_data_virtaddr);
  657. }
  658. #endif
  659. register_mcu_interface();
  660. #ifdef CONFIG_REVERSING_TRACK
  661. carback->context.track_frame_delay = 100;//100ms
  662. carback->context.track_data_status = 1;
  663. carback->context.carback_signal = 1;
  664. carback->context.track_setting = 1;
  665. carback->context.layer_status = 0;
  666. carback->context.buffer_num = TRACK_FRAME_NUM;
  667. carback->context.buffer_index = 0;
  668. ark_track_get_screen_info(&carback->context.screen_width, &carback->context.screen_height);
  669. /* initialize rt timer */
  670. carback->context.track_queue = create_singlethread_workqueue("track_queue");
  671. if (!carback->context.track_queue) {
  672. printk(KERN_ERR "%s %d: , create_singlethread_workqueue fail.\n", __func__, __LINE__);
  673. goto err_track;
  674. }
  675. if (track_paint_init() < 0) {
  676. printk(KERN_ERR "%s %d: ,track_paint_init fail.\n", __func__, __LINE__);
  677. unregister_mcu_interface();
  678. }
  679. INIT_WORK(&carback->context.track_work, track_paint_work);
  680. carback->context.track_display_size = carback->context.screen_width * carback->context.screen_height * 4 * carback->context.buffer_num;
  681. carback->context.track_display_virtaddr =
  682. (unsigned int)dma_alloc_coherent(&pdev->dev, carback->context.track_display_size,
  683. &carback->context.track_display_phyaddr, GFP_KERNEL);
  684. if (!carback->context.track_display_virtaddr) {
  685. printk(KERN_ALERT "%s %d: ,alloc track display buffer failed.\n", __func__, __LINE__);
  686. } else {
  687. timer_setup(&carback->context.track_timer, track_timer_handler, 0);
  688. for (i = 0; i < carback->context.buffer_num; i++) {
  689. carback->context.tdisplay_virtaddr[i] = carback->context.track_display_virtaddr + carback->context.screen_width * carback->context.screen_height * 4*i;
  690. carback->context.tdisplay_phyaddr[i] = carback->context.track_display_phyaddr + carback->context.screen_width * carback->context.screen_height * 4*i;
  691. }
  692. }
  693. #endif
  694. ark_carback_dev_init(&carback->context);
  695. error = devm_request_irq(&pdev->dev, carback->irq, ark_carback_intr_handler, 0, "ark-carback", carback);
  696. if (error) {
  697. printk(KERN_ERR "%s %d: can't get assigned carback irq %d, error %d\n",
  698. __func__, __LINE__, carback->irq, error);
  699. goto err_irq;
  700. return error;
  701. }
  702. if (!gpiod_get_value(carback->context.detect)) {
  703. mod_timer(&carback->context.carback_filter_timer, jiffies + msecs_to_jiffies(50));
  704. //if(carback->context && carback->context.send_mcu_carback)
  705. //carback->context.send_mcu_carback(true);
  706. } else {
  707. carback->context.carback_status = 0;
  708. //if(carback_context && carback_context->send_mcu_carback)
  709. // carback_context->send_mcu_carback(true);
  710. }
  711. carback->context.dev = &pdev->dev;
  712. platform_set_drvdata(pdev, carback);
  713. return 0;
  714. err_irq:
  715. /* free the interrupt channel */
  716. if (carback->context.gpio_id >= 0) {
  717. free_irq(gpio_to_irq(carback->context.gpio_id), carback);
  718. carback->context.gpio_id = -1;
  719. }
  720. cdev_del(&carback->cdev);
  721. #ifdef CONFIG_REVERSING_TRACK
  722. del_timer(&carback->context.track_timer);
  723. err_track:
  724. /* initialize rt timer */
  725. if (carback->context.track_queue)
  726. destroy_workqueue(carback->context.track_queue);
  727. #endif
  728. err_cdev_add:
  729. if (carback->carback_class) {
  730. if (carback->carback_device) {
  731. device_destroy(carback->carback_class, dev);
  732. }
  733. class_destroy(carback->carback_class);
  734. }
  735. unregister_chrdev_region(dev, carback->num);
  736. err_driver_register:
  737. kfree(carback);
  738. return error;
  739. }
  740. /* This function is invoked when the device module is removed from the
  741. * kernel. It releases all resources to the system.
  742. */
  743. static void ark_carback_remove(struct platform_device *pdev)
  744. {
  745. struct ark_carback *carback;
  746. dev_t dev;
  747. carback = platform_get_drvdata(pdev);
  748. if (carback == NULL)
  749. return ;
  750. dev = MKDEV(carback->major, carback->minor_start);
  751. /* free the interrupt channel */
  752. if (carback->context.gpio_id >= 0) {
  753. free_irq(gpio_to_irq(carback->context.gpio_id), carback);
  754. carback->context.gpio_id = -1;
  755. }
  756. carback->context.track_data_status = 1;
  757. carback->context.carback_signal = 1;
  758. #ifdef CONFIG_REVERSING_TRACK
  759. /* initialize rt timer */
  760. del_timer(&carback->context.track_timer);
  761. if (carback->context.track_queue)
  762. destroy_workqueue(carback->context.track_queue);
  763. track_paint_deinit();
  764. if (carback->context.track_display_virtaddr)
  765. dma_free_wc(&pdev->dev, carback->context.track_display_size, (void *)carback->context.track_display_virtaddr,
  766. carback->context.track_display_phyaddr);
  767. #endif
  768. unregister_mcu_interface();
  769. ark_carback_dev_uninit(&carback->context);
  770. cdev_del(&carback->cdev);
  771. unregister_chrdev_region(dev, carback->num);
  772. kfree(carback);
  773. }
  774. static struct platform_driver ark_carback_driver = {
  775. .driver = {
  776. .name = "ark1668e-carback",
  777. .of_match_table = of_match_ptr(ark_carback_of_match),
  778. },
  779. .probe = ark_carback_probe,
  780. .remove = ark_carback_remove,
  781. };
  782. static int __init ark_carback_init(void)
  783. {
  784. int ret;
  785. ret = platform_driver_register(&ark_carback_driver);
  786. if (ret != 0) {
  787. printk(KERN_ERR "%s %d: failed to register ark_carback_driver\n",
  788. __func__, __LINE__);
  789. }
  790. return ret;
  791. }
  792. late_initcall_sync(ark_carback_init);