]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android/external-libkmsxx.git/blob - kms++/src/connector.cpp
91414317556b32f5f3c8bd59f6c2f89ac4b8d68c
[android/external-libkmsxx.git] / kms++ / src / connector.cpp
1 #include <stdio.h>
2 #include <iostream>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <cassert>
6 #include <cmath>
8 #include <kms++/kms++.h>
9 #include "helpers.h"
11 using namespace std;
13 namespace kms
14 {
16 #ifndef DRM_MODE_CONNECTOR_DPI
17 #define DRM_MODE_CONNECTOR_DPI 17
18 #endif
20 static const map<int, string> connector_names = {
21         { DRM_MODE_CONNECTOR_Unknown, "Unknown" },
22         { DRM_MODE_CONNECTOR_VGA, "VGA" },
23         { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
24         { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
25         { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
26         { DRM_MODE_CONNECTOR_Composite, "Composite" },
27         { DRM_MODE_CONNECTOR_SVIDEO, "S-Video" },
28         { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
29         { DRM_MODE_CONNECTOR_Component, "Component" },
30         { DRM_MODE_CONNECTOR_9PinDIN, "9-Pin-DIN" },
31         { DRM_MODE_CONNECTOR_DisplayPort, "DP" },
32         { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
33         { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
34         { DRM_MODE_CONNECTOR_TV, "TV" },
35         { DRM_MODE_CONNECTOR_eDP, "eDP" },
36         { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
37         { DRM_MODE_CONNECTOR_DSI, "DSI" },
38         { DRM_MODE_CONNECTOR_DPI, "DPI" },
39 };
41 static const map<int, string> connection_str = {
42         { 0, "<unknown>" },
43         { DRM_MODE_CONNECTED, "Connected" },
44         { DRM_MODE_DISCONNECTED, "Disconnected" },
45         { DRM_MODE_UNKNOWNCONNECTION, "Unknown" },
46 };
48 static const map<int, string> subpix_str = {
49 #define DEF_SUBPIX(c) { DRM_MODE_SUBPIXEL_##c, #c }
50         DEF_SUBPIX(UNKNOWN),
51         DEF_SUBPIX(HORIZONTAL_RGB),
52         DEF_SUBPIX(HORIZONTAL_BGR),
53         DEF_SUBPIX(VERTICAL_RGB),
54         DEF_SUBPIX(VERTICAL_BGR),
55         DEF_SUBPIX(NONE),
56 #undef DEF_SUBPIX
57 };
59 struct ConnectorPriv
60 {
61         drmModeConnectorPtr drm_connector;
62 };
64 Connector::Connector(Card &card, uint32_t id, uint32_t idx)
65         :DrmPropObject(card, id, DRM_MODE_OBJECT_CONNECTOR, idx)
66 {
67         m_priv = new ConnectorPriv();
69         m_priv->drm_connector = drmModeGetConnector(this->card().fd(), this->id());
70         assert(m_priv->drm_connector);
72         // XXX drmModeGetConnector() does forced probe, which seems to change (at least) EDID blob id.
73         // XXX So refresh the props again here.
74         refresh_props();
76         const auto& name = connector_names.at(m_priv->drm_connector->connector_type);
77         m_fullname = name + "-" + to_string(m_priv->drm_connector->connector_type_id);
78 }
80 Connector::~Connector()
81 {
82         drmModeFreeConnector(m_priv->drm_connector);
83         delete m_priv;
84 }
86 void Connector::refresh()
87 {
88         drmModeFreeConnector(m_priv->drm_connector);
90         m_priv->drm_connector = drmModeGetConnector(this->card().fd(), this->id());
91         assert(m_priv->drm_connector);
93         // XXX drmModeGetConnector() does forced probe, which seems to change (at least) EDID blob id.
94         // XXX So refresh the props again here.
95         refresh_props();
97         const auto& name = connector_names.at(m_priv->drm_connector->connector_type);
98         m_fullname = name + "-" + to_string(m_priv->drm_connector->connector_type_id);
99 }
101 void Connector::setup()
103         if (m_priv->drm_connector->encoder_id != 0)
104                 m_current_encoder = card().get_encoder(m_priv->drm_connector->encoder_id);
105         else
106                 m_current_encoder = 0;
108         if (m_current_encoder)
109                 m_saved_crtc = m_current_encoder->get_crtc();
110         else
111                 m_saved_crtc = 0;
114 void Connector::restore_mode()
116         if (m_saved_crtc)
117                 m_saved_crtc->restore_mode(this);
120 Videomode Connector::get_default_mode() const
122         if (m_priv->drm_connector->count_modes == 0)
123                 throw invalid_argument("no modes available\n");
124         drmModeModeInfo drmmode = m_priv->drm_connector->modes[0];
126         return drm_mode_to_video_mode(drmmode);
129 Videomode Connector::get_mode(const string& mode) const
131         auto c = m_priv->drm_connector;
133         for (int i = 0; i < c->count_modes; i++)
134                 if (mode == c->modes[i].name)
135                         return drm_mode_to_video_mode(c->modes[i]);
137         throw invalid_argument(mode + ": mode not found");
140 Videomode Connector::get_mode(unsigned xres, unsigned yres, float vrefresh, bool ilace) const
142         auto c = m_priv->drm_connector;
144         for (int i = 0; i < c->count_modes; i++) {
145                 Videomode m = drm_mode_to_video_mode(c->modes[i]);
147                 if (m.hdisplay != xres || m.vdisplay != yres)
148                         continue;
150                 if (ilace != m.interlace())
151                         continue;
153                 if (vrefresh && vrefresh != m.calculated_vrefresh())
154                         continue;
156                 return m;
157         }
159         // If not found, do another round using rounded vrefresh
161         for (int i = 0; i < c->count_modes; i++) {
162                 Videomode m = drm_mode_to_video_mode(c->modes[i]);
164                 if (m.hdisplay != xres || m.vdisplay != yres)
165                         continue;
167                 if (ilace != m.interlace())
168                         continue;
170                 if (vrefresh && vrefresh != roundf(m.calculated_vrefresh()))
171                         continue;
173                 return m;
174         }
176         throw invalid_argument("mode not found");
179 bool Connector::connected() const
181         return m_priv->drm_connector->connection == DRM_MODE_CONNECTED ||
182                         m_priv->drm_connector->connection == DRM_MODE_UNKNOWNCONNECTION;
185 vector<Crtc*> Connector::get_possible_crtcs() const
187         vector<Crtc*> crtcs;
189         for (int i = 0; i < m_priv->drm_connector->count_encoders; ++i) {
190                 auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]);
192                 auto l = enc->get_possible_crtcs();
194                 crtcs.insert(crtcs.end(), l.begin(), l.end());
195         }
197         return crtcs;
200 Crtc* Connector::get_current_crtc() const
202         if (m_current_encoder)
203                 return m_current_encoder->get_crtc();
204         else
205                 return 0;
208 uint32_t Connector::connector_type() const
210         return m_priv->drm_connector->connector_type;
213 uint32_t Connector::connector_type_id() const
215         return m_priv->drm_connector->connector_type_id;
218 uint32_t Connector::mmWidth() const
220         return m_priv->drm_connector->mmWidth;
223 uint32_t Connector::mmHeight() const
225         return m_priv->drm_connector->mmHeight;
228 uint32_t Connector::subpixel() const
230         return m_priv->drm_connector->subpixel;
233 const string& Connector::subpixel_str() const
235         return subpix_str.at(subpixel());
238 std::vector<Videomode> Connector::get_modes() const
240         vector<Videomode> modes;
242         for (int i = 0; i < m_priv->drm_connector->count_modes; i++)
243                 modes.push_back(drm_mode_to_video_mode(
244                                         m_priv->drm_connector->modes[i]));
246         return modes;
249 std::vector<Encoder*> Connector::get_encoders() const
251         vector<Encoder*> encoders;
253         for (int i = 0; i < m_priv->drm_connector->count_encoders; i++) {
254                 auto enc = card().get_encoder(m_priv->drm_connector->encoders[i]);
255                 encoders.push_back(enc);
256         }
257         return encoders;