summaryrefslogtreecommitdiff
path: root/kms++
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2019-01-10 13:59:34 +0200
committerTomi Valkeinen <tomi.valkeinen@ti.com>2019-01-14 09:27:28 +0200
commitf63f1b1a16269ddcce75a61d540429fe3d41cfc8 (patch)
tree33208ee6969537d7c4d732ba5f052699bdf185e9 /kms++
parent21c70a626cef72804f0ea270ffbae803e76e5b71 (diff)
Card: improve DRM card selection
Add new Card constructor: Card(const std::string& driver, uint32_t idx) which can be used to open Nth card for the given driver. The default constructor behavior is: - If KMSXX_DEVICE env variable is set, the card device with that path is opened. - If KMSXX_DRIVER env variable is set, the card with the given driver name and index is opened. The format is either "drvname" or "drvname:idx". - If neither env variable is given, open /dev/dri/card0 Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'kms++')
-rw-r--r--kms++/inc/kms++/card.h4
-rw-r--r--kms++/src/card.cpp91
2 files changed, 88 insertions, 7 deletions
diff --git a/kms++/inc/kms++/card.h b/kms++/inc/kms++/card.h
index 77f97a3..b96e1c1 100644
--- a/kms++/inc/kms++/card.h
+++ b/kms++/inc/kms++/card.h
@@ -14,7 +14,8 @@ class Card
friend class Framebuffer;
public:
Card();
- Card(const std::string& device);
+ Card(const std::string& dev_path);
+ Card(const std::string& driver, uint32_t idx);
virtual ~Card();
Card(const Card& other) = delete;
@@ -54,6 +55,7 @@ public:
const std::string& version_name() const { return m_version_name; }
private:
+ void setup();
void restore_modes();
std::map<uint32_t, DrmObject*> m_obmap;
diff --git a/kms++/src/card.cpp b/kms++/src/card.cpp
index a5c6d53..5d6a597 100644
--- a/kms++/src/card.cpp
+++ b/kms++/src/card.cpp
@@ -6,6 +6,7 @@
#include <string.h>
#include <algorithm>
#include <cerrno>
+#include <algorithm>
#include <xf86drm.h>
#include <xf86drmMode.h>
@@ -17,19 +18,97 @@ using namespace std;
namespace kms
{
+static int open_device_by_path(string path)
+{
+ int fd = open(path.c_str(), O_RDWR | O_CLOEXEC);
+ if (fd < 0)
+ throw invalid_argument(string(strerror(errno)) + " opening device " + path);
+ return fd;
+}
+
+// open Nth DRM card with the given driver name
+static int open_device_by_driver(string name, uint32_t idx)
+{
+ uint32_t matches = 0;
+
+ transform(name.begin(), name.end(), name.begin(), ::tolower);
+
+ for (uint32_t i = 0; ; ++i) {
+ string path = "/dev/dri/card" + to_string(i);
+
+ int fd = open(path.c_str(), O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ // presume no more card nodes
+ throw invalid_argument("no card found for " + name + ":" + to_string(idx));
+ }
+
+ drmVersionPtr ver = drmGetVersion(fd);
+ string drv_name = string(ver->name, ver->name_len);
+ drmFreeVersion(ver);
+
+ transform(drv_name.begin(), drv_name.end(), drv_name.begin(), ::tolower);
+
+ if (name == drv_name) {
+ if (idx == matches)
+ return fd;
+ matches++;
+ }
+
+ close(fd);
+ }
+}
+
Card::Card()
- : Card("/dev/dri/card0")
{
+ const char* drv_p = getenv("KMSXX_DRIVER");
+ const char* dev_p = getenv("KMSXX_DEVICE");
+
+ if (dev_p) {
+ string dev(dev_p);
+ m_fd = open_device_by_path(dev);
+ } else if (drv_p) {
+ string drv(drv_p);
+
+ auto isplit = find(drv.begin(), drv.end(), ':');
+
+ if (isplit == drv.begin())
+ throw runtime_error("Invalid KMSXX_DRIVER");
+
+ string name;
+ uint32_t num = 0;
+
+ if (isplit == drv.end()) {
+ name = drv;
+ } else {
+ name = string(drv.begin(), isplit);
+ string numstr = string(isplit + 1, drv.end());
+ num = stoul(numstr);
+ }
+
+ m_fd = open_device_by_driver(name, num);
+ } else {
+ m_fd = open_device_by_path("/dev/dri/card0");
+ }
+
+ setup();
}
+Card::Card(const std::string& driver, uint32_t idx)
+{
+ m_fd = open_device_by_driver(driver, idx);
+
+ setup();
+}
-Card::Card(const std::string& device)
+Card::Card(const std::string& dev_path)
{
- int fd = open(device.c_str(), O_RDWR | O_CLOEXEC);
- if (fd < 0)
- throw invalid_argument(string(strerror(errno)) + " opening " + device);
- m_fd = fd;
+ m_fd = open_device_by_path(dev_path);
+
+ setup();
+}
+void Card::setup()
+{
drmVersionPtr ver = drmGetVersion(m_fd);
m_version_major = ver->version_major;
m_version_minor = ver->version_minor;