]>
Commit | Line | Data |
---|---|---|
81dee67e SM |
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> | |
6 | #include<linux/mm.h> | |
7 | #include<linux/slab.h> | |
8 | #include<linux/delay.h> | |
9 | #include<linux/fb.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> | |
16 | #ifdef CONFIG_MTRR | |
17 | #include <asm/mtrr.h> | |
18 | #endif | |
19 | #include<linux/platform_device.h> | |
20 | #include<linux/screen_info.h> | |
21 | ||
22 | #include "sm750.h" | |
23 | #include "sm750_hw.h" | |
24 | #include "ddk750.h" | |
25 | #include "sm750_accel.h" | |
26 | ||
d2a60377 | 27 | int hw_sm750_map(struct lynx_share* share, struct pci_dev* pdev) |
81dee67e SM |
28 | { |
29 | int ret; | |
30 | struct sm750_share * spec_share; | |
31 | ||
32 | ||
d2a60377 | 33 | spec_share = container_of(share, struct sm750_share,share); |
81dee67e SM |
34 | ret = 0; |
35 | ||
d2a60377 | 36 | share->vidreg_start = pci_resource_start(pdev, 1); |
81dee67e SM |
37 | share->vidreg_size = MB(2); |
38 | ||
e936351a | 39 | pr_info("mmio phyAddr = %lx\n", share->vidreg_start); |
81dee67e SM |
40 | |
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 | |
44 | * successfully | |
45 | * */ | |
46 | ||
d2a60377 | 47 | if((ret = pci_request_region(pdev, 1, "sm750fb"))) |
81dee67e SM |
48 | { |
49 | pr_err("Can not request PCI regions.\n"); | |
50 | goto exit; | |
51 | } | |
52 | ||
53 | /* now map mmio and vidmem*/ | |
d2a60377 | 54 | share->pvReg = ioremap_nocache(share->vidreg_start, share->vidreg_size); |
81dee67e SM |
55 | if(!share->pvReg){ |
56 | pr_err("mmio failed\n"); | |
57 | ret = -EFAULT; | |
58 | goto exit; | |
59 | }else{ | |
d2a60377 | 60 | pr_info("mmio virtual addr = %p\n", share->pvReg); |
81dee67e SM |
61 | } |
62 | ||
63 | ||
64 | share->accel.dprBase = share->pvReg + DE_BASE_ADDR_TYPE1; | |
65 | share->accel.dpPortBase = share->pvReg + DE_PORT_ADDR_TYPE1; | |
66 | ||
d2a60377 | 67 | ddk750_set_mmio(share->pvReg,share->devid, share->revid); |
81dee67e | 68 | |
d2a60377 | 69 | share->vidmem_start = pci_resource_start(pdev, 0); |
81dee67e SM |
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. | |
74 | * */ | |
75 | share->vidmem_size = hw_sm750_getVMSize(share); | |
e936351a | 76 | pr_info("video memory phyAddr = %lx, size = %u bytes\n", |
d2a60377 | 77 | share->vidmem_start, share->vidmem_size); |
81dee67e SM |
78 | |
79 | /* reserve the vidmem space of smi adaptor */ | |
80 | #if 0 | |
81 | if((ret = pci_request_region(pdev,0,_moduleName_))) | |
82 | { | |
83 | pr_err("Can not request PCI regions.\n"); | |
84 | goto exit; | |
85 | } | |
86 | #endif | |
87 | ||
88 | share->pvMem = ioremap(share->vidmem_start, | |
89 | share->vidmem_size); | |
90 | ||
91 | if(!share->pvMem){ | |
92 | pr_err("Map video memory failed\n"); | |
93 | ret = -EFAULT; | |
94 | goto exit; | |
95 | }else{ | |
d2a60377 | 96 | pr_info("video memory vaddr = %p\n", share->pvMem); |
81dee67e SM |
97 | } |
98 | exit: | |
99 | return ret; | |
100 | } | |
101 | ||
102 | ||
103 | ||
d2a60377 | 104 | int hw_sm750_inithw(struct lynx_share* share, struct pci_dev * pdev) |
81dee67e SM |
105 | { |
106 | struct sm750_share * spec_share; | |
107 | struct init_status * parm; | |
108 | ||
d2a60377 | 109 | spec_share = container_of(share, struct sm750_share,share); |
81dee67e SM |
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; | |
115 | ||
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; | |
120 | ||
121 | ddk750_initHw((initchip_param_t *)&spec_share->state.initParm); | |
122 | /* for sm718,open pci burst */ | |
123 | if(share->devid == 0x718){ | |
124 | POKE32(SYSTEM_CTRL, | |
d2a60377 | 125 | FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON)); |
81dee67e SM |
126 | } |
127 | ||
128 | /* sm750 use sii164, it can be setup with default value | |
129 | * by on power, so initDVIDisp can be skipped */ | |
130 | #if 0 | |
131 | ddk750_initDVIDisp(); | |
132 | #endif | |
133 | ||
134 | if(getChipType() != SM750LE) | |
135 | { | |
136 | /* does user need CRT ?*/ | |
137 | if(spec_share->state.nocrt){ | |
138 | POKE32(MISC_CTRL, | |
139 | FIELD_SET(PEEK32(MISC_CTRL), | |
140 | MISC_CTRL, | |
d2a60377 | 141 | DAC_POWER, OFF)); |
81dee67e SM |
142 | /* shut off dpms */ |
143 | POKE32(SYSTEM_CTRL, | |
144 | FIELD_SET(PEEK32(SYSTEM_CTRL), | |
145 | SYSTEM_CTRL, | |
d2a60377 | 146 | DPMS, VNHN)); |
81dee67e SM |
147 | }else{ |
148 | POKE32(MISC_CTRL, | |
149 | FIELD_SET(PEEK32(MISC_CTRL), | |
150 | MISC_CTRL, | |
d2a60377 | 151 | DAC_POWER, ON)); |
81dee67e SM |
152 | /* turn on dpms */ |
153 | POKE32(SYSTEM_CTRL, | |
154 | FIELD_SET(PEEK32(SYSTEM_CTRL), | |
155 | SYSTEM_CTRL, | |
d2a60377 | 156 | DPMS, VPHP)); |
81dee67e SM |
157 | } |
158 | ||
159 | switch (spec_share->state.pnltype){ | |
160 | case sm750_doubleTFT: | |
161 | case sm750_24TFT: | |
162 | case sm750_dualTFT: | |
163 | POKE32(PANEL_DISPLAY_CTRL, | |
164 | FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), | |
165 | PANEL_DISPLAY_CTRL, | |
166 | TFT_DISP, | |
167 | spec_share->state.pnltype)); | |
168 | break; | |
169 | } | |
170 | }else{ | |
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. | |
174 | */ | |
175 | swI2CInit(0,1); | |
176 | ||
177 | ||
178 | /* Customer may NOT use CH7301 DVI chip, which has to be | |
179 | initialized differently. | |
180 | */ | |
181 | if (swI2CReadReg(0xec, 0x4a) == 0x95) | |
182 | { | |
183 | /* The following register values for CH7301 are from | |
184 | Chrontel app note and our experiment. | |
185 | */ | |
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"); | |
191 | } | |
192 | } | |
193 | ||
194 | /* init 2d engine */ | |
195 | if(!share->accel_off){ | |
196 | hw_sm750_initAccel(share); | |
197 | // share->accel.de_wait = hw_sm750_deWait; | |
198 | } | |
199 | ||
200 | return 0; | |
201 | } | |
202 | ||
203 | ||
204 | resource_size_t hw_sm750_getVMSize(struct lynx_share * share) | |
205 | { | |
206 | resource_size_t ret; | |
207 | ||
208 | ret = ddk750_getVMSize(); | |
209 | return ret; | |
210 | } | |
211 | ||
212 | ||
213 | ||
d2a60377 | 214 | int hw_sm750_output_checkMode(struct lynxfb_output* output, struct fb_var_screeninfo* var) |
81dee67e SM |
215 | { |
216 | ||
217 | return 0; | |
218 | } | |
219 | ||
220 | ||
221 | int hw_sm750_output_setMode(struct lynxfb_output* output, | |
d2a60377 | 222 | struct fb_var_screeninfo* var, struct fb_fix_screeninfo* fix) |
81dee67e SM |
223 | { |
224 | int ret; | |
225 | disp_output_t dispSet; | |
226 | int channel; | |
227 | ||
228 | ret = 0; | |
229 | dispSet = 0; | |
230 | channel = *output->channel; | |
231 | ||
232 | ||
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; | |
240 | ||
241 | }else{ | |
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; | |
247 | ||
248 | } | |
249 | ddk750_setLogicalDispOut(dispSet); | |
250 | }else{ | |
251 | /* just open DISPLAY_CONTROL_750LE register bit 3:0*/ | |
252 | u32 reg; | |
253 | reg = PEEK32(DISPLAY_CONTROL_750LE); | |
254 | reg |= 0xf; | |
d2a60377 | 255 | POKE32(DISPLAY_CONTROL_750LE, reg); |
81dee67e SM |
256 | } |
257 | ||
258 | pr_info("ddk setlogicdispout done \n"); | |
259 | return ret; | |
260 | } | |
261 | ||
262 | void hw_sm750_output_clear(struct lynxfb_output* output) | |
263 | { | |
264 | ||
265 | return; | |
266 | } | |
267 | ||
d2a60377 | 268 | int hw_sm750_crtc_checkMode(struct lynxfb_crtc* crtc, struct fb_var_screeninfo* var) |
81dee67e SM |
269 | { |
270 | struct lynx_share * share; | |
271 | ||
272 | ||
d2a60377 | 273 | share = container_of(crtc, struct lynxfb_par,crtc)->share; |
81dee67e SM |
274 | |
275 | switch (var->bits_per_pixel){ | |
276 | case 8: | |
277 | case 16: | |
278 | break; | |
279 | case 32: | |
62fa8e10 | 280 | if (share->revid == SM750LE_REVISION_ID) { |
81dee67e SM |
281 | pr_debug("750le do not support 32bpp\n"); |
282 | return -EINVAL; | |
283 | } | |
284 | break; | |
285 | default: | |
286 | return -EINVAL; | |
287 | ||
288 | } | |
289 | ||
290 | return 0; | |
291 | } | |
292 | ||
293 | ||
294 | /* | |
295 | set the controller's mode for @crtc charged with @var and @fix parameters | |
296 | */ | |
297 | int hw_sm750_crtc_setMode(struct lynxfb_crtc* crtc, | |
298 | struct fb_var_screeninfo* var, | |
299 | struct fb_fix_screeninfo* fix) | |
300 | { | |
301 | int ret,fmt; | |
302 | u32 reg; | |
303 | mode_parameter_t modparm; | |
304 | clock_type_t clock; | |
305 | struct lynx_share * share; | |
306 | struct lynxfb_par * par; | |
307 | ||
308 | ||
309 | ret = 0; | |
d2a60377 | 310 | par = container_of(crtc, struct lynxfb_par, crtc); |
81dee67e SM |
311 | share = par->share; |
312 | #if 1 | |
313 | if(!share->accel_off){ | |
314 | /* set 2d engine pixel format according to mode bpp */ | |
315 | switch(var->bits_per_pixel){ | |
316 | case 8: | |
317 | fmt = 0; | |
318 | break; | |
319 | case 16: | |
320 | fmt = 1; | |
321 | break; | |
322 | case 32: | |
323 | default: | |
324 | fmt = 2; | |
325 | break; | |
326 | } | |
d2a60377 | 327 | hw_set2dformat(&share->accel, fmt); |
81dee67e SM |
328 | } |
329 | #endif | |
330 | ||
331 | /* set timing */ | |
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; | |
345 | ||
346 | /* choose pll */ | |
347 | if(crtc->channel != sm750_secondary) | |
348 | clock = PRIMARY_PLL; | |
349 | else | |
350 | clock = SECONDARY_PLL; | |
351 | ||
d2a60377 SA |
352 | pr_debug("Request pixel clock = %lu\n", modparm.pixel_clock); |
353 | ret = ddk750_setModeTiming(&modparm, clock); | |
81dee67e SM |
354 | if(ret){ |
355 | pr_err("Set mode timing failed\n"); | |
356 | goto exit; | |
357 | } | |
358 | ||
359 | if(crtc->channel != sm750_secondary){ | |
360 | /* set pitch, offset ,width,start address ,etc... */ | |
361 | POKE32(PANEL_FB_ADDRESS, | |
d2a60377 SA |
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)); | |
81dee67e SM |
365 | |
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); | |
369 | ||
370 | POKE32(PANEL_FB_WIDTH, | |
d2a60377 SA |
371 | FIELD_VALUE(0, PANEL_FB_WIDTH, WIDTH, reg)| |
372 | FIELD_VALUE(0, PANEL_FB_WIDTH, OFFSET, fix->line_length)); | |
81dee67e SM |
373 | |
374 | POKE32(PANEL_WINDOW_WIDTH, | |
d2a60377 SA |
375 | FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH, var->xres -1)| |
376 | FIELD_VALUE(0, PANEL_WINDOW_WIDTH, X, var->xoffset)); | |
81dee67e SM |
377 | |
378 | POKE32(PANEL_WINDOW_HEIGHT, | |
d2a60377 SA |
379 | FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, HEIGHT, var->yres_virtual - 1)| |
380 | FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, Y, var->yoffset)); | |
81dee67e | 381 | |
d2a60377 | 382 | POKE32(PANEL_PLANE_TL, 0); |
81dee67e SM |
383 | |
384 | POKE32(PANEL_PLANE_BR, | |
d2a60377 SA |
385 | FIELD_VALUE(0, PANEL_PLANE_BR, BOTTOM, var->yres - 1)| |
386 | FIELD_VALUE(0, PANEL_PLANE_BR,RIGHT, var->xres - 1)); | |
81dee67e SM |
387 | |
388 | /* set pixel format */ | |
389 | reg = PEEK32(PANEL_DISPLAY_CTRL); | |
390 | POKE32(PANEL_DISPLAY_CTRL, | |
391 | FIELD_VALUE(reg, | |
d2a60377 | 392 | PANEL_DISPLAY_CTRL, FORMAT, |
81dee67e SM |
393 | (var->bits_per_pixel >> 4) |
394 | )); | |
395 | }else{ | |
396 | /* not implemented now */ | |
d2a60377 | 397 | POKE32(CRT_FB_ADDRESS, crtc->oScreen); |
81dee67e SM |
398 | reg = var->xres * (var->bits_per_pixel >> 3); |
399 | /* crtc->channel is not equal to par->index on numeric,be aware of that */ | |
d2a60377 | 400 | reg = PADDING(crtc->line_pad, reg); |
81dee67e SM |
401 | |
402 | POKE32(CRT_FB_WIDTH, | |
d2a60377 SA |
403 | FIELD_VALUE(0, CRT_FB_WIDTH, WIDTH, reg)| |
404 | FIELD_VALUE(0, CRT_FB_WIDTH, OFFSET, fix->line_length)); | |
81dee67e SM |
405 | |
406 | /* SET PIXEL FORMAT */ | |
407 | reg = PEEK32(CRT_DISPLAY_CTRL); | |
d2a60377 SA |
408 | reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, FORMAT, var->bits_per_pixel >> 4); |
409 | POKE32(CRT_DISPLAY_CTRL, reg); | |
81dee67e SM |
410 | |
411 | } | |
412 | ||
413 | ||
414 | exit: | |
415 | return ret; | |
416 | } | |
417 | ||
418 | void hw_sm750_crtc_clear(struct lynxfb_crtc* crtc) | |
419 | { | |
420 | ||
421 | return; | |
422 | } | |
423 | ||
d2a60377 SA |
424 | int hw_sm750_setColReg(struct lynxfb_crtc* crtc, ushort index, |
425 | ushort red, ushort green, ushort blue) | |
81dee67e SM |
426 | { |
427 | static unsigned int add[]={PANEL_PALETTE_RAM,CRT_PALETTE_RAM}; | |
d2a60377 | 428 | POKE32(add[crtc->channel] + index*4, (red<<16)|(green<<8)|blue); |
81dee67e SM |
429 | return 0; |
430 | } | |
431 | ||
d2a60377 | 432 | int hw_sm750le_setBLANK(struct lynxfb_output * output, int blank){ |
81dee67e SM |
433 | int dpms,crtdb; |
434 | ||
435 | switch(blank) | |
436 | { | |
437 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | |
438 | case FB_BLANK_UNBLANK: | |
439 | #else | |
440 | case VESA_NO_BLANKING: | |
441 | #endif | |
442 | dpms = CRT_DISPLAY_CTRL_DPMS_0; | |
443 | crtdb = CRT_DISPLAY_CTRL_BLANK_OFF; | |
444 | break; | |
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; | |
449 | break; | |
450 | #endif | |
451 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | |
452 | case FB_BLANK_VSYNC_SUSPEND: | |
453 | #else | |
454 | case VESA_VSYNC_SUSPEND: | |
455 | #endif | |
456 | dpms = CRT_DISPLAY_CTRL_DPMS_2; | |
457 | crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | |
458 | break; | |
459 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | |
460 | case FB_BLANK_HSYNC_SUSPEND: | |
461 | #else | |
462 | case VESA_HSYNC_SUSPEND: | |
463 | #endif | |
464 | dpms = CRT_DISPLAY_CTRL_DPMS_1; | |
465 | crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | |
466 | break; | |
467 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | |
468 | case FB_BLANK_POWERDOWN: | |
469 | #else | |
470 | case VESA_POWERDOWN: | |
471 | #endif | |
472 | dpms = CRT_DISPLAY_CTRL_DPMS_3; | |
473 | crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | |
474 | break; | |
e74ac550 GKH |
475 | default: |
476 | return -EINVAL; | |
81dee67e SM |
477 | } |
478 | ||
479 | if(output->paths & sm750_crt){ | |
d2a60377 SA |
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)); | |
81dee67e SM |
482 | } |
483 | return 0; | |
484 | } | |
485 | ||
486 | int hw_sm750_setBLANK(struct lynxfb_output* output,int blank) | |
487 | { | |
d2a60377 | 488 | unsigned int dpms, pps, crtdb; |
81dee67e SM |
489 | |
490 | dpms = pps = crtdb = 0; | |
491 | ||
492 | switch (blank) | |
493 | { | |
494 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | |
495 | case FB_BLANK_UNBLANK: | |
496 | #else | |
497 | case VESA_NO_BLANKING: | |
498 | #endif | |
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; | |
503 | break; | |
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; | |
510 | break; | |
511 | #endif | |
512 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | |
513 | case FB_BLANK_VSYNC_SUSPEND: | |
514 | #else | |
515 | case VESA_VSYNC_SUSPEND: | |
516 | #endif | |
517 | dpms = SYSTEM_CTRL_DPMS_VNHP; | |
518 | pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; | |
519 | crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | |
520 | break; | |
521 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | |
522 | case FB_BLANK_HSYNC_SUSPEND: | |
523 | #else | |
524 | case VESA_HSYNC_SUSPEND: | |
525 | #endif | |
526 | dpms = SYSTEM_CTRL_DPMS_VPHN; | |
527 | pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; | |
528 | crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | |
529 | break; | |
530 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | |
531 | case FB_BLANK_POWERDOWN: | |
532 | #else | |
533 | case VESA_POWERDOWN: | |
534 | #endif | |
535 | dpms = SYSTEM_CTRL_DPMS_VNHN; | |
536 | pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; | |
537 | crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | |
538 | break; | |
539 | } | |
540 | ||
541 | if(output->paths & sm750_crt){ | |
542 | ||
d2a60377 SA |
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)); | |
81dee67e SM |
545 | } |
546 | ||
547 | if(output->paths & sm750_panel){ | |
d2a60377 | 548 | POKE32(PANEL_DISPLAY_CTRL, FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, DATA, pps)); |
81dee67e SM |
549 | } |
550 | ||
551 | return 0; | |
552 | } | |
553 | ||
554 | ||
555 | void hw_sm750_initAccel(struct lynx_share * share) | |
556 | { | |
557 | u32 reg; | |
558 | enable2DEngine(1); | |
559 | ||
560 | if(getChipType() == SM750LE){ | |
561 | reg = PEEK32(DE_STATE1); | |
d2a60377 | 562 | reg = FIELD_SET(reg, DE_STATE1, DE_ABORT,ON); |
81dee67e SM |
563 | POKE32(DE_STATE1,reg); |
564 | ||
565 | reg = PEEK32(DE_STATE1); | |
d2a60377 SA |
566 | reg = FIELD_SET(reg, DE_STATE1, DE_ABORT,OFF); |
567 | POKE32(DE_STATE1, reg); | |
81dee67e SM |
568 | |
569 | }else{ | |
570 | /* engine reset */ | |
571 | reg = PEEK32(SYSTEM_CTRL); | |
d2a60377 SA |
572 | reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT,ON); |
573 | POKE32(SYSTEM_CTRL, reg); | |
81dee67e SM |
574 | |
575 | reg = PEEK32(SYSTEM_CTRL); | |
d2a60377 SA |
576 | reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT,OFF); |
577 | POKE32(SYSTEM_CTRL, reg); | |
81dee67e SM |
578 | } |
579 | ||
580 | /* call 2d init */ | |
581 | share->accel.de_init(&share->accel); | |
582 | } | |
583 | ||
6fa7db83 | 584 | int hw_sm750le_deWait(void) |
81dee67e SM |
585 | { |
586 | int i=0x10000000; | |
587 | while(i--){ | |
588 | unsigned int dwVal = PEEK32(DE_STATE2); | |
d2a60377 SA |
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)) | |
81dee67e SM |
592 | { |
593 | return 0; | |
594 | } | |
595 | } | |
596 | /* timeout error */ | |
597 | return -1; | |
598 | } | |
599 | ||
600 | ||
6fa7db83 | 601 | int hw_sm750_deWait(void) |
81dee67e SM |
602 | { |
603 | int i=0x10000000; | |
604 | while(i--){ | |
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)) | |
609 | { | |
610 | return 0; | |
611 | } | |
612 | } | |
613 | /* timeout error */ | |
614 | return -1; | |
615 | } | |
616 | ||
617 | int hw_sm750_pan_display(struct lynxfb_crtc *crtc, | |
618 | const struct fb_var_screeninfo *var, | |
619 | const struct fb_info *info) | |
620 | { | |
621 | uint32_t total; | |
622 | //check params | |
623 | if ((var->xoffset + var->xres > var->xres_virtual) || | |
624 | (var->yoffset + var->yres > var->yres_virtual)) { | |
625 | return -EINVAL; | |
626 | } | |
627 | ||
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)); | |
635 | } else { | |
636 | POKE32(CRT_FB_ADDRESS, | |
637 | FIELD_VALUE(PEEK32(CRT_FB_ADDRESS), | |
638 | CRT_FB_ADDRESS, ADDRESS, total)); | |
639 | } | |
640 | return 0; | |
641 | } | |
642 |