xref: /aosp_15_r20/external/libkmsxx/kms++/src/videomode.cpp (revision f0687c8a10b3e371dbe09214db6664e37c283cca)
1*f0687c8aSRaman Tenneti #include <xf86drm.h>
2*f0687c8aSRaman Tenneti #include <xf86drmMode.h>
3*f0687c8aSRaman Tenneti #include <cmath>
4*f0687c8aSRaman Tenneti #include <sstream>
5*f0687c8aSRaman Tenneti #include <fmt/format.h>
6*f0687c8aSRaman Tenneti 
7*f0687c8aSRaman Tenneti #include <kms++/kms++.h>
8*f0687c8aSRaman Tenneti #include "helpers.h"
9*f0687c8aSRaman Tenneti 
10*f0687c8aSRaman Tenneti using namespace std;
11*f0687c8aSRaman Tenneti 
12*f0687c8aSRaman Tenneti namespace kms
13*f0687c8aSRaman Tenneti {
valid() const14*f0687c8aSRaman Tenneti bool Videomode::valid() const
15*f0687c8aSRaman Tenneti {
16*f0687c8aSRaman Tenneti 	return !!clock;
17*f0687c8aSRaman Tenneti }
18*f0687c8aSRaman Tenneti 
to_blob(Card & card) const19*f0687c8aSRaman Tenneti unique_ptr<Blob> Videomode::to_blob(Card& card) const
20*f0687c8aSRaman Tenneti {
21*f0687c8aSRaman Tenneti 	drmModeModeInfo drm_mode = video_mode_to_drm_mode(*this);
22*f0687c8aSRaman Tenneti 
23*f0687c8aSRaman Tenneti 	return unique_ptr<Blob>(new Blob(card, &drm_mode, sizeof(drm_mode)));
24*f0687c8aSRaman Tenneti }
25*f0687c8aSRaman Tenneti 
calculated_vrefresh() const26*f0687c8aSRaman Tenneti float Videomode::calculated_vrefresh() const
27*f0687c8aSRaman Tenneti {
28*f0687c8aSRaman Tenneti 	// XXX interlace should only halve visible vertical lines, not blanking
29*f0687c8aSRaman Tenneti 	float refresh = (clock * 1000.0) / (htotal * vtotal) * (interlace() ? 2 : 1);
30*f0687c8aSRaman Tenneti 	return roundf(refresh * 100.0) / 100.0;
31*f0687c8aSRaman Tenneti }
32*f0687c8aSRaman Tenneti 
interlace() const33*f0687c8aSRaman Tenneti bool Videomode::interlace() const
34*f0687c8aSRaman Tenneti {
35*f0687c8aSRaman Tenneti 	return flags & DRM_MODE_FLAG_INTERLACE;
36*f0687c8aSRaman Tenneti }
37*f0687c8aSRaman Tenneti 
hsync() const38*f0687c8aSRaman Tenneti SyncPolarity Videomode::hsync() const
39*f0687c8aSRaman Tenneti {
40*f0687c8aSRaman Tenneti 	if (flags & DRM_MODE_FLAG_PHSYNC)
41*f0687c8aSRaman Tenneti 		return SyncPolarity::Positive;
42*f0687c8aSRaman Tenneti 	if (flags & DRM_MODE_FLAG_NHSYNC)
43*f0687c8aSRaman Tenneti 		return SyncPolarity::Negative;
44*f0687c8aSRaman Tenneti 	return SyncPolarity::Undefined;
45*f0687c8aSRaman Tenneti }
46*f0687c8aSRaman Tenneti 
vsync() const47*f0687c8aSRaman Tenneti SyncPolarity Videomode::vsync() const
48*f0687c8aSRaman Tenneti {
49*f0687c8aSRaman Tenneti 	if (flags & DRM_MODE_FLAG_PVSYNC)
50*f0687c8aSRaman Tenneti 		return SyncPolarity::Positive;
51*f0687c8aSRaman Tenneti 	if (flags & DRM_MODE_FLAG_NVSYNC)
52*f0687c8aSRaman Tenneti 		return SyncPolarity::Negative;
53*f0687c8aSRaman Tenneti 	return SyncPolarity::Undefined;
54*f0687c8aSRaman Tenneti }
55*f0687c8aSRaman Tenneti 
set_interlace(bool ilace)56*f0687c8aSRaman Tenneti void Videomode::set_interlace(bool ilace)
57*f0687c8aSRaman Tenneti {
58*f0687c8aSRaman Tenneti 	if (ilace)
59*f0687c8aSRaman Tenneti 		flags |= DRM_MODE_FLAG_INTERLACE;
60*f0687c8aSRaman Tenneti 	else
61*f0687c8aSRaman Tenneti 		flags &= ~DRM_MODE_FLAG_INTERLACE;
62*f0687c8aSRaman Tenneti }
63*f0687c8aSRaman Tenneti 
set_hsync(SyncPolarity pol)64*f0687c8aSRaman Tenneti void Videomode::set_hsync(SyncPolarity pol)
65*f0687c8aSRaman Tenneti {
66*f0687c8aSRaman Tenneti 	flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC);
67*f0687c8aSRaman Tenneti 
68*f0687c8aSRaman Tenneti 	switch (pol) {
69*f0687c8aSRaman Tenneti 	case SyncPolarity::Positive:
70*f0687c8aSRaman Tenneti 		flags |= DRM_MODE_FLAG_PHSYNC;
71*f0687c8aSRaman Tenneti 		break;
72*f0687c8aSRaman Tenneti 	case SyncPolarity::Negative:
73*f0687c8aSRaman Tenneti 		flags |= DRM_MODE_FLAG_NHSYNC;
74*f0687c8aSRaman Tenneti 		break;
75*f0687c8aSRaman Tenneti 	default:
76*f0687c8aSRaman Tenneti 		break;
77*f0687c8aSRaman Tenneti 	}
78*f0687c8aSRaman Tenneti }
79*f0687c8aSRaman Tenneti 
set_vsync(SyncPolarity pol)80*f0687c8aSRaman Tenneti void Videomode::set_vsync(SyncPolarity pol)
81*f0687c8aSRaman Tenneti {
82*f0687c8aSRaman Tenneti 	flags &= ~(DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC);
83*f0687c8aSRaman Tenneti 
84*f0687c8aSRaman Tenneti 	switch (pol) {
85*f0687c8aSRaman Tenneti 	case SyncPolarity::Positive:
86*f0687c8aSRaman Tenneti 		flags |= DRM_MODE_FLAG_PVSYNC;
87*f0687c8aSRaman Tenneti 		break;
88*f0687c8aSRaman Tenneti 	case SyncPolarity::Negative:
89*f0687c8aSRaman Tenneti 		flags |= DRM_MODE_FLAG_NVSYNC;
90*f0687c8aSRaman Tenneti 		break;
91*f0687c8aSRaman Tenneti 	default:
92*f0687c8aSRaman Tenneti 		break;
93*f0687c8aSRaman Tenneti 	}
94*f0687c8aSRaman Tenneti }
95*f0687c8aSRaman Tenneti 
to_string_short() const96*f0687c8aSRaman Tenneti string Videomode::to_string_short() const
97*f0687c8aSRaman Tenneti {
98*f0687c8aSRaman Tenneti 	return fmt::format("{}x{}{}@{:.2f}", hdisplay, vdisplay, interlace() ? "i" : "", calculated_vrefresh());
99*f0687c8aSRaman Tenneti }
100*f0687c8aSRaman Tenneti 
sync_to_char(SyncPolarity pol)101*f0687c8aSRaman Tenneti static char sync_to_char(SyncPolarity pol)
102*f0687c8aSRaman Tenneti {
103*f0687c8aSRaman Tenneti 	switch (pol) {
104*f0687c8aSRaman Tenneti 	case SyncPolarity::Positive:
105*f0687c8aSRaman Tenneti 		return '+';
106*f0687c8aSRaman Tenneti 	case SyncPolarity::Negative:
107*f0687c8aSRaman Tenneti 		return '-';
108*f0687c8aSRaman Tenneti 	default:
109*f0687c8aSRaman Tenneti 		return '?';
110*f0687c8aSRaman Tenneti 	}
111*f0687c8aSRaman Tenneti }
112*f0687c8aSRaman Tenneti 
to_string_long() const113*f0687c8aSRaman Tenneti string Videomode::to_string_long() const
114*f0687c8aSRaman Tenneti {
115*f0687c8aSRaman Tenneti 	string h = fmt::format("{}/{}/{}/{}/{}", hdisplay, hfp(), hsw(), hbp(), sync_to_char(hsync()));
116*f0687c8aSRaman Tenneti 	string v = fmt::format("{}/{}/{}/{}/{}", vdisplay, vfp(), vsw(), vbp(), sync_to_char(vsync()));
117*f0687c8aSRaman Tenneti 
118*f0687c8aSRaman Tenneti 	string str = fmt::format("{} {:.3f} {} {} {} ({:.2f}) {:#x} {:#x}",
119*f0687c8aSRaman Tenneti 				 to_string_short(),
120*f0687c8aSRaman Tenneti 				 clock / 1000.0,
121*f0687c8aSRaman Tenneti 				 h, v,
122*f0687c8aSRaman Tenneti 				 vrefresh, calculated_vrefresh(),
123*f0687c8aSRaman Tenneti 				 flags,
124*f0687c8aSRaman Tenneti 				 type);
125*f0687c8aSRaman Tenneti 
126*f0687c8aSRaman Tenneti 	return str;
127*f0687c8aSRaman Tenneti }
128*f0687c8aSRaman Tenneti 
to_string_long_padded() const129*f0687c8aSRaman Tenneti string Videomode::to_string_long_padded() const
130*f0687c8aSRaman Tenneti {
131*f0687c8aSRaman Tenneti 	string h = fmt::format("{}/{}/{}/{}/{}", hdisplay, hfp(), hsw(), hbp(), sync_to_char(hsync()));
132*f0687c8aSRaman Tenneti 	string v = fmt::format("{}/{}/{}/{}/{}", vdisplay, vfp(), vsw(), vbp(), sync_to_char(vsync()));
133*f0687c8aSRaman Tenneti 
134*f0687c8aSRaman Tenneti 	string str = fmt::format("{:<16} {:7.3f} {:<18} {:<18} {:2} ({:.2f}) {:#10x} {:#6x}",
135*f0687c8aSRaman Tenneti 				 to_string_short(),
136*f0687c8aSRaman Tenneti 				 clock / 1000.0,
137*f0687c8aSRaman Tenneti 				 h, v,
138*f0687c8aSRaman Tenneti 				 vrefresh, calculated_vrefresh(),
139*f0687c8aSRaman Tenneti 				 flags,
140*f0687c8aSRaman Tenneti 				 type);
141*f0687c8aSRaman Tenneti 
142*f0687c8aSRaman Tenneti 	return str;
143*f0687c8aSRaman Tenneti }
144*f0687c8aSRaman Tenneti 
videomode_from_timings(uint32_t clock_khz,uint16_t hact,uint16_t hfp,uint16_t hsw,uint16_t hbp,uint16_t vact,uint16_t vfp,uint16_t vsw,uint16_t vbp)145*f0687c8aSRaman Tenneti Videomode videomode_from_timings(uint32_t clock_khz,
146*f0687c8aSRaman Tenneti 				 uint16_t hact, uint16_t hfp, uint16_t hsw, uint16_t hbp,
147*f0687c8aSRaman Tenneti 				 uint16_t vact, uint16_t vfp, uint16_t vsw, uint16_t vbp)
148*f0687c8aSRaman Tenneti {
149*f0687c8aSRaman Tenneti 	Videomode m{};
150*f0687c8aSRaman Tenneti 	m.clock = clock_khz;
151*f0687c8aSRaman Tenneti 
152*f0687c8aSRaman Tenneti 	m.hdisplay = hact;
153*f0687c8aSRaman Tenneti 	m.hsync_start = hact + hfp;
154*f0687c8aSRaman Tenneti 	m.hsync_end = hact + hfp + hsw;
155*f0687c8aSRaman Tenneti 	m.htotal = hact + hfp + hsw + hbp;
156*f0687c8aSRaman Tenneti 
157*f0687c8aSRaman Tenneti 	m.vdisplay = vact;
158*f0687c8aSRaman Tenneti 	m.vsync_start = vact + vfp;
159*f0687c8aSRaman Tenneti 	m.vsync_end = vact + vfp + vsw;
160*f0687c8aSRaman Tenneti 	m.vtotal = vact + vfp + vsw + vbp;
161*f0687c8aSRaman Tenneti 
162*f0687c8aSRaman Tenneti 	return m;
163*f0687c8aSRaman Tenneti }
164*f0687c8aSRaman Tenneti 
165*f0687c8aSRaman Tenneti } // namespace kms
166