linux/drivers/gpu/drm/ast/ast_dp501.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <linux/delay.h>
   4#include <linux/firmware.h>
   5#include <linux/module.h>
   6
   7#include "ast_drv.h"
   8
   9MODULE_FIRMWARE("ast_dp501_fw.bin");
  10
  11static void ast_release_firmware(void *data)
  12{
  13        struct ast_private *ast = data;
  14
  15        release_firmware(ast->dp501_fw);
  16        ast->dp501_fw = NULL;
  17}
  18
  19static int ast_load_dp501_microcode(struct drm_device *dev)
  20{
  21        struct ast_private *ast = to_ast_private(dev);
  22        int ret;
  23
  24        ret = request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev);
  25        if (ret)
  26                return ret;
  27
  28        return devm_add_action_or_reset(dev->dev, ast_release_firmware, ast);
  29}
  30
  31static void send_ack(struct ast_private *ast)
  32{
  33        u8 sendack;
  34        sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);
  35        sendack |= 0x80;
  36        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);
  37}
  38
  39static void send_nack(struct ast_private *ast)
  40{
  41        u8 sendack;
  42        sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff);
  43        sendack &= ~0x80;
  44        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack);
  45}
  46
  47static bool wait_ack(struct ast_private *ast)
  48{
  49        u8 waitack;
  50        u32 retry = 0;
  51        do {
  52                waitack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 0xff);
  53                waitack &= 0x80;
  54                udelay(100);
  55        } while ((!waitack) && (retry++ < 1000));
  56
  57        if (retry < 1000)
  58                return true;
  59        else
  60                return false;
  61}
  62
  63static bool wait_nack(struct ast_private *ast)
  64{
  65        u8 waitack;
  66        u32 retry = 0;
  67        do {
  68                waitack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 0xff);
  69                waitack &= 0x80;
  70                udelay(100);
  71        } while ((waitack) && (retry++ < 1000));
  72
  73        if (retry < 1000)
  74                return true;
  75        else
  76                return false;
  77}
  78
  79static void set_cmd_trigger(struct ast_private *ast)
  80{
  81        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x40);
  82}
  83
  84static void clear_cmd_trigger(struct ast_private *ast)
  85{
  86        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x00);
  87}
  88
  89#if 0
  90static bool wait_fw_ready(struct ast_private *ast)
  91{
  92        u8 waitready;
  93        u32 retry = 0;
  94        do {
  95                waitready = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd2, 0xff);
  96                waitready &= 0x40;
  97                udelay(100);
  98        } while ((!waitready) && (retry++ < 1000));
  99
 100        if (retry < 1000)
 101                return true;
 102        else
 103                return false;
 104}
 105#endif
 106
 107static bool ast_write_cmd(struct drm_device *dev, u8 data)
 108{
 109        struct ast_private *ast = to_ast_private(dev);
 110        int retry = 0;
 111        if (wait_nack(ast)) {
 112                send_nack(ast);
 113                ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data);
 114                send_ack(ast);
 115                set_cmd_trigger(ast);
 116                do {
 117                        if (wait_ack(ast)) {
 118                                clear_cmd_trigger(ast);
 119                                send_nack(ast);
 120                                return true;
 121                        }
 122                } while (retry++ < 100);
 123        }
 124        clear_cmd_trigger(ast);
 125        send_nack(ast);
 126        return false;
 127}
 128
 129static bool ast_write_data(struct drm_device *dev, u8 data)
 130{
 131        struct ast_private *ast = to_ast_private(dev);
 132
 133        if (wait_nack(ast)) {
 134                send_nack(ast);
 135                ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data);
 136                send_ack(ast);
 137                if (wait_ack(ast)) {
 138                        send_nack(ast);
 139                        return true;
 140                }
 141        }
 142        send_nack(ast);
 143        return false;
 144}
 145
 146#if 0
 147static bool ast_read_data(struct drm_device *dev, u8 *data)
 148{
 149        struct ast_private *ast = to_ast_private(dev);
 150        u8 tmp;
 151
 152        *data = 0;
 153
 154        if (wait_ack(ast) == false)
 155                return false;
 156        tmp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd3, 0xff);
 157        *data = tmp;
 158        if (wait_nack(ast) == false) {
 159                send_nack(ast);
 160                return false;
 161        }
 162        send_nack(ast);
 163        return true;
 164}
 165
 166static void clear_cmd(struct ast_private *ast)
 167{
 168        send_nack(ast);
 169        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, 0x00);
 170}
 171#endif
 172
 173void ast_set_dp501_video_output(struct drm_device *dev, u8 mode)
 174{
 175        ast_write_cmd(dev, 0x40);
 176        ast_write_data(dev, mode);
 177
 178        msleep(10);
 179}
 180
 181static u32 get_fw_base(struct ast_private *ast)
 182{
 183        return ast_mindwm(ast, 0x1e6e2104) & 0x7fffffff;
 184}
 185
 186bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size)
 187{
 188        struct ast_private *ast = to_ast_private(dev);
 189        u32 i, data;
 190        u32 boot_address;
 191
 192        if (ast->config_mode != ast_use_p2a)
 193                return false;
 194
 195        data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
 196        if (data) {
 197                boot_address = get_fw_base(ast);
 198                for (i = 0; i < size; i += 4)
 199                        *(u32 *)(addr + i) = ast_mindwm(ast, boot_address + i);
 200                return true;
 201        }
 202        return false;
 203}
 204
 205static bool ast_launch_m68k(struct drm_device *dev)
 206{
 207        struct ast_private *ast = to_ast_private(dev);
 208        u32 i, data, len = 0;
 209        u32 boot_address;
 210        u8 *fw_addr = NULL;
 211        u8 jreg;
 212
 213        if (ast->config_mode != ast_use_p2a)
 214                return false;
 215
 216        data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
 217        if (!data) {
 218
 219                if (ast->dp501_fw_addr) {
 220                        fw_addr = ast->dp501_fw_addr;
 221                        len = 32*1024;
 222                } else {
 223                        if (!ast->dp501_fw &&
 224                            ast_load_dp501_microcode(dev) < 0)
 225                                return false;
 226
 227                        fw_addr = (u8 *)ast->dp501_fw->data;
 228                        len = ast->dp501_fw->size;
 229                }
 230                /* Get BootAddress */
 231                ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
 232                data = ast_mindwm(ast, 0x1e6e0004);
 233                switch (data & 0x03) {
 234                case 0:
 235                        boot_address = 0x44000000;
 236                        break;
 237                default:
 238                case 1:
 239                        boot_address = 0x48000000;
 240                        break;
 241                case 2:
 242                        boot_address = 0x50000000;
 243                        break;
 244                case 3:
 245                        boot_address = 0x60000000;
 246                        break;
 247                }
 248                boot_address -= 0x200000; /* -2MB */
 249
 250                /* copy image to buffer */
 251                for (i = 0; i < len; i += 4) {
 252                        data = *(u32 *)(fw_addr + i);
 253                        ast_moutdwm(ast, boot_address + i, data);
 254                }
 255
 256                /* Init SCU */
 257                ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
 258
 259                /* Launch FW */
 260                ast_moutdwm(ast, 0x1e6e2104, 0x80000000 + boot_address);
 261                ast_moutdwm(ast, 0x1e6e2100, 1);
 262
 263                /* Update Scratch */
 264                data = ast_mindwm(ast, 0x1e6e2040) & 0xfffff1ff;                /* D[11:9] = 100b: UEFI handling */
 265                data |= 0x800;
 266                ast_moutdwm(ast, 0x1e6e2040, data);
 267
 268                jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 0xfc); /* D[1:0]: Reserved Video Buffer */
 269                jreg |= 0x02;
 270                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x99, jreg);
 271        }
 272        return true;
 273}
 274
 275u8 ast_get_dp501_max_clk(struct drm_device *dev)
 276{
 277        struct ast_private *ast = to_ast_private(dev);
 278        u32 boot_address, offset, data;
 279        u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
 280        u32 *plinkcap;
 281
 282        if (ast->config_mode == ast_use_p2a) {
 283                boot_address = get_fw_base(ast);
 284
 285                /* validate FW version */
 286                offset = AST_DP501_GBL_VERSION;
 287                data = ast_mindwm(ast, boot_address + offset);
 288                if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */
 289                        return maxclk;
 290
 291                /* Read Link Capability */
 292                offset  = AST_DP501_LINKRATE;
 293                plinkcap = (u32 *)linkcap;
 294                *plinkcap  = ast_mindwm(ast, boot_address + offset);
 295                if (linkcap[2] == 0) {
 296                        linkrate = linkcap[0];
 297                        linklanes = linkcap[1];
 298                        data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
 299                        if (data > 0xff)
 300                                data = 0xff;
 301                        maxclk = (u8)data;
 302                }
 303        } else {
 304                if (!ast->dp501_fw_buf)
 305                        return AST_DP501_DEFAULT_DCLK;  /* 1024x768 as default */
 306
 307                /* dummy read */
 308                offset = 0x0000;
 309                data = readl(ast->dp501_fw_buf + offset);
 310
 311                /* validate FW version */
 312                offset = AST_DP501_GBL_VERSION;
 313                data = readl(ast->dp501_fw_buf + offset);
 314                if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */
 315                        return maxclk;
 316
 317                /* Read Link Capability */
 318                offset = AST_DP501_LINKRATE;
 319                plinkcap = (u32 *)linkcap;
 320                *plinkcap = readl(ast->dp501_fw_buf + offset);
 321                if (linkcap[2] == 0) {
 322                        linkrate = linkcap[0];
 323                        linklanes = linkcap[1];
 324                        data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
 325                        if (data > 0xff)
 326                                data = 0xff;
 327                        maxclk = (u8)data;
 328                }
 329        }
 330        return maxclk;
 331}
 332
 333bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
 334{
 335        struct ast_private *ast = to_ast_private(dev);
 336        u32 i, boot_address, offset, data;
 337        u32 *pEDIDidx;
 338
 339        if (ast->config_mode == ast_use_p2a) {
 340                boot_address = get_fw_base(ast);
 341
 342                /* validate FW version */
 343                offset = AST_DP501_GBL_VERSION;
 344                data = ast_mindwm(ast, boot_address + offset);
 345                if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1)
 346                        return false;
 347
 348                /* validate PnP Monitor */
 349                offset = AST_DP501_PNPMONITOR;
 350                data = ast_mindwm(ast, boot_address + offset);
 351                if (!(data & AST_DP501_PNP_CONNECTED))
 352                        return false;
 353
 354                /* Read EDID */
 355                offset = AST_DP501_EDID_DATA;
 356                for (i = 0; i < 128; i += 4) {
 357                        data = ast_mindwm(ast, boot_address + offset + i);
 358                        pEDIDidx = (u32 *)(ediddata + i);
 359                        *pEDIDidx = data;
 360                }
 361        } else {
 362                if (!ast->dp501_fw_buf)
 363                        return false;
 364
 365                /* dummy read */
 366                offset = 0x0000;
 367                data = readl(ast->dp501_fw_buf + offset);
 368
 369                /* validate FW version */
 370                offset = AST_DP501_GBL_VERSION;
 371                data = readl(ast->dp501_fw_buf + offset);
 372                if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1)
 373                        return false;
 374
 375                /* validate PnP Monitor */
 376                offset = AST_DP501_PNPMONITOR;
 377                data = readl(ast->dp501_fw_buf + offset);
 378                if (!(data & AST_DP501_PNP_CONNECTED))
 379                        return false;
 380
 381                /* Read EDID */
 382                offset = AST_DP501_EDID_DATA;
 383                for (i = 0; i < 128; i += 4) {
 384                        data = readl(ast->dp501_fw_buf + offset + i);
 385                        pEDIDidx = (u32 *)(ediddata + i);
 386                        *pEDIDidx = data;
 387                }
 388        }
 389
 390        return true;
 391}
 392
 393static bool ast_init_dvo(struct drm_device *dev)
 394{
 395        struct ast_private *ast = to_ast_private(dev);
 396        u8 jreg;
 397        u32 data;
 398        ast_write32(ast, 0xf004, 0x1e6e0000);
 399        ast_write32(ast, 0xf000, 0x1);
 400        ast_write32(ast, 0x12000, 0x1688a8a8);
 401
 402        jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
 403        if (!(jreg & 0x80)) {
 404                /* Init SCU DVO Settings */
 405                data = ast_read32(ast, 0x12008);
 406                /* delay phase */
 407                data &= 0xfffff8ff;
 408                data |= 0x00000500;
 409                ast_write32(ast, 0x12008, data);
 410
 411                if (ast->chip == AST2300) {
 412                        data = ast_read32(ast, 0x12084);
 413                        /* multi-pins for DVO single-edge */
 414                        data |= 0xfffe0000;
 415                        ast_write32(ast, 0x12084, data);
 416
 417                        data = ast_read32(ast, 0x12088);
 418                        /* multi-pins for DVO single-edge */
 419                        data |= 0x000fffff;
 420                        ast_write32(ast, 0x12088, data);
 421
 422                        data = ast_read32(ast, 0x12090);
 423                        /* multi-pins for DVO single-edge */
 424                        data &= 0xffffffcf;
 425                        data |= 0x00000020;
 426                        ast_write32(ast, 0x12090, data);
 427                } else { /* AST2400 */
 428                        data = ast_read32(ast, 0x12088);
 429                        /* multi-pins for DVO single-edge */
 430                        data |= 0x30000000;
 431                        ast_write32(ast, 0x12088, data);
 432
 433                        data = ast_read32(ast, 0x1208c);
 434                        /* multi-pins for DVO single-edge */
 435                        data |= 0x000000cf;
 436                        ast_write32(ast, 0x1208c, data);
 437
 438                        data = ast_read32(ast, 0x120a4);
 439                        /* multi-pins for DVO single-edge */
 440                        data |= 0xffff0000;
 441                        ast_write32(ast, 0x120a4, data);
 442
 443                        data = ast_read32(ast, 0x120a8);
 444                        /* multi-pins for DVO single-edge */
 445                        data |= 0x0000000f;
 446                        ast_write32(ast, 0x120a8, data);
 447
 448                        data = ast_read32(ast, 0x12094);
 449                        /* multi-pins for DVO single-edge */
 450                        data |= 0x00000002;
 451                        ast_write32(ast, 0x12094, data);
 452                }
 453        }
 454
 455        /* Force to DVO */
 456        data = ast_read32(ast, 0x1202c);
 457        data &= 0xfffbffff;
 458        ast_write32(ast, 0x1202c, data);
 459
 460        /* Init VGA DVO Settings */
 461        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);
 462        return true;
 463}
 464
 465
 466static void ast_init_analog(struct drm_device *dev)
 467{
 468        struct ast_private *ast = to_ast_private(dev);
 469        u32 data;
 470
 471        /*
 472         * Set DAC source to VGA mode in SCU2C via the P2A
 473         * bridge. First configure the P2U to target the SCU
 474         * in case it isn't at this stage.
 475         */
 476        ast_write32(ast, 0xf004, 0x1e6e0000);
 477        ast_write32(ast, 0xf000, 0x1);
 478
 479        /* Then unlock the SCU with the magic password */
 480        ast_write32(ast, 0x12000, 0x1688a8a8);
 481        ast_write32(ast, 0x12000, 0x1688a8a8);
 482        ast_write32(ast, 0x12000, 0x1688a8a8);
 483
 484        /* Finally, clear bits [17:16] of SCU2c */
 485        data = ast_read32(ast, 0x1202c);
 486        data &= 0xfffcffff;
 487        ast_write32(ast, 0, data);
 488
 489        /* Disable DVO */
 490        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x00);
 491}
 492
 493void ast_init_3rdtx(struct drm_device *dev)
 494{
 495        struct ast_private *ast = to_ast_private(dev);
 496        u8 jreg;
 497
 498        if (ast->chip == AST2300 || ast->chip == AST2400) {
 499                jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
 500                switch (jreg & 0x0e) {
 501                case 0x04:
 502                        ast_init_dvo(dev);
 503                        break;
 504                case 0x08:
 505                        ast_launch_m68k(dev);
 506                        break;
 507                case 0x0c:
 508                        ast_init_dvo(dev);
 509                        break;
 510                default:
 511                        if (ast->tx_chip_type == AST_TX_SIL164)
 512                                ast_init_dvo(dev);
 513                        else
 514                                ast_init_analog(dev);
 515                }
 516        }
 517}
 518