drm/ast: Split ast_set_vbios_mode_info()

The implementation of ast_set_vbios_mode() converts a DRM display mode
and framebuffer into an adjusted mode and stores information for the
video BIOS to several scratch regsiters.

Here we split the function into individual functions that do the
conversion, set the VBIOS mode information and format information.
This makes it compatible with support for primary planes and atomic
modesetting.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191107083404.6852-6-tzimmermann@suse.de
This commit is contained in:
Thomas Zimmermann 2019-11-07 09:34:00 +01:00
parent 0d45ad989d
commit 259d14a76a

View File

@ -82,13 +82,12 @@ static void ast_crtc_load_lut(struct drm_crtc *crtc)
ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8); ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8);
} }
static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mode *mode, static bool ast_get_vbios_mode_info(const struct drm_framebuffer *fb,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, struct drm_display_mode *adjusted_mode,
struct ast_vbios_mode_info *vbios_mode) struct ast_vbios_mode_info *vbios_mode)
{ {
struct ast_private *ast = crtc->dev->dev_private; u32 refresh_rate_index = 0, refresh_rate;
const struct drm_framebuffer *fb = crtc->primary->fb;
u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate;
const struct ast_vbios_enhtable *best = NULL; const struct ast_vbios_enhtable *best = NULL;
u32 hborder, vborder; u32 hborder, vborder;
bool check_sync; bool check_sync;
@ -96,22 +95,19 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
switch (fb->format->cpp[0] * 8) { switch (fb->format->cpp[0] * 8) {
case 8: case 8:
vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
color_index = VGAModeIndex - 1;
break; break;
case 16: case 16:
vbios_mode->std_table = &vbios_stdtable[HiCModeIndex]; vbios_mode->std_table = &vbios_stdtable[HiCModeIndex];
color_index = HiCModeIndex;
break; break;
case 24: case 24:
case 32: case 32:
vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex]; vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex];
color_index = TrueCModeIndex;
break; break;
default: default:
return false; return false;
} }
switch (crtc->mode.crtc_hdisplay) { switch (mode->crtc_hdisplay) {
case 640: case 640:
vbios_mode->enh_table = &res_640x480[refresh_rate_index]; vbios_mode->enh_table = &res_640x480[refresh_rate_index];
break; break;
@ -122,7 +118,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
vbios_mode->enh_table = &res_1024x768[refresh_rate_index]; vbios_mode->enh_table = &res_1024x768[refresh_rate_index];
break; break;
case 1280: case 1280:
if (crtc->mode.crtc_vdisplay == 800) if (mode->crtc_vdisplay == 800)
vbios_mode->enh_table = &res_1280x800[refresh_rate_index]; vbios_mode->enh_table = &res_1280x800[refresh_rate_index];
else else
vbios_mode->enh_table = &res_1280x1024[refresh_rate_index]; vbios_mode->enh_table = &res_1280x1024[refresh_rate_index];
@ -134,7 +130,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
vbios_mode->enh_table = &res_1440x900[refresh_rate_index]; vbios_mode->enh_table = &res_1440x900[refresh_rate_index];
break; break;
case 1600: case 1600:
if (crtc->mode.crtc_vdisplay == 900) if (mode->crtc_vdisplay == 900)
vbios_mode->enh_table = &res_1600x900[refresh_rate_index]; vbios_mode->enh_table = &res_1600x900[refresh_rate_index];
else else
vbios_mode->enh_table = &res_1600x1200[refresh_rate_index]; vbios_mode->enh_table = &res_1600x1200[refresh_rate_index];
@ -143,7 +139,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
vbios_mode->enh_table = &res_1680x1050[refresh_rate_index]; vbios_mode->enh_table = &res_1680x1050[refresh_rate_index];
break; break;
case 1920: case 1920:
if (crtc->mode.crtc_vdisplay == 1080) if (mode->crtc_vdisplay == 1080)
vbios_mode->enh_table = &res_1920x1080[refresh_rate_index]; vbios_mode->enh_table = &res_1920x1080[refresh_rate_index];
else else
vbios_mode->enh_table = &res_1920x1200[refresh_rate_index]; vbios_mode->enh_table = &res_1920x1200[refresh_rate_index];
@ -154,7 +150,8 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
refresh_rate = drm_mode_vrefresh(mode); refresh_rate = drm_mode_vrefresh(mode);
check_sync = vbios_mode->enh_table->flags & WideScreenMode; check_sync = vbios_mode->enh_table->flags & WideScreenMode;
do {
while (1) {
const struct ast_vbios_enhtable *loop = vbios_mode->enh_table; const struct ast_vbios_enhtable *loop = vbios_mode->enh_table;
while (loop->refresh_rate != 0xff) { while (loop->refresh_rate != 0xff) {
@ -178,7 +175,8 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
if (best || !check_sync) if (best || !check_sync)
break; break;
check_sync = 0; check_sync = 0;
} while (1); }
if (best) if (best)
vbios_mode->enh_table = best; vbios_mode->enh_table = best;
@ -203,34 +201,65 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo
vbios_mode->enh_table->vfp + vbios_mode->enh_table->vfp +
vbios_mode->enh_table->vsync); vbios_mode->enh_table->vsync);
return true;
}
static void ast_set_vbios_color_reg(struct drm_crtc *crtc,
const struct drm_framebuffer *fb,
const struct ast_vbios_mode_info *vbios_mode)
{
struct ast_private *ast = crtc->dev->dev_private;
u32 color_index;
switch (fb->format->cpp[0]) {
case 1:
color_index = VGAModeIndex - 1;
break;
case 2:
color_index = HiCModeIndex;
break;
case 3:
case 4:
color_index = TrueCModeIndex;
default:
return;
}
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0x0f) << 4));
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00);
if (vbios_mode->enh_table->flags & NewModeInfo) {
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, fb->format->cpp[0] * 8);
}
}
static void ast_set_vbios_mode_reg(struct drm_crtc *crtc,
const struct drm_display_mode *adjusted_mode,
const struct ast_vbios_mode_info *vbios_mode)
{
struct ast_private *ast = crtc->dev->dev_private;
u32 refresh_rate_index, mode_id;
refresh_rate_index = vbios_mode->enh_table->refresh_rate_index; refresh_rate_index = vbios_mode->enh_table->refresh_rate_index;
mode_id = vbios_mode->enh_table->mode_id; mode_id = vbios_mode->enh_table->mode_id;
if (ast->chip == AST1180) { ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff);
/* TODO 1180 */ ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);
} else {
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0xf) << 4));
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00);
if (vbios_mode->enh_table->flags & NewModeInfo) {
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92,
fb->format->cpp[0] * 8);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay); if (vbios_mode->enh_table->flags & NewModeInfo) {
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
} ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8);
} }
return true;
} }
static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode, static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct ast_vbios_mode_info *vbios_mode) struct ast_vbios_mode_info *vbios_mode)
{ {
@ -581,20 +610,24 @@ static int ast_crtc_mode_set(struct drm_crtc *crtc,
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct ast_private *ast = crtc->dev->dev_private; struct ast_private *ast = crtc->dev->dev_private;
const struct drm_framebuffer *fb = crtc->primary->fb;
struct ast_vbios_mode_info vbios_mode; struct ast_vbios_mode_info vbios_mode;
bool ret; bool succ;
if (ast->chip == AST1180) { if (ast->chip == AST1180) {
DRM_ERROR("AST 1180 modesetting not supported\n"); DRM_ERROR("AST 1180 modesetting not supported\n");
return -EINVAL; return -EINVAL;
} }
ret = ast_get_vbios_mode_info(crtc, mode, adjusted_mode, &vbios_mode); succ = ast_get_vbios_mode_info(fb, mode, adjusted_mode, &vbios_mode);
if (ret == false) if (!succ)
return -EINVAL; return -EINVAL;
ast_open_key(ast); ast_open_key(ast);
ast_set_vbios_color_reg(crtc, fb, &vbios_mode);
ast_set_vbios_mode_reg(crtc, adjusted_mode, &vbios_mode);
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
ast_set_std_reg(crtc, adjusted_mode, &vbios_mode); ast_set_std_reg(crtc, adjusted_mode, &vbios_mode);
ast_set_crtc_reg(crtc, adjusted_mode, &vbios_mode); ast_set_crtc_reg(crtc, adjusted_mode, &vbios_mode);
ast_set_offset_reg(crtc); ast_set_offset_reg(crtc);