1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
4 #include <linux/string.h>
6 #include <linux/slab.h>
7 #include <linux/delay.h>
9 #include <linux/ioport.h>
10 #include <linux/init.h>
11 #include <linux/pci.h>
12 #include <linux/vmalloc.h>
13 #include <linux/pagemap.h>
14 #include <linux/console.h>
18 #include <linux/platform_device.h>
19 #include <linux/screen_info.h>
20 #include <linux/sizes.h>
24 #include "sm750_accel.h"
26 int hw_sm750_map(struct sm750_dev
*sm750_dev
, struct pci_dev
*pdev
)
32 sm750_dev
->vidreg_start
= pci_resource_start(pdev
, 1);
33 sm750_dev
->vidreg_size
= SZ_2M
;
35 pr_info("mmio phyAddr = %lx\n", sm750_dev
->vidreg_start
);
37 /* reserve the vidreg space of smi adaptor
38 * if you do this, u need to add release region code
39 * in lynxfb_remove, or memory will not be mapped again
42 ret
= pci_request_region(pdev
, 1, "sm750fb");
44 pr_err("Can not request PCI regions.\n");
48 /* now map mmio and vidmem*/
49 sm750_dev
->pvReg
= ioremap_nocache(sm750_dev
->vidreg_start
,
50 sm750_dev
->vidreg_size
);
51 if (!sm750_dev
->pvReg
) {
52 pr_err("mmio failed\n");
56 pr_info("mmio virtual addr = %p\n", sm750_dev
->pvReg
);
60 sm750_dev
->accel
.dprBase
= sm750_dev
->pvReg
+ DE_BASE_ADDR_TYPE1
;
61 sm750_dev
->accel
.dpPortBase
= sm750_dev
->pvReg
+ DE_PORT_ADDR_TYPE1
;
63 ddk750_set_mmio(sm750_dev
->pvReg
, sm750_dev
->devid
, sm750_dev
->revid
);
65 sm750_dev
->vidmem_start
= pci_resource_start(pdev
, 0);
66 /* don't use pdev_resource[x].end - resource[x].start to
67 * calculate the resource size,its only the maximum available
68 * size but not the actual size,use
69 * @ddk750_getVMSize function can be safe.
71 sm750_dev
->vidmem_size
= ddk750_getVMSize();
72 pr_info("video memory phyAddr = %lx, size = %u bytes\n",
73 sm750_dev
->vidmem_start
, sm750_dev
->vidmem_size
);
75 /* reserve the vidmem space of smi adaptor */
76 sm750_dev
->pvMem
= ioremap_wc(sm750_dev
->vidmem_start
,
77 sm750_dev
->vidmem_size
);
78 if (!sm750_dev
->pvMem
) {
79 pr_err("Map video memory failed\n");
83 pr_info("video memory vaddr = %p\n", sm750_dev
->pvMem
);
91 int hw_sm750_inithw(struct sm750_dev
*sm750_dev
, struct pci_dev
*pdev
)
93 struct init_status
*parm
;
95 parm
= &sm750_dev
->initParm
;
96 if (parm
->chip_clk
== 0)
97 parm
->chip_clk
= (getChipType() == SM750LE
) ?
98 DEFAULT_SM750LE_CHIP_CLOCK
:
99 DEFAULT_SM750_CHIP_CLOCK
;
101 if (parm
->mem_clk
== 0)
102 parm
->mem_clk
= parm
->chip_clk
;
103 if (parm
->master_clk
== 0)
104 parm
->master_clk
= parm
->chip_clk
/3;
106 ddk750_initHw((initchip_param_t
*)&sm750_dev
->initParm
);
107 /* for sm718,open pci burst */
108 if (sm750_dev
->devid
== 0x718) {
110 PEEK32(SYSTEM_CTRL
) | SYSTEM_CTRL_PCI_BURST
);
113 if (getChipType() != SM750LE
) {
115 /* does user need CRT ?*/
116 if (sm750_dev
->nocrt
) {
118 PEEK32(MISC_CTRL
) | MISC_CTRL_DAC_POWER_OFF
);
120 val
= PEEK32(SYSTEM_CTRL
) & ~SYSTEM_CTRL_DPMS_MASK
;
121 val
|= SYSTEM_CTRL_DPMS_VPHN
;
122 POKE32(SYSTEM_CTRL
, val
);
125 PEEK32(MISC_CTRL
) & ~MISC_CTRL_DAC_POWER_OFF
);
127 val
= PEEK32(SYSTEM_CTRL
) & ~SYSTEM_CTRL_DPMS_MASK
;
128 val
|= SYSTEM_CTRL_DPMS_VPHP
;
129 POKE32(SYSTEM_CTRL
, val
);
132 val
= PEEK32(PANEL_DISPLAY_CTRL
) &
133 ~(PANEL_DISPLAY_CTRL_DUAL_DISPLAY
|
134 PANEL_DISPLAY_CTRL_DOUBLE_PIXEL
);
135 switch (sm750_dev
->pnltype
) {
138 case sm750_doubleTFT
:
139 val
|= PANEL_DISPLAY_CTRL_DOUBLE_PIXEL
;
142 val
|= PANEL_DISPLAY_CTRL_DUAL_DISPLAY
;
145 POKE32(PANEL_DISPLAY_CTRL
, val
);
147 /* for 750LE ,no DVI chip initialization makes Monitor no signal */
148 /* Set up GPIO for software I2C to program DVI chip in the
149 Xilinx SP605 board, in order to have video signal.
151 sm750_sw_i2c_init(0, 1);
153 /* Customer may NOT use CH7301 DVI chip, which has to be
154 initialized differently.
156 if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) {
157 /* The following register values for CH7301 are from
158 Chrontel app note and our experiment.
160 pr_info("yes,CH7301 DVI chip found\n");
161 sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16);
162 sm750_sw_i2c_write_reg(0xec, 0x21, 0x9);
163 sm750_sw_i2c_write_reg(0xec, 0x49, 0xC0);
164 pr_info("okay,CH7301 DVI chip setup done\n");
169 if (!sm750_dev
->accel_off
)
170 hw_sm750_initAccel(sm750_dev
);
175 int hw_sm750_output_setMode(struct lynxfb_output
*output
,
176 struct fb_var_screeninfo
*var
, struct fb_fix_screeninfo
*fix
)
179 disp_output_t dispSet
;
184 channel
= *output
->channel
;
187 if (getChipType() != SM750LE
) {
188 if (channel
== sm750_primary
) {
189 pr_info("primary channel\n");
190 if (output
->paths
& sm750_panel
)
191 dispSet
|= do_LCD1_PRI
;
192 if (output
->paths
& sm750_crt
)
193 dispSet
|= do_CRT_PRI
;
196 pr_info("secondary channel\n");
197 if (output
->paths
& sm750_panel
)
198 dispSet
|= do_LCD1_SEC
;
199 if (output
->paths
& sm750_crt
)
200 dispSet
|= do_CRT_SEC
;
203 ddk750_setLogicalDispOut(dispSet
);
205 /* just open DISPLAY_CONTROL_750LE register bit 3:0*/
208 reg
= PEEK32(DISPLAY_CONTROL_750LE
);
210 POKE32(DISPLAY_CONTROL_750LE
, reg
);
213 pr_info("ddk setlogicdispout done\n");
217 int hw_sm750_crtc_checkMode(struct lynxfb_crtc
*crtc
, struct fb_var_screeninfo
*var
)
219 struct sm750_dev
*sm750_dev
;
220 struct lynxfb_par
*par
= container_of(crtc
, struct lynxfb_par
, crtc
);
222 sm750_dev
= par
->dev
;
224 switch (var
->bits_per_pixel
) {
229 if (sm750_dev
->revid
== SM750LE_REVISION_ID
) {
230 pr_debug("750le do not support 32bpp\n");
244 set the controller's mode for @crtc charged with @var and @fix parameters
246 int hw_sm750_crtc_setMode(struct lynxfb_crtc
*crtc
,
247 struct fb_var_screeninfo
*var
,
248 struct fb_fix_screeninfo
*fix
)
252 mode_parameter_t modparm
;
254 struct sm750_dev
*sm750_dev
;
255 struct lynxfb_par
*par
;
259 par
= container_of(crtc
, struct lynxfb_par
, crtc
);
260 sm750_dev
= par
->dev
;
262 if (!sm750_dev
->accel_off
) {
263 /* set 2d engine pixel format according to mode bpp */
264 switch (var
->bits_per_pixel
) {
276 hw_set2dformat(&sm750_dev
->accel
, fmt
);
280 modparm
.pixel_clock
= ps_to_hz(var
->pixclock
);
281 modparm
.vertical_sync_polarity
= (var
->sync
& FB_SYNC_HOR_HIGH_ACT
) ? POS
:NEG
;
282 modparm
.horizontal_sync_polarity
= (var
->sync
& FB_SYNC_VERT_HIGH_ACT
) ? POS
:NEG
;
283 modparm
.clock_phase_polarity
= (var
->sync
& FB_SYNC_COMP_HIGH_ACT
) ? POS
:NEG
;
284 modparm
.horizontal_display_end
= var
->xres
;
285 modparm
.horizontal_sync_width
= var
->hsync_len
;
286 modparm
.horizontal_sync_start
= var
->xres
+ var
->right_margin
;
287 modparm
.horizontal_total
= var
->xres
+ var
->left_margin
+ var
->right_margin
+ var
->hsync_len
;
288 modparm
.vertical_display_end
= var
->yres
;
289 modparm
.vertical_sync_height
= var
->vsync_len
;
290 modparm
.vertical_sync_start
= var
->yres
+ var
->lower_margin
;
291 modparm
.vertical_total
= var
->yres
+ var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
294 if (crtc
->channel
!= sm750_secondary
)
297 clock
= SECONDARY_PLL
;
299 pr_debug("Request pixel clock = %lu\n", modparm
.pixel_clock
);
300 ret
= ddk750_setModeTiming(&modparm
, clock
);
302 pr_err("Set mode timing failed\n");
306 if (crtc
->channel
!= sm750_secondary
) {
307 /* set pitch, offset ,width,start address ,etc... */
308 POKE32(PANEL_FB_ADDRESS
,
309 crtc
->oScreen
& PANEL_FB_ADDRESS_ADDRESS_MASK
);
311 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
312 /* crtc->channel is not equal to par->index on numeric,be aware of that */
313 reg
= ALIGN(reg
, crtc
->line_pad
);
314 reg
= (reg
<< PANEL_FB_WIDTH_WIDTH_SHIFT
) &
315 PANEL_FB_WIDTH_WIDTH_MASK
;
316 reg
|= (fix
->line_length
& PANEL_FB_WIDTH_OFFSET_MASK
);
317 POKE32(PANEL_FB_WIDTH
, reg
);
319 reg
= ((var
->xres
- 1) << PANEL_WINDOW_WIDTH_WIDTH_SHIFT
) &
320 PANEL_WINDOW_WIDTH_WIDTH_MASK
;
321 reg
|= (var
->xoffset
& PANEL_WINDOW_WIDTH_X_MASK
);
322 POKE32(PANEL_WINDOW_WIDTH
, reg
);
324 reg
= ((var
->yres_virtual
- 1) <<
325 PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT
);
326 reg
&= PANEL_WINDOW_HEIGHT_HEIGHT_MASK
;
327 reg
|= (var
->yoffset
& PANEL_WINDOW_HEIGHT_Y_MASK
);
328 POKE32(PANEL_WINDOW_HEIGHT
, reg
);
330 POKE32(PANEL_PLANE_TL
, 0);
332 reg
= ((var
->yres
- 1) << PANEL_PLANE_BR_BOTTOM_SHIFT
) &
333 PANEL_PLANE_BR_BOTTOM_MASK
;
334 reg
|= ((var
->xres
- 1) & PANEL_PLANE_BR_RIGHT_MASK
);
335 POKE32(PANEL_PLANE_BR
, reg
);
337 /* set pixel format */
338 reg
= PEEK32(PANEL_DISPLAY_CTRL
);
339 POKE32(PANEL_DISPLAY_CTRL
, reg
| (var
->bits_per_pixel
>> 4));
341 /* not implemented now */
342 POKE32(CRT_FB_ADDRESS
, crtc
->oScreen
);
343 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
344 /* crtc->channel is not equal to par->index on numeric,be aware of that */
345 reg
= ALIGN(reg
, crtc
->line_pad
) << CRT_FB_WIDTH_WIDTH_SHIFT
;
346 reg
&= CRT_FB_WIDTH_WIDTH_MASK
;
347 reg
|= (fix
->line_length
& CRT_FB_WIDTH_OFFSET_MASK
);
348 POKE32(CRT_FB_WIDTH
, reg
);
350 /* SET PIXEL FORMAT */
351 reg
= PEEK32(CRT_DISPLAY_CTRL
);
352 reg
|= ((var
->bits_per_pixel
>> 4) &
353 CRT_DISPLAY_CTRL_FORMAT_MASK
);
354 POKE32(CRT_DISPLAY_CTRL
, reg
);
363 int hw_sm750_setColReg(struct lynxfb_crtc
*crtc
, ushort index
,
364 ushort red
, ushort green
, ushort blue
)
366 static unsigned int add
[] = {PANEL_PALETTE_RAM
, CRT_PALETTE_RAM
};
368 POKE32(add
[crtc
->channel
] + index
*4, (red
<<16)|(green
<<8)|blue
);
372 int hw_sm750le_setBLANK(struct lynxfb_output
*output
, int blank
)
377 case FB_BLANK_UNBLANK
:
378 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
381 case FB_BLANK_NORMAL
:
382 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
383 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
385 case FB_BLANK_VSYNC_SUSPEND
:
386 dpms
= CRT_DISPLAY_CTRL_DPMS_2
;
387 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
389 case FB_BLANK_HSYNC_SUSPEND
:
390 dpms
= CRT_DISPLAY_CTRL_DPMS_1
;
391 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
393 case FB_BLANK_POWERDOWN
:
394 dpms
= CRT_DISPLAY_CTRL_DPMS_3
;
395 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
401 if (output
->paths
& sm750_crt
) {
404 val
= PEEK32(CRT_DISPLAY_CTRL
) & ~CRT_DISPLAY_CTRL_DPMS_MASK
;
405 POKE32(CRT_DISPLAY_CTRL
, val
| dpms
);
407 val
= PEEK32(CRT_DISPLAY_CTRL
) & ~CRT_DISPLAY_CTRL_BLANK
;
408 POKE32(CRT_DISPLAY_CTRL
, val
| crtdb
);
413 int hw_sm750_setBLANK(struct lynxfb_output
*output
, int blank
)
415 unsigned int dpms
, pps
, crtdb
;
417 dpms
= pps
= crtdb
= 0;
420 case FB_BLANK_UNBLANK
:
421 pr_debug("flag = FB_BLANK_UNBLANK\n");
422 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
423 pps
= PANEL_DISPLAY_CTRL_DATA
;
425 case FB_BLANK_NORMAL
:
426 pr_debug("flag = FB_BLANK_NORMAL\n");
427 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
428 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
430 case FB_BLANK_VSYNC_SUSPEND
:
431 dpms
= SYSTEM_CTRL_DPMS_VNHP
;
432 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
434 case FB_BLANK_HSYNC_SUSPEND
:
435 dpms
= SYSTEM_CTRL_DPMS_VPHN
;
436 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
438 case FB_BLANK_POWERDOWN
:
439 dpms
= SYSTEM_CTRL_DPMS_VNHN
;
440 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
444 if (output
->paths
& sm750_crt
) {
445 unsigned int val
= PEEK32(SYSTEM_CTRL
) & ~SYSTEM_CTRL_DPMS_MASK
;
447 POKE32(SYSTEM_CTRL
, val
| dpms
);
449 val
= PEEK32(CRT_DISPLAY_CTRL
) & ~CRT_DISPLAY_CTRL_BLANK
;
450 POKE32(CRT_DISPLAY_CTRL
, val
| crtdb
);
453 if (output
->paths
& sm750_panel
) {
454 unsigned int val
= PEEK32(PANEL_DISPLAY_CTRL
);
456 val
&= ~PANEL_DISPLAY_CTRL_DATA
;
458 POKE32(PANEL_DISPLAY_CTRL
, val
);
465 void hw_sm750_initAccel(struct sm750_dev
*sm750_dev
)
471 if (getChipType() == SM750LE
) {
472 reg
= PEEK32(DE_STATE1
);
473 reg
|= DE_STATE1_DE_ABORT
;
474 POKE32(DE_STATE1
, reg
);
476 reg
= PEEK32(DE_STATE1
);
477 reg
&= ~DE_STATE1_DE_ABORT
;
478 POKE32(DE_STATE1
, reg
);
482 reg
= PEEK32(SYSTEM_CTRL
);
483 reg
|= SYSTEM_CTRL_DE_ABORT
;
484 POKE32(SYSTEM_CTRL
, reg
);
486 reg
= PEEK32(SYSTEM_CTRL
);
487 reg
&= ~SYSTEM_CTRL_DE_ABORT
;
488 POKE32(SYSTEM_CTRL
, reg
);
492 sm750_dev
->accel
.de_init(&sm750_dev
->accel
);
495 int hw_sm750le_deWait(void)
498 unsigned int mask
= DE_STATE2_DE_STATUS_BUSY
| DE_STATE2_DE_FIFO_EMPTY
|
499 DE_STATE2_DE_MEM_FIFO_EMPTY
;
502 unsigned int val
= PEEK32(DE_STATE2
);
505 (DE_STATE2_DE_FIFO_EMPTY
| DE_STATE2_DE_MEM_FIFO_EMPTY
))
513 int hw_sm750_deWait(void)
516 unsigned int mask
= SYSTEM_CTRL_DE_STATUS_BUSY
|
517 SYSTEM_CTRL_DE_FIFO_EMPTY
|
518 SYSTEM_CTRL_DE_MEM_FIFO_EMPTY
;
521 unsigned int val
= PEEK32(SYSTEM_CTRL
);
524 (SYSTEM_CTRL_DE_FIFO_EMPTY
| SYSTEM_CTRL_DE_MEM_FIFO_EMPTY
))
531 int hw_sm750_pan_display(struct lynxfb_crtc
*crtc
,
532 const struct fb_var_screeninfo
*var
,
533 const struct fb_info
*info
)
537 if ((var
->xoffset
+ var
->xres
> var
->xres_virtual
) ||
538 (var
->yoffset
+ var
->yres
> var
->yres_virtual
)) {
542 total
= var
->yoffset
* info
->fix
.line_length
+
543 ((var
->xoffset
* var
->bits_per_pixel
) >> 3);
544 total
+= crtc
->oScreen
;
545 if (crtc
->channel
== sm750_primary
) {
546 POKE32(PANEL_FB_ADDRESS
,
547 PEEK32(PANEL_FB_ADDRESS
) |
548 (total
& PANEL_FB_ADDRESS_ADDRESS_MASK
));
550 POKE32(CRT_FB_ADDRESS
,
551 PEEK32(CRT_FB_ADDRESS
) |
552 (total
& CRT_FB_ADDRESS_ADDRESS_MASK
));