root/drivers/gpu/drm/ast/ast_dp501.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ast_load_dp501_microcode
  2. send_ack
  3. send_nack
  4. wait_ack
  5. wait_nack
  6. set_cmd_trigger
  7. clear_cmd_trigger
  8. wait_fw_ready
  9. ast_write_cmd
  10. ast_write_data
  11. ast_read_data
  12. clear_cmd
  13. ast_set_dp501_video_output
  14. get_fw_base
  15. ast_backup_fw
  16. ast_launch_m68k
  17. ast_get_dp501_max_clk
  18. ast_dp501_read_edid
  19. ast_init_dvo
  20. ast_init_analog
  21. ast_init_3rdtx
  22. ast_release_firmware

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

/* [<][>][^][v][top][bottom][index][help] */