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