carminefb.c 22 KB

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