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>
8 #include<linux/delay.h>
10 #include<linux/ioport.h>
11 #include<linux/init.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>
25 #include "sm750_accel.h"
27 int hw_sm750_map(struct lynx_share
* share
, struct pci_dev
* pdev
)
30 struct sm750_share
*spec_share
;
33 spec_share
= container_of(share
, struct sm750_share
, share
);
36 share
->vidreg_start
= pci_resource_start(pdev
, 1);
37 share
->vidreg_size
= MB(2);
39 pr_info("mmio phyAddr = %lx\n", share
->vidreg_start
);
41 /* reserve the vidreg space of smi adaptor
42 * if you do this, u need to add release region code
43 * in lynxfb_remove, or memory will not be mapped again
47 if((ret
= pci_request_region(pdev
, 1, "sm750fb")))
49 pr_err("Can not request PCI regions.\n");
53 /* now map mmio and vidmem*/
54 share
->pvReg
= ioremap_nocache(share
->vidreg_start
, share
->vidreg_size
);
56 pr_err("mmio failed\n");
60 pr_info("mmio virtual addr = %p\n", share
->pvReg
);
64 share
->accel
.dprBase
= share
->pvReg
+ DE_BASE_ADDR_TYPE1
;
65 share
->accel
.dpPortBase
= share
->pvReg
+ DE_PORT_ADDR_TYPE1
;
67 ddk750_set_mmio(share
->pvReg
, share
->devid
, share
->revid
);
69 share
->vidmem_start
= pci_resource_start(pdev
, 0);
70 /* don't use pdev_resource[x].end - resource[x].start to
71 * calculate the resource size,its only the maximum available
72 * size but not the actual size,use
73 * @hw_sm750_getVMSize function can be safe.
75 share
->vidmem_size
= hw_sm750_getVMSize(share
);
76 pr_info("video memory phyAddr = %lx, size = %u bytes\n",
77 share
->vidmem_start
, share
->vidmem_size
);
79 /* reserve the vidmem space of smi adaptor */
81 if((ret
= pci_request_region(pdev
, 0, _moduleName_
)))
83 pr_err("Can not request PCI regions.\n");
88 share
->pvMem
= ioremap_wc(share
->vidmem_start
, share
->vidmem_size
);
91 pr_err("Map video memory failed\n");
95 pr_info("video memory vaddr = %p\n", share
->pvMem
);
103 int hw_sm750_inithw(struct lynx_share
*share
, struct pci_dev
*pdev
)
105 struct sm750_share
*spec_share
;
106 struct init_status
*parm
;
108 spec_share
= container_of(share
, struct sm750_share
, share
);
109 parm
= &spec_share
->state
.initParm
;
110 if(parm
->chip_clk
== 0)
111 parm
->chip_clk
= (getChipType() == SM750LE
)?
112 DEFAULT_SM750LE_CHIP_CLOCK
:
113 DEFAULT_SM750_CHIP_CLOCK
;
115 if(parm
->mem_clk
== 0)
116 parm
->mem_clk
= parm
->chip_clk
;
117 if(parm
->master_clk
== 0)
118 parm
->master_clk
= parm
->chip_clk
/3;
120 ddk750_initHw((initchip_param_t
*)&spec_share
->state
.initParm
);
121 /* for sm718,open pci burst */
122 if(share
->devid
== 0x718){
124 FIELD_SET(PEEK32(SYSTEM_CTRL
), SYSTEM_CTRL
, PCI_BURST
, ON
));
127 /* sm750 use sii164, it can be setup with default value
128 * by on power, so initDVIDisp can be skipped */
130 ddk750_initDVIDisp();
133 if(getChipType() != SM750LE
)
135 /* does user need CRT ?*/
136 if(spec_share
->state
.nocrt
){
138 FIELD_SET(PEEK32(MISC_CTRL
),
143 FIELD_SET(PEEK32(SYSTEM_CTRL
),
148 FIELD_SET(PEEK32(MISC_CTRL
),
153 FIELD_SET(PEEK32(SYSTEM_CTRL
),
158 switch (spec_share
->state
.pnltype
){
159 case sm750_doubleTFT
:
162 POKE32(PANEL_DISPLAY_CTRL
,
163 FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL
),
166 spec_share
->state
.pnltype
));
170 /* for 750LE ,no DVI chip initilization makes Monitor no signal */
171 /* Set up GPIO for software I2C to program DVI chip in the
172 Xilinx SP605 board, in order to have video signal.
177 /* Customer may NOT use CH7301 DVI chip, which has to be
178 initialized differently.
180 if (swI2CReadReg(0xec, 0x4a) == 0x95)
182 /* The following register values for CH7301 are from
183 Chrontel app note and our experiment.
185 pr_info("yes,CH7301 DVI chip found\n");
186 swI2CWriteReg(0xec, 0x1d, 0x16);
187 swI2CWriteReg(0xec, 0x21, 0x9);
188 swI2CWriteReg(0xec, 0x49, 0xC0);
189 pr_info("okay,CH7301 DVI chip setup done\n");
194 if(!share
->accel_off
){
195 hw_sm750_initAccel(share
);
202 resource_size_t
hw_sm750_getVMSize(struct lynx_share
*share
)
206 ret
= ddk750_getVMSize();
212 int hw_sm750_output_checkMode(struct lynxfb_output
* output
, struct fb_var_screeninfo
* var
)
219 int hw_sm750_output_setMode(struct lynxfb_output
* output
,
220 struct fb_var_screeninfo
* var
, struct fb_fix_screeninfo
* fix
)
223 disp_output_t dispSet
;
228 channel
= *output
->channel
;
231 if(getChipType() != SM750LE
){
232 if(channel
== sm750_primary
){
233 pr_info("primary channel\n");
234 if(output
->paths
& sm750_panel
)
235 dispSet
|= do_LCD1_PRI
;
236 if(output
->paths
& sm750_crt
)
237 dispSet
|= do_CRT_PRI
;
240 pr_info("secondary channel\n");
241 if(output
->paths
& sm750_panel
)
242 dispSet
|= do_LCD1_SEC
;
243 if(output
->paths
& sm750_crt
)
244 dispSet
|= do_CRT_SEC
;
247 ddk750_setLogicalDispOut(dispSet
);
249 /* just open DISPLAY_CONTROL_750LE register bit 3:0*/
251 reg
= PEEK32(DISPLAY_CONTROL_750LE
);
253 POKE32(DISPLAY_CONTROL_750LE
, reg
);
256 pr_info("ddk setlogicdispout done \n");
260 void hw_sm750_output_clear(struct lynxfb_output
* output
)
266 int hw_sm750_crtc_checkMode(struct lynxfb_crtc
* crtc
, struct fb_var_screeninfo
* var
)
268 struct lynx_share
*share
;
271 share
= container_of(crtc
, struct lynxfb_par
, crtc
)->share
;
273 switch (var
->bits_per_pixel
){
278 if (share
->revid
== SM750LE_REVISION_ID
) {
279 pr_debug("750le do not support 32bpp\n");
293 set the controller's mode for @crtc charged with @var and @fix parameters
295 int hw_sm750_crtc_setMode(struct lynxfb_crtc
* crtc
,
296 struct fb_var_screeninfo
* var
,
297 struct fb_fix_screeninfo
* fix
)
301 mode_parameter_t modparm
;
303 struct lynx_share
*share
;
304 struct lynxfb_par
*par
;
308 par
= container_of(crtc
, struct lynxfb_par
, crtc
);
311 if(!share
->accel_off
){
312 /* set 2d engine pixel format according to mode bpp */
313 switch(var
->bits_per_pixel
){
325 hw_set2dformat(&share
->accel
, fmt
);
330 modparm
.pixel_clock
= ps_to_hz(var
->pixclock
);
331 modparm
.vertical_sync_polarity
= (var
->sync
& FB_SYNC_HOR_HIGH_ACT
) ? POS
:NEG
;
332 modparm
.horizontal_sync_polarity
= (var
->sync
& FB_SYNC_VERT_HIGH_ACT
) ? POS
:NEG
;
333 modparm
.clock_phase_polarity
= (var
->sync
& FB_SYNC_COMP_HIGH_ACT
) ? POS
:NEG
;
334 modparm
.horizontal_display_end
= var
->xres
;
335 modparm
.horizontal_sync_width
= var
->hsync_len
;
336 modparm
.horizontal_sync_start
= var
->xres
+ var
->right_margin
;
337 modparm
.horizontal_total
= var
->xres
+ var
->left_margin
+ var
->right_margin
+ var
->hsync_len
;
338 modparm
.vertical_display_end
= var
->yres
;
339 modparm
.vertical_sync_height
= var
->vsync_len
;
340 modparm
.vertical_sync_start
= var
->yres
+ var
->lower_margin
;
341 modparm
.vertical_total
= var
->yres
+ var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
344 if(crtc
->channel
!= sm750_secondary
)
347 clock
= SECONDARY_PLL
;
349 pr_debug("Request pixel clock = %lu\n", modparm
.pixel_clock
);
350 ret
= ddk750_setModeTiming(&modparm
, clock
);
352 pr_err("Set mode timing failed\n");
356 if(crtc
->channel
!= sm750_secondary
){
357 /* set pitch, offset ,width,start address ,etc... */
358 POKE32(PANEL_FB_ADDRESS
,
359 FIELD_SET(0, PANEL_FB_ADDRESS
, STATUS
, CURRENT
)|
360 FIELD_SET(0, PANEL_FB_ADDRESS
, EXT
, LOCAL
)|
361 FIELD_VALUE(0, PANEL_FB_ADDRESS
, ADDRESS
, crtc
->oScreen
));
363 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
364 /* crtc->channel is not equal to par->index on numeric,be aware of that */
365 reg
= PADDING(crtc
->line_pad
, reg
);
367 POKE32(PANEL_FB_WIDTH
,
368 FIELD_VALUE(0, PANEL_FB_WIDTH
, WIDTH
, reg
)|
369 FIELD_VALUE(0, PANEL_FB_WIDTH
, OFFSET
, fix
->line_length
));
371 POKE32(PANEL_WINDOW_WIDTH
,
372 FIELD_VALUE(0, PANEL_WINDOW_WIDTH
, WIDTH
, var
->xres
-1)|
373 FIELD_VALUE(0, PANEL_WINDOW_WIDTH
, X
, var
->xoffset
));
375 POKE32(PANEL_WINDOW_HEIGHT
,
376 FIELD_VALUE(0, PANEL_WINDOW_HEIGHT
, HEIGHT
, var
->yres_virtual
- 1)|
377 FIELD_VALUE(0, PANEL_WINDOW_HEIGHT
, Y
, var
->yoffset
));
379 POKE32(PANEL_PLANE_TL
, 0);
381 POKE32(PANEL_PLANE_BR
,
382 FIELD_VALUE(0, PANEL_PLANE_BR
, BOTTOM
, var
->yres
- 1)|
383 FIELD_VALUE(0, PANEL_PLANE_BR
, RIGHT
, var
->xres
- 1));
385 /* set pixel format */
386 reg
= PEEK32(PANEL_DISPLAY_CTRL
);
387 POKE32(PANEL_DISPLAY_CTRL
,
389 PANEL_DISPLAY_CTRL
, FORMAT
,
390 (var
->bits_per_pixel
>> 4)
393 /* not implemented now */
394 POKE32(CRT_FB_ADDRESS
, crtc
->oScreen
);
395 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
396 /* crtc->channel is not equal to par->index on numeric,be aware of that */
397 reg
= PADDING(crtc
->line_pad
, reg
);
400 FIELD_VALUE(0, CRT_FB_WIDTH
, WIDTH
, reg
)|
401 FIELD_VALUE(0, CRT_FB_WIDTH
, OFFSET
, fix
->line_length
));
403 /* SET PIXEL FORMAT */
404 reg
= PEEK32(CRT_DISPLAY_CTRL
);
405 reg
= FIELD_VALUE(reg
, CRT_DISPLAY_CTRL
, FORMAT
, var
->bits_per_pixel
>> 4);
406 POKE32(CRT_DISPLAY_CTRL
, reg
);
415 void hw_sm750_crtc_clear(struct lynxfb_crtc
* crtc
)
421 int hw_sm750_setColReg(struct lynxfb_crtc
* crtc
, ushort index
,
422 ushort red
, ushort green
, ushort blue
)
424 static unsigned int add
[]={PANEL_PALETTE_RAM
, CRT_PALETTE_RAM
};
425 POKE32(add
[crtc
->channel
] + index
*4, (red
<<16)|(green
<<8)|blue
);
429 int hw_sm750le_setBLANK(struct lynxfb_output
* output
, int blank
){
434 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
435 case FB_BLANK_UNBLANK
:
437 case VESA_NO_BLANKING
:
439 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
440 crtdb
= CRT_DISPLAY_CTRL_BLANK_OFF
;
442 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
443 case FB_BLANK_NORMAL
:
444 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
445 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
448 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
449 case FB_BLANK_VSYNC_SUSPEND
:
451 case VESA_VSYNC_SUSPEND
:
453 dpms
= CRT_DISPLAY_CTRL_DPMS_2
;
454 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
456 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
457 case FB_BLANK_HSYNC_SUSPEND
:
459 case VESA_HSYNC_SUSPEND
:
461 dpms
= CRT_DISPLAY_CTRL_DPMS_1
;
462 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
464 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
465 case FB_BLANK_POWERDOWN
:
469 dpms
= CRT_DISPLAY_CTRL_DPMS_3
;
470 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
476 if(output
->paths
& sm750_crt
){
477 POKE32(CRT_DISPLAY_CTRL
, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL
), CRT_DISPLAY_CTRL
, DPMS
, dpms
));
478 POKE32(CRT_DISPLAY_CTRL
, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL
), CRT_DISPLAY_CTRL
, BLANK
, crtdb
));
483 int hw_sm750_setBLANK(struct lynxfb_output
* output
, int blank
)
485 unsigned int dpms
, pps
, crtdb
;
487 dpms
= pps
= crtdb
= 0;
491 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
492 case FB_BLANK_UNBLANK
:
494 case VESA_NO_BLANKING
:
496 pr_info("flag = FB_BLANK_UNBLANK \n");
497 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
498 pps
= PANEL_DISPLAY_CTRL_DATA_ENABLE
;
499 crtdb
= CRT_DISPLAY_CTRL_BLANK_OFF
;
501 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
502 case FB_BLANK_NORMAL
:
503 pr_info("flag = FB_BLANK_NORMAL \n");
504 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
505 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
506 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
509 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
510 case FB_BLANK_VSYNC_SUSPEND
:
512 case VESA_VSYNC_SUSPEND
:
514 dpms
= SYSTEM_CTRL_DPMS_VNHP
;
515 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
516 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
518 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
519 case FB_BLANK_HSYNC_SUSPEND
:
521 case VESA_HSYNC_SUSPEND
:
523 dpms
= SYSTEM_CTRL_DPMS_VPHN
;
524 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
525 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
527 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
528 case FB_BLANK_POWERDOWN
:
532 dpms
= SYSTEM_CTRL_DPMS_VNHN
;
533 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
534 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
538 if(output
->paths
& sm750_crt
){
540 POKE32(SYSTEM_CTRL
, FIELD_VALUE(PEEK32(SYSTEM_CTRL
), SYSTEM_CTRL
, DPMS
, dpms
));
541 POKE32(CRT_DISPLAY_CTRL
, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL
), CRT_DISPLAY_CTRL
, BLANK
, crtdb
));
544 if(output
->paths
& sm750_panel
){
545 POKE32(PANEL_DISPLAY_CTRL
, FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL
), PANEL_DISPLAY_CTRL
, DATA
, pps
));
552 void hw_sm750_initAccel(struct lynx_share
*share
)
557 if(getChipType() == SM750LE
){
558 reg
= PEEK32(DE_STATE1
);
559 reg
= FIELD_SET(reg
, DE_STATE1
, DE_ABORT
, ON
);
560 POKE32(DE_STATE1
, reg
);
562 reg
= PEEK32(DE_STATE1
);
563 reg
= FIELD_SET(reg
, DE_STATE1
, DE_ABORT
, OFF
);
564 POKE32(DE_STATE1
, reg
);
568 reg
= PEEK32(SYSTEM_CTRL
);
569 reg
= FIELD_SET(reg
, SYSTEM_CTRL
, DE_ABORT
, ON
);
570 POKE32(SYSTEM_CTRL
, reg
);
572 reg
= PEEK32(SYSTEM_CTRL
);
573 reg
= FIELD_SET(reg
, SYSTEM_CTRL
, DE_ABORT
, OFF
);
574 POKE32(SYSTEM_CTRL
, reg
);
578 share
->accel
.de_init(&share
->accel
);
581 int hw_sm750le_deWait(void)
585 unsigned int dwVal
= PEEK32(DE_STATE2
);
586 if((FIELD_GET(dwVal
, DE_STATE2
, DE_STATUS
) == DE_STATE2_DE_STATUS_IDLE
) &&
587 (FIELD_GET(dwVal
, DE_STATE2
, DE_FIFO
) == DE_STATE2_DE_FIFO_EMPTY
) &&
588 (FIELD_GET(dwVal
, DE_STATE2
, DE_MEM_FIFO
) == DE_STATE2_DE_MEM_FIFO_EMPTY
))
598 int hw_sm750_deWait(void)
602 unsigned int dwVal
= PEEK32(SYSTEM_CTRL
);
603 if((FIELD_GET(dwVal
, SYSTEM_CTRL
, DE_STATUS
) == SYSTEM_CTRL_DE_STATUS_IDLE
) &&
604 (FIELD_GET(dwVal
, SYSTEM_CTRL
, DE_FIFO
) == SYSTEM_CTRL_DE_FIFO_EMPTY
) &&
605 (FIELD_GET(dwVal
, SYSTEM_CTRL
, DE_MEM_FIFO
) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY
))
614 int hw_sm750_pan_display(struct lynxfb_crtc
*crtc
,
615 const struct fb_var_screeninfo
*var
,
616 const struct fb_info
*info
)
620 if ((var
->xoffset
+ var
->xres
> var
->xres_virtual
) ||
621 (var
->yoffset
+ var
->yres
> var
->yres_virtual
)) {
625 total
= var
->yoffset
* info
->fix
.line_length
+
626 ((var
->xoffset
* var
->bits_per_pixel
) >> 3);
627 total
+= crtc
->oScreen
;
628 if (crtc
->channel
== sm750_primary
) {
629 POKE32(PANEL_FB_ADDRESS
,
630 FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS
),
631 PANEL_FB_ADDRESS
, ADDRESS
, total
));
633 POKE32(CRT_FB_ADDRESS
,
634 FIELD_VALUE(PEEK32(CRT_FB_ADDRESS
),
635 CRT_FB_ADDRESS
, ADDRESS
, total
));