static void send_nack(struct ast_private *ast) { u8 sendack; sendack = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0xff); sendack &= ~0x80; ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, 0x00, sendack); }
static void ast_init_analog(struct drm_device *dev) { struct ast_private *ast = dev->dev_private; u32 data; /* * Set DAC source to VGA mode in SCU2C via the P2A * bridge. First configure the P2U to target the SCU * in case it isn't at this stage. */ ast_write32(ast, 0xf004, 0x1e6e0000); ast_write32(ast, 0xf000, 0x1); /* Then unlock the SCU with the magic password */ ast_write32(ast, 0x12000, 0x1688a8a8); ast_write32(ast, 0x12000, 0x1688a8a8); ast_write32(ast, 0x12000, 0x1688a8a8); /* Finally, clear bits [17:16] of SCU2c */ data = ast_read32(ast, 0x1202c); data &= 0xfffcffff; ast_write32(ast, 0, data); /* Disable DVO */ ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x00); }
static bool ast_write_data(struct drm_device *dev, u8 data) { struct ast_private *ast = dev->dev_private; if (wait_nack(ast)) { send_nack(ast); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data); send_ack(ast); if (wait_ack(ast)) { send_nack(ast); return true; } } send_nack(ast); return false; }
static bool ast_write_cmd(struct drm_device *dev, u8 data) { struct ast_private *ast = dev->dev_private; int retry = 0; if (wait_nack(ast)) { send_nack(ast); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, data); send_ack(ast); set_cmd_trigger(ast); do { if (wait_ack(ast)) { clear_cmd_trigger(ast); send_nack(ast); return true; } } while (retry++ < 100); } clear_cmd_trigger(ast); send_nack(ast); return false; }
static void clear_cmd_trigger(struct ast_private *ast) { ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9b, ~0x40, 0x00); }
static bool ast_init_dvo(struct drm_device *dev) { struct ast_private *ast = dev->dev_private; u8 jreg; u32 data; ast_write32(ast, 0xf004, 0x1e6e0000); ast_write32(ast, 0xf000, 0x1); ast_write32(ast, 0x12000, 0x1688a8a8); jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); if (!(jreg & 0x80)) { /* Init SCU DVO Settings */ data = ast_read32(ast, 0x12008); /* delay phase */ data &= 0xfffff8ff; data |= 0x00000500; ast_write32(ast, 0x12008, data); if (ast->chip == AST2300) { data = ast_read32(ast, 0x12084); /* multi-pins for DVO single-edge */ data |= 0xfffe0000; ast_write32(ast, 0x12084, data); data = ast_read32(ast, 0x12088); /* multi-pins for DVO single-edge */ data |= 0x000fffff; ast_write32(ast, 0x12088, data); data = ast_read32(ast, 0x12090); /* multi-pins for DVO single-edge */ data &= 0xffffffcf; data |= 0x00000020; ast_write32(ast, 0x12090, data); } else { /* AST2400 */ data = ast_read32(ast, 0x12088); /* multi-pins for DVO single-edge */ data |= 0x30000000; ast_write32(ast, 0x12088, data); data = ast_read32(ast, 0x1208c); /* multi-pins for DVO single-edge */ data |= 0x000000cf; ast_write32(ast, 0x1208c, data); data = ast_read32(ast, 0x120a4); /* multi-pins for DVO single-edge */ data |= 0xffff0000; ast_write32(ast, 0x120a4, data); data = ast_read32(ast, 0x120a8); /* multi-pins for DVO single-edge */ data |= 0x0000000f; ast_write32(ast, 0x120a8, data); data = ast_read32(ast, 0x12094); /* multi-pins for DVO single-edge */ data |= 0x00000002; ast_write32(ast, 0x12094, data); } } /* Force to DVO */ data = ast_read32(ast, 0x1202c); data &= 0xfffbffff; ast_write32(ast, 0x1202c, data); /* Init VGA DVO Settings */ ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); return true; }
static void clear_cmd(struct ast_private *ast) { send_nack(ast); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x9a, 0x00, 0x00); }