drm: Track VIC for modes

Some modes are "standard", and have a VIC (Video Identification Code). Try
to figure out if the modes available to us have an associated VIC, store it
and print it.

This is preparation for eventually enabling YUV420 support, which is only
supported on a per-mode basis.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
Derek Foreman 2026-04-09 15:00:15 -05:00
parent 36e95611ec
commit 3b33d4fab7
2 changed files with 109 additions and 1 deletions

View file

@ -293,6 +293,7 @@ struct drm_mode {
struct weston_mode base;
drmModeModeInfo mode_info;
uint32_t blob_id;
uint8_t vic;
};
enum drm_fb_type {

View file

@ -100,6 +100,27 @@ drm_to_weston_mode_aspect_ratio(uint32_t drm_mode_flags)
}
}
static enum di_cta_video_format_picture_aspect_ratio
drm_to_cta_aspect_ratio(uint32_t drm_mode_flags, bool *valid)
{
*valid = true;
switch (drm_mode_flags & DRM_MODE_FLAG_PIC_AR_MASK) {
case DRM_MODE_FLAG_PIC_AR_4_3:
return DI_CTA_VIDEO_FORMAT_PICTURE_ASPECT_RATIO_4_3;
case DRM_MODE_FLAG_PIC_AR_16_9:
return DI_CTA_VIDEO_FORMAT_PICTURE_ASPECT_RATIO_16_9;
case DRM_MODE_FLAG_PIC_AR_64_27:
return DI_CTA_VIDEO_FORMAT_PICTURE_ASPECT_RATIO_64_27;
case DRM_MODE_FLAG_PIC_AR_256_135:
return DI_CTA_VIDEO_FORMAT_PICTURE_ASPECT_RATIO_256_135;
case DRM_MODE_FLAG_PIC_AR_NONE:
default:
*valid = false;
return DI_CTA_VIDEO_FORMAT_PICTURE_ASPECT_RATIO_4_3;
}
}
static const char *
aspect_ratio_to_string(enum weston_mode_aspect_ratio ratio)
{
@ -509,6 +530,85 @@ drm_refresh_rate_mHz(const drmModeModeInfo *info)
return refresh;
}
static bool
drmmodeinfo_is_fmt(const drmModeModeInfo *info,
const struct di_cta_video_format *fmt)
{
int vfront = info->vsync_start - info->vdisplay;
int vsync = info->vsync_end - info->vsync_start;
int vback = info->vtotal - info->vsync_end;
int hfront = info->hsync_start - info->hdisplay;
int hsync = info->hsync_end - info->hsync_start;
int hback = info->htotal - info->hsync_end;
uint32_t fmt_clock_khz = fmt->pixel_clock_hz / 1000;
enum di_cta_video_format_sync_polarity hpol, vpol;
bool interlaced = !!(info->flags & DRM_MODE_FLAG_INTERLACE);
enum di_cta_video_format_picture_aspect_ratio info_ar;
bool valid_ar;
if (info->flags & DRM_MODE_FLAG_PHSYNC)
hpol = DI_CTA_VIDEO_FORMAT_SYNC_POSITIVE;
else if (info->flags & DRM_MODE_FLAG_NHSYNC)
hpol = DI_CTA_VIDEO_FORMAT_SYNC_NEGATIVE;
else
return false;
if (info->flags & DRM_MODE_FLAG_PVSYNC)
vpol = DI_CTA_VIDEO_FORMAT_SYNC_POSITIVE;
else if (info->flags & DRM_MODE_FLAG_NVSYNC)
vpol = DI_CTA_VIDEO_FORMAT_SYNC_NEGATIVE;
else
return false;
info_ar = drm_to_cta_aspect_ratio(info->flags, &valid_ar);
if (!valid_ar)
return false;
/* The clock match is imprecise because it's already rounded off
* in drmModeModeInfo.
*/
if (info->hdisplay != fmt->h_active ||
info->vdisplay != fmt->v_active ||
hfront != fmt->h_front ||
vfront != fmt->v_front ||
hsync != fmt->h_sync ||
vsync != fmt->v_sync ||
hback != fmt->h_back ||
vback != fmt->v_back ||
info->clock != fmt_clock_khz ||
hpol != fmt->h_sync_polarity ||
vpol != fmt->v_sync_polarity ||
interlaced != fmt->interlaced ||
info_ar != fmt->picture_aspect_ratio)
return false;
return true;
}
static int
match_cta_mode(const drmModeModeInfo *info)
{
const struct di_cta_video_format *fmt;
uint8_t vic;
/* FIXME: Some day we'll probably get this from libdi high-
* level api, but for now we kludge it here.
*
* The stop at 219 works around an off by one bug in some
* releases of libdi, and needs to be 255 when we can
* bump version to ensure the fix.
*/
for (vic = 0; vic < 220; vic++) {
fmt = di_cta_video_format_from_vic(vic);
if (!fmt)
continue;
assert(fmt->vic == vic);
if (drmmodeinfo_is_fmt(info, fmt))
return vic;
}
return 0;
}
/**
* Add a mode to output's mode list
*
@ -536,6 +636,8 @@ drm_output_add_mode(struct drm_output *output, const drmModeModeInfo *info)
mode->mode_info = *info;
mode->blob_id = 0;
mode->vic = match_cta_mode(info);
if (info->type & DRM_MODE_TYPE_PREFERRED)
mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
@ -583,7 +685,12 @@ drm_output_print_modes(struct drm_output *output)
dm = to_drm_mode(m);
aspect_ratio = aspect_ratio_to_string(m->aspect_ratio);
weston_log_continue(STAMP_SPACE "%s@%.1f%s%s%s, %.1f MHz\n",
if (dm->vic)
weston_log_continue(STAMP_SPACE "VIC %3d, ", dm->vic);
else
weston_log_continue(STAMP_SPACE " ");
weston_log_continue("%s@%.1f%s%s%s, %.1f MHz\n",
dm->mode_info.name, m->refresh / 1000.0,
aspect_ratio,
m->flags & WL_OUTPUT_MODE_PREFERRED ?