GNU Linux-libre 4.9.294-gnu1
[releases.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 int 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         /* reserve the vidreg space of smi adaptor
38          * if you do this, you need to add release region code
39          * in lynxfb_remove, or memory will not be mapped again
40          * successfully
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         /* now map mmio and vidmem */
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         /* don't use pdev_resource[x].end - resource[x].start to
66          * calculate the resource size, it's only the maximum available
67          * size but not the actual size, using
68          * @ddk750_getVMSize function can be safe.
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         /* reserve the vidmem space of smi adaptor */
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         }
84 exit:
85         return ret;
86 }
87
88 int 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         /* for sm718, open pci burst */
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                 /* does user need CRT? */
113                 if (sm750_dev->nocrt) {
114                         POKE32(MISC_CTRL,
115                                PEEK32(MISC_CTRL) | MISC_CTRL_DAC_POWER_OFF);
116                         /* shut off dpms */
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                         /* turn on dpms */
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                 /* 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.
149                  */
150                 sm750_sw_i2c_init(0, 1);
151
152                 /* Customer may NOT use CH7301 DVI chip, which has to be
153                  * initialized differently.
154                  */
155                 if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) {
156                 /* The following register values for CH7301 are from
157                  * Chrontel app note and our experiment.
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         /* init 2d engine */
168         if (!sm750_dev->accel_off)
169                 hw_sm750_initAccel(sm750_dev);
170
171         return 0;
172 }
173
174 int 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                 /* just open DISPLAY_CONTROL_750LE register bit 3:0 */
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
215 int 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 /* set the controller's mode for @crtc charged with @var and @fix parameters */
241 int 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                 /* set 2d engine pixel format according to mode bpp */
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         /* set timing */
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         /* choose pll */
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                 /* set pitch, offset, width, start address, etc... */
307                 POKE32(PANEL_FB_ADDRESS,
308                        crtc->oScreen & PANEL_FB_ADDRESS_ADDRESS_MASK);
309
310                 reg = var->xres * (var->bits_per_pixel >> 3);
311                 /* crtc->channel is not equal to par->index on numeric,
312                  * be aware of that
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                 /* set pixel format */
339                 reg = PEEK32(PANEL_DISPLAY_CTRL);
340                 POKE32(PANEL_DISPLAY_CTRL, reg | (var->bits_per_pixel >> 4));
341         } else {
342                 /* not implemented now */
343                 POKE32(CRT_FB_ADDRESS, crtc->oScreen);
344                 reg = var->xres * (var->bits_per_pixel >> 3);
345                 /* crtc->channel is not equal to par->index on numeric,
346                  * be aware of that
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                 /* SET PIXEL FORMAT */
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
360 exit:
361         return ret;
362 }
363
364 int 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
374 int 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
415 int 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
468 void 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                 /* engine reset */
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         /* call 2d init */
495         sm750_dev->accel.de_init(&sm750_dev->accel);
496 }
497
498 int 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         /* timeout error */
512         return -1;
513 }
514
515 int 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         /* timeout error */
530         return -1;
531 }
532
533 int 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         /* 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,
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 }