modedb_dmt: update table
[android/external-libkmsxx.git] / utils / kmstest.cpp
index ccddccbc7f27d6db9a89c48199179c3e20af1296..cfec7804bc2184ba88e5c8ff7607ea7de945605f 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <kms++/kms++.h>
 #include <kms++/modedb.h>
+#include <kms++/mode_cvt.h>
 
 #include <kms++util/kms++util.h>
 
@@ -45,6 +46,9 @@ static bool s_use_cea;
 static unsigned s_num_buffers = 1;
 static bool s_flip_mode;
 static bool s_flip_sync;
+static bool s_cvt;
+static bool s_cvt_v2;
+static bool s_cvt_vid_opt;
 
 static set<Crtc*> s_used_crtcs;
 static set<Plane*> s_used_planes;
@@ -101,71 +105,135 @@ static void get_default_crtc(Card& card, OutputInfo& output)
 
 static void parse_crtc(Card& card, const string& crtc_str, OutputInfo& output)
 {
-       // @12:1920x1200@60
-       const regex mode_re("(?:(@?)(\\d+):)?(?:(\\d+)x(\\d+)(i)?)(?:@([\\d\\.]+))?");
+       // @12:1920x1200i@60
+       // @12:33000000,800/210/30/16/-,480/22/13/10/-,i
+
+       const regex modename_re("(?:(@?)(\\d+):)?"      // @12:
+                               "(?:(\\d+)x(\\d+)(i)?)" // 1920x1200i
+                               "(?:@([\\d\\.]+))?");   // @60
+
+       const regex modeline_re("(?:(@?)(\\d+):)?"                      // @12:
+                               "(\\d+),"                               // 33000000,
+                               "(\\d+)/(\\d+)/(\\d+)/(\\d+)/([+-]),"   // 800/210/30/16/-,
+                               "(\\d+)/(\\d+)/(\\d+)/(\\d+)/([+-])"    // 480/22/13/10/-
+                               "(?:,([i]+))?"                          // ,i
+                               );
 
        smatch sm;
-       if (!regex_match(crtc_str, sm, mode_re))
-               EXIT("Failed to parse crtc option '%s'", crtc_str.c_str());
+       if (regex_match(crtc_str, sm, modename_re)) {
+               if (sm[2].matched) {
+                       bool use_id = sm[1].length() == 1;
+                       unsigned num = stoul(sm[2].str());
 
-       if (sm[2].matched) {
-               bool use_id = sm[1].length() == 1;
-               unsigned num = stoul(sm[2].str());
+                       if (use_id) {
+                               Crtc* c = card.get_crtc(num);
+                               if (!c)
+                                       EXIT("Bad crtc id '%u'", num);
 
-               if (use_id) {
-                       Crtc* c = card.get_crtc(num);
-                       if (!c)
-                               EXIT("Bad crtc id '%u'", num);
+                               output.crtc = c;
+                       } else {
+                               auto crtcs = card.get_crtcs();
 
-                       output.crtc = c;
-               } else {
-                       auto crtcs = card.get_crtcs();
+                               if (num >= crtcs.size())
+                                       EXIT("Bad crtc number '%u'", num);
 
-                       if (num >= crtcs.size())
-                               EXIT("Bad crtc number '%u'", num);
+                               output.crtc = crtcs[num];
+                       }
+               } else {
+                       output.crtc = output.connector->get_current_crtc();
+               }
 
-                       output.crtc = crtcs[num];
+               unsigned w = stoul(sm[3]);
+               unsigned h = stoul(sm[4]);
+               bool ilace = sm[5].matched ? true : false;
+               float refresh = sm[6].matched ? stof(sm[6]) : 0;
+
+               if (s_cvt) {
+                       output.mode = videomode_from_cvt(w, h, refresh, ilace, s_cvt_v2, s_cvt_vid_opt);
+               } else if (s_use_dmt) {
+                       try {
+                               output.mode = find_dmt(w, h, refresh, ilace);
+                       } catch (exception& e) {
+                               EXIT("Mode not found from DMT tables\n");
+                       }
+               } else if (s_use_cea) {
+                       try {
+                               output.mode = find_cea(w, h, refresh, ilace);
+                       } catch (exception& e) {
+                               EXIT("Mode not found from CEA tables\n");
+                       }
+               } else {
+                       try {
+                               output.mode = output.connector->get_mode(w, h, refresh, ilace);
+                       } catch (exception& e) {
+                               EXIT("Mode not found from the connector\n");
+                       }
                }
-       } else {
-               output.crtc = output.connector->get_current_crtc();
-       }
+       } else if (regex_match(crtc_str, sm, modeline_re)) {
+               if (sm[2].matched) {
+                       bool use_id = sm[1].length() == 1;
+                       unsigned num = stoul(sm[2].str());
 
-       unsigned w = stoul(sm[3]);
-       unsigned h = stoul(sm[4]);
-       bool ilace = sm[5].matched ? true : false;
-       float refresh = sm[6].matched ? stof(sm[6]) : 0;
+                       if (use_id) {
+                               Crtc* c = card.get_crtc(num);
+                               if (!c)
+                                       EXIT("Bad crtc id '%u'", num);
 
-       bool found_mode = false;
+                               output.crtc = c;
+                       } else {
+                               auto crtcs = card.get_crtcs();
 
-       try {
-               output.mode = output.connector->get_mode(w, h, refresh, ilace);
-               found_mode = true;
-       } catch (exception& e) { }
+                               if (num >= crtcs.size())
+                                       EXIT("Bad crtc number '%u'", num);
 
-       if (!found_mode && s_use_dmt) {
-               try {
-                       output.mode = find_dmt(w, h, refresh, ilace);
-                       found_mode = true;
-                       printf("Found mode from DMT\n");
-               } catch (exception& e) { }
-       }
+                               output.crtc = crtcs[num];
+                       }
+               } else {
+                       output.crtc = output.connector->get_current_crtc();
+               }
 
-       if (!found_mode && s_use_cea) {
-               try {
-                       output.mode = find_cea(w, h, refresh, ilace);
-                       found_mode = true;
-                       printf("Found mode from CEA\n");
-               } catch (exception& e) { }
+               unsigned clock = stoul(sm[3]);
+
+               unsigned hact = stoul(sm[4]);
+               unsigned hfp = stoul(sm[5]);
+               unsigned hsw = stoul(sm[6]);
+               unsigned hbp = stoul(sm[7]);
+               bool h_pos_sync = sm[8] == "+" ? true : false;
+
+               unsigned vact = stoul(sm[9]);
+               unsigned vfp = stoul(sm[10]);
+               unsigned vsw = stoul(sm[11]);
+               unsigned vbp = stoul(sm[12]);
+               bool v_pos_sync = sm[13] == "+" ? true : false;
+
+               output.mode = videomode_from_timings(clock / 1000, hact, hfp, hsw, hbp, vact, vfp, vsw, vbp);
+               output.mode.set_hsync(h_pos_sync ? SyncPolarity::Positive : SyncPolarity::Negative);
+               output.mode.set_vsync(v_pos_sync ? SyncPolarity::Positive : SyncPolarity::Negative);
+
+               if (sm[14].matched) {
+                       for (int i = 0; i < sm[14].length(); ++i) {
+                               char f = string(sm[14])[i];
+
+                               switch (f) {
+                               case 'i':
+                                       output.mode.set_interlace(true);
+                                       break;
+                               default:
+                                       EXIT("Bad mode flag %c", f);
+                               }
+                       }
+               }
+       } else {
+               EXIT("Failed to parse crtc option '%s'", crtc_str.c_str());
        }
-
-       if (!found_mode)
-               throw invalid_argument("Mode not found");
 }
 
 static void parse_plane(Card& card, const string& plane_str, const OutputInfo& output, PlaneInfo& pinfo)
 {
        // 3:400,400-400x400
-       const regex plane_re("(?:(@?)(\\d+):)?(?:(\\d+),(\\d+)-)?(\\d+)x(\\d+)");
+       const regex plane_re("(?:(@?)(\\d+):)?"         // 3:
+                            "(?:(\\d+),(\\d+)-)?"      // 400,400-
+                            "(\\d+)x(\\d+)");          // 400x400
 
        smatch sm;
        if (!regex_match(plane_str, sm, plane_re))
@@ -239,7 +307,9 @@ static vector<DumbFramebuffer*> parse_fb(Card& card, const string& fb_str, unsig
        if (!fb_str.empty()) {
                // XXX the regexp is not quite correct
                // 400x400-NV12
-               const regex fb_re("(?:(\\d+)x(\\d+))?(?:-)?(\\w\\w\\w\\w)?");
+               const regex fb_re("(?:(\\d+)x(\\d+))?"          // 400x400
+                                 "(?:-)?"                      // -
+                                 "(\\w\\w\\w\\w)?");           // NV12
 
                smatch sm;
                if (!regex_match(fb_str, sm, fb_re))
@@ -262,16 +332,19 @@ static vector<DumbFramebuffer*> parse_fb(Card& card, const string& fb_str, unsig
 }
 
 static const char* usage_str =
-               "Usage: testpat [OPTION]...\n\n"
+               "Usage: kmstest [OPTION]...\n\n"
                "Show a test pattern on a display or plane\n\n"
                "Options:\n"
                "      --device=DEVICE       DEVICE is the path to DRM card to open\n"
                "  -c, --connector=CONN      CONN is <connector>\n"
                "  -r, --crtc=CRTC           CRTC is [<crtc>:]<w>x<h>[@<Hz>]\n"
+               "                            or\n"
+               "                            [<crtc>:]<pclk>,<hact>/<hfp>/<hsw>/<hbp>/<hsp>,<vact>/<vfp>/<vsw>/<vbp>/<vsp>[,i]\n"
                "  -p, --plane=PLANE         PLANE is [<plane>:][<x>,<y>-]<w>x<h>\n"
                "  -f, --fb=FB               FB is [<w>x<h>][-][<4cc>]\n"
                "      --dmt                 Search for the given mode from DMT tables\n"
                "      --cea                 Search for the given mode from CEA tables\n"
+               "      --cvt=CVT             Create videomode with CVT. CVT is 'v1', 'v2' or 'v2o'\n"
                "      --flip                Do page flipping for each output\n"
                "      --sync                Synchronize page flipping\n"
                "\n"
@@ -281,18 +354,18 @@ static const char* usage_str =
                "Options can be given multiple times to set up multiple displays or planes.\n"
                "Options may apply to previous options, e.g. a plane will be set on a crtc set in\n"
                "an earlier option.\n"
-               "If you omit parameters, testpat tries to guess what you mean\n"
+               "If you omit parameters, kmstest tries to guess what you mean\n"
                "\n"
                "Examples:\n"
                "\n"
                "Set eDP-1 mode to 1920x1080@60, show XR24 framebuffer on the crtc, and a 400x400 XB24 plane:\n"
-               "    testpat -c eDP-1 -r 1920x1080@60 -f XR24 -p 400x400 -f XB24\n\n"
+               "    kmstest -c eDP-1 -r 1920x1080@60 -f XR24 -p 400x400 -f XB24\n\n"
                "XR24 framebuffer on first connected connector in the default mode:\n"
-               "    testpat -f XR24\n\n"
+               "    kmstest -f XR24\n\n"
                "XR24 framebuffer on a 400x400 plane on the first connected connector in the default mode:\n"
-               "    testpat -p 400x400 -f XR24\n\n"
+               "    kmstest -p 400x400 -f XR24\n\n"
                "Test pattern on the second connector with default mode:\n"
-               "    testpat -c 1\n"
+               "    kmstest -c 1\n"
                ;
 
 static void usage()
@@ -360,6 +433,19 @@ static vector<Arg> parse_cmdline(int argc, char **argv)
                {
                        s_flip_sync = true;
                }),
+               Option("|cvt=", [&](string s)
+               {
+                       if (s == "v1")
+                               s_cvt = true;
+                       else if (s == "v2")
+                               s_cvt = s_cvt_v2 = true;
+                       else if (s == "v2o")
+                               s_cvt = s_cvt_v2 = s_cvt_vid_opt = true;
+                       else {
+                               usage();
+                               exit(-1);
+                       }
+               }),
                Option("h|help", [&]()
                {
                        usage();
@@ -598,20 +684,20 @@ static void set_crtcs_n_planes(Card& card, const vector<OutputInfo>& outputs)
                auto conn = o.connector;
                auto crtc = o.crtc;
 
-               if (!o.fbs.empty()) {
-                       auto fb = o.fbs[0];
+               blobs.emplace_back(o.mode.to_blob(card));
+               Blob* mode_blob = blobs.back().get();
 
-                       blobs.emplace_back(o.mode.to_blob(card));
-                       Blob* mode_blob = blobs.back().get();
+               req.add(conn, {
+                               { "CRTC_ID", crtc->id() },
+                       });
 
-                       req.add(conn, {
-                                       { "CRTC_ID", crtc->id() },
-                               });
+               req.add(crtc, {
+                               { "ACTIVE", 1 },
+                               { "MODE_ID", mode_blob->id() },
+                       });
 
-                       req.add(crtc, {
-                                       { "ACTIVE", 1 },
-                                       { "MODE_ID", mode_blob->id() },
-                               });
+               if (!o.fbs.empty()) {
+                       auto fb = o.fbs[0];
 
                        req.add(o.primary_plane, {
                                        { "FB_ID", fb->id() },