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