Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-block.git] / drivers / staging / sm750fb / sm750_hw.c
CommitLineData
67088d49
MR
1#include <linux/module.h>
2#include <linux/kernel.h>
3#include <linux/errno.h>
4#include <linux/string.h>
5#include <linux/mm.h>
6#include <linux/slab.h>
7#include <linux/delay.h>
8#include <linux/fb.h>
9#include <linux/ioport.h>
10#include <linux/init.h>
11#include <linux/pci.h>
12#include <linux/vmalloc.h>
13#include <linux/pagemap.h>
81dee67e
SM
14#include <linux/console.h>
15#ifdef CONFIG_MTRR
16#include <asm/mtrr.h>
17#endif
67088d49
MR
18#include <linux/platform_device.h>
19#include <linux/screen_info.h>
4cf26d85 20#include <linux/sizes.h>
81dee67e
SM
21
22#include "sm750.h"
81dee67e
SM
23#include "ddk750.h"
24#include "sm750_accel.h"
25
efe9bc08
EL
26void __iomem *mmio750;
27
700591a9 28int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
81dee67e
SM
29{
30 int ret;
29d87336 31
81dee67e
SM
32 ret = 0;
33
e359b6a8
MR
34 sm750_dev->vidreg_start = pci_resource_start(pdev, 1);
35 sm750_dev->vidreg_size = SZ_2M;
81dee67e 36
e359b6a8 37 pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start);
81dee67e 38
f5016082
ES
39 /*
40 * reserve the vidreg space of smi adaptor
878336c3 41 * if you do this, you need to add release region code
81dee67e
SM
42 * in lynxfb_remove, or memory will not be mapped again
43 * successfully
878336c3 44 */
9a52ae2d
AS
45 ret = pci_request_region(pdev, 1, "sm750fb");
46 if (ret) {
81dee67e
SM
47 pr_err("Can not request PCI regions.\n");
48 goto exit;
49 }
50
878336c3 51 /* now map mmio and vidmem */
e359b6a8
MR
52 sm750_dev->pvReg = ioremap_nocache(sm750_dev->vidreg_start,
53 sm750_dev->vidreg_size);
54 if (!sm750_dev->pvReg) {
81dee67e
SM
55 pr_err("mmio failed\n");
56 ret = -EFAULT;
57 goto exit;
5e83e283 58 } else {
e359b6a8 59 pr_info("mmio virtual addr = %p\n", sm750_dev->pvReg);
81dee67e
SM
60 }
61
e359b6a8
MR
62 sm750_dev->accel.dprBase = sm750_dev->pvReg + DE_BASE_ADDR_TYPE1;
63 sm750_dev->accel.dpPortBase = sm750_dev->pvReg + DE_PORT_ADDR_TYPE1;
81dee67e 64
efe9bc08
EL
65 mmio750 = sm750_dev->pvReg;
66 sm750_set_chip_type(sm750_dev->devid, sm750_dev->revid);
81dee67e 67
e359b6a8 68 sm750_dev->vidmem_start = pci_resource_start(pdev, 0);
f5016082
ES
69 /*
70 * don't use pdev_resource[x].end - resource[x].start to
878336c3
SW
71 * calculate the resource size, it's only the maximum available
72 * size but not the actual size, using
3fcb465f 73 * @ddk750_get_vm_size function can be safe.
878336c3 74 */
3fcb465f 75 sm750_dev->vidmem_size = ddk750_get_vm_size();
e936351a 76 pr_info("video memory phyAddr = %lx, size = %u bytes\n",
e359b6a8 77 sm750_dev->vidmem_start, sm750_dev->vidmem_size);
81dee67e
SM
78
79 /* reserve the vidmem space of smi adaptor */
e359b6a8
MR
80 sm750_dev->pvMem = ioremap_wc(sm750_dev->vidmem_start,
81 sm750_dev->vidmem_size);
82 if (!sm750_dev->pvMem) {
81dee67e
SM
83 pr_err("Map video memory failed\n");
84 ret = -EFAULT;
85 goto exit;
5e83e283 86 } else {
e359b6a8 87 pr_info("video memory vaddr = %p\n", sm750_dev->pvMem);
81dee67e
SM
88 }
89exit:
90 return ret;
91}
92
700591a9 93int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
81dee67e 94{
eb0f4271 95 struct init_status *parm;
29d87336 96
1757d106 97 parm = &sm750_dev->initParm;
6d1b3d64 98 if (parm->chip_clk == 0)
06a4f429 99 parm->chip_clk = (sm750_get_chip_type() == SM750LE) ?
81dee67e
SM
100 DEFAULT_SM750LE_CHIP_CLOCK :
101 DEFAULT_SM750_CHIP_CLOCK;
102
6d1b3d64 103 if (parm->mem_clk == 0)
81dee67e 104 parm->mem_clk = parm->chip_clk;
6d1b3d64 105 if (parm->master_clk == 0)
1f24c865 106 parm->master_clk = parm->chip_clk / 3;
81dee67e 107
3fcb465f 108 ddk750_init_hw((struct initchip_param *)&sm750_dev->initParm);
878336c3 109 /* for sm718, open pci burst */
e359b6a8 110 if (sm750_dev->devid == 0x718) {
c075b6f2
MS
111 poke32(SYSTEM_CTRL,
112 peek32(SYSTEM_CTRL) | SYSTEM_CTRL_PCI_BURST);
81dee67e
SM
113 }
114
06a4f429 115 if (sm750_get_chip_type() != SM750LE) {
a8856ff8 116 unsigned int val;
878336c3 117 /* does user need CRT? */
1757d106 118 if (sm750_dev->nocrt) {
c075b6f2
MS
119 poke32(MISC_CTRL,
120 peek32(MISC_CTRL) | MISC_CTRL_DAC_POWER_OFF);
81dee67e 121 /* shut off dpms */
c075b6f2 122 val = peek32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
a8856ff8 123 val |= SYSTEM_CTRL_DPMS_VPHN;
c075b6f2 124 poke32(SYSTEM_CTRL, val);
5e83e283 125 } else {
c075b6f2
MS
126 poke32(MISC_CTRL,
127 peek32(MISC_CTRL) & ~MISC_CTRL_DAC_POWER_OFF);
81dee67e 128 /* turn on dpms */
c075b6f2 129 val = peek32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
a8856ff8 130 val |= SYSTEM_CTRL_DPMS_VPHP;
c075b6f2 131 poke32(SYSTEM_CTRL, val);
81dee67e
SM
132 }
133
c075b6f2 134 val = peek32(PANEL_DISPLAY_CTRL) &
f5d7f190
MR
135 ~(PANEL_DISPLAY_CTRL_DUAL_DISPLAY |
136 PANEL_DISPLAY_CTRL_DOUBLE_PIXEL);
1757d106 137 switch (sm750_dev->pnltype) {
990e5666 138 case sm750_24TFT:
f5d7f190
MR
139 break;
140 case sm750_doubleTFT:
141 val |= PANEL_DISPLAY_CTRL_DOUBLE_PIXEL;
142 break;
990e5666 143 case sm750_dualTFT:
f5d7f190
MR
144 val |= PANEL_DISPLAY_CTRL_DUAL_DISPLAY;
145 break;
81dee67e 146 }
c075b6f2 147 poke32(PANEL_DISPLAY_CTRL, val);
5e83e283 148 } else {
f5016082
ES
149 /*
150 * for 750LE, no DVI chip initialization
878336c3
SW
151 * makes Monitor no signal
152 *
153 * Set up GPIO for software I2C to program DVI chip in the
154 * Xilinx SP605 board, in order to have video signal.
81dee67e 155 */
da6985f5 156 sm750_sw_i2c_init(0, 1);
81dee67e 157
f5016082
ES
158 /*
159 * Customer may NOT use CH7301 DVI chip, which has to be
878336c3
SW
160 * initialized differently.
161 */
da6985f5 162 if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) {
f5016082
ES
163 /*
164 * The following register values for CH7301 are from
165 * Chrontel app note and our experiment.
166 */
81dee67e 167 pr_info("yes,CH7301 DVI chip found\n");
da6985f5
JR
168 sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16);
169 sm750_sw_i2c_write_reg(0xec, 0x21, 0x9);
170 sm750_sw_i2c_write_reg(0xec, 0x49, 0xC0);
81dee67e 171 pr_info("okay,CH7301 DVI chip setup done\n");
da6985f5 172 }
81dee67e
SM
173 }
174
175 /* init 2d engine */
e359b6a8 176 if (!sm750_dev->accel_off)
700591a9 177 hw_sm750_initAccel(sm750_dev);
81dee67e
SM
178
179 return 0;
180}
181
e188ea32 182int hw_sm750_output_setMode(struct lynxfb_output *output,
bfbeb71c
SW
183 struct fb_var_screeninfo *var,
184 struct fb_fix_screeninfo *fix)
81dee67e
SM
185{
186 int ret;
187 disp_output_t dispSet;
188 int channel;
29d87336 189
81dee67e
SM
190 ret = 0;
191 dispSet = 0;
192 channel = *output->channel;
193
06a4f429 194 if (sm750_get_chip_type() != SM750LE) {
6d1b3d64 195 if (channel == sm750_primary) {
81dee67e 196 pr_info("primary channel\n");
6d1b3d64 197 if (output->paths & sm750_panel)
81dee67e 198 dispSet |= do_LCD1_PRI;
6d1b3d64 199 if (output->paths & sm750_crt)
81dee67e
SM
200 dispSet |= do_CRT_PRI;
201
5e83e283 202 } else {
81dee67e 203 pr_info("secondary channel\n");
6d1b3d64 204 if (output->paths & sm750_panel)
81dee67e 205 dispSet |= do_LCD1_SEC;
6d1b3d64 206 if (output->paths & sm750_crt)
81dee67e 207 dispSet |= do_CRT_SEC;
81dee67e
SM
208 }
209 ddk750_setLogicalDispOut(dispSet);
5e83e283 210 } else {
878336c3 211 /* just open DISPLAY_CONTROL_750LE register bit 3:0 */
81dee67e 212 u32 reg;
40403c1b 213
c075b6f2 214 reg = peek32(DISPLAY_CONTROL_750LE);
81dee67e 215 reg |= 0xf;
c075b6f2 216 poke32(DISPLAY_CONTROL_750LE, reg);
81dee67e
SM
217 }
218
a1fe154f 219 pr_info("ddk setlogicdispout done\n");
81dee67e
SM
220 return ret;
221}
222
ec489447
SW
223int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc,
224 struct fb_var_screeninfo *var)
81dee67e 225{
e359b6a8 226 struct sm750_dev *sm750_dev;
f11fa2a9 227 struct lynxfb_par *par = container_of(crtc, struct lynxfb_par, crtc);
29d87336 228
e359b6a8 229 sm750_dev = par->dev;
81dee67e 230
e0ded448 231 switch (var->bits_per_pixel) {
990e5666
AS
232 case 8:
233 case 16:
234 break;
235 case 32:
e359b6a8 236 if (sm750_dev->revid == SM750LE_REVISION_ID) {
990e5666 237 pr_debug("750le do not support 32bpp\n");
81dee67e 238 return -EINVAL;
990e5666
AS
239 }
240 break;
241 default:
242 return -EINVAL;
81dee67e
SM
243 }
244
245 return 0;
246}
247
878336c3 248/* set the controller's mode for @crtc charged with @var and @fix parameters */
e188ea32 249int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
bfbeb71c
SW
250 struct fb_var_screeninfo *var,
251 struct fb_fix_screeninfo *fix)
81dee67e 252{
bdec7773 253 int ret, fmt;
81dee67e 254 u32 reg;
bf760231 255 struct mode_parameter modparm;
81dee67e 256 clock_type_t clock;
e359b6a8 257 struct sm750_dev *sm750_dev;
eb0f4271 258 struct lynxfb_par *par;
81dee67e 259
81dee67e 260 ret = 0;
d2a60377 261 par = container_of(crtc, struct lynxfb_par, crtc);
e359b6a8 262 sm750_dev = par->dev;
cfac7d6a 263
e359b6a8 264 if (!sm750_dev->accel_off) {
81dee67e 265 /* set 2d engine pixel format according to mode bpp */
6d1b3d64 266 switch (var->bits_per_pixel) {
990e5666
AS
267 case 8:
268 fmt = 0;
269 break;
270 case 16:
271 fmt = 1;
272 break;
273 case 32:
274 default:
275 fmt = 2;
276 break;
81dee67e 277 }
52d0744d 278 sm750_hw_set2dformat(&sm750_dev->accel, fmt);
81dee67e 279 }
81dee67e
SM
280
281 /* set timing */
81dee67e 282 modparm.pixel_clock = ps_to_hz(var->pixclock);
1f24c865
SW
283 modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT)
284 ? POS : NEG;
285 modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT)
286 ? POS : NEG;
287 modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT)
288 ? POS : NEG;
81dee67e
SM
289 modparm.horizontal_display_end = var->xres;
290 modparm.horizontal_sync_width = var->hsync_len;
291 modparm.horizontal_sync_start = var->xres + var->right_margin;
ec489447
SW
292 modparm.horizontal_total = var->xres + var->left_margin +
293 var->right_margin + var->hsync_len;
81dee67e
SM
294 modparm.vertical_display_end = var->yres;
295 modparm.vertical_sync_height = var->vsync_len;
296 modparm.vertical_sync_start = var->yres + var->lower_margin;
ec489447
SW
297 modparm.vertical_total = var->yres + var->upper_margin +
298 var->lower_margin + var->vsync_len;
81dee67e
SM
299
300 /* choose pll */
6d1b3d64 301 if (crtc->channel != sm750_secondary)
81dee67e
SM
302 clock = PRIMARY_PLL;
303 else
304 clock = SECONDARY_PLL;
305
d2a60377
SA
306 pr_debug("Request pixel clock = %lu\n", modparm.pixel_clock);
307 ret = ddk750_setModeTiming(&modparm, clock);
6d1b3d64 308 if (ret) {
81dee67e
SM
309 pr_err("Set mode timing failed\n");
310 goto exit;
311 }
312
6d1b3d64 313 if (crtc->channel != sm750_secondary) {
878336c3 314 /* set pitch, offset, width, start address, etc... */
c075b6f2 315 poke32(PANEL_FB_ADDRESS,
4463690a 316 crtc->oScreen & PANEL_FB_ADDRESS_ADDRESS_MASK);
81dee67e
SM
317
318 reg = var->xres * (var->bits_per_pixel >> 3);
f5016082
ES
319 /*
320 * crtc->channel is not equal to par->index on numeric,
878336c3
SW
321 * be aware of that
322 */
e3a3f9f5 323 reg = ALIGN(reg, crtc->line_pad);
26a3cc90
MR
324 reg = (reg << PANEL_FB_WIDTH_WIDTH_SHIFT) &
325 PANEL_FB_WIDTH_WIDTH_MASK;
326 reg |= (fix->line_length & PANEL_FB_WIDTH_OFFSET_MASK);
c075b6f2 327 poke32(PANEL_FB_WIDTH, reg);
81dee67e 328
4c221d82
MR
329 reg = ((var->xres - 1) << PANEL_WINDOW_WIDTH_WIDTH_SHIFT) &
330 PANEL_WINDOW_WIDTH_WIDTH_MASK;
331 reg |= (var->xoffset & PANEL_WINDOW_WIDTH_X_MASK);
c075b6f2 332 poke32(PANEL_WINDOW_WIDTH, reg);
81dee67e 333
837b6555
RS
334 reg = (var->yres_virtual - 1) <<
335 PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT;
f91969f7
MR
336 reg &= PANEL_WINDOW_HEIGHT_HEIGHT_MASK;
337 reg |= (var->yoffset & PANEL_WINDOW_HEIGHT_Y_MASK);
c075b6f2 338 poke32(PANEL_WINDOW_HEIGHT, reg);
81dee67e 339
c075b6f2 340 poke32(PANEL_PLANE_TL, 0);
81dee67e 341
27b047bb
MR
342 reg = ((var->yres - 1) << PANEL_PLANE_BR_BOTTOM_SHIFT) &
343 PANEL_PLANE_BR_BOTTOM_MASK;
344 reg |= ((var->xres - 1) & PANEL_PLANE_BR_RIGHT_MASK);
c075b6f2 345 poke32(PANEL_PLANE_BR, reg);
81dee67e
SM
346
347 /* set pixel format */
c075b6f2
MS
348 reg = peek32(PANEL_DISPLAY_CTRL);
349 poke32(PANEL_DISPLAY_CTRL, reg | (var->bits_per_pixel >> 4));
5e83e283 350 } else {
81dee67e 351 /* not implemented now */
c075b6f2 352 poke32(CRT_FB_ADDRESS, crtc->oScreen);
81dee67e 353 reg = var->xres * (var->bits_per_pixel >> 3);
f5016082
ES
354 /*
355 * crtc->channel is not equal to par->index on numeric,
878336c3
SW
356 * be aware of that
357 */
d6a4cba7
MR
358 reg = ALIGN(reg, crtc->line_pad) << CRT_FB_WIDTH_WIDTH_SHIFT;
359 reg &= CRT_FB_WIDTH_WIDTH_MASK;
360 reg |= (fix->line_length & CRT_FB_WIDTH_OFFSET_MASK);
c075b6f2 361 poke32(CRT_FB_WIDTH, reg);
81dee67e
SM
362
363 /* SET PIXEL FORMAT */
c075b6f2 364 reg = peek32(CRT_DISPLAY_CTRL);
cdce1f18
MR
365 reg |= ((var->bits_per_pixel >> 4) &
366 CRT_DISPLAY_CTRL_FORMAT_MASK);
c075b6f2 367 poke32(CRT_DISPLAY_CTRL, reg);
81dee67e
SM
368 }
369
81dee67e
SM
370exit:
371 return ret;
372}
373
e188ea32 374int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
bfbeb71c 375 ushort red, ushort green, ushort blue)
81dee67e 376{
d5fca403 377 static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
40403c1b 378
c075b6f2 379 poke32(add[crtc->channel] + index * 4,
1f24c865 380 (red << 16) | (green << 8) | blue);
81dee67e
SM
381 return 0;
382}
383
14a974c5
AS
384int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank)
385{
bdec7773 386 int dpms, crtdb;
29d87336 387
4bcdffee 388 switch (blank) {
990e5666 389 case FB_BLANK_UNBLANK:
990e5666 390 dpms = CRT_DISPLAY_CTRL_DPMS_0;
d8264edf 391 crtdb = 0;
990e5666 392 break;
990e5666
AS
393 case FB_BLANK_NORMAL:
394 dpms = CRT_DISPLAY_CTRL_DPMS_0;
d8264edf 395 crtdb = CRT_DISPLAY_CTRL_BLANK;
990e5666 396 break;
990e5666 397 case FB_BLANK_VSYNC_SUSPEND:
990e5666 398 dpms = CRT_DISPLAY_CTRL_DPMS_2;
d8264edf 399 crtdb = CRT_DISPLAY_CTRL_BLANK;
990e5666 400 break;
990e5666 401 case FB_BLANK_HSYNC_SUSPEND:
990e5666 402 dpms = CRT_DISPLAY_CTRL_DPMS_1;
d8264edf 403 crtdb = CRT_DISPLAY_CTRL_BLANK;
990e5666 404 break;
990e5666 405 case FB_BLANK_POWERDOWN:
990e5666 406 dpms = CRT_DISPLAY_CTRL_DPMS_3;
d8264edf 407 crtdb = CRT_DISPLAY_CTRL_BLANK;
990e5666
AS
408 break;
409 default:
410 return -EINVAL;
81dee67e
SM
411 }
412
6d1b3d64 413 if (output->paths & sm750_crt) {
d8264edf
MR
414 unsigned int val;
415
c075b6f2
MS
416 val = peek32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_DPMS_MASK;
417 poke32(CRT_DISPLAY_CTRL, val | dpms);
d8264edf 418
c075b6f2
MS
419 val = peek32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_BLANK;
420 poke32(CRT_DISPLAY_CTRL, val | crtdb);
81dee67e
SM
421 }
422 return 0;
423}
424
e188ea32 425int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
81dee67e 426{
d2a60377 427 unsigned int dpms, pps, crtdb;
29d87336 428
ec489447
SW
429 dpms = 0;
430 pps = 0;
431 crtdb = 0;
81dee67e 432
4bcdffee 433 switch (blank) {
990e5666 434 case FB_BLANK_UNBLANK:
5b621779 435 pr_debug("flag = FB_BLANK_UNBLANK\n");
990e5666 436 dpms = SYSTEM_CTRL_DPMS_VPHP;
6fba39cf 437 pps = PANEL_DISPLAY_CTRL_DATA;
990e5666 438 break;
990e5666 439 case FB_BLANK_NORMAL:
5b621779 440 pr_debug("flag = FB_BLANK_NORMAL\n");
990e5666 441 dpms = SYSTEM_CTRL_DPMS_VPHP;
d8264edf 442 crtdb = CRT_DISPLAY_CTRL_BLANK;
990e5666 443 break;
990e5666 444 case FB_BLANK_VSYNC_SUSPEND:
990e5666 445 dpms = SYSTEM_CTRL_DPMS_VNHP;
d8264edf 446 crtdb = CRT_DISPLAY_CTRL_BLANK;
990e5666 447 break;
990e5666 448 case FB_BLANK_HSYNC_SUSPEND:
990e5666 449 dpms = SYSTEM_CTRL_DPMS_VPHN;
d8264edf 450 crtdb = CRT_DISPLAY_CTRL_BLANK;
990e5666 451 break;
990e5666 452 case FB_BLANK_POWERDOWN:
990e5666 453 dpms = SYSTEM_CTRL_DPMS_VNHN;
d8264edf 454 crtdb = CRT_DISPLAY_CTRL_BLANK;
990e5666 455 break;
81dee67e
SM
456 }
457
6d1b3d64 458 if (output->paths & sm750_crt) {
c075b6f2 459 unsigned int val = peek32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
81dee67e 460
c075b6f2 461 poke32(SYSTEM_CTRL, val | dpms);
d8264edf 462
c075b6f2
MS
463 val = peek32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_BLANK;
464 poke32(CRT_DISPLAY_CTRL, val | crtdb);
81dee67e
SM
465 }
466
6fba39cf 467 if (output->paths & sm750_panel) {
c075b6f2 468 unsigned int val = peek32(PANEL_DISPLAY_CTRL);
6fba39cf
MR
469
470 val &= ~PANEL_DISPLAY_CTRL_DATA;
471 val |= pps;
c075b6f2 472 poke32(PANEL_DISPLAY_CTRL, val);
6fba39cf 473 }
81dee67e
SM
474
475 return 0;
476}
477
700591a9 478void hw_sm750_initAccel(struct sm750_dev *sm750_dev)
81dee67e
SM
479{
480 u32 reg;
40403c1b 481
52d0744d 482 sm750_enable_2d_engine(1);
81dee67e 483
06a4f429 484 if (sm750_get_chip_type() == SM750LE) {
c075b6f2 485 reg = peek32(DE_STATE1);
c808d6ce 486 reg |= DE_STATE1_DE_ABORT;
c075b6f2 487 poke32(DE_STATE1, reg);
81dee67e 488
c075b6f2 489 reg = peek32(DE_STATE1);
c808d6ce 490 reg &= ~DE_STATE1_DE_ABORT;
c075b6f2 491 poke32(DE_STATE1, reg);
81dee67e 492
5e83e283 493 } else {
81dee67e 494 /* engine reset */
c075b6f2 495 reg = peek32(SYSTEM_CTRL);
410c756d 496 reg |= SYSTEM_CTRL_DE_ABORT;
c075b6f2 497 poke32(SYSTEM_CTRL, reg);
81dee67e 498
c075b6f2 499 reg = peek32(SYSTEM_CTRL);
410c756d 500 reg &= ~SYSTEM_CTRL_DE_ABORT;
c075b6f2 501 poke32(SYSTEM_CTRL, reg);
81dee67e
SM
502 }
503
504 /* call 2d init */
e359b6a8 505 sm750_dev->accel.de_init(&sm750_dev->accel);
81dee67e
SM
506}
507
6fa7db83 508int hw_sm750le_deWait(void)
81dee67e 509{
d5fca403 510 int i = 0x10000000;
ae6061db
MR
511 unsigned int mask = DE_STATE2_DE_STATUS_BUSY | DE_STATE2_DE_FIFO_EMPTY |
512 DE_STATE2_DE_MEM_FIFO_EMPTY;
40403c1b 513
6d1b3d64 514 while (i--) {
c075b6f2 515 unsigned int val = peek32(DE_STATE2);
40403c1b 516
ae6061db
MR
517 if ((val & mask) ==
518 (DE_STATE2_DE_FIFO_EMPTY | DE_STATE2_DE_MEM_FIFO_EMPTY))
81dee67e 519 return 0;
81dee67e
SM
520 }
521 /* timeout error */
522 return -1;
523}
524
6fa7db83 525int hw_sm750_deWait(void)
81dee67e 526{
d5fca403 527 int i = 0x10000000;
410c756d
MR
528 unsigned int mask = SYSTEM_CTRL_DE_STATUS_BUSY |
529 SYSTEM_CTRL_DE_FIFO_EMPTY |
530 SYSTEM_CTRL_DE_MEM_FIFO_EMPTY;
40403c1b 531
6d1b3d64 532 while (i--) {
c075b6f2 533 unsigned int val = peek32(SYSTEM_CTRL);
40403c1b 534
410c756d
MR
535 if ((val & mask) ==
536 (SYSTEM_CTRL_DE_FIFO_EMPTY | SYSTEM_CTRL_DE_MEM_FIFO_EMPTY))
81dee67e 537 return 0;
81dee67e
SM
538 }
539 /* timeout error */
540 return -1;
541}
542
543int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
bfbeb71c
SW
544 const struct fb_var_screeninfo *var,
545 const struct fb_info *info)
81dee67e 546{
1fed320a 547 u32 total;
202add2a
AS
548 /* check params */
549 if ((var->xoffset + var->xres > var->xres_virtual) ||
550 (var->yoffset + var->yres > var->yres_virtual)) {
551 return -EINVAL;
552 }
553
554 total = var->yoffset * info->fix.line_length +
555 ((var->xoffset * var->bits_per_pixel) >> 3);
556 total += crtc->oScreen;
557 if (crtc->channel == sm750_primary) {
c075b6f2
MS
558 poke32(PANEL_FB_ADDRESS,
559 peek32(PANEL_FB_ADDRESS) |
4463690a 560 (total & PANEL_FB_ADDRESS_ADDRESS_MASK));
202add2a 561 } else {
c075b6f2
MS
562 poke32(CRT_FB_ADDRESS,
563 peek32(CRT_FB_ADDRESS) |
7ea833df 564 (total & CRT_FB_ADDRESS_ADDRESS_MASK));
202add2a
AS
565 }
566 return 0;
81dee67e 567}