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>
7 #include <linux/slab.h>
8 #include <linux/delay.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>
19 #include <linux/platform_device.h>
20 #include <linux/screen_info.h>
21 #include <linux/sizes.h>
25 #include "sm750_accel.h"
27 int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
33 sm750_dev->vidreg_start = pci_resource_start(pdev, 1);
34 sm750_dev->vidreg_size = SZ_2M;
36 pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start);
38 /* reserve the vidreg space of smi adaptor
39 * if you do this, u need to add release region code
40 * in lynxfb_remove, or memory will not be mapped again
43 ret = pci_request_region(pdev, 1, "sm750fb");
45 pr_err("Can not request PCI regions.\n");
49 /* now map mmio and vidmem*/
50 sm750_dev->pvReg = ioremap_nocache(sm750_dev->vidreg_start,
51 sm750_dev->vidreg_size);
52 if (!sm750_dev->pvReg) {
53 pr_err("mmio failed\n");
57 pr_info("mmio virtual addr = %p\n", sm750_dev->pvReg);
61 sm750_dev->accel.dprBase = sm750_dev->pvReg + DE_BASE_ADDR_TYPE1;
62 sm750_dev->accel.dpPortBase = sm750_dev->pvReg + DE_PORT_ADDR_TYPE1;
64 ddk750_set_mmio(sm750_dev->pvReg, sm750_dev->devid, sm750_dev->revid);
66 sm750_dev->vidmem_start = pci_resource_start(pdev, 0);
67 /* don't use pdev_resource[x].end - resource[x].start to
68 * calculate the resource size,its only the maximum available
69 * size but not the actual size,use
70 * @ddk750_getVMSize function can be safe.
72 sm750_dev->vidmem_size = ddk750_getVMSize();
73 pr_info("video memory phyAddr = %lx, size = %u bytes\n",
74 sm750_dev->vidmem_start, sm750_dev->vidmem_size);
76 /* reserve the vidmem space of smi adaptor */
77 sm750_dev->pvMem = ioremap_wc(sm750_dev->vidmem_start,
78 sm750_dev->vidmem_size);
79 if (!sm750_dev->pvMem) {
80 pr_err("Map video memory failed\n");
84 pr_info("video memory vaddr = %p\n", sm750_dev->pvMem);
92 int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
94 struct init_status *parm;
96 parm = &sm750_dev->initParm;
97 if (parm->chip_clk == 0)
98 parm->chip_clk = (getChipType() == SM750LE) ?
99 DEFAULT_SM750LE_CHIP_CLOCK :
100 DEFAULT_SM750_CHIP_CLOCK;
102 if (parm->mem_clk == 0)
103 parm->mem_clk = parm->chip_clk;
104 if (parm->master_clk == 0)
105 parm->master_clk = parm->chip_clk/3;
107 ddk750_initHw((initchip_param_t *)&sm750_dev->initParm);
108 /* for sm718,open pci burst */
109 if (sm750_dev->devid == 0x718) {
111 FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON));
114 if (getChipType() != SM750LE) {
115 /* does user need CRT ?*/
116 if (sm750_dev->nocrt) {
118 FIELD_SET(PEEK32(MISC_CTRL),
123 FIELD_SET(PEEK32(SYSTEM_CTRL),
128 FIELD_SET(PEEK32(MISC_CTRL),
133 FIELD_SET(PEEK32(SYSTEM_CTRL),
138 switch (sm750_dev->pnltype) {
139 case sm750_doubleTFT:
142 POKE32(PANEL_DISPLAY_CTRL,
143 FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL),
146 sm750_dev->pnltype));
150 /* for 750LE ,no DVI chip initilization makes Monitor no signal */
151 /* Set up GPIO for software I2C to program DVI chip in the
152 Xilinx SP605 board, in order to have video signal.
154 sm750_sw_i2c_init(0, 1);
157 /* Customer may NOT use CH7301 DVI chip, which has to be
158 initialized differently.
160 if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) {
161 /* The following register values for CH7301 are from
162 Chrontel app note and our experiment.
164 pr_info("yes,CH7301 DVI chip found\n");
165 sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16);
166 sm750_sw_i2c_write_reg(0xec, 0x21, 0x9);
167 sm750_sw_i2c_write_reg(0xec, 0x49, 0xC0);
168 pr_info("okay,CH7301 DVI chip setup done\n");
173 if (!sm750_dev->accel_off)
174 hw_sm750_initAccel(sm750_dev);
179 int hw_sm750_output_setMode(struct lynxfb_output *output,
180 struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
183 disp_output_t dispSet;
188 channel = *output->channel;
191 if (getChipType() != SM750LE) {
192 if (channel == sm750_primary) {
193 pr_info("primary channel\n");
194 if (output->paths & sm750_panel)
195 dispSet |= do_LCD1_PRI;
196 if (output->paths & sm750_crt)
197 dispSet |= do_CRT_PRI;
200 pr_info("secondary channel\n");
201 if (output->paths & sm750_panel)
202 dispSet |= do_LCD1_SEC;
203 if (output->paths & sm750_crt)
204 dispSet |= do_CRT_SEC;
207 ddk750_setLogicalDispOut(dispSet);
209 /* just open DISPLAY_CONTROL_750LE register bit 3:0*/
212 reg = PEEK32(DISPLAY_CONTROL_750LE);
214 POKE32(DISPLAY_CONTROL_750LE, reg);
217 pr_info("ddk setlogicdispout done\n");
221 int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var)
223 struct sm750_dev *sm750_dev;
224 struct lynxfb_par *par = container_of(crtc, struct lynxfb_par, crtc);
226 sm750_dev = par->dev;
228 switch (var->bits_per_pixel) {
233 if (sm750_dev->revid == SM750LE_REVISION_ID) {
234 pr_debug("750le do not support 32bpp\n");
248 set the controller's mode for @crtc charged with @var and @fix parameters
250 int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
251 struct fb_var_screeninfo *var,
252 struct fb_fix_screeninfo *fix)
256 mode_parameter_t modparm;
258 struct sm750_dev *sm750_dev;
259 struct lynxfb_par *par;
263 par = container_of(crtc, struct lynxfb_par, crtc);
264 sm750_dev = par->dev;
266 if (!sm750_dev->accel_off) {
267 /* set 2d engine pixel format according to mode bpp */
268 switch (var->bits_per_pixel) {
280 hw_set2dformat(&sm750_dev->accel, fmt);
284 modparm.pixel_clock = ps_to_hz(var->pixclock);
285 modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? POS:NEG;
286 modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? POS:NEG;
287 modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT) ? POS:NEG;
288 modparm.horizontal_display_end = var->xres;
289 modparm.horizontal_sync_width = var->hsync_len;
290 modparm.horizontal_sync_start = var->xres + var->right_margin;
291 modparm.horizontal_total = var->xres + var->left_margin + var->right_margin + var->hsync_len;
292 modparm.vertical_display_end = var->yres;
293 modparm.vertical_sync_height = var->vsync_len;
294 modparm.vertical_sync_start = var->yres + var->lower_margin;
295 modparm.vertical_total = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
298 if (crtc->channel != sm750_secondary)
301 clock = SECONDARY_PLL;
303 pr_debug("Request pixel clock = %lu\n", modparm.pixel_clock);
304 ret = ddk750_setModeTiming(&modparm, clock);
306 pr_err("Set mode timing failed\n");
310 if (crtc->channel != sm750_secondary) {
311 /* set pitch, offset ,width,start address ,etc... */
312 POKE32(PANEL_FB_ADDRESS,
313 FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, CURRENT)|
314 FIELD_SET(0, PANEL_FB_ADDRESS, EXT, LOCAL)|
315 FIELD_VALUE(0, PANEL_FB_ADDRESS, ADDRESS, crtc->oScreen));
317 reg = var->xres * (var->bits_per_pixel >> 3);
318 /* crtc->channel is not equal to par->index on numeric,be aware of that */
319 reg = ALIGN(reg, crtc->line_pad);
321 POKE32(PANEL_FB_WIDTH,
322 FIELD_VALUE(0, PANEL_FB_WIDTH, WIDTH, reg)|
323 FIELD_VALUE(0, PANEL_FB_WIDTH, OFFSET, fix->line_length));
325 POKE32(PANEL_WINDOW_WIDTH,
326 FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH, var->xres - 1)|
327 FIELD_VALUE(0, PANEL_WINDOW_WIDTH, X, var->xoffset));
329 POKE32(PANEL_WINDOW_HEIGHT,
330 FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, HEIGHT, var->yres_virtual - 1)|
331 FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, Y, var->yoffset));
333 POKE32(PANEL_PLANE_TL, 0);
335 POKE32(PANEL_PLANE_BR,
336 FIELD_VALUE(0, PANEL_PLANE_BR, BOTTOM, var->yres - 1)|
337 FIELD_VALUE(0, PANEL_PLANE_BR, RIGHT, var->xres - 1));
339 /* set pixel format */
340 reg = PEEK32(PANEL_DISPLAY_CTRL);
341 POKE32(PANEL_DISPLAY_CTRL,
343 PANEL_DISPLAY_CTRL, FORMAT,
344 (var->bits_per_pixel >> 4)
347 /* not implemented now */
348 POKE32(CRT_FB_ADDRESS, crtc->oScreen);
349 reg = var->xres * (var->bits_per_pixel >> 3);
350 /* crtc->channel is not equal to par->index on numeric,be aware of that */
351 reg = ALIGN(reg, crtc->line_pad);
354 FIELD_VALUE(0, CRT_FB_WIDTH, WIDTH, reg)|
355 FIELD_VALUE(0, CRT_FB_WIDTH, OFFSET, fix->line_length));
357 /* SET PIXEL FORMAT */
358 reg = PEEK32(CRT_DISPLAY_CTRL);
359 reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, FORMAT, var->bits_per_pixel >> 4);
360 POKE32(CRT_DISPLAY_CTRL, reg);
369 int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
370 ushort red, ushort green, ushort blue)
372 static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
374 POKE32(add[crtc->channel] + index*4, (red<<16)|(green<<8)|blue);
378 int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank)
383 case FB_BLANK_UNBLANK:
384 dpms = CRT_DISPLAY_CTRL_DPMS_0;
385 crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
387 case FB_BLANK_NORMAL:
388 dpms = CRT_DISPLAY_CTRL_DPMS_0;
389 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
391 case FB_BLANK_VSYNC_SUSPEND:
392 dpms = CRT_DISPLAY_CTRL_DPMS_2;
393 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
395 case FB_BLANK_HSYNC_SUSPEND:
396 dpms = CRT_DISPLAY_CTRL_DPMS_1;
397 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
399 case FB_BLANK_POWERDOWN:
400 dpms = CRT_DISPLAY_CTRL_DPMS_3;
401 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
407 if (output->paths & sm750_crt) {
408 POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, DPMS, dpms));
409 POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
414 int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
416 unsigned int dpms, pps, crtdb;
418 dpms = pps = crtdb = 0;
421 case FB_BLANK_UNBLANK:
422 pr_info("flag = FB_BLANK_UNBLANK\n");
423 dpms = SYSTEM_CTRL_DPMS_VPHP;
424 pps = PANEL_DISPLAY_CTRL_DATA_ENABLE;
425 crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
427 case FB_BLANK_NORMAL:
428 pr_info("flag = FB_BLANK_NORMAL\n");
429 dpms = SYSTEM_CTRL_DPMS_VPHP;
430 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
431 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
433 case FB_BLANK_VSYNC_SUSPEND:
434 dpms = SYSTEM_CTRL_DPMS_VNHP;
435 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
436 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
438 case FB_BLANK_HSYNC_SUSPEND:
439 dpms = SYSTEM_CTRL_DPMS_VPHN;
440 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
441 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
443 case FB_BLANK_POWERDOWN:
444 dpms = SYSTEM_CTRL_DPMS_VNHN;
445 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
446 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
450 if (output->paths & sm750_crt) {
452 POKE32(SYSTEM_CTRL, FIELD_VALUE(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, DPMS, dpms));
453 POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
456 if (output->paths & sm750_panel)
457 POKE32(PANEL_DISPLAY_CTRL, FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, DATA, pps));
463 void hw_sm750_initAccel(struct sm750_dev *sm750_dev)
469 if (getChipType() == SM750LE) {
470 reg = PEEK32(DE_STATE1);
471 reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, ON);
472 POKE32(DE_STATE1, reg);
474 reg = PEEK32(DE_STATE1);
475 reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, OFF);
476 POKE32(DE_STATE1, reg);
480 reg = PEEK32(SYSTEM_CTRL);
481 reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, ON);
482 POKE32(SYSTEM_CTRL, reg);
484 reg = PEEK32(SYSTEM_CTRL);
485 reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, OFF);
486 POKE32(SYSTEM_CTRL, reg);
490 sm750_dev->accel.de_init(&sm750_dev->accel);
493 int hw_sm750le_deWait(void)
498 unsigned int dwVal = PEEK32(DE_STATE2);
500 if ((FIELD_GET(dwVal, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) &&
501 (FIELD_GET(dwVal, DE_STATE2, DE_FIFO) == DE_STATE2_DE_FIFO_EMPTY) &&
502 (FIELD_GET(dwVal, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) {
511 int hw_sm750_deWait(void)
516 unsigned int dwVal = PEEK32(SYSTEM_CTRL);
518 if ((FIELD_GET(dwVal, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) &&
519 (FIELD_GET(dwVal, SYSTEM_CTRL, DE_FIFO) == SYSTEM_CTRL_DE_FIFO_EMPTY) &&
520 (FIELD_GET(dwVal, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) {
528 int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
529 const struct fb_var_screeninfo *var,
530 const struct fb_info *info)
534 if ((var->xoffset + var->xres > var->xres_virtual) ||
535 (var->yoffset + var->yres > var->yres_virtual)) {
539 total = var->yoffset * info->fix.line_length +
540 ((var->xoffset * var->bits_per_pixel) >> 3);
541 total += crtc->oScreen;
542 if (crtc->channel == sm750_primary) {
543 POKE32(PANEL_FB_ADDRESS,
544 FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS),
545 PANEL_FB_ADDRESS, ADDRESS, total));
547 POKE32(CRT_FB_ADDRESS,
548 FIELD_VALUE(PEEK32(CRT_FB_ADDRESS),
549 CRT_FB_ADDRESS, ADDRESS, total));