From: Antonio Ospite <ospite@studenti.unina.it>
Date: Tue, 24 Jan 2012 15:43:23 +0000 (+0100)
Subject: Implement am7xxx_set_power_mode()
X-Git-Tag: v0.1.0~14
X-Git-Url: https://git.ao2.it/libam7xxx.git/commitdiff_plain/ad32c9df36e8ec1c5b336bdad10ae771298b4d39?ds=inline;hp=--cc

Implement am7xxx_set_power_mode()

The AM7XXX_PACKET_TYPE_POWER expects the power mode to be specified in
the header_data section of the header like a value between 0 and 4, but
with one bit per field, each field being a little-endian 32 bit integer.
---

ad32c9df36e8ec1c5b336bdad10ae771298b4d39
diff --git a/src/am7xxx.c b/src/am7xxx.c
index 483eaf7..7bd4a2c 100644
--- a/src/am7xxx.c
+++ b/src/am7xxx.c
@@ -38,6 +38,17 @@ static void dump_image_header(struct am7xxx_image_header *i)
 	printf("\timage size: 0x%08x (%u)\n", i->image_size, i->image_size);
 }
 
+static void dump_power_header(struct am7xxx_power_header *p)
+{
+	if (p == NULL)
+		return;
+
+	printf("Power header:\n");
+	printf("\tbit2: 0x%08x (%u)\n", p->bit2, p->bit2);
+	printf("\tbit1: 0x%08x (%u)\n", p->bit1, p->bit1);
+	printf("\tbit0: 0x%08x (%u)\n", p->bit0, p->bit0);
+}
+
 static void dump_header(struct am7xxx_header *h)
 {
 	if (h == NULL)
@@ -54,6 +65,10 @@ static void dump_header(struct am7xxx_header *h)
 		dump_image_header(&(h->header_data.image));
 		break;
 
+	case AM7XXX_PACKET_TYPE_POWER:
+		dump_power_header(&(h->header_data.power));
+		break;
+
 	default:
 		printf("Packet type not supported!\n");
 		break;
@@ -209,3 +224,56 @@ int am7xxx_send_image(am7xxx_device dev,
 
 	return send_data(dev, image, size);
 }
+
+int am7xxx_set_power_mode(am7xxx_device dev, am7xxx_power_mode mode)
+{
+	int ret;
+	struct am7xxx_header h = {
+		.packet_type     = AM7XXX_PACKET_TYPE_POWER,
+		.unknown0        = 0x00,
+		.header_data_len = sizeof(struct am7xxx_power_header),
+		.unknown2        = 0x3e,
+		.unknown3        = 0x10,
+	};
+
+	switch(mode) {
+	case AM7XXX_POWER_OFF:
+		h.header_data.power.bit2 = 0;
+		h.header_data.power.bit1 = 0;
+		h.header_data.power.bit0 = 0;
+		break;
+
+	case AM7XXX_POWER_LOW:
+		h.header_data.power.bit2 = 0;
+		h.header_data.power.bit1 = 0;
+		h.header_data.power.bit0 = 1;
+
+	case AM7XXX_POWER_MIDDLE:
+		h.header_data.power.bit2 = 0;
+		h.header_data.power.bit1 = 1;
+		h.header_data.power.bit0 = 0;
+		break;
+
+	case AM7XXX_POWER_HIGH:
+		h.header_data.power.bit2 = 0;
+		h.header_data.power.bit1 = 1;
+		h.header_data.power.bit0 = 1;
+		break;
+
+	case AM7XXX_POWER_TURBO:
+		h.header_data.power.bit2 = 1;
+		h.header_data.power.bit1 = 0;
+		h.header_data.power.bit0 = 0;
+		break;
+
+	default:
+		fprintf(stderr, "Unsupported power mode.\n");
+		return -EINVAL;
+	};
+
+	ret = send_header(dev, &h);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
diff --git a/src/am7xxx.h b/src/am7xxx.h
index 49510eb..6847796 100644
--- a/src/am7xxx.h
+++ b/src/am7xxx.h
@@ -41,10 +41,11 @@ typedef enum {
 } am7xxx_image_format;
 
 typedef enum {
-	AM7XXX_POWER_OFF  = 0,
-	AM7XXX_POWER_LOW  = 1,
-	AM7XXX_POWER_MID  = 2,
-	AM7XXX_POWER_HIGH = 3,
+	AM7XXX_POWER_OFF    = 0,
+	AM7XXX_POWER_LOW    = 1,
+	AM7XXX_POWER_MIDDLE = 2,
+	AM7XXX_POWER_HIGH   = 3,
+	AM7XXX_POWER_TURBO  = 4,
 } am7xxx_power_mode;
 
 struct am7xxx_generic_header {
@@ -62,9 +63,9 @@ struct am7xxx_image_header {
 };
 
 struct am7xxx_power_header {
-	uint32_t power_low;
-	uint32_t power_mid;
-	uint32_t power_high;
+	uint32_t bit2;
+	uint32_t bit1;
+	uint32_t bit0;
 };
 
 /*
@@ -107,6 +108,14 @@ int am7xxx_send_image(am7xxx_device dev,
 		      uint8_t *image,
 		      unsigned int size);
 
+/*
+ * 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().
+ *
+ * Remember to mention that when writing the API doc.
+ */
+int am7xxx_set_power_mode(am7xxx_device dev, am7xxx_power_mode mode);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/picoproj.c b/src/picoproj.c
index 6e95fdb..7485f71 100644
--- a/src/picoproj.c
+++ b/src/picoproj.c
@@ -130,6 +130,13 @@ int main(int argc, char *argv[])
 		goto out_munmap;
 	}
 
+	ret = am7xxx_set_power_mode(dev, AM7XXX_POWER_LOW);
+	if (ret < 0) {
+		perror("am7xxx_set_power_mode");
+		exit_code = EXIT_FAILURE;
+		goto cleanup;
+	}
+
 	ret = am7xxx_send_image(dev, format, width, height, image, size);
 	if (ret < 0) {
 		perror("am7xxx_send_image");