carminefb.c 22 KB

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