1 // SPDX-License-Identifier: GPL-2.0
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 void __iomem
*mmio750
;
29 int hw_sm750_map(struct sm750_dev
*sm750_dev
, struct pci_dev
*pdev
)
35 sm750_dev
->vidreg_start
= pci_resource_start(pdev
, 1);
36 sm750_dev
->vidreg_size
= SZ_2M
;
38 pr_info("mmio phyAddr = %lx\n", sm750_dev
->vidreg_start
);
41 * reserve the vidreg space of smi adaptor
42 * if you do this, you need to add release region code
43 * in lynxfb_remove, or memory will not be mapped again
46 ret
= pci_request_region(pdev
, 1, "sm750fb");
48 pr_err("Can not request PCI regions.\n");
52 /* now map mmio and vidmem */
53 sm750_dev
->pvReg
= ioremap_nocache(sm750_dev
->vidreg_start
,
54 sm750_dev
->vidreg_size
);
55 if (!sm750_dev
->pvReg
) {
56 pr_err("mmio failed\n");
60 pr_info("mmio virtual addr = %p\n", sm750_dev
->pvReg
);
63 sm750_dev
->accel
.dprBase
= sm750_dev
->pvReg
+ DE_BASE_ADDR_TYPE1
;
64 sm750_dev
->accel
.dpPortBase
= sm750_dev
->pvReg
+ DE_PORT_ADDR_TYPE1
;
66 mmio750
= sm750_dev
->pvReg
;
67 sm750_set_chip_type(sm750_dev
->devid
, sm750_dev
->revid
);
69 sm750_dev
->vidmem_start
= pci_resource_start(pdev
, 0);
71 * don't use pdev_resource[x].end - resource[x].start to
72 * calculate the resource size, it's only the maximum available
73 * size but not the actual size, using
74 * @ddk750_get_vm_size function can be safe.
76 sm750_dev
->vidmem_size
= ddk750_get_vm_size();
77 pr_info("video memory phyAddr = %lx, size = %u bytes\n",
78 sm750_dev
->vidmem_start
, sm750_dev
->vidmem_size
);
80 /* reserve the vidmem space of smi adaptor */
81 sm750_dev
->pvMem
= ioremap_wc(sm750_dev
->vidmem_start
,
82 sm750_dev
->vidmem_size
);
83 if (!sm750_dev
->pvMem
) {
84 pr_err("Map video memory failed\n");
88 pr_info("video memory vaddr = %p\n", sm750_dev
->pvMem
);
94 int hw_sm750_inithw(struct sm750_dev
*sm750_dev
, struct pci_dev
*pdev
)
96 struct init_status
*parm
;
98 parm
= &sm750_dev
->initParm
;
99 if (parm
->chip_clk
== 0)
100 parm
->chip_clk
= (sm750_get_chip_type() == SM750LE
) ?
101 DEFAULT_SM750LE_CHIP_CLOCK
:
102 DEFAULT_SM750_CHIP_CLOCK
;
104 if (parm
->mem_clk
== 0)
105 parm
->mem_clk
= parm
->chip_clk
;
106 if (parm
->master_clk
== 0)
107 parm
->master_clk
= parm
->chip_clk
/ 3;
109 ddk750_init_hw((struct initchip_param
*)&sm750_dev
->initParm
);
110 /* for sm718, open pci burst */
111 if (sm750_dev
->devid
== 0x718) {
113 peek32(SYSTEM_CTRL
) | SYSTEM_CTRL_PCI_BURST
);
116 if (sm750_get_chip_type() != SM750LE
) {
118 /* does user need CRT? */
119 if (sm750_dev
->nocrt
) {
121 peek32(MISC_CTRL
) | MISC_CTRL_DAC_POWER_OFF
);
123 val
= peek32(SYSTEM_CTRL
) & ~SYSTEM_CTRL_DPMS_MASK
;
124 val
|= SYSTEM_CTRL_DPMS_VPHN
;
125 poke32(SYSTEM_CTRL
, val
);
128 peek32(MISC_CTRL
) & ~MISC_CTRL_DAC_POWER_OFF
);
130 val
= peek32(SYSTEM_CTRL
) & ~SYSTEM_CTRL_DPMS_MASK
;
131 val
|= SYSTEM_CTRL_DPMS_VPHP
;
132 poke32(SYSTEM_CTRL
, val
);
135 val
= peek32(PANEL_DISPLAY_CTRL
) &
136 ~(PANEL_DISPLAY_CTRL_DUAL_DISPLAY
|
137 PANEL_DISPLAY_CTRL_DOUBLE_PIXEL
);
138 switch (sm750_dev
->pnltype
) {
141 case sm750_doubleTFT
:
142 val
|= PANEL_DISPLAY_CTRL_DOUBLE_PIXEL
;
145 val
|= PANEL_DISPLAY_CTRL_DUAL_DISPLAY
;
148 poke32(PANEL_DISPLAY_CTRL
, val
);
151 * for 750LE, no DVI chip initialization
152 * makes Monitor no signal
154 * Set up GPIO for software I2C to program DVI chip in the
155 * Xilinx SP605 board, in order to have video signal.
157 sm750_sw_i2c_init(0, 1);
160 * Customer may NOT use CH7301 DVI chip, which has to be
161 * initialized differently.
163 if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) {
165 * The following register values for CH7301 are from
166 * Chrontel app note and our experiment.
168 pr_info("yes,CH7301 DVI chip found\n");
169 sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16);
170 sm750_sw_i2c_write_reg(0xec, 0x21, 0x9);
171 sm750_sw_i2c_write_reg(0xec, 0x49, 0xC0);
172 pr_info("okay,CH7301 DVI chip setup done\n");
177 if (!sm750_dev
->accel_off
)
178 hw_sm750_initAccel(sm750_dev
);
183 int hw_sm750_output_setMode(struct lynxfb_output
*output
,
184 struct fb_var_screeninfo
*var
,
185 struct fb_fix_screeninfo
*fix
)
188 disp_output_t dispSet
;
193 channel
= *output
->channel
;
195 if (sm750_get_chip_type() != SM750LE
) {
196 if (channel
== sm750_primary
) {
197 pr_info("primary channel\n");
198 if (output
->paths
& sm750_panel
)
199 dispSet
|= do_LCD1_PRI
;
200 if (output
->paths
& sm750_crt
)
201 dispSet
|= do_CRT_PRI
;
204 pr_info("secondary channel\n");
205 if (output
->paths
& sm750_panel
)
206 dispSet
|= do_LCD1_SEC
;
207 if (output
->paths
& sm750_crt
)
208 dispSet
|= do_CRT_SEC
;
210 ddk750_setLogicalDispOut(dispSet
);
212 /* just open DISPLAY_CONTROL_750LE register bit 3:0 */
215 reg
= peek32(DISPLAY_CONTROL_750LE
);
217 poke32(DISPLAY_CONTROL_750LE
, reg
);
220 pr_info("ddk setlogicdispout done\n");
224 int hw_sm750_crtc_checkMode(struct lynxfb_crtc
*crtc
,
225 struct fb_var_screeninfo
*var
)
227 struct sm750_dev
*sm750_dev
;
228 struct lynxfb_par
*par
= container_of(crtc
, struct lynxfb_par
, crtc
);
230 sm750_dev
= par
->dev
;
232 switch (var
->bits_per_pixel
) {
237 if (sm750_dev
->revid
== SM750LE_REVISION_ID
) {
238 pr_debug("750le do not support 32bpp\n");
249 /* 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 struct mode_parameter modparm
;
258 struct sm750_dev
*sm750_dev
;
259 struct lynxfb_par
*par
;
262 par
= container_of(crtc
, struct lynxfb_par
, crtc
);
263 sm750_dev
= par
->dev
;
265 if (!sm750_dev
->accel_off
) {
266 /* set 2d engine pixel format according to mode bpp */
267 switch (var
->bits_per_pixel
) {
279 sm750_hw_set2dformat(&sm750_dev
->accel
, fmt
);
283 modparm
.pixel_clock
= ps_to_hz(var
->pixclock
);
284 modparm
.vertical_sync_polarity
= (var
->sync
& FB_SYNC_HOR_HIGH_ACT
)
286 modparm
.horizontal_sync_polarity
= (var
->sync
& FB_SYNC_VERT_HIGH_ACT
)
288 modparm
.clock_phase_polarity
= (var
->sync
& FB_SYNC_COMP_HIGH_ACT
)
290 modparm
.horizontal_display_end
= var
->xres
;
291 modparm
.horizontal_sync_width
= var
->hsync_len
;
292 modparm
.horizontal_sync_start
= var
->xres
+ var
->right_margin
;
293 modparm
.horizontal_total
= var
->xres
+ var
->left_margin
+
294 var
->right_margin
+ var
->hsync_len
;
295 modparm
.vertical_display_end
= var
->yres
;
296 modparm
.vertical_sync_height
= var
->vsync_len
;
297 modparm
.vertical_sync_start
= var
->yres
+ var
->lower_margin
;
298 modparm
.vertical_total
= var
->yres
+ var
->upper_margin
+
299 var
->lower_margin
+ var
->vsync_len
;
302 if (crtc
->channel
!= sm750_secondary
)
305 clock
= SECONDARY_PLL
;
307 pr_debug("Request pixel clock = %lu\n", modparm
.pixel_clock
);
308 ret
= ddk750_setModeTiming(&modparm
, clock
);
310 pr_err("Set mode timing failed\n");
314 if (crtc
->channel
!= sm750_secondary
) {
315 /* set pitch, offset, width, start address, etc... */
316 poke32(PANEL_FB_ADDRESS
,
317 crtc
->oScreen
& PANEL_FB_ADDRESS_ADDRESS_MASK
);
319 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
321 * crtc->channel is not equal to par->index on numeric,
324 reg
= ALIGN(reg
, crtc
->line_pad
);
325 reg
= (reg
<< PANEL_FB_WIDTH_WIDTH_SHIFT
) &
326 PANEL_FB_WIDTH_WIDTH_MASK
;
327 reg
|= (fix
->line_length
& PANEL_FB_WIDTH_OFFSET_MASK
);
328 poke32(PANEL_FB_WIDTH
, reg
);
330 reg
= ((var
->xres
- 1) << PANEL_WINDOW_WIDTH_WIDTH_SHIFT
) &
331 PANEL_WINDOW_WIDTH_WIDTH_MASK
;
332 reg
|= (var
->xoffset
& PANEL_WINDOW_WIDTH_X_MASK
);
333 poke32(PANEL_WINDOW_WIDTH
, reg
);
335 reg
= (var
->yres_virtual
- 1) <<
336 PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT
;
337 reg
&= PANEL_WINDOW_HEIGHT_HEIGHT_MASK
;
338 reg
|= (var
->yoffset
& PANEL_WINDOW_HEIGHT_Y_MASK
);
339 poke32(PANEL_WINDOW_HEIGHT
, reg
);
341 poke32(PANEL_PLANE_TL
, 0);
343 reg
= ((var
->yres
- 1) << PANEL_PLANE_BR_BOTTOM_SHIFT
) &
344 PANEL_PLANE_BR_BOTTOM_MASK
;
345 reg
|= ((var
->xres
- 1) & PANEL_PLANE_BR_RIGHT_MASK
);
346 poke32(PANEL_PLANE_BR
, reg
);
348 /* set pixel format */
349 reg
= peek32(PANEL_DISPLAY_CTRL
);
350 poke32(PANEL_DISPLAY_CTRL
, reg
| (var
->bits_per_pixel
>> 4));
352 /* not implemented now */
353 poke32(CRT_FB_ADDRESS
, crtc
->oScreen
);
354 reg
= var
->xres
* (var
->bits_per_pixel
>> 3);
356 * crtc->channel is not equal to par->index on numeric,
359 reg
= ALIGN(reg
, crtc
->line_pad
) << CRT_FB_WIDTH_WIDTH_SHIFT
;
360 reg
&= CRT_FB_WIDTH_WIDTH_MASK
;
361 reg
|= (fix
->line_length
& CRT_FB_WIDTH_OFFSET_MASK
);
362 poke32(CRT_FB_WIDTH
, reg
);
364 /* SET PIXEL FORMAT */
365 reg
= peek32(CRT_DISPLAY_CTRL
);
366 reg
|= ((var
->bits_per_pixel
>> 4) &
367 CRT_DISPLAY_CTRL_FORMAT_MASK
);
368 poke32(CRT_DISPLAY_CTRL
, reg
);
375 int hw_sm750_setColReg(struct lynxfb_crtc
*crtc
, ushort index
,
376 ushort red
, ushort green
, ushort blue
)
378 static unsigned int add
[] = {PANEL_PALETTE_RAM
, CRT_PALETTE_RAM
};
380 poke32(add
[crtc
->channel
] + index
* 4,
381 (red
<< 16) | (green
<< 8) | blue
);
385 int hw_sm750le_setBLANK(struct lynxfb_output
*output
, int blank
)
390 case FB_BLANK_UNBLANK
:
391 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
394 case FB_BLANK_NORMAL
:
395 dpms
= CRT_DISPLAY_CTRL_DPMS_0
;
396 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
398 case FB_BLANK_VSYNC_SUSPEND
:
399 dpms
= CRT_DISPLAY_CTRL_DPMS_2
;
400 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
402 case FB_BLANK_HSYNC_SUSPEND
:
403 dpms
= CRT_DISPLAY_CTRL_DPMS_1
;
404 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
406 case FB_BLANK_POWERDOWN
:
407 dpms
= CRT_DISPLAY_CTRL_DPMS_3
;
408 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
414 if (output
->paths
& sm750_crt
) {
417 val
= peek32(CRT_DISPLAY_CTRL
) & ~CRT_DISPLAY_CTRL_DPMS_MASK
;
418 poke32(CRT_DISPLAY_CTRL
, val
| dpms
);
420 val
= peek32(CRT_DISPLAY_CTRL
) & ~CRT_DISPLAY_CTRL_BLANK
;
421 poke32(CRT_DISPLAY_CTRL
, val
| crtdb
);
426 int hw_sm750_setBLANK(struct lynxfb_output
*output
, int blank
)
428 unsigned int dpms
, pps
, crtdb
;
435 case FB_BLANK_UNBLANK
:
436 pr_debug("flag = FB_BLANK_UNBLANK\n");
437 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
438 pps
= PANEL_DISPLAY_CTRL_DATA
;
440 case FB_BLANK_NORMAL
:
441 pr_debug("flag = FB_BLANK_NORMAL\n");
442 dpms
= SYSTEM_CTRL_DPMS_VPHP
;
443 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
445 case FB_BLANK_VSYNC_SUSPEND
:
446 dpms
= SYSTEM_CTRL_DPMS_VNHP
;
447 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
449 case FB_BLANK_HSYNC_SUSPEND
:
450 dpms
= SYSTEM_CTRL_DPMS_VPHN
;
451 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
453 case FB_BLANK_POWERDOWN
:
454 dpms
= SYSTEM_CTRL_DPMS_VNHN
;
455 crtdb
= CRT_DISPLAY_CTRL_BLANK
;
459 if (output
->paths
& sm750_crt
) {
460 unsigned int val
= peek32(SYSTEM_CTRL
) & ~SYSTEM_CTRL_DPMS_MASK
;
462 poke32(SYSTEM_CTRL
, val
| dpms
);
464 val
= peek32(CRT_DISPLAY_CTRL
) & ~CRT_DISPLAY_CTRL_BLANK
;
465 poke32(CRT_DISPLAY_CTRL
, val
| crtdb
);
468 if (output
->paths
& sm750_panel
) {
469 unsigned int val
= peek32(PANEL_DISPLAY_CTRL
);
471 val
&= ~PANEL_DISPLAY_CTRL_DATA
;
473 poke32(PANEL_DISPLAY_CTRL
, val
);
479 void hw_sm750_initAccel(struct sm750_dev
*sm750_dev
)
483 sm750_enable_2d_engine(1);
485 if (sm750_get_chip_type() == SM750LE
) {
486 reg
= peek32(DE_STATE1
);
487 reg
|= DE_STATE1_DE_ABORT
;
488 poke32(DE_STATE1
, reg
);
490 reg
= peek32(DE_STATE1
);
491 reg
&= ~DE_STATE1_DE_ABORT
;
492 poke32(DE_STATE1
, reg
);
496 reg
= peek32(SYSTEM_CTRL
);
497 reg
|= SYSTEM_CTRL_DE_ABORT
;
498 poke32(SYSTEM_CTRL
, reg
);
500 reg
= peek32(SYSTEM_CTRL
);
501 reg
&= ~SYSTEM_CTRL_DE_ABORT
;
502 poke32(SYSTEM_CTRL
, reg
);
506 sm750_dev
->accel
.de_init(&sm750_dev
->accel
);
509 int hw_sm750le_deWait(void)
512 unsigned int mask
= DE_STATE2_DE_STATUS_BUSY
| DE_STATE2_DE_FIFO_EMPTY
|
513 DE_STATE2_DE_MEM_FIFO_EMPTY
;
516 unsigned int val
= peek32(DE_STATE2
);
519 (DE_STATE2_DE_FIFO_EMPTY
| DE_STATE2_DE_MEM_FIFO_EMPTY
))
526 int hw_sm750_deWait(void)
529 unsigned int mask
= SYSTEM_CTRL_DE_STATUS_BUSY
|
530 SYSTEM_CTRL_DE_FIFO_EMPTY
|
531 SYSTEM_CTRL_DE_MEM_FIFO_EMPTY
;
534 unsigned int val
= peek32(SYSTEM_CTRL
);
537 (SYSTEM_CTRL_DE_FIFO_EMPTY
| SYSTEM_CTRL_DE_MEM_FIFO_EMPTY
))
544 int hw_sm750_pan_display(struct lynxfb_crtc
*crtc
,
545 const struct fb_var_screeninfo
*var
,
546 const struct fb_info
*info
)
550 if ((var
->xoffset
+ var
->xres
> var
->xres_virtual
) ||
551 (var
->yoffset
+ var
->yres
> var
->yres_virtual
)) {
555 total
= var
->yoffset
* info
->fix
.line_length
+
556 ((var
->xoffset
* var
->bits_per_pixel
) >> 3);
557 total
+= crtc
->oScreen
;
558 if (crtc
->channel
== sm750_primary
) {
559 poke32(PANEL_FB_ADDRESS
,
560 peek32(PANEL_FB_ADDRESS
) |
561 (total
& PANEL_FB_ADDRESS_ADDRESS_MASK
));
563 poke32(CRT_FB_ADDRESS
,
564 peek32(CRT_FB_ADDRESS
) |
565 (total
& CRT_FB_ADDRESS_ADDRESS_MASK
));