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