carminefb.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Frame buffer driver for the Carmine GPU.
  4. *
  5. * The driver configures the GPU as follows
  6. * - FB0 is display 0 with unique memory area
  7. * - FB1 is display 1 with unique memory area
  8. * - both display use 32 bit colors
  9. */
  10. #include <linux/aperture.h>
  11. #include <linux/delay.h>
  12. #include <linux/errno.h>
  13. #include <linux/fb.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/pci.h>
  16. #include <linux/slab.h>
  17. #include <linux/module.h>
  18. #include "carminefb.h"
  19. #include "carminefb_regs.h"
  20. #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
  21. #error "The endianness of the target host has not been defined."
  22. #endif
  23. /*
  24. * The initial video mode can be supplied via two different ways:
  25. * - as a string that is passed to fb_find_mode() (module option fb_mode_str)
  26. * - as an integer that picks the video mode from carmine_modedb[] (module
  27. * option fb_mode)
  28. *
  29. * If nothing is used than the initial video mode will be the
  30. * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[].
  31. */
  32. #define CARMINEFB_DEFAULT_VIDEO_MODE 1
  33. static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
  34. module_param(fb_mode, uint, 0444);
  35. MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
  36. static char *fb_mode_str;
  37. module_param(fb_mode_str, charp, 0444);
  38. MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
  39. /*
  40. * Carminefb displays:
  41. * 0b000 None
  42. * 0b001 Display 0
  43. * 0b010 Display 1
  44. */
  45. static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
  46. module_param(fb_displays, int, 0444);
  47. MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
  48. struct carmine_hw {
  49. void __iomem *v_regs;
  50. void __iomem *screen_mem;
  51. struct fb_info *fb[MAX_DISPLAY];
  52. };
  53. struct carmine_resolution {
  54. u32 htp;
  55. u32 hsp;
  56. u32 hsw;
  57. u32 hdp;
  58. u32 vtr;
  59. u32 vsp;
  60. u32 vsw;
  61. u32 vdp;
  62. u32 disp_mode;
  63. };
  64. struct carmine_fb {
  65. void __iomem *display_reg;
  66. void __iomem *screen_base;
  67. u32 smem_offset;
  68. u32 cur_mode;
  69. u32 new_mode;
  70. struct carmine_resolution *res;
  71. u32 pseudo_palette[16];
  72. };
  73. static struct fb_fix_screeninfo carminefb_fix = {
  74. .id = "Carmine",
  75. .type = FB_TYPE_PACKED_PIXELS,
  76. .visual = FB_VISUAL_TRUECOLOR,
  77. .accel = FB_ACCEL_NONE,
  78. };
  79. static const struct fb_videomode carmine_modedb[] = {
  80. {
  81. .name = "640x480",
  82. .xres = 640,
  83. .yres = 480,
  84. }, {
  85. .name = "800x600",
  86. .xres = 800,
  87. .yres = 600,
  88. },
  89. };
  90. static struct carmine_resolution car_modes[] = {
  91. {
  92. /* 640x480 */
  93. .htp = 800,
  94. .hsp = 672,
  95. .hsw = 96,
  96. .hdp = 640,
  97. .vtr = 525,
  98. .vsp = 490,
  99. .vsw = 2,
  100. .vdp = 480,
  101. .disp_mode = 0x1400,
  102. },
  103. {
  104. /* 800x600 */
  105. .htp = 1060,
  106. .hsp = 864,
  107. .hsw = 72,
  108. .hdp = 800,
  109. .vtr = 628,
  110. .vsp = 601,
  111. .vsw = 2,
  112. .vdp = 600,
  113. .disp_mode = 0x0d00,
  114. }
  115. };
  116. static int carmine_find_mode(const struct fb_var_screeninfo *var)
  117. {
  118. int i;
  119. for (i = 0; i < ARRAY_SIZE(car_modes); i++)
  120. if (car_modes[i].hdp == var->xres &&
  121. car_modes[i].vdp == var->yres)
  122. return i;
  123. return -EINVAL;
  124. }
  125. static void c_set_disp_reg(const struct carmine_fb *par,
  126. u32 offset, u32 val)
  127. {
  128. writel(val, par->display_reg + offset);
  129. }
  130. static u32 c_get_disp_reg(const struct carmine_fb *par,
  131. u32 offset)
  132. {
  133. return readl(par->display_reg + offset);
  134. }
  135. static void c_set_hw_reg(const struct carmine_hw *hw,
  136. u32 offset, u32 val)
  137. {
  138. writel(val, hw->v_regs + offset);
  139. }
  140. static u32 c_get_hw_reg(const struct carmine_hw *hw,
  141. u32 offset)
  142. {
  143. return readl(hw->v_regs + offset);
  144. }
  145. static int carmine_setcolreg(unsigned regno, unsigned red, unsigned green,
  146. unsigned blue, unsigned transp, struct fb_info *info)
  147. {
  148. if (regno >= 16)
  149. return 1;
  150. red >>= 8;
  151. green >>= 8;
  152. blue >>= 8;
  153. transp >>= 8;
  154. ((__be32 *)info->pseudo_palette)[regno] = cpu_to_be32(transp << 24 |
  155. red << 0 | green << 8 | blue << 16);
  156. return 0;
  157. }
  158. static int carmine_check_var(struct fb_var_screeninfo *var,
  159. struct fb_info *info)
  160. {
  161. int ret;
  162. ret = carmine_find_mode(var);
  163. if (ret < 0)
  164. return ret;
  165. if (var->grayscale || var->rotate || var->nonstd)
  166. return -EINVAL;
  167. var->xres_virtual = var->xres;
  168. var->yres_virtual = var->yres;
  169. var->bits_per_pixel = 32;
  170. #ifdef __BIG_ENDIAN
  171. var->transp.offset = 24;
  172. var->red.offset = 0;
  173. var->green.offset = 8;
  174. var->blue.offset = 16;
  175. #else
  176. var->transp.offset = 24;
  177. var->red.offset = 16;
  178. var->green.offset = 8;
  179. var->blue.offset = 0;
  180. #endif
  181. var->red.length = 8;
  182. var->green.length = 8;
  183. var->blue.length = 8;
  184. var->transp.length = 8;
  185. var->red.msb_right = 0;
  186. var->green.msb_right = 0;
  187. var->blue.msb_right = 0;
  188. var->transp.msb_right = 0;
  189. return 0;
  190. }
  191. static void carmine_init_display_param(struct carmine_fb *par)
  192. {
  193. u32 width;
  194. u32 height;
  195. u32 param;
  196. u32 window_size;
  197. u32 soffset = par->smem_offset;
  198. c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0);
  199. c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0);
  200. c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE,
  201. CARMINE_CURSOR0_PRIORITY_MASK |
  202. CARMINE_CURSOR1_PRIORITY_MASK |
  203. CARMINE_CURSOR_CUTZ_MASK);
  204. /* Set default cursor position */
  205. c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0);
  206. c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0);
  207. /* Set default display mode */
  208. c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE |
  209. CARMINE_EXT_CMODE_DIRECT24_RGBA);
  210. c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE,
  211. CARMINE_EXT_CMODE_DIRECT24_RGBA);
  212. c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE |
  213. CARMINE_EXT_CMODE_DIRECT24_RGBA);
  214. c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE |
  215. CARMINE_EXT_CMODE_DIRECT24_RGBA);
  216. c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE |
  217. CARMINE_EXT_CMODE_DIRECT24_RGBA);
  218. c_set_disp_reg(par, CARMINE_DISP_REG_L5_EXT_MODE, CARMINE_EXTEND_MODE |
  219. CARMINE_EXT_CMODE_DIRECT24_RGBA);
  220. c_set_disp_reg(par, CARMINE_DISP_REG_L6_EXT_MODE, CARMINE_EXTEND_MODE |
  221. CARMINE_EXT_CMODE_DIRECT24_RGBA);
  222. c_set_disp_reg(par, CARMINE_DISP_REG_L7_EXT_MODE, CARMINE_EXTEND_MODE |
  223. CARMINE_EXT_CMODE_DIRECT24_RGBA);
  224. /* Set default frame size to layer mode register */
  225. width = par->res->hdp * 4 / CARMINE_DISP_WIDTH_UNIT;
  226. width = width << CARMINE_DISP_WIDTH_SHIFT;
  227. height = par->res->vdp - 1;
  228. param = width | height;
  229. c_set_disp_reg(par, CARMINE_DISP_REG_L0_MODE_W_H, param);
  230. c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIDTH, width);
  231. c_set_disp_reg(par, CARMINE_DISP_REG_L2_MODE_W_H, param);
  232. c_set_disp_reg(par, CARMINE_DISP_REG_L3_MODE_W_H, param);
  233. c_set_disp_reg(par, CARMINE_DISP_REG_L4_MODE_W_H, param);
  234. c_set_disp_reg(par, CARMINE_DISP_REG_L5_MODE_W_H, param);
  235. c_set_disp_reg(par, CARMINE_DISP_REG_L6_MODE_W_H, param);
  236. c_set_disp_reg(par, CARMINE_DISP_REG_L7_MODE_W_H, param);
  237. /* Set default pos and size */
  238. window_size = (par->res->vdp - 1) << CARMINE_DISP_WIN_H_SHIFT;
  239. window_size |= par->res->hdp;
  240. c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_POS, 0);
  241. c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_SIZE, window_size);
  242. c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_POS, 0);
  243. c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_SIZE, window_size);
  244. c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_POS, 0);
  245. c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_SIZE, window_size);
  246. c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_POS, 0);
  247. c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_SIZE, window_size);
  248. c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_POS, 0);
  249. c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_SIZE, window_size);
  250. c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_POS, 0);
  251. c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_SIZE, window_size);
  252. c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_POS, 0);
  253. c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_SIZE, window_size);
  254. c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_POS, 0);
  255. c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_SIZE, window_size);
  256. /* Set default origin address */
  257. c_set_disp_reg(par, CARMINE_DISP_REG_L0_ORG_ADR, soffset);
  258. c_set_disp_reg(par, CARMINE_DISP_REG_L1_ORG_ADR, soffset);
  259. c_set_disp_reg(par, CARMINE_DISP_REG_L2_ORG_ADR1, soffset);
  260. c_set_disp_reg(par, CARMINE_DISP_REG_L3_ORG_ADR1, soffset);
  261. c_set_disp_reg(par, CARMINE_DISP_REG_L4_ORG_ADR1, soffset);
  262. c_set_disp_reg(par, CARMINE_DISP_REG_L5_ORG_ADR1, soffset);
  263. c_set_disp_reg(par, CARMINE_DISP_REG_L6_ORG_ADR1, soffset);
  264. c_set_disp_reg(par, CARMINE_DISP_REG_L7_ORG_ADR1, soffset);
  265. /* Set default display address */
  266. c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_ADR, soffset);
  267. c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_ADR1, soffset);
  268. c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_ADR1, soffset);
  269. c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_ADR1, soffset);
  270. c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_ADR1, soffset);
  271. c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_ADR0, soffset);
  272. c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_ADR0, soffset);
  273. /* Set default display position */
  274. c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_POS, 0);
  275. c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_POS, 0);
  276. c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_POS, 0);
  277. c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_POS, 0);
  278. c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_POS, 0);
  279. c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_POS, 0);
  280. c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_POS, 0);
  281. /* Set default blend mode */
  282. c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L0, 0);
  283. c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L1, 0);
  284. c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L2, 0);
  285. c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L3, 0);
  286. c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L4, 0);
  287. c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L5, 0);
  288. c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L6, 0);
  289. c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L7, 0);
  290. /* default transparency mode */
  291. c_set_disp_reg(par, CARMINE_DISP_REG_L0_TRANS, 0);
  292. c_set_disp_reg(par, CARMINE_DISP_REG_L1_TRANS, 0);
  293. c_set_disp_reg(par, CARMINE_DISP_REG_L2_TRANS, 0);
  294. c_set_disp_reg(par, CARMINE_DISP_REG_L3_TRANS, 0);
  295. c_set_disp_reg(par, CARMINE_DISP_REG_L4_TRANS, 0);
  296. c_set_disp_reg(par, CARMINE_DISP_REG_L5_TRANS, 0);
  297. c_set_disp_reg(par, CARMINE_DISP_REG_L6_TRANS, 0);
  298. c_set_disp_reg(par, CARMINE_DISP_REG_L7_TRANS, 0);
  299. /* Set default read skip parameter */
  300. c_set_disp_reg(par, CARMINE_DISP_REG_L0RM, 0);
  301. c_set_disp_reg(par, CARMINE_DISP_REG_L2RM, 0);
  302. c_set_disp_reg(par, CARMINE_DISP_REG_L3RM, 0);
  303. c_set_disp_reg(par, CARMINE_DISP_REG_L4RM, 0);
  304. c_set_disp_reg(par, CARMINE_DISP_REG_L5RM, 0);
  305. c_set_disp_reg(par, CARMINE_DISP_REG_L6RM, 0);
  306. c_set_disp_reg(par, CARMINE_DISP_REG_L7RM, 0);
  307. c_set_disp_reg(par, CARMINE_DISP_REG_L0PX, 0);
  308. c_set_disp_reg(par, CARMINE_DISP_REG_L2PX, 0);
  309. c_set_disp_reg(par, CARMINE_DISP_REG_L3PX, 0);
  310. c_set_disp_reg(par, CARMINE_DISP_REG_L4PX, 0);
  311. c_set_disp_reg(par, CARMINE_DISP_REG_L5PX, 0);
  312. c_set_disp_reg(par, CARMINE_DISP_REG_L6PX, 0);
  313. c_set_disp_reg(par, CARMINE_DISP_REG_L7PX, 0);
  314. c_set_disp_reg(par, CARMINE_DISP_REG_L0PY, 0);
  315. c_set_disp_reg(par, CARMINE_DISP_REG_L2PY, 0);
  316. c_set_disp_reg(par, CARMINE_DISP_REG_L3PY, 0);
  317. c_set_disp_reg(par, CARMINE_DISP_REG_L4PY, 0);
  318. c_set_disp_reg(par, CARMINE_DISP_REG_L5PY, 0);
  319. c_set_disp_reg(par, CARMINE_DISP_REG_L6PY, 0);
  320. c_set_disp_reg(par, CARMINE_DISP_REG_L7PY, 0);
  321. }
  322. static void set_display_parameters(struct carmine_fb *par)
  323. {
  324. u32 mode;
  325. u32 hdp, vdp, htp, hsp, hsw, vtr, vsp, vsw;
  326. /*
  327. * display timing. Parameters are decreased by one because hardware
  328. * spec is 0 to (n - 1)
  329. * */
  330. hdp = par->res->hdp - 1;
  331. vdp = par->res->vdp - 1;
  332. htp = par->res->htp - 1;
  333. hsp = par->res->hsp - 1;
  334. hsw = par->res->hsw - 1;
  335. vtr = par->res->vtr - 1;
  336. vsp = par->res->vsp - 1;
  337. vsw = par->res->vsw - 1;
  338. c_set_disp_reg(par, CARMINE_DISP_REG_H_TOTAL,
  339. htp << CARMINE_DISP_HTP_SHIFT);
  340. c_set_disp_reg(par, CARMINE_DISP_REG_H_PERIOD,
  341. (hdp << CARMINE_DISP_HDB_SHIFT) | hdp);
  342. c_set_disp_reg(par, CARMINE_DISP_REG_V_H_W_H_POS,
  343. (vsw << CARMINE_DISP_VSW_SHIFT) |
  344. (hsw << CARMINE_DISP_HSW_SHIFT) |
  345. (hsp));
  346. c_set_disp_reg(par, CARMINE_DISP_REG_V_TOTAL,
  347. vtr << CARMINE_DISP_VTR_SHIFT);
  348. c_set_disp_reg(par, CARMINE_DISP_REG_V_PERIOD_POS,
  349. (vdp << CARMINE_DISP_VDP_SHIFT) | vsp);
  350. /* clock */
  351. mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1);
  352. mode = (mode & ~CARMINE_DISP_DCM_MASK) |
  353. (par->res->disp_mode & CARMINE_DISP_DCM_MASK);
  354. /* enable video output and layer 0 */
  355. mode |= CARMINE_DEN | CARMINE_L0E;
  356. c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode);
  357. }
  358. static int carmine_set_par(struct fb_info *info)
  359. {
  360. struct carmine_fb *par = info->par;
  361. int ret;
  362. ret = carmine_find_mode(&info->var);
  363. if (ret < 0)
  364. return ret;
  365. par->new_mode = ret;
  366. if (par->cur_mode != par->new_mode) {
  367. par->cur_mode = par->new_mode;
  368. par->res = &car_modes[par->new_mode];
  369. carmine_init_display_param(par);
  370. set_display_parameters(par);
  371. }
  372. info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
  373. return 0;
  374. }
  375. static int init_hardware(struct carmine_hw *hw)
  376. {
  377. u32 flags;
  378. u32 loops;
  379. u32 ret;
  380. /* Initialize Carmine */
  381. /* Sets internal clock */
  382. c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,
  383. CARMINE_DFLT_IP_CLOCK_ENABLE);
  384. /* Video signal output is turned off */
  385. c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
  386. c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
  387. /* Software reset */
  388. c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1);
  389. c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0);
  390. /* I/O mode settings */
  391. flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 |
  392. CARMINE_DFLT_IP_DCTL_IO_CONT0;
  393. c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0,
  394. flags);
  395. /* DRAM initial sequence */
  396. flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD;
  397. c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD,
  398. flags);
  399. flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 |
  400. CARMINE_DFLT_IP_DCTL_EMODE;
  401. c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE,
  402. flags);
  403. flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 |
  404. CARMINE_DFLT_IP_DCTL_SET_TIME2;
  405. c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2,
  406. flags);
  407. flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 |
  408. CARMINE_DFLT_IP_DCTL_FIFO_DEPTH;
  409. c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags);
  410. flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1;
  411. c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1,
  412. flags);
  413. flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
  414. CARMINE_DFLT_IP_DCTL_STATES;
  415. c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
  416. flags);
  417. /* Executes DLL reset */
  418. if (CARMINE_DCTL_DLL_RESET) {
  419. for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) {
  420. ret = c_get_hw_reg(hw, CARMINE_DCTL_REG +
  421. CARMINE_DCTL_REG_RSV0_STATES);
  422. ret &= CARMINE_DCTL_REG_STATES_MASK;
  423. if (!ret)
  424. break;
  425. mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL);
  426. }
  427. if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) {
  428. printk(KERN_ERR "DRAM init failed\n");
  429. return -EIO;
  430. }
  431. }
  432. flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 |
  433. CARMINE_DFLT_IP_DCTL_ADD;
  434. c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags);
  435. flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
  436. CARMINE_DFLT_IP_DCTL_STATES_AFT_RST;
  437. c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
  438. flags);
  439. /* Initialize the write back register */
  440. c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM,
  441. CARMINE_WB_REG_WBM_DEFAULT);
  442. /* Initialize the Kottos registers */
  443. c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0);
  444. c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0);
  445. /* Set DC offsets */
  446. c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0);
  447. c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0);
  448. c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0);
  449. c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0);
  450. c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0);
  451. c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0);
  452. return 0;
  453. }
  454. static const struct fb_ops carminefb_ops = {
  455. .owner = THIS_MODULE,
  456. .fb_fillrect = cfb_fillrect,
  457. .fb_copyarea = cfb_copyarea,
  458. .fb_imageblit = cfb_imageblit,
  459. .fb_check_var = carmine_check_var,
  460. .fb_set_par = carmine_set_par,
  461. .fb_setcolreg = carmine_setcolreg,
  462. };
  463. static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
  464. int smem_offset, struct device *device,
  465. struct fb_info **rinfo)
  466. {
  467. int ret;
  468. struct fb_info *info;
  469. struct carmine_fb *par;
  470. info = framebuffer_alloc(sizeof *par, device);
  471. if (!info)
  472. return -ENOMEM;
  473. par = info->par;
  474. par->display_reg = regs;
  475. par->smem_offset = smem_offset;
  476. info->screen_base = smem_base + smem_offset;
  477. info->screen_size = CARMINE_DISPLAY_MEM;
  478. info->fbops = &carminefb_ops;
  479. info->fix = carminefb_fix;
  480. info->pseudo_palette = par->pseudo_palette;
  481. info->flags = FBINFO_DEFAULT;
  482. ret = fb_alloc_cmap(&info->cmap, 256, 1);
  483. if (ret < 0)
  484. goto err_free_fb;
  485. if (fb_mode >= ARRAY_SIZE(carmine_modedb))
  486. fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
  487. par->cur_mode = par->new_mode = ~0;
  488. ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb,
  489. ARRAY_SIZE(carmine_modedb),
  490. &carmine_modedb[fb_mode], 32);
  491. if (!ret || ret == 4) {
  492. ret = -EINVAL;
  493. goto err_dealloc_cmap;
  494. }
  495. fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb),
  496. &info->modelist);
  497. ret = register_framebuffer(info);
  498. if (ret < 0)
  499. goto err_dealloc_cmap;
  500. fb_info(info, "%s frame buffer device\n", info->fix.id);
  501. *rinfo = info;
  502. return 0;
  503. err_dealloc_cmap:
  504. fb_dealloc_cmap(&info->cmap);
  505. err_free_fb:
  506. framebuffer_release(info);
  507. return ret;
  508. }
  509. static void cleanup_fb_device(struct fb_info *info)
  510. {
  511. if (info) {
  512. unregister_framebuffer(info);
  513. fb_dealloc_cmap(&info->cmap);
  514. framebuffer_release(info);
  515. }
  516. }
  517. static int carminefb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
  518. {
  519. struct carmine_hw *hw;
  520. struct device *device = &dev->dev;
  521. struct fb_info *info;
  522. int ret;
  523. ret = aperture_remove_conflicting_pci_devices(dev, "carminefb");
  524. if (ret)
  525. return ret;
  526. ret = pci_enable_device(dev);
  527. if (ret)
  528. return ret;
  529. ret = -ENOMEM;
  530. hw = kzalloc(sizeof *hw, GFP_KERNEL);
  531. if (!hw)
  532. goto err_enable_pci;
  533. carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR);
  534. carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR);
  535. if (!request_mem_region(carminefb_fix.mmio_start,
  536. carminefb_fix.mmio_len,
  537. "carminefb regbase")) {
  538. printk(KERN_ERR "carminefb: Can't reserve regbase.\n");
  539. ret = -EBUSY;
  540. goto err_free_hw;
  541. }
  542. hw->v_regs = ioremap(carminefb_fix.mmio_start,
  543. carminefb_fix.mmio_len);
  544. if (!hw->v_regs) {
  545. printk(KERN_ERR "carminefb: Can't remap %s register.\n",
  546. carminefb_fix.id);
  547. goto err_free_reg_mmio;
  548. }
  549. carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR);
  550. carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR);
  551. /* The memory area tends to be very large (256 MiB). Remap only what
  552. * is required for that largest resolution to avoid remaps at run
  553. * time
  554. */
  555. if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM)
  556. carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM;
  557. else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) {
  558. printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "
  559. "are required.", carminefb_fix.smem_len,
  560. CARMINE_TOTAL_DIPLAY_MEM);
  561. goto err_unmap_vregs;
  562. }
  563. if (!request_mem_region(carminefb_fix.smem_start,
  564. carminefb_fix.smem_len, "carminefb smem")) {
  565. printk(KERN_ERR "carminefb: Can't reserve smem.\n");
  566. goto err_unmap_vregs;
  567. }
  568. hw->screen_mem = ioremap(carminefb_fix.smem_start,
  569. carminefb_fix.smem_len);
  570. if (!hw->screen_mem) {
  571. printk(KERN_ERR "carmine: Can't ioremap smem area.\n");
  572. goto err_reg_smem;
  573. }
  574. ret = init_hardware(hw);
  575. if (ret)
  576. goto err_unmap_screen;
  577. info = NULL;
  578. if (fb_displays & CARMINE_USE_DISPLAY0) {
  579. ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG,
  580. hw->screen_mem, CARMINE_DISPLAY_MEM * 0,
  581. device, &info);
  582. if (ret)
  583. goto err_deinit_hw;
  584. }
  585. hw->fb[0] = info;
  586. info = NULL;
  587. if (fb_displays & CARMINE_USE_DISPLAY1) {
  588. ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG,
  589. hw->screen_mem, CARMINE_DISPLAY_MEM * 1,
  590. device, &info);
  591. if (ret)
  592. goto err_cleanup_fb0;
  593. }
  594. hw->fb[1] = info;
  595. info = NULL;
  596. pci_set_drvdata(dev, hw);
  597. return 0;
  598. err_cleanup_fb0:
  599. cleanup_fb_device(hw->fb[0]);
  600. err_deinit_hw:
  601. /* disable clock, etc */
  602. c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
  603. err_unmap_screen:
  604. iounmap(hw->screen_mem);
  605. err_reg_smem:
  606. release_mem_region(carminefb_fix.smem_start, carminefb_fix.smem_len);
  607. err_unmap_vregs:
  608. iounmap(hw->v_regs);
  609. err_free_reg_mmio:
  610. release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
  611. err_free_hw:
  612. kfree(hw);
  613. err_enable_pci:
  614. pci_disable_device(dev);
  615. return ret;
  616. }
  617. static void carminefb_remove(struct pci_dev *dev)
  618. {
  619. struct carmine_hw *hw = pci_get_drvdata(dev);
  620. struct fb_fix_screeninfo fix;
  621. int i;
  622. /* in case we use only fb1 and not fb1 */
  623. if (hw->fb[0])
  624. fix = hw->fb[0]->fix;
  625. else
  626. fix = hw->fb[1]->fix;
  627. /* deactivate display(s) and switch clocks */
  628. c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
  629. c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
  630. c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
  631. for (i = 0; i < MAX_DISPLAY; i++)
  632. cleanup_fb_device(hw->fb[i]);
  633. iounmap(hw->screen_mem);
  634. release_mem_region(fix.smem_start, fix.smem_len);
  635. iounmap(hw->v_regs);
  636. release_mem_region(fix.mmio_start, fix.mmio_len);
  637. pci_disable_device(dev);
  638. kfree(hw);
  639. }
  640. #define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf
  641. static struct pci_device_id carmine_devices[] = {
  642. {
  643. PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)},
  644. {0, 0, 0, 0, 0, 0, 0}
  645. };
  646. MODULE_DEVICE_TABLE(pci, carmine_devices);
  647. static struct pci_driver carmine_pci_driver = {
  648. .name = "carminefb",
  649. .id_table = carmine_devices,
  650. .probe = carminefb_probe,
  651. .remove = carminefb_remove,
  652. };
  653. static int __init carminefb_init(void)
  654. {
  655. if (!(fb_displays &
  656. (CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) {
  657. printk(KERN_ERR "If you disable both displays than you don't "
  658. "need the driver at all\n");
  659. return -EINVAL;
  660. }
  661. return pci_register_driver(&carmine_pci_driver);
  662. }
  663. module_init(carminefb_init);
  664. static void __exit carminefb_cleanup(void)
  665. {
  666. pci_unregister_driver(&carmine_pci_driver);
  667. }
  668. module_exit(carminefb_cleanup);
  669. MODULE_AUTHOR("Sebastian Siewior <[email protected]>");
  670. MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices");
  671. MODULE_LICENSE("GPL v2");