mirror of
https://github.com/torvalds/linux.git
synced 2024-12-12 06:02:38 +00:00
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:
parent
0d45ad989d
commit
259d14a76a
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user