1 // SPDX-License-Identifier: GPL-2.0-only
3 * Frame buffer driver for the Carmine GPU.
5 * The driver configures the GPU as follows
6 * - FB0 is display 0 with unique memory area
7 * - FB1 is display 1 with unique memory area
8 * - both display use 32 bit colors
10 #include <linux/aperture.h>
11 #include <linux/delay.h>
12 #include <linux/errno.h>
14 #include <linux/interrupt.h>
15 #include <linux/pci.h>
16 #include <linux/slab.h>
17 #include <linux/module.h>
19 #include "carminefb.h"
20 #include "carminefb_regs.h"
22 #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
23 #error "The endianness of the target host has not been defined."
27 * The initial video mode can be supplied via two different ways:
28 * - as a string that is passed to fb_find_mode() (module option fb_mode_str)
29 * - as an integer that picks the video mode from carmine_modedb[] (module
32 * If nothing is used than the initial video mode will be the
33 * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[].
35 #define CARMINEFB_DEFAULT_VIDEO_MODE 1
37 static unsigned int fb_mode
= CARMINEFB_DEFAULT_VIDEO_MODE
;
38 module_param(fb_mode
, uint
, 0444);
39 MODULE_PARM_DESC(fb_mode
, "Initial video mode as integer.");
41 static char *fb_mode_str
;
42 module_param(fb_mode_str
, charp
, 0444);
43 MODULE_PARM_DESC(fb_mode_str
, "Initial video mode in characters.");
51 static int fb_displays
= CARMINE_USE_DISPLAY0
| CARMINE_USE_DISPLAY1
;
52 module_param(fb_displays
, int, 0444);
53 MODULE_PARM_DESC(fb_displays
, "Bit mode, which displays are used");
57 void __iomem
*screen_mem
;
58 struct fb_info
*fb
[MAX_DISPLAY
];
61 struct carmine_resolution
{
74 void __iomem
*display_reg
;
75 void __iomem
*screen_base
;
79 struct carmine_resolution
*res
;
80 u32 pseudo_palette
[16];
83 static struct fb_fix_screeninfo carminefb_fix
= {
85 .type
= FB_TYPE_PACKED_PIXELS
,
86 .visual
= FB_VISUAL_TRUECOLOR
,
87 .accel
= FB_ACCEL_NONE
,
90 static const struct fb_videomode carmine_modedb
[] = {
102 static struct carmine_resolution car_modes
[] = {
129 static int carmine_find_mode(const struct fb_var_screeninfo
*var
)
133 for (i
= 0; i
< ARRAY_SIZE(car_modes
); i
++)
134 if (car_modes
[i
].hdp
== var
->xres
&&
135 car_modes
[i
].vdp
== var
->yres
)
140 static void c_set_disp_reg(const struct carmine_fb
*par
,
143 writel(val
, par
->display_reg
+ offset
);
146 static u32
c_get_disp_reg(const struct carmine_fb
*par
,
149 return readl(par
->display_reg
+ offset
);
152 static void c_set_hw_reg(const struct carmine_hw
*hw
,
155 writel(val
, hw
->v_regs
+ offset
);
158 static u32
c_get_hw_reg(const struct carmine_hw
*hw
,
161 return readl(hw
->v_regs
+ offset
);
164 static int carmine_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
165 unsigned blue
, unsigned transp
, struct fb_info
*info
)
175 ((__be32
*)info
->pseudo_palette
)[regno
] = cpu_to_be32(transp
<< 24 |
176 red
<< 0 | green
<< 8 | blue
<< 16);
180 static int carmine_check_var(struct fb_var_screeninfo
*var
,
181 struct fb_info
*info
)
185 ret
= carmine_find_mode(var
);
189 if (var
->grayscale
|| var
->rotate
|| var
->nonstd
)
192 var
->xres_virtual
= var
->xres
;
193 var
->yres_virtual
= var
->yres
;
195 var
->bits_per_pixel
= 32;
198 var
->transp
.offset
= 24;
200 var
->green
.offset
= 8;
201 var
->blue
.offset
= 16;
203 var
->transp
.offset
= 24;
204 var
->red
.offset
= 16;
205 var
->green
.offset
= 8;
206 var
->blue
.offset
= 0;
210 var
->green
.length
= 8;
211 var
->blue
.length
= 8;
212 var
->transp
.length
= 8;
214 var
->red
.msb_right
= 0;
215 var
->green
.msb_right
= 0;
216 var
->blue
.msb_right
= 0;
217 var
->transp
.msb_right
= 0;
221 static void carmine_init_display_param(struct carmine_fb
*par
)
227 u32 soffset
= par
->smem_offset
;
229 c_set_disp_reg(par
, CARMINE_DISP_REG_C_TRANS
, 0);
230 c_set_disp_reg(par
, CARMINE_DISP_REG_MLMR_TRANS
, 0);
231 c_set_disp_reg(par
, CARMINE_DISP_REG_CURSOR_MODE
,
232 CARMINE_CURSOR0_PRIORITY_MASK
|
233 CARMINE_CURSOR1_PRIORITY_MASK
|
234 CARMINE_CURSOR_CUTZ_MASK
);
236 /* Set default cursor position */
237 c_set_disp_reg(par
, CARMINE_DISP_REG_CUR1_POS
, 0 << 16 | 0);
238 c_set_disp_reg(par
, CARMINE_DISP_REG_CUR2_POS
, 0 << 16 | 0);
240 /* Set default display mode */
241 c_set_disp_reg(par
, CARMINE_DISP_REG_L0_EXT_MODE
, CARMINE_WINDOW_MODE
|
242 CARMINE_EXT_CMODE_DIRECT24_RGBA
);
243 c_set_disp_reg(par
, CARMINE_DISP_REG_L1_EXT_MODE
,
244 CARMINE_EXT_CMODE_DIRECT24_RGBA
);
245 c_set_disp_reg(par
, CARMINE_DISP_REG_L2_EXT_MODE
, CARMINE_EXTEND_MODE
|
246 CARMINE_EXT_CMODE_DIRECT24_RGBA
);
247 c_set_disp_reg(par
, CARMINE_DISP_REG_L3_EXT_MODE
, CARMINE_EXTEND_MODE
|
248 CARMINE_EXT_CMODE_DIRECT24_RGBA
);
249 c_set_disp_reg(par
, CARMINE_DISP_REG_L4_EXT_MODE
, CARMINE_EXTEND_MODE
|
250 CARMINE_EXT_CMODE_DIRECT24_RGBA
);
251 c_set_disp_reg(par
, CARMINE_DISP_REG_L5_EXT_MODE
, CARMINE_EXTEND_MODE
|
252 CARMINE_EXT_CMODE_DIRECT24_RGBA
);
253 c_set_disp_reg(par
, CARMINE_DISP_REG_L6_EXT_MODE
, CARMINE_EXTEND_MODE
|
254 CARMINE_EXT_CMODE_DIRECT24_RGBA
);
255 c_set_disp_reg(par
, CARMINE_DISP_REG_L7_EXT_MODE
, CARMINE_EXTEND_MODE
|
256 CARMINE_EXT_CMODE_DIRECT24_RGBA
);
258 /* Set default frame size to layer mode register */
259 width
= par
->res
->hdp
* 4 / CARMINE_DISP_WIDTH_UNIT
;
260 width
= width
<< CARMINE_DISP_WIDTH_SHIFT
;
262 height
= par
->res
->vdp
- 1;
263 param
= width
| height
;
265 c_set_disp_reg(par
, CARMINE_DISP_REG_L0_MODE_W_H
, param
);
266 c_set_disp_reg(par
, CARMINE_DISP_REG_L1_WIDTH
, width
);
267 c_set_disp_reg(par
, CARMINE_DISP_REG_L2_MODE_W_H
, param
);
268 c_set_disp_reg(par
, CARMINE_DISP_REG_L3_MODE_W_H
, param
);
269 c_set_disp_reg(par
, CARMINE_DISP_REG_L4_MODE_W_H
, param
);
270 c_set_disp_reg(par
, CARMINE_DISP_REG_L5_MODE_W_H
, param
);
271 c_set_disp_reg(par
, CARMINE_DISP_REG_L6_MODE_W_H
, param
);
272 c_set_disp_reg(par
, CARMINE_DISP_REG_L7_MODE_W_H
, param
);
274 /* Set default pos and size */
275 window_size
= (par
->res
->vdp
- 1) << CARMINE_DISP_WIN_H_SHIFT
;
276 window_size
|= par
->res
->hdp
;
278 c_set_disp_reg(par
, CARMINE_DISP_REG_L0_WIN_POS
, 0);
279 c_set_disp_reg(par
, CARMINE_DISP_REG_L0_WIN_SIZE
, window_size
);
280 c_set_disp_reg(par
, CARMINE_DISP_REG_L1_WIN_POS
, 0);
281 c_set_disp_reg(par
, CARMINE_DISP_REG_L1_WIN_SIZE
, window_size
);
282 c_set_disp_reg(par
, CARMINE_DISP_REG_L2_WIN_POS
, 0);
283 c_set_disp_reg(par
, CARMINE_DISP_REG_L2_WIN_SIZE
, window_size
);
284 c_set_disp_reg(par
, CARMINE_DISP_REG_L3_WIN_POS
, 0);
285 c_set_disp_reg(par
, CARMINE_DISP_REG_L3_WIN_SIZE
, window_size
);
286 c_set_disp_reg(par
, CARMINE_DISP_REG_L4_WIN_POS
, 0);
287 c_set_disp_reg(par
, CARMINE_DISP_REG_L4_WIN_SIZE
, window_size
);
288 c_set_disp_reg(par
, CARMINE_DISP_REG_L5_WIN_POS
, 0);
289 c_set_disp_reg(par
, CARMINE_DISP_REG_L5_WIN_SIZE
, window_size
);
290 c_set_disp_reg(par
, CARMINE_DISP_REG_L6_WIN_POS
, 0);
291 c_set_disp_reg(par
, CARMINE_DISP_REG_L6_WIN_SIZE
, window_size
);
292 c_set_disp_reg(par
, CARMINE_DISP_REG_L7_WIN_POS
, 0);
293 c_set_disp_reg(par
, CARMINE_DISP_REG_L7_WIN_SIZE
, window_size
);
295 /* Set default origin address */
296 c_set_disp_reg(par
, CARMINE_DISP_REG_L0_ORG_ADR
, soffset
);
297 c_set_disp_reg(par
, CARMINE_DISP_REG_L1_ORG_ADR
, soffset
);
298 c_set_disp_reg(par
, CARMINE_DISP_REG_L2_ORG_ADR1
, soffset
);
299 c_set_disp_reg(par
, CARMINE_DISP_REG_L3_ORG_ADR1
, soffset
);
300 c_set_disp_reg(par
, CARMINE_DISP_REG_L4_ORG_ADR1
, soffset
);
301 c_set_disp_reg(par
, CARMINE_DISP_REG_L5_ORG_ADR1
, soffset
);
302 c_set_disp_reg(par
, CARMINE_DISP_REG_L6_ORG_ADR1
, soffset
);
303 c_set_disp_reg(par
, CARMINE_DISP_REG_L7_ORG_ADR1
, soffset
);
305 /* Set default display address */
306 c_set_disp_reg(par
, CARMINE_DISP_REG_L0_DISP_ADR
, soffset
);
307 c_set_disp_reg(par
, CARMINE_DISP_REG_L2_DISP_ADR1
, soffset
);
308 c_set_disp_reg(par
, CARMINE_DISP_REG_L3_DISP_ADR1
, soffset
);
309 c_set_disp_reg(par
, CARMINE_DISP_REG_L4_DISP_ADR1
, soffset
);
310 c_set_disp_reg(par
, CARMINE_DISP_REG_L5_DISP_ADR1
, soffset
);
311 c_set_disp_reg(par
, CARMINE_DISP_REG_L6_DISP_ADR0
, soffset
);
312 c_set_disp_reg(par
, CARMINE_DISP_REG_L7_DISP_ADR0
, soffset
);
314 /* Set default display position */
315 c_set_disp_reg(par
, CARMINE_DISP_REG_L0_DISP_POS
, 0);
316 c_set_disp_reg(par
, CARMINE_DISP_REG_L2_DISP_POS
, 0);
317 c_set_disp_reg(par
, CARMINE_DISP_REG_L3_DISP_POS
, 0);
318 c_set_disp_reg(par
, CARMINE_DISP_REG_L4_DISP_POS
, 0);
319 c_set_disp_reg(par
, CARMINE_DISP_REG_L5_DISP_POS
, 0);
320 c_set_disp_reg(par
, CARMINE_DISP_REG_L6_DISP_POS
, 0);
321 c_set_disp_reg(par
, CARMINE_DISP_REG_L7_DISP_POS
, 0);
323 /* Set default blend mode */
324 c_set_disp_reg(par
, CARMINE_DISP_REG_BLEND_MODE_L0
, 0);
325 c_set_disp_reg(par
, CARMINE_DISP_REG_BLEND_MODE_L1
, 0);
326 c_set_disp_reg(par
, CARMINE_DISP_REG_BLEND_MODE_L2
, 0);
327 c_set_disp_reg(par
, CARMINE_DISP_REG_BLEND_MODE_L3
, 0);
328 c_set_disp_reg(par
, CARMINE_DISP_REG_BLEND_MODE_L4
, 0);
329 c_set_disp_reg(par
, CARMINE_DISP_REG_BLEND_MODE_L5
, 0);
330 c_set_disp_reg(par
, CARMINE_DISP_REG_BLEND_MODE_L6
, 0);
331 c_set_disp_reg(par
, CARMINE_DISP_REG_BLEND_MODE_L7
, 0);
333 /* default transparency mode */
334 c_set_disp_reg(par
, CARMINE_DISP_REG_L0_TRANS
, 0);
335 c_set_disp_reg(par
, CARMINE_DISP_REG_L1_TRANS
, 0);
336 c_set_disp_reg(par
, CARMINE_DISP_REG_L2_TRANS
, 0);
337 c_set_disp_reg(par
, CARMINE_DISP_REG_L3_TRANS
, 0);
338 c_set_disp_reg(par
, CARMINE_DISP_REG_L4_TRANS
, 0);
339 c_set_disp_reg(par
, CARMINE_DISP_REG_L5_TRANS
, 0);
340 c_set_disp_reg(par
, CARMINE_DISP_REG_L6_TRANS
, 0);
341 c_set_disp_reg(par
, CARMINE_DISP_REG_L7_TRANS
, 0);
343 /* Set default read skip parameter */
344 c_set_disp_reg(par
, CARMINE_DISP_REG_L0RM
, 0);
345 c_set_disp_reg(par
, CARMINE_DISP_REG_L2RM
, 0);
346 c_set_disp_reg(par
, CARMINE_DISP_REG_L3RM
, 0);
347 c_set_disp_reg(par
, CARMINE_DISP_REG_L4RM
, 0);
348 c_set_disp_reg(par
, CARMINE_DISP_REG_L5RM
, 0);
349 c_set_disp_reg(par
, CARMINE_DISP_REG_L6RM
, 0);
350 c_set_disp_reg(par
, CARMINE_DISP_REG_L7RM
, 0);
352 c_set_disp_reg(par
, CARMINE_DISP_REG_L0PX
, 0);
353 c_set_disp_reg(par
, CARMINE_DISP_REG_L2PX
, 0);
354 c_set_disp_reg(par
, CARMINE_DISP_REG_L3PX
, 0);
355 c_set_disp_reg(par
, CARMINE_DISP_REG_L4PX
, 0);
356 c_set_disp_reg(par
, CARMINE_DISP_REG_L5PX
, 0);
357 c_set_disp_reg(par
, CARMINE_DISP_REG_L6PX
, 0);
358 c_set_disp_reg(par
, CARMINE_DISP_REG_L7PX
, 0);
360 c_set_disp_reg(par
, CARMINE_DISP_REG_L0PY
, 0);
361 c_set_disp_reg(par
, CARMINE_DISP_REG_L2PY
, 0);
362 c_set_disp_reg(par
, CARMINE_DISP_REG_L3PY
, 0);
363 c_set_disp_reg(par
, CARMINE_DISP_REG_L4PY
, 0);
364 c_set_disp_reg(par
, CARMINE_DISP_REG_L5PY
, 0);
365 c_set_disp_reg(par
, CARMINE_DISP_REG_L6PY
, 0);
366 c_set_disp_reg(par
, CARMINE_DISP_REG_L7PY
, 0);
369 static void set_display_parameters(struct carmine_fb
*par
)
372 u32 hdp
, vdp
, htp
, hsp
, hsw
, vtr
, vsp
, vsw
;
375 * display timing. Parameters are decreased by one because hardware
376 * spec is 0 to (n - 1)
378 hdp
= par
->res
->hdp
- 1;
379 vdp
= par
->res
->vdp
- 1;
380 htp
= par
->res
->htp
- 1;
381 hsp
= par
->res
->hsp
- 1;
382 hsw
= par
->res
->hsw
- 1;
383 vtr
= par
->res
->vtr
- 1;
384 vsp
= par
->res
->vsp
- 1;
385 vsw
= par
->res
->vsw
- 1;
387 c_set_disp_reg(par
, CARMINE_DISP_REG_H_TOTAL
,
388 htp
<< CARMINE_DISP_HTP_SHIFT
);
389 c_set_disp_reg(par
, CARMINE_DISP_REG_H_PERIOD
,
390 (hdp
<< CARMINE_DISP_HDB_SHIFT
) | hdp
);
391 c_set_disp_reg(par
, CARMINE_DISP_REG_V_H_W_H_POS
,
392 (vsw
<< CARMINE_DISP_VSW_SHIFT
) |
393 (hsw
<< CARMINE_DISP_HSW_SHIFT
) |
395 c_set_disp_reg(par
, CARMINE_DISP_REG_V_TOTAL
,
396 vtr
<< CARMINE_DISP_VTR_SHIFT
);
397 c_set_disp_reg(par
, CARMINE_DISP_REG_V_PERIOD_POS
,
398 (vdp
<< CARMINE_DISP_VDP_SHIFT
) | vsp
);
401 mode
= c_get_disp_reg(par
, CARMINE_DISP_REG_DCM1
);
402 mode
= (mode
& ~CARMINE_DISP_DCM_MASK
) |
403 (par
->res
->disp_mode
& CARMINE_DISP_DCM_MASK
);
404 /* enable video output and layer 0 */
405 mode
|= CARMINE_DEN
| CARMINE_L0E
;
406 c_set_disp_reg(par
, CARMINE_DISP_REG_DCM1
, mode
);
409 static int carmine_set_par(struct fb_info
*info
)
411 struct carmine_fb
*par
= info
->par
;
414 ret
= carmine_find_mode(&info
->var
);
419 if (par
->cur_mode
!= par
->new_mode
) {
421 par
->cur_mode
= par
->new_mode
;
422 par
->res
= &car_modes
[par
->new_mode
];
424 carmine_init_display_param(par
);
425 set_display_parameters(par
);
428 info
->fix
.line_length
= info
->var
.xres
* info
->var
.bits_per_pixel
/ 8;
432 static int init_hardware(struct carmine_hw
*hw
)
438 /* Initialize Carmine */
439 /* Sets internal clock */
440 c_set_hw_reg(hw
, CARMINE_CTL_REG
+ CARMINE_CTL_REG_CLOCK_ENABLE
,
441 CARMINE_DFLT_IP_CLOCK_ENABLE
);
443 /* Video signal output is turned off */
444 c_set_hw_reg(hw
, CARMINE_DISP0_REG
+ CARMINE_DISP_REG_DCM1
, 0);
445 c_set_hw_reg(hw
, CARMINE_DISP1_REG
+ CARMINE_DISP_REG_DCM1
, 0);
448 c_set_hw_reg(hw
, CARMINE_CTL_REG
+ CARMINE_CTL_REG_SOFTWARE_RESET
, 1);
449 c_set_hw_reg(hw
, CARMINE_CTL_REG
+ CARMINE_CTL_REG_SOFTWARE_RESET
, 0);
451 /* I/O mode settings */
452 flags
= CARMINE_DFLT_IP_DCTL_IO_CONT1
<< 16 |
453 CARMINE_DFLT_IP_DCTL_IO_CONT0
;
454 c_set_hw_reg(hw
, CARMINE_DCTL_REG
+ CARMINE_DCTL_REG_IOCONT1_IOCONT0
,
457 /* DRAM initial sequence */
458 flags
= CARMINE_DFLT_IP_DCTL_MODE
<< 16 | CARMINE_DFLT_IP_DCTL_ADD
;
459 c_set_hw_reg(hw
, CARMINE_DCTL_REG
+ CARMINE_DCTL_REG_MODE_ADD
,
462 flags
= CARMINE_DFLT_IP_DCTL_SET_TIME1
<< 16 |
463 CARMINE_DFLT_IP_DCTL_EMODE
;
464 c_set_hw_reg(hw
, CARMINE_DCTL_REG
+ CARMINE_DCTL_REG_SETTIME1_EMODE
,
467 flags
= CARMINE_DFLT_IP_DCTL_REFRESH
<< 16 |
468 CARMINE_DFLT_IP_DCTL_SET_TIME2
;
469 c_set_hw_reg(hw
, CARMINE_DCTL_REG
+ CARMINE_DCTL_REG_REFRESH_SETTIME2
,
472 flags
= CARMINE_DFLT_IP_DCTL_RESERVE2
<< 16 |
473 CARMINE_DFLT_IP_DCTL_FIFO_DEPTH
;
474 c_set_hw_reg(hw
, CARMINE_DCTL_REG
+ CARMINE_DCTL_REG_RSV2_RSV1
, flags
);
476 flags
= CARMINE_DFLT_IP_DCTL_DDRIF2
<< 16 | CARMINE_DFLT_IP_DCTL_DDRIF1
;
477 c_set_hw_reg(hw
, CARMINE_DCTL_REG
+ CARMINE_DCTL_REG_DDRIF2_DDRIF1
,
480 flags
= CARMINE_DFLT_IP_DCTL_RESERVE0
<< 16 |
481 CARMINE_DFLT_IP_DCTL_STATES
;
482 c_set_hw_reg(hw
, CARMINE_DCTL_REG
+ CARMINE_DCTL_REG_RSV0_STATES
,
485 /* Executes DLL reset */
486 if (CARMINE_DCTL_DLL_RESET
) {
487 for (loops
= 0; loops
< CARMINE_DCTL_INIT_WAIT_LIMIT
; loops
++) {
489 ret
= c_get_hw_reg(hw
, CARMINE_DCTL_REG
+
490 CARMINE_DCTL_REG_RSV0_STATES
);
491 ret
&= CARMINE_DCTL_REG_STATES_MASK
;
495 mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL
);
498 if (loops
>= CARMINE_DCTL_INIT_WAIT_LIMIT
) {
499 printk(KERN_ERR
"DRAM init failed\n");
504 flags
= CARMINE_DFLT_IP_DCTL_MODE_AFT_RST
<< 16 |
505 CARMINE_DFLT_IP_DCTL_ADD
;
506 c_set_hw_reg(hw
, CARMINE_DCTL_REG
+ CARMINE_DCTL_REG_MODE_ADD
, flags
);
508 flags
= CARMINE_DFLT_IP_DCTL_RESERVE0
<< 16 |
509 CARMINE_DFLT_IP_DCTL_STATES_AFT_RST
;
510 c_set_hw_reg(hw
, CARMINE_DCTL_REG
+ CARMINE_DCTL_REG_RSV0_STATES
,
513 /* Initialize the write back register */
514 c_set_hw_reg(hw
, CARMINE_WB_REG
+ CARMINE_WB_REG_WBM
,
515 CARMINE_WB_REG_WBM_DEFAULT
);
517 /* Initialize the Kottos registers */
518 c_set_hw_reg(hw
, CARMINE_GRAPH_REG
+ CARMINE_GRAPH_REG_VRINTM
, 0);
519 c_set_hw_reg(hw
, CARMINE_GRAPH_REG
+ CARMINE_GRAPH_REG_VRERRM
, 0);
522 c_set_hw_reg(hw
, CARMINE_GRAPH_REG
+ CARMINE_GRAPH_REG_DC_OFFSET_PX
, 0);
523 c_set_hw_reg(hw
, CARMINE_GRAPH_REG
+ CARMINE_GRAPH_REG_DC_OFFSET_PY
, 0);
524 c_set_hw_reg(hw
, CARMINE_GRAPH_REG
+ CARMINE_GRAPH_REG_DC_OFFSET_LX
, 0);
525 c_set_hw_reg(hw
, CARMINE_GRAPH_REG
+ CARMINE_GRAPH_REG_DC_OFFSET_LY
, 0);
526 c_set_hw_reg(hw
, CARMINE_GRAPH_REG
+ CARMINE_GRAPH_REG_DC_OFFSET_TX
, 0);
527 c_set_hw_reg(hw
, CARMINE_GRAPH_REG
+ CARMINE_GRAPH_REG_DC_OFFSET_TY
, 0);
531 static const struct fb_ops carminefb_ops
= {
532 .owner
= THIS_MODULE
,
533 FB_DEFAULT_IOMEM_OPS
,
534 .fb_check_var
= carmine_check_var
,
535 .fb_set_par
= carmine_set_par
,
536 .fb_setcolreg
= carmine_setcolreg
,
539 static int alloc_carmine_fb(void __iomem
*regs
, void __iomem
*smem_base
,
540 int smem_offset
, struct device
*device
,
541 struct fb_info
**rinfo
)
544 struct fb_info
*info
;
545 struct carmine_fb
*par
;
547 info
= framebuffer_alloc(sizeof *par
, device
);
552 par
->display_reg
= regs
;
553 par
->smem_offset
= smem_offset
;
555 info
->screen_base
= smem_base
+ smem_offset
;
556 info
->screen_size
= CARMINE_DISPLAY_MEM
;
557 info
->fbops
= &carminefb_ops
;
559 info
->fix
= carminefb_fix
;
560 info
->pseudo_palette
= par
->pseudo_palette
;
562 ret
= fb_alloc_cmap(&info
->cmap
, 256, 1);
566 if (fb_mode
>= ARRAY_SIZE(carmine_modedb
))
567 fb_mode
= CARMINEFB_DEFAULT_VIDEO_MODE
;
569 par
->cur_mode
= par
->new_mode
= ~0;
571 ret
= fb_find_mode(&info
->var
, info
, fb_mode_str
, carmine_modedb
,
572 ARRAY_SIZE(carmine_modedb
),
573 &carmine_modedb
[fb_mode
], 32);
574 if (!ret
|| ret
== 4) {
576 goto err_dealloc_cmap
;
579 fb_videomode_to_modelist(carmine_modedb
, ARRAY_SIZE(carmine_modedb
),
582 ret
= register_framebuffer(info
);
584 goto err_dealloc_cmap
;
586 fb_info(info
, "%s frame buffer device\n", info
->fix
.id
);
592 fb_dealloc_cmap(&info
->cmap
);
594 framebuffer_release(info
);
598 static void cleanup_fb_device(struct fb_info
*info
)
601 unregister_framebuffer(info
);
602 fb_dealloc_cmap(&info
->cmap
);
603 framebuffer_release(info
);
607 static int carminefb_probe(struct pci_dev
*dev
, const struct pci_device_id
*ent
)
609 struct carmine_hw
*hw
;
610 struct device
*device
= &dev
->dev
;
611 struct fb_info
*info
;
614 ret
= aperture_remove_conflicting_pci_devices(dev
, "carminefb");
618 ret
= pci_enable_device(dev
);
623 hw
= kzalloc(sizeof *hw
, GFP_KERNEL
);
627 carminefb_fix
.mmio_start
= pci_resource_start(dev
, CARMINE_CONFIG_BAR
);
628 carminefb_fix
.mmio_len
= pci_resource_len(dev
, CARMINE_CONFIG_BAR
);
630 if (!request_mem_region(carminefb_fix
.mmio_start
,
631 carminefb_fix
.mmio_len
,
632 "carminefb regbase")) {
633 printk(KERN_ERR
"carminefb: Can't reserve regbase.\n");
637 hw
->v_regs
= ioremap(carminefb_fix
.mmio_start
,
638 carminefb_fix
.mmio_len
);
640 printk(KERN_ERR
"carminefb: Can't remap %s register.\n",
642 goto err_free_reg_mmio
;
645 carminefb_fix
.smem_start
= pci_resource_start(dev
, CARMINE_MEMORY_BAR
);
646 carminefb_fix
.smem_len
= pci_resource_len(dev
, CARMINE_MEMORY_BAR
);
648 /* The memory area tends to be very large (256 MiB). Remap only what
649 * is required for that largest resolution to avoid remaps at run
652 if (carminefb_fix
.smem_len
> CARMINE_TOTAL_DIPLAY_MEM
)
653 carminefb_fix
.smem_len
= CARMINE_TOTAL_DIPLAY_MEM
;
655 else if (carminefb_fix
.smem_len
< CARMINE_TOTAL_DIPLAY_MEM
) {
656 printk(KERN_ERR
"carminefb: Memory bar is only %d bytes, %d "
657 "are required.", carminefb_fix
.smem_len
,
658 CARMINE_TOTAL_DIPLAY_MEM
);
659 goto err_unmap_vregs
;
662 if (!request_mem_region(carminefb_fix
.smem_start
,
663 carminefb_fix
.smem_len
, "carminefb smem")) {
664 printk(KERN_ERR
"carminefb: Can't reserve smem.\n");
665 goto err_unmap_vregs
;
668 hw
->screen_mem
= ioremap(carminefb_fix
.smem_start
,
669 carminefb_fix
.smem_len
);
670 if (!hw
->screen_mem
) {
671 printk(KERN_ERR
"carmine: Can't ioremap smem area.\n");
675 ret
= init_hardware(hw
);
677 goto err_unmap_screen
;
680 if (fb_displays
& CARMINE_USE_DISPLAY0
) {
681 ret
= alloc_carmine_fb(hw
->v_regs
+ CARMINE_DISP0_REG
,
682 hw
->screen_mem
, CARMINE_DISPLAY_MEM
* 0,
691 if (fb_displays
& CARMINE_USE_DISPLAY1
) {
692 ret
= alloc_carmine_fb(hw
->v_regs
+ CARMINE_DISP1_REG
,
693 hw
->screen_mem
, CARMINE_DISPLAY_MEM
* 1,
696 goto err_cleanup_fb0
;
702 pci_set_drvdata(dev
, hw
);
706 cleanup_fb_device(hw
->fb
[0]);
708 /* disable clock, etc */
709 c_set_hw_reg(hw
, CARMINE_CTL_REG
+ CARMINE_CTL_REG_CLOCK_ENABLE
, 0);
711 iounmap(hw
->screen_mem
);
713 release_mem_region(carminefb_fix
.smem_start
, carminefb_fix
.smem_len
);
717 release_mem_region(carminefb_fix
.mmio_start
, carminefb_fix
.mmio_len
);
721 pci_disable_device(dev
);
725 static void carminefb_remove(struct pci_dev
*dev
)
727 struct carmine_hw
*hw
= pci_get_drvdata(dev
);
728 struct fb_fix_screeninfo fix
;
731 /* in case we use only fb1 and not fb1 */
733 fix
= hw
->fb
[0]->fix
;
735 fix
= hw
->fb
[1]->fix
;
737 /* deactivate display(s) and switch clocks */
738 c_set_hw_reg(hw
, CARMINE_DISP0_REG
+ CARMINE_DISP_REG_DCM1
, 0);
739 c_set_hw_reg(hw
, CARMINE_DISP1_REG
+ CARMINE_DISP_REG_DCM1
, 0);
740 c_set_hw_reg(hw
, CARMINE_CTL_REG
+ CARMINE_CTL_REG_CLOCK_ENABLE
, 0);
742 for (i
= 0; i
< MAX_DISPLAY
; i
++)
743 cleanup_fb_device(hw
->fb
[i
]);
745 iounmap(hw
->screen_mem
);
746 release_mem_region(fix
.smem_start
, fix
.smem_len
);
748 release_mem_region(fix
.mmio_start
, fix
.mmio_len
);
750 pci_disable_device(dev
);
754 #define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf
755 static struct pci_device_id carmine_devices
[] = {
757 PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED
, 0x202b)},
758 {0, 0, 0, 0, 0, 0, 0}
761 MODULE_DEVICE_TABLE(pci
, carmine_devices
);
763 static struct pci_driver carmine_pci_driver
= {
765 .id_table
= carmine_devices
,
766 .probe
= carminefb_probe
,
767 .remove
= carminefb_remove
,
770 static int __init
carminefb_init(void)
772 if (fb_modesetting_disabled("carminefb"))
776 (CARMINE_USE_DISPLAY0
| CARMINE_USE_DISPLAY1
))) {
777 printk(KERN_ERR
"If you disable both displays than you don't "
778 "need the driver at all\n");
781 return pci_register_driver(&carmine_pci_driver
);
783 module_init(carminefb_init
);
785 static void __exit
carminefb_cleanup(void)
787 pci_unregister_driver(&carmine_pci_driver
);
789 module_exit(carminefb_cleanup
);
791 MODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>");
792 MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices");
793 MODULE_LICENSE("GPL v2");