grvga.c 14 KB

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