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        data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
 193        if (data) {
 194                boot_address = get_fw_base(ast);
 195                for (i = 0; i < size; i += 4)
 196                        *(u32 *)(addr + i) = ast_mindwm(ast, boot_address + i);
 197                return true;
 198        }
 199        return false;
 200}
 201
 202static bool ast_launch_m68k(struct drm_device *dev)
 203{
 204        struct ast_private *ast = to_ast_private(dev);
 205        u32 i, data, len = 0;
 206        u32 boot_address;
 207        u8 *fw_addr = NULL;
 208        u8 jreg;
 209
 210        data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
 211        if (!data) {
 212
 213                if (ast->dp501_fw_addr) {
 214                        fw_addr = ast->dp501_fw_addr;
 215                        len = 32*1024;
 216                } else {
 217                        if (!ast->dp501_fw &&
 218                            ast_load_dp501_microcode(dev) < 0)
 219                                return false;
 220
 221                        fw_addr = (u8 *)ast->dp501_fw->data;
 222                        len = ast->dp501_fw->size;
 223                }
 224                /* Get BootAddress */
 225                ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
 226                data = ast_mindwm(ast, 0x1e6e0004);
 227                switch (data & 0x03) {
 228                case 0:
 229                        boot_address = 0x44000000;
 230                        break;
 231                default:
 232                case 1:
 233                        boot_address = 0x48000000;
 234                        break;
 235                case 2:
 236                        boot_address = 0x50000000;
 237                        break;
 238                case 3:
 239                        boot_address = 0x60000000;
 240                        break;
 241                }
 242                boot_address -= 0x200000; /* -2MB */
 243
 244                /* copy image to buffer */
 245                for (i = 0; i < len; i += 4) {
 246                        data = *(u32 *)(fw_addr + i);
 247                        ast_moutdwm(ast, boot_address + i, data);
 248                }
 249
 250                /* Init SCU */
 251                ast_moutdwm(ast, 0x1e6e2000, 0x1688a8a8);
 252
 253                /* Launch FW */
 254                ast_moutdwm(ast, 0x1e6e2104, 0x80000000 + boot_address);
 255                ast_moutdwm(ast, 0x1e6e2100, 1);
 256
 257                /* Update Scratch */
 258                data = ast_mindwm(ast, 0x1e6e2040) & 0xfffff1ff;                /* D[11:9] = 100b: UEFI handling */
 259                data |= 0x800;
 260                ast_moutdwm(ast, 0x1e6e2040, data);
 261
 262                jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 0xfc); /* D[1:0]: Reserved Video Buffer */
 263                jreg |= 0x02;
 264                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x99, jreg);
 265        }
 266        return true;
 267}
 268
 269u8 ast_get_dp501_max_clk(struct drm_device *dev)
 270{
 271        struct ast_private *ast = to_ast_private(dev);
 272        u32 boot_address, offset, data;
 273        u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
 274
 275        boot_address = get_fw_base(ast);
 276
 277        /* validate FW version */
 278        offset = 0xf000;
 279        data = ast_mindwm(ast, boot_address + offset);
 280        if ((data & 0xf0) != 0x10) /* version: 1x */
 281                return maxclk;
 282
 283        /* Read Link Capability */
 284        offset  = 0xf014;
 285        *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
 286        if (linkcap[2] == 0) {
 287                linkrate = linkcap[0];
 288                linklanes = linkcap[1];
 289                data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
 290                if (data > 0xff)
 291                        data = 0xff;
 292                maxclk = (u8)data;
 293        }
 294        return maxclk;
 295}
 296
 297bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
 298{
 299        struct ast_private *ast = to_ast_private(dev);
 300        u32 i, boot_address, offset, data;
 301
 302        boot_address = get_fw_base(ast);
 303
 304        /* validate FW version */
 305        offset = 0xf000;
 306        data = ast_mindwm(ast, boot_address + offset);
 307        if ((data & 0xf0) != 0x10)
 308                return false;
 309
 310        /* validate PnP Monitor */
 311        offset = 0xf010;
 312        data = ast_mindwm(ast, boot_address + offset);
 313        if (!(data & 0x01))
 314                return false;
 315
 316        /* Read EDID */
 317        offset = 0xf020;
 318        for (i = 0; i < 128; i += 4) {
 319                data = ast_mindwm(ast, boot_address + offset + i);
 320                *(u32 *)(ediddata + i) = data;
 321        }
 322
 323        return true;
 324}
 325
 326static bool ast_init_dvo(struct drm_device *dev)
 327{
 328        struct ast_private *ast = to_ast_private(dev);
 329        u8 jreg;
 330        u32 data;
 331        ast_write32(ast, 0xf004, 0x1e6e0000);
 332        ast_write32(ast, 0xf000, 0x1);
 333        ast_write32(ast, 0x12000, 0x1688a8a8);
 334
 335        jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
 336        if (!(jreg & 0x80)) {
 337                /* Init SCU DVO Settings */
 338                data = ast_read32(ast, 0x12008);
 339                /* delay phase */
 340                data &= 0xfffff8ff;
 341                data |= 0x00000500;
 342                ast_write32(ast, 0x12008, data);
 343
 344                if (ast->chip == AST2300) {
 345                        data = ast_read32(ast, 0x12084);
 346                        /* multi-pins for DVO single-edge */
 347                        data |= 0xfffe0000;
 348                        ast_write32(ast, 0x12084, data);
 349
 350                        data = ast_read32(ast, 0x12088);
 351                        /* multi-pins for DVO single-edge */
 352                        data |= 0x000fffff;
 353                        ast_write32(ast, 0x12088, data);
 354
 355                        data = ast_read32(ast, 0x12090);
 356                        /* multi-pins for DVO single-edge */
 357                        data &= 0xffffffcf;
 358                        data |= 0x00000020;
 359                        ast_write32(ast, 0x12090, data);
 360                } else { /* AST2400 */
 361                        data = ast_read32(ast, 0x12088);
 362                        /* multi-pins for DVO single-edge */
 363                        data |= 0x30000000;
 364                        ast_write32(ast, 0x12088, data);
 365
 366                        data = ast_read32(ast, 0x1208c);
 367                        /* multi-pins for DVO single-edge */
 368                        data |= 0x000000cf;
 369                        ast_write32(ast, 0x1208c, data);
 370
 371                        data = ast_read32(ast, 0x120a4);
 372                        /* multi-pins for DVO single-edge */
 373                        data |= 0xffff0000;
 374                        ast_write32(ast, 0x120a4, data);
 375
 376                        data = ast_read32(ast, 0x120a8);
 377                        /* multi-pins for DVO single-edge */
 378                        data |= 0x0000000f;
 379                        ast_write32(ast, 0x120a8, data);
 380
 381                        data = ast_read32(ast, 0x12094);
 382                        /* multi-pins for DVO single-edge */
 383                        data |= 0x00000002;
 384                        ast_write32(ast, 0x12094, data);
 385                }
 386        }
 387
 388        /* Force to DVO */
 389        data = ast_read32(ast, 0x1202c);
 390        data &= 0xfffbffff;
 391        ast_write32(ast, 0x1202c, data);
 392
 393        /* Init VGA DVO Settings */
 394        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);
 395        return true;
 396}
 397
 398
 399static void ast_init_analog(struct drm_device *dev)
 400{
 401        struct ast_private *ast = to_ast_private(dev);
 402        u32 data;
 403
 404        /*
 405         * Set DAC source to VGA mode in SCU2C via the P2A
 406         * bridge. First configure the P2U to target the SCU
 407         * in case it isn't at this stage.
 408         */
 409        ast_write32(ast, 0xf004, 0x1e6e0000);
 410        ast_write32(ast, 0xf000, 0x1);
 411
 412        /* Then unlock the SCU with the magic password */
 413        ast_write32(ast, 0x12000, 0x1688a8a8);
 414        ast_write32(ast, 0x12000, 0x1688a8a8);
 415        ast_write32(ast, 0x12000, 0x1688a8a8);
 416
 417        /* Finally, clear bits [17:16] of SCU2c */
 418        data = ast_read32(ast, 0x1202c);
 419        data &= 0xfffcffff;
 420        ast_write32(ast, 0, data);
 421
 422        /* Disable DVO */
 423        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x00);
 424}
 425
 426void ast_init_3rdtx(struct drm_device *dev)
 427{
 428        struct ast_private *ast = to_ast_private(dev);
 429        u8 jreg;
 430
 431        if (ast->chip == AST2300 || ast->chip == AST2400) {
 432                jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
 433                switch (jreg & 0x0e) {
 434                case 0x04:
 435                        ast_init_dvo(dev);
 436                        break;
 437                case 0x08:
 438                        ast_launch_m68k(dev);
 439                        break;
 440                case 0x0c:
 441                        ast_init_dvo(dev);
 442                        break;
 443                default:
 444                        if (ast->tx_chip_type == AST_TX_SIL164)
 445                                ast_init_dvo(dev);
 446                        else
 447                                ast_init_analog(dev);
 448                }
 449        }
 450}
 451