sm750_hw.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. #include <linux/version.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/errno.h>
  5. #include <linux/string.h>
  6. #include <linux/mm.h>
  7. #include <linux/slab.h>
  8. #include <linux/delay.h>
  9. #include <linux/fb.h>
  10. #include <linux/ioport.h>
  11. #include <linux/init.h>
  12. #include <linux/pci.h>
  13. #include <linux/vmalloc.h>
  14. #include <linux/pagemap.h>
  15. #include <linux/console.h>
  16. #ifdef CONFIG_MTRR
  17. #include <asm/mtrr.h>
  18. #endif
  19. #include <linux/platform_device.h>
  20. #include <linux/screen_info.h>
  21. #include <linux/sizes.h>
  22. #include "sm750.h"
  23. #include "ddk750.h"
  24. #include "sm750_accel.h"
  25. int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
  26. {
  27. int ret;
  28. ret = 0;
  29. sm750_dev->vidreg_start = pci_resource_start(pdev, 1);
  30. sm750_dev->vidreg_size = SZ_2M;
  31. pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start);
  32. /* reserve the vidreg space of smi adaptor
  33. * if you do this, u need to add release region code
  34. * in lynxfb_remove, or memory will not be mapped again
  35. * successfully
  36. * */
  37. ret = pci_request_region(pdev, 1, "sm750fb");
  38. if (ret) {
  39. pr_err("Can not request PCI regions.\n");
  40. goto exit;
  41. }
  42. /* now map mmio and vidmem*/
  43. sm750_dev->pvReg = ioremap_nocache(sm750_dev->vidreg_start,
  44. sm750_dev->vidreg_size);
  45. if (!sm750_dev->pvReg) {
  46. pr_err("mmio failed\n");
  47. ret = -EFAULT;
  48. goto exit;
  49. } else {
  50. pr_info("mmio virtual addr = %p\n", sm750_dev->pvReg);
  51. }
  52. sm750_dev->accel.dprBase = sm750_dev->pvReg + DE_BASE_ADDR_TYPE1;
  53. sm750_dev->accel.dpPortBase = sm750_dev->pvReg + DE_PORT_ADDR_TYPE1;
  54. ddk750_set_mmio(sm750_dev->pvReg, sm750_dev->devid, sm750_dev->revid);
  55. sm750_dev->vidmem_start = pci_resource_start(pdev, 0);
  56. /* don't use pdev_resource[x].end - resource[x].start to
  57. * calculate the resource size,its only the maximum available
  58. * size but not the actual size,use
  59. * @ddk750_getVMSize function can be safe.
  60. * */
  61. sm750_dev->vidmem_size = ddk750_getVMSize();
  62. pr_info("video memory phyAddr = %lx, size = %u bytes\n",
  63. sm750_dev->vidmem_start, sm750_dev->vidmem_size);
  64. /* reserve the vidmem space of smi adaptor */
  65. sm750_dev->pvMem = ioremap_wc(sm750_dev->vidmem_start,
  66. sm750_dev->vidmem_size);
  67. if (!sm750_dev->pvMem) {
  68. pr_err("Map video memory failed\n");
  69. ret = -EFAULT;
  70. goto exit;
  71. } else {
  72. pr_info("video memory vaddr = %p\n", sm750_dev->pvMem);
  73. }
  74. exit:
  75. return ret;
  76. }
  77. int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
  78. {
  79. struct init_status *parm;
  80. parm = &sm750_dev->initParm;
  81. if (parm->chip_clk == 0)
  82. parm->chip_clk = (getChipType() == SM750LE) ?
  83. DEFAULT_SM750LE_CHIP_CLOCK :
  84. DEFAULT_SM750_CHIP_CLOCK;
  85. if (parm->mem_clk == 0)
  86. parm->mem_clk = parm->chip_clk;
  87. if (parm->master_clk == 0)
  88. parm->master_clk = parm->chip_clk/3;
  89. ddk750_initHw((initchip_param_t *)&sm750_dev->initParm);
  90. /* for sm718,open pci burst */
  91. if (sm750_dev->devid == 0x718) {
  92. POKE32(SYSTEM_CTRL,
  93. FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON));
  94. }
  95. if (getChipType() != SM750LE) {
  96. /* does user need CRT ?*/
  97. if (sm750_dev->nocrt) {
  98. POKE32(MISC_CTRL,
  99. FIELD_SET(PEEK32(MISC_CTRL),
  100. MISC_CTRL,
  101. DAC_POWER, OFF));
  102. /* shut off dpms */
  103. POKE32(SYSTEM_CTRL,
  104. FIELD_SET(PEEK32(SYSTEM_CTRL),
  105. SYSTEM_CTRL,
  106. DPMS, VNHN));
  107. } else {
  108. POKE32(MISC_CTRL,
  109. FIELD_SET(PEEK32(MISC_CTRL),
  110. MISC_CTRL,
  111. DAC_POWER, ON));
  112. /* turn on dpms */
  113. POKE32(SYSTEM_CTRL,
  114. FIELD_SET(PEEK32(SYSTEM_CTRL),
  115. SYSTEM_CTRL,
  116. DPMS, VPHP));
  117. }
  118. switch (sm750_dev->pnltype) {
  119. case sm750_doubleTFT:
  120. case sm750_24TFT:
  121. case sm750_dualTFT:
  122. POKE32(PANEL_DISPLAY_CTRL,
  123. FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL),
  124. PANEL_DISPLAY_CTRL,
  125. TFT_DISP,
  126. sm750_dev->pnltype));
  127. break;
  128. }
  129. } else {
  130. /* for 750LE ,no DVI chip initilization makes Monitor no signal */
  131. /* Set up GPIO for software I2C to program DVI chip in the
  132. Xilinx SP605 board, in order to have video signal.
  133. */
  134. sm750_sw_i2c_init(0, 1);
  135. /* Customer may NOT use CH7301 DVI chip, which has to be
  136. initialized differently.
  137. */
  138. if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) {
  139. /* The following register values for CH7301 are from
  140. Chrontel app note and our experiment.
  141. */
  142. pr_info("yes,CH7301 DVI chip found\n");
  143. sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16);
  144. sm750_sw_i2c_write_reg(0xec, 0x21, 0x9);
  145. sm750_sw_i2c_write_reg(0xec, 0x49, 0xC0);
  146. pr_info("okay,CH7301 DVI chip setup done\n");
  147. }
  148. }
  149. /* init 2d engine */
  150. if (!sm750_dev->accel_off)
  151. hw_sm750_initAccel(sm750_dev);
  152. return 0;
  153. }
  154. int hw_sm750_output_setMode(struct lynxfb_output *output,
  155. struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
  156. {
  157. int ret;
  158. disp_output_t dispSet;
  159. int channel;
  160. ret = 0;
  161. dispSet = 0;
  162. channel = *output->channel;
  163. if (getChipType() != SM750LE) {
  164. if (channel == sm750_primary) {
  165. pr_info("primary channel\n");
  166. if (output->paths & sm750_panel)
  167. dispSet |= do_LCD1_PRI;
  168. if (output->paths & sm750_crt)
  169. dispSet |= do_CRT_PRI;
  170. } else {
  171. pr_info("secondary channel\n");
  172. if (output->paths & sm750_panel)
  173. dispSet |= do_LCD1_SEC;
  174. if (output->paths & sm750_crt)
  175. dispSet |= do_CRT_SEC;
  176. }
  177. ddk750_setLogicalDispOut(dispSet);
  178. } else {
  179. /* just open DISPLAY_CONTROL_750LE register bit 3:0*/
  180. u32 reg;
  181. reg = PEEK32(DISPLAY_CONTROL_750LE);
  182. reg |= 0xf;
  183. POKE32(DISPLAY_CONTROL_750LE, reg);
  184. }
  185. pr_info("ddk setlogicdispout done\n");
  186. return ret;
  187. }
  188. int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var)
  189. {
  190. struct sm750_dev *sm750_dev;
  191. struct lynxfb_par *par = container_of(crtc, struct lynxfb_par, crtc);
  192. sm750_dev = par->dev;
  193. switch (var->bits_per_pixel) {
  194. case 8:
  195. case 16:
  196. break;
  197. case 32:
  198. if (sm750_dev->revid == SM750LE_REVISION_ID) {
  199. pr_debug("750le do not support 32bpp\n");
  200. return -EINVAL;
  201. }
  202. break;
  203. default:
  204. return -EINVAL;
  205. }
  206. return 0;
  207. }
  208. /*
  209. set the controller's mode for @crtc charged with @var and @fix parameters
  210. */
  211. int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
  212. struct fb_var_screeninfo *var,
  213. struct fb_fix_screeninfo *fix)
  214. {
  215. int ret, fmt;
  216. u32 reg;
  217. mode_parameter_t modparm;
  218. clock_type_t clock;
  219. struct sm750_dev *sm750_dev;
  220. struct lynxfb_par *par;
  221. ret = 0;
  222. par = container_of(crtc, struct lynxfb_par, crtc);
  223. sm750_dev = par->dev;
  224. if (!sm750_dev->accel_off) {
  225. /* set 2d engine pixel format according to mode bpp */
  226. switch (var->bits_per_pixel) {
  227. case 8:
  228. fmt = 0;
  229. break;
  230. case 16:
  231. fmt = 1;
  232. break;
  233. case 32:
  234. default:
  235. fmt = 2;
  236. break;
  237. }
  238. hw_set2dformat(&sm750_dev->accel, fmt);
  239. }
  240. /* set timing */
  241. modparm.pixel_clock = ps_to_hz(var->pixclock);
  242. modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? POS:NEG;
  243. modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? POS:NEG;
  244. modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT) ? POS:NEG;
  245. modparm.horizontal_display_end = var->xres;
  246. modparm.horizontal_sync_width = var->hsync_len;
  247. modparm.horizontal_sync_start = var->xres + var->right_margin;
  248. modparm.horizontal_total = var->xres + var->left_margin + var->right_margin + var->hsync_len;
  249. modparm.vertical_display_end = var->yres;
  250. modparm.vertical_sync_height = var->vsync_len;
  251. modparm.vertical_sync_start = var->yres + var->lower_margin;
  252. modparm.vertical_total = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
  253. /* choose pll */
  254. if (crtc->channel != sm750_secondary)
  255. clock = PRIMARY_PLL;
  256. else
  257. clock = SECONDARY_PLL;
  258. pr_debug("Request pixel clock = %lu\n", modparm.pixel_clock);
  259. ret = ddk750_setModeTiming(&modparm, clock);
  260. if (ret) {
  261. pr_err("Set mode timing failed\n");
  262. goto exit;
  263. }
  264. if (crtc->channel != sm750_secondary) {
  265. /* set pitch, offset ,width,start address ,etc... */
  266. POKE32(PANEL_FB_ADDRESS,
  267. FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, CURRENT)|
  268. FIELD_SET(0, PANEL_FB_ADDRESS, EXT, LOCAL)|
  269. FIELD_VALUE(0, PANEL_FB_ADDRESS, ADDRESS, crtc->oScreen));
  270. reg = var->xres * (var->bits_per_pixel >> 3);
  271. /* crtc->channel is not equal to par->index on numeric,be aware of that */
  272. reg = ALIGN(reg, crtc->line_pad);
  273. POKE32(PANEL_FB_WIDTH,
  274. FIELD_VALUE(0, PANEL_FB_WIDTH, WIDTH, reg)|
  275. FIELD_VALUE(0, PANEL_FB_WIDTH, OFFSET, fix->line_length));
  276. POKE32(PANEL_WINDOW_WIDTH,
  277. FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH, var->xres - 1)|
  278. FIELD_VALUE(0, PANEL_WINDOW_WIDTH, X, var->xoffset));
  279. POKE32(PANEL_WINDOW_HEIGHT,
  280. FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, HEIGHT, var->yres_virtual - 1)|
  281. FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, Y, var->yoffset));
  282. POKE32(PANEL_PLANE_TL, 0);
  283. POKE32(PANEL_PLANE_BR,
  284. FIELD_VALUE(0, PANEL_PLANE_BR, BOTTOM, var->yres - 1)|
  285. FIELD_VALUE(0, PANEL_PLANE_BR, RIGHT, var->xres - 1));
  286. /* set pixel format */
  287. reg = PEEK32(PANEL_DISPLAY_CTRL);
  288. POKE32(PANEL_DISPLAY_CTRL,
  289. FIELD_VALUE(reg,
  290. PANEL_DISPLAY_CTRL, FORMAT,
  291. (var->bits_per_pixel >> 4)
  292. ));
  293. } else {
  294. /* not implemented now */
  295. POKE32(CRT_FB_ADDRESS, crtc->oScreen);
  296. reg = var->xres * (var->bits_per_pixel >> 3);
  297. /* crtc->channel is not equal to par->index on numeric,be aware of that */
  298. reg = ALIGN(reg, crtc->line_pad);
  299. POKE32(CRT_FB_WIDTH,
  300. FIELD_VALUE(0, CRT_FB_WIDTH, WIDTH, reg)|
  301. FIELD_VALUE(0, CRT_FB_WIDTH, OFFSET, fix->line_length));
  302. /* SET PIXEL FORMAT */
  303. reg = PEEK32(CRT_DISPLAY_CTRL);
  304. reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, FORMAT, var->bits_per_pixel >> 4);
  305. POKE32(CRT_DISPLAY_CTRL, reg);
  306. }
  307. exit:
  308. return ret;
  309. }
  310. int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
  311. ushort red, ushort green, ushort blue)
  312. {
  313. static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
  314. POKE32(add[crtc->channel] + index*4, (red<<16)|(green<<8)|blue);
  315. return 0;
  316. }
  317. int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank)
  318. {
  319. int dpms, crtdb;
  320. switch (blank) {
  321. case FB_BLANK_UNBLANK:
  322. dpms = CRT_DISPLAY_CTRL_DPMS_0;
  323. crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
  324. break;
  325. case FB_BLANK_NORMAL:
  326. dpms = CRT_DISPLAY_CTRL_DPMS_0;
  327. crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
  328. break;
  329. case FB_BLANK_VSYNC_SUSPEND:
  330. dpms = CRT_DISPLAY_CTRL_DPMS_2;
  331. crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
  332. break;
  333. case FB_BLANK_HSYNC_SUSPEND:
  334. dpms = CRT_DISPLAY_CTRL_DPMS_1;
  335. crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
  336. break;
  337. case FB_BLANK_POWERDOWN:
  338. dpms = CRT_DISPLAY_CTRL_DPMS_3;
  339. crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
  340. break;
  341. default:
  342. return -EINVAL;
  343. }
  344. if (output->paths & sm750_crt) {
  345. POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, DPMS, dpms));
  346. POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
  347. }
  348. return 0;
  349. }
  350. int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
  351. {
  352. unsigned int dpms, pps, crtdb;
  353. dpms = pps = crtdb = 0;
  354. switch (blank) {
  355. case FB_BLANK_UNBLANK:
  356. pr_info("flag = FB_BLANK_UNBLANK\n");
  357. dpms = SYSTEM_CTRL_DPMS_VPHP;
  358. pps = PANEL_DISPLAY_CTRL_DATA_ENABLE;
  359. crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
  360. break;
  361. case FB_BLANK_NORMAL:
  362. pr_info("flag = FB_BLANK_NORMAL\n");
  363. dpms = SYSTEM_CTRL_DPMS_VPHP;
  364. pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
  365. crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
  366. break;
  367. case FB_BLANK_VSYNC_SUSPEND:
  368. dpms = SYSTEM_CTRL_DPMS_VNHP;
  369. pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
  370. crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
  371. break;
  372. case FB_BLANK_HSYNC_SUSPEND:
  373. dpms = SYSTEM_CTRL_DPMS_VPHN;
  374. pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
  375. crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
  376. break;
  377. case FB_BLANK_POWERDOWN:
  378. dpms = SYSTEM_CTRL_DPMS_VNHN;
  379. pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
  380. crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
  381. break;
  382. }
  383. if (output->paths & sm750_crt) {
  384. POKE32(SYSTEM_CTRL, FIELD_VALUE(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, DPMS, dpms));
  385. POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
  386. }
  387. if (output->paths & sm750_panel)
  388. POKE32(PANEL_DISPLAY_CTRL, FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, DATA, pps));
  389. return 0;
  390. }
  391. void hw_sm750_initAccel(struct sm750_dev *sm750_dev)
  392. {
  393. u32 reg;
  394. enable2DEngine(1);
  395. if (getChipType() == SM750LE) {
  396. reg = PEEK32(DE_STATE1);
  397. reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, ON);
  398. POKE32(DE_STATE1, reg);
  399. reg = PEEK32(DE_STATE1);
  400. reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, OFF);
  401. POKE32(DE_STATE1, reg);
  402. } else {
  403. /* engine reset */
  404. reg = PEEK32(SYSTEM_CTRL);
  405. reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, ON);
  406. POKE32(SYSTEM_CTRL, reg);
  407. reg = PEEK32(SYSTEM_CTRL);
  408. reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, OFF);
  409. POKE32(SYSTEM_CTRL, reg);
  410. }
  411. /* call 2d init */
  412. sm750_dev->accel.de_init(&sm750_dev->accel);
  413. }
  414. int hw_sm750le_deWait(void)
  415. {
  416. int i = 0x10000000;
  417. while (i--) {
  418. unsigned int dwVal = PEEK32(DE_STATE2);
  419. if ((FIELD_GET(dwVal, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) &&
  420. (FIELD_GET(dwVal, DE_STATE2, DE_FIFO) == DE_STATE2_DE_FIFO_EMPTY) &&
  421. (FIELD_GET(dwVal, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) {
  422. return 0;
  423. }
  424. }
  425. /* timeout error */
  426. return -1;
  427. }
  428. int hw_sm750_deWait(void)
  429. {
  430. int i = 0x10000000;
  431. while (i--) {
  432. unsigned int dwVal = PEEK32(SYSTEM_CTRL);
  433. if ((FIELD_GET(dwVal, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) &&
  434. (FIELD_GET(dwVal, SYSTEM_CTRL, DE_FIFO) == SYSTEM_CTRL_DE_FIFO_EMPTY) &&
  435. (FIELD_GET(dwVal, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) {
  436. return 0;
  437. }
  438. }
  439. /* timeout error */
  440. return -1;
  441. }
  442. int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
  443. const struct fb_var_screeninfo *var,
  444. const struct fb_info *info)
  445. {
  446. uint32_t total;
  447. /* check params */
  448. if ((var->xoffset + var->xres > var->xres_virtual) ||
  449. (var->yoffset + var->yres > var->yres_virtual)) {
  450. return -EINVAL;
  451. }
  452. total = var->yoffset * info->fix.line_length +
  453. ((var->xoffset * var->bits_per_pixel) >> 3);
  454. total += crtc->oScreen;
  455. if (crtc->channel == sm750_primary) {
  456. POKE32(PANEL_FB_ADDRESS,
  457. FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS),
  458. PANEL_FB_ADDRESS, ADDRESS, total));
  459. } else {
  460. POKE32(CRT_FB_ADDRESS,
  461. FIELD_VALUE(PEEK32(CRT_FB_ADDRESS),
  462. CRT_FB_ADDRESS, ADDRESS, total));
  463. }
  464. return 0;
  465. }