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