grvga.c 14 KB

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