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