]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/staging/sm750fb/sm750_hw.c
Merge tag 'media/v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / sm750fb / sm750_hw.c
CommitLineData
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
e188ea32 27int hw_sm750_map(struct lynx_share *share, struct pci_dev *pdev)
81dee67e
SM
28{
29 int ret;
eb0f4271 30 struct sm750_share *spec_share;
29d87336 31
81dee67e 32
bdec7773 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 * */
9a52ae2d
AS
46 ret = pci_request_region(pdev, 1, "sm750fb");
47 if (ret) {
81dee67e
SM
48 pr_err("Can not request PCI regions.\n");
49 goto exit;
50 }
51
52 /* now map mmio and vidmem*/
d2a60377 53 share->pvReg = ioremap_nocache(share->vidreg_start, share->vidreg_size);
6d1b3d64 54 if (!share->pvReg) {
81dee67e
SM
55 pr_err("mmio failed\n");
56 ret = -EFAULT;
57 goto exit;
5e83e283 58 } else {
d2a60377 59 pr_info("mmio virtual addr = %p\n", share->pvReg);
81dee67e
SM
60 }
61
29d87336 62
81dee67e
SM
63 share->accel.dprBase = share->pvReg + DE_BASE_ADDR_TYPE1;
64 share->accel.dpPortBase = share->pvReg + DE_PORT_ADDR_TYPE1;
65
bdec7773 66 ddk750_set_mmio(share->pvReg, share->devid, share->revid);
81dee67e 67
d2a60377 68 share->vidmem_start = pci_resource_start(pdev, 0);
81dee67e
SM
69 /* don't use pdev_resource[x].end - resource[x].start to
70 * calculate the resource size,its only the maximum available
71 * size but not the actual size,use
72 * @hw_sm750_getVMSize function can be safe.
73 * */
74 share->vidmem_size = hw_sm750_getVMSize(share);
e936351a 75 pr_info("video memory phyAddr = %lx, size = %u bytes\n",
d2a60377 76 share->vidmem_start, share->vidmem_size);
81dee67e
SM
77
78 /* reserve the vidmem space of smi adaptor */
79#if 0
9a52ae2d
AS
80 ret = pci_request_region(pdev, 0, _moduleName_);
81 if (ret) {
81dee67e
SM
82 pr_err("Can not request PCI regions.\n");
83 goto exit;
84 }
85#endif
86
2e043a92 87 share->pvMem = ioremap_wc(share->vidmem_start, share->vidmem_size);
81dee67e 88
6d1b3d64 89 if (!share->pvMem) {
81dee67e
SM
90 pr_err("Map video memory failed\n");
91 ret = -EFAULT;
92 goto exit;
5e83e283 93 } else {
d2a60377 94 pr_info("video memory vaddr = %p\n", share->pvMem);
81dee67e
SM
95 }
96exit:
97 return ret;
98}
99
100
101
eb0f4271 102int hw_sm750_inithw(struct lynx_share *share, struct pci_dev *pdev)
81dee67e 103{
eb0f4271
GD
104 struct sm750_share *spec_share;
105 struct init_status *parm;
29d87336 106
bdec7773 107 spec_share = container_of(share, struct sm750_share, share);
81dee67e 108 parm = &spec_share->state.initParm;
6d1b3d64 109 if (parm->chip_clk == 0)
d5fca403 110 parm->chip_clk = (getChipType() == SM750LE) ?
81dee67e
SM
111 DEFAULT_SM750LE_CHIP_CLOCK :
112 DEFAULT_SM750_CHIP_CLOCK;
113
6d1b3d64 114 if (parm->mem_clk == 0)
81dee67e 115 parm->mem_clk = parm->chip_clk;
6d1b3d64 116 if (parm->master_clk == 0)
81dee67e
SM
117 parm->master_clk = parm->chip_clk/3;
118
119 ddk750_initHw((initchip_param_t *)&spec_share->state.initParm);
120 /* for sm718,open pci burst */
6d1b3d64 121 if (share->devid == 0x718) {
81dee67e 122 POKE32(SYSTEM_CTRL,
d2a60377 123 FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON));
81dee67e
SM
124 }
125
126 /* sm750 use sii164, it can be setup with default value
127 * by on power, so initDVIDisp can be skipped */
128#if 0
129 ddk750_initDVIDisp();
130#endif
131
4bcdffee 132 if (getChipType() != SM750LE) {
81dee67e 133 /* does user need CRT ?*/
6d1b3d64 134 if (spec_share->state.nocrt) {
81dee67e
SM
135 POKE32(MISC_CTRL,
136 FIELD_SET(PEEK32(MISC_CTRL),
137 MISC_CTRL,
d2a60377 138 DAC_POWER, OFF));
81dee67e
SM
139 /* shut off dpms */
140 POKE32(SYSTEM_CTRL,
141 FIELD_SET(PEEK32(SYSTEM_CTRL),
142 SYSTEM_CTRL,
d2a60377 143 DPMS, VNHN));
5e83e283 144 } else {
81dee67e
SM
145 POKE32(MISC_CTRL,
146 FIELD_SET(PEEK32(MISC_CTRL),
147 MISC_CTRL,
d2a60377 148 DAC_POWER, ON));
81dee67e
SM
149 /* turn on dpms */
150 POKE32(SYSTEM_CTRL,
151 FIELD_SET(PEEK32(SYSTEM_CTRL),
152 SYSTEM_CTRL,
d2a60377 153 DPMS, VPHP));
81dee67e
SM
154 }
155
e0ded448 156 switch (spec_share->state.pnltype) {
990e5666
AS
157 case sm750_doubleTFT:
158 case sm750_24TFT:
159 case sm750_dualTFT:
160 POKE32(PANEL_DISPLAY_CTRL,
161 FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL),
162 PANEL_DISPLAY_CTRL,
163 TFT_DISP,
164 spec_share->state.pnltype));
165 break;
81dee67e 166 }
5e83e283 167 } else {
81dee67e
SM
168 /* for 750LE ,no DVI chip initilization makes Monitor no signal */
169 /* Set up GPIO for software I2C to program DVI chip in the
170 Xilinx SP605 board, in order to have video signal.
171 */
202add2a 172 swI2CInit(0, 1);
81dee67e
SM
173
174
202add2a
AS
175 /* Customer may NOT use CH7301 DVI chip, which has to be
176 initialized differently.
177 */
4bcdffee 178 if (swI2CReadReg(0xec, 0x4a) == 0x95) {
202add2a
AS
179 /* The following register values for CH7301 are from
180 Chrontel app note and our experiment.
181 */
81dee67e 182 pr_info("yes,CH7301 DVI chip found\n");
202add2a
AS
183 swI2CWriteReg(0xec, 0x1d, 0x16);
184 swI2CWriteReg(0xec, 0x21, 0x9);
185 swI2CWriteReg(0xec, 0x49, 0xC0);
81dee67e 186 pr_info("okay,CH7301 DVI chip setup done\n");
202add2a 187 }
81dee67e
SM
188 }
189
190 /* init 2d engine */
7b05cbe8 191 if (!share->accel_off)
81dee67e 192 hw_sm750_initAccel(share);
81dee67e
SM
193
194 return 0;
195}
196
197
eb0f4271 198resource_size_t hw_sm750_getVMSize(struct lynx_share *share)
81dee67e
SM
199{
200 resource_size_t ret;
29d87336 201
81dee67e
SM
202 ret = ddk750_getVMSize();
203 return ret;
204}
205
206
207
e188ea32 208int hw_sm750_output_checkMode(struct lynxfb_output *output, struct fb_var_screeninfo *var)
81dee67e 209{
29d87336 210
81dee67e
SM
211 return 0;
212}
213
214
e188ea32
AS
215int hw_sm750_output_setMode(struct lynxfb_output *output,
216 struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
81dee67e
SM
217{
218 int ret;
219 disp_output_t dispSet;
220 int channel;
29d87336 221
81dee67e
SM
222 ret = 0;
223 dispSet = 0;
224 channel = *output->channel;
225
226
6d1b3d64
AS
227 if (getChipType() != SM750LE) {
228 if (channel == sm750_primary) {
81dee67e 229 pr_info("primary channel\n");
6d1b3d64 230 if (output->paths & sm750_panel)
81dee67e 231 dispSet |= do_LCD1_PRI;
6d1b3d64 232 if (output->paths & sm750_crt)
81dee67e
SM
233 dispSet |= do_CRT_PRI;
234
5e83e283 235 } else {
81dee67e 236 pr_info("secondary channel\n");
6d1b3d64 237 if (output->paths & sm750_panel)
81dee67e 238 dispSet |= do_LCD1_SEC;
6d1b3d64 239 if (output->paths & sm750_crt)
81dee67e
SM
240 dispSet |= do_CRT_SEC;
241
242 }
243 ddk750_setLogicalDispOut(dispSet);
5e83e283 244 } else {
81dee67e
SM
245 /* just open DISPLAY_CONTROL_750LE register bit 3:0*/
246 u32 reg;
40403c1b 247
81dee67e
SM
248 reg = PEEK32(DISPLAY_CONTROL_750LE);
249 reg |= 0xf;
d2a60377 250 POKE32(DISPLAY_CONTROL_750LE, reg);
81dee67e
SM
251 }
252
a1fe154f 253 pr_info("ddk setlogicdispout done\n");
81dee67e
SM
254 return ret;
255}
256
e188ea32 257void hw_sm750_output_clear(struct lynxfb_output *output)
81dee67e 258{
29d87336 259
81dee67e
SM
260 return;
261}
262
e188ea32 263int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var)
81dee67e 264{
eb0f4271 265 struct lynx_share *share;
29d87336 266
81dee67e 267
bdec7773 268 share = container_of(crtc, struct lynxfb_par, crtc)->share;
81dee67e 269
e0ded448 270 switch (var->bits_per_pixel) {
990e5666
AS
271 case 8:
272 case 16:
273 break;
274 case 32:
275 if (share->revid == SM750LE_REVISION_ID) {
276 pr_debug("750le do not support 32bpp\n");
81dee67e 277 return -EINVAL;
990e5666
AS
278 }
279 break;
280 default:
281 return -EINVAL;
81dee67e
SM
282
283 }
284
285 return 0;
286}
287
288
289/*
290 set the controller's mode for @crtc charged with @var and @fix parameters
291*/
e188ea32
AS
292int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
293 struct fb_var_screeninfo *var,
294 struct fb_fix_screeninfo *fix)
81dee67e 295{
bdec7773 296 int ret, fmt;
81dee67e
SM
297 u32 reg;
298 mode_parameter_t modparm;
299 clock_type_t clock;
eb0f4271
GD
300 struct lynx_share *share;
301 struct lynxfb_par *par;
81dee67e 302
29d87336 303
81dee67e 304 ret = 0;
d2a60377 305 par = container_of(crtc, struct lynxfb_par, crtc);
81dee67e
SM
306 share = par->share;
307#if 1
6d1b3d64 308 if (!share->accel_off) {
81dee67e 309 /* set 2d engine pixel format according to mode bpp */
6d1b3d64 310 switch (var->bits_per_pixel) {
990e5666
AS
311 case 8:
312 fmt = 0;
313 break;
314 case 16:
315 fmt = 1;
316 break;
317 case 32:
318 default:
319 fmt = 2;
320 break;
81dee67e 321 }
d2a60377 322 hw_set2dformat(&share->accel, fmt);
81dee67e
SM
323 }
324#endif
325
326 /* set timing */
81dee67e
SM
327 modparm.pixel_clock = ps_to_hz(var->pixclock);
328 modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? POS:NEG;
329 modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? POS:NEG;
d5fca403 330 modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT) ? POS:NEG;
81dee67e
SM
331 modparm.horizontal_display_end = var->xres;
332 modparm.horizontal_sync_width = var->hsync_len;
333 modparm.horizontal_sync_start = var->xres + var->right_margin;
334 modparm.horizontal_total = var->xres + var->left_margin + var->right_margin + var->hsync_len;
335 modparm.vertical_display_end = var->yres;
336 modparm.vertical_sync_height = var->vsync_len;
337 modparm.vertical_sync_start = var->yres + var->lower_margin;
338 modparm.vertical_total = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
339
340 /* choose pll */
6d1b3d64 341 if (crtc->channel != sm750_secondary)
81dee67e
SM
342 clock = PRIMARY_PLL;
343 else
344 clock = SECONDARY_PLL;
345
d2a60377
SA
346 pr_debug("Request pixel clock = %lu\n", modparm.pixel_clock);
347 ret = ddk750_setModeTiming(&modparm, clock);
6d1b3d64 348 if (ret) {
81dee67e
SM
349 pr_err("Set mode timing failed\n");
350 goto exit;
351 }
352
6d1b3d64 353 if (crtc->channel != sm750_secondary) {
81dee67e
SM
354 /* set pitch, offset ,width,start address ,etc... */
355 POKE32(PANEL_FB_ADDRESS,
d2a60377
SA
356 FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, CURRENT)|
357 FIELD_SET(0, PANEL_FB_ADDRESS, EXT, LOCAL)|
358 FIELD_VALUE(0, PANEL_FB_ADDRESS, ADDRESS, crtc->oScreen));
81dee67e
SM
359
360 reg = var->xres * (var->bits_per_pixel >> 3);
361 /* crtc->channel is not equal to par->index on numeric,be aware of that */
bdec7773 362 reg = PADDING(crtc->line_pad, reg);
81dee67e
SM
363
364 POKE32(PANEL_FB_WIDTH,
d2a60377
SA
365 FIELD_VALUE(0, PANEL_FB_WIDTH, WIDTH, reg)|
366 FIELD_VALUE(0, PANEL_FB_WIDTH, OFFSET, fix->line_length));
81dee67e
SM
367
368 POKE32(PANEL_WINDOW_WIDTH,
d5fca403 369 FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH, var->xres - 1)|
d2a60377 370 FIELD_VALUE(0, PANEL_WINDOW_WIDTH, X, var->xoffset));
81dee67e
SM
371
372 POKE32(PANEL_WINDOW_HEIGHT,
d2a60377
SA
373 FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, HEIGHT, var->yres_virtual - 1)|
374 FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, Y, var->yoffset));
81dee67e 375
d2a60377 376 POKE32(PANEL_PLANE_TL, 0);
81dee67e
SM
377
378 POKE32(PANEL_PLANE_BR,
d2a60377 379 FIELD_VALUE(0, PANEL_PLANE_BR, BOTTOM, var->yres - 1)|
bdec7773 380 FIELD_VALUE(0, PANEL_PLANE_BR, RIGHT, var->xres - 1));
81dee67e
SM
381
382 /* set pixel format */
383 reg = PEEK32(PANEL_DISPLAY_CTRL);
384 POKE32(PANEL_DISPLAY_CTRL,
385 FIELD_VALUE(reg,
d2a60377 386 PANEL_DISPLAY_CTRL, FORMAT,
81dee67e
SM
387 (var->bits_per_pixel >> 4)
388 ));
5e83e283 389 } else {
81dee67e 390 /* not implemented now */
d2a60377 391 POKE32(CRT_FB_ADDRESS, crtc->oScreen);
81dee67e
SM
392 reg = var->xres * (var->bits_per_pixel >> 3);
393 /* crtc->channel is not equal to par->index on numeric,be aware of that */
d2a60377 394 reg = PADDING(crtc->line_pad, reg);
81dee67e
SM
395
396 POKE32(CRT_FB_WIDTH,
d2a60377
SA
397 FIELD_VALUE(0, CRT_FB_WIDTH, WIDTH, reg)|
398 FIELD_VALUE(0, CRT_FB_WIDTH, OFFSET, fix->line_length));
81dee67e
SM
399
400 /* SET PIXEL FORMAT */
401 reg = PEEK32(CRT_DISPLAY_CTRL);
d2a60377
SA
402 reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, FORMAT, var->bits_per_pixel >> 4);
403 POKE32(CRT_DISPLAY_CTRL, reg);
81dee67e
SM
404
405 }
406
407
408exit:
409 return ret;
410}
411
e188ea32 412void hw_sm750_crtc_clear(struct lynxfb_crtc *crtc)
81dee67e 413{
29d87336 414
81dee67e
SM
415 return;
416}
417
e188ea32 418int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
d2a60377 419 ushort red, ushort green, ushort blue)
81dee67e 420{
d5fca403 421 static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
40403c1b 422
d2a60377 423 POKE32(add[crtc->channel] + index*4, (red<<16)|(green<<8)|blue);
81dee67e
SM
424 return 0;
425}
426
14a974c5
AS
427int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank)
428{
bdec7773 429 int dpms, crtdb;
29d87336 430
4bcdffee 431 switch (blank) {
bdec7773 432#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
990e5666 433 case FB_BLANK_UNBLANK:
81dee67e 434#else
990e5666 435 case VESA_NO_BLANKING:
81dee67e 436#endif
990e5666
AS
437 dpms = CRT_DISPLAY_CTRL_DPMS_0;
438 crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
439 break;
bdec7773 440#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
990e5666
AS
441 case FB_BLANK_NORMAL:
442 dpms = CRT_DISPLAY_CTRL_DPMS_0;
443 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
444 break;
81dee67e 445#endif
bdec7773 446#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
990e5666 447 case FB_BLANK_VSYNC_SUSPEND:
81dee67e 448#else
990e5666 449 case VESA_VSYNC_SUSPEND:
81dee67e 450#endif
990e5666
AS
451 dpms = CRT_DISPLAY_CTRL_DPMS_2;
452 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
453 break;
bdec7773 454#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
990e5666 455 case FB_BLANK_HSYNC_SUSPEND:
81dee67e 456#else
990e5666 457 case VESA_HSYNC_SUSPEND:
81dee67e 458#endif
990e5666
AS
459 dpms = CRT_DISPLAY_CTRL_DPMS_1;
460 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
461 break;
bdec7773 462#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
990e5666 463 case FB_BLANK_POWERDOWN:
81dee67e 464#else
990e5666 465 case VESA_POWERDOWN:
81dee67e 466#endif
990e5666
AS
467 dpms = CRT_DISPLAY_CTRL_DPMS_3;
468 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
469 break;
470 default:
471 return -EINVAL;
81dee67e
SM
472 }
473
6d1b3d64 474 if (output->paths & sm750_crt) {
d2a60377
SA
475 POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, DPMS, dpms));
476 POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
81dee67e
SM
477 }
478 return 0;
479}
480
e188ea32 481int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
81dee67e 482{
d2a60377 483 unsigned int dpms, pps, crtdb;
29d87336 484
81dee67e
SM
485 dpms = pps = crtdb = 0;
486
4bcdffee 487 switch (blank) {
bdec7773 488#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
990e5666 489 case FB_BLANK_UNBLANK:
81dee67e 490#else
990e5666 491 case VESA_NO_BLANKING:
81dee67e 492#endif
a1fe154f 493 pr_info("flag = FB_BLANK_UNBLANK\n");
990e5666
AS
494 dpms = SYSTEM_CTRL_DPMS_VPHP;
495 pps = PANEL_DISPLAY_CTRL_DATA_ENABLE;
496 crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
497 break;
bdec7773 498#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
990e5666 499 case FB_BLANK_NORMAL:
a1fe154f 500 pr_info("flag = FB_BLANK_NORMAL\n");
990e5666
AS
501 dpms = SYSTEM_CTRL_DPMS_VPHP;
502 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
503 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
504 break;
81dee67e 505#endif
bdec7773 506#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
990e5666 507 case FB_BLANK_VSYNC_SUSPEND:
81dee67e 508#else
990e5666 509 case VESA_VSYNC_SUSPEND:
81dee67e 510#endif
990e5666
AS
511 dpms = SYSTEM_CTRL_DPMS_VNHP;
512 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
513 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
514 break;
bdec7773 515#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
990e5666 516 case FB_BLANK_HSYNC_SUSPEND:
81dee67e 517#else
990e5666 518 case VESA_HSYNC_SUSPEND:
81dee67e 519#endif
990e5666
AS
520 dpms = SYSTEM_CTRL_DPMS_VPHN;
521 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
522 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
523 break;
bdec7773 524#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
990e5666 525 case FB_BLANK_POWERDOWN:
81dee67e 526#else
990e5666 527 case VESA_POWERDOWN:
81dee67e 528#endif
990e5666
AS
529 dpms = SYSTEM_CTRL_DPMS_VNHN;
530 pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
531 crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
532 break;
81dee67e
SM
533 }
534
6d1b3d64 535 if (output->paths & sm750_crt) {
81dee67e 536
bdec7773
IA
537 POKE32(SYSTEM_CTRL, FIELD_VALUE(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, DPMS, dpms));
538 POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
81dee67e
SM
539 }
540
7b05cbe8 541 if (output->paths & sm750_panel)
d2a60377 542 POKE32(PANEL_DISPLAY_CTRL, FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, DATA, pps));
81dee67e
SM
543
544 return 0;
545}
546
547
eb0f4271 548void hw_sm750_initAccel(struct lynx_share *share)
81dee67e
SM
549{
550 u32 reg;
40403c1b 551
81dee67e
SM
552 enable2DEngine(1);
553
6d1b3d64 554 if (getChipType() == SM750LE) {
81dee67e 555 reg = PEEK32(DE_STATE1);
bdec7773
IA
556 reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, ON);
557 POKE32(DE_STATE1, reg);
81dee67e
SM
558
559 reg = PEEK32(DE_STATE1);
bdec7773 560 reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, OFF);
d2a60377 561 POKE32(DE_STATE1, reg);
81dee67e 562
5e83e283 563 } else {
81dee67e
SM
564 /* engine reset */
565 reg = PEEK32(SYSTEM_CTRL);
bdec7773 566 reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, ON);
d2a60377 567 POKE32(SYSTEM_CTRL, reg);
81dee67e
SM
568
569 reg = PEEK32(SYSTEM_CTRL);
bdec7773 570 reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, OFF);
d2a60377 571 POKE32(SYSTEM_CTRL, reg);
81dee67e
SM
572 }
573
574 /* call 2d init */
575 share->accel.de_init(&share->accel);
576}
577
6fa7db83 578int hw_sm750le_deWait(void)
81dee67e 579{
d5fca403 580 int i = 0x10000000;
40403c1b 581
6d1b3d64 582 while (i--) {
81dee67e 583 unsigned int dwVal = PEEK32(DE_STATE2);
40403c1b 584
6d1b3d64 585 if ((FIELD_GET(dwVal, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) &&
d2a60377 586 (FIELD_GET(dwVal, DE_STATE2, DE_FIFO) == DE_STATE2_DE_FIFO_EMPTY) &&
4bcdffee 587 (FIELD_GET(dwVal, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) {
81dee67e
SM
588 return 0;
589 }
590 }
591 /* timeout error */
592 return -1;
593}
594
595
6fa7db83 596int hw_sm750_deWait(void)
81dee67e 597{
d5fca403 598 int i = 0x10000000;
40403c1b 599
6d1b3d64 600 while (i--) {
81dee67e 601 unsigned int dwVal = PEEK32(SYSTEM_CTRL);
40403c1b 602
6d1b3d64 603 if ((FIELD_GET(dwVal, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) &&
bdec7773 604 (FIELD_GET(dwVal, SYSTEM_CTRL, DE_FIFO) == SYSTEM_CTRL_DE_FIFO_EMPTY) &&
4bcdffee 605 (FIELD_GET(dwVal, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) {
81dee67e
SM
606 return 0;
607 }
608 }
609 /* timeout error */
610 return -1;
611}
612
613int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
202add2a
AS
614 const struct fb_var_screeninfo *var,
615 const struct fb_info *info)
81dee67e 616{
202add2a
AS
617 uint32_t total;
618 /* check params */
619 if ((var->xoffset + var->xres > var->xres_virtual) ||
620 (var->yoffset + var->yres > var->yres_virtual)) {
621 return -EINVAL;
622 }
623
624 total = var->yoffset * info->fix.line_length +
625 ((var->xoffset * var->bits_per_pixel) >> 3);
626 total += crtc->oScreen;
627 if (crtc->channel == sm750_primary) {
628 POKE32(PANEL_FB_ADDRESS,
629 FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS),
630 PANEL_FB_ADDRESS, ADDRESS, total));
631 } else {
632 POKE32(CRT_FB_ADDRESS,
633 FIELD_VALUE(PEEK32(CRT_FB_ADDRESS),
634 CRT_FB_ADDRESS, ADDRESS, total));
635 }
636 return 0;
81dee67e 637}