3 * Copyright 2012 Red Hat
5 * This file is subject to the terms and conditions of the GNU General
6 * Public License version 2. See the file COPYING in the main
7 * directory of this archive for more details.
9 * Authors: Matthew Garrett
12 * Portions of this code derived from cirrusfb.c:
13 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
15 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
18 #include <drm/drm_crtc_helper.h>
20 #include <video/cirrus.h>
22 #include "cirrus_drv.h"
24 #define CIRRUS_LUT_SIZE 256
26 #define PALETTE_INDEX 0x8
27 #define PALETTE_DATA 0x9
30 * This file contains setup code for the CRTC.
33 static void cirrus_crtc_load_lut(struct drm_crtc
*crtc
)
35 struct cirrus_crtc
*cirrus_crtc
= to_cirrus_crtc(crtc
);
36 struct drm_device
*dev
= crtc
->dev
;
37 struct cirrus_device
*cdev
= dev
->dev_private
;
43 for (i
= 0; i
< CIRRUS_LUT_SIZE
; i
++) {
45 WREG8(PALETTE_INDEX
, i
);
46 WREG8(PALETTE_DATA
, cirrus_crtc
->lut_r
[i
]);
47 WREG8(PALETTE_DATA
, cirrus_crtc
->lut_g
[i
]);
48 WREG8(PALETTE_DATA
, cirrus_crtc
->lut_b
[i
]);
53 * The DRM core requires DPMS functions, but they make little sense in our
54 * case and so are just stubs
57 static void cirrus_crtc_dpms(struct drm_crtc
*crtc
, int mode
)
59 struct drm_device
*dev
= crtc
->dev
;
60 struct cirrus_device
*cdev
= dev
->dev_private
;
64 case DRM_MODE_DPMS_ON
:
68 case DRM_MODE_DPMS_STANDBY
:
72 case DRM_MODE_DPMS_SUSPEND
:
76 case DRM_MODE_DPMS_OFF
:
84 WREG8(SEQ_INDEX
, 0x1);
85 sr01
|= RREG8(SEQ_DATA
) & ~0x20;
88 WREG8(GFX_INDEX
, 0xe);
89 gr0e
|= RREG8(GFX_DATA
) & ~0x06;
94 * The core passes the desired mode to the CRTC code to see whether any
95 * CRTC-specific modifications need to be made to it. We're in a position
96 * to just pass that straight through, so this does nothing
98 static bool cirrus_crtc_mode_fixup(struct drm_crtc
*crtc
,
99 const struct drm_display_mode
*mode
,
100 struct drm_display_mode
*adjusted_mode
)
105 void cirrus_set_start_address(struct drm_crtc
*crtc
, unsigned offset
)
107 struct cirrus_device
*cdev
= crtc
->dev
->dev_private
;
112 WREG_CRT(0x0c, (u8
)((addr
>> 8) & 0xff));
113 WREG_CRT(0x0d, (u8
)(addr
& 0xff));
115 WREG8(CRT_INDEX
, 0x1b);
116 tmp
= RREG8(CRT_DATA
);
118 tmp
|= (addr
>> 16) & 0x01;
119 tmp
|= (addr
>> 15) & 0x0c;
121 WREG8(CRT_INDEX
, 0x1d);
122 tmp
= RREG8(CRT_DATA
);
124 tmp
|= (addr
>> 12) & 0x80;
128 /* cirrus is different - we will force move buffers out of VRAM */
129 static int cirrus_crtc_do_set_base(struct drm_crtc
*crtc
,
130 struct drm_framebuffer
*fb
,
131 int x
, int y
, int atomic
)
133 struct cirrus_device
*cdev
= crtc
->dev
->dev_private
;
134 struct drm_gem_object
*obj
;
135 struct cirrus_framebuffer
*cirrus_fb
;
136 struct cirrus_bo
*bo
;
140 /* push the previous fb to system ram */
142 cirrus_fb
= to_cirrus_framebuffer(fb
);
143 obj
= cirrus_fb
->obj
;
144 bo
= gem_to_cirrus_bo(obj
);
145 ret
= cirrus_bo_reserve(bo
, false);
148 cirrus_bo_push_sysram(bo
);
149 cirrus_bo_unreserve(bo
);
152 cirrus_fb
= to_cirrus_framebuffer(crtc
->fb
);
153 obj
= cirrus_fb
->obj
;
154 bo
= gem_to_cirrus_bo(obj
);
156 ret
= cirrus_bo_reserve(bo
, false);
160 ret
= cirrus_bo_pin(bo
, TTM_PL_FLAG_VRAM
, &gpu_addr
);
162 cirrus_bo_unreserve(bo
);
166 if (&cdev
->mode_info
.gfbdev
->gfb
== cirrus_fb
) {
167 /* if pushing console in kmap it */
168 ret
= ttm_bo_kmap(&bo
->bo
, 0, bo
->bo
.num_pages
, &bo
->kmap
);
170 DRM_ERROR("failed to kmap fbcon\n");
172 cirrus_bo_unreserve(bo
);
174 cirrus_set_start_address(crtc
, (u32
)gpu_addr
);
178 static int cirrus_crtc_mode_set_base(struct drm_crtc
*crtc
, int x
, int y
,
179 struct drm_framebuffer
*old_fb
)
181 return cirrus_crtc_do_set_base(crtc
, old_fb
, x
, y
, 0);
185 * The meat of this driver. The core passes us a mode and we have to program
186 * it. The modesetting here is the bare minimum required to satisfy the qemu
187 * emulation of this hardware, and running this against a real device is
188 * likely to result in an inadequately programmed mode. We've already had
189 * the opportunity to modify the mode, so whatever we receive here should
190 * be something that can be correctly programmed and displayed
192 static int cirrus_crtc_mode_set(struct drm_crtc
*crtc
,
193 struct drm_display_mode
*mode
,
194 struct drm_display_mode
*adjusted_mode
,
195 int x
, int y
, struct drm_framebuffer
*old_fb
)
197 struct drm_device
*dev
= crtc
->dev
;
198 struct cirrus_device
*cdev
= dev
->dev_private
;
199 int hsyncstart
, hsyncend
, htotal
, hdispend
;
200 int vtotal
, vdispend
;
202 int sr07
= 0, hdr
= 0;
204 htotal
= mode
->htotal
/ 8;
205 hsyncend
= mode
->hsync_end
/ 8;
206 hsyncstart
= mode
->hsync_start
/ 8;
207 hdispend
= mode
->hdisplay
/ 8;
209 vtotal
= mode
->vtotal
;
210 vdispend
= mode
->vdisplay
;
220 WREG_CRT(VGA_CRTC_V_SYNC_END
, 0x20);
221 WREG_CRT(VGA_CRTC_H_TOTAL
, htotal
);
222 WREG_CRT(VGA_CRTC_H_DISP
, hdispend
);
223 WREG_CRT(VGA_CRTC_H_SYNC_START
, hsyncstart
);
224 WREG_CRT(VGA_CRTC_H_SYNC_END
, hsyncend
);
225 WREG_CRT(VGA_CRTC_V_TOTAL
, vtotal
& 0xff);
226 WREG_CRT(VGA_CRTC_V_DISP_END
, vdispend
& 0xff);
229 if ((vdispend
+ 1) & 512)
231 WREG_CRT(VGA_CRTC_MAX_SCAN
, tmp
);
234 * Overflow bits for values that don't fit in the standard registers
241 if ((vdispend
+ 1) & 256)
247 WREG_CRT(VGA_CRTC_OVERFLOW
, tmp
);
251 /* More overflow bits */
253 if ((htotal
+ 5) & 64)
255 if ((htotal
+ 5) & 128)
262 WREG_CRT(CL_CRT1A
, tmp
);
264 /* Disable Hercules/CGA compatibility */
265 WREG_CRT(VGA_CRTC_MODE
, 0x03);
267 WREG8(SEQ_INDEX
, 0x7);
268 sr07
= RREG8(SEQ_DATA
);
271 switch (crtc
->fb
->bits_per_pixel
) {
293 /* Program the pitch */
294 tmp
= crtc
->fb
->pitches
[0] / 8;
295 WREG_CRT(VGA_CRTC_OFFSET
, tmp
);
297 /* Enable extended blanking and pitch bits, and enable full memory */
299 tmp
|= (crtc
->fb
->pitches
[0] >> 7) & 0x10;
300 tmp
|= (crtc
->fb
->pitches
[0] >> 6) & 0x40;
303 /* Enable high-colour modes */
304 WREG_GFX(VGA_GFX_MODE
, 0x40);
306 /* And set graphics mode */
307 WREG_GFX(VGA_GFX_MISC
, 0x01);
310 cirrus_crtc_do_set_base(crtc
, old_fb
, x
, y
, 0);
312 /* Unblank (needed on S3 resume, vgabios doesn't do it then) */
318 * This is called before a mode is programmed. A typical use might be to
319 * enable DPMS during the programming to avoid seeing intermediate stages,
320 * but that's not relevant to us
322 static void cirrus_crtc_prepare(struct drm_crtc
*crtc
)
327 * This is called after a mode is programmed. It should reverse anything done
328 * by the prepare function
330 static void cirrus_crtc_commit(struct drm_crtc
*crtc
)
335 * The core can pass us a set of gamma values to program. We actually only
336 * use this for 8-bit mode so can't perform smooth fades on deeper modes,
337 * but it's a requirement that we provide the function
339 static void cirrus_crtc_gamma_set(struct drm_crtc
*crtc
, u16
*red
, u16
*green
,
340 u16
*blue
, uint32_t start
, uint32_t size
)
342 struct cirrus_crtc
*cirrus_crtc
= to_cirrus_crtc(crtc
);
345 if (size
!= CIRRUS_LUT_SIZE
)
348 for (i
= 0; i
< CIRRUS_LUT_SIZE
; i
++) {
349 cirrus_crtc
->lut_r
[i
] = red
[i
];
350 cirrus_crtc
->lut_g
[i
] = green
[i
];
351 cirrus_crtc
->lut_b
[i
] = blue
[i
];
353 cirrus_crtc_load_lut(crtc
);
356 /* Simple cleanup function */
357 static void cirrus_crtc_destroy(struct drm_crtc
*crtc
)
359 struct cirrus_crtc
*cirrus_crtc
= to_cirrus_crtc(crtc
);
361 drm_crtc_cleanup(crtc
);
365 /* These provide the minimum set of functions required to handle a CRTC */
366 static const struct drm_crtc_funcs cirrus_crtc_funcs
= {
367 .gamma_set
= cirrus_crtc_gamma_set
,
368 .set_config
= drm_crtc_helper_set_config
,
369 .destroy
= cirrus_crtc_destroy
,
372 static const struct drm_crtc_helper_funcs cirrus_helper_funcs
= {
373 .dpms
= cirrus_crtc_dpms
,
374 .mode_fixup
= cirrus_crtc_mode_fixup
,
375 .mode_set
= cirrus_crtc_mode_set
,
376 .mode_set_base
= cirrus_crtc_mode_set_base
,
377 .prepare
= cirrus_crtc_prepare
,
378 .commit
= cirrus_crtc_commit
,
379 .load_lut
= cirrus_crtc_load_lut
,
383 static void cirrus_crtc_init(struct drm_device
*dev
)
385 struct cirrus_device
*cdev
= dev
->dev_private
;
386 struct cirrus_crtc
*cirrus_crtc
;
389 cirrus_crtc
= kzalloc(sizeof(struct cirrus_crtc
) +
390 (CIRRUSFB_CONN_LIMIT
* sizeof(struct drm_connector
*)),
393 if (cirrus_crtc
== NULL
)
396 drm_crtc_init(dev
, &cirrus_crtc
->base
, &cirrus_crtc_funcs
);
398 drm_mode_crtc_set_gamma_size(&cirrus_crtc
->base
, CIRRUS_LUT_SIZE
);
399 cdev
->mode_info
.crtc
= cirrus_crtc
;
401 for (i
= 0; i
< CIRRUS_LUT_SIZE
; i
++) {
402 cirrus_crtc
->lut_r
[i
] = i
;
403 cirrus_crtc
->lut_g
[i
] = i
;
404 cirrus_crtc
->lut_b
[i
] = i
;
407 drm_crtc_helper_add(&cirrus_crtc
->base
, &cirrus_helper_funcs
);
410 /** Sets the color ramps on behalf of fbcon */
411 void cirrus_crtc_fb_gamma_set(struct drm_crtc
*crtc
, u16 red
, u16 green
,
414 struct cirrus_crtc
*cirrus_crtc
= to_cirrus_crtc(crtc
);
416 cirrus_crtc
->lut_r
[regno
] = red
;
417 cirrus_crtc
->lut_g
[regno
] = green
;
418 cirrus_crtc
->lut_b
[regno
] = blue
;
421 /** Gets the color ramps on behalf of fbcon */
422 void cirrus_crtc_fb_gamma_get(struct drm_crtc
*crtc
, u16
*red
, u16
*green
,
423 u16
*blue
, int regno
)
425 struct cirrus_crtc
*cirrus_crtc
= to_cirrus_crtc(crtc
);
427 *red
= cirrus_crtc
->lut_r
[regno
];
428 *green
= cirrus_crtc
->lut_g
[regno
];
429 *blue
= cirrus_crtc
->lut_b
[regno
];
433 static bool cirrus_encoder_mode_fixup(struct drm_encoder
*encoder
,
434 const struct drm_display_mode
*mode
,
435 struct drm_display_mode
*adjusted_mode
)
440 static void cirrus_encoder_mode_set(struct drm_encoder
*encoder
,
441 struct drm_display_mode
*mode
,
442 struct drm_display_mode
*adjusted_mode
)
446 static void cirrus_encoder_dpms(struct drm_encoder
*encoder
, int state
)
451 static void cirrus_encoder_prepare(struct drm_encoder
*encoder
)
455 static void cirrus_encoder_commit(struct drm_encoder
*encoder
)
459 void cirrus_encoder_destroy(struct drm_encoder
*encoder
)
461 struct cirrus_encoder
*cirrus_encoder
= to_cirrus_encoder(encoder
);
462 drm_encoder_cleanup(encoder
);
463 kfree(cirrus_encoder
);
466 static const struct drm_encoder_helper_funcs cirrus_encoder_helper_funcs
= {
467 .dpms
= cirrus_encoder_dpms
,
468 .mode_fixup
= cirrus_encoder_mode_fixup
,
469 .mode_set
= cirrus_encoder_mode_set
,
470 .prepare
= cirrus_encoder_prepare
,
471 .commit
= cirrus_encoder_commit
,
474 static const struct drm_encoder_funcs cirrus_encoder_encoder_funcs
= {
475 .destroy
= cirrus_encoder_destroy
,
478 static struct drm_encoder
*cirrus_encoder_init(struct drm_device
*dev
)
480 struct drm_encoder
*encoder
;
481 struct cirrus_encoder
*cirrus_encoder
;
483 cirrus_encoder
= kzalloc(sizeof(struct cirrus_encoder
), GFP_KERNEL
);
487 encoder
= &cirrus_encoder
->base
;
488 encoder
->possible_crtcs
= 0x1;
490 drm_encoder_init(dev
, encoder
, &cirrus_encoder_encoder_funcs
,
491 DRM_MODE_ENCODER_DAC
);
492 drm_encoder_helper_add(encoder
, &cirrus_encoder_helper_funcs
);
498 int cirrus_vga_get_modes(struct drm_connector
*connector
)
502 /* Just add a static list of modes */
503 count
= drm_add_modes_noedid(connector
, 1280, 1024);
504 drm_set_preferred_mode(connector
, 1024, 768);
508 static int cirrus_vga_mode_valid(struct drm_connector
*connector
,
509 struct drm_display_mode
*mode
)
511 /* Any mode we've added is valid */
515 struct drm_encoder
*cirrus_connector_best_encoder(struct drm_connector
518 int enc_id
= connector
->encoder_ids
[0];
519 struct drm_mode_object
*obj
;
520 struct drm_encoder
*encoder
;
522 /* pick the encoder ids */
525 drm_mode_object_find(connector
->dev
, enc_id
,
526 DRM_MODE_OBJECT_ENCODER
);
529 encoder
= obj_to_encoder(obj
);
535 static enum drm_connector_status
cirrus_vga_detect(struct drm_connector
536 *connector
, bool force
)
538 return connector_status_connected
;
541 static void cirrus_connector_destroy(struct drm_connector
*connector
)
543 drm_connector_cleanup(connector
);
547 struct drm_connector_helper_funcs cirrus_vga_connector_helper_funcs
= {
548 .get_modes
= cirrus_vga_get_modes
,
549 .mode_valid
= cirrus_vga_mode_valid
,
550 .best_encoder
= cirrus_connector_best_encoder
,
553 struct drm_connector_funcs cirrus_vga_connector_funcs
= {
554 .dpms
= drm_helper_connector_dpms
,
555 .detect
= cirrus_vga_detect
,
556 .fill_modes
= drm_helper_probe_single_connector_modes
,
557 .destroy
= cirrus_connector_destroy
,
560 static struct drm_connector
*cirrus_vga_init(struct drm_device
*dev
)
562 struct drm_connector
*connector
;
563 struct cirrus_connector
*cirrus_connector
;
565 cirrus_connector
= kzalloc(sizeof(struct cirrus_connector
), GFP_KERNEL
);
566 if (!cirrus_connector
)
569 connector
= &cirrus_connector
->base
;
571 drm_connector_init(dev
, connector
,
572 &cirrus_vga_connector_funcs
, DRM_MODE_CONNECTOR_VGA
);
574 drm_connector_helper_add(connector
, &cirrus_vga_connector_helper_funcs
);
580 int cirrus_modeset_init(struct cirrus_device
*cdev
)
582 struct drm_encoder
*encoder
;
583 struct drm_connector
*connector
;
586 drm_mode_config_init(cdev
->dev
);
587 cdev
->mode_info
.mode_config_initialized
= true;
589 cdev
->dev
->mode_config
.max_width
= CIRRUS_MAX_FB_WIDTH
;
590 cdev
->dev
->mode_config
.max_height
= CIRRUS_MAX_FB_HEIGHT
;
592 cdev
->dev
->mode_config
.fb_base
= cdev
->mc
.vram_base
;
593 cdev
->dev
->mode_config
.preferred_depth
= 24;
594 /* don't prefer a shadow on virt GPU */
595 cdev
->dev
->mode_config
.prefer_shadow
= 0;
597 cirrus_crtc_init(cdev
->dev
);
599 encoder
= cirrus_encoder_init(cdev
->dev
);
601 DRM_ERROR("cirrus_encoder_init failed\n");
605 connector
= cirrus_vga_init(cdev
->dev
);
607 DRM_ERROR("cirrus_vga_init failed\n");
611 drm_mode_connector_attach_encoder(connector
, encoder
);
613 ret
= cirrus_fbdev_init(cdev
);
615 DRM_ERROR("cirrus_fbdev_init failed\n");
622 void cirrus_modeset_fini(struct cirrus_device
*cdev
)
624 cirrus_fbdev_fini(cdev
);
626 if (cdev
->mode_info
.mode_config_initialized
) {
627 drm_mode_config_cleanup(cdev
->dev
);
628 cdev
->mode_info
.mode_config_initialized
= false;