Merge branch 'am7xxx_set_zoom_mode'
authorAntonio Ospite <ospite@studenti.unina.it>
Fri, 27 Jul 2012 10:57:44 +0000 (12:57 +0200)
committerAntonio Ospite <ospite@studenti.unina.it>
Fri, 27 Jul 2012 10:57:44 +0000 (12:57 +0200)
contrib/libam7xxx_test_image_800x480.svg [new file with mode: 0644]
doc/man/am7xxx-play.1.txt
doc/man/picoproj.1.txt
examples/am7xxx-play.c
examples/picoproj.c
src/am7xxx.c
src/am7xxx.h

diff --git a/contrib/libam7xxx_test_image_800x480.svg b/contrib/libam7xxx_test_image_800x480.svg
new file mode 100644 (file)
index 0000000..4591d08
--- /dev/null
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="800"
+   height="480"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.3.1 r9886"
+   sodipodi:docname="libam7xxx_test_image_800x480.svg"
+   inkscape:export-filename="/home/ao2/libam7xxx_test_image_800x480.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.98994949"
+     inkscape:cx="350.20761"
+     inkscape:cy="242.81028"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1152"
+     inkscape:window-height="756"
+     inkscape:window-x="0"
+     inkscape:window-y="29"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Background"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-572.36218)"
+     style="display:inline"
+     sodipodi:insensitive="true">
+    <rect
+       style="color:#000000;fill:#000400;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2982"
+       width="800"
+       height="480"
+       x="0"
+       y="572.36218" />
+    <text
+       xml:space="preserve"
+       style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0.09px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
+       x="274.20743"
+       y="663.45349"
+       id="text3782"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3784"
+         x="274.20743"
+         y="663.45349">libam7xxx test screen</tspan></text>
+    <path
+       sodipodi:type="arc"
+       style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path3778"
+       sodipodi:cx="452.54834"
+       sodipodi:cy="296.15222"
+       sodipodi:rx="88.893425"
+       sodipodi:ry="76.771591"
+       d="m 541.44176,296.15222 a 88.893425,76.771591 0 1 1 -177.78685,0 88.893425,76.771591 0 1 1 177.78685,0 z"
+       transform="matrix(1.091899,0,0,1.2643041,-94.13708,437.93571)" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Original Size"
+     sodipodi:insensitive="true">
+    <rect
+       style="color:#000000;fill:none;stroke:#00ffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect3752"
+       width="799"
+       height="479"
+       x="0.5"
+       y="0.5" />
+    <text
+       xml:space="preserve"
+       style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0.09px;word-spacing:0px;fill:#00ffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
+       x="124.24876"
+       y="390.09644"
+       id="text3756"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3758"
+         x="124.24876"
+         y="390.09644">Original Size: 800x480 (aspect ratio 5:3)</tspan></text>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer3"
+     inkscape:label="Zoom 1: H Scale"
+     sodipodi:insensitive="true">
+    <rect
+       style="color:#000000;fill:none;stroke:#ffff00;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect3762"
+       width="589"
+       height="479"
+       x="105.5"
+       y="0.5"
+       inkscape:export-xdpi="90"
+       inkscape:export-ydpi="90" />
+    <text
+       xml:space="preserve"
+       style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0.09px;word-spacing:0px;fill:#ffff00;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
+       x="124.5183"
+       y="419.9223"
+       id="text3768"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3770"
+         x="124.5183"
+         y="419.9223">Zoom 1 (H scale): 590x480</tspan></text>
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Zoom 2: H/V Scale"
+     style="display:inline"
+     sodipodi:insensitive="true">
+    <rect
+       style="color:#000000;fill:none;stroke:#ff00ff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect3772"
+       width="799"
+       height="459"
+       x="0.5"
+       y="10.5" />
+    <text
+       xml:space="preserve"
+       style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0.09px;word-spacing:0px;fill:#ff00ff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
+       x="124.5183"
+       y="449.69543"
+       id="text3774"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3776"
+         x="124.5183"
+         y="449.69543">Zoom 2 (H/V Scale): 800x460</tspan></text>
+  </g>
+</svg>
index 5054da4..098e556 100644 (file)
@@ -53,11 +53,14 @@ EXAMPLE:
 *-l* '<log level>'::
     the verbosity level of libam7xxx output (0-5)
 
-*-p* '<power level>'::
-    power level of device, between 0 (off) and 4 (maximum) +
+*-p* '<power mode>'::
+    the power mode of device, between 0 (off) and 4 (turbo) +
     WARNING: Level 2 and greater require the master AND
              the slave connector to be plugged in.
 
+*-z* '<zoom mode>'::
+    the display zoom mode, between 0 (original) and 3 (test)
+
 *-h*::
     this help message
 
index ce56f0e..263b0df 100644 (file)
@@ -37,11 +37,14 @@ OPTIONS
 *-l* '<log level>'::
     the verbosity level of libam7xxx output (0-5)
 
-*-p* '<power level>'::
-    power level of device, between 0 (off) and 4 (maximum) +
+*-p* '<power mode>'::
+    the power mode of device, between 0 (off) and 4 (turbo) +
     WARNING: Level 2 and greater require the master AND
              the slave connector to be plugged in.
 
+*-z* '<zoom mode>'::
+    the display zoom mode, between 0 (original) and 3 (test)
+
 *-W* '<image width>'::
     the width of the image to upload
 
index 324ed89..6d5d3c7 100644 (file)
@@ -594,8 +594,12 @@ static void usage(char *name)
        printf("\t\t\t\t\t2 - NV12\n");
        printf("\t-q <quality>\t\tquality of jpeg sent to the device, between 1 and 100\n");
        printf("\t-l <log level>\t\tthe verbosity level of libam7xxx output (0-5)\n");
-       printf("\t-p <power level>\tpower level of device, between %x (off) and %x (maximum)\n", AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
-       printf("\t\t\t\tWARNING: Level 2 and greater require the master AND\n\t\t\t\t\t the slave connector to be plugged in.\n");
+       printf("\t-p <power mode>\t\tthe power mode of device, between %d (off) and %d (turbo)\n",
+              AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
+       printf("\t\t\t\tWARNING: Level 2 and greater require the master AND\n");
+       printf("\t\t\t\t         the slave connector to be plugged in.\n");
+       printf("\t-z <zoom mode>\t\tthe display zoom mode, between %d (original) and %d (test)\n",
+              AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST);
        printf("\t-h \t\t\tthis help message\n");
        printf("\n\nEXAMPLES OF USE:\n");
        printf("\t%s -f x11grab -i :0.0 -o video_size=800x480\n", name);
@@ -619,11 +623,12 @@ int main(int argc, char *argv[])
        unsigned int quality = 95;
        int log_level = AM7XXX_LOG_INFO;
        am7xxx_power_mode power_mode = AM7XXX_POWER_LOW;
+       am7xxx_zoom_mode zoom = AM7XXX_ZOOM_ORIGINAL;
        int format = AM7XXX_IMAGE_FORMAT_JPEG;
        am7xxx_context *ctx;
        am7xxx_device *dev;
 
-       while ((opt = getopt(argc, argv, "f:i:o:s:uF:q:l:p:h")) != -1) {
+       while ((opt = getopt(argc, argv, "f:i:o:s:uF:q:l:p:z:h")) != -1) {
                switch (opt) {
                case 'f':
                        input_format_string = strdup(optarg);
@@ -715,14 +720,30 @@ int main(int argc, char *argv[])
                        case AM7XXX_POWER_MIDDLE:
                        case AM7XXX_POWER_HIGH:
                        case AM7XXX_POWER_TURBO:
-                               fprintf(stdout, "Power mode: %x\n", power_mode);
+                               fprintf(stdout, "Power mode: %d\n", power_mode);
                                break;
                        default:
-                               fprintf(stderr, "Invalid power mode value, must be between %x and %x\n", AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
+                               fprintf(stderr, "Invalid power mode value, must be between %d and %d\n",
+                                       AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
                                ret = -EINVAL;
                                goto out;
                        }
                        break;
+               case 'z':
+                       zoom = atoi(optarg);
+                       switch(zoom) {
+                       case AM7XXX_ZOOM_ORIGINAL:
+                       case AM7XXX_ZOOM_H:
+                       case AM7XXX_ZOOM_H_V:
+                       case AM7XXX_ZOOM_TEST:
+                               fprintf(stdout, "Zoom: %d\n", zoom);
+                               break;
+                       default:
+                               fprintf(stderr, "Invalid zoom mode value, must be between %d and %d\n",
+                                       AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST);
+                               exit(EXIT_FAILURE);
+                       }
+                       break;
                case 'h':
                        usage(argv[0]);
                        ret = 0;
@@ -782,12 +803,22 @@ int main(int argc, char *argv[])
                goto cleanup;
        }
 
+       ret = am7xxx_set_zoom_mode(dev, zoom);
+       if (ret < 0) {
+               perror("am7xxx_set_zoom_mode");
+               goto cleanup;
+       }
+
        ret = am7xxx_set_power_mode(dev, power_mode);
        if (ret < 0) {
                perror("am7xxx_set_power_mode");
                goto cleanup;
        }
 
+       /* When setting AM7XXX_ZOOM_TEST don't display the actual image */
+       if (zoom == AM7XXX_ZOOM_TEST)
+               goto cleanup;
+
        ret = am7xxx_play(input_format_string,
                          &options,
                          input_path,
index 8503612..54cbedf 100644 (file)
@@ -41,8 +41,12 @@ static void usage(char *name)
        printf("\t\t\t\t\t1 - JPEG\n");
        printf("\t\t\t\t\t2 - NV12\n");
        printf("\t-l <log level>\t\tthe verbosity level of libam7xxx output (0-5)\n");
-       printf("\t-p <power level>\tpower level of device, between %x (off) and %x (maximum)\n", AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
-       printf("\t\t\t\tWARNING: Level 2 and greater require the master AND\n\t\t\t\t\t the slave connector to be plugged in.\n");
+       printf("\t-p <power mode>\t\tthe power mode of device, between %d (off) and %d (turbo)\n",
+              AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
+       printf("\t\t\t\tWARNING: Level 2 and greater require the master AND\n");
+       printf("\t\t\t\t         the slave connector to be plugged in.\n");
+       printf("\t-z <zoom mode>\t\tthe display zoom mode, between %d (original) and %d (test)\n",
+              AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST);
        printf("\t-W <image width>\tthe width of the image to upload\n");
        printf("\t-H <image height>\tthe height of the image to upload\n");
        printf("\t-h \t\t\tthis help message\n");
@@ -63,6 +67,7 @@ int main(int argc, char *argv[])
        am7xxx_device *dev;
        int log_level = AM7XXX_LOG_INFO;
        am7xxx_power_mode power_mode = AM7XXX_POWER_LOW;
+       am7xxx_zoom_mode zoom = AM7XXX_ZOOM_ORIGINAL;
        int format = AM7XXX_IMAGE_FORMAT_JPEG;
        int width = 800;
        int height = 480;
@@ -70,7 +75,7 @@ int main(int argc, char *argv[])
        unsigned int size;
        am7xxx_device_info device_info;
 
-       while ((opt = getopt(argc, argv, "f:F:l:p:W:H:h")) != -1) {
+       while ((opt = getopt(argc, argv, "f:F:l:p:z:W:H:h")) != -1) {
                switch (opt) {
                case 'f':
                        if (filename[0] != '\0')
@@ -106,10 +111,26 @@ int main(int argc, char *argv[])
                        case AM7XXX_POWER_MIDDLE:
                        case AM7XXX_POWER_HIGH:
                        case AM7XXX_POWER_TURBO:
-                               fprintf(stdout, "Power mode: %x\n", power_mode);
+                               fprintf(stdout, "Power mode: %d\n", power_mode);
                                break;
                        default:
-                               fprintf(stderr, "Invalid power mode value, must be between %x and %x\n", AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
+                               fprintf(stderr, "Invalid power mode value, must be between %d and %d\n",
+                                       AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
+                               exit(EXIT_FAILURE);
+                       }
+                       break;
+               case 'z':
+                       zoom = atoi(optarg);
+                       switch(zoom) {
+                       case AM7XXX_ZOOM_ORIGINAL:
+                       case AM7XXX_ZOOM_H:
+                       case AM7XXX_ZOOM_H_V:
+                       case AM7XXX_ZOOM_TEST:
+                               fprintf(stdout, "Zoom: %d\n", zoom);
+                               break;
+                       default:
+                               fprintf(stderr, "Invalid zoom mode value, must be between %d and %d\n",
+                                       AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST);
                                exit(EXIT_FAILURE);
                        }
                        break;
@@ -215,6 +236,13 @@ int main(int argc, char *argv[])
        printf("Native resolution: %dx%d\n",
               device_info.native_width, device_info.native_height);
 
+       ret = am7xxx_set_zoom_mode(dev, zoom);
+       if (ret < 0) {
+               perror("am7xxx_set_zoom_mode");
+               exit_code = EXIT_FAILURE;
+               goto cleanup;
+       }
+
        ret = am7xxx_set_power_mode(dev, power_mode);
        if (ret < 0) {
                perror("am7xxx_set_power_mode");
@@ -222,6 +250,11 @@ int main(int argc, char *argv[])
                goto cleanup;
        }
 
+       /* When setting AM7XXX_ZOOM_TEST don't display the actual image */
+       if (zoom == AM7XXX_ZOOM_TEST)
+               goto cleanup;
+
+
        if ((unsigned int)width > device_info.native_width ||
            (unsigned int)height > device_info.native_height)
                fprintf(stderr, "WARNING: image not fitting the native resolution, it may be displayed wrongly!\n");
index 24b2b50..5b98b84 100644 (file)
@@ -116,7 +116,7 @@ typedef enum {
        AM7XXX_PACKET_TYPE_DEVINFO = 0x01,
        AM7XXX_PACKET_TYPE_IMAGE   = 0x02,
        AM7XXX_PACKET_TYPE_POWER   = 0x04,
-       AM7XXX_PACKET_TYPE_UNKNOWN = 0x05,
+       AM7XXX_PACKET_TYPE_ZOOM    = 0x05,
 } am7xxx_packet_type;
 
 struct am7xxx_generic_header {
@@ -146,6 +146,11 @@ struct am7xxx_power_header {
        uint32_t bit0;
 };
 
+struct am7xxx_zoom_header {
+       uint32_t bit1;
+       uint32_t bit0;
+};
+
 /*
  * Examples of packet headers:
  *
@@ -171,6 +176,7 @@ struct am7xxx_header {
                struct am7xxx_devinfo_header devinfo;
                struct am7xxx_image_header image;
                struct am7xxx_power_header power;
+               struct am7xxx_zoom_header zoom;
        } header_data;
 };
 
@@ -211,6 +217,16 @@ static void debug_dump_power_header(am7xxx_context *ctx, struct am7xxx_power_hea
        debug(ctx, "\tbit0: 0x%08x (%u)\n", p->bit0, p->bit0);
 }
 
+static void debug_dump_zoom_header(am7xxx_context *ctx, struct am7xxx_zoom_header *z)
+{
+       if (ctx == NULL || z == NULL)
+               return;
+
+       debug(ctx, "Zoom header:\n");
+       debug(ctx, "\tbit1: 0x%08x (%u)\n", z->bit1, z->bit1);
+       debug(ctx, "\tbit0: 0x%08x (%u)\n", z->bit0, z->bit0);
+}
+
 static void debug_dump_header(am7xxx_context *ctx, struct am7xxx_header *h)
 {
        if (ctx == NULL || h == NULL)
@@ -236,6 +252,10 @@ static void debug_dump_header(am7xxx_context *ctx, struct am7xxx_header *h)
                debug_dump_power_header(ctx, &(h->header_data.power));
                break;
 
+       case AM7XXX_PACKET_TYPE_ZOOM:
+               debug_dump_zoom_header(ctx, &(h->header_data.zoom));
+               break;
+
        default:
                debug(ctx, "Packet type not supported!\n");
                break;
@@ -826,7 +846,7 @@ AM7XXX_PUBLIC int am7xxx_send_image(am7xxx_device *dev,
        return send_data(dev, image, image_size);
 }
 
-AM7XXX_PUBLIC int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode mode)
+AM7XXX_PUBLIC int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode power)
 {
        int ret;
        struct am7xxx_header h = {
@@ -837,7 +857,7 @@ AM7XXX_PUBLIC int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode mo
                .unknown3        = 0x10,
        };
 
-       switch(mode) {
+       switch(power) {
        case AM7XXX_POWER_OFF:
                h.header_data.power.bit2 = 0;
                h.header_data.power.bit1 = 0;
@@ -869,7 +889,51 @@ AM7XXX_PUBLIC int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode mo
                break;
 
        default:
-               error(dev->ctx, "Power mode not supported!\n");
+               error(dev->ctx, "Unsupported power mode.\n");
+               return -EINVAL;
+       };
+
+       ret = send_header(dev, &h);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+AM7XXX_PUBLIC int am7xxx_set_zoom_mode(am7xxx_device *dev, am7xxx_zoom_mode zoom)
+{
+       int ret;
+       struct am7xxx_header h = {
+               .packet_type     = AM7XXX_PACKET_TYPE_ZOOM,
+               .direction       = AM7XXX_DIRECTION_OUT,
+               .header_data_len = sizeof(struct am7xxx_zoom_header),
+               .unknown2        = 0x3e,
+               .unknown3        = 0x10,
+       };
+
+       switch(zoom) {
+       case AM7XXX_ZOOM_ORIGINAL:
+               h.header_data.zoom.bit1 = 0;
+               h.header_data.zoom.bit0 = 0;
+               break;
+
+       case AM7XXX_ZOOM_H:
+               h.header_data.zoom.bit1 = 0;
+               h.header_data.zoom.bit0 = 1;
+               break;
+
+       case AM7XXX_ZOOM_H_V:
+               h.header_data.zoom.bit1 = 1;
+               h.header_data.zoom.bit0 = 0;
+               break;
+
+       case AM7XXX_ZOOM_TEST:
+               h.header_data.zoom.bit1 = 1;
+               h.header_data.zoom.bit0 = 1;
+               break;
+
+       default:
+               error(dev->ctx, "Unsupported zoom mode.\n");
                return -EINVAL;
        };
 
index 51f9324..24636c3 100644 (file)
@@ -105,6 +105,24 @@ typedef enum {
 } am7xxx_power_mode;
 
 /**
+ * The display zoom modes.
+ *
+ * An am7xxx device can display images using several zoom modes.
+ *
+ * @note Changing the zoom mode can change the aspect ratio of the displayed
+ * image.
+ *
+ * @note On the zoom test screen the version of the firmware running on the
+ * device is shown as well (e.g SPI_V21.0.0_2011.03.18).
+ */
+typedef enum {
+       AM7XXX_ZOOM_ORIGINAL = 0, /**< Original Size, as retrieved via #am7xxx_device_info. */
+       AM7XXX_ZOOM_H        = 1, /**< Zoom 1: H Scale (changes aspect ratio). */
+       AM7XXX_ZOOM_H_V      = 2, /**< Zoom 2: H/V Scale (changes aspect ratio). */
+       AM7XXX_ZOOM_TEST     = 3, /**< Zoom test screen, the firmware version is shown as well. */
+} am7xxx_zoom_mode;
+
+/**
  * Initialize the library context and data structures, and scan for devices.
  *
  * @param[out] ctx A pointer to the context the library will be used in.
@@ -226,17 +244,38 @@ int am7xxx_send_image(am7xxx_device *dev,
 /**
  * Set the power mode of an am7xxx device.
  *
- * \note If we set the mode to AM7XXX_POWER_OFF we can't turn the
- * display on again by using only am7xxx_set_power_mode(). This needs to be
- * investigated, maybe some other command can reset the device.
+ * @note When setting the mode to AM7XXX_POWER_OFF the display can't be turned
+ * on again by using only am7xxx_set_power_mode(), am7xxx_set_zoom_mode() has
+ * to be called first, the current guess is that the latter performs some
+ * other resets beside setting the zoom mode.
  *
- * @param[in] dev A pointer to the structure representing the device to get info of
- * @param[in] mode The power mode to put the device in (see @link am7xxx_power_mode @endlink enum)
+ * @param[in] dev A pointer to the structure representing the device to set power mode to
+ * @param[in] power The power mode to put the device in (see #am7xxx_power_mode enum)
+ *
+ * @return 0 on success, a negative value on error
+ *
+ */
+int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode power);
+
+/**
+ * Set the zoom mode of an am7xxx device.
+ *
+ * @note When setting the mode to AM7XXX_ZOOM_TEST, the calling program might
+ * want to skip displaying actual images.
+ *
+ * @note It looks like that power mode and zoom mode are related somehow wrt.
+ * resetting the operational mode after AM7XXX_POWER_OFF, applications can
+ * restore the display properly using this combination:
+ *  - Off: power mode 0, zoom mode 3
+ *  - On: power mode != 0, zoom mode != 3
+ *
+ * @param[in] dev A pointer to the structure representing the device to set zoom mode to
+ * @param[in] zoom The zoom mode to put the device in (see #am7xxx_zoom_mode enum)
  *
  * @return 0 on success, a negative value on error
  *
  */
-int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode mode);
+int am7xxx_set_zoom_mode(am7xxx_device *dev, am7xxx_zoom_mode zoom);
 
 #ifdef __cplusplus
 }