#include <linux/delay.h>
#include <linux/pci.h>
#include <drm/drm_drv.h>
#include "ast_drv.h"
#include "ast_post.h"
void ast_2000_set_def_ext_reg(struct ast_device *ast)
{
static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff };
u8 i, index, reg;
const u8 *ext_reg_info;
for (i = 0x81; i <= 0x9f; i++)
ast_set_index_reg(ast, AST_IO_VGACRI, i, 0x00);
ext_reg_info = extreginfo;
index = 0xa0;
while (*ext_reg_info != 0xff) {
ast_set_index_reg_mask(ast, AST_IO_VGACRI, index, 0x00, *ext_reg_info);
index++;
ext_reg_info++;
}
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x8c, 0x00, 0x01);
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x00, 0x00);
reg = 0x04;
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xff, reg);
}
static const struct ast_dramstruct ast2000_dram_table_data[] = {
AST_DRAMSTRUCT_REG(AST_REG_MCR108, 0x00000000),
AST_DRAMSTRUCT_REG(AST_REG_MCR120, 0x00004a21),
AST_DRAMSTRUCT_UDELAY(67u),
AST_DRAMSTRUCT_REG(AST_REG_MCR00, 0xffffffff),
AST_DRAMSTRUCT_REG(AST_REG_MCR04, 0x00000089),
AST_DRAMSTRUCT_REG(AST_REG_MCR08, 0x22331353),
AST_DRAMSTRUCT_REG(AST_REG_MCR0C, 0x0d07000b),
AST_DRAMSTRUCT_REG(AST_REG_MCR10, 0x11113333),
AST_DRAMSTRUCT_REG(AST_REG_MCR20, 0x00110350),
AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x1e0828f0),
AST_DRAMSTRUCT_REG(AST_REG_MCR24, 0x00000001),
AST_DRAMSTRUCT_REG(AST_REG_MCR1C, 0x00000000),
AST_DRAMSTRUCT_REG(AST_REG_MCR14, 0x00000003),
AST_DRAMSTRUCT_UDELAY(67u),
AST_DRAMSTRUCT_REG(AST_REG_MCR18, 0x00000131),
AST_DRAMSTRUCT_REG(AST_REG_MCR14, 0x00000001),
AST_DRAMSTRUCT_UDELAY(67u),
AST_DRAMSTRUCT_REG(AST_REG_MCR18, 0x00000031),
AST_DRAMSTRUCT_REG(AST_REG_MCR14, 0x00000001),
AST_DRAMSTRUCT_UDELAY(67u),
AST_DRAMSTRUCT_REG(AST_REG_MCR28, 0x1e0828f1),
AST_DRAMSTRUCT_REG(AST_REG_MCR24, 0x00000003),
AST_DRAMSTRUCT_REG(AST_REG_MCR2C, 0x1f0f28fb),
AST_DRAMSTRUCT_REG(AST_REG_MCR30, 0xfffffe01),
AST_DRAMSTRUCT_INVALID,
};
static void ast_post_chip_2000(struct ast_device *ast)
{
u8 j;
u32 i;
j = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
if ((j & 0x80) == 0) {
const struct ast_dramstruct *dram_reg_info = ast2000_dram_table_data;
u32 mcr140;
ast_moutdwm_poll(ast, AST_REG_MCR100, 0xa8, 0xa8);
while (!AST_DRAMSTRUCT_IS(dram_reg_info, INVALID)) {
if (AST_DRAMSTRUCT_IS(dram_reg_info, UDELAY)) {
for (i = 0; i < 15; i++)
udelay(dram_reg_info->data);
} else {
ast_moutdwm(ast, dram_reg_info->index, dram_reg_info->data);
}
dram_reg_info++;
}
mcr140 = ast_mindwm(ast, AST_REG_MCR140);
mcr140 |= 0x00000040;
ast_moutdwm(ast, AST_REG_MCR140, mcr140);
}
do {
j = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff);
} while ((j & 0x40) == 0);
}
int ast_2000_post(struct ast_device *ast)
{
ast_2000_set_def_ext_reg(ast);
if (ast->config_mode == ast_use_p2a) {
ast_post_chip_2000(ast);
} else {
if (ast->tx_chip == AST_TX_SIL164) {
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x80);
}
}
return 0;
}
const struct ast_vbios_dclk_info ast_2000_dclk_table[] = {
{0x2c, 0xe7, 0x03},
{0x95, 0x62, 0x03},
{0x67, 0x63, 0x01},
{0x76, 0x63, 0x01},
{0xee, 0x67, 0x01},
{0x82, 0x62, 0x01},
{0xc6, 0x64, 0x01},
{0x94, 0x62, 0x01},
{0x80, 0x64, 0x00},
{0x7b, 0x63, 0x00},
{0x67, 0x62, 0x00},
{0x7c, 0x62, 0x00},
{0x8e, 0x62, 0x00},
{0x85, 0x24, 0x00},
{0x67, 0x22, 0x00},
{0x6a, 0x22, 0x00},
{0x4d, 0x4c, 0x80},
{0x68, 0x6f, 0x80},
{0x28, 0x49, 0x80},
{0x37, 0x49, 0x80},
{0x1f, 0x45, 0x80},
{0x47, 0x6c, 0x80},
{0x25, 0x65, 0x80},
{0x77, 0x58, 0x80},
{0x32, 0x67, 0x80},
{0x6a, 0x6d, 0x80},
{0x3b, 0x2c, 0x81},
};
void ast_2000_detect_tx_chip(struct ast_device *ast, bool need_post)
{
enum ast_tx_chip tx_chip = AST_TX_NONE;
u8 vgacra3;
if (!need_post) {
vgacra3 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xff);
if (vgacra3 & AST_IO_VGACRA3_DVO_ENABLED)
tx_chip = AST_TX_SIL164;
}
__ast_device_set_tx_chip(ast, tx_chip);
}
static const struct ast_device_quirks ast_2000_device_quirks = {
.crtc_mem_req_threshold_low = 31,
.crtc_mem_req_threshold_high = 47,
};
struct drm_device *ast_2000_device_create(struct pci_dev *pdev,
const struct drm_driver *drv,
enum ast_chip chip,
enum ast_config_mode config_mode,
void __iomem *regs,
void __iomem *ioregs,
bool need_post)
{
struct drm_device *dev;
struct ast_device *ast;
int ret;
ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base);
if (IS_ERR(ast))
return ERR_CAST(ast);
dev = &ast->base;
ast_device_init(ast, chip, config_mode, regs, ioregs, &ast_2000_device_quirks);
ast->dclk_table = ast_2000_dclk_table;
ast_2000_detect_tx_chip(ast, need_post);
if (need_post) {
ret = ast_post_gpu(ast);
if (ret)
return ERR_PTR(ret);
}
ret = ast_mm_init(ast);
if (ret)
return ERR_PTR(ret);
ret = ast_mode_config_init(ast);
if (ret)
return ERR_PTR(ret);
return dev;
}