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
hw_sm750_map(struct sm750_dev * sm750_dev,struct pci_dev * pdev)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
hw_sm750_inithw(struct sm750_dev * sm750_dev,struct pci_dev * pdev)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
hw_sm750_output_setMode(struct lynxfb_output * output,struct fb_var_screeninfo * var,struct fb_fix_screeninfo * fix)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
hw_sm750_crtc_checkMode(struct lynxfb_crtc * crtc,struct fb_var_screeninfo * var)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 */
hw_sm750_crtc_setMode(struct lynxfb_crtc * crtc,struct fb_var_screeninfo * var,struct fb_fix_screeninfo * fix)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
hw_sm750_setColReg(struct lynxfb_crtc * crtc,ushort index,ushort red,ushort green,ushort blue)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
hw_sm750le_setBLANK(struct lynxfb_output * output,int blank)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
hw_sm750_setBLANK(struct lynxfb_output * output,int blank)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
hw_sm750_initAccel(struct sm750_dev * sm750_dev)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
hw_sm750le_deWait(void)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
hw_sm750_deWait(void)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
hw_sm750_pan_display(struct lynxfb_crtc * crtc,const struct fb_var_screeninfo * var,const struct fb_info * info)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 }
570