linux/drivers/gpu/drm/cirrus/cirrus_mode.c
<<
>>
Prefs
   1
   2/*
   3 * Copyright 2012 Red Hat
   4 *
   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.
   8 *
   9 * Authors: Matthew Garrett
  10 *          Dave Airlie
  11 *
  12 * Portions of this code derived from cirrusfb.c:
  13 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
  14 *
  15 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
  16 */
  17#include <drm/drmP.h>
  18#include <drm/drm_crtc_helper.h>
  19
  20#include <video/cirrus.h>
  21
  22#include "cirrus_drv.h"
  23
  24#define CIRRUS_LUT_SIZE 256
  25
  26#define PALETTE_INDEX 0x8
  27#define PALETTE_DATA 0x9
  28
  29/*
  30 * This file contains setup code for the CRTC.
  31 */
  32
  33static void cirrus_crtc_load_lut(struct drm_crtc *crtc)
  34{
  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;
  38        int i;
  39
  40        if (!crtc->enabled)
  41                return;
  42
  43        for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
  44                /* VGA registers */
  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]);
  49        }
  50}
  51
  52/*
  53 * The DRM core requires DPMS functions, but they make little sense in our
  54 * case and so are just stubs
  55 */
  56
  57static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode)
  58{
  59        struct drm_device *dev = crtc->dev;
  60        struct cirrus_device *cdev = dev->dev_private;
  61        u8 sr01, gr0e;
  62
  63        switch (mode) {
  64        case DRM_MODE_DPMS_ON:
  65                sr01 = 0x00;
  66                gr0e = 0x00;
  67                break;
  68        case DRM_MODE_DPMS_STANDBY:
  69                sr01 = 0x20;
  70                gr0e = 0x02;
  71                break;
  72        case DRM_MODE_DPMS_SUSPEND:
  73                sr01 = 0x20;
  74                gr0e = 0x04;
  75                break;
  76        case DRM_MODE_DPMS_OFF:
  77                sr01 = 0x20;
  78                gr0e = 0x06;
  79                break;
  80        default:
  81                return;
  82        }
  83
  84        WREG8(SEQ_INDEX, 0x1);
  85        sr01 |= RREG8(SEQ_DATA) & ~0x20;
  86        WREG_SEQ(0x1, sr01);
  87
  88        WREG8(GFX_INDEX, 0xe);
  89        gr0e |= RREG8(GFX_DATA) & ~0x06;
  90        WREG_GFX(0xe, gr0e);
  91}
  92
  93/*
  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
  97 */
  98static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc,
  99                                   const struct drm_display_mode *mode,
 100                                   struct drm_display_mode *adjusted_mode)
 101{
 102        return true;
 103}
 104
 105void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset)
 106{
 107        struct cirrus_device *cdev = crtc->dev->dev_private;
 108        u32 addr;
 109        u8 tmp;
 110
 111        addr = offset >> 2;
 112        WREG_CRT(0x0c, (u8)((addr >> 8) & 0xff));
 113        WREG_CRT(0x0d, (u8)(addr & 0xff));
 114
 115        WREG8(CRT_INDEX, 0x1b);
 116        tmp = RREG8(CRT_DATA);
 117        tmp &= 0xf2;
 118        tmp |= (addr >> 16) & 0x01;
 119        tmp |= (addr >> 15) & 0x0c;
 120        WREG_CRT(0x1b, tmp);
 121        WREG8(CRT_INDEX, 0x1d);
 122        tmp = RREG8(CRT_DATA);
 123        tmp &= 0x7f;
 124        tmp |= (addr >> 12) & 0x80;
 125        WREG_CRT(0x1d, tmp);
 126}
 127
 128/* cirrus is different - we will force move buffers out of VRAM */
 129static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
 130                                struct drm_framebuffer *fb,
 131                                int x, int y, int atomic)
 132{
 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;
 137        int ret;
 138        u64 gpu_addr;
 139
 140        /* push the previous fb to system ram */
 141        if (!atomic && fb) {
 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);
 146                if (ret)
 147                        return ret;
 148                cirrus_bo_push_sysram(bo);
 149                cirrus_bo_unreserve(bo);
 150        }
 151
 152        cirrus_fb = to_cirrus_framebuffer(crtc->fb);
 153        obj = cirrus_fb->obj;
 154        bo = gem_to_cirrus_bo(obj);
 155
 156        ret = cirrus_bo_reserve(bo, false);
 157        if (ret)
 158                return ret;
 159
 160        ret = cirrus_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
 161        if (ret) {
 162                cirrus_bo_unreserve(bo);
 163                return ret;
 164        }
 165
 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);
 169                if (ret)
 170                        DRM_ERROR("failed to kmap fbcon\n");
 171        }
 172        cirrus_bo_unreserve(bo);
 173
 174        cirrus_set_start_address(crtc, (u32)gpu_addr);
 175        return 0;
 176}
 177
 178static int cirrus_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 179                             struct drm_framebuffer *old_fb)
 180{
 181        return cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
 182}
 183
 184/*
 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
 191 */
 192static 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)
 196{
 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;
 201        int tmp;
 202        int sr07 = 0, hdr = 0;
 203
 204        htotal = mode->htotal / 8;
 205        hsyncend = mode->hsync_end / 8;
 206        hsyncstart = mode->hsync_start / 8;
 207        hdispend = mode->hdisplay / 8;
 208
 209        vtotal = mode->vtotal;
 210        vdispend = mode->vdisplay;
 211
 212        vdispend -= 1;
 213        vtotal -= 2;
 214
 215        htotal -= 5;
 216        hdispend -= 1;
 217        hsyncstart += 1;
 218        hsyncend += 1;
 219
 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);
 227
 228        tmp = 0x40;
 229        if ((vdispend + 1) & 512)
 230                tmp |= 0x20;
 231        WREG_CRT(VGA_CRTC_MAX_SCAN, tmp);
 232
 233        /*
 234         * Overflow bits for values that don't fit in the standard registers
 235         */
 236        tmp = 16;
 237        if (vtotal & 256)
 238                tmp |= 1;
 239        if (vdispend & 256)
 240                tmp |= 2;
 241        if ((vdispend + 1) & 256)
 242                tmp |= 8;
 243        if (vtotal & 512)
 244                tmp |= 32;
 245        if (vdispend & 512)
 246                tmp |= 64;
 247        WREG_CRT(VGA_CRTC_OVERFLOW, tmp);
 248
 249        tmp = 0;
 250
 251        /* More overflow bits */
 252
 253        if ((htotal + 5) & 64)
 254                tmp |= 16;
 255        if ((htotal + 5) & 128)
 256                tmp |= 32;
 257        if (vtotal & 256)
 258                tmp |= 64;
 259        if (vtotal & 512)
 260                tmp |= 128;
 261
 262        WREG_CRT(CL_CRT1A, tmp);
 263
 264        /* Disable Hercules/CGA compatibility */
 265        WREG_CRT(VGA_CRTC_MODE, 0x03);
 266
 267        WREG8(SEQ_INDEX, 0x7);
 268        sr07 = RREG8(SEQ_DATA);
 269        sr07 &= 0xe0;
 270        hdr = 0;
 271        switch (crtc->fb->bits_per_pixel) {
 272        case 8:
 273                sr07 |= 0x11;
 274                break;
 275        case 16:
 276                sr07 |= 0xc1;
 277                hdr = 0xc0;
 278                break;
 279        case 24:
 280                sr07 |= 0x15;
 281                hdr = 0xc5;
 282                break;
 283        case 32:
 284                sr07 |= 0x19;
 285                hdr = 0xc5;
 286                break;
 287        default:
 288                return -1;
 289        }
 290
 291        WREG_SEQ(0x7, sr07);
 292
 293        /* Program the pitch */
 294        tmp = crtc->fb->pitches[0] / 8;
 295        WREG_CRT(VGA_CRTC_OFFSET, tmp);
 296
 297        /* Enable extended blanking and pitch bits, and enable full memory */
 298        tmp = 0x22;
 299        tmp |= (crtc->fb->pitches[0] >> 7) & 0x10;
 300        tmp |= (crtc->fb->pitches[0] >> 6) & 0x40;
 301        WREG_CRT(0x1b, tmp);
 302
 303        /* Enable high-colour modes */
 304        WREG_GFX(VGA_GFX_MODE, 0x40);
 305
 306        /* And set graphics mode */
 307        WREG_GFX(VGA_GFX_MISC, 0x01);
 308
 309        WREG_HDR(hdr);
 310        cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
 311        return 0;
 312}
 313
 314/*
 315 * This is called before a mode is programmed. A typical use might be to
 316 * enable DPMS during the programming to avoid seeing intermediate stages,
 317 * but that's not relevant to us
 318 */
 319static void cirrus_crtc_prepare(struct drm_crtc *crtc)
 320{
 321}
 322
 323/*
 324 * This is called after a mode is programmed. It should reverse anything done
 325 * by the prepare function
 326 */
 327static void cirrus_crtc_commit(struct drm_crtc *crtc)
 328{
 329}
 330
 331/*
 332 * The core can pass us a set of gamma values to program. We actually only
 333 * use this for 8-bit mode so can't perform smooth fades on deeper modes,
 334 * but it's a requirement that we provide the function
 335 */
 336static void cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
 337                                  u16 *blue, uint32_t start, uint32_t size)
 338{
 339        struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
 340        int i;
 341
 342        if (size != CIRRUS_LUT_SIZE)
 343                return;
 344
 345        for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
 346                cirrus_crtc->lut_r[i] = red[i];
 347                cirrus_crtc->lut_g[i] = green[i];
 348                cirrus_crtc->lut_b[i] = blue[i];
 349        }
 350        cirrus_crtc_load_lut(crtc);
 351}
 352
 353/* Simple cleanup function */
 354static void cirrus_crtc_destroy(struct drm_crtc *crtc)
 355{
 356        struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
 357
 358        drm_crtc_cleanup(crtc);
 359        kfree(cirrus_crtc);
 360}
 361
 362/* These provide the minimum set of functions required to handle a CRTC */
 363static const struct drm_crtc_funcs cirrus_crtc_funcs = {
 364        .gamma_set = cirrus_crtc_gamma_set,
 365        .set_config = drm_crtc_helper_set_config,
 366        .destroy = cirrus_crtc_destroy,
 367};
 368
 369static const struct drm_crtc_helper_funcs cirrus_helper_funcs = {
 370        .dpms = cirrus_crtc_dpms,
 371        .mode_fixup = cirrus_crtc_mode_fixup,
 372        .mode_set = cirrus_crtc_mode_set,
 373        .mode_set_base = cirrus_crtc_mode_set_base,
 374        .prepare = cirrus_crtc_prepare,
 375        .commit = cirrus_crtc_commit,
 376        .load_lut = cirrus_crtc_load_lut,
 377};
 378
 379/* CRTC setup */
 380static void cirrus_crtc_init(struct drm_device *dev)
 381{
 382        struct cirrus_device *cdev = dev->dev_private;
 383        struct cirrus_crtc *cirrus_crtc;
 384        int i;
 385
 386        cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) +
 387                              (CIRRUSFB_CONN_LIMIT * sizeof(struct drm_connector *)),
 388                              GFP_KERNEL);
 389
 390        if (cirrus_crtc == NULL)
 391                return;
 392
 393        drm_crtc_init(dev, &cirrus_crtc->base, &cirrus_crtc_funcs);
 394
 395        drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE);
 396        cdev->mode_info.crtc = cirrus_crtc;
 397
 398        for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
 399                cirrus_crtc->lut_r[i] = i;
 400                cirrus_crtc->lut_g[i] = i;
 401                cirrus_crtc->lut_b[i] = i;
 402        }
 403
 404        drm_crtc_helper_add(&cirrus_crtc->base, &cirrus_helper_funcs);
 405}
 406
 407/** Sets the color ramps on behalf of fbcon */
 408void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
 409                              u16 blue, int regno)
 410{
 411        struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
 412
 413        cirrus_crtc->lut_r[regno] = red;
 414        cirrus_crtc->lut_g[regno] = green;
 415        cirrus_crtc->lut_b[regno] = blue;
 416}
 417
 418/** Gets the color ramps on behalf of fbcon */
 419void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
 420                              u16 *blue, int regno)
 421{
 422        struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
 423
 424        *red = cirrus_crtc->lut_r[regno];
 425        *green = cirrus_crtc->lut_g[regno];
 426        *blue = cirrus_crtc->lut_b[regno];
 427}
 428
 429
 430static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder,
 431                                      const struct drm_display_mode *mode,
 432                                      struct drm_display_mode *adjusted_mode)
 433{
 434        return true;
 435}
 436
 437static void cirrus_encoder_mode_set(struct drm_encoder *encoder,
 438                                struct drm_display_mode *mode,
 439                                struct drm_display_mode *adjusted_mode)
 440{
 441}
 442
 443static void cirrus_encoder_dpms(struct drm_encoder *encoder, int state)
 444{
 445        return;
 446}
 447
 448static void cirrus_encoder_prepare(struct drm_encoder *encoder)
 449{
 450}
 451
 452static void cirrus_encoder_commit(struct drm_encoder *encoder)
 453{
 454}
 455
 456void cirrus_encoder_destroy(struct drm_encoder *encoder)
 457{
 458        struct cirrus_encoder *cirrus_encoder = to_cirrus_encoder(encoder);
 459        drm_encoder_cleanup(encoder);
 460        kfree(cirrus_encoder);
 461}
 462
 463static const struct drm_encoder_helper_funcs cirrus_encoder_helper_funcs = {
 464        .dpms = cirrus_encoder_dpms,
 465        .mode_fixup = cirrus_encoder_mode_fixup,
 466        .mode_set = cirrus_encoder_mode_set,
 467        .prepare = cirrus_encoder_prepare,
 468        .commit = cirrus_encoder_commit,
 469};
 470
 471static const struct drm_encoder_funcs cirrus_encoder_encoder_funcs = {
 472        .destroy = cirrus_encoder_destroy,
 473};
 474
 475static struct drm_encoder *cirrus_encoder_init(struct drm_device *dev)
 476{
 477        struct drm_encoder *encoder;
 478        struct cirrus_encoder *cirrus_encoder;
 479
 480        cirrus_encoder = kzalloc(sizeof(struct cirrus_encoder), GFP_KERNEL);
 481        if (!cirrus_encoder)
 482                return NULL;
 483
 484        encoder = &cirrus_encoder->base;
 485        encoder->possible_crtcs = 0x1;
 486
 487        drm_encoder_init(dev, encoder, &cirrus_encoder_encoder_funcs,
 488                         DRM_MODE_ENCODER_DAC);
 489        drm_encoder_helper_add(encoder, &cirrus_encoder_helper_funcs);
 490
 491        return encoder;
 492}
 493
 494
 495int cirrus_vga_get_modes(struct drm_connector *connector)
 496{
 497        /* Just add a static list of modes */
 498        drm_add_modes_noedid(connector, 640, 480);
 499        drm_add_modes_noedid(connector, 800, 600);
 500        drm_add_modes_noedid(connector, 1024, 768);
 501        drm_add_modes_noedid(connector, 1280, 1024);
 502
 503        return 4;
 504}
 505
 506static int cirrus_vga_mode_valid(struct drm_connector *connector,
 507                                 struct drm_display_mode *mode)
 508{
 509        /* Any mode we've added is valid */
 510        return MODE_OK;
 511}
 512
 513struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
 514                                                  *connector)
 515{
 516        int enc_id = connector->encoder_ids[0];
 517        struct drm_mode_object *obj;
 518        struct drm_encoder *encoder;
 519
 520        /* pick the encoder ids */
 521        if (enc_id) {
 522                obj =
 523                    drm_mode_object_find(connector->dev, enc_id,
 524                                         DRM_MODE_OBJECT_ENCODER);
 525                if (!obj)
 526                        return NULL;
 527                encoder = obj_to_encoder(obj);
 528                return encoder;
 529        }
 530        return NULL;
 531}
 532
 533static enum drm_connector_status cirrus_vga_detect(struct drm_connector
 534                                                   *connector, bool force)
 535{
 536        return connector_status_connected;
 537}
 538
 539static void cirrus_connector_destroy(struct drm_connector *connector)
 540{
 541        drm_connector_cleanup(connector);
 542        kfree(connector);
 543}
 544
 545struct drm_connector_helper_funcs cirrus_vga_connector_helper_funcs = {
 546        .get_modes = cirrus_vga_get_modes,
 547        .mode_valid = cirrus_vga_mode_valid,
 548        .best_encoder = cirrus_connector_best_encoder,
 549};
 550
 551struct drm_connector_funcs cirrus_vga_connector_funcs = {
 552        .dpms = drm_helper_connector_dpms,
 553        .detect = cirrus_vga_detect,
 554        .fill_modes = drm_helper_probe_single_connector_modes,
 555        .destroy = cirrus_connector_destroy,
 556};
 557
 558static struct drm_connector *cirrus_vga_init(struct drm_device *dev)
 559{
 560        struct drm_connector *connector;
 561        struct cirrus_connector *cirrus_connector;
 562
 563        cirrus_connector = kzalloc(sizeof(struct cirrus_connector), GFP_KERNEL);
 564        if (!cirrus_connector)
 565                return NULL;
 566
 567        connector = &cirrus_connector->base;
 568
 569        drm_connector_init(dev, connector,
 570                           &cirrus_vga_connector_funcs, DRM_MODE_CONNECTOR_VGA);
 571
 572        drm_connector_helper_add(connector, &cirrus_vga_connector_helper_funcs);
 573
 574        return connector;
 575}
 576
 577
 578int cirrus_modeset_init(struct cirrus_device *cdev)
 579{
 580        struct drm_encoder *encoder;
 581        struct drm_connector *connector;
 582        int ret;
 583
 584        drm_mode_config_init(cdev->dev);
 585        cdev->mode_info.mode_config_initialized = true;
 586
 587        cdev->dev->mode_config.max_width = CIRRUS_MAX_FB_WIDTH;
 588        cdev->dev->mode_config.max_height = CIRRUS_MAX_FB_HEIGHT;
 589
 590        cdev->dev->mode_config.fb_base = cdev->mc.vram_base;
 591        cdev->dev->mode_config.preferred_depth = 24;
 592        /* don't prefer a shadow on virt GPU */
 593        cdev->dev->mode_config.prefer_shadow = 0;
 594
 595        cirrus_crtc_init(cdev->dev);
 596
 597        encoder = cirrus_encoder_init(cdev->dev);
 598        if (!encoder) {
 599                DRM_ERROR("cirrus_encoder_init failed\n");
 600                return -1;
 601        }
 602
 603        connector = cirrus_vga_init(cdev->dev);
 604        if (!connector) {
 605                DRM_ERROR("cirrus_vga_init failed\n");
 606                return -1;
 607        }
 608
 609        drm_mode_connector_attach_encoder(connector, encoder);
 610
 611        ret = cirrus_fbdev_init(cdev);
 612        if (ret) {
 613                DRM_ERROR("cirrus_fbdev_init failed\n");
 614                return ret;
 615        }
 616
 617        return 0;
 618}
 619
 620void cirrus_modeset_fini(struct cirrus_device *cdev)
 621{
 622        cirrus_fbdev_fini(cdev);
 623
 624        if (cdev->mode_info.mode_config_initialized) {
 625                drm_mode_config_cleanup(cdev->dev);
 626                cdev->mode_info.mode_config_initialized = false;
 627        }
 628}
 629