grvga.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. /*
  2. * Driver for Aeroflex Gaisler SVGACTRL framebuffer device.
  3. *
  4. * 2011 (c) Aeroflex Gaisler AB
  5. *
  6. * Full documentation of the core can be found here:
  7. * http://www.gaisler.com/products/grlib/grip.pdf
  8. *
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License as published by the
  11. * Free Software Foundation; either version 2 of the License, or (at your
  12. * option) any later version.
  13. *
  14. * Contributors: Kristoffer Glembo <kristoffer@gaisler.com>
  15. *
  16. */
  17. #include <linux/platform_device.h>
  18. #include <linux/dma-mapping.h>
  19. #include <linux/of_platform.h>
  20. #include <linux/of_device.h>
  21. #include <linux/module.h>
  22. #include <linux/kernel.h>
  23. #include <linux/string.h>
  24. #include <linux/delay.h>
  25. #include <linux/errno.h>
  26. #include <linux/init.h>
  27. #include <linux/slab.h>
  28. #include <linux/tty.h>
  29. #include <linux/mm.h>
  30. #include <linux/fb.h>
  31. #include <linux/io.h>
  32. struct grvga_regs {
  33. u32 status; /* 0x00 */
  34. u32 video_length; /* 0x04 */
  35. u32 front_porch; /* 0x08 */
  36. u32 sync_length; /* 0x0C */
  37. u32 line_length; /* 0x10 */
  38. u32 fb_pos; /* 0x14 */
  39. u32 clk_vector[4]; /* 0x18 */
  40. u32 clut; /* 0x20 */
  41. };
  42. struct grvga_par {
  43. struct grvga_regs *regs;
  44. u32 color_palette[16]; /* 16 entry pseudo palette used by fbcon in true color mode */
  45. int clk_sel;
  46. int fb_alloced; /* = 1 if framebuffer is allocated in main memory */
  47. };
  48. static const struct fb_videomode grvga_modedb[] = {
  49. {
  50. /* 640x480 @ 60 Hz */
  51. NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2,
  52. 0, FB_VMODE_NONINTERLACED
  53. }, {
  54. /* 800x600 @ 60 Hz */
  55. NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
  56. 0, FB_VMODE_NONINTERLACED
  57. }, {
  58. /* 800x600 @ 72 Hz */
  59. NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
  60. 0, FB_VMODE_NONINTERLACED
  61. }, {
  62. /* 1024x768 @ 60 Hz */
  63. NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
  64. 0, FB_VMODE_NONINTERLACED
  65. }
  66. };
  67. static struct fb_fix_screeninfo grvga_fix = {
  68. .id = "AG SVGACTRL",
  69. .type = FB_TYPE_PACKED_PIXELS,
  70. .visual = FB_VISUAL_PSEUDOCOLOR,
  71. .xpanstep = 0,
  72. .ypanstep = 1,
  73. .ywrapstep = 0,
  74. .accel = FB_ACCEL_NONE,
  75. };
  76. static int grvga_check_var(struct fb_var_screeninfo *var,
  77. struct fb_info *info)
  78. {
  79. struct grvga_par *par = info->par;
  80. int i;
  81. if (!var->xres)
  82. var->xres = 1;
  83. if (!var->yres)
  84. var->yres = 1;
  85. if (var->bits_per_pixel <= 8)
  86. var->bits_per_pixel = 8;
  87. else if (var->bits_per_pixel <= 16)
  88. var->bits_per_pixel = 16;
  89. else if (var->bits_per_pixel <= 24)
  90. var->bits_per_pixel = 24;
  91. else if (var->bits_per_pixel <= 32)
  92. var->bits_per_pixel = 32;
  93. else
  94. return -EINVAL;
  95. var->xres_virtual = var->xres;
  96. var->yres_virtual = 2*var->yres;
  97. if (info->fix.smem_len) {
  98. if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len)
  99. return -ENOMEM;
  100. }
  101. /* Which clocks that are available can be read out in these registers */
  102. for (i = 0; i <= 3 ; i++) {
  103. if (var->pixclock == par->regs->clk_vector[i])
  104. break;
  105. }
  106. if (i <= 3)
  107. par->clk_sel = i;
  108. else
  109. return -EINVAL;
  110. switch (info->var.bits_per_pixel) {
  111. case 8:
  112. var->red = (struct fb_bitfield) {0, 8, 0}; /* offset, length, msb-right */
  113. var->green = (struct fb_bitfield) {0, 8, 0};
  114. var->blue = (struct fb_bitfield) {0, 8, 0};
  115. var->transp = (struct fb_bitfield) {0, 0, 0};
  116. break;
  117. case 16:
  118. var->red = (struct fb_bitfield) {11, 5, 0};
  119. var->green = (struct fb_bitfield) {5, 6, 0};
  120. var->blue = (struct fb_bitfield) {0, 5, 0};
  121. var->transp = (struct fb_bitfield) {0, 0, 0};
  122. break;
  123. case 24:
  124. case 32:
  125. var->red = (struct fb_bitfield) {16, 8, 0};
  126. var->green = (struct fb_bitfield) {8, 8, 0};
  127. var->blue = (struct fb_bitfield) {0, 8, 0};
  128. var->transp = (struct fb_bitfield) {24, 8, 0};
  129. break;
  130. default:
  131. return -EINVAL;
  132. }
  133. return 0;
  134. }
  135. static int grvga_set_par(struct fb_info *info)
  136. {
  137. u32 func = 0;
  138. struct grvga_par *par = info->par;
  139. __raw_writel(((info->var.yres - 1) << 16) | (info->var.xres - 1),
  140. &par->regs->video_length);
  141. __raw_writel((info->var.lower_margin << 16) | (info->var.right_margin),
  142. &par->regs->front_porch);
  143. __raw_writel((info->var.vsync_len << 16) | (info->var.hsync_len),
  144. &par->regs->sync_length);
  145. __raw_writel(((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) |
  146. (info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1),
  147. &par->regs->line_length);
  148. switch (info->var.bits_per_pixel) {
  149. case 8:
  150. info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
  151. func = 1;
  152. break;
  153. case 16:
  154. info->fix.visual = FB_VISUAL_TRUECOLOR;
  155. func = 2;
  156. break;
  157. case 24:
  158. case 32:
  159. info->fix.visual = FB_VISUAL_TRUECOLOR;
  160. func = 3;
  161. break;
  162. default:
  163. return -EINVAL;
  164. }
  165. __raw_writel((par->clk_sel << 6) | (func << 4) | 1,
  166. &par->regs->status);
  167. info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8;
  168. return 0;
  169. }
  170. static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info)
  171. {
  172. struct grvga_par *par;
  173. par = info->par;
  174. if (regno >= 256) /* Size of CLUT */
  175. return -EINVAL;
  176. if (info->var.grayscale) {
  177. /* grayscale = 0.30*R + 0.59*G + 0.11*B */
  178. red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
  179. }
  180. #define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
  181. red = CNVT_TOHW(red, info->var.red.length);
  182. green = CNVT_TOHW(green, info->var.green.length);
  183. blue = CNVT_TOHW(blue, info->var.blue.length);
  184. transp = CNVT_TOHW(transp, info->var.transp.length);
  185. #undef CNVT_TOHW
  186. /* In PSEUDOCOLOR we use the hardware CLUT */
  187. if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
  188. __raw_writel((regno << 24) | (red << 16) | (green << 8) | blue,
  189. &par->regs->clut);
  190. /* Truecolor uses the pseudo palette */
  191. else if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
  192. u32 v;
  193. if (regno >= 16)
  194. return -EINVAL;
  195. v = (red << info->var.red.offset) |
  196. (green << info->var.green.offset) |
  197. (blue << info->var.blue.offset) |
  198. (transp << info->var.transp.offset);
  199. ((u32 *) (info->pseudo_palette))[regno] = v;
  200. }
  201. return 0;
  202. }
  203. static int grvga_pan_display(struct fb_var_screeninfo *var,
  204. struct fb_info *info)
  205. {
  206. struct grvga_par *par = info->par;
  207. struct fb_fix_screeninfo *fix = &info->fix;
  208. u32 base_addr;
  209. if (var->xoffset != 0)
  210. return -EINVAL;
  211. base_addr = fix->smem_start + (var->yoffset * fix->line_length);
  212. base_addr &= ~3UL;
  213. /* Set framebuffer base address */
  214. __raw_writel(base_addr,
  215. &par->regs->fb_pos);
  216. return 0;
  217. }
  218. static struct fb_ops grvga_ops = {
  219. .owner = THIS_MODULE,
  220. .fb_check_var = grvga_check_var,
  221. .fb_set_par = grvga_set_par,
  222. .fb_setcolreg = grvga_setcolreg,
  223. .fb_pan_display = grvga_pan_display,
  224. .fb_fillrect = cfb_fillrect,
  225. .fb_copyarea = cfb_copyarea,
  226. .fb_imageblit = cfb_imageblit
  227. };
  228. static int grvga_parse_custom(char *options,
  229. struct fb_var_screeninfo *screendata)
  230. {
  231. char *this_opt;
  232. int count = 0;
  233. if (!options || !*options)
  234. return -1;
  235. while ((this_opt = strsep(&options, " ")) != NULL) {
  236. if (!*this_opt)
  237. continue;
  238. switch (count) {
  239. case 0:
  240. screendata->pixclock = simple_strtoul(this_opt, NULL, 0);
  241. count++;
  242. break;
  243. case 1:
  244. screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0);
  245. count++;
  246. break;
  247. case 2:
  248. screendata->right_margin = simple_strtoul(this_opt, NULL, 0);
  249. count++;
  250. break;
  251. case 3:
  252. screendata->hsync_len = simple_strtoul(this_opt, NULL, 0);
  253. count++;
  254. break;
  255. case 4:
  256. screendata->left_margin = simple_strtoul(this_opt, NULL, 0);
  257. count++;
  258. break;
  259. case 5:
  260. screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0);
  261. count++;
  262. break;
  263. case 6:
  264. screendata->lower_margin = simple_strtoul(this_opt, NULL, 0);
  265. count++;
  266. break;
  267. case 7:
  268. screendata->vsync_len = simple_strtoul(this_opt, NULL, 0);
  269. count++;
  270. break;
  271. case 8:
  272. screendata->upper_margin = simple_strtoul(this_opt, NULL, 0);
  273. count++;
  274. break;
  275. case 9:
  276. screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0);
  277. count++;
  278. break;
  279. default:
  280. return -1;
  281. }
  282. }
  283. screendata->activate = FB_ACTIVATE_NOW;
  284. screendata->vmode = FB_VMODE_NONINTERLACED;
  285. return 0;
  286. }
  287. static int grvga_probe(struct platform_device *dev)
  288. {
  289. struct fb_info *info;
  290. int retval = -ENOMEM;
  291. unsigned long virtual_start;
  292. unsigned long grvga_fix_addr = 0;
  293. unsigned long physical_start = 0;
  294. unsigned long grvga_mem_size = 0;
  295. struct grvga_par *par = NULL;
  296. char *options = NULL, *mode_opt = NULL;
  297. info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev);
  298. if (!info) {
  299. dev_err(&dev->dev, "framebuffer_alloc failed\n");
  300. return -ENOMEM;
  301. }
  302. /* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>]
  303. *
  304. * If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters
  305. * If address is left out, we allocate memory,
  306. * if size is left out we only allocate enough to support the given mode.
  307. */
  308. if (fb_get_options("grvga", &options)) {
  309. retval = -ENODEV;
  310. goto free_fb;
  311. }
  312. if (!options || !*options)
  313. options = "640x480-8@60";
  314. while (1) {
  315. char *this_opt = strsep(&options, ",");
  316. if (!this_opt)
  317. break;
  318. if (!strncmp(this_opt, "custom", 6)) {
  319. if (grvga_parse_custom(this_opt, &info->var) < 0) {
  320. dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt);
  321. retval = -EINVAL;
  322. goto free_fb;
  323. }
  324. } else if (!strncmp(this_opt, "addr", 4))
  325. grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16);
  326. else if (!strncmp(this_opt, "size", 4))
  327. grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0);
  328. else
  329. mode_opt = this_opt;
  330. }
  331. par = info->par;
  332. info->fbops = &grvga_ops;
  333. info->fix = grvga_fix;
  334. info->pseudo_palette = par->color_palette;
  335. info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
  336. info->fix.smem_len = grvga_mem_size;
  337. if (!devm_request_mem_region(&dev->dev, dev->resource[0].start,
  338. resource_size(&dev->resource[0]), "grlib-svgactrl regs")) {
  339. dev_err(&dev->dev, "registers already mapped\n");
  340. retval = -EBUSY;
  341. goto free_fb;
  342. }
  343. par->regs = of_ioremap(&dev->resource[0], 0,
  344. resource_size(&dev->resource[0]),
  345. "grlib-svgactrl regs");
  346. if (!par->regs) {
  347. dev_err(&dev->dev, "failed to map registers\n");
  348. retval = -ENOMEM;
  349. goto free_fb;
  350. }
  351. retval = fb_alloc_cmap(&info->cmap, 256, 0);
  352. if (retval < 0) {
  353. dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n");
  354. retval = -ENOMEM;
  355. goto unmap_regs;
  356. }
  357. if (mode_opt) {
  358. retval = fb_find_mode(&info->var, info, mode_opt,
  359. grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8);
  360. if (!retval || retval == 4) {
  361. retval = -EINVAL;
  362. goto dealloc_cmap;
  363. }
  364. }
  365. if (!grvga_mem_size)
  366. grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8;
  367. if (grvga_fix_addr) {
  368. /* Got framebuffer base address from argument list */
  369. physical_start = grvga_fix_addr;
  370. if (!devm_request_mem_region(&dev->dev, physical_start,
  371. grvga_mem_size, dev->name)) {
  372. dev_err(&dev->dev, "failed to request memory region\n");
  373. retval = -ENOMEM;
  374. goto dealloc_cmap;
  375. }
  376. virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size);
  377. if (!virtual_start) {
  378. dev_err(&dev->dev, "error mapping framebuffer memory\n");
  379. retval = -ENOMEM;
  380. goto dealloc_cmap;
  381. }
  382. } else { /* Allocate frambuffer memory */
  383. unsigned long page;
  384. virtual_start = (unsigned long) __get_free_pages(GFP_DMA,
  385. get_order(grvga_mem_size));
  386. if (!virtual_start) {
  387. dev_err(&dev->dev,
  388. "unable to allocate framebuffer memory (%lu bytes)\n",
  389. grvga_mem_size);
  390. retval = -ENOMEM;
  391. goto dealloc_cmap;
  392. }
  393. physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE);
  394. /* Set page reserved so that mmap will work. This is necessary
  395. * since we'll be remapping normal memory.
  396. */
  397. for (page = virtual_start;
  398. page < PAGE_ALIGN(virtual_start + grvga_mem_size);
  399. page += PAGE_SIZE) {
  400. SetPageReserved(virt_to_page(page));
  401. }
  402. par->fb_alloced = 1;
  403. }
  404. memset((unsigned long *) virtual_start, 0, grvga_mem_size);
  405. info->screen_base = (char __iomem *) virtual_start;
  406. info->fix.smem_start = physical_start;
  407. info->fix.smem_len = grvga_mem_size;
  408. dev_set_drvdata(&dev->dev, info);
  409. dev_info(&dev->dev,
  410. "Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ %p\n",
  411. info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel,
  412. grvga_mem_size >> 10, info->screen_base);
  413. retval = register_framebuffer(info);
  414. if (retval < 0) {
  415. dev_err(&dev->dev, "failed to register framebuffer\n");
  416. goto free_mem;
  417. }
  418. __raw_writel(physical_start, &par->regs->fb_pos);
  419. __raw_writel(__raw_readl(&par->regs->status) | 1, /* Enable framebuffer */
  420. &par->regs->status);
  421. return 0;
  422. free_mem:
  423. if (grvga_fix_addr)
  424. iounmap((void *)virtual_start);
  425. else
  426. kfree((void *)virtual_start);
  427. dealloc_cmap:
  428. fb_dealloc_cmap(&info->cmap);
  429. unmap_regs:
  430. of_iounmap(&dev->resource[0], par->regs,
  431. resource_size(&dev->resource[0]));
  432. free_fb:
  433. framebuffer_release(info);
  434. return retval;
  435. }
  436. static int grvga_remove(struct platform_device *device)
  437. {
  438. struct fb_info *info = dev_get_drvdata(&device->dev);
  439. struct grvga_par *par;
  440. if (info) {
  441. par = info->par;
  442. unregister_framebuffer(info);
  443. fb_dealloc_cmap(&info->cmap);
  444. of_iounmap(&device->resource[0], par->regs,
  445. resource_size(&device->resource[0]));
  446. if (!par->fb_alloced)
  447. iounmap(info->screen_base);
  448. else
  449. kfree((void *)info->screen_base);
  450. framebuffer_release(info);
  451. }
  452. return 0;
  453. }
  454. static struct of_device_id svgactrl_of_match[] = {
  455. {
  456. .name = "GAISLER_SVGACTRL",
  457. },
  458. {
  459. .name = "01_063",
  460. },
  461. {},
  462. };
  463. MODULE_DEVICE_TABLE(of, svgactrl_of_match);
  464. static struct platform_driver grvga_driver = {
  465. .driver = {
  466. .name = "grlib-svgactrl",
  467. .of_match_table = svgactrl_of_match,
  468. },
  469. .probe = grvga_probe,
  470. .remove = grvga_remove,
  471. };
  472. module_platform_driver(grvga_driver);
  473. MODULE_LICENSE("GPL");
  474. MODULE_AUTHOR("Aeroflex Gaisler");
  475. MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver");