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