Advertisement
Guest User

patch for ax206fb

a guest
May 2nd, 2012
338
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 37.17 KB | None | 0 0
  1. diff -Nuar spfb//ax206fb.c ax206fb//ax206fb.c
  2. --- spfb//ax206fb.c 1970-01-01 07:30:00.000000000 +0730
  3. +++ ax206fb//ax206fb.c  2012-04-30 19:50:37.357391119 +0800
  4. @@ -0,0 +1,698 @@
  5. +/*
  6. + *  ax206fb.c
  7. + *
  8. + *  Samsung Picture Frame Buffer
  9. + *
  10. + *      This file is subject to the terms and conditions of the GNU General
  11. + *      Public License.  See the file COPYING in the main directory of this
  12. + *      archive for more details.
  13. + *
  14. + *     This is an virtal frame buffer driver based on
  15. + *      linux/drivers/video/vfb.c.
  16. + *
  17. + *  README:
  18. + *    
  19. + *  This is a virtual framebuffer driver written for Samsung Picture Frames (like
  20. + *  the Samsung SPF-85H). These frames can be used as a litte USB monitor. So one
  21. + *  can send JPEG encoded pictures to them.
  22. + *
  23. + *  However, as it is not a good idea to have a JPEG encoder running in kernelspace
  24. + *  we need an additional userspace application which does the JPEG frame encoding.
  25. + *  Furthermore this app also sends the encoded image via libusb to the frame.
  26. + *
  27. + *  The cool thing about this driver is the efficiant implementation of the
  28. + *  reader/writer paradigm in order to circumvent periodic, CPU intensive FB refreshs.
  29. + *
  30. + *  The userland deamon performs a blocking read on /sys/kernel/debug/ax206fb. When ever
  31. + *  an application writes something to the framebuffer (via the character dev),
  32. + *  the read call returns and the FB can be refreshed.
  33. + *
  34. + *  This works perfect if for instance the application mmap's the framebuffer and
  35. + *  performs a single write on the character device.
  36. + *  However it can cause problems when an application just uses the character device
  37. + *  and does many write calls at once as each of them causes on refresh.
  38. + *
  39. + */
  40. +
  41. +#include <linux/module.h>
  42. +#include <linux/kernel.h>
  43. +#include <linux/errno.h>
  44. +#include <linux/string.h>
  45. +#include <linux/mm.h>
  46. +#include <linux/slab.h>
  47. +#include <linux/vmalloc.h>
  48. +#include <linux/delay.h>
  49. +#include <linux/interrupt.h>
  50. +#include <linux/platform_device.h>
  51. +#include <linux/uaccess.h>
  52. +#include <linux/debugfs.h>
  53. +#include <linux/pid.h>
  54. +#include <linux/wait.h>
  55. +
  56. +#include <linux/fb.h>
  57. +#include <linux/init.h>
  58. +
  59. +/*
  60. + *  RAM we reserve for the frame buffer. This defines the maximum screen
  61. + *  size
  62. + *
  63. + *  The default can be overridden if the driver is compiled as a module
  64. + */
  65. +#define VIDEOMEMSIZE   (2*1024*1024)   /* 2 MB */
  66. +
  67. +static void *videomemory;
  68. +static u_long videomemorysize = VIDEOMEMSIZE;
  69. +module_param(videomemorysize, ulong, 0);
  70. +
  71. +/**********************************************************************
  72. + *
  73. + * Memory management
  74. + *
  75. + **********************************************************************/
  76. +static void *rvmalloc(unsigned long size)
  77. +{
  78. +   void *mem;
  79. +   unsigned long adr;
  80. +
  81. +   size = PAGE_ALIGN(size);
  82. +   mem = vmalloc_32(size);
  83. +   if (!mem)
  84. +       return NULL;
  85. +
  86. +   memset(mem, 0, size); /* Clear the ram out, no junk to the user */
  87. +   adr = (unsigned long) mem;
  88. +   while (size > 0) {
  89. +       SetPageReserved(vmalloc_to_page((void *)adr));
  90. +       adr += PAGE_SIZE;
  91. +       size -= PAGE_SIZE;
  92. +   }
  93. +
  94. +   return mem;
  95. +}
  96. +
  97. +static void rvfree(void *mem, unsigned long size)
  98. +{
  99. +   unsigned long adr;
  100. +
  101. +   if (!mem)
  102. +       return;
  103. +
  104. +   adr = (unsigned long) mem;
  105. +   while ((long) size > 0) {
  106. +       ClearPageReserved(vmalloc_to_page((void *)adr));
  107. +       adr += PAGE_SIZE;
  108. +       size -= PAGE_SIZE;
  109. +   }
  110. +   vfree(mem);
  111. +}
  112. +
  113. +
  114. +static struct fb_var_screeninfo ax206fb_default __initdata = {
  115. +   .xres =     128,
  116. +   .yres =     128,
  117. +   .xres_virtual = 128,
  118. +   .yres_virtual = 128,
  119. +   .bits_per_pixel = 16,
  120. +   .red =      { 0, 8, 0 },
  121. +   .green =    { 0, 8, 0 },
  122. +   .blue =     { 0, 8, 0 },
  123. +   .activate = FB_ACTIVATE_NOW, //FB_ACTIVATE_TEST,
  124. +   .height =   -1,
  125. +   .width =    -1,
  126. +   .vmode =    FB_VMODE_NONINTERLACED,
  127. +};
  128. +
  129. +static struct fb_fix_screeninfo ax206fb_fix __initdata = {
  130. +   .id =           "AX206 DPF Frame Buffer",
  131. +   .type =         FB_TYPE_PACKED_PIXELS,
  132. +   .visual =       FB_VISUAL_PSEUDOCOLOR,
  133. +   .xpanstep =     1,
  134. +   .ypanstep =     1,
  135. +   .ywrapstep =    1,
  136. +   .accel =        FB_ACCEL_NONE,
  137. +};
  138. +
  139. +
  140. +/* function prototypes */
  141. +static ssize_t ax206fb_read_sysfs(struct file *file, char __user *user, size_t count, loff_t *ppos);                                
  142. +
  143. +static int ax206fb_check_var(struct fb_var_screeninfo *var,
  144. +            struct fb_info *info);
  145. +static int ax206fb_set_par(struct fb_info *info);
  146. +static int ax206fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  147. +            u_int transp, struct fb_info *info);
  148. +static int ax206fb_pan_display(struct fb_var_screeninfo *var,
  149. +              struct fb_info *info);
  150. +static int ax206fb_mmap(struct fb_info *info,
  151. +           struct vm_area_struct *vma);
  152. +
  153. +
  154. +struct dentry *ax206fb_debugfs_entry;
  155. +
  156. +static const struct file_operations ax206fb_sysfs_fops = {
  157. +   .read = ax206fb_read_sysfs,
  158. +};
  159. +
  160. +
  161. +static DECLARE_WAIT_QUEUE_HEAD(wq);
  162. +static int wq_flag = 0;
  163. +
  164. +
  165. +static ssize_t ax206fb_read_sysfs(struct file *file, char __user *user, size_t count, loff_t *ppos)
  166. +{
  167. +   char buf[] = "|";
  168. +  
  169. +   wait_event_interruptible(wq, wq_flag != 0);
  170. +   wq_flag = 0;
  171. +  
  172. +   return simple_read_from_buffer(user, count, ppos, buf, 1);
  173. +}
  174. +
  175. +
  176. +static ssize_t ax206fb_write(struct fb_info *info, const char __user *buf,
  177. +               size_t count, loff_t *ppos)
  178. +{
  179. +   unsigned long p = *ppos;
  180. +   void *dst;
  181. +   int err = 0;
  182. +   unsigned long total_size;
  183. +
  184. +   if (info->state != FBINFO_STATE_RUNNING)
  185. +       return -EPERM;
  186. +
  187. +   total_size = info->fix.smem_len;
  188. +
  189. +   if (p > total_size)
  190. +       return -EFBIG;
  191. +
  192. +   if (count > total_size) {
  193. +       err = -EFBIG;
  194. +       count = total_size;
  195. +   }
  196. +
  197. +   if (count + p > total_size) {
  198. +       if (!err)
  199. +           err = -ENOSPC;
  200. +
  201. +       count = total_size - p;
  202. +   }
  203. +
  204. +   dst = (void __force *) (info->screen_base + p);
  205. +
  206. +   if (copy_from_user(dst, buf, count))
  207. +       err = -EFAULT;
  208. +
  209. +   if  (!err)
  210. +       *ppos += count;
  211. +      
  212. +   /* wake userspace process, so fb can be written to display */
  213. +   wq_flag = 1;
  214. +   wake_up_interruptible(&wq);
  215. +
  216. +   return (err) ? err : count;
  217. +}
  218. +
  219. +
  220. +static struct fb_ops ax206fb_ops = {
  221. +   .fb_read        = fb_sys_read,
  222. +   .fb_write       = ax206fb_write,
  223. +   .fb_check_var   = ax206fb_check_var,
  224. +   .fb_set_par     = ax206fb_set_par,
  225. +   .fb_setcolreg   = ax206fb_setcolreg,
  226. +   .fb_pan_display = ax206fb_pan_display,
  227. +   .fb_fillrect    = sys_fillrect,
  228. +   .fb_copyarea    = sys_copyarea,
  229. +   .fb_imageblit   = sys_imageblit,
  230. +   .fb_mmap        = ax206fb_mmap,
  231. +};
  232. +
  233. +/*
  234. + *  Internal routines
  235. + */
  236. +static u_long get_line_length(int xres_virtual, int bpp)
  237. +{
  238. +   u_long length;
  239. +
  240. +   length = xres_virtual * bpp;
  241. +   length = (length + 31) & ~31;
  242. +   length >>= 3;
  243. +   return (length);
  244. +}
  245. +
  246. +/*
  247. + *  Setting the video mode has been split into two parts.
  248. + *  First part, xxxfb_check_var, must not write anything
  249. + *  to hardware, it should only verify and adjust var.
  250. + *  This means it doesn't alter par but it does use hardware
  251. + *  data from it to check this var.
  252. + */
  253. +static int ax206fb_check_var(struct fb_var_screeninfo *var,
  254. +            struct fb_info *info)
  255. +{
  256. +   u_long line_length;
  257. +
  258. +   /*
  259. +    *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
  260. +    *  as FB_VMODE_SMOOTH_XPAN is only used internally
  261. +    */
  262. +
  263. +   if (var->vmode & FB_VMODE_CONUPDATE) {
  264. +       var->vmode |= FB_VMODE_YWRAP;
  265. +       var->xoffset = info->var.xoffset;
  266. +       var->yoffset = info->var.yoffset;
  267. +   }
  268. +
  269. +   /*
  270. +    *  Some very basic checks
  271. +    */
  272. +   if (!var->xres)
  273. +       var->xres = 1;
  274. +   if (!var->yres)
  275. +       var->yres = 1;
  276. +   if (var->xres > var->xres_virtual)
  277. +       var->xres_virtual = var->xres;
  278. +   if (var->yres > var->yres_virtual)
  279. +       var->yres_virtual = var->yres;
  280. +   if (var->bits_per_pixel <= 1)
  281. +       var->bits_per_pixel = 1;
  282. +   else if (var->bits_per_pixel <= 8)
  283. +       var->bits_per_pixel = 8;
  284. +   else if (var->bits_per_pixel <= 16)
  285. +       var->bits_per_pixel = 16;
  286. +   else if (var->bits_per_pixel <= 24)
  287. +       var->bits_per_pixel = 24;
  288. +   else if (var->bits_per_pixel <= 32)
  289. +       var->bits_per_pixel = 32;
  290. +   else
  291. +       return -EINVAL;
  292. +
  293. +   if (var->xres_virtual < var->xoffset + var->xres)
  294. +       var->xres_virtual = var->xoffset + var->xres;
  295. +   if (var->yres_virtual < var->yoffset + var->yres)
  296. +       var->yres_virtual = var->yoffset + var->yres;
  297. +
  298. +   /*
  299. +    *  Memory limit
  300. +    */
  301. +   line_length =
  302. +       get_line_length(var->xres_virtual, var->bits_per_pixel);
  303. +   if (line_length * var->yres_virtual > videomemorysize)
  304. +       return -ENOMEM;
  305. +
  306. +   /*
  307. +    * Now that we checked it we alter var. The reason being is that the video
  308. +    * mode passed in might not work but slight changes to it might make it
  309. +    * work. This way we let the user know what is acceptable.
  310. +    */
  311. +   switch (var->bits_per_pixel) {
  312. +   case 1:
  313. +   case 8:
  314. +       var->red.offset = 0;
  315. +       var->red.length = 8;
  316. +       var->green.offset = 0;
  317. +       var->green.length = 8;
  318. +       var->blue.offset = 0;
  319. +       var->blue.length = 8;
  320. +       var->transp.offset = 0;
  321. +       var->transp.length = 0;
  322. +       break;
  323. +   case 16:        /* RGBA 5551 */
  324. +       if (var->transp.length) {
  325. +           var->red.offset = 0;
  326. +           var->red.length = 5;
  327. +           var->green.offset = 5;
  328. +           var->green.length = 5;
  329. +           var->blue.offset = 10;
  330. +           var->blue.length = 5;
  331. +           var->transp.offset = 15;
  332. +           var->transp.length = 1;
  333. +       } else {    /* RGB 565 */
  334. +           var->red.offset = 0;
  335. +           var->red.length = 5;
  336. +           var->green.offset = 5;
  337. +           var->green.length = 6;
  338. +           var->blue.offset = 11;
  339. +           var->blue.length = 5;
  340. +           var->transp.offset = 0;
  341. +           var->transp.length = 0;
  342. +       }
  343. +       break;
  344. +   case 24:        /* RGB 888 */
  345. +       var->red.offset = 0;
  346. +       var->red.length = 8;
  347. +       var->green.offset = 8;
  348. +       var->green.length = 8;
  349. +       var->blue.offset = 16;
  350. +       var->blue.length = 8;
  351. +       var->transp.offset = 0;
  352. +       var->transp.length = 0;
  353. +       break;
  354. +   case 32:        /* RGBA 8888 */
  355. +       var->red.offset = 0;
  356. +       var->red.length = 8;
  357. +       var->green.offset = 8;
  358. +       var->green.length = 8;
  359. +       var->blue.offset = 16;
  360. +       var->blue.length = 8;
  361. +       var->transp.offset = 24;
  362. +       var->transp.length = 8;
  363. +       break;
  364. +   }
  365. +   var->red.msb_right = 0;
  366. +   var->green.msb_right = 0;
  367. +   var->blue.msb_right = 0;
  368. +   var->transp.msb_right = 0;
  369. +
  370. +   return 0;
  371. +}
  372. +
  373. +/* This routine actually sets the video mode. It's in here where we
  374. + * the hardware state info->par and fix which can be affected by the
  375. + * change in par. For this driver it doesn't do much.
  376. + */
  377. +static int ax206fb_set_par(struct fb_info *info)
  378. +{
  379. +   info->fix.line_length = get_line_length(info->var.xres_virtual,
  380. +                       info->var.bits_per_pixel);
  381. +   return 0;
  382. +}
  383. +
  384. +/*
  385. + *  Set a single color register. The values supplied are already
  386. + *  rounded down to the hardware's capabilities (according to the
  387. + *  entries in the var structure). Return != 0 for invalid regno.
  388. + */
  389. +static int ax206fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  390. +            u_int transp, struct fb_info *info)
  391. +{
  392. +   if (regno >= 256)   /* no. of hw registers */
  393. +       return 1;
  394. +   /*
  395. +    * Program hardware... do anything you want with transp
  396. +    */
  397. +
  398. +   /* grayscale works only partially under directcolor */
  399. +   if (info->var.grayscale) {
  400. +       /* grayscale = 0.30*R + 0.59*G + 0.11*B */
  401. +       red = green = blue =
  402. +           (red * 77 + green * 151 + blue * 28) >> 8;
  403. +   }
  404. +
  405. +   /* Directcolor:
  406. +    *   var->{color}.offset contains start of bitfield
  407. +    *   var->{color}.length contains length of bitfield
  408. +    *   {hardwarespecific} contains width of RAMDAC
  409. +    *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
  410. +    *   RAMDAC[X] is programmed to (red, green, blue)
  411. +    *
  412. +    * Pseudocolor:
  413. +    *    var->{color}.offset is 0 unless the palette index takes less than
  414. +    *                        bits_per_pixel bits and is stored in the upper
  415. +    *                        bits of the pixel value
  416. +    *    var->{color}.length is set so that 1 << length is the number of available
  417. +    *                        palette entries
  418. +    *    cmap is not used
  419. +    *    RAMDAC[X] is programmed to (red, green, blue)
  420. +    *
  421. +    * Truecolor:
  422. +    *    does not use DAC. Usually 3 are present.
  423. +    *    var->{color}.offset contains start of bitfield
  424. +    *    var->{color}.length contains length of bitfield
  425. +    *    cmap is programmed to (red << red.offset) | (green << green.offset) |
  426. +    *                      (blue << blue.offset) | (transp << transp.offset)
  427. +    *    RAMDAC does not exist
  428. +    */
  429. +#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
  430. +   switch (info->fix.visual) {
  431. +   case FB_VISUAL_TRUECOLOR:
  432. +   case FB_VISUAL_PSEUDOCOLOR:
  433. +       red = CNVT_TOHW(red, info->var.red.length);
  434. +       green = CNVT_TOHW(green, info->var.green.length);
  435. +       blue = CNVT_TOHW(blue, info->var.blue.length);
  436. +       transp = CNVT_TOHW(transp, info->var.transp.length);
  437. +       break;
  438. +   case FB_VISUAL_DIRECTCOLOR:
  439. +       red = CNVT_TOHW(red, 8);    /* expect 8 bit DAC */
  440. +       green = CNVT_TOHW(green, 8);
  441. +       blue = CNVT_TOHW(blue, 8);
  442. +       /* hey, there is bug in transp handling... */
  443. +       transp = CNVT_TOHW(transp, 8);
  444. +       break;
  445. +   }
  446. +#undef CNVT_TOHW
  447. +   /* Truecolor has hardware independent palette */
  448. +   if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
  449. +       u32 v;
  450. +
  451. +       if (regno >= 16)
  452. +           return 1;
  453. +
  454. +       v = (red << info->var.red.offset) |
  455. +           (green << info->var.green.offset) |
  456. +           (blue << info->var.blue.offset) |
  457. +           (transp << info->var.transp.offset);
  458. +       switch (info->var.bits_per_pixel) {
  459. +       case 8:
  460. +           break;
  461. +       case 16:
  462. +           ((u32 *) (info->pseudo_palette))[regno] = v;
  463. +           break;
  464. +       case 24:
  465. +       case 32:
  466. +           ((u32 *) (info->pseudo_palette))[regno] = v;
  467. +           break;
  468. +       }
  469. +       return 0;
  470. +   }
  471. +   return 0;
  472. +}
  473. +
  474. +/*
  475. + *  Pan or Wrap the Display
  476. + *
  477. + *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
  478. + */
  479. +static int ax206fb_pan_display(struct fb_var_screeninfo *var,
  480. +              struct fb_info *info)
  481. +{
  482. +   if (var->vmode & FB_VMODE_YWRAP) {
  483. +       if (var->yoffset < 0
  484. +           || var->yoffset >= info->var.yres_virtual
  485. +           || var->xoffset)
  486. +           return -EINVAL;
  487. +   } else {
  488. +       if (var->xoffset + var->xres > info->var.xres_virtual ||
  489. +           var->yoffset + var->yres > info->var.yres_virtual)
  490. +           return -EINVAL;
  491. +   }
  492. +   info->var.xoffset = var->xoffset;
  493. +   info->var.yoffset = var->yoffset;
  494. +   if (var->vmode & FB_VMODE_YWRAP)
  495. +       info->var.vmode |= FB_VMODE_YWRAP;
  496. +   else
  497. +       info->var.vmode &= ~FB_VMODE_YWRAP;
  498. +   return 0;
  499. +}
  500. +
  501. +/*
  502. + *  Most drivers don't need their own mmap function
  503. + */
  504. +static int ax206fb_mmap(struct fb_info *info,
  505. +           struct vm_area_struct *vma)
  506. +{
  507. +   unsigned long start = vma->vm_start;
  508. +   unsigned long size = vma->vm_end - vma->vm_start;
  509. +   unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
  510. +   unsigned long page, pos;
  511. +
  512. +   if (offset + size > info->fix.smem_len) {
  513. +       return -EINVAL;
  514. +   }
  515. +
  516. +   pos = (unsigned long)info->fix.smem_start + offset;
  517. +
  518. +   while (size > 0) {
  519. +       page = vmalloc_to_pfn((void *)pos);
  520. +       if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
  521. +           return -EAGAIN;
  522. +       }
  523. +       start += PAGE_SIZE;
  524. +       pos += PAGE_SIZE;
  525. +       if (size > PAGE_SIZE)
  526. +           size -= PAGE_SIZE;
  527. +       else
  528. +           size = 0;
  529. +   }
  530. +
  531. +   vma->vm_flags |= VM_RESERVED;   /* avoid to swap out this VMA */
  532. +   return 0;
  533. +
  534. +}
  535. +
  536. +#ifndef MODULE
  537. +/*
  538. + * The virtual framebuffer driver is only enabled if explicitly
  539. + * requested by passing 'video=vfb:' (or any actual options).
  540. + */
  541. +static int __init ax206fb_setup(char *options)
  542. +{
  543. +   char *this_opt;
  544. +
  545. +   if (!options)
  546. +       return 1;
  547. +
  548. +
  549. +   if (!*options)
  550. +       return 1;
  551. +
  552. +   while ((this_opt = strsep(&options, ",")) != NULL) {
  553. +       if (!*this_opt)
  554. +           continue;
  555. +   }
  556. +   return 1;
  557. +}
  558. +#endif  /*  MODULE  */
  559. +
  560. +/*
  561. + *  Initialisation
  562. + */
  563. +static int __init ax206fb_probe(struct platform_device *dev)
  564. +{
  565. +   struct fb_info *info;
  566. +   int retval = -ENOMEM;
  567. +
  568. +   /*
  569. +    * For real video cards we use ioremap.
  570. +    */
  571. +   if (!(videomemory = rvmalloc(videomemorysize)))
  572. +       return retval;
  573. +
  574. +   /*
  575. +    * VFB must clear memory to prevent kernel info
  576. +    * leakage into userspace
  577. +    * VGA-based drivers MUST NOT clear memory if
  578. +    * they want to be able to take over vgacon
  579. +    */
  580. +   memset(videomemory, 0, videomemorysize);
  581. +
  582. +   info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
  583. +   if (!info)
  584. +       goto err;
  585. +
  586. +   info->screen_base = (char __iomem *)videomemory;
  587. +   info->fbops = &ax206fb_ops;
  588. +
  589. +   info->var = ax206fb_default;
  590. +   ax206fb_fix.smem_start = (unsigned long) videomemory;
  591. +   ax206fb_fix.smem_len = videomemorysize;
  592. +   info->fix = ax206fb_fix;
  593. +   info->pseudo_palette = info->par;
  594. +   info->par = NULL;
  595. +   info->flags = FBINFO_FLAG_DEFAULT;
  596. +
  597. +   retval = fb_alloc_cmap(&info->cmap, 256, 0);
  598. +   if (retval < 0)
  599. +       goto err1;
  600. +
  601. +   retval = register_framebuffer(info);
  602. +   if (retval < 0)
  603. +       goto err2;
  604. +   platform_set_drvdata(dev, info);
  605. +
  606. +   printk(KERN_INFO
  607. +          "fb%d: AX206 Picture Frame frame buffer device created, using %ldK of video memory\n",
  608. +          info->node, videomemorysize >> 10);
  609. +   return 0;
  610. +err2:
  611. +   fb_dealloc_cmap(&info->cmap);
  612. +err1:
  613. +   framebuffer_release(info);
  614. +err:
  615. +   rvfree(videomemory, videomemorysize);
  616. +   return retval;
  617. +}
  618. +
  619. +static int ax206fb_remove(struct platform_device *dev)
  620. +{
  621. +   struct fb_info *info = platform_get_drvdata(dev);
  622. +
  623. +   if (info) {
  624. +       unregister_framebuffer(info);
  625. +       rvfree(videomemory, videomemorysize);
  626. +       fb_dealloc_cmap(&info->cmap);
  627. +       framebuffer_release(info);
  628. +   }
  629. +   return 0;
  630. +}
  631. +
  632. +
  633. +
  634. +
  635. +static struct platform_driver ax206fb_driver = {
  636. +   .probe  = ax206fb_probe,
  637. +   .remove = ax206fb_remove,
  638. +   .driver = {
  639. +       .name   = "ax206fb",
  640. +   },
  641. +};
  642. +
  643. +static struct platform_device *ax206fb_device;
  644. +
  645. +static int __init ax206fb_init(void)
  646. +{
  647. +   int ret = 0;
  648. +
  649. +#ifndef MODULE
  650. +   char *option = NULL;
  651. +
  652. +   if (fb_get_options("ax206fb", &option))
  653. +       return -ENODEV;
  654. +   ax206fb_setup(option);
  655. +#endif
  656. +
  657. +   ret = platform_driver_register(&ax206fb_driver);
  658. +   if (!ret) {
  659. +       ax206fb_device = platform_device_alloc("ax206fb", 0);
  660. +
  661. +       if (ax206fb_device)
  662. +           ret = platform_device_add(ax206fb_device);
  663. +       else
  664. +           ret = -ENOMEM;
  665. +
  666. +       if (ret) {
  667. +           platform_device_put(ax206fb_device);
  668. +           platform_driver_unregister(&ax206fb_driver);
  669. +       }
  670. +   }
  671. +  
  672. +   /* create debugfs entry */
  673. +   ax206fb_debugfs_entry = debugfs_create_file("ax206fb", 0444, NULL, NULL, &ax206fb_sysfs_fops);
  674. +
  675. +   return ret;
  676. +}
  677. +
  678. +module_init(ax206fb_init);
  679. +
  680. +#ifdef MODULE
  681. +static void __exit ax206fb_exit(void)
  682. +{
  683. +   /* cleanup and exit */ 
  684. +   platform_device_unregister(ax206fb_device);
  685. +   platform_driver_unregister(&ax206fb_driver);
  686. +  
  687. +   debugfs_remove(ax206fb_debugfs_entry);
  688. +  
  689. +   printk(KERN_INFO "ax206fb module unloaded\n");
  690. +}
  691. +
  692. +module_exit(ax206fb_exit);
  693. +
  694. +MODULE_LICENSE("GPL");
  695. +#endif /* MODULE */
  696. +
  697. +
  698. +
  699. +
  700. +
  701. +
  702. +
  703. diff -Nuar spfb//load_mods.sh ax206fb//load_mods.sh
  704. --- spfb//load_mods.sh  2010-10-26 00:36:30.000000000 +0800
  705. +++ ax206fb//load_mods.sh   2012-05-02 20:01:41.934968654 +0800
  706. @@ -3,4 +3,4 @@
  707.  modprobe sysimgblt
  708.  modprobe syscopyarea
  709.  modprobe fb_sys_fops
  710. -insmod ./spfb.ko
  711. +insmod ./ax206fb.ko
  712. diff -Nuar spfb//Makefile ax206fb//Makefile
  713. --- spfb//Makefile  2010-08-03 03:53:44.000000000 +0800
  714. +++ ax206fb//Makefile   2012-05-01 09:51:40.005880764 +0800
  715. @@ -1,7 +1,7 @@
  716. -obj-m += spfb.o
  717. +obj-m += ax206fb.o
  718.  
  719.  all:
  720. -   make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
  721. +   make -C /usr/src/linux-3.3.2 M=$(PWD) modules
  722.  
  723.  clean:
  724.     make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  725. diff -Nuar spfb//spfb.c ax206fb//spfb.c
  726. --- spfb//spfb.c    2010-11-01 02:14:48.000000000 +0800
  727. +++ ax206fb//spfb.c 1970-01-01 07:30:00.000000000 +0730
  728. @@ -1,698 +0,0 @@
  729. -/*
  730. - *  spfb.c
  731. - *
  732. - *  Samsung Picture Frame Buffer
  733. - *
  734. - *      This file is subject to the terms and conditions of the GNU General
  735. - *      Public License.  See the file COPYING in the main directory of this
  736. - *      archive for more details.
  737. - *
  738. - *     This is an virtal frame buffer driver based on
  739. - *      linux/drivers/video/vfb.c.
  740. - *
  741. - *  README:
  742. - *    
  743. - *  This is a virtual framebuffer driver written for Samsung Picture Frames (like
  744. - *  the Samsung SPF-85H). These frames can be used as a litte USB monitor. So one
  745. - *  can send JPEG encoded pictures to them.
  746. - *
  747. - *  However, as it is not a good idea to have a JPEG encoder running in kernelspace
  748. - *  we need an additional userspace application which does the JPEG frame encoding.
  749. - *  Furthermore this app also sends the encoded image via libusb to the frame.
  750. - *
  751. - *  The cool thing about this driver is the efficiant implementation of the
  752. - *  reader/writer paradigm in order to circumvent periodic, CPU intensive FB refreshs.
  753. - *
  754. - *  The userland deamon performs a blocking read on /sys/kernel/debug/spfb. When ever
  755. - *  an application writes something to the framebuffer (via the character dev),
  756. - *  the read call returns and the FB can be refreshed.
  757. - *
  758. - *  This works perfect if for instance the application mmap's the framebuffer and
  759. - *  performs a single write on the character device.
  760. - *  However it can cause problems when an application just uses the character device
  761. - *  and does many write calls at once as each of them causes on refresh.
  762. - *
  763. - */
  764. -
  765. -#include <linux/module.h>
  766. -#include <linux/kernel.h>
  767. -#include <linux/errno.h>
  768. -#include <linux/string.h>
  769. -#include <linux/mm.h>
  770. -#include <linux/slab.h>
  771. -#include <linux/vmalloc.h>
  772. -#include <linux/delay.h>
  773. -#include <linux/interrupt.h>
  774. -#include <linux/platform_device.h>
  775. -#include <linux/uaccess.h>
  776. -#include <linux/debugfs.h>
  777. -#include <linux/pid.h>
  778. -#include <linux/wait.h>
  779. -
  780. -#include <linux/fb.h>
  781. -#include <linux/init.h>
  782. -
  783. -/*
  784. - *  RAM we reserve for the frame buffer. This defines the maximum screen
  785. - *  size
  786. - *
  787. - *  The default can be overridden if the driver is compiled as a module
  788. - */
  789. -#define VIDEOMEMSIZE   (2*1024*1024)   /* 2 MB */
  790. -
  791. -static void *videomemory;
  792. -static u_long videomemorysize = VIDEOMEMSIZE;
  793. -module_param(videomemorysize, ulong, 0);
  794. -
  795. -/**********************************************************************
  796. - *
  797. - * Memory management
  798. - *
  799. - **********************************************************************/
  800. -static void *rvmalloc(unsigned long size)
  801. -{
  802. -   void *mem;
  803. -   unsigned long adr;
  804. -
  805. -   size = PAGE_ALIGN(size);
  806. -   mem = vmalloc_32(size);
  807. -   if (!mem)
  808. -       return NULL;
  809. -
  810. -   memset(mem, 0, size); /* Clear the ram out, no junk to the user */
  811. -   adr = (unsigned long) mem;
  812. -   while (size > 0) {
  813. -       SetPageReserved(vmalloc_to_page((void *)adr));
  814. -       adr += PAGE_SIZE;
  815. -       size -= PAGE_SIZE;
  816. -   }
  817. -
  818. -   return mem;
  819. -}
  820. -
  821. -static void rvfree(void *mem, unsigned long size)
  822. -{
  823. -   unsigned long adr;
  824. -
  825. -   if (!mem)
  826. -       return;
  827. -
  828. -   adr = (unsigned long) mem;
  829. -   while ((long) size > 0) {
  830. -       ClearPageReserved(vmalloc_to_page((void *)adr));
  831. -       adr += PAGE_SIZE;
  832. -       size -= PAGE_SIZE;
  833. -   }
  834. -   vfree(mem);
  835. -}
  836. -
  837. -
  838. -static struct fb_var_screeninfo spfb_default __initdata = {
  839. -   .xres =     800,
  840. -   .yres =     600,
  841. -   .xres_virtual = 800,
  842. -   .yres_virtual = 600,
  843. -   .bits_per_pixel = 16,
  844. -   .red =      { 0, 8, 0 },
  845. -   .green =    { 0, 8, 0 },
  846. -   .blue =     { 0, 8, 0 },
  847. -   .activate = FB_ACTIVATE_NOW, //FB_ACTIVATE_TEST,
  848. -   .height =   -1,
  849. -   .width =    -1,
  850. -   .vmode =    FB_VMODE_NONINTERLACED,
  851. -};
  852. -
  853. -static struct fb_fix_screeninfo spfb_fix __initdata = {
  854. -   .id =           "SPF Frame Buffer",
  855. -   .type =         FB_TYPE_PACKED_PIXELS,
  856. -   .visual =       FB_VISUAL_PSEUDOCOLOR,
  857. -   .xpanstep =     1,
  858. -   .ypanstep =     1,
  859. -   .ywrapstep =    1,
  860. -   .accel =        FB_ACCEL_NONE,
  861. -};
  862. -
  863. -
  864. -/* function prototypes */
  865. -static ssize_t spfb_read_sysfs(struct file *file, char __user *user, size_t count, loff_t *ppos);                                
  866. -
  867. -static int spfb_check_var(struct fb_var_screeninfo *var,
  868. -            struct fb_info *info);
  869. -static int spfb_set_par(struct fb_info *info);
  870. -static int spfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  871. -            u_int transp, struct fb_info *info);
  872. -static int spfb_pan_display(struct fb_var_screeninfo *var,
  873. -              struct fb_info *info);
  874. -static int spfb_mmap(struct fb_info *info,
  875. -           struct vm_area_struct *vma);
  876. -
  877. -
  878. -struct dentry *spfb_debugfs_entry;
  879. -
  880. -static const struct file_operations spfb_sysfs_fops = {
  881. -   .read = spfb_read_sysfs,
  882. -};
  883. -
  884. -
  885. -static DECLARE_WAIT_QUEUE_HEAD(wq);
  886. -static int wq_flag = 0;
  887. -
  888. -
  889. -static ssize_t spfb_read_sysfs(struct file *file, char __user *user, size_t count, loff_t *ppos)
  890. -{
  891. -   char buf[] = "|";
  892. -  
  893. -   wait_event_interruptible(wq, wq_flag != 0);
  894. -   wq_flag = 0;
  895. -  
  896. -   return simple_read_from_buffer(user, count, ppos, buf, 1);
  897. -}
  898. -
  899. -
  900. -static ssize_t spfb_write(struct fb_info *info, const char __user *buf,
  901. -               size_t count, loff_t *ppos)
  902. -{
  903. -   unsigned long p = *ppos;
  904. -   void *dst;
  905. -   int err = 0;
  906. -   unsigned long total_size;
  907. -
  908. -   if (info->state != FBINFO_STATE_RUNNING)
  909. -       return -EPERM;
  910. -
  911. -   total_size = info->fix.smem_len;
  912. -
  913. -   if (p > total_size)
  914. -       return -EFBIG;
  915. -
  916. -   if (count > total_size) {
  917. -       err = -EFBIG;
  918. -       count = total_size;
  919. -   }
  920. -
  921. -   if (count + p > total_size) {
  922. -       if (!err)
  923. -           err = -ENOSPC;
  924. -
  925. -       count = total_size - p;
  926. -   }
  927. -
  928. -   dst = (void __force *) (info->screen_base + p);
  929. -
  930. -   if (copy_from_user(dst, buf, count))
  931. -       err = -EFAULT;
  932. -
  933. -   if  (!err)
  934. -       *ppos += count;
  935. -      
  936. -   /* wake userspace process, so fb can be written to display */
  937. -   wq_flag = 1;
  938. -   wake_up_interruptible(&wq);
  939. -
  940. -   return (err) ? err : count;
  941. -}
  942. -
  943. -
  944. -static struct fb_ops spfb_ops = {
  945. -   .fb_read        = fb_sys_read,
  946. -   .fb_write       = spfb_write,
  947. -   .fb_check_var   = spfb_check_var,
  948. -   .fb_set_par     = spfb_set_par,
  949. -   .fb_setcolreg   = spfb_setcolreg,
  950. -   .fb_pan_display = spfb_pan_display,
  951. -   .fb_fillrect    = sys_fillrect,
  952. -   .fb_copyarea    = sys_copyarea,
  953. -   .fb_imageblit   = sys_imageblit,
  954. -   .fb_mmap        = spfb_mmap,
  955. -};
  956. -
  957. -/*
  958. - *  Internal routines
  959. - */
  960. -static u_long get_line_length(int xres_virtual, int bpp)
  961. -{
  962. -   u_long length;
  963. -
  964. -   length = xres_virtual * bpp;
  965. -   length = (length + 31) & ~31;
  966. -   length >>= 3;
  967. -   return (length);
  968. -}
  969. -
  970. -/*
  971. - *  Setting the video mode has been split into two parts.
  972. - *  First part, xxxfb_check_var, must not write anything
  973. - *  to hardware, it should only verify and adjust var.
  974. - *  This means it doesn't alter par but it does use hardware
  975. - *  data from it to check this var.
  976. - */
  977. -static int spfb_check_var(struct fb_var_screeninfo *var,
  978. -            struct fb_info *info)
  979. -{
  980. -   u_long line_length;
  981. -
  982. -   /*
  983. -    *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
  984. -    *  as FB_VMODE_SMOOTH_XPAN is only used internally
  985. -    */
  986. -
  987. -   if (var->vmode & FB_VMODE_CONUPDATE) {
  988. -       var->vmode |= FB_VMODE_YWRAP;
  989. -       var->xoffset = info->var.xoffset;
  990. -       var->yoffset = info->var.yoffset;
  991. -   }
  992. -
  993. -   /*
  994. -    *  Some very basic checks
  995. -    */
  996. -   if (!var->xres)
  997. -       var->xres = 1;
  998. -   if (!var->yres)
  999. -       var->yres = 1;
  1000. -   if (var->xres > var->xres_virtual)
  1001. -       var->xres_virtual = var->xres;
  1002. -   if (var->yres > var->yres_virtual)
  1003. -       var->yres_virtual = var->yres;
  1004. -   if (var->bits_per_pixel <= 1)
  1005. -       var->bits_per_pixel = 1;
  1006. -   else if (var->bits_per_pixel <= 8)
  1007. -       var->bits_per_pixel = 8;
  1008. -   else if (var->bits_per_pixel <= 16)
  1009. -       var->bits_per_pixel = 16;
  1010. -   else if (var->bits_per_pixel <= 24)
  1011. -       var->bits_per_pixel = 24;
  1012. -   else if (var->bits_per_pixel <= 32)
  1013. -       var->bits_per_pixel = 32;
  1014. -   else
  1015. -       return -EINVAL;
  1016. -
  1017. -   if (var->xres_virtual < var->xoffset + var->xres)
  1018. -       var->xres_virtual = var->xoffset + var->xres;
  1019. -   if (var->yres_virtual < var->yoffset + var->yres)
  1020. -       var->yres_virtual = var->yoffset + var->yres;
  1021. -
  1022. -   /*
  1023. -    *  Memory limit
  1024. -    */
  1025. -   line_length =
  1026. -       get_line_length(var->xres_virtual, var->bits_per_pixel);
  1027. -   if (line_length * var->yres_virtual > videomemorysize)
  1028. -       return -ENOMEM;
  1029. -
  1030. -   /*
  1031. -    * Now that we checked it we alter var. The reason being is that the video
  1032. -    * mode passed in might not work but slight changes to it might make it
  1033. -    * work. This way we let the user know what is acceptable.
  1034. -    */
  1035. -   switch (var->bits_per_pixel) {
  1036. -   case 1:
  1037. -   case 8:
  1038. -       var->red.offset = 0;
  1039. -       var->red.length = 8;
  1040. -       var->green.offset = 0;
  1041. -       var->green.length = 8;
  1042. -       var->blue.offset = 0;
  1043. -       var->blue.length = 8;
  1044. -       var->transp.offset = 0;
  1045. -       var->transp.length = 0;
  1046. -       break;
  1047. -   case 16:        /* RGBA 5551 */
  1048. -       if (var->transp.length) {
  1049. -           var->red.offset = 0;
  1050. -           var->red.length = 5;
  1051. -           var->green.offset = 5;
  1052. -           var->green.length = 5;
  1053. -           var->blue.offset = 10;
  1054. -           var->blue.length = 5;
  1055. -           var->transp.offset = 15;
  1056. -           var->transp.length = 1;
  1057. -       } else {    /* RGB 565 */
  1058. -           var->red.offset = 0;
  1059. -           var->red.length = 5;
  1060. -           var->green.offset = 5;
  1061. -           var->green.length = 6;
  1062. -           var->blue.offset = 11;
  1063. -           var->blue.length = 5;
  1064. -           var->transp.offset = 0;
  1065. -           var->transp.length = 0;
  1066. -       }
  1067. -       break;
  1068. -   case 24:        /* RGB 888 */
  1069. -       var->red.offset = 0;
  1070. -       var->red.length = 8;
  1071. -       var->green.offset = 8;
  1072. -       var->green.length = 8;
  1073. -       var->blue.offset = 16;
  1074. -       var->blue.length = 8;
  1075. -       var->transp.offset = 0;
  1076. -       var->transp.length = 0;
  1077. -       break;
  1078. -   case 32:        /* RGBA 8888 */
  1079. -       var->red.offset = 0;
  1080. -       var->red.length = 8;
  1081. -       var->green.offset = 8;
  1082. -       var->green.length = 8;
  1083. -       var->blue.offset = 16;
  1084. -       var->blue.length = 8;
  1085. -       var->transp.offset = 24;
  1086. -       var->transp.length = 8;
  1087. -       break;
  1088. -   }
  1089. -   var->red.msb_right = 0;
  1090. -   var->green.msb_right = 0;
  1091. -   var->blue.msb_right = 0;
  1092. -   var->transp.msb_right = 0;
  1093. -
  1094. -   return 0;
  1095. -}
  1096. -
  1097. -/* This routine actually sets the video mode. It's in here where we
  1098. - * the hardware state info->par and fix which can be affected by the
  1099. - * change in par. For this driver it doesn't do much.
  1100. - */
  1101. -static int spfb_set_par(struct fb_info *info)
  1102. -{
  1103. -   info->fix.line_length = get_line_length(info->var.xres_virtual,
  1104. -                       info->var.bits_per_pixel);
  1105. -   return 0;
  1106. -}
  1107. -
  1108. -/*
  1109. - *  Set a single color register. The values supplied are already
  1110. - *  rounded down to the hardware's capabilities (according to the
  1111. - *  entries in the var structure). Return != 0 for invalid regno.
  1112. - */
  1113. -static int spfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  1114. -            u_int transp, struct fb_info *info)
  1115. -{
  1116. -   if (regno >= 256)   /* no. of hw registers */
  1117. -       return 1;
  1118. -   /*
  1119. -    * Program hardware... do anything you want with transp
  1120. -    */
  1121. -
  1122. -   /* grayscale works only partially under directcolor */
  1123. -   if (info->var.grayscale) {
  1124. -       /* grayscale = 0.30*R + 0.59*G + 0.11*B */
  1125. -       red = green = blue =
  1126. -           (red * 77 + green * 151 + blue * 28) >> 8;
  1127. -   }
  1128. -
  1129. -   /* Directcolor:
  1130. -    *   var->{color}.offset contains start of bitfield
  1131. -    *   var->{color}.length contains length of bitfield
  1132. -    *   {hardwarespecific} contains width of RAMDAC
  1133. -    *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
  1134. -    *   RAMDAC[X] is programmed to (red, green, blue)
  1135. -    *
  1136. -    * Pseudocolor:
  1137. -    *    var->{color}.offset is 0 unless the palette index takes less than
  1138. -    *                        bits_per_pixel bits and is stored in the upper
  1139. -    *                        bits of the pixel value
  1140. -    *    var->{color}.length is set so that 1 << length is the number of available
  1141. -    *                        palette entries
  1142. -    *    cmap is not used
  1143. -    *    RAMDAC[X] is programmed to (red, green, blue)
  1144. -    *
  1145. -    * Truecolor:
  1146. -    *    does not use DAC. Usually 3 are present.
  1147. -    *    var->{color}.offset contains start of bitfield
  1148. -    *    var->{color}.length contains length of bitfield
  1149. -    *    cmap is programmed to (red << red.offset) | (green << green.offset) |
  1150. -    *                      (blue << blue.offset) | (transp << transp.offset)
  1151. -    *    RAMDAC does not exist
  1152. -    */
  1153. -#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
  1154. -   switch (info->fix.visual) {
  1155. -   case FB_VISUAL_TRUECOLOR:
  1156. -   case FB_VISUAL_PSEUDOCOLOR:
  1157. -       red = CNVT_TOHW(red, info->var.red.length);
  1158. -       green = CNVT_TOHW(green, info->var.green.length);
  1159. -       blue = CNVT_TOHW(blue, info->var.blue.length);
  1160. -       transp = CNVT_TOHW(transp, info->var.transp.length);
  1161. -       break;
  1162. -   case FB_VISUAL_DIRECTCOLOR:
  1163. -       red = CNVT_TOHW(red, 8);    /* expect 8 bit DAC */
  1164. -       green = CNVT_TOHW(green, 8);
  1165. -       blue = CNVT_TOHW(blue, 8);
  1166. -       /* hey, there is bug in transp handling... */
  1167. -       transp = CNVT_TOHW(transp, 8);
  1168. -       break;
  1169. -   }
  1170. -#undef CNVT_TOHW
  1171. -   /* Truecolor has hardware independent palette */
  1172. -   if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
  1173. -       u32 v;
  1174. -
  1175. -       if (regno >= 16)
  1176. -           return 1;
  1177. -
  1178. -       v = (red << info->var.red.offset) |
  1179. -           (green << info->var.green.offset) |
  1180. -           (blue << info->var.blue.offset) |
  1181. -           (transp << info->var.transp.offset);
  1182. -       switch (info->var.bits_per_pixel) {
  1183. -       case 8:
  1184. -           break;
  1185. -       case 16:
  1186. -           ((u32 *) (info->pseudo_palette))[regno] = v;
  1187. -           break;
  1188. -       case 24:
  1189. -       case 32:
  1190. -           ((u32 *) (info->pseudo_palette))[regno] = v;
  1191. -           break;
  1192. -       }
  1193. -       return 0;
  1194. -   }
  1195. -   return 0;
  1196. -}
  1197. -
  1198. -/*
  1199. - *  Pan or Wrap the Display
  1200. - *
  1201. - *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
  1202. - */
  1203. -static int spfb_pan_display(struct fb_var_screeninfo *var,
  1204. -              struct fb_info *info)
  1205. -{
  1206. -   if (var->vmode & FB_VMODE_YWRAP) {
  1207. -       if (var->yoffset < 0
  1208. -           || var->yoffset >= info->var.yres_virtual
  1209. -           || var->xoffset)
  1210. -           return -EINVAL;
  1211. -   } else {
  1212. -       if (var->xoffset + var->xres > info->var.xres_virtual ||
  1213. -           var->yoffset + var->yres > info->var.yres_virtual)
  1214. -           return -EINVAL;
  1215. -   }
  1216. -   info->var.xoffset = var->xoffset;
  1217. -   info->var.yoffset = var->yoffset;
  1218. -   if (var->vmode & FB_VMODE_YWRAP)
  1219. -       info->var.vmode |= FB_VMODE_YWRAP;
  1220. -   else
  1221. -       info->var.vmode &= ~FB_VMODE_YWRAP;
  1222. -   return 0;
  1223. -}
  1224. -
  1225. -/*
  1226. - *  Most drivers don't need their own mmap function
  1227. - */
  1228. -static int spfb_mmap(struct fb_info *info,
  1229. -           struct vm_area_struct *vma)
  1230. -{
  1231. -   unsigned long start = vma->vm_start;
  1232. -   unsigned long size = vma->vm_end - vma->vm_start;
  1233. -   unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
  1234. -   unsigned long page, pos;
  1235. -
  1236. -   if (offset + size > info->fix.smem_len) {
  1237. -       return -EINVAL;
  1238. -   }
  1239. -
  1240. -   pos = (unsigned long)info->fix.smem_start + offset;
  1241. -
  1242. -   while (size > 0) {
  1243. -       page = vmalloc_to_pfn((void *)pos);
  1244. -       if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
  1245. -           return -EAGAIN;
  1246. -       }
  1247. -       start += PAGE_SIZE;
  1248. -       pos += PAGE_SIZE;
  1249. -       if (size > PAGE_SIZE)
  1250. -           size -= PAGE_SIZE;
  1251. -       else
  1252. -           size = 0;
  1253. -   }
  1254. -
  1255. -   vma->vm_flags |= VM_RESERVED;   /* avoid to swap out this VMA */
  1256. -   return 0;
  1257. -
  1258. -}
  1259. -
  1260. -#ifndef MODULE
  1261. -/*
  1262. - * The virtual framebuffer driver is only enabled if explicitly
  1263. - * requested by passing 'video=vfb:' (or any actual options).
  1264. - */
  1265. -static int __init spfb_setup(char *options)
  1266. -{
  1267. -   char *this_opt;
  1268. -
  1269. -   if (!options)
  1270. -       return 1;
  1271. -
  1272. -
  1273. -   if (!*options)
  1274. -       return 1;
  1275. -
  1276. -   while ((this_opt = strsep(&options, ",")) != NULL) {
  1277. -       if (!*this_opt)
  1278. -           continue;
  1279. -   }
  1280. -   return 1;
  1281. -}
  1282. -#endif  /*  MODULE  */
  1283. -
  1284. -/*
  1285. - *  Initialisation
  1286. - */
  1287. -static int __init spfb_probe(struct platform_device *dev)
  1288. -{
  1289. -   struct fb_info *info;
  1290. -   int retval = -ENOMEM;
  1291. -
  1292. -   /*
  1293. -    * For real video cards we use ioremap.
  1294. -    */
  1295. -   if (!(videomemory = rvmalloc(videomemorysize)))
  1296. -       return retval;
  1297. -
  1298. -   /*
  1299. -    * VFB must clear memory to prevent kernel info
  1300. -    * leakage into userspace
  1301. -    * VGA-based drivers MUST NOT clear memory if
  1302. -    * they want to be able to take over vgacon
  1303. -    */
  1304. -   memset(videomemory, 0, videomemorysize);
  1305. -
  1306. -   info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
  1307. -   if (!info)
  1308. -       goto err;
  1309. -
  1310. -   info->screen_base = (char __iomem *)videomemory;
  1311. -   info->fbops = &spfb_ops;
  1312. -
  1313. -   info->var = spfb_default;
  1314. -   spfb_fix.smem_start = (unsigned long) videomemory;
  1315. -   spfb_fix.smem_len = videomemorysize;
  1316. -   info->fix = spfb_fix;
  1317. -   info->pseudo_palette = info->par;
  1318. -   info->par = NULL;
  1319. -   info->flags = FBINFO_FLAG_DEFAULT;
  1320. -
  1321. -   retval = fb_alloc_cmap(&info->cmap, 256, 0);
  1322. -   if (retval < 0)
  1323. -       goto err1;
  1324. -
  1325. -   retval = register_framebuffer(info);
  1326. -   if (retval < 0)
  1327. -       goto err2;
  1328. -   platform_set_drvdata(dev, info);
  1329. -
  1330. -   printk(KERN_INFO
  1331. -          "fb%d: Samsung Picture Frame frame buffer device created, using %ldK of video memory\n",
  1332. -          info->node, videomemorysize >> 10);
  1333. -   return 0;
  1334. -err2:
  1335. -   fb_dealloc_cmap(&info->cmap);
  1336. -err1:
  1337. -   framebuffer_release(info);
  1338. -err:
  1339. -   rvfree(videomemory, videomemorysize);
  1340. -   return retval;
  1341. -}
  1342. -
  1343. -static int spfb_remove(struct platform_device *dev)
  1344. -{
  1345. -   struct fb_info *info = platform_get_drvdata(dev);
  1346. -
  1347. -   if (info) {
  1348. -       unregister_framebuffer(info);
  1349. -       rvfree(videomemory, videomemorysize);
  1350. -       fb_dealloc_cmap(&info->cmap);
  1351. -       framebuffer_release(info);
  1352. -   }
  1353. -   return 0;
  1354. -}
  1355. -
  1356. -
  1357. -
  1358. -
  1359. -static struct platform_driver spfb_driver = {
  1360. -   .probe  = spfb_probe,
  1361. -   .remove = spfb_remove,
  1362. -   .driver = {
  1363. -       .name   = "spfb",
  1364. -   },
  1365. -};
  1366. -
  1367. -static struct platform_device *spfb_device;
  1368. -
  1369. -static int __init spfb_init(void)
  1370. -{
  1371. -   int ret = 0;
  1372. -
  1373. -#ifndef MODULE
  1374. -   char *option = NULL;
  1375. -
  1376. -   if (fb_get_options("spfb", &option))
  1377. -       return -ENODEV;
  1378. -   spfb_setup(option);
  1379. -#endif
  1380. -
  1381. -   ret = platform_driver_register(&spfb_driver);
  1382. -   if (!ret) {
  1383. -       spfb_device = platform_device_alloc("spfb", 0);
  1384. -
  1385. -       if (spfb_device)
  1386. -           ret = platform_device_add(spfb_device);
  1387. -       else
  1388. -           ret = -ENOMEM;
  1389. -
  1390. -       if (ret) {
  1391. -           platform_device_put(spfb_device);
  1392. -           platform_driver_unregister(&spfb_driver);
  1393. -       }
  1394. -   }
  1395. -  
  1396. -   /* create debugfs entry */
  1397. -   spfb_debugfs_entry = debugfs_create_file("spfb", 0444, NULL, NULL, &spfb_sysfs_fops);
  1398. -
  1399. -   return ret;
  1400. -}
  1401. -
  1402. -module_init(spfb_init);
  1403. -
  1404. -#ifdef MODULE
  1405. -static void __exit spfb_exit(void)
  1406. -{
  1407. -   /* cleanup and exit */ 
  1408. -   platform_device_unregister(spfb_device);
  1409. -   platform_driver_unregister(&spfb_driver);
  1410. -  
  1411. -   debugfs_remove(spfb_debugfs_entry);
  1412. -  
  1413. -   printk(KERN_INFO "spfb module unloaded\n");
  1414. -}
  1415. -
  1416. -module_exit(spfb_exit);
  1417. -
  1418. -MODULE_LICENSE("GPL");
  1419. -#endif /* MODULE */
  1420. -
  1421. -
  1422. -
  1423. -
  1424. -
  1425. -
  1426. -
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement