linux/drivers/gpu/drm/ast/ast_mode.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Red Hat Inc.
   3 * Parts based on xf86-video-ast
   4 * Copyright (c) 2005 ASPEED Technology Inc.
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a
   7 * copy of this software and associated documentation files (the
   8 * "Software"), to deal in the Software without restriction, including
   9 * without limitation the rights to use, copy, modify, merge, publish,
  10 * distribute, sub license, and/or sell copies of the Software, and to
  11 * permit persons to whom the Software is furnished to do so, subject to
  12 * the following conditions:
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * The above copyright notice and this permission notice (including the
  23 * next paragraph) shall be included in all copies or substantial portions
  24 * of the Software.
  25 *
  26 */
  27/*
  28 * Authors: Dave Airlie <airlied@redhat.com>
  29 */
  30
  31#include <linux/export.h>
  32#include <linux/pci.h>
  33
  34#include <drm/drm_atomic.h>
  35#include <drm/drm_atomic_helper.h>
  36#include <drm/drm_atomic_state_helper.h>
  37#include <drm/drm_crtc.h>
  38#include <drm/drm_crtc_helper.h>
  39#include <drm/drm_fourcc.h>
  40#include <drm/drm_gem_framebuffer_helper.h>
  41#include <drm/drm_gem_vram_helper.h>
  42#include <drm/drm_plane_helper.h>
  43#include <drm/drm_probe_helper.h>
  44#include <drm/drm_simple_kms_helper.h>
  45
  46#include "ast_drv.h"
  47#include "ast_tables.h"
  48
  49static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
  50static void ast_i2c_destroy(struct ast_i2c_chan *i2c);
  51
  52static inline void ast_load_palette_index(struct ast_private *ast,
  53                                     u8 index, u8 red, u8 green,
  54                                     u8 blue)
  55{
  56        ast_io_write8(ast, AST_IO_DAC_INDEX_WRITE, index);
  57        ast_io_read8(ast, AST_IO_SEQ_PORT);
  58        ast_io_write8(ast, AST_IO_DAC_DATA, red);
  59        ast_io_read8(ast, AST_IO_SEQ_PORT);
  60        ast_io_write8(ast, AST_IO_DAC_DATA, green);
  61        ast_io_read8(ast, AST_IO_SEQ_PORT);
  62        ast_io_write8(ast, AST_IO_DAC_DATA, blue);
  63        ast_io_read8(ast, AST_IO_SEQ_PORT);
  64}
  65
  66static void ast_crtc_load_lut(struct ast_private *ast, struct drm_crtc *crtc)
  67{
  68        u16 *r, *g, *b;
  69        int i;
  70
  71        if (!crtc->enabled)
  72                return;
  73
  74        r = crtc->gamma_store;
  75        g = r + crtc->gamma_size;
  76        b = g + crtc->gamma_size;
  77
  78        for (i = 0; i < 256; i++)
  79                ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8);
  80}
  81
  82static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
  83                                    const struct drm_display_mode *mode,
  84                                    struct drm_display_mode *adjusted_mode,
  85                                    struct ast_vbios_mode_info *vbios_mode)
  86{
  87        u32 refresh_rate_index = 0, refresh_rate;
  88        const struct ast_vbios_enhtable *best = NULL;
  89        u32 hborder, vborder;
  90        bool check_sync;
  91
  92        switch (format->cpp[0] * 8) {
  93        case 8:
  94                vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
  95                break;
  96        case 16:
  97                vbios_mode->std_table = &vbios_stdtable[HiCModeIndex];
  98                break;
  99        case 24:
 100        case 32:
 101                vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex];
 102                break;
 103        default:
 104                return false;
 105        }
 106
 107        switch (mode->crtc_hdisplay) {
 108        case 640:
 109                vbios_mode->enh_table = &res_640x480[refresh_rate_index];
 110                break;
 111        case 800:
 112                vbios_mode->enh_table = &res_800x600[refresh_rate_index];
 113                break;
 114        case 1024:
 115                vbios_mode->enh_table = &res_1024x768[refresh_rate_index];
 116                break;
 117        case 1280:
 118                if (mode->crtc_vdisplay == 800)
 119                        vbios_mode->enh_table = &res_1280x800[refresh_rate_index];
 120                else
 121                        vbios_mode->enh_table = &res_1280x1024[refresh_rate_index];
 122                break;
 123        case 1360:
 124                vbios_mode->enh_table = &res_1360x768[refresh_rate_index];
 125                break;
 126        case 1440:
 127                vbios_mode->enh_table = &res_1440x900[refresh_rate_index];
 128                break;
 129        case 1600:
 130                if (mode->crtc_vdisplay == 900)
 131                        vbios_mode->enh_table = &res_1600x900[refresh_rate_index];
 132                else
 133                        vbios_mode->enh_table = &res_1600x1200[refresh_rate_index];
 134                break;
 135        case 1680:
 136                vbios_mode->enh_table = &res_1680x1050[refresh_rate_index];
 137                break;
 138        case 1920:
 139                if (mode->crtc_vdisplay == 1080)
 140                        vbios_mode->enh_table = &res_1920x1080[refresh_rate_index];
 141                else
 142                        vbios_mode->enh_table = &res_1920x1200[refresh_rate_index];
 143                break;
 144        default:
 145                return false;
 146        }
 147
 148        refresh_rate = drm_mode_vrefresh(mode);
 149        check_sync = vbios_mode->enh_table->flags & WideScreenMode;
 150
 151        while (1) {
 152                const struct ast_vbios_enhtable *loop = vbios_mode->enh_table;
 153
 154                while (loop->refresh_rate != 0xff) {
 155                        if ((check_sync) &&
 156                            (((mode->flags & DRM_MODE_FLAG_NVSYNC)  &&
 157                              (loop->flags & PVSync))  ||
 158                             ((mode->flags & DRM_MODE_FLAG_PVSYNC)  &&
 159                              (loop->flags & NVSync))  ||
 160                             ((mode->flags & DRM_MODE_FLAG_NHSYNC)  &&
 161                              (loop->flags & PHSync))  ||
 162                             ((mode->flags & DRM_MODE_FLAG_PHSYNC)  &&
 163                              (loop->flags & NHSync)))) {
 164                                loop++;
 165                                continue;
 166                        }
 167                        if (loop->refresh_rate <= refresh_rate
 168                            && (!best || loop->refresh_rate > best->refresh_rate))
 169                                best = loop;
 170                        loop++;
 171                }
 172                if (best || !check_sync)
 173                        break;
 174                check_sync = 0;
 175        }
 176
 177        if (best)
 178                vbios_mode->enh_table = best;
 179
 180        hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0;
 181        vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0;
 182
 183        adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht;
 184        adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder;
 185        adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder;
 186        adjusted_mode->crtc_hsync_start = vbios_mode->enh_table->hde + hborder +
 187                vbios_mode->enh_table->hfp;
 188        adjusted_mode->crtc_hsync_end = (vbios_mode->enh_table->hde + hborder +
 189                                         vbios_mode->enh_table->hfp +
 190                                         vbios_mode->enh_table->hsync);
 191
 192        adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt;
 193        adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder;
 194        adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder;
 195        adjusted_mode->crtc_vsync_start = vbios_mode->enh_table->vde + vborder +
 196                vbios_mode->enh_table->vfp;
 197        adjusted_mode->crtc_vsync_end = (vbios_mode->enh_table->vde + vborder +
 198                                         vbios_mode->enh_table->vfp +
 199                                         vbios_mode->enh_table->vsync);
 200
 201        return true;
 202}
 203
 204static void ast_set_vbios_color_reg(struct ast_private *ast,
 205                                    const struct drm_format_info *format,
 206                                    const struct ast_vbios_mode_info *vbios_mode)
 207{
 208        u32 color_index;
 209
 210        switch (format->cpp[0]) {
 211        case 1:
 212                color_index = VGAModeIndex - 1;
 213                break;
 214        case 2:
 215                color_index = HiCModeIndex;
 216                break;
 217        case 3:
 218        case 4:
 219                color_index = TrueCModeIndex;
 220                break;
 221        default:
 222                return;
 223        }
 224
 225        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0x0f) << 4));
 226
 227        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00);
 228
 229        if (vbios_mode->enh_table->flags & NewModeInfo) {
 230                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
 231                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, format->cpp[0] * 8);
 232        }
 233}
 234
 235static void ast_set_vbios_mode_reg(struct ast_private *ast,
 236                                   const struct drm_display_mode *adjusted_mode,
 237                                   const struct ast_vbios_mode_info *vbios_mode)
 238{
 239        u32 refresh_rate_index, mode_id;
 240
 241        refresh_rate_index = vbios_mode->enh_table->refresh_rate_index;
 242        mode_id = vbios_mode->enh_table->mode_id;
 243
 244        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff);
 245        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);
 246
 247        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00);
 248
 249        if (vbios_mode->enh_table->flags & NewModeInfo) {
 250                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
 251                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
 252                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
 253                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8);
 254                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay);
 255                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8);
 256        }
 257}
 258
 259static void ast_set_std_reg(struct ast_private *ast,
 260                            struct drm_display_mode *mode,
 261                            struct ast_vbios_mode_info *vbios_mode)
 262{
 263        const struct ast_vbios_stdtable *stdtable;
 264        u32 i;
 265        u8 jreg;
 266
 267        stdtable = vbios_mode->std_table;
 268
 269        jreg = stdtable->misc;
 270        ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
 271
 272        /* Set SEQ; except Screen Disable field */
 273        ast_set_index_reg(ast, AST_IO_SEQ_PORT, 0x00, 0x03);
 274        ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, stdtable->seq[0]);
 275        for (i = 1; i < 4; i++) {
 276                jreg = stdtable->seq[i];
 277                ast_set_index_reg(ast, AST_IO_SEQ_PORT, (i + 1) , jreg);
 278        }
 279
 280        /* Set CRTC; except base address and offset */
 281        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00);
 282        for (i = 0; i < 12; i++)
 283                ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]);
 284        for (i = 14; i < 19; i++)
 285                ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]);
 286        for (i = 20; i < 25; i++)
 287                ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]);
 288
 289        /* set AR */
 290        jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ);
 291        for (i = 0; i < 20; i++) {
 292                jreg = stdtable->ar[i];
 293                ast_io_write8(ast, AST_IO_AR_PORT_WRITE, (u8)i);
 294                ast_io_write8(ast, AST_IO_AR_PORT_WRITE, jreg);
 295        }
 296        ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x14);
 297        ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x00);
 298
 299        jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ);
 300        ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x20);
 301
 302        /* Set GR */
 303        for (i = 0; i < 9; i++)
 304                ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]);
 305}
 306
 307static void ast_set_crtc_reg(struct ast_private *ast,
 308                             struct drm_display_mode *mode,
 309                             struct ast_vbios_mode_info *vbios_mode)
 310{
 311        u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0;
 312        u16 temp, precache = 0;
 313
 314        if ((ast->chip == AST2500) &&
 315            (vbios_mode->enh_table->flags & AST2500PreCatchCRT))
 316                precache = 40;
 317
 318        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00);
 319
 320        temp = (mode->crtc_htotal >> 3) - 5;
 321        if (temp & 0x100)
 322                jregAC |= 0x01; /* HT D[8] */
 323        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x00, 0x00, temp);
 324
 325        temp = (mode->crtc_hdisplay >> 3) - 1;
 326        if (temp & 0x100)
 327                jregAC |= 0x04; /* HDE D[8] */
 328        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x01, 0x00, temp);
 329
 330        temp = (mode->crtc_hblank_start >> 3) - 1;
 331        if (temp & 0x100)
 332                jregAC |= 0x10; /* HBS D[8] */
 333        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x02, 0x00, temp);
 334
 335        temp = ((mode->crtc_hblank_end >> 3) - 1) & 0x7f;
 336        if (temp & 0x20)
 337                jreg05 |= 0x80;  /* HBE D[5] */
 338        if (temp & 0x40)
 339                jregAD |= 0x01;  /* HBE D[5] */
 340        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x03, 0xE0, (temp & 0x1f));
 341
 342        temp = ((mode->crtc_hsync_start-precache) >> 3) - 1;
 343        if (temp & 0x100)
 344                jregAC |= 0x40; /* HRS D[5] */
 345        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x04, 0x00, temp);
 346
 347        temp = (((mode->crtc_hsync_end-precache) >> 3) - 1) & 0x3f;
 348        if (temp & 0x20)
 349                jregAD |= 0x04; /* HRE D[5] */
 350        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05));
 351
 352        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAC, 0x00, jregAC);
 353        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAD, 0x00, jregAD);
 354
 355        /* vert timings */
 356        temp = (mode->crtc_vtotal) - 2;
 357        if (temp & 0x100)
 358                jreg07 |= 0x01;
 359        if (temp & 0x200)
 360                jreg07 |= 0x20;
 361        if (temp & 0x400)
 362                jregAE |= 0x01;
 363        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x06, 0x00, temp);
 364
 365        temp = (mode->crtc_vsync_start) - 1;
 366        if (temp & 0x100)
 367                jreg07 |= 0x04;
 368        if (temp & 0x200)
 369                jreg07 |= 0x80;
 370        if (temp & 0x400)
 371                jregAE |= 0x08;
 372        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x10, 0x00, temp);
 373
 374        temp = (mode->crtc_vsync_end - 1) & 0x3f;
 375        if (temp & 0x10)
 376                jregAE |= 0x20;
 377        if (temp & 0x20)
 378                jregAE |= 0x40;
 379        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x70, temp & 0xf);
 380
 381        temp = mode->crtc_vdisplay - 1;
 382        if (temp & 0x100)
 383                jreg07 |= 0x02;
 384        if (temp & 0x200)
 385                jreg07 |= 0x40;
 386        if (temp & 0x400)
 387                jregAE |= 0x02;
 388        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x12, 0x00, temp);
 389
 390        temp = mode->crtc_vblank_start - 1;
 391        if (temp & 0x100)
 392                jreg07 |= 0x08;
 393        if (temp & 0x200)
 394                jreg09 |= 0x20;
 395        if (temp & 0x400)
 396                jregAE |= 0x04;
 397        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x15, 0x00, temp);
 398
 399        temp = mode->crtc_vblank_end - 1;
 400        if (temp & 0x100)
 401                jregAE |= 0x10;
 402        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x16, 0x00, temp);
 403
 404        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x07, 0x00, jreg07);
 405        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x09, 0xdf, jreg09);
 406        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAE, 0x00, (jregAE | 0x80));
 407
 408        if (precache)
 409                ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x80);
 410        else
 411                ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x00);
 412
 413        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80);
 414}
 415
 416static void ast_set_offset_reg(struct ast_private *ast,
 417                               struct drm_framebuffer *fb)
 418{
 419        u16 offset;
 420
 421        offset = fb->pitches[0] >> 3;
 422        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff));
 423        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);
 424}
 425
 426static void ast_set_dclk_reg(struct ast_private *ast,
 427                             struct drm_display_mode *mode,
 428                             struct ast_vbios_mode_info *vbios_mode)
 429{
 430        const struct ast_vbios_dclk_info *clk_info;
 431
 432        if (ast->chip == AST2500)
 433                clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index];
 434        else
 435                clk_info = &dclk_table[vbios_mode->enh_table->dclk_index];
 436
 437        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc0, 0x00, clk_info->param1);
 438        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc1, 0x00, clk_info->param2);
 439        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xbb, 0x0f,
 440                               (clk_info->param3 & 0xc0) |
 441                               ((clk_info->param3 & 0x3) << 4));
 442}
 443
 444static void ast_set_color_reg(struct ast_private *ast,
 445                              const struct drm_format_info *format)
 446{
 447        u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;
 448
 449        switch (format->cpp[0] * 8) {
 450        case 8:
 451                jregA0 = 0x70;
 452                jregA3 = 0x01;
 453                jregA8 = 0x00;
 454                break;
 455        case 15:
 456        case 16:
 457                jregA0 = 0x70;
 458                jregA3 = 0x04;
 459                jregA8 = 0x02;
 460                break;
 461        case 32:
 462                jregA0 = 0x70;
 463                jregA3 = 0x08;
 464                jregA8 = 0x02;
 465                break;
 466        }
 467
 468        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa0, 0x8f, jregA0);
 469        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xf0, jregA3);
 470        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8);
 471}
 472
 473static void ast_set_crtthd_reg(struct ast_private *ast)
 474{
 475        /* Set Threshold */
 476        if (ast->chip == AST2300 || ast->chip == AST2400 ||
 477            ast->chip == AST2500) {
 478                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);
 479                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);
 480        } else if (ast->chip == AST2100 ||
 481                   ast->chip == AST1100 ||
 482                   ast->chip == AST2200 ||
 483                   ast->chip == AST2150) {
 484                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x3f);
 485                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x2f);
 486        } else {
 487                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x2f);
 488                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x1f);
 489        }
 490}
 491
 492static void ast_set_sync_reg(struct ast_private *ast,
 493                             struct drm_display_mode *mode,
 494                             struct ast_vbios_mode_info *vbios_mode)
 495{
 496        u8 jreg;
 497
 498        jreg  = ast_io_read8(ast, AST_IO_MISC_PORT_READ);
 499        jreg &= ~0xC0;
 500        if (vbios_mode->enh_table->flags & NVSync) jreg |= 0x80;
 501        if (vbios_mode->enh_table->flags & NHSync) jreg |= 0x40;
 502        ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
 503}
 504
 505static void ast_set_start_address_crt1(struct ast_private *ast,
 506                                       unsigned offset)
 507{
 508        u32 addr;
 509
 510        addr = offset >> 2;
 511        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0d, (u8)(addr & 0xff));
 512        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0c, (u8)((addr >> 8) & 0xff));
 513        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xaf, (u8)((addr >> 16) & 0xff));
 514
 515}
 516
 517static void ast_wait_for_vretrace(struct ast_private *ast)
 518{
 519        unsigned long timeout = jiffies + HZ;
 520        u8 vgair1;
 521
 522        do {
 523                vgair1 = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ);
 524        } while (!(vgair1 & AST_IO_VGAIR1_VREFRESH) && time_before(jiffies, timeout));
 525}
 526
 527/*
 528 * Primary plane
 529 */
 530
 531static const uint32_t ast_primary_plane_formats[] = {
 532        DRM_FORMAT_XRGB8888,
 533        DRM_FORMAT_RGB565,
 534        DRM_FORMAT_C8,
 535};
 536
 537static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
 538                                                 struct drm_plane_state *state)
 539{
 540        struct drm_crtc_state *crtc_state;
 541        struct ast_crtc_state *ast_crtc_state;
 542        int ret;
 543
 544        if (!state->crtc)
 545                return 0;
 546
 547        crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc);
 548
 549        ret = drm_atomic_helper_check_plane_state(state, crtc_state,
 550                                                  DRM_PLANE_HELPER_NO_SCALING,
 551                                                  DRM_PLANE_HELPER_NO_SCALING,
 552                                                  false, true);
 553        if (ret)
 554                return ret;
 555
 556        if (!state->visible)
 557                return 0;
 558
 559        ast_crtc_state = to_ast_crtc_state(crtc_state);
 560
 561        ast_crtc_state->format = state->fb->format;
 562
 563        return 0;
 564}
 565
 566static void
 567ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
 568                                       struct drm_plane_state *old_state)
 569{
 570        struct drm_device *dev = plane->dev;
 571        struct ast_private *ast = to_ast_private(dev);
 572        struct drm_plane_state *state = plane->state;
 573        struct drm_gem_vram_object *gbo;
 574        s64 gpu_addr;
 575        struct drm_framebuffer *fb = state->fb;
 576        struct drm_framebuffer *old_fb = old_state->fb;
 577
 578        if (!old_fb || (fb->format != old_fb->format)) {
 579                struct drm_crtc_state *crtc_state = state->crtc->state;
 580                struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
 581                struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
 582
 583                ast_set_color_reg(ast, fb->format);
 584                ast_set_vbios_color_reg(ast, fb->format, vbios_mode_info);
 585        }
 586
 587        gbo = drm_gem_vram_of_gem(fb->obj[0]);
 588        gpu_addr = drm_gem_vram_offset(gbo);
 589        if (drm_WARN_ON_ONCE(dev, gpu_addr < 0))
 590                return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */
 591
 592        ast_set_offset_reg(ast, fb);
 593        ast_set_start_address_crt1(ast, (u32)gpu_addr);
 594
 595        ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00);
 596}
 597
 598static void
 599ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
 600                                        struct drm_plane_state *old_state)
 601{
 602        struct ast_private *ast = to_ast_private(plane->dev);
 603
 604        ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20);
 605}
 606
 607static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {
 608        .prepare_fb = drm_gem_vram_plane_helper_prepare_fb,
 609        .cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb,
 610        .atomic_check = ast_primary_plane_helper_atomic_check,
 611        .atomic_update = ast_primary_plane_helper_atomic_update,
 612        .atomic_disable = ast_primary_plane_helper_atomic_disable,
 613};
 614
 615static const struct drm_plane_funcs ast_primary_plane_funcs = {
 616        .update_plane = drm_atomic_helper_update_plane,
 617        .disable_plane = drm_atomic_helper_disable_plane,
 618        .destroy = drm_plane_cleanup,
 619        .reset = drm_atomic_helper_plane_reset,
 620        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
 621        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 622};
 623
 624/*
 625 * Cursor plane
 626 */
 627
 628static const uint32_t ast_cursor_plane_formats[] = {
 629        DRM_FORMAT_ARGB8888,
 630};
 631
 632static int
 633ast_cursor_plane_helper_prepare_fb(struct drm_plane *plane,
 634                                   struct drm_plane_state *new_state)
 635{
 636        struct drm_framebuffer *fb = new_state->fb;
 637        struct drm_crtc *crtc = new_state->crtc;
 638        struct ast_private *ast;
 639        int ret;
 640
 641        if (!crtc || !fb)
 642                return 0;
 643
 644        ast = to_ast_private(plane->dev);
 645
 646        ret = ast_cursor_blit(ast, fb);
 647        if (ret)
 648                return ret;
 649
 650        return 0;
 651}
 652
 653static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
 654                                                struct drm_plane_state *state)
 655{
 656        struct drm_framebuffer *fb = state->fb;
 657        struct drm_crtc_state *crtc_state;
 658        int ret;
 659
 660        if (!state->crtc)
 661                return 0;
 662
 663        crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc);
 664
 665        ret = drm_atomic_helper_check_plane_state(state, crtc_state,
 666                                                  DRM_PLANE_HELPER_NO_SCALING,
 667                                                  DRM_PLANE_HELPER_NO_SCALING,
 668                                                  true, true);
 669        if (ret)
 670                return ret;
 671
 672        if (!state->visible)
 673                return 0;
 674
 675        if (fb->width > AST_MAX_HWC_WIDTH || fb->height > AST_MAX_HWC_HEIGHT)
 676                return -EINVAL;
 677
 678        return 0;
 679}
 680
 681static void
 682ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
 683                                      struct drm_plane_state *old_state)
 684{
 685        struct drm_plane_state *state = plane->state;
 686        struct drm_framebuffer *fb = state->fb;
 687        struct ast_private *ast = to_ast_private(plane->dev);
 688        unsigned int offset_x, offset_y;
 689
 690        offset_x = AST_MAX_HWC_WIDTH - fb->width;
 691        offset_y = AST_MAX_HWC_WIDTH - fb->height;
 692
 693        if (state->fb != old_state->fb) {
 694                /* A new cursor image was installed. */
 695                ast_cursor_page_flip(ast);
 696        }
 697
 698        ast_cursor_show(ast, state->crtc_x, state->crtc_y,
 699                        offset_x, offset_y);
 700}
 701
 702static void
 703ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
 704                                       struct drm_plane_state *old_state)
 705{
 706        struct ast_private *ast = to_ast_private(plane->dev);
 707
 708        ast_cursor_hide(ast);
 709}
 710
 711static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = {
 712        .prepare_fb = ast_cursor_plane_helper_prepare_fb,
 713        .cleanup_fb = NULL, /* not required for cursor plane */
 714        .atomic_check = ast_cursor_plane_helper_atomic_check,
 715        .atomic_update = ast_cursor_plane_helper_atomic_update,
 716        .atomic_disable = ast_cursor_plane_helper_atomic_disable,
 717};
 718
 719static const struct drm_plane_funcs ast_cursor_plane_funcs = {
 720        .update_plane = drm_atomic_helper_update_plane,
 721        .disable_plane = drm_atomic_helper_disable_plane,
 722        .destroy = drm_plane_cleanup,
 723        .reset = drm_atomic_helper_plane_reset,
 724        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
 725        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 726};
 727
 728/*
 729 * CRTC
 730 */
 731
 732static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
 733{
 734        struct ast_private *ast = to_ast_private(crtc->dev);
 735
 736        /* TODO: Maybe control display signal generation with
 737         *       Sync Enable (bit CR17.7).
 738         */
 739        switch (mode) {
 740        case DRM_MODE_DPMS_ON:
 741        case DRM_MODE_DPMS_STANDBY:
 742        case DRM_MODE_DPMS_SUSPEND:
 743                if (ast->tx_chip_type == AST_TX_DP501)
 744                        ast_set_dp501_video_output(crtc->dev, 1);
 745                break;
 746        case DRM_MODE_DPMS_OFF:
 747                if (ast->tx_chip_type == AST_TX_DP501)
 748                        ast_set_dp501_video_output(crtc->dev, 0);
 749                break;
 750        }
 751}
 752
 753static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
 754                                        struct drm_atomic_state *state)
 755{
 756        struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
 757                                                                          crtc);
 758        struct drm_device *dev = crtc->dev;
 759        struct ast_crtc_state *ast_state;
 760        const struct drm_format_info *format;
 761        bool succ;
 762
 763        if (!crtc_state->enable)
 764                return 0; /* no mode checks if CRTC is being disabled */
 765
 766        ast_state = to_ast_crtc_state(crtc_state);
 767
 768        format = ast_state->format;
 769        if (drm_WARN_ON_ONCE(dev, !format))
 770                return -EINVAL; /* BUG: We didn't set format in primary check(). */
 771
 772        succ = ast_get_vbios_mode_info(format, &crtc_state->mode,
 773                                       &crtc_state->adjusted_mode,
 774                                       &ast_state->vbios_mode_info);
 775        if (!succ)
 776                return -EINVAL;
 777
 778        return 0;
 779}
 780
 781static void
 782ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 783                             struct drm_atomic_state *state)
 784{
 785        struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
 786                                                                          crtc);
 787        struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,
 788                                                                              crtc);
 789        struct ast_private *ast = to_ast_private(crtc->dev);
 790        struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
 791        struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
 792
 793        /*
 794         * The gamma LUT has to be reloaded after changing the primary
 795         * plane's color format.
 796         */
 797        if (old_ast_crtc_state->format != ast_crtc_state->format)
 798                ast_crtc_load_lut(ast, crtc);
 799}
 800
 801static void
 802ast_crtc_helper_atomic_enable(struct drm_crtc *crtc,
 803                              struct drm_atomic_state *state)
 804{
 805        struct drm_device *dev = crtc->dev;
 806        struct ast_private *ast = to_ast_private(dev);
 807        struct drm_crtc_state *crtc_state = crtc->state;
 808        struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
 809        struct ast_vbios_mode_info *vbios_mode_info =
 810                &ast_crtc_state->vbios_mode_info;
 811        struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
 812
 813        ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
 814        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
 815        ast_set_std_reg(ast, adjusted_mode, vbios_mode_info);
 816        ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info);
 817        ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info);
 818        ast_set_crtthd_reg(ast);
 819        ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info);
 820
 821        ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
 822}
 823
 824static void
 825ast_crtc_helper_atomic_disable(struct drm_crtc *crtc,
 826                               struct drm_atomic_state *state)
 827{
 828        struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,
 829                                                                              crtc);
 830        struct drm_device *dev = crtc->dev;
 831        struct ast_private *ast = to_ast_private(dev);
 832
 833        ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 834
 835        /*
 836         * HW cursors require the underlying primary plane and CRTC to
 837         * display a valid mode and image. This is not the case during
 838         * full modeset operations. So we temporarily disable any active
 839         * plane, including the HW cursor. Each plane's atomic_update()
 840         * helper will re-enable it if necessary.
 841         *
 842         * We only do this during *full* modesets. It does not affect
 843         * simple pageflips on the planes.
 844         */
 845        drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false);
 846
 847        /*
 848         * Ensure that no scanout takes place before reprogramming mode
 849         * and format registers.
 850         */
 851        ast_wait_for_vretrace(ast);
 852}
 853
 854static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
 855        .atomic_check = ast_crtc_helper_atomic_check,
 856        .atomic_flush = ast_crtc_helper_atomic_flush,
 857        .atomic_enable = ast_crtc_helper_atomic_enable,
 858        .atomic_disable = ast_crtc_helper_atomic_disable,
 859};
 860
 861static void ast_crtc_reset(struct drm_crtc *crtc)
 862{
 863        struct ast_crtc_state *ast_state =
 864                kzalloc(sizeof(*ast_state), GFP_KERNEL);
 865
 866        if (crtc->state)
 867                crtc->funcs->atomic_destroy_state(crtc, crtc->state);
 868
 869        __drm_atomic_helper_crtc_reset(crtc, &ast_state->base);
 870}
 871
 872static struct drm_crtc_state *
 873ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
 874{
 875        struct ast_crtc_state *new_ast_state, *ast_state;
 876        struct drm_device *dev = crtc->dev;
 877
 878        if (drm_WARN_ON(dev, !crtc->state))
 879                return NULL;
 880
 881        new_ast_state = kmalloc(sizeof(*new_ast_state), GFP_KERNEL);
 882        if (!new_ast_state)
 883                return NULL;
 884        __drm_atomic_helper_crtc_duplicate_state(crtc, &new_ast_state->base);
 885
 886        ast_state = to_ast_crtc_state(crtc->state);
 887
 888        new_ast_state->format = ast_state->format;
 889        memcpy(&new_ast_state->vbios_mode_info, &ast_state->vbios_mode_info,
 890               sizeof(new_ast_state->vbios_mode_info));
 891
 892        return &new_ast_state->base;
 893}
 894
 895static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc,
 896                                          struct drm_crtc_state *state)
 897{
 898        struct ast_crtc_state *ast_state = to_ast_crtc_state(state);
 899
 900        __drm_atomic_helper_crtc_destroy_state(&ast_state->base);
 901        kfree(ast_state);
 902}
 903
 904static const struct drm_crtc_funcs ast_crtc_funcs = {
 905        .reset = ast_crtc_reset,
 906        .destroy = drm_crtc_cleanup,
 907        .set_config = drm_atomic_helper_set_config,
 908        .page_flip = drm_atomic_helper_page_flip,
 909        .atomic_duplicate_state = ast_crtc_atomic_duplicate_state,
 910        .atomic_destroy_state = ast_crtc_atomic_destroy_state,
 911};
 912
 913static int ast_crtc_init(struct drm_device *dev)
 914{
 915        struct ast_private *ast = to_ast_private(dev);
 916        struct drm_crtc *crtc = &ast->crtc;
 917        int ret;
 918
 919        ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane,
 920                                        &ast->cursor_plane, &ast_crtc_funcs,
 921                                        NULL);
 922        if (ret)
 923                return ret;
 924
 925        drm_mode_crtc_set_gamma_size(crtc, 256);
 926        drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs);
 927
 928        return 0;
 929}
 930
 931/*
 932 * Encoder
 933 */
 934
 935static int ast_encoder_init(struct drm_device *dev)
 936{
 937        struct ast_private *ast = to_ast_private(dev);
 938        struct drm_encoder *encoder = &ast->encoder;
 939        int ret;
 940
 941        ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC);
 942        if (ret)
 943                return ret;
 944
 945        encoder->possible_crtcs = 1;
 946
 947        return 0;
 948}
 949
 950/*
 951 * Connector
 952 */
 953
 954static int ast_get_modes(struct drm_connector *connector)
 955{
 956        struct ast_connector *ast_connector = to_ast_connector(connector);
 957        struct ast_private *ast = to_ast_private(connector->dev);
 958        struct edid *edid;
 959        int ret;
 960        bool flags = false;
 961        if (ast->tx_chip_type == AST_TX_DP501) {
 962                ast->dp501_maxclk = 0xff;
 963                edid = kmalloc(128, GFP_KERNEL);
 964                if (!edid)
 965                        return -ENOMEM;
 966
 967                flags = ast_dp501_read_edid(connector->dev, (u8 *)edid);
 968                if (flags)
 969                        ast->dp501_maxclk = ast_get_dp501_max_clk(connector->dev);
 970                else
 971                        kfree(edid);
 972        }
 973        if (!flags)
 974                edid = drm_get_edid(connector, &ast_connector->i2c->adapter);
 975        if (edid) {
 976                drm_connector_update_edid_property(&ast_connector->base, edid);
 977                ret = drm_add_edid_modes(connector, edid);
 978                kfree(edid);
 979                return ret;
 980        } else
 981                drm_connector_update_edid_property(&ast_connector->base, NULL);
 982        return 0;
 983}
 984
 985static enum drm_mode_status ast_mode_valid(struct drm_connector *connector,
 986                          struct drm_display_mode *mode)
 987{
 988        struct ast_private *ast = to_ast_private(connector->dev);
 989        int flags = MODE_NOMODE;
 990        uint32_t jtemp;
 991
 992        if (ast->support_wide_screen) {
 993                if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050))
 994                        return MODE_OK;
 995                if ((mode->hdisplay == 1280) && (mode->vdisplay == 800))
 996                        return MODE_OK;
 997                if ((mode->hdisplay == 1440) && (mode->vdisplay == 900))
 998                        return MODE_OK;
 999                if ((mode->hdisplay == 1360) && (mode->vdisplay == 768))
1000                        return MODE_OK;
1001                if ((mode->hdisplay == 1600) && (mode->vdisplay == 900))
1002                        return MODE_OK;
1003
1004                if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
1005                    (ast->chip == AST2300) || (ast->chip == AST2400) ||
1006                    (ast->chip == AST2500)) {
1007                        if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
1008                                return MODE_OK;
1009
1010                        if ((mode->hdisplay == 1920) && (mode->vdisplay == 1200)) {
1011                                jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
1012                                if (jtemp & 0x01)
1013                                        return MODE_NOMODE;
1014                                else
1015                                        return MODE_OK;
1016                        }
1017                }
1018        }
1019        switch (mode->hdisplay) {
1020        case 640:
1021                if (mode->vdisplay == 480) flags = MODE_OK;
1022                break;
1023        case 800:
1024                if (mode->vdisplay == 600) flags = MODE_OK;
1025                break;
1026        case 1024:
1027                if (mode->vdisplay == 768) flags = MODE_OK;
1028                break;
1029        case 1280:
1030                if (mode->vdisplay == 1024) flags = MODE_OK;
1031                break;
1032        case 1600:
1033                if (mode->vdisplay == 1200) flags = MODE_OK;
1034                break;
1035        default:
1036                return flags;
1037        }
1038
1039        return flags;
1040}
1041
1042static void ast_connector_destroy(struct drm_connector *connector)
1043{
1044        struct ast_connector *ast_connector = to_ast_connector(connector);
1045        ast_i2c_destroy(ast_connector->i2c);
1046        drm_connector_cleanup(connector);
1047}
1048
1049static const struct drm_connector_helper_funcs ast_connector_helper_funcs = {
1050        .get_modes = ast_get_modes,
1051        .mode_valid = ast_mode_valid,
1052};
1053
1054static const struct drm_connector_funcs ast_connector_funcs = {
1055        .reset = drm_atomic_helper_connector_reset,
1056        .fill_modes = drm_helper_probe_single_connector_modes,
1057        .destroy = ast_connector_destroy,
1058        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1059        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1060};
1061
1062static int ast_connector_init(struct drm_device *dev)
1063{
1064        struct ast_private *ast = to_ast_private(dev);
1065        struct ast_connector *ast_connector = &ast->connector;
1066        struct drm_connector *connector = &ast_connector->base;
1067        struct drm_encoder *encoder = &ast->encoder;
1068
1069        ast_connector->i2c = ast_i2c_create(dev);
1070        if (!ast_connector->i2c)
1071                drm_err(dev, "failed to add ddc bus for connector\n");
1072
1073        drm_connector_init_with_ddc(dev, connector,
1074                                    &ast_connector_funcs,
1075                                    DRM_MODE_CONNECTOR_VGA,
1076                                    &ast_connector->i2c->adapter);
1077
1078        drm_connector_helper_add(connector, &ast_connector_helper_funcs);
1079
1080        connector->interlace_allowed = 0;
1081        connector->doublescan_allowed = 0;
1082
1083        connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1084
1085        drm_connector_attach_encoder(connector, encoder);
1086
1087        return 0;
1088}
1089
1090/*
1091 * Mode config
1092 */
1093
1094static const struct drm_mode_config_helper_funcs
1095ast_mode_config_helper_funcs = {
1096        .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
1097};
1098
1099static const struct drm_mode_config_funcs ast_mode_config_funcs = {
1100        .fb_create = drm_gem_fb_create,
1101        .mode_valid = drm_vram_helper_mode_valid,
1102        .atomic_check = drm_atomic_helper_check,
1103        .atomic_commit = drm_atomic_helper_commit,
1104};
1105
1106int ast_mode_config_init(struct ast_private *ast)
1107{
1108        struct drm_device *dev = &ast->base;
1109        struct pci_dev *pdev = to_pci_dev(dev->dev);
1110        int ret;
1111
1112        ret = ast_cursor_init(ast);
1113        if (ret)
1114                return ret;
1115
1116        ret = drmm_mode_config_init(dev);
1117        if (ret)
1118                return ret;
1119
1120        dev->mode_config.funcs = &ast_mode_config_funcs;
1121        dev->mode_config.min_width = 0;
1122        dev->mode_config.min_height = 0;
1123        dev->mode_config.preferred_depth = 24;
1124        dev->mode_config.prefer_shadow = 1;
1125        dev->mode_config.fb_base = pci_resource_start(pdev, 0);
1126
1127        if (ast->chip == AST2100 ||
1128            ast->chip == AST2200 ||
1129            ast->chip == AST2300 ||
1130            ast->chip == AST2400 ||
1131            ast->chip == AST2500) {
1132                dev->mode_config.max_width = 1920;
1133                dev->mode_config.max_height = 2048;
1134        } else {
1135                dev->mode_config.max_width = 1600;
1136                dev->mode_config.max_height = 1200;
1137        }
1138
1139        dev->mode_config.helper_private = &ast_mode_config_helper_funcs;
1140
1141        memset(&ast->primary_plane, 0, sizeof(ast->primary_plane));
1142        ret = drm_universal_plane_init(dev, &ast->primary_plane, 0x01,
1143                                       &ast_primary_plane_funcs,
1144                                       ast_primary_plane_formats,
1145                                       ARRAY_SIZE(ast_primary_plane_formats),
1146                                       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
1147        if (ret) {
1148                drm_err(dev, "ast: drm_universal_plane_init() failed: %d\n", ret);
1149                return ret;
1150        }
1151        drm_plane_helper_add(&ast->primary_plane,
1152                             &ast_primary_plane_helper_funcs);
1153
1154        ret = drm_universal_plane_init(dev, &ast->cursor_plane, 0x01,
1155                                       &ast_cursor_plane_funcs,
1156                                       ast_cursor_plane_formats,
1157                                       ARRAY_SIZE(ast_cursor_plane_formats),
1158                                       NULL, DRM_PLANE_TYPE_CURSOR, NULL);
1159        if (ret) {
1160                drm_err(dev, "drm_universal_plane_failed(): %d\n", ret);
1161                return ret;
1162        }
1163        drm_plane_helper_add(&ast->cursor_plane,
1164                             &ast_cursor_plane_helper_funcs);
1165
1166        ast_crtc_init(dev);
1167        ast_encoder_init(dev);
1168        ast_connector_init(dev);
1169
1170        drm_mode_config_reset(dev);
1171
1172        return 0;
1173}
1174
1175static int get_clock(void *i2c_priv)
1176{
1177        struct ast_i2c_chan *i2c = i2c_priv;
1178        struct ast_private *ast = to_ast_private(i2c->dev);
1179        uint32_t val, val2, count, pass;
1180
1181        count = 0;
1182        pass = 0;
1183        val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
1184        do {
1185                val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
1186                if (val == val2) {
1187                        pass++;
1188                } else {
1189                        pass = 0;
1190                        val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
1191                }
1192        } while ((pass < 5) && (count++ < 0x10000));
1193
1194        return val & 1 ? 1 : 0;
1195}
1196
1197static int get_data(void *i2c_priv)
1198{
1199        struct ast_i2c_chan *i2c = i2c_priv;
1200        struct ast_private *ast = to_ast_private(i2c->dev);
1201        uint32_t val, val2, count, pass;
1202
1203        count = 0;
1204        pass = 0;
1205        val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
1206        do {
1207                val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
1208                if (val == val2) {
1209                        pass++;
1210                } else {
1211                        pass = 0;
1212                        val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
1213                }
1214        } while ((pass < 5) && (count++ < 0x10000));
1215
1216        return val & 1 ? 1 : 0;
1217}
1218
1219static void set_clock(void *i2c_priv, int clock)
1220{
1221        struct ast_i2c_chan *i2c = i2c_priv;
1222        struct ast_private *ast = to_ast_private(i2c->dev);
1223        int i;
1224        u8 ujcrb7, jtemp;
1225
1226        for (i = 0; i < 0x10000; i++) {
1227                ujcrb7 = ((clock & 0x01) ? 0 : 1);
1228                ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7);
1229                jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01);
1230                if (ujcrb7 == jtemp)
1231                        break;
1232        }
1233}
1234
1235static void set_data(void *i2c_priv, int data)
1236{
1237        struct ast_i2c_chan *i2c = i2c_priv;
1238        struct ast_private *ast = to_ast_private(i2c->dev);
1239        int i;
1240        u8 ujcrb7, jtemp;
1241
1242        for (i = 0; i < 0x10000; i++) {
1243                ujcrb7 = ((data & 0x01) ? 0 : 1) << 2;
1244                ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7);
1245                jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04);
1246                if (ujcrb7 == jtemp)
1247                        break;
1248        }
1249}
1250
1251static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev)
1252{
1253        struct ast_i2c_chan *i2c;
1254        int ret;
1255
1256        i2c = kzalloc(sizeof(struct ast_i2c_chan), GFP_KERNEL);
1257        if (!i2c)
1258                return NULL;
1259
1260        i2c->adapter.owner = THIS_MODULE;
1261        i2c->adapter.class = I2C_CLASS_DDC;
1262        i2c->adapter.dev.parent = dev->dev;
1263        i2c->dev = dev;
1264        i2c_set_adapdata(&i2c->adapter, i2c);
1265        snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
1266                 "AST i2c bit bus");
1267        i2c->adapter.algo_data = &i2c->bit;
1268
1269        i2c->bit.udelay = 20;
1270        i2c->bit.timeout = 2;
1271        i2c->bit.data = i2c;
1272        i2c->bit.setsda = set_data;
1273        i2c->bit.setscl = set_clock;
1274        i2c->bit.getsda = get_data;
1275        i2c->bit.getscl = get_clock;
1276        ret = i2c_bit_add_bus(&i2c->adapter);
1277        if (ret) {
1278                drm_err(dev, "Failed to register bit i2c\n");
1279                goto out_free;
1280        }
1281
1282        return i2c;
1283out_free:
1284        kfree(i2c);
1285        return NULL;
1286}
1287
1288static void ast_i2c_destroy(struct ast_i2c_chan *i2c)
1289{
1290        if (!i2c)
1291                return;
1292        i2c_del_adapter(&i2c->adapter);
1293        kfree(i2c);
1294}
1295