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>
14#include <linux/console.h>
15#ifdef CONFIG_MTRR
16#include <asm/mtrr.h>
17#endif
18#include <linux/platform_device.h>
19#include <linux/screen_info.h>
20#include <linux/sizes.h>
21
22#include "sm750.h"
23#include "ddk750.h"
24#include "sm750_accel.h"
25
26int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
27{
28 int ret;
29
30 ret = 0;
31
32 sm750_dev->vidreg_start = pci_resource_start(pdev, 1);
33 sm750_dev->vidreg_size = SZ_2M;
34
35 pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start);
36
37
38
39
40
41
42 ret = pci_request_region(pdev, 1, "sm750fb");
43 if (ret) {
44 pr_err("Can not request PCI regions.\n");
45 goto exit;
46 }
47
48
49 sm750_dev->pvReg = ioremap_nocache(sm750_dev->vidreg_start,
50 sm750_dev->vidreg_size);
51 if (!sm750_dev->pvReg) {
52 pr_err("mmio failed\n");
53 ret = -EFAULT;
54 goto exit;
55 } else {
56 pr_info("mmio virtual addr = %p\n", sm750_dev->pvReg);
57 }
58
59 sm750_dev->accel.dprBase = sm750_dev->pvReg + DE_BASE_ADDR_TYPE1;
60 sm750_dev->accel.dpPortBase = sm750_dev->pvReg + DE_PORT_ADDR_TYPE1;
61
62 ddk750_set_mmio(sm750_dev->pvReg, sm750_dev->devid, sm750_dev->revid);
63
64 sm750_dev->vidmem_start = pci_resource_start(pdev, 0);
65
66
67
68
69
70 sm750_dev->vidmem_size = ddk750_getVMSize();
71 pr_info("video memory phyAddr = %lx, size = %u bytes\n",
72 sm750_dev->vidmem_start, sm750_dev->vidmem_size);
73
74
75 sm750_dev->pvMem = ioremap_wc(sm750_dev->vidmem_start,
76 sm750_dev->vidmem_size);
77 if (!sm750_dev->pvMem) {
78 pr_err("Map video memory failed\n");
79 ret = -EFAULT;
80 goto exit;
81 } else {
82 pr_info("video memory vaddr = %p\n", sm750_dev->pvMem);
83 }
84exit:
85 return ret;
86}
87
88int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev)
89{
90 struct init_status *parm;
91
92 parm = &sm750_dev->initParm;
93 if (parm->chip_clk == 0)
94 parm->chip_clk = (sm750_get_chip_type() == SM750LE) ?
95 DEFAULT_SM750LE_CHIP_CLOCK :
96 DEFAULT_SM750_CHIP_CLOCK;
97
98 if (parm->mem_clk == 0)
99 parm->mem_clk = parm->chip_clk;
100 if (parm->master_clk == 0)
101 parm->master_clk = parm->chip_clk / 3;
102
103 ddk750_initHw((initchip_param_t *)&sm750_dev->initParm);
104
105 if (sm750_dev->devid == 0x718) {
106 POKE32(SYSTEM_CTRL,
107 PEEK32(SYSTEM_CTRL) | SYSTEM_CTRL_PCI_BURST);
108 }
109
110 if (sm750_get_chip_type() != SM750LE) {
111 unsigned int val;
112
113 if (sm750_dev->nocrt) {
114 POKE32(MISC_CTRL,
115 PEEK32(MISC_CTRL) | MISC_CTRL_DAC_POWER_OFF);
116
117 val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
118 val |= SYSTEM_CTRL_DPMS_VPHN;
119 POKE32(SYSTEM_CTRL, val);
120 } else {
121 POKE32(MISC_CTRL,
122 PEEK32(MISC_CTRL) & ~MISC_CTRL_DAC_POWER_OFF);
123
124 val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
125 val |= SYSTEM_CTRL_DPMS_VPHP;
126 POKE32(SYSTEM_CTRL, val);
127 }
128
129 val = PEEK32(PANEL_DISPLAY_CTRL) &
130 ~(PANEL_DISPLAY_CTRL_DUAL_DISPLAY |
131 PANEL_DISPLAY_CTRL_DOUBLE_PIXEL);
132 switch (sm750_dev->pnltype) {
133 case sm750_24TFT:
134 break;
135 case sm750_doubleTFT:
136 val |= PANEL_DISPLAY_CTRL_DOUBLE_PIXEL;
137 break;
138 case sm750_dualTFT:
139 val |= PANEL_DISPLAY_CTRL_DUAL_DISPLAY;
140 break;
141 }
142 POKE32(PANEL_DISPLAY_CTRL, val);
143 } else {
144
145
146
147
148
149
150 sm750_sw_i2c_init(0, 1);
151
152
153
154
155 if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) {
156
157
158
159 pr_info("yes,CH7301 DVI chip found\n");
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);
163 pr_info("okay,CH7301 DVI chip setup done\n");
164 }
165 }
166
167
168 if (!sm750_dev->accel_off)
169 hw_sm750_initAccel(sm750_dev);
170
171 return 0;
172}
173
174int hw_sm750_output_setMode(struct lynxfb_output *output,
175 struct fb_var_screeninfo *var,
176 struct fb_fix_screeninfo *fix)
177{
178 int ret;
179 disp_output_t dispSet;
180 int channel;
181
182 ret = 0;
183 dispSet = 0;
184 channel = *output->channel;
185
186 if (sm750_get_chip_type() != SM750LE) {
187 if (channel == sm750_primary) {
188 pr_info("primary channel\n");
189 if (output->paths & sm750_panel)
190 dispSet |= do_LCD1_PRI;
191 if (output->paths & sm750_crt)
192 dispSet |= do_CRT_PRI;
193
194 } else {
195 pr_info("secondary channel\n");
196 if (output->paths & sm750_panel)
197 dispSet |= do_LCD1_SEC;
198 if (output->paths & sm750_crt)
199 dispSet |= do_CRT_SEC;
200 }
201 ddk750_setLogicalDispOut(dispSet);
202 } else {
203
204 u32 reg;
205
206 reg = PEEK32(DISPLAY_CONTROL_750LE);
207 reg |= 0xf;
208 POKE32(DISPLAY_CONTROL_750LE, reg);
209 }
210
211 pr_info("ddk setlogicdispout done\n");
212 return ret;
213}
214
215int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc,
216 struct fb_var_screeninfo *var)
217{
218 struct sm750_dev *sm750_dev;
219 struct lynxfb_par *par = container_of(crtc, struct lynxfb_par, crtc);
220
221 sm750_dev = par->dev;
222
223 switch (var->bits_per_pixel) {
224 case 8:
225 case 16:
226 break;
227 case 32:
228 if (sm750_dev->revid == SM750LE_REVISION_ID) {
229 pr_debug("750le do not support 32bpp\n");
230 return -EINVAL;
231 }
232 break;
233 default:
234 return -EINVAL;
235 }
236
237 return 0;
238}
239
240
241int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
242 struct fb_var_screeninfo *var,
243 struct fb_fix_screeninfo *fix)
244{
245 int ret, fmt;
246 u32 reg;
247 mode_parameter_t modparm;
248 clock_type_t clock;
249 struct sm750_dev *sm750_dev;
250 struct lynxfb_par *par;
251
252 ret = 0;
253 par = container_of(crtc, struct lynxfb_par, crtc);
254 sm750_dev = par->dev;
255
256 if (!sm750_dev->accel_off) {
257
258 switch (var->bits_per_pixel) {
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;
269 }
270 hw_set2dformat(&sm750_dev->accel, fmt);
271 }
272
273
274 modparm.pixel_clock = ps_to_hz(var->pixclock);
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;
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;
284 modparm.horizontal_total = var->xres + var->left_margin +
285 var->right_margin + var->hsync_len;
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;
289 modparm.vertical_total = var->yres + var->upper_margin +
290 var->lower_margin + var->vsync_len;
291
292
293 if (crtc->channel != sm750_secondary)
294 clock = PRIMARY_PLL;
295 else
296 clock = SECONDARY_PLL;
297
298 pr_debug("Request pixel clock = %lu\n", modparm.pixel_clock);
299 ret = ddk750_setModeTiming(&modparm, clock);
300 if (ret) {
301 pr_err("Set mode timing failed\n");
302 goto exit;
303 }
304
305 if (crtc->channel != sm750_secondary) {
306
307 POKE32(PANEL_FB_ADDRESS,
308 crtc->oScreen & PANEL_FB_ADDRESS_ADDRESS_MASK);
309
310 reg = var->xres * (var->bits_per_pixel >> 3);
311
312
313
314 reg = ALIGN(reg, crtc->line_pad);
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);
319
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);
324
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);
330
331 POKE32(PANEL_PLANE_TL, 0);
332
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);
337
338
339 reg = PEEK32(PANEL_DISPLAY_CTRL);
340 POKE32(PANEL_DISPLAY_CTRL, reg | (var->bits_per_pixel >> 4));
341 } else {
342
343 POKE32(CRT_FB_ADDRESS, crtc->oScreen);
344 reg = var->xres * (var->bits_per_pixel >> 3);
345
346
347
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);
352
353
354 reg = PEEK32(CRT_DISPLAY_CTRL);
355 reg |= ((var->bits_per_pixel >> 4) &
356 CRT_DISPLAY_CTRL_FORMAT_MASK);
357 POKE32(CRT_DISPLAY_CTRL, reg);
358 }
359
360exit:
361 return ret;
362}
363
364int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
365 ushort red, ushort green, ushort blue)
366{
367 static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
368
369 POKE32(add[crtc->channel] + index * 4,
370 (red << 16) | (green << 8) | blue);
371 return 0;
372}
373
374int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank)
375{
376 int dpms, crtdb;
377
378 switch (blank) {
379 case FB_BLANK_UNBLANK:
380 dpms = CRT_DISPLAY_CTRL_DPMS_0;
381 crtdb = 0;
382 break;
383 case FB_BLANK_NORMAL:
384 dpms = CRT_DISPLAY_CTRL_DPMS_0;
385 crtdb = CRT_DISPLAY_CTRL_BLANK;
386 break;
387 case FB_BLANK_VSYNC_SUSPEND:
388 dpms = CRT_DISPLAY_CTRL_DPMS_2;
389 crtdb = CRT_DISPLAY_CTRL_BLANK;
390 break;
391 case FB_BLANK_HSYNC_SUSPEND:
392 dpms = CRT_DISPLAY_CTRL_DPMS_1;
393 crtdb = CRT_DISPLAY_CTRL_BLANK;
394 break;
395 case FB_BLANK_POWERDOWN:
396 dpms = CRT_DISPLAY_CTRL_DPMS_3;
397 crtdb = CRT_DISPLAY_CTRL_BLANK;
398 break;
399 default:
400 return -EINVAL;
401 }
402
403 if (output->paths & sm750_crt) {
404 unsigned int val;
405
406 val = PEEK32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_DPMS_MASK;
407 POKE32(CRT_DISPLAY_CTRL, val | dpms);
408
409 val = PEEK32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_BLANK;
410 POKE32(CRT_DISPLAY_CTRL, val | crtdb);
411 }
412 return 0;
413}
414
415int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
416{
417 unsigned int dpms, pps, crtdb;
418
419 dpms = 0;
420 pps = 0;
421 crtdb = 0;
422
423 switch (blank) {
424 case FB_BLANK_UNBLANK:
425 pr_debug("flag = FB_BLANK_UNBLANK\n");
426 dpms = SYSTEM_CTRL_DPMS_VPHP;
427 pps = PANEL_DISPLAY_CTRL_DATA;
428 break;
429 case FB_BLANK_NORMAL:
430 pr_debug("flag = FB_BLANK_NORMAL\n");
431 dpms = SYSTEM_CTRL_DPMS_VPHP;
432 crtdb = CRT_DISPLAY_CTRL_BLANK;
433 break;
434 case FB_BLANK_VSYNC_SUSPEND:
435 dpms = SYSTEM_CTRL_DPMS_VNHP;
436 crtdb = CRT_DISPLAY_CTRL_BLANK;
437 break;
438 case FB_BLANK_HSYNC_SUSPEND:
439 dpms = SYSTEM_CTRL_DPMS_VPHN;
440 crtdb = CRT_DISPLAY_CTRL_BLANK;
441 break;
442 case FB_BLANK_POWERDOWN:
443 dpms = SYSTEM_CTRL_DPMS_VNHN;
444 crtdb = CRT_DISPLAY_CTRL_BLANK;
445 break;
446 }
447
448 if (output->paths & sm750_crt) {
449 unsigned int val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
450
451 POKE32(SYSTEM_CTRL, val | dpms);
452
453 val = PEEK32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_BLANK;
454 POKE32(CRT_DISPLAY_CTRL, val | crtdb);
455 }
456
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 }
464
465 return 0;
466}
467
468void hw_sm750_initAccel(struct sm750_dev *sm750_dev)
469{
470 u32 reg;
471
472 enable2DEngine(1);
473
474 if (sm750_get_chip_type() == SM750LE) {
475 reg = PEEK32(DE_STATE1);
476 reg |= DE_STATE1_DE_ABORT;
477 POKE32(DE_STATE1, reg);
478
479 reg = PEEK32(DE_STATE1);
480 reg &= ~DE_STATE1_DE_ABORT;
481 POKE32(DE_STATE1, reg);
482
483 } else {
484
485 reg = PEEK32(SYSTEM_CTRL);
486 reg |= SYSTEM_CTRL_DE_ABORT;
487 POKE32(SYSTEM_CTRL, reg);
488
489 reg = PEEK32(SYSTEM_CTRL);
490 reg &= ~SYSTEM_CTRL_DE_ABORT;
491 POKE32(SYSTEM_CTRL, reg);
492 }
493
494
495 sm750_dev->accel.de_init(&sm750_dev->accel);
496}
497
498int hw_sm750le_deWait(void)
499{
500 int i = 0x10000000;
501 unsigned int mask = DE_STATE2_DE_STATUS_BUSY | DE_STATE2_DE_FIFO_EMPTY |
502 DE_STATE2_DE_MEM_FIFO_EMPTY;
503
504 while (i--) {
505 unsigned int val = PEEK32(DE_STATE2);
506
507 if ((val & mask) ==
508 (DE_STATE2_DE_FIFO_EMPTY | DE_STATE2_DE_MEM_FIFO_EMPTY))
509 return 0;
510 }
511
512 return -1;
513}
514
515int hw_sm750_deWait(void)
516{
517 int i = 0x10000000;
518 unsigned int mask = SYSTEM_CTRL_DE_STATUS_BUSY |
519 SYSTEM_CTRL_DE_FIFO_EMPTY |
520 SYSTEM_CTRL_DE_MEM_FIFO_EMPTY;
521
522 while (i--) {
523 unsigned int val = PEEK32(SYSTEM_CTRL);
524
525 if ((val & mask) ==
526 (SYSTEM_CTRL_DE_FIFO_EMPTY | SYSTEM_CTRL_DE_MEM_FIFO_EMPTY))
527 return 0;
528 }
529
530 return -1;
531}
532
533int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
534 const struct fb_var_screeninfo *var,
535 const struct fb_info *info)
536{
537 u32 total;
538
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,
549 PEEK32(PANEL_FB_ADDRESS) |
550 (total & PANEL_FB_ADDRESS_ADDRESS_MASK));
551 } else {
552 POKE32(CRT_FB_ADDRESS,
553 PEEK32(CRT_FB_ADDRESS) |
554 (total & CRT_FB_ADDRESS_ADDRESS_MASK));
555 }
556 return 0;
557}
558