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