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(share
->vidmem_start
,
92 pr_err("Map video memory failed\n");
96 pr_info("video memory vaddr = %p\n", share
->pvMem
);
104 int hw_sm750_inithw(struct lynx_share
* share
, struct pci_dev
* pdev
)
106 struct sm750_share
* spec_share
;
107 struct init_status
* parm
;
109 spec_share
= container_of(share
, struct sm750_share
,share
);
110 parm
= &spec_share
->state
.initParm
;
111 if(parm
->chip_clk
== 0)
112 parm
->chip_clk
= (getChipType() == SM750LE
)?
113 DEFAULT_SM750LE_CHIP_CLOCK
:
114 DEFAULT_SM750_CHIP_CLOCK
;
116 if(parm
->mem_clk
== 0)
117 parm
->mem_clk
= parm
->chip_clk
;
118 if(parm
->master_clk
== 0)
119 parm
->master_clk
= parm
->chip_clk
/3;
121 ddk750_initHw((initchip_param_t
*)&spec_share
->state
.initParm
);
122 /* for sm718,open pci burst */
123 if(share
->devid
== 0x718){
125 FIELD_SET(PEEK32(SYSTEM_CTRL
), SYSTEM_CTRL
, PCI_BURST
, ON
));
128 /* sm750 use sii164, it can be setup with default value
129 * by on power, so initDVIDisp can be skipped */
131 ddk750_initDVIDisp();
134 if(getChipType() != SM750LE
)
136 /* does user need CRT ?*/
137 if(spec_share
->state
.nocrt
){
139 FIELD_SET(PEEK32(MISC_CTRL
),
144 FIELD_SET(PEEK32(SYSTEM_CTRL
),
149 FIELD_SET(PEEK32(MISC_CTRL
),
154 FIELD_SET(PEEK32(SYSTEM_CTRL
),
159 switch (spec_share
->state
.pnltype
){
160 case sm750_doubleTFT
:
163 POKE32(PANEL_DISPLAY_CTRL
,
164 FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL
),
167 spec_share
->state
.pnltype
));
171 /* for 750LE ,no DVI chip initilization makes Monitor no signal */
172 /* Set up GPIO for software I2C to program DVI chip in the
173 Xilinx SP605 board, in order to have video signal.
178 /* Customer may NOT use CH7301 DVI chip, which has to be
179 initialized differently.
181 if (swI2CReadReg(0xec, 0x4a) == 0x95)
183 /* The following register values for CH7301 are from
184 Chrontel app note and our experiment.
186 pr_info("yes,CH7301 DVI chip found\n");
187 swI2CWriteReg(0xec, 0x1d, 0x16);
188 swI2CWriteReg(0xec, 0x21, 0x9);
189 swI2CWriteReg(0xec, 0x49, 0xC0);
190 pr_info("okay,CH7301 DVI chip setup done\n");
195 if(!share
->accel_off
){
196 hw_sm750_initAccel(share
);
197 // share->accel.de_wait = hw_sm750_deWait;
204 resource_size_t
hw_sm750_getVMSize(struct lynx_share
* share
)
208 ret
= ddk750_getVMSize();
214 int hw_sm750_output_checkMode(struct lynxfb_output
* output
, struct fb_var_screeninfo
* var
)
221 int hw_sm750_output_setMode(struct lynxfb_output
* output
,
222 struct fb_var_screeninfo
* var
, struct fb_fix_screeninfo
* fix
)
225 disp_output_t dispSet
;
230 channel
= *output
->channel
;
233 if(getChipType() != SM750LE
){
234 if(channel
== sm750_primary
){
235 pr_info("primary channel\n");
236 if(output
->paths
& sm750_panel
)
237 dispSet
|= do_LCD1_PRI
;
238 if(output
->paths
& sm750_crt
)
239 dispSet
|= do_CRT_PRI
;
242 pr_info("secondary channel\n");
243 if(output
->paths
& sm750_panel
)
244 dispSet
|= do_LCD1_SEC
;
245 if(output
->paths
& sm750_crt
)
246 dispSet
|= do_CRT_SEC
;
249 ddk750_setLogicalDispOut(dispSet
);
251 /* just open DISPLAY_CONTROL_750LE register bit 3:0*/
253 reg
= PEEK32(DISPLAY_CONTROL_750LE
);
255 POKE32(DISPLAY_CONTROL_750LE
, reg
);
258 pr_info("ddk setlogicdispout done \n");
262 void hw_sm750_output_clear(struct lynxfb_output
* output
)
268 int hw_sm750_crtc_checkMode(struct lynxfb_crtc
* crtc
, struct fb_var_screeninfo
* var
)
270 struct lynx_share
* share
;
273 share
= container_of(crtc
, struct lynxfb_par
,crtc
)->share
;
275 switch (var
->bits_per_pixel
){
280 if (share
->revid
== SM750LE_REVISION_ID
) {
281 pr_debug("750le do not support 32bpp\n");
295 set the controller's mode for @crtc charged with @var and @fix parameters
297 int hw_sm750_crtc_setMode(struct lynxfb_crtc
* crtc
,
298 struct fb_var_screeninfo
* var
,
299 struct fb_fix_screeninfo
* fix
)
303 mode_parameter_t modparm
;
305 struct lynx_share
* share
;
306 struct lynxfb_par
* par
;
310 par
= container_of(crtc
, struct lynxfb_par
, crtc
);
313 if(!share
->accel_off
){
314 /* set 2d engine pixel format according to mode bpp */
315 switch(var
->bits_per_pixel
){
327 hw_set2dformat(&share
->accel
, fmt
);
332 // modparm.pixel_clock = PS_TO_HZ(var->pixclock);
333 modparm
.pixel_clock
= ps_to_hz(var
->pixclock
);
334 modparm
.vertical_sync_polarity
= (var
->sync
& FB_SYNC_HOR_HIGH_ACT
) ? POS
:NEG
;
335 modparm
.horizontal_sync_polarity
= (var
->sync
& FB_SYNC_VERT_HIGH_ACT
) ? POS
:NEG
;
336 modparm
.clock_phase_polarity
= (var
->sync
& FB_SYNC_COMP_HIGH_ACT
) ? POS
:NEG
;
337 modparm
.horizontal_display_end
= var
->xres
;
338 modparm
.horizontal_sync_width
= var
->hsync_len
;
339 modparm
.horizontal_sync_start
= var
->xres
+ var
->right_margin
;
340 modparm
.horizontal_total
= var
->xres
+ var
->left_margin
+ var
->right_margin
+ var
->hsync_len
;
341 modparm
.vertical_display_end
= var
->yres
;
342 modparm
.vertical_sync_height
= var
->vsync_len
;
343 modparm
.vertical_sync_start
= var
->yres
+ var
->lower_margin
;
344 modparm
.vertical_total
= var
->yres
+ var
->upper_margin
+ var
->lower_margin
+ var
->vsync_len
;
347 if(crtc
->channel
!= sm750_secondary
)
350 clock
= SECONDARY_PLL
;
352 pr_debug("Request pixel clock = %lu\n", modparm
.pixel_clock
);
353 ret
= ddk750_setModeTiming(&modparm
, clock
);
355 pr_err("Set mode timing failed\n");
359 if(crtc
->channel
!= sm750_secondary
){
360 /* set pitch, offset ,width,start address ,etc... */
361 POKE32(PANEL_FB_ADDRESS
,
362 FIELD_SET(0, PANEL_FB_ADDRESS
, STATUS
, CURRENT
)|
363 FIELD_SET(0, PANEL_FB_ADDRESS
, EXT
, LOCAL
)|
364 FIELD_VALUE(0, PANEL_FB_ADDRESS
, ADDRESS
, crtc
->oScreen
));
366 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
367 /* crtc->channel is not equal to par->index on numeric,be aware of that */
368 reg
= PADDING(crtc
->line_pad
,reg
);
370 POKE32(PANEL_FB_WIDTH
,
371 FIELD_VALUE(0, PANEL_FB_WIDTH
, WIDTH
, reg
)|
372 FIELD_VALUE(0, PANEL_FB_WIDTH
, OFFSET
, fix
->line_length
));
374 POKE32(PANEL_WINDOW_WIDTH
,
375 FIELD_VALUE(0, PANEL_WINDOW_WIDTH
, WIDTH
, var
->xres
-1)|
376 FIELD_VALUE(0, PANEL_WINDOW_WIDTH
, X
, var
->xoffset
));
378 POKE32(PANEL_WINDOW_HEIGHT
,
379 FIELD_VALUE(0, PANEL_WINDOW_HEIGHT
, HEIGHT
, var
->yres_virtual
- 1)|
380 FIELD_VALUE(0, PANEL_WINDOW_HEIGHT
, Y
, var
->yoffset
));
382 POKE32(PANEL_PLANE_TL
, 0);
384 POKE32(PANEL_PLANE_BR
,
385 FIELD_VALUE(0, PANEL_PLANE_BR
, BOTTOM
, var
->yres
- 1)|
386 FIELD_VALUE(0, PANEL_PLANE_BR
,RIGHT
, var
->xres
- 1));
388 /* set pixel format */
389 reg
= PEEK32(PANEL_DISPLAY_CTRL
);
390 POKE32(PANEL_DISPLAY_CTRL
,
392 PANEL_DISPLAY_CTRL
, FORMAT
,
393 (var
->bits_per_pixel
>> 4)
396 /* not implemented now */
397 POKE32(CRT_FB_ADDRESS
, crtc
->oScreen
);
398 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
399 /* crtc->channel is not equal to par->index on numeric,be aware of that */
400 reg
= PADDING(crtc
->line_pad
, reg
);
403 FIELD_VALUE(0, CRT_FB_WIDTH
, WIDTH
, reg
)|
404 FIELD_VALUE(0, CRT_FB_WIDTH
, OFFSET
, fix
->line_length
));
406 /* SET PIXEL FORMAT */
407 reg
= PEEK32(CRT_DISPLAY_CTRL
);
408 reg
= FIELD_VALUE(reg
, CRT_DISPLAY_CTRL
, FORMAT
, var
->bits_per_pixel
>> 4);
409 POKE32(CRT_DISPLAY_CTRL
, reg
);
418 void hw_sm750_crtc_clear(struct lynxfb_crtc
* crtc
)
424 int hw_sm750_setColReg(struct lynxfb_crtc
* crtc
, ushort index
,
425 ushort red
, ushort green
, ushort blue
)
427 static unsigned int add
[]={PANEL_PALETTE_RAM
,CRT_PALETTE_RAM
};
428 POKE32(add
[crtc
->channel
] + index
*4, (red
<<16)|(green
<<8)|blue
);
432 int hw_sm750le_setBLANK(struct lynxfb_output
* output
, int blank
){
437 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
438 case FB_BLANK_UNBLANK
:
440 case VESA_NO_BLANKING
:
442 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
443 crtdb
= CRT_DISPLAY_CTRL_BLANK_OFF
;
445 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
446 case FB_BLANK_NORMAL
:
447 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
448 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
451 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
452 case FB_BLANK_VSYNC_SUSPEND
:
454 case VESA_VSYNC_SUSPEND
:
456 dpms
= CRT_DISPLAY_CTRL_DPMS_2
;
457 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
459 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
460 case FB_BLANK_HSYNC_SUSPEND
:
462 case VESA_HSYNC_SUSPEND
:
464 dpms
= CRT_DISPLAY_CTRL_DPMS_1
;
465 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
467 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
468 case FB_BLANK_POWERDOWN
:
472 dpms
= CRT_DISPLAY_CTRL_DPMS_3
;
473 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
479 if(output
->paths
& sm750_crt
){
480 POKE32(CRT_DISPLAY_CTRL
, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL
), CRT_DISPLAY_CTRL
, DPMS
, dpms
));
481 POKE32(CRT_DISPLAY_CTRL
, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL
), CRT_DISPLAY_CTRL
, BLANK
, crtdb
));
486 int hw_sm750_setBLANK(struct lynxfb_output
* output
,int blank
)
488 unsigned int dpms
, pps
, crtdb
;
490 dpms
= pps
= crtdb
= 0;
494 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
495 case FB_BLANK_UNBLANK
:
497 case VESA_NO_BLANKING
:
499 pr_info("flag = FB_BLANK_UNBLANK \n");
500 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
501 pps
= PANEL_DISPLAY_CTRL_DATA_ENABLE
;
502 crtdb
= CRT_DISPLAY_CTRL_BLANK_OFF
;
504 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
505 case FB_BLANK_NORMAL
:
506 pr_info("flag = FB_BLANK_NORMAL \n");
507 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
508 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
509 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
512 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
513 case FB_BLANK_VSYNC_SUSPEND
:
515 case VESA_VSYNC_SUSPEND
:
517 dpms
= SYSTEM_CTRL_DPMS_VNHP
;
518 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
519 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
521 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
522 case FB_BLANK_HSYNC_SUSPEND
:
524 case VESA_HSYNC_SUSPEND
:
526 dpms
= SYSTEM_CTRL_DPMS_VPHN
;
527 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
528 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
530 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
531 case FB_BLANK_POWERDOWN
:
535 dpms
= SYSTEM_CTRL_DPMS_VNHN
;
536 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
537 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
541 if(output
->paths
& sm750_crt
){
543 POKE32(SYSTEM_CTRL
,FIELD_VALUE(PEEK32(SYSTEM_CTRL
), SYSTEM_CTRL
, DPMS
, dpms
));
544 POKE32(CRT_DISPLAY_CTRL
,FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL
), CRT_DISPLAY_CTRL
,BLANK
, crtdb
));
547 if(output
->paths
& sm750_panel
){
548 POKE32(PANEL_DISPLAY_CTRL
, FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL
), PANEL_DISPLAY_CTRL
, DATA
, pps
));
555 void hw_sm750_initAccel(struct lynx_share
* share
)
560 if(getChipType() == SM750LE
){
561 reg
= PEEK32(DE_STATE1
);
562 reg
= FIELD_SET(reg
, DE_STATE1
, DE_ABORT
,ON
);
563 POKE32(DE_STATE1
,reg
);
565 reg
= PEEK32(DE_STATE1
);
566 reg
= FIELD_SET(reg
, DE_STATE1
, DE_ABORT
,OFF
);
567 POKE32(DE_STATE1
, reg
);
571 reg
= PEEK32(SYSTEM_CTRL
);
572 reg
= FIELD_SET(reg
, SYSTEM_CTRL
, DE_ABORT
,ON
);
573 POKE32(SYSTEM_CTRL
, reg
);
575 reg
= PEEK32(SYSTEM_CTRL
);
576 reg
= FIELD_SET(reg
, SYSTEM_CTRL
, DE_ABORT
,OFF
);
577 POKE32(SYSTEM_CTRL
, reg
);
581 share
->accel
.de_init(&share
->accel
);
584 int hw_sm750le_deWait(void)
588 unsigned int dwVal
= PEEK32(DE_STATE2
);
589 if((FIELD_GET(dwVal
, DE_STATE2
, DE_STATUS
) == DE_STATE2_DE_STATUS_IDLE
) &&
590 (FIELD_GET(dwVal
, DE_STATE2
, DE_FIFO
) == DE_STATE2_DE_FIFO_EMPTY
) &&
591 (FIELD_GET(dwVal
, DE_STATE2
, DE_MEM_FIFO
) == DE_STATE2_DE_MEM_FIFO_EMPTY
))
601 int hw_sm750_deWait(void)
605 unsigned int dwVal
= PEEK32(SYSTEM_CTRL
);
606 if((FIELD_GET(dwVal
,SYSTEM_CTRL
,DE_STATUS
) == SYSTEM_CTRL_DE_STATUS_IDLE
) &&
607 (FIELD_GET(dwVal
,SYSTEM_CTRL
,DE_FIFO
) == SYSTEM_CTRL_DE_FIFO_EMPTY
) &&
608 (FIELD_GET(dwVal
,SYSTEM_CTRL
,DE_MEM_FIFO
) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY
))
617 int hw_sm750_pan_display(struct lynxfb_crtc
*crtc
,
618 const struct fb_var_screeninfo
*var
,
619 const struct fb_info
*info
)
623 if ((var
->xoffset
+ var
->xres
> var
->xres_virtual
) ||
624 (var
->yoffset
+ var
->yres
> var
->yres_virtual
)) {
628 total
= var
->yoffset
* info
->fix
.line_length
+
629 ((var
->xoffset
* var
->bits_per_pixel
) >> 3);
630 total
+= crtc
->oScreen
;
631 if (crtc
->channel
== sm750_primary
) {
632 POKE32(PANEL_FB_ADDRESS
,
633 FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS
),
634 PANEL_FB_ADDRESS
, ADDRESS
, total
));
636 POKE32(CRT_FB_ADDRESS
,
637 FIELD_VALUE(PEEK32(CRT_FB_ADDRESS
),
638 CRT_FB_ADDRESS
, ADDRESS
, total
));