/*
 * ofbset - fbset for OMAP displays
 *
 * Copyright (c) 2010, Gražvydas Ignotas
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the organization nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define __user
#include "omapfb.h"

#define RET_CHECK(r, msg) \
	if (ret < 0) { \
		perror(msg); \
		return 1; \
	}

static void usage(void)
{
	fprintf(stderr, "usage:\n"
		"    -h, --help   : this help\n"
		"    -s, --show   : show current settings\n"
		"    -fb <device> : framebuffer device (default /dev/fb0)\n"
		"    -mem <bytes> : memory to reserve for this FB\n"
		"    -pos <x y>   : overlay position on display\n"
		"    -size <w h>  : overlay size\n"
		"    -en <{1,0}>  : enable/disable the overlay\n");

	exit(1);
}

int main(int argc, char *argv[])
{
	struct omapfb_plane_info pi;
	struct omapfb_mem_info mi;
	const char *fbname = "/dev/fb0";
	const char *newmem = NULL;
	const char *newx = NULL, *newy = NULL;
	const char *neww = NULL, *newh = NULL;
	const char *enable = NULL;
	int old_enable, show = 0, change = 0;
	int i, ret, fd;

	if (argc < 2)
		usage();

	for (i = 1; i < argc; i++) {
		if	(!strcmp(argv[i], "-s"))
			show = 1;
		else if (!strcmp(argv[i], "-fb") && i + 1 < argc)
			fbname = argv[++i];
		else if (!strcmp(argv[i], "-mem") && i + 1 < argc) {
			newmem = argv[++i];
			change = 1;
		}
		else if (!strcmp(argv[i], "-pos") && i + 2 < argc) {
			newx = argv[++i];
			newy = argv[++i];
			change = 1;
		}
		else if (!strcmp(argv[i], "-size") && i + 2 < argc) {
			neww = argv[++i];
			newh = argv[++i];
			change = 1;
		}
		else if (!strcmp(argv[i], "-en") && i + 1 < argc) {
			enable = argv[++i];
			change = 1;
		}
		else
			usage();
	}

	fd = open(fbname, O_RDWR);
	if (fd < 0) {
		fprintf(stderr, "open %s", fbname);
		perror("");
		return 1;
	}

	ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi);
	RET_CHECK(ret, "ioctl QUERY_PLANE");

	ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi);
	RET_CHECK(ret, "ioctl QUERY_MEM");

	if (show) {
		printf("pos:     %d %d\n", pi.pos_x, pi.pos_y);
		printf("size:    %d %d\n", pi.out_width, pi.out_height);
		printf("mem:     %d\n", mi.size);
		printf("enabled: %s\n", pi.enabled ? "yes" : "no");
	}
	if (!change)
		return 0;

	/* must disable when changing stuff */
	old_enable = pi.enabled;
	if (pi.enabled) {
		pi.enabled = 0;
		ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
		RET_CHECK(ret, "ioctl SETUP_PLANE");
	}

	if (newmem) {
		mi.size = strtoul(newmem, NULL, 0);
		ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);
		RET_CHECK(ret, "ioctl SETUP_MEM");
	}

	if (newx && newy) {
		pi.pos_x = atoi(newx);
		pi.pos_y = atoi(newy);
	}
	if (neww && newh) {
		pi.out_width = atoi(neww);
		pi.out_height = atoi(newh);
	}
	if (enable)
		pi.enabled = atoi(enable);
	else
		pi.enabled = old_enable;

	ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
	if (ret < 0) {
		perror("ioctl SETUP_PLANE");
		return 1;
	}

	close(fd);
	return 0;
}

