tx3912fb.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /*
  2. * drivers/video/tx3912fb.c
  3. *
  4. * Copyright (C) 1999 Harald Koerfgen
  5. * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com)
  6. *
  7. * This file is subject to the terms and conditions of the GNU General Public
  8. * License. See the file COPYING in the main directory of this archive for
  9. * more details.
  10. *
  11. * Framebuffer for LCD controller in TMPR3912/05 and PR31700 processors
  12. */
  13. #include <linux/module.h>
  14. #include <linux/kernel.h>
  15. #include <linux/errno.h>
  16. #include <linux/string.h>
  17. #include <linux/tty.h>
  18. #include <linux/delay.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/init.h>
  21. #include <linux/pm.h>
  22. #include <linux/fb.h>
  23. #include <asm/io.h>
  24. #include <asm/bootinfo.h>
  25. #include <asm/uaccess.h>
  26. #include <asm/tx3912.h>
  27. #include <video/tx3912.h>
  28. /*
  29. * Frame buffer, palette and console structures
  30. */
  31. static struct fb_info fb_info;
  32. static u32 cfb8[16];
  33. static struct fb_fix_screeninfo tx3912fb_fix __initdata = {
  34. .id = "tx3912fb",
  35. .smem_len = ((240 * 320)/2),
  36. .type = FB_TYPE_PACKED_PIXELS,
  37. .visual = FB_VISUAL_TRUECOLOR,
  38. .xpanstep = 1,
  39. .ypanstep = 1,
  40. .ywrapstep = 1,
  41. .accel = FB_ACCEL_NONE,
  42. };
  43. static struct fb_var_screeninfo tx3912fb_var = {
  44. .xres = 240,
  45. .yres = 320,
  46. .xres_virtual = 240,
  47. .yres_virtual = 320,
  48. .bits_per_pixel =4,
  49. .red = { 0, 4, 0 }, /* ??? */
  50. .green = { 0, 4, 0 },
  51. .blue = { 0, 4, 0 },
  52. .activate = FB_ACTIVATE_NOW,
  53. .width = -1,
  54. .height = -1,
  55. .pixclock = 20000,
  56. .left_margin = 64,
  57. .right_margin = 64,
  58. .upper_margin = 32,
  59. .lower_margin = 32,
  60. .hsync_len = 64,
  61. .vsync_len = 2,
  62. .vmode = FB_VMODE_NONINTERLACED,
  63. };
  64. /*
  65. * Interface used by the world
  66. */
  67. int tx3912fb_init(void);
  68. static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green,
  69. u_int blue, u_int transp,
  70. struct fb_info *info);
  71. /*
  72. * Macros
  73. */
  74. #define get_line_length(xres_virtual, bpp) \
  75. (u_long) (((int) xres_virtual * (int) bpp + 7) >> 3)
  76. /*
  77. * Frame buffer operations structure used by console driver
  78. */
  79. static struct fb_ops tx3912fb_ops = {
  80. .owner = THIS_MODULE,
  81. .fb_setcolreg = tx3912fb_setcolreg,
  82. .fb_fillrect = cfb_fillrect,
  83. .fb_copyarea = cfb_copyarea,
  84. .fb_imageblit = cfb_imageblit,
  85. };
  86. static int tx3912fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
  87. {
  88. /*
  89. * Memory limit
  90. */
  91. line_length =
  92. get_line_length(var->xres_virtual, var->bits_per_pixel);
  93. if ((line_length * var->yres_virtual) > info->fix.smem_len)
  94. return -ENOMEM;
  95. return 0;
  96. }
  97. static int tx3912fb_set_par(struct fb_info *info)
  98. {
  99. u_long tx3912fb_paddr = 0;
  100. /* Disable the video logic */
  101. outl(inl(TX3912_VIDEO_CTRL1) &
  102. ~(TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
  103. TX3912_VIDEO_CTRL1);
  104. udelay(200);
  105. /* Set start address for DMA transfer */
  106. outl(tx3912fb_paddr, TX3912_VIDEO_CTRL3);
  107. /* Set end address for DMA transfer */
  108. outl((tx3912fb_paddr + tx3912fb_fix.smem_len + 1), TX3912_VIDEO_CTRL4);
  109. /* Set the pixel depth */
  110. switch (info->var.bits_per_pixel) {
  111. case 1:
  112. /* Monochrome */
  113. outl(inl(TX3912_VIDEO_CTRL1) &
  114. ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
  115. info->fix.visual = FB_VISUAL_MONO10;
  116. break;
  117. case 4:
  118. /* 4-bit gray */
  119. outl(inl(TX3912_VIDEO_CTRL1) &
  120. ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
  121. outl(inl(TX3912_VIDEO_CTRL1) |
  122. TX3912_VIDEO_CTRL1_BITSEL_4BIT_GRAY,
  123. TX3912_VIDEO_CTRL1);
  124. info->fix.visual = FB_VISUAL_TRUECOLOR;
  125. break;
  126. case 8:
  127. /* 8-bit color */
  128. outl(inl(TX3912_VIDEO_CTRL1) &
  129. ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
  130. outl(inl(TX3912_VIDEO_CTRL1) |
  131. TX3912_VIDEO_CTRL1_BITSEL_8BIT_COLOR,
  132. TX3912_VIDEO_CTRL1);
  133. info->fix.visual = FB_VISUAL_TRUECOLOR;
  134. break;
  135. case 2:
  136. default:
  137. /* 2-bit gray */
  138. outl(inl(TX3912_VIDEO_CTRL1) &
  139. ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
  140. outl(inl(TX3912_VIDEO_CTRL1) |
  141. TX3912_VIDEO_CTRL1_BITSEL_2BIT_GRAY,
  142. TX3912_VIDEO_CTRL1);
  143. info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
  144. break;
  145. }
  146. /* Enable the video clock */
  147. outl(inl(TX3912_CLK_CTRL) | TX3912_CLK_CTRL_ENVIDCLK,
  148. TX3912_CLK_CTRL);
  149. /* Unfreeze video logic and enable DF toggle */
  150. outl(inl(TX3912_VIDEO_CTRL1) &
  151. ~(TX3912_VIDEO_CTRL1_ENFREEZEFRAME |
  152. TX3912_VIDEO_CTRL1_DFMODE)
  153. , TX3912_VIDEO_CTRL1);
  154. udelay(200);
  155. /* Enable the video logic */
  156. outl(inl(TX3912_VIDEO_CTRL1) |
  157. (TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
  158. TX3912_VIDEO_CTRL1);
  159. info->fix.line_length = get_line_length(var->xres_virtual,
  160. var->bits_per_pixel);
  161. }
  162. /*
  163. * Set a single color register
  164. */
  165. static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green,
  166. u_int blue, u_int transp,
  167. struct fb_info *info)
  168. {
  169. if (regno > 255)
  170. return 1;
  171. if (regno < 16)
  172. ((u32 *)(info->pseudo_palette))[regno] = ((red & 0xe000) >> 8)
  173. | ((green & 0xe000) >> 11)
  174. | ((blue & 0xc000) >> 14);
  175. return 0;
  176. }
  177. int __init tx3912fb_setup(char *options);
  178. /*
  179. * Initialization of the framebuffer
  180. */
  181. int __init tx3912fb_init(void)
  182. {
  183. u_long tx3912fb_paddr = 0;
  184. int size = (info->var.bits_per_pixel == 8) ? 256 : 16;
  185. char *option = NULL;
  186. if (fb_get_options("tx3912fb", &option))
  187. return -ENODEV;
  188. tx3912fb_setup(option);
  189. /* Disable the video logic */
  190. outl(inl(TX3912_VIDEO_CTRL1) &
  191. ~(TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
  192. TX3912_VIDEO_CTRL1);
  193. udelay(200);
  194. /* Set start address for DMA transfer */
  195. outl(tx3912fb_paddr, TX3912_VIDEO_CTRL3);
  196. /* Set end address for DMA transfer */
  197. outl((tx3912fb_paddr + tx3912fb_fix.smem_len + 1), TX3912_VIDEO_CTRL4);
  198. /* Set the pixel depth */
  199. switch (tx3912fb_var.bits_per_pixel) {
  200. case 1:
  201. /* Monochrome */
  202. outl(inl(TX3912_VIDEO_CTRL1) &
  203. ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
  204. tx3912fb_fix.visual = FB_VISUAL_MONO10;
  205. break;
  206. case 4:
  207. /* 4-bit gray */
  208. outl(inl(TX3912_VIDEO_CTRL1) &
  209. ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
  210. outl(inl(TX3912_VIDEO_CTRL1) |
  211. TX3912_VIDEO_CTRL1_BITSEL_4BIT_GRAY,
  212. TX3912_VIDEO_CTRL1);
  213. tx3912fb_fix.visual = FB_VISUAL_TRUECOLOR;
  214. tx3912fb_fix.grayscale = 1;
  215. break;
  216. case 8:
  217. /* 8-bit color */
  218. outl(inl(TX3912_VIDEO_CTRL1) &
  219. ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
  220. outl(inl(TX3912_VIDEO_CTRL1) |
  221. TX3912_VIDEO_CTRL1_BITSEL_8BIT_COLOR,
  222. TX3912_VIDEO_CTRL1);
  223. tx3912fb_fix.visual = FB_VISUAL_TRUECOLOR;
  224. break;
  225. case 2:
  226. default:
  227. /* 2-bit gray */
  228. outl(inl(TX3912_VIDEO_CTRL1) &
  229. ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
  230. outl(inl(TX3912_VIDEO_CTRL1) |
  231. TX3912_VIDEO_CTRL1_BITSEL_2BIT_GRAY,
  232. TX3912_VIDEO_CTRL1);
  233. tx3912fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
  234. tx3912fb_fix.grayscale = 1;
  235. break;
  236. }
  237. /* Enable the video clock */
  238. outl(inl(TX3912_CLK_CTRL) | TX3912_CLK_CTRL_ENVIDCLK,
  239. TX3912_CLK_CTRL);
  240. /* Unfreeze video logic and enable DF toggle */
  241. outl(inl(TX3912_VIDEO_CTRL1) &
  242. ~(TX3912_VIDEO_CTRL1_ENFREEZEFRAME | TX3912_VIDEO_CTRL1_DFMODE),
  243. TX3912_VIDEO_CTRL1);
  244. udelay(200);
  245. /* Clear the framebuffer */
  246. memset((void *) tx3912fb_fix.smem_start, 0xff, tx3912fb_fix.smem_len);
  247. udelay(200);
  248. /* Enable the video logic */
  249. outl(inl(TX3912_VIDEO_CTRL1) |
  250. (TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
  251. TX3912_VIDEO_CTRL1);
  252. /*
  253. * Memory limit
  254. */
  255. tx3912fb_fix.line_length =
  256. get_line_length(tx3912fb_var.xres_virtual, tx3912fb_var.bits_per_pixel);
  257. if ((tx3912fb_fix.line_length * tx3912fb_var.yres_virtual) > tx3912fb_fix.smem_len)
  258. return -ENOMEM;
  259. fb_info.fbops = &tx3912fb_ops;
  260. fb_info.var = tx3912fb_var;
  261. fb_info.fix = tx3912fb_fix;
  262. fb_info.pseudo_palette = pseudo_palette;
  263. fb_info.flags = FBINFO_DEFAULT;
  264. /* Clear the framebuffer */
  265. memset((void *) fb_info.fix.smem_start, 0xff, fb_info.fix.smem_len);
  266. udelay(200);
  267. fb_alloc_cmap(&info->cmap, size, 0);
  268. if (register_framebuffer(&fb_info) < 0)
  269. return -1;
  270. printk(KERN_INFO "fb%d: TX3912 frame buffer using %uKB.\n",
  271. fb_info.node, (u_int) (fb_info.fix.smem_len >> 10));
  272. return 0;
  273. }
  274. int __init tx3912fb_setup(char *options)
  275. {
  276. char *this_opt;
  277. if (!options || !*options)
  278. return 0;
  279. while ((this_opt = strsep(&options, ","))) {
  280. if (!strncmp(options, "bpp:", 4))
  281. tx3912fb_var.bits_per_pixel = simple_strtoul(options+4, NULL, 0);
  282. }
  283. return 0;
  284. }
  285. module_init(tx3912fb_init);
  286. MODULE_LICENSE("GPL");