1 /*******************************************************************
2 *Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
3 *Permission is hereby granted, free of charge, to any person obtaining a copy
4 *of this software and associated documentation files (the "Software"), to deal
5 *in the Software without restriction, including without limitation the rights to
6 *use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 *of the Software, and to permit persons to whom the Software is furnished to
8 *do so, subject to the following conditions:
10 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
12 *OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 *NONINFRINGEMENT. IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
14 *HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
15 *WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
16 *FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
17 *OTHER DEALINGS IN THE SOFTWARE.
18 *******************************************************************/
19 #include<linux/version.h>
20 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
21 #include<linux/config.h>
23 #include <linux/version.h>
24 #include<linux/module.h>
25 #include<linux/kernel.h>
26 #include<linux/errno.h>
27 #include<linux/string.h>
29 #include<linux/slab.h>
30 #include<linux/delay.h>
32 #include<linux/ioport.h>
33 #include<linux/init.h>
35 #include<linux/vmalloc.h>
36 #include<linux/pagemap.h>
37 #include <linux/console.h>
42 #ifdef CONFIG_FB_LYNXFB_DOMAINS
43 #include <asm-l/iolinkmask.h>
46 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
47 /* no below two header files in 2.6.9 */
48 #include<linux/platform_device.h>
49 #include<linux/screen_info.h>
55 #include "lynx_hw750.h"
57 #include "lynx_accel.h"
59 int hw_sm750_map(struct lynx_share
*share
, struct pci_dev
*pdev
)
62 struct sm750_share
*spec_share
;
64 #ifdef CONFIG_FB_LYNXFB_DOMAINS
66 #endif /* CONFIG_FB_LYNXFB_DOMAINS */
70 spec_share
= container_of(share
, struct sm750_share
, share
);
73 share
->vidreg_start
= pci_resource_start(pdev
, 1);
74 share
->vidreg_size
= MB(2);
76 /* reserve the vidreg space of smi adaptor
77 * if you do this, u need to add release region code
78 * in lynxfb_remove, or memory will not be mapped again
83 /* now map mmio and vidmem */
85 ioremap_nocache(share
->vidreg_start
, share
->vidreg_size
);
87 err_msg("mmio failed\n");
92 share
->accel
.dprBase
= share
->pvReg
+ DE_BASE_ADDR_TYPE1
;
93 share
->accel
.dpPortBase
= share
->pvReg
+ DE_PORT_ADDR_TYPE1
;
94 #ifdef CONFIG_FB_LYNXFB_DOMAINS
95 domain
= pci_domain_nr(pdev
->bus
);
96 ddk750_set_mmio(share
->pvReg
, share
->devid
, share
->revid
, domain
);
98 ddk750_set_mmio(share
->pvReg
, share
->devid
, share
->revid
);
99 #endif /* CONFIG_FB_LYNXFB_DOMAINS */
101 share
->vidmem_start
= pci_resource_start(pdev
, 0);
102 /* don't use pdev_resource[x].end - resource[x].start to
103 * calculate the resource size, its only the maximum available
104 * size but not the actual size, use
105 * @hw_sm750_getVMSize function can be safe.
107 #ifdef CONFIG_FB_LYNXFB_DOMAINS
108 share
->vidmem_size
= hw_sm750_getVMSize(share
, domain
);
110 share
->vidmem_size
= hw_sm750_getVMSize(share
);
111 #endif /* CONFIG_FB_LYNXFB_DOMAINS */
112 inf_msg("video memory size = %lld mb\n", share
->vidmem_size
>> 20);
114 /* reserve the vidmem space of smi adaptor */
116 share
->pvMem
= ioremap(share
->vidmem_start
, share
->vidmem_size
);
119 err_msg("Map video memory failed\n");
124 inf_msg("video memory vaddr = %p\n", share
->pvMem
);
129 #ifdef CONFIG_FB_LYNXFB_DOMAINS
131 int hw_sm750_inithw(struct lynx_share
*share
, struct pci_dev
*pdev
)
133 struct sm750_share
*spec_share
;
134 struct init_status
*parm
;
139 domain
= pci_domain_nr(pdev
->bus
);
141 spec_share
= container_of(share
, struct sm750_share
, share
);
142 parm
= &spec_share
->state
.initParm
;
143 if (parm
->chip_clk
== 0)
144 parm
->chip_clk
= (getChipType(domain
) == SM750LE
) ?
145 DEFAULT_SM750LE_CHIP_CLOCK
: DEFAULT_SM750_CHIP_CLOCK
;
147 if (parm
->mem_clk
== 0)
148 parm
->mem_clk
= parm
->chip_clk
;
149 if (parm
->master_clk
== 0)
150 parm
->master_clk
= parm
->chip_clk
/ 3;
152 ddk750_initHw((initchip_param_t
*) & spec_share
->state
.initParm
,
154 /* for sm718, open pci burst */
155 if (share
->devid
== 0x718) {
157 PEEK32(SYSTEM_CTRL
, domain
) | (1 <<
158 SYSTEM_CTRL_PCI_BURST_LSB
), domain
);
161 /* sm750 use sii164, it can be setup with default value
162 * by on power, so initDVIDisp can be skipped */
164 if (getChipType(domain
) != SM750LE
) {
165 /* does user need CRT ? */
166 if (spec_share
->state
.nocrt
) {
168 PEEK32(MISC_CTRL
, domain
) |
169 (1 << MISC_CTRL_DAC_POWER_LSB
), domain
);
172 PEEK32(SYSTEM_CTRL
, domain
) |
173 (3 << SYSTEM_CTRL_DPMS_LSB
), domain
);
176 PEEK32(MISC_CTRL
, domain
) &
177 (~(1 << MISC_CTRL_DAC_POWER_LSB
)), domain
);
180 PEEK32(SYSTEM_CTRL
, domain
) &
181 (~(3 << SYSTEM_CTRL_DPMS_LSB
)), domain
);
184 switch (spec_share
->state
.pnltype
) {
185 case sm750_doubleTFT
:
188 POKE32(PANEL_DISPLAY_CTRL
,
189 PEEK32(PANEL_DISPLAY_CTRL
, domain
) &
190 (~(3 << PANEL_DISPLAY_CTRL_TFT_DISP_LSB
)),
192 POKE32(PANEL_DISPLAY_CTRL
,
193 PEEK32(PANEL_DISPLAY_CTRL
, domain
) |
196 PANEL_DISPLAY_CTRL_TFT_DISP_LSB
), domain
);
200 /* for 750LE , no DVI chip initilization makes Monitor no signal */
201 /* Set up GPIO for software I2C to program DVI chip in the
202 Xilinx SP605 board, in order to have video signal.
204 swI2CInit(0, 1, domain
);
207 /* Customer may NOT use CH7301 DVI chip, which has to be
208 initialized differently.
210 if (swI2CReadReg(0xec, 0x4a, domain
) == 0x95) {
211 /* The following register values for CH7301 are from
212 Chrontel app note and our experiment.
214 inf_msg("yes, CH7301 DVI chip found\n");
215 swI2CWriteReg(0xec, 0x1d, 0x16, domain
);
216 swI2CWriteReg(0xec, 0x21, 0x9, domain
);
217 swI2CWriteReg(0xec, 0x49, 0xC0, domain
);
218 inf_msg("okay, CH7301 DVI chip setup done\n");
223 if (!share
->accel_off
) {
224 hw_sm750_initAccel(share
, domain
);
230 resource_size_t
hw_sm750_getVMSize(struct lynx_share
*share
, int domain
)
234 ret
= ddk750_getVMSize(domain
);
240 int hw_sm750_output_checkMode(struct lynxfb_output
*output
,
241 struct fb_var_screeninfo
*var
, int domain
)
248 int hw_sm750_output_setMode(struct lynxfb_output
*output
,
249 struct fb_var_screeninfo
*var
,
250 struct fb_fix_screeninfo
*fix
,
254 disp_output_t dispSet
;
259 channel
= *output
->channel
;
262 if (getChipType(domain
) != SM750LE
) {
263 if (channel
== sm750_primary
) {
264 inf_msg("primary channel\n");
265 if (output
->paths
& sm750_panel
)
266 dispSet
|= do_LCD1_PRI
;
267 if (output
->paths
& sm750_crt
)
268 dispSet
|= do_CRT_PRI
;
271 inf_msg("secondary channel\n");
272 if (output
->paths
& sm750_panel
)
273 dispSet
|= do_LCD1_SEC
;
274 if (output
->paths
& sm750_crt
)
275 dispSet
|= do_CRT_SEC
;
278 ddk750_setLogicalDispOut(dispSet
, domain
);
280 /* just open DISPLAY_CONTROL_750LE register bit 3:0 */
282 reg
= PEEK32(DISPLAY_CONTROL_750LE
, domain
);
284 POKE32(DISPLAY_CONTROL_750LE
, reg
, domain
);
287 inf_msg("ddk setlogicdispout done \n");
291 void hw_sm750_output_clear(struct lynxfb_output
*output
, int domain
)
297 int hw_sm750_crtc_checkMode(struct lynxfb_crtc
*crtc
,
298 struct fb_var_screeninfo
*var
, int domain
)
300 struct lynx_share
*share
;
303 share
= container_of(crtc
, struct lynxfb_par
, crtc
)->share
;
305 switch (var
->bits_per_pixel
) {
310 if (share
->revid
== (unsigned char) SM750LE_REVISION_ID
) {
311 dbg_msg("750le do not support 32bpp\n");
325 set the controller's mode for @crtc charged with @var and @fix parameters
327 int hw_sm750_crtc_setMode(struct lynxfb_crtc
*crtc
,
328 struct fb_var_screeninfo
*var
,
329 struct fb_fix_screeninfo
*fix
, int domain
)
333 mode_parameter_t modparm
;
335 struct lynx_share
*share
;
336 struct lynxfb_par
*par
;
340 par
= container_of(crtc
, struct lynxfb_par
, crtc
);
343 if (!share
->accel_off
) {
344 /* set 2d engine pixel format according to mode bpp */
345 switch (var
->bits_per_pixel
) {
357 hw_set2dformat(&share
->accel
, fmt
);
362 modparm
.pixel_clock
= ps_to_hz(var
->pixclock
);
363 modparm
.vertical_sync_polarity
=
364 (var
->sync
& FB_SYNC_HOR_HIGH_ACT
) ? POS
: NEG
;
365 modparm
.horizontal_sync_polarity
=
366 (var
->sync
& FB_SYNC_VERT_HIGH_ACT
) ? POS
: NEG
;
367 modparm
.clock_phase_polarity
=
368 (var
->sync
& FB_SYNC_COMP_HIGH_ACT
) ? POS
: NEG
;
369 modparm
.horizontal_display_end
= var
->xres
;
370 modparm
.horizontal_sync_width
= var
->hsync_len
;
371 modparm
.horizontal_sync_start
= var
->xres
+ var
->right_margin
;
372 modparm
.horizontal_total
=
373 var
->xres
+ var
->left_margin
+ var
->right_margin
+
375 modparm
.vertical_display_end
= var
->yres
;
376 modparm
.vertical_sync_height
= var
->vsync_len
;
377 modparm
.vertical_sync_start
= var
->yres
+ var
->lower_margin
;
378 modparm
.vertical_total
=
379 var
->yres
+ var
->upper_margin
+ var
->lower_margin
+
383 if (crtc
->channel
!= sm750_secondary
)
386 clock
= SECONDARY_PLL
;
388 dbg_msg("Request pixel clock = %lu\n", modparm
.pixel_clock
);
389 ret
= ddk750_setModeTiming(&modparm
, clock
, domain
);
391 err_msg("Set mode timing failed\n");
395 if (crtc
->channel
!= sm750_secondary
) {
396 /* set pitch, offset , width, start address , etc... */
397 POKE32(PANEL_FB_ADDRESS
,
398 crtc
->oScreen
<< PANEL_FB_ADDRESS_ADDRESS_LSB
, domain
);
399 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
400 /* crtc->channel is not equal to par->index on numeric, be aware of that */
401 reg
= PADDING(crtc
->line_pad
, reg
);
402 POKE32(PANEL_FB_WIDTH
,
403 (reg
<< PANEL_FB_WIDTH_WIDTH_LSB
) |
404 (fix
->line_length
<< PANEL_FB_WIDTH_OFFSET_LSB
),
407 POKE32(PANEL_WINDOW_WIDTH
,
408 ((var
->xres
- 1) << PANEL_WINDOW_WIDTH_WIDTH_LSB
) |
409 (var
->xoffset
<< PANEL_WINDOW_WIDTH_X_LSB
),
412 POKE32(PANEL_WINDOW_HEIGHT
,
413 ((var
->yres_virtual
- 1) << PANEL_WINDOW_HEIGHT_HEIGHT_LSB
) |
414 (var
->yoffset
<< PANEL_WINDOW_HEIGHT_Y_LSB
),
417 POKE32(PANEL_PLANE_TL
, 0, domain
);
419 POKE32(PANEL_PLANE_BR
,
420 ((var
->yres
- 1) << PANEL_PLANE_BR_BOTTOM_LSB
) |
421 ((var
->xres
- 1) << PANEL_PLANE_BR_RIGHT_LSB
),
424 /* set pixel format */
425 reg
= PEEK32(PANEL_DISPLAY_CTRL
, domain
);
426 POKE32(PANEL_DISPLAY_CTRL
,
427 (reg
& (~(3 << PANEL_DISPLAY_CTRL_FORMAT_LSB
))) |
428 ((var
->bits_per_pixel
>> 4) <<
429 PANEL_DISPLAY_CTRL_FORMAT_LSB
),
432 /* not implemented now */
433 POKE32(CRT_FB_ADDRESS
, crtc
->oScreen
, domain
);
434 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
435 /* crtc->channel is not equal to par->index on numeric, be aware of that */
436 reg
= PADDING(crtc
->line_pad
, reg
);
438 (reg
<< CRT_FB_WIDTH_WIDTH_LSB
) |
439 (fix
->line_length
<< CRT_FB_WIDTH_OFFSET_LSB
), domain
);
441 /* SET PIXEL FORMAT */
442 reg
= PEEK32(CRT_DISPLAY_CTRL
, domain
);
445 bits_per_pixel
>> 4) << CRT_DISPLAY_CTRL_FORMAT_LSB
;
446 POKE32(CRT_DISPLAY_CTRL
, reg
, domain
);
454 void hw_sm750_crtc_clear(struct lynxfb_crtc
*crtc
, int domain
)
460 int hw_sm750_setColReg(struct lynxfb_crtc
*crtc
, ushort index
,
461 ushort red
, ushort green
, ushort blue
, int domain
)
463 static unsigned int add
[] = { PANEL_PALETTE_RAM
, CRT_PALETTE_RAM
};
464 POKE32(add
[crtc
->channel
] + index
* 4,
465 (red
<< 16) | (green
<< 8) | blue
, domain
);
469 int hw_sm750le_setBLANK(struct lynxfb_output
*output
, int blank
, int domain
)
474 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
475 case FB_BLANK_UNBLANK
:
477 case VESA_NO_BLANKING
:
479 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
480 crtdb
= CRT_DISPLAY_CTRL_BLANK_OFF
;
482 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
483 case FB_BLANK_NORMAL
:
484 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
485 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
488 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
489 case FB_BLANK_VSYNC_SUSPEND
:
491 case VESA_VSYNC_SUSPEND
:
493 dpms
= CRT_DISPLAY_CTRL_DPMS_2
;
494 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
496 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
497 case FB_BLANK_HSYNC_SUSPEND
:
499 case VESA_HSYNC_SUSPEND
:
501 dpms
= CRT_DISPLAY_CTRL_DPMS_1
;
502 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
504 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
505 case FB_BLANK_POWERDOWN
:
509 dpms
= CRT_DISPLAY_CTRL_DPMS_3
;
510 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
516 if (output
->paths
& sm750_crt
) {
517 POKE32(CRT_DISPLAY_CTRL
,
518 (PEEK32(CRT_DISPLAY_CTRL
, domain
) &
519 (~(3 << CRT_DISPLAY_CTRL_DPMS_LSB
))) | (dpms
<<
520 CRT_DISPLAY_CTRL_DPMS_LSB
), domain
);
521 POKE32(CRT_DISPLAY_CTRL
,
522 (PEEK32(CRT_DISPLAY_CTRL
, domain
) &
523 (~(1 << CRT_DISPLAY_CTRL_BLANK_LSB
))) | (crtdb
<<
524 CRT_DISPLAY_CTRL_BLANK_LSB
), domain
);
529 int hw_sm750_setBLANK(struct lynxfb_output
*output
, int blank
, int domain
)
531 unsigned int dpms
, pps
, crtdb
;
533 dpms
= pps
= crtdb
= 0;
536 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
537 case FB_BLANK_UNBLANK
:
539 case VESA_NO_BLANKING
:
541 dbg_msg("flag = FB_BLANK_UNBLANK \n");
542 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
543 pps
= PANEL_DISPLAY_CTRL_DATA_ENABLE
;
544 crtdb
= CRT_DISPLAY_CTRL_BLANK_OFF
;
546 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
547 case FB_BLANK_NORMAL
:
548 dbg_msg("flag = FB_BLANK_NORMAL \n");
549 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
550 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
551 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
554 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
555 case FB_BLANK_VSYNC_SUSPEND
:
557 case VESA_VSYNC_SUSPEND
:
559 dpms
= SYSTEM_CTRL_DPMS_VNHP
;
560 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
561 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
563 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
564 case FB_BLANK_HSYNC_SUSPEND
:
566 case VESA_HSYNC_SUSPEND
:
568 dpms
= SYSTEM_CTRL_DPMS_VPHN
;
569 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
570 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
572 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
573 case FB_BLANK_POWERDOWN
:
577 dpms
= SYSTEM_CTRL_DPMS_VNHN
;
578 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
579 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
583 if (output
->paths
& sm750_crt
) {
585 (PEEK32(SYSTEM_CTRL
, domain
) & (~(3 << SYSTEM_CTRL_DPMS_LSB
)))
586 | (dpms
<< SYSTEM_CTRL_DPMS_LSB
), domain
);
587 POKE32(CRT_DISPLAY_CTRL
,
588 (PEEK32(CRT_DISPLAY_CTRL
, domain
) &
589 (~(1 << CRT_DISPLAY_CTRL_BLANK_LSB
)))
590 | (crtdb
<< CRT_DISPLAY_CTRL_BLANK_LSB
), domain
);
593 if (output
->paths
& sm750_panel
) {
594 POKE32(PANEL_DISPLAY_CTRL
,
595 (PEEK32(PANEL_DISPLAY_CTRL
, domain
) &
596 (~(1 << PANEL_DISPLAY_CTRL_DATA_LSB
)))
597 | (pps
<< PANEL_DISPLAY_CTRL_DATA_LSB
), domain
);
604 void hw_sm750_initAccel(struct lynx_share
*share
, int domain
)
607 enable2DEngine(1, domain
);
609 if (getChipType(domain
) == SM750LE
) {
610 reg
= PEEK32(DE_STATE1
, domain
);
611 reg
|= 1 << DE_STATE1_DE_ABORT_LSB
;
612 POKE32(DE_STATE1
, reg
, domain
);
614 reg
= PEEK32(DE_STATE1
, domain
);
615 reg
&= ~(1 << DE_STATE1_DE_ABORT_LSB
);
616 POKE32(DE_STATE1
, reg
, domain
);
620 reg
= PEEK32(SYSTEM_CTRL
, domain
);
621 reg
|= 1 << SYSTEM_CTRL_DE_ABORT_LSB
;
622 POKE32(SYSTEM_CTRL
, reg
, domain
);
624 reg
= PEEK32(SYSTEM_CTRL
, domain
);
625 reg
&= ~(1 << SYSTEM_CTRL_DE_ABORT_LSB
);
626 POKE32(SYSTEM_CTRL
, reg
, domain
);
630 share
->accel
.de_init(&share
->accel
);
633 int hw_sm750le_deWait(int domain
)
637 unsigned int dwVal
= PEEK32(DE_STATE2
, domain
);
638 if (((1 & (dwVal
>> DE_STATE2_DE_STATUS_LSB
)) ==
639 DE_STATE2_DE_STATUS_IDLE
)
640 && ((1 & (dwVal
>> DE_STATE2_DE_FIFO_LSB
)) ==
641 DE_STATE2_DE_FIFO_EMPTY
)
642 && ((1 & (dwVal
>> DE_STATE2_DE_MEM_FIFO_LSB
)) ==
643 DE_STATE2_DE_MEM_FIFO_EMPTY
)) {
652 int hw_sm750_deWait(int domain
)
656 unsigned int dwVal
= PEEK32(SYSTEM_CTRL
, domain
);
657 if (((1 & (dwVal
>> SYSTEM_CTRL_DE_STATUS_LSB
)) ==
658 SYSTEM_CTRL_DE_STATUS_IDLE
)
659 && ((1 & (dwVal
>> SYSTEM_CTRL_DE_FIFO_LSB
)) ==
660 SYSTEM_CTRL_DE_FIFO_EMPTY
)
661 && ((1 & (dwVal
>> SYSTEM_CTRL_DE_MEM_FIFO_LSB
)) ==
662 SYSTEM_CTRL_DE_MEM_FIFO_EMPTY
)) {
670 int hw_sm750_pan_display(struct lynxfb_crtc
*crtc
,
671 const struct fb_var_screeninfo
*var
,
672 const struct fb_info
*info
,
676 if ((var
->xoffset
+ var
->xres
> var
->xres_virtual
) ||
677 (var
->yoffset
+ var
->yres
> var
->yres_virtual
)) {
681 total
= var
->yoffset
* info
->fix
.line_length
+
682 ((var
->xoffset
* var
->bits_per_pixel
) >> 3);
683 total
+= crtc
->oScreen
;
684 if (crtc
->channel
== sm750_primary
) {
685 POKE32(PANEL_FB_ADDRESS
,
686 (PEEK32(PANEL_FB_ADDRESS
, domain
) &
687 (~(0x3ffffff << PANEL_FB_ADDRESS_ADDRESS_LSB
))) |
688 (total
<< PANEL_FB_ADDRESS_ADDRESS_LSB
), domain
);
690 POKE32(CRT_FB_ADDRESS
,
691 (PEEK32(CRT_FB_ADDRESS
, domain
) &
692 (~(0x3ffffff << CRT_FB_ADDRESS_ADDRESS_LSB
))) |
693 (total
<< CRT_FB_ADDRESS_ADDRESS_LSB
), domain
);
697 #else /* !CONFIG_FB_LYNXFB_DOMAINS: */
699 int hw_sm750_inithw(struct lynx_share
*share
, struct pci_dev
*pdev
)
701 struct sm750_share
*spec_share
;
702 struct init_status
*parm
;
706 spec_share
= container_of(share
, struct sm750_share
, share
);
707 parm
= &spec_share
->state
.initParm
;
708 if (parm
->chip_clk
== 0)
709 parm
->chip_clk
= (getChipType() == SM750LE
) ?
710 DEFAULT_SM750LE_CHIP_CLOCK
: DEFAULT_SM750_CHIP_CLOCK
;
712 if (parm
->mem_clk
== 0)
713 parm
->mem_clk
= parm
->chip_clk
;
714 if (parm
->master_clk
== 0)
715 parm
->master_clk
= parm
->chip_clk
/ 3;
717 ddk750_initHw((initchip_param_t
*) & spec_share
->state
.initParm
);
718 /* for sm718, open pci burst */
719 if (share
->devid
== 0x718) {
721 PEEK32(SYSTEM_CTRL
) | (1 <<
722 SYSTEM_CTRL_PCI_BURST_LSB
));
725 /* sm750 use sii164, it can be setup with default value
726 * by on power, so initDVIDisp can be skipped */
728 if (getChipType() != SM750LE
) {
729 /* does user need CRT ? */
730 if (spec_share
->state
.nocrt
) {
733 (1 << MISC_CTRL_DAC_POWER_LSB
));
736 PEEK32(SYSTEM_CTRL
) |
737 (3 << SYSTEM_CTRL_DPMS_LSB
));
741 (~(1 << MISC_CTRL_DAC_POWER_LSB
)));
744 PEEK32(SYSTEM_CTRL
) &
745 (~(3 << SYSTEM_CTRL_DPMS_LSB
)));
748 switch (spec_share
->state
.pnltype
) {
749 case sm750_doubleTFT
:
752 POKE32(PANEL_DISPLAY_CTRL
,
753 PEEK32(PANEL_DISPLAY_CTRL
) &
754 (~(3 << PANEL_DISPLAY_CTRL_TFT_DISP_LSB
)));
755 POKE32(PANEL_DISPLAY_CTRL
,
756 PEEK32(PANEL_DISPLAY_CTRL
) |
759 PANEL_DISPLAY_CTRL_TFT_DISP_LSB
));
763 /* for 750LE , no DVI chip initilization makes Monitor no signal */
764 /* Set up GPIO for software I2C to program DVI chip in the
765 Xilinx SP605 board, in order to have video signal.
770 /* Customer may NOT use CH7301 DVI chip, which has to be
771 initialized differently.
773 if (swI2CReadReg(0xec, 0x4a) == 0x95) {
774 /* The following register values for CH7301 are from
775 Chrontel app note and our experiment.
777 inf_msg("yes, CH7301 DVI chip found\n");
778 swI2CWriteReg(0xec, 0x1d, 0x16);
779 swI2CWriteReg(0xec, 0x21, 0x9);
780 swI2CWriteReg(0xec, 0x49, 0xC0);
781 inf_msg("okay, CH7301 DVI chip setup done\n");
786 if (!share
->accel_off
) {
787 hw_sm750_initAccel(share
);
793 resource_size_t
hw_sm750_getVMSize(struct lynx_share
*share
)
797 ret
= ddk750_getVMSize();
803 int hw_sm750_output_checkMode(struct lynxfb_output
*output
,
804 struct fb_var_screeninfo
*var
)
811 int hw_sm750_output_setMode(struct lynxfb_output
*output
,
812 struct fb_var_screeninfo
*var
,
813 struct fb_fix_screeninfo
*fix
)
816 disp_output_t dispSet
;
821 channel
= *output
->channel
;
824 if (getChipType() != SM750LE
) {
825 if (channel
== sm750_primary
) {
826 inf_msg("primary channel\n");
827 if (output
->paths
& sm750_panel
)
828 dispSet
|= do_LCD1_PRI
;
829 if (output
->paths
& sm750_crt
)
830 dispSet
|= do_CRT_PRI
;
833 inf_msg("secondary channel\n");
834 if (output
->paths
& sm750_panel
)
835 dispSet
|= do_LCD1_SEC
;
836 if (output
->paths
& sm750_crt
)
837 dispSet
|= do_CRT_SEC
;
840 ddk750_setLogicalDispOut(dispSet
);
842 /* just open DISPLAY_CONTROL_750LE register bit 3:0 */
844 reg
= PEEK32(DISPLAY_CONTROL_750LE
);
846 POKE32(DISPLAY_CONTROL_750LE
, reg
);
849 inf_msg("ddk setlogicdispout done \n");
853 void hw_sm750_output_clear(struct lynxfb_output
*output
)
859 int hw_sm750_crtc_checkMode(struct lynxfb_crtc
*crtc
,
860 struct fb_var_screeninfo
*var
)
862 struct lynx_share
*share
;
865 share
= container_of(crtc
, struct lynxfb_par
, crtc
)->share
;
867 switch (var
->bits_per_pixel
) {
872 if (share
->revid
== (unsigned char) SM750LE_REVISION_ID
) {
873 dbg_msg("750le do not support 32bpp\n");
887 set the controller's mode for @crtc charged with @var and @fix parameters
889 int hw_sm750_crtc_setMode(struct lynxfb_crtc
*crtc
,
890 struct fb_var_screeninfo
*var
,
891 struct fb_fix_screeninfo
*fix
)
895 mode_parameter_t modparm
;
897 struct lynx_share
*share
;
898 struct lynxfb_par
*par
;
902 par
= container_of(crtc
, struct lynxfb_par
, crtc
);
905 if (!share
->accel_off
) {
906 /* set 2d engine pixel format according to mode bpp */
907 switch (var
->bits_per_pixel
) {
919 hw_set2dformat(&share
->accel
, fmt
);
924 modparm
.pixel_clock
= ps_to_hz(var
->pixclock
);
925 modparm
.vertical_sync_polarity
=
926 (var
->sync
& FB_SYNC_HOR_HIGH_ACT
) ? POS
: NEG
;
927 modparm
.horizontal_sync_polarity
=
928 (var
->sync
& FB_SYNC_VERT_HIGH_ACT
) ? POS
: NEG
;
929 modparm
.clock_phase_polarity
=
930 (var
->sync
& FB_SYNC_COMP_HIGH_ACT
) ? POS
: NEG
;
931 modparm
.horizontal_display_end
= var
->xres
;
932 modparm
.horizontal_sync_width
= var
->hsync_len
;
933 modparm
.horizontal_sync_start
= var
->xres
+ var
->right_margin
;
934 modparm
.horizontal_total
=
935 var
->xres
+ var
->left_margin
+ var
->right_margin
+
937 modparm
.vertical_display_end
= var
->yres
;
938 modparm
.vertical_sync_height
= var
->vsync_len
;
939 modparm
.vertical_sync_start
= var
->yres
+ var
->lower_margin
;
940 modparm
.vertical_total
=
941 var
->yres
+ var
->upper_margin
+ var
->lower_margin
+
945 if (crtc
->channel
!= sm750_secondary
)
948 clock
= SECONDARY_PLL
;
950 dbg_msg("Request pixel clock = %lu\n", modparm
.pixel_clock
);
951 ret
= ddk750_setModeTiming(&modparm
, clock
);
953 err_msg("Set mode timing failed\n");
957 if (crtc
->channel
!= sm750_secondary
) {
958 /* set pitch, offset , width, start address , etc... */
959 POKE32(PANEL_FB_ADDRESS
,
960 crtc
->oScreen
<< PANEL_FB_ADDRESS_ADDRESS_LSB
);
961 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
962 /* crtc->channel is not equal to par->index on numeric, be aware of that */
963 reg
= PADDING(crtc
->line_pad
, reg
);
964 POKE32(PANEL_FB_WIDTH
,
965 (reg
<< PANEL_FB_WIDTH_WIDTH_LSB
) |
966 (fix
->line_length
<< PANEL_FB_WIDTH_OFFSET_LSB
));
968 POKE32(PANEL_WINDOW_WIDTH
,
969 ((var
->xres
- 1) << PANEL_WINDOW_WIDTH_WIDTH_LSB
) |
970 (var
->xoffset
<< PANEL_WINDOW_WIDTH_X_LSB
));
972 POKE32(PANEL_WINDOW_HEIGHT
,
973 ((var
->yres_virtual
- 1) << PANEL_WINDOW_HEIGHT_HEIGHT_LSB
) |
974 (var
->yoffset
<< PANEL_WINDOW_HEIGHT_Y_LSB
));
976 POKE32(PANEL_PLANE_TL
, 0);
978 POKE32(PANEL_PLANE_BR
,
979 ((var
->yres
- 1) << PANEL_PLANE_BR_BOTTOM_LSB
) |
980 ((var
->xres
- 1) << PANEL_PLANE_BR_RIGHT_LSB
));
982 /* set pixel format */
983 reg
= PEEK32(PANEL_DISPLAY_CTRL
);
984 POKE32(PANEL_DISPLAY_CTRL
,
985 (reg
& (~(3 << PANEL_DISPLAY_CTRL_FORMAT_LSB
))) |
986 ((var
->bits_per_pixel
>> 4) <<
987 PANEL_DISPLAY_CTRL_FORMAT_LSB
));
989 /* not implemented now */
990 POKE32(CRT_FB_ADDRESS
, crtc
->oScreen
);
991 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
992 /* crtc->channel is not equal to par->index on numeric, be aware of that */
993 reg
= PADDING(crtc
->line_pad
, reg
);
995 (reg
<< CRT_FB_WIDTH_WIDTH_LSB
) |
996 (fix
->line_length
<< CRT_FB_WIDTH_OFFSET_LSB
));
998 /* SET PIXEL FORMAT */
999 reg
= PEEK32(CRT_DISPLAY_CTRL
);
1002 bits_per_pixel
>> 4) << CRT_DISPLAY_CTRL_FORMAT_LSB
;
1003 POKE32(CRT_DISPLAY_CTRL
, reg
);
1011 void hw_sm750_crtc_clear(struct lynxfb_crtc
*crtc
)
1017 int hw_sm750_setColReg(struct lynxfb_crtc
*crtc
, ushort index
,
1018 ushort red
, ushort green
, ushort blue
)
1020 static unsigned int add
[] = { PANEL_PALETTE_RAM
, CRT_PALETTE_RAM
};
1021 POKE32(add
[crtc
->channel
] + index
* 4,
1022 (red
<< 16) | (green
<< 8) | blue
);
1026 int hw_sm750le_setBLANK(struct lynxfb_output
*output
, int blank
)
1031 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
1032 case FB_BLANK_UNBLANK
:
1034 case VESA_NO_BLANKING
:
1036 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
1037 crtdb
= CRT_DISPLAY_CTRL_BLANK_OFF
;
1039 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
1040 case FB_BLANK_NORMAL
:
1041 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
1042 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
1045 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
1046 case FB_BLANK_VSYNC_SUSPEND
:
1048 case VESA_VSYNC_SUSPEND
:
1050 dpms
= CRT_DISPLAY_CTRL_DPMS_2
;
1051 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
1053 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
1054 case FB_BLANK_HSYNC_SUSPEND
:
1056 case VESA_HSYNC_SUSPEND
:
1058 dpms
= CRT_DISPLAY_CTRL_DPMS_1
;
1059 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
1061 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
1062 case FB_BLANK_POWERDOWN
:
1064 case VESA_POWERDOWN
:
1066 dpms
= CRT_DISPLAY_CTRL_DPMS_3
;
1067 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
1073 if (output
->paths
& sm750_crt
) {
1074 POKE32(CRT_DISPLAY_CTRL
,
1075 (PEEK32(CRT_DISPLAY_CTRL
) &
1076 (~(3 << CRT_DISPLAY_CTRL_DPMS_LSB
))) | (dpms
<<
1077 CRT_DISPLAY_CTRL_DPMS_LSB
));
1078 POKE32(CRT_DISPLAY_CTRL
,
1079 (PEEK32(CRT_DISPLAY_CTRL
) &
1080 (~(1 << CRT_DISPLAY_CTRL_BLANK_LSB
))) | (crtdb
<<
1081 CRT_DISPLAY_CTRL_BLANK_LSB
));
1086 int hw_sm750_setBLANK(struct lynxfb_output
*output
, int blank
)
1088 unsigned int dpms
, pps
, crtdb
;
1090 dpms
= pps
= crtdb
= 0;
1093 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
1094 case FB_BLANK_UNBLANK
:
1096 case VESA_NO_BLANKING
:
1098 dbg_msg("flag = FB_BLANK_UNBLANK \n");
1099 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
1100 pps
= PANEL_DISPLAY_CTRL_DATA_ENABLE
;
1101 crtdb
= CRT_DISPLAY_CTRL_BLANK_OFF
;
1103 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
1104 case FB_BLANK_NORMAL
:
1105 dbg_msg("flag = FB_BLANK_NORMAL \n");
1106 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
1107 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
1108 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
1111 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
1112 case FB_BLANK_VSYNC_SUSPEND
:
1114 case VESA_VSYNC_SUSPEND
:
1116 dpms
= SYSTEM_CTRL_DPMS_VNHP
;
1117 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
1118 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
1120 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
1121 case FB_BLANK_HSYNC_SUSPEND
:
1123 case VESA_HSYNC_SUSPEND
:
1125 dpms
= SYSTEM_CTRL_DPMS_VPHN
;
1126 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
1127 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
1129 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
1130 case FB_BLANK_POWERDOWN
:
1132 case VESA_POWERDOWN
:
1134 dpms
= SYSTEM_CTRL_DPMS_VNHN
;
1135 pps
= PANEL_DISPLAY_CTRL_DATA_DISABLE
;
1136 crtdb
= CRT_DISPLAY_CTRL_BLANK_ON
;
1140 if (output
->paths
& sm750_crt
) {
1142 (PEEK32(SYSTEM_CTRL
) & (~(3 << SYSTEM_CTRL_DPMS_LSB
)))
1143 | (dpms
<< SYSTEM_CTRL_DPMS_LSB
));
1144 POKE32(CRT_DISPLAY_CTRL
,
1145 (PEEK32(CRT_DISPLAY_CTRL
) &
1146 (~(1 << CRT_DISPLAY_CTRL_BLANK_LSB
)))
1147 | (crtdb
<< CRT_DISPLAY_CTRL_BLANK_LSB
));
1150 if (output
->paths
& sm750_panel
) {
1151 POKE32(PANEL_DISPLAY_CTRL
,
1152 (PEEK32(PANEL_DISPLAY_CTRL
) &
1153 (~(1 << PANEL_DISPLAY_CTRL_DATA_LSB
)))
1154 | (pps
<< PANEL_DISPLAY_CTRL_DATA_LSB
));
1161 void hw_sm750_initAccel(struct lynx_share
*share
)
1166 if (getChipType() == SM750LE
) {
1167 reg
= PEEK32(DE_STATE1
);
1168 reg
|= 1 << DE_STATE1_DE_ABORT_LSB
;
1169 POKE32(DE_STATE1
, reg
);
1171 reg
= PEEK32(DE_STATE1
);
1172 reg
&= ~(1 << DE_STATE1_DE_ABORT_LSB
);
1173 POKE32(DE_STATE1
, reg
);
1177 reg
= PEEK32(SYSTEM_CTRL
);
1178 reg
|= 1 << SYSTEM_CTRL_DE_ABORT_LSB
;
1179 POKE32(SYSTEM_CTRL
, reg
);
1181 reg
= PEEK32(SYSTEM_CTRL
);
1182 reg
&= ~(1 << SYSTEM_CTRL_DE_ABORT_LSB
);
1183 POKE32(SYSTEM_CTRL
, reg
);
1187 share
->accel
.de_init(&share
->accel
);
1190 int hw_sm750le_deWait()
1194 unsigned int dwVal
= PEEK32(DE_STATE2
);
1195 if (((1 & (dwVal
>> DE_STATE2_DE_STATUS_LSB
)) ==
1196 DE_STATE2_DE_STATUS_IDLE
)
1197 && ((1 & (dwVal
>> DE_STATE2_DE_FIFO_LSB
)) ==
1198 DE_STATE2_DE_FIFO_EMPTY
)
1199 && ((1 & (dwVal
>> DE_STATE2_DE_MEM_FIFO_LSB
)) ==
1200 DE_STATE2_DE_MEM_FIFO_EMPTY
)) {
1209 int hw_sm750_deWait()
1213 unsigned int dwVal
= PEEK32(SYSTEM_CTRL
);
1214 if (((1 & (dwVal
>> SYSTEM_CTRL_DE_STATUS_LSB
)) ==
1215 SYSTEM_CTRL_DE_STATUS_IDLE
)
1216 && ((1 & (dwVal
>> SYSTEM_CTRL_DE_FIFO_LSB
)) ==
1217 SYSTEM_CTRL_DE_FIFO_EMPTY
)
1218 && ((1 & (dwVal
>> SYSTEM_CTRL_DE_MEM_FIFO_LSB
)) ==
1219 SYSTEM_CTRL_DE_MEM_FIFO_EMPTY
)) {
1227 int hw_sm750_pan_display(struct lynxfb_crtc
*crtc
,
1228 const struct fb_var_screeninfo
*var
,
1229 const struct fb_info
*info
)
1232 if ((var
->xoffset
+ var
->xres
> var
->xres_virtual
) ||
1233 (var
->yoffset
+ var
->yres
> var
->yres_virtual
)) {
1237 total
= var
->yoffset
* info
->fix
.line_length
+
1238 ((var
->xoffset
* var
->bits_per_pixel
) >> 3);
1239 total
+= crtc
->oScreen
;
1240 if (crtc
->channel
== sm750_primary
) {
1241 POKE32(PANEL_FB_ADDRESS
,
1242 (PEEK32(PANEL_FB_ADDRESS
) &
1243 (~(0x3ffffff << PANEL_FB_ADDRESS_ADDRESS_LSB
))) |
1244 (total
<< PANEL_FB_ADDRESS_ADDRESS_LSB
));
1246 POKE32(CRT_FB_ADDRESS
,
1247 (PEEK32(CRT_FB_ADDRESS
) &
1248 (~(0x3ffffff << CRT_FB_ADDRESS_ADDRESS_LSB
))) |
1249 (total
<< CRT_FB_ADDRESS_ADDRESS_LSB
));
1253 #endif /* !CONFIG_FB_LYNXFB_DOMAINS */