/*
 *  PS3 video mode utility.
 *
 *  Copyright (C) 2006 Sony Computer Entertainment Inc.
 *  Copyright 2006 Sony Corp.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
#include <stdint.h>
#include <sys/ioctl.h>

#include "ps3-av.h"

#define PS3_UTILS_APP_NAME "ps3-video-mode"

#if defined(PACKAGE_VERSION) && defined(PACKAGE_NAME)
#define PS3_UTILS_VERSION PS3_UTILS_APP_NAME " (" PACKAGE_NAME ") " PACKAGE_VERSION "\n\n"
#else
#define PS3_UTILS_VERSION ""
#endif

#if defined(PACKAGE_BUGREPORT)
#define PS3_UTILS_BUGREPORT "Send bug reports to " PACKAGE_BUGREPORT ".\n\n"
#else
#define PS3_UTILS_BUGREPORT ""
#endif

#define FB_NAME "/dev/fb0"

#define PS3FB_IOCTL_SETMODE          _IOW('r',  1, int)
#define PS3FB_IOCTL_GETMODE          _IOR('r',  2, int)

struct option long_options[] = {
	{ "help"  , 0, NULL, 'h' },
	{ "video" , 1, NULL, 'v' }, /* video mode */
	{ "rgb"   , 0, NULL, 'r' }, /* RGB color space */
	{ "full"  , 0, NULL, 'f' }, /* full screen mode */
	{ "color" , 0, NULL, 'c' }, /* HDMI full range */
	{ "dither", 0, NULL, 'd' }, /* dither ON */
	{ "hdcp"  , 0, NULL, 'H' }, /* HDCP OFF, Retail PS3 product doesn't support this */
	{ NULL    , 0, NULL,  0  }
};

static void usage(void)
{
	printf(PS3_UTILS_VERSION);
	printf(
	"Usage:\n"
	"  " PS3_UTILS_APP_NAME " [options]\n"
	"\n"
	"Options:\n"
	"  --help,  -h          print this message\n"
	"  --video, -v <ID>     set video mode ID\n"
	"  --full,  -f          use full screen mode\n"
	"  --color, -c          use HDMI full range\n"
	"  --dither,-d          use dither ON mode\n"
	"\n"
	"Video mode ID:\n"
	"  0:auto mode \n"
	"  YUV 60Hz  1:480i  2:480p  3:720p  4:1080i  5:1080p\n"
	"  YUV 50Hz  6:576i  7:576p  8:720p  9:1080i 10:1080p\n"
	"  RGB 60Hz 33:480i 34:480p 35:720p 36:1080i 37:1080p\n"
	"  RGB 50Hz 38:576i 39:576p 40:720p 41:1080i 42:1080p\n"
	"  VESA     11:WXGA 12:SXGA 13:WUXGA\n"
	"\n"
	"  full screen mode: <video mode ID> + 128\n"
	"  dither ON mode  : <video mode ID> + 2048\n" 
	"\n"
	"Example:\n"
	"  " PS3_UTILS_APP_NAME " -v 3 -f    720p 60Hz with full screen mode.\n"
	"  " PS3_UTILS_APP_NAME " -v 131     Same as above.\n"
	"\n"
	"If no argument is given, displays the current video mode.\n"
	);
	printf(PS3_UTILS_BUGREPORT);
	exit(1);
}

int main(int argc, char *argv[])
{
	int fd, res, c;
	int vid = -1;
	int opt = 0;

	while((c = getopt_long(argc, argv, "hv:rfcdH", long_options, NULL))
		!= EOF) {
		switch(c) {
		case 'v':
			vid = atoi(optarg);
			break;
		case 'r':
			opt |= PS3AV_MODE_RGB;
			break;
		case 'f':
			opt |= PS3AV_MODE_FULL;
			break;
		case 'c':
			opt |= PS3AV_MODE_COLOR;
			opt |= PS3AV_MODE_WHITE;
			break;
		case 'd':
			opt |= PS3AV_MODE_DITHER;
			break;
		case 'H':
			opt |= PS3AV_MODE_HDCP_OFF;
			break;
		case 'h':
		default:
			usage();
			exit(1);
			break;
		}
	}

	vid |= opt;

	/* open device */
	if ((fd = open(FB_NAME, O_RDWR)) < 0) {
		printf("error open:%d\n", fd);
		return -1;
	}

	/* ioctl */
	if (vid < 0) {
		vid = 0;
		if ((res = ioctl(fd, PS3FB_IOCTL_GETMODE, (unsigned long)&vid)) 
				< 0) {
			printf("PS3FB_IOCTL_GETMODE failed, status %d\n", res);
		} else {
			printf("%d\n", vid);
		}
	} else {
		if ((res = ioctl(fd, PS3FB_IOCTL_SETMODE, (unsigned long)&vid))
				< 0) {
			printf("PS3FB_IOCTL_SETMODE failed, status %d\n", res);
		} else {
			printf("video mode:%d\n", vid);
		}
	}

	/* close device */
	close(fd);

	return 0;
}

