vdin.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /*
  2. * VDIN driver
  3. *
  4. * Author: Lin Xu <lin.xu@amlogic.com>
  5. * Bobby Yang <bo.yang@amlogic.com>
  6. *
  7. * Copyright (C) 2010 Amlogic Inc.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. /* Standard Linux headers */
  14. #include <linux/types.h>
  15. #include <linux/errno.h>
  16. #include <linux/init.h>
  17. #include <linux/module.h>
  18. #include <linux/kernel.h>
  19. #include <linux/slab.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/fs.h>
  22. #include <linux/device.h>
  23. #include <linux/cdev.h>
  24. #include <linux/platform_device.h>
  25. //#include <linux/etherdevice.h>
  26. #include <linux/interrupt.h>
  27. #include <linux/errno.h>
  28. #include <asm/uaccess.h>
  29. #include <linux/delay.h>
  30. #include <linux/workqueue.h>
  31. #include <linux/time.h>
  32. #include <linux/mm.h>
  33. /* Amlogic headers */
  34. #include <linux/amports/canvas.h>
  35. #include <mach/am_regs.h>
  36. #include <linux/amports/vframe.h>
  37. #include <linux/amports/vframe_provider.h>
  38. #include <linux/amports/vframe_receiver.h>
  39. #include <media/amlogic/656in.h>
  40. /* TVIN headers */
  41. #include "tvin_global.h"
  42. #include "tvin_format_table.h"
  43. #include "tvin_notifier.h"
  44. #include "vdin_regs.h"
  45. #include "vdin.h"
  46. #include "vdin_vf.h"
  47. #include "vdin_ctl.h"
  48. #define VDIN_NAME "vdin"
  49. #define VDIN_DRIVER_NAME "vdin"
  50. #define VDIN_MODULE_NAME "vdin"
  51. #define VDIN_DEVICE_NAME "vdin"
  52. #define VDIN_CLASS_NAME "vdin"
  53. #define PROVIDER_NAME "vdin"
  54. #if defined(CONFIG_ARCH_MESON) || defined (CONFIG_ARCH_MESON3)
  55. #define VDIN_COUNT 1
  56. #elif defined(CONFIG_ARCH_MESON2)
  57. #define VDIN_COUNT 2
  58. #elif defined(CONFIG_ARCH_MESON6)
  59. #define VDIN_COUNT 1
  60. #endif
  61. #define VDIN_PUT_INTERVAL 1 //(HZ/100) //10ms, #define HZ 100
  62. #define INVALID_VDIN_INPUT 0xffffffff
  63. static dev_t vdin_devno;
  64. static struct class *vdin_clsp;
  65. #if defined(CONFIG_ARCH_MESON) || defined (CONFIG_ARCH_MESON3)
  66. unsigned int vdin_addr_offset[VDIN_COUNT] = {0x00};
  67. #elif defined(CONFIG_ARCH_MESON2)
  68. unsigned int vdin_addr_offset[VDIN_COUNT] = {0x00, 0x70};
  69. #elif defined(CONFIG_ARCH_MESON6)
  70. unsigned int vdin_addr_offset[VDIN_COUNT] = {0x00};
  71. #endif
  72. static vdin_dev_t *vdin_devp[VDIN_COUNT];
  73. //#define VDIN_DBG_MSG_CNT
  74. #ifdef VDIN_DBG_MSG_CNT
  75. typedef struct vdin_dbg_msg_s {
  76. u32 vdin_isr_hard_counter;
  77. u32 vdin_tasklet_counter;
  78. u32 vdin_get_new_frame_cnt;
  79. u32 vdin_dec_run_none_cnt;
  80. u32 vdin_tasklet_invalid_type_cnt;
  81. u32 vdin_tasklet_valid_type_cnt;
  82. u32 vdin_from_video_recycle_cnt;
  83. u32 vdin_irq_short_time_cnt;
  84. u32 vdin_timer_puch_nf_cnt;
  85. }vdin_dbg_msg_t;
  86. static vdin_dbg_msg_t vdin_dbg_msg = {
  87. .vdin_isr_hard_counter = 0,
  88. .vdin_tasklet_counter = 0, //u32 ;
  89. .vdin_get_new_frame_cnt = 0, //u32 ;
  90. .vdin_dec_run_none_cnt = 0, //u32 ;
  91. .vdin_tasklet_invalid_type_cnt = 0, //u32 ;
  92. .vdin_tasklet_valid_type_cnt = 0, //u32 ;
  93. .vdin_from_video_recycle_cnt = 0, //u32 ;
  94. .vdin_irq_short_time_cnt = 0,
  95. .vdin_timer_puch_nf_cnt = 0,
  96. };
  97. #endif
  98. void tvin_dec_register(struct vdin_dev_s *devp, struct tvin_dec_ops_s *ops)
  99. {
  100. ulong flags;
  101. if (devp->dec_ops)
  102. tvin_dec_unregister(devp);
  103. spin_lock_irqsave(&devp->dec_lock, flags);
  104. devp->dec_ops = ops;
  105. spin_unlock_irqrestore(&devp->dec_lock, flags);
  106. }
  107. void tvin_dec_unregister(struct vdin_dev_s *devp)
  108. {
  109. ulong flags;
  110. spin_lock_irqsave(&devp->dec_lock, flags);
  111. devp->dec_ops = NULL;
  112. spin_unlock_irqrestore(&devp->dec_lock, flags);
  113. }
  114. void vdin_info_update(struct vdin_dev_s *devp, struct tvin_parm_s *para)
  115. {
  116. //check decoder signal status
  117. devp->para.status = para->status;
  118. devp->para.fmt_info.fmt= para->fmt_info.fmt;
  119. devp->para.fmt_info.v_active= para->fmt_info.v_active;
  120. devp->para.fmt_info.h_active= para->fmt_info.h_active;
  121. devp->para.fmt_info.frame_rate=para->fmt_info.frame_rate;
  122. if((para->status != TVIN_SIG_STATUS_STABLE) || (para->fmt_info.fmt== TVIN_SIG_FMT_NULL))
  123. return;
  124. //write vdin registers
  125. vdin_set_all_regs(devp);
  126. }
  127. EXPORT_SYMBOL(vdin_info_update);
  128. static void vdin_put_timer_func(unsigned long arg)
  129. {
  130. struct timer_list *timer = (struct timer_list *)arg;
  131. while (!vfq_empty_recycle()) {
  132. vframe_t *vf = vfq_pop_recycle();
  133. vfq_push_newframe(vf);
  134. #ifdef VDIN_DBG_MSG_CNT
  135. vdin_dbg_msg.vdin_timer_puch_nf_cnt++;
  136. #endif
  137. }
  138. tvin_check_notifier_call(TVIN_EVENT_INFO_CHECK, NULL);
  139. timer->expires = jiffies + VDIN_PUT_INTERVAL;
  140. add_timer(timer);
  141. }
  142. static void vdin_start_dec(struct vdin_dev_s *devp)
  143. {
  144. vdin_vf_init();
  145. vdin_reg_vf_provider();
  146. vf_notify_receiver(PROVIDER_NAME,VFRAME_EVENT_PROVIDER_START,NULL);
  147. #ifdef VDIN_DBG_MSG_CNT
  148. vdin_dbg_msg.vdin_isr_hard_counter = 0;
  149. vdin_dbg_msg.vdin_tasklet_counter = 0;
  150. vdin_dbg_msg.vdin_get_new_frame_cnt = 0;
  151. vdin_dbg_msg.vdin_dec_run_none_cnt = 0;
  152. vdin_dbg_msg.vdin_tasklet_invalid_type_cnt = 0;
  153. vdin_dbg_msg.vdin_tasklet_valid_type_cnt = 0;
  154. vdin_dbg_msg.vdin_from_video_recycle_cnt = 0;
  155. vdin_dbg_msg.vdin_irq_short_time_cnt = 0;
  156. vdin_dbg_msg.vdin_timer_puch_nf_cnt = 0;
  157. #endif
  158. vdin_set_default_regmap(devp->addr_offset);
  159. tvin_dec_notifier_call(TVIN_EVENT_DEC_START, devp);
  160. //write vdin registers
  161. // vdin_set_all_regs(devp);
  162. return;
  163. }
  164. static void vdin_stop_dec(struct vdin_dev_s *devp)
  165. {
  166. vdin_unreg_vf_provider();
  167. //load default setting for vdin
  168. vdin_set_default_regmap(devp->addr_offset);
  169. tvin_dec_notifier_call(TVIN_EVENT_DEC_STOP, devp);
  170. }
  171. int start_tvin_service(int no ,tvin_parm_t *para)
  172. {
  173. struct vdin_dev_s *devp;
  174. if((!para)||(no > 1)){
  175. return -1;
  176. }
  177. devp = vdin_devp[no];
  178. devp->para.port = para->port;
  179. devp->para.fmt_info.fmt= para->fmt_info.fmt;
  180. devp->para.fmt_info.h_active= para->fmt_info.h_active;
  181. devp->para.fmt_info.v_active= para->fmt_info.v_active;
  182. devp->para.fmt_info.hsync_phase= para->fmt_info.hsync_phase;
  183. devp->para.fmt_info.vsync_phase= para->fmt_info.vsync_phase;
  184. devp->para.fmt_info.frame_rate= para->fmt_info.frame_rate;
  185. devp->flags |= VDIN_FLAG_DEC_STARTED;
  186. vdin_start_dec(devp);
  187. msleep(10);
  188. tasklet_enable(&devp->isr_tasklet);
  189. devp->pre_irq_time = jiffies,
  190. enable_irq(devp->irq);
  191. }
  192. int stop_tvin_service(int no)
  193. {
  194. struct vdin_dev_s *devp;
  195. if(no > 1){
  196. return -1;
  197. }
  198. devp = vdin_devp[no];
  199. devp->flags &= (~VDIN_FLAG_DEC_STARTED);
  200. disable_irq_nosync(devp->irq);
  201. tasklet_disable_nosync(&devp->isr_tasklet);
  202. // vdin_notify_receiver(VFRAME_EVENT_PROVIDER_UNREG,NULL ,NULL);
  203. //vf_notify_receiver(PROVIDER_NAME,VFRAME_EVENT_PROVIDER_UNREG,NULL);
  204. vdin_stop_dec(devp);
  205. }
  206. static int canvas_start_index = VDIN_START_CANVAS ;
  207. static int canvas_total_num = BT656IN_VF_POOL_SIZE;
  208. void set_tvin_canvas_info(int start , int num)
  209. {
  210. canvas_start_index = start;
  211. canvas_total_num = num;
  212. }
  213. void get_tvin_canvas_info(int* start , int* num)
  214. {
  215. *start = canvas_start_index ;
  216. *num = canvas_total_num;
  217. }
  218. /*as use the spin_lock,
  219. *1--there is no sleep,
  220. *2--it is better to shorter the time,
  221. *3--it is better to shorter the time,
  222. */
  223. static irqreturn_t vdin_isr(int irq, void *dev_id)
  224. {
  225. ulong flags, vdin_cur_irq_time;
  226. struct timeval now;
  227. struct vdin_dev_s *devp = (struct vdin_dev_s *)dev_id;
  228. spin_lock_irqsave(&devp->isr_lock, flags);
  229. do_gettimeofday(&now);
  230. vdin_cur_irq_time = (now.tv_sec*1000) + (now.tv_usec/1000);
  231. #ifdef VDIN_DBG_MSG_CNT
  232. vdin_dbg_msg.vdin_isr_hard_counter++;
  233. if((vdin_dbg_msg.vdin_isr_hard_counter % 3600) == 0)
  234. {
  235. pr_info("%s--vdin_dbg_msg :\n%d \n %d \n %d \n %d \n %d \n %d \n %d \n %d \n %d \n", __FUNCTION__,
  236. vdin_dbg_msg.vdin_isr_hard_counter,
  237. vdin_dbg_msg.vdin_tasklet_counter,
  238. vdin_dbg_msg.vdin_get_new_frame_cnt,
  239. vdin_dbg_msg.vdin_dec_run_none_cnt,
  240. vdin_dbg_msg.vdin_tasklet_invalid_type_cnt,
  241. vdin_dbg_msg.vdin_tasklet_valid_type_cnt,
  242. vdin_dbg_msg.vdin_from_video_recycle_cnt,
  243. vdin_dbg_msg.vdin_irq_short_time_cnt,
  244. vdin_dbg_msg.vdin_timer_puch_nf_cnt
  245. );
  246. }
  247. #endif
  248. if(time_after(vdin_cur_irq_time, devp->pre_irq_time))
  249. {
  250. if((vdin_cur_irq_time - devp->pre_irq_time) < 7) //short time
  251. {
  252. devp->pre_irq_time = vdin_cur_irq_time;
  253. #ifdef VDIN_DBG_MSG_CNT
  254. vdin_dbg_msg.vdin_irq_short_time_cnt++;
  255. #endif
  256. spin_unlock_irqrestore(&devp->isr_lock, flags);
  257. return IRQ_HANDLED;
  258. }
  259. }
  260. devp->pre_irq_time = vdin_cur_irq_time;
  261. tasklet_hi_schedule(&devp->isr_tasklet);
  262. spin_unlock_irqrestore(&devp->isr_lock, flags);
  263. return IRQ_HANDLED;
  264. }
  265. #include <linux/videodev2.h>
  266. extern int vm_fill_buffer(struct videobuf_buffer* vb , int format , int magic);
  267. static void vdin_isr_tasklet(unsigned long arg)
  268. {
  269. int ret = 0;
  270. vframe_t *vf = NULL;
  271. struct vdin_dev_s *devp = (struct vdin_dev_s*)arg;
  272. #ifdef VDIN_DBG_MSG_CNT
  273. vdin_dbg_msg.vdin_tasklet_counter++;
  274. #endif
  275. spin_lock(&devp->isr_lock);
  276. vf = vfq_pop_newframe();
  277. if(vf == NULL )
  278. {
  279. vfq_push_recycle(vf);
  280. spin_unlock(&devp->isr_lock);
  281. return;
  282. }
  283. #ifdef VDIN_DBG_MSG_CNT
  284. vdin_dbg_msg.vdin_get_new_frame_cnt++;
  285. #endif
  286. if (!devp->dec_ops || !devp->dec_ops->dec_run)
  287. {
  288. pr_err("vdin%d: no registered decode\n", devp->index);
  289. vfq_push_recycle(vf);
  290. #ifdef VDIN_DBG_MSG_CNT
  291. vdin_dbg_msg.vdin_dec_run_none_cnt++;
  292. #endif
  293. spin_unlock(&devp->isr_lock);
  294. return;
  295. }
  296. vf->type = INVALID_VDIN_INPUT;
  297. vf->pts = 0;
  298. ret = devp->dec_ops->dec_run(vf);
  299. if(vf->type == INVALID_VDIN_INPUT)
  300. {
  301. vfq_push_recycle(vf);
  302. #ifdef VDIN_DBG_MSG_CNT
  303. vdin_dbg_msg.vdin_tasklet_invalid_type_cnt++;
  304. #endif
  305. }
  306. else
  307. {
  308. vdin_set_vframe_prop_info(vf, devp->addr_offset);
  309. vfq_push_display(vf);
  310. // vdin_notify_receiver(VFRAME_EVENT_PROVIDER_VFRAME_READY,NULL ,NULL);
  311. vf_notify_receiver(PROVIDER_NAME,VFRAME_EVENT_PROVIDER_VFRAME_READY,NULL);
  312. #ifdef VDIN_DBG_MSG_CNT
  313. vdin_dbg_msg.vdin_tasklet_valid_type_cnt++;
  314. #endif
  315. }
  316. spin_unlock(&devp->isr_lock);
  317. }
  318. static int vdin_open(struct inode *inode, struct file *file)
  319. {
  320. vdin_dev_t *devp;
  321. /* Get the per-device structure that contains this cdev */
  322. devp = container_of(inode->i_cdev, vdin_dev_t, cdev);
  323. file->private_data = devp;
  324. if (devp->index >= VDIN_COUNT)
  325. return -ENXIO;
  326. return 0;
  327. }
  328. static int vdin_release(struct inode *inode, struct file *file)
  329. {
  330. vdin_dev_t *devp = file->private_data;
  331. file->private_data = NULL;
  332. //printk(KERN_INFO "vdin: device %d release ok.\n", devp->index);
  333. return 0;
  334. }
  335. static inline bool vdin_port_valid(enum tvin_port_e port)
  336. {
  337. bool ret = false;
  338. #if defined(CONFIG_ARCH_MESON)|| defined (CONFIG_ARCH_MESON3)|| defined(CONFIG_ARCH_MESON6)
  339. switch (port>>8)
  340. {
  341. case 0x01: // mpeg
  342. case 0x02: // 656
  343. case 0x80: // dvin
  344. ret = true;
  345. break;
  346. default:
  347. break;
  348. }
  349. #elif defined(CONFIG_ARCH_MESON2)
  350. switch (port>>8)
  351. {
  352. case 0x01: // mpeg
  353. case 0x02: // 656
  354. case 0x04: // VGA
  355. case 0x08: // COMPONENT
  356. case 0x10: // CVBS
  357. case 0x20: // SVIDEO
  358. case 0x40: // hdmi
  359. case 0x80: // dvin
  360. ret = true;
  361. default:
  362. break;
  363. }
  364. #endif
  365. return ret;
  366. }
  367. static int vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  368. {
  369. int ret = 0;
  370. vdin_dev_t *devp;
  371. void __user *argp = (void __user *)arg;
  372. struct inode *inode = file->f_dentry->d_inode;
  373. if (_IOC_TYPE(cmd) != TVIN_IOC_MAGIC) {
  374. return -EINVAL;
  375. }
  376. devp = container_of(inode->i_cdev, vdin_dev_t, cdev);
  377. switch (cmd)
  378. {
  379. case TVIN_IOC_START_DEC:
  380. {
  381. struct tvin_parm_s para;
  382. pr_info("vdin%d: TVIN_IOC_START_DEC (0x%x)\n", devp->index, devp->flags);
  383. if(devp->flags & VDIN_FLAG_DEC_STARTED)
  384. {
  385. pr_err("vdin%d: decode started already\n", devp->index);
  386. ret = -EINVAL;
  387. break;
  388. }
  389. if (copy_from_user(&para, argp, sizeof(struct tvin_parm_s)))
  390. {
  391. pr_err("vdin%d: invalid paramenter\n", devp->index);
  392. ret = -EFAULT;
  393. break;
  394. }
  395. if (!vdin_port_valid(para.port))
  396. {
  397. pr_err("vdin%d: not supported port 0x%x\n", devp->index, para.port);
  398. ret = -EFAULT;
  399. break;
  400. }
  401. //init vdin signal info
  402. devp->para.port = para.port;
  403. devp->para.fmt_info.fmt= para.fmt_info.fmt;
  404. devp->para.fmt_info.frame_rate= para.fmt_info.frame_rate;
  405. devp->para.fmt_info.h_active=para.fmt_info.h_active;
  406. devp->para.fmt_info.v_active=para.fmt_info.v_active;
  407. devp->para.fmt_info.reserved=para.fmt_info.reserved;
  408. devp->para.status = TVIN_SIG_STATUS_NULL;
  409. devp->para.cap_addr = 0x85100000;
  410. devp->flags |= VDIN_FLAG_DEC_STARTED;
  411. //printk("devp addr is %x",devp);
  412. //printk("addr_offset is %x",devp->addr_offset);
  413. vdin_start_dec(devp);
  414. pr_info("vdin%d: TVIN_IOC_START_DEC ok\n", devp->index);
  415. #if defined(CONFIG_ARCH_MESON2)
  416. vdin_set_meas_mux(devp->addr_offset, devp->para.port);
  417. #endif
  418. msleep(10);
  419. tasklet_enable(&devp->isr_tasklet);
  420. devp->pre_irq_time = jiffies,
  421. enable_irq(devp->irq);
  422. pr_info("TVIN_IOC_START_DEC ok, vdin%d_irq is enabled.\n", devp->index);
  423. break;
  424. }
  425. case TVIN_IOC_STOP_DEC:
  426. {
  427. pr_info("vdin%d: TVIN_IOC_STOP_DEC (flags:0x%x)\n", devp->index, devp->flags);
  428. if(!(devp->flags & VDIN_FLAG_DEC_STARTED))
  429. {
  430. pr_err("vdin%d: can't stop, decode havn't started\n", devp->index);
  431. ret = -EINVAL;
  432. break;
  433. }
  434. disable_irq_nosync(devp->irq);
  435. tasklet_disable_nosync(&devp->isr_tasklet);
  436. vdin_stop_dec(devp);
  437. devp->flags &= (~VDIN_FLAG_DEC_STARTED);
  438. break;
  439. }
  440. case TVIN_IOC_G_PARM:
  441. {
  442. if (copy_to_user((void __user *)arg, &devp->para, sizeof(struct tvin_parm_s)))
  443. {
  444. ret = -EFAULT;
  445. }
  446. break;
  447. }
  448. case TVIN_IOC_S_PARM:
  449. {
  450. struct tvin_parm_s para = {TVIN_PORT_NULL, {TVIN_SIG_FMT_NULL,0,0,0,0}, TVIN_SIG_STATUS_NULL, 0, 0, 0,0};
  451. if (copy_from_user(&para, argp, sizeof(struct tvin_parm_s)))
  452. {
  453. ret = -EFAULT;
  454. break;
  455. }
  456. //get tvin port selection and other setting
  457. devp->para.flag = para.flag;
  458. if(!(devp->para.flag & TVIN_PARM_FLAG_CAP))
  459. {
  460. devp->para.cap_addr = 0; //reset frame capture address 0 means null data
  461. devp->para.cap_size = 0;
  462. devp->para.canvas_index = 0;
  463. }
  464. if(devp->para.port != para.port)
  465. {
  466. //to do
  467. }
  468. break;
  469. }
  470. default:
  471. ret = -ENOIOCTLCMD;
  472. break;
  473. }
  474. return ret;
  475. }
  476. static int vdin_mmap(struct file *file, struct vm_area_struct * vma)
  477. {
  478. vdin_dev_t *devp = file->private_data;
  479. unsigned long off, pfn;
  480. unsigned long start, size;
  481. u32 len;
  482. if (!devp)
  483. {
  484. pr_err("%s: the device is not exist. \n", __func__);
  485. return -ENODEV;
  486. }
  487. if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
  488. {
  489. pr_err("%s: memory address is exist. \n", __func__);
  490. return -EINVAL;
  491. }
  492. if(!(devp->para.flag & TVIN_PARM_FLAG_CAP))
  493. {
  494. pr_err("%s: the capture flag is not set . \n", __func__);
  495. return -EINVAL;
  496. }
  497. /* if((devp->para.cap_addr == 0) || (devp->para.canvas_index == 0))
  498. {
  499. pr_err("%s: the capture address is invalid . \n", __func__);
  500. return -EINVAL;
  501. }
  502. pr_info("cap_addr = 0x%x; cap_size = %d\n", devp->para.cap_addr, devp->para.cap_size);
  503. */
  504. off = vma->vm_pgoff << PAGE_SHIFT;
  505. mutex_lock(&devp->mm_lock);
  506. start = devp->para.cap_addr;
  507. len = PAGE_ALIGN((start & ~PAGE_MASK) + devp->para.cap_size);
  508. mutex_unlock(&devp->mm_lock);
  509. start &= PAGE_MASK;
  510. if ((vma->vm_end - vma->vm_start + off) > len)
  511. {
  512. pr_err("%s: memory address is overflow. \n", __func__);
  513. return -EINVAL;
  514. }
  515. off += start;
  516. vma->vm_pgoff = off >> PAGE_SHIFT;
  517. vma->vm_flags |= VM_IO | VM_RESERVED;
  518. size = vma->vm_end - vma->vm_start;
  519. pfn = off >> PAGE_SHIFT;
  520. if (io_remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot))
  521. {
  522. pr_err("%s: remap is failing. \n", __func__);
  523. return -EAGAIN;
  524. }
  525. return 0;
  526. }
  527. static struct file_operations vdin_fops = {
  528. .owner = THIS_MODULE,
  529. .open = vdin_open,
  530. .release = vdin_release,
  531. .unlocked_ioctl = vdin_ioctl,
  532. .mmap = vdin_mmap,
  533. };
  534. static int vdin_probe(struct platform_device *pdev)
  535. {
  536. int ret;
  537. int i;
  538. struct device *devp;
  539. struct resource *res;
  540. char name[12];
  541. ret = alloc_chrdev_region(&vdin_devno, 0, VDIN_COUNT, VDIN_NAME);
  542. if (ret < 0) {
  543. printk(KERN_ERR "vdin: failed to allocate major number\n");
  544. return 0;
  545. }
  546. vdin_clsp = class_create(THIS_MODULE, VDIN_NAME);
  547. if (IS_ERR(vdin_clsp))
  548. {
  549. unregister_chrdev_region(vdin_devno, VDIN_COUNT);
  550. return PTR_ERR(vdin_clsp);
  551. }
  552. for (i = 0; i < VDIN_COUNT; ++i)
  553. {
  554. /* allocate memory for the per-device structure */
  555. vdin_devp[i] = kmalloc(sizeof(struct vdin_dev_s), GFP_KERNEL);
  556. if (!vdin_devp[i])
  557. {
  558. printk(KERN_ERR "vdin: failed to allocate memory for vdin device\n");
  559. return -ENOMEM;
  560. }
  561. vdin_devp[i]->index = i;
  562. vdin_devp[i]->dec_lock = __SPIN_LOCK_UNLOCKED(vdin_devp[i]->dec_lock);
  563. vdin_devp[i]->dec_ops = NULL;
  564. /* connect the file operations with cdev */
  565. cdev_init(&vdin_devp[i]->cdev, &vdin_fops);
  566. vdin_devp[i]->cdev.owner = THIS_MODULE;
  567. /* connect the major/minor number to the cdev */
  568. ret = cdev_add(&vdin_devp[i]->cdev, (vdin_devno + i), 1);
  569. if (ret) {
  570. printk(KERN_ERR "vdin: failed to add device\n");
  571. /* @todo do with error */
  572. return ret;
  573. }
  574. /* create /dev nodes */
  575. devp = device_create(vdin_clsp, NULL, MKDEV(MAJOR(vdin_devno), i),
  576. NULL, "vdin%d", i);
  577. if (IS_ERR(devp)) {
  578. printk(KERN_ERR "vdin: failed to create device node\n");
  579. class_destroy(vdin_clsp);
  580. /* @todo do with error */
  581. return PTR_ERR(devp);;
  582. }
  583. /* get device memory */
  584. res = platform_get_resource(pdev, IORESOURCE_MEM, i);
  585. if (!res) {
  586. printk(KERN_ERR "vdin: can't get memory resource\n");
  587. return -EFAULT;
  588. }
  589. vdin_devp[i]->mem_start = res->start;
  590. vdin_devp[i]->mem_size = res->end - res->start + 1;
  591. pr_info(" vdin[%d] memory start addr is %x, mem_size is %x . \n",i,
  592. vdin_devp[i]->mem_start,vdin_devp[i]->mem_size);
  593. /* get device irq */
  594. res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
  595. if (!res) {
  596. printk(KERN_ERR "vdin: can't get memory resource\n");
  597. return -EFAULT;
  598. }
  599. vdin_devp[i]->irq = res->start;
  600. vdin_devp[i]->flags = VDIN_FLAG_NULL;
  601. pr_info("vdin%d: flags:0x%x\n", vdin_devp[i]->index, vdin_devp[i]->flags);
  602. vdin_devp[i]->addr_offset = vdin_addr_offset[i];
  603. vdin_devp[i]->para.flag = 0;
  604. sprintf(name, "vdin%d-irq", i);
  605. /* register vdin irq */
  606. ret = request_irq(vdin_devp[i]->irq, vdin_isr, IRQF_SHARED, name, (void *)vdin_devp[i]);
  607. if (ret) {
  608. printk(KERN_ERR "vdin: irq regist error.\n");
  609. return -ENOENT;
  610. }
  611. disable_irq(vdin_devp[i]->irq);
  612. init_timer(&vdin_devp[i]->timer);
  613. vdin_devp[i]->timer.data = (ulong) &vdin_devp[i]->timer;
  614. vdin_devp[i]->timer.function = vdin_put_timer_func;
  615. vdin_devp[i]->timer.expires = jiffies + VDIN_PUT_INTERVAL * 50;
  616. add_timer(&vdin_devp[i]->timer);
  617. mutex_init(&vdin_devp[i]->mm_lock);
  618. vdin_devp[i]->isr_lock = __SPIN_LOCK_UNLOCKED(vdin_devp[i]->isr_lock);
  619. tasklet_init(&vdin_devp[i]->isr_tasklet, vdin_isr_tasklet, (unsigned long)vdin_devp[i]);
  620. tasklet_disable(&vdin_devp[i]->isr_tasklet);
  621. }
  622. printk(KERN_INFO "vdin: driver initialized ok\n");
  623. return 0;
  624. }
  625. static int vdin_remove(struct platform_device *pdev)
  626. {
  627. int i = 0;
  628. for (i = 0; i < VDIN_COUNT; ++i)
  629. {
  630. mutex_destroy(&(vdin_devp[i]->mm_lock));
  631. tasklet_kill(&vdin_devp[i]->isr_tasklet);
  632. del_timer_sync(&vdin_devp[i]->timer);
  633. free_irq(vdin_devp[i]->irq,(void *)vdin_devp[i]);
  634. del_timer(&vdin_devp[i]->timer);
  635. device_destroy(vdin_clsp, MKDEV(MAJOR(vdin_devno), i));
  636. cdev_del(&vdin_devp[i]->cdev);
  637. kfree(vdin_devp[i]);
  638. }
  639. class_destroy(vdin_clsp);
  640. unregister_chrdev_region(vdin_devno, VDIN_COUNT);
  641. printk(KERN_ERR "vdin: driver removed ok.\n");
  642. return 0;
  643. }
  644. static struct platform_driver vdin_driver = {
  645. .probe = vdin_probe,
  646. .remove = vdin_remove,
  647. .driver = {
  648. .name = VDIN_DRIVER_NAME,
  649. }
  650. };
  651. static int __init vdin_init(void)
  652. {
  653. int ret = 0;
  654. ret = platform_driver_register(&vdin_driver);
  655. if (ret != 0) {
  656. printk(KERN_ERR "failed to register vdin module, error %d\n", ret);
  657. return -ENODEV;
  658. }
  659. return ret;
  660. }
  661. static void __exit vdin_exit(void)
  662. {
  663. platform_driver_unregister(&vdin_driver);
  664. }
  665. module_init(vdin_init);
  666. module_exit(vdin_exit);
  667. MODULE_DESCRIPTION("AMLOGIC VDIN driver");
  668. MODULE_LICENSE("GPL");
  669. MODULE_AUTHOR("Xu Lin <lin.xu@amlogic.com>");