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