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