blob: 76e01644fc3ea3f6cd9a91ec55949f1f277446cb [file] [log] [blame]
// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xlibint.h>
#include <X11/Xproto.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrandr.h>
#if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 2)
#define HAS_RANDR_1_2 1
#else
#error Only tested with xrandr 1.2
#endif
#include "ch7036.h"
#include "edid_utils.h"
#include "xrr_utils.h"
#define MAX_EDID_EXT 4
#define DEF_DEV "/dev/i2c-2"
static Display *dpy;
static Window root;
static int screen;
void usage(char *prog)
{
fprintf(stderr, "Usage: %s [-d<i2c device>|-n] [i|d|h|m|o] ...\n", prog);
fprintf(stderr, "-d: set i2c device to use (default %s)\n", DEF_DEV);
fprintf(stderr, "-g: set gpio device to use (default none)\n");
fprintf(stderr, "-n: Use dummy i2c device\n");
fprintf(stderr, "-v: Verbose, print every I2C access\n");
fprintf(stderr, "c - calculate and write in INC values\n");
fprintf(stderr, "m - monitor on\n");
fprintf(stderr, "o - monitor off (keep ddc)\n");
fprintf(stderr, "O - monitor off (power down ddc)\n");
fprintf(stderr, "r - reset and release datapath\n");
fprintf(stderr, "R - reset and release chip, regs go to defaults\n");
fprintf(stderr, "l <file> - Load firmware from file\n");
fprintf(stderr, "v - show MCU firmware version\n");
fprintf(stderr, "e - read and dump EDID\n");
fprintf(stderr, "E - dump test EDIDs\n");
fprintf(stderr, "a - wait for gpio to signal attatch\n");
fprintf(stderr, "d - wait for gpio to signal dettatch\n");
fprintf(stderr, "W<page>,<reg>,<value> - Write CH7036 register\n");
fprintf(stderr, "G<page>,<reg> - Get CH7036 register\n");
exit(1);
}
int main(int argc, char *argv[])
{
int i2cdev;
int gpiodev = 0;
char *i2cfile = DEF_DEV;
char *gpiofile = NULL;
int arg;
int err;
XRRModeInfo *xmode;
int dummy_i2c = 0;
for(arg=1; arg < argc; arg++) {
if ((argv[arg][0]) != '-') break;
switch (argv[arg][1]) {
default:
fprintf(stderr, "Unknown option: %s\n", argv[arg]);
usage(argv[0]);
case 'n':
dummy_i2c = 1;
break;
case 'v':
ch7036_debugi2c = 1;
break;
case 'd':
if (argv[arg][2] != 0)
i2cfile = argv[arg] + 2;
else {
if (++arg < argc)
i2cfile = argv[arg];
else {
fprintf(stderr, "-d needs filename: %s\n", argv[arg]);
usage(argv[0]);
}
}
break;
case 'g':
if (argv[arg][2] != 0)
gpiofile = argv[arg] + 2;
else {
if (++arg < argc)
gpiofile = argv[arg];
else {
fprintf(stderr, "-g needs filename: %s\n", argv[arg]);
usage(argv[0]);
}
}
break;
}
}
if (dummy_i2c)
i2cdev = -1;
else {
i2cdev = open(i2cfile, O_RDWR);
if (i2cdev < 0) {
fprintf(stderr, "Could not open %s: %s\n", i2cfile, strerror(errno));
exit(1);
}
}
if (gpiofile != NULL) {
gpiodev = open(gpiofile, O_RDONLY);
if (gpiodev < 0) {
fprintf(stderr, "Could not open %s: %s\n", gpiofile, strerror(errno));
exit(1);
}
}
/* CH7036 only has one slave address option */
if (dummy_i2c)
err = 0;
else
err = ioctl(i2cdev, I2C_SLAVE, CH7036_I2C_ADDR);
if (err < 0) {
fprintf(stderr, "Could not set slave address 0x%x: %s\n",
CH7036_I2C_ADDR, strerror(errno));
exit(1);
}
/* Read the information */
err = ch_read_reg(i2cdev, CH7036_DEVID);
fprintf(stderr, "Found device ID 0x%02x\n", err);
err = ch_read_reg(i2cdev, CH7036_HDMI_ST);
fprintf(stderr, "HDMI status 0x%02x: %s\n", err,
(err & 0x10) ? "connected (or firmware not running)":"not detected");
dpy = XOpenDisplay(":0.0");
if (dpy == NULL) {
fprintf(stderr, "Can't open display :0.0\n");
exit(1);
}
screen = DefaultScreen (dpy);
root = RootWindow (dpy, screen);
xmode = get_x_mode_info(dpy, root);
showmode(xmode);
for(;arg < argc; arg++) {
switch(argv[arg][0]) {
default:
fprintf(stderr,"Unknown command letter %s\n", argv[arg]);
usage(argv[0]);
break;
case 'c':
printf("Calc INCs\n");
ch_calculate_incs(i2cdev);
break;
case 'm':
printf("MONITOR on\n");
ch_monitor_on(i2cdev, 1, 1);
break;
case 'O':
printf("MONITOR off (and power down ddc)\n");
ch_monitor_off(i2cdev);
break;
case 'o':
printf("MONITOR off (keep ddc alive)\n");
ch_monitor_off_keep_ddc(i2cdev);
break;
case 'W':
{
int page, reg, value;
char *endn;
page = strtol(argv[arg] + 1, &endn, 0);
if (endn[0] != ',') {
fprintf(stderr, "Expecting 1st comma (W<page>,<reg>,<value>) in %s\n",
argv[arg]);
break;
}
reg = strtol(endn + 1, &endn, 0);
if (endn[0] != ',') {
fprintf(stderr, "Expecting 2nd comma (W<page>,<reg>,<value>) in %s\n",
argv[arg]);
break;
}
value = strtol(endn + 1, &endn, 0);
if (endn != argv[arg]) argv[arg] = endn - 1;
printf("Write 0x%x, 0x%x, 0x%x\n", page, reg, value);
ch_write_reg(i2cdev, page, reg, value);
break;
}
case 'G':
{
int page, reg, value;
char *endn;
page = strtol(argv[arg] + 1, &endn, 0);
if (endn[0] != ',') {
fprintf(stderr, "Expecting 1st comma (G<page>,<reg>) in %s\n",
argv[arg]);
break;
}
reg = strtol(endn + 1, &endn, 0);
if (endn != argv[arg]) argv[arg] = endn - 1;
value = ch_read_reg(i2cdev, page, reg);
printf("Read 0x%x, 0x%x --> 0x%x\n", page, reg, value);
break;
}
case 'r':
printf("RESET datapath\n");
ch_reset_datapath(i2cdev);
break;
case 'R':
printf("RESET to defaults\n");
ch_reset_todefault(i2cdev);
break;
case 'l':
if (arg > (argc-1)) {
fprintf(stderr, "No firmware filename found\n");
usage(argv[0]);
break;
}
printf("LOAD firmware %s\n", argv[arg+1]);
ch_load_firmware(i2cdev, argv[arg+1]);
arg++;
/* Make sure continuation check fails below */
if (argv[arg][0])
argv[arg][1] = 0;
else
argv[arg]--;
break;
case 'v':
printf("Get MCU firmware version\n");
ch_mcu_version(i2cdev, 1, 1);
break;
case 'E':
{
int i = 1;
while (show_test_edid(stdout, i) == 0) i++;
break;
}
case 'e':
{
int ext, i;
unsigned char edid[MAX_EDID_EXT*128];
printf("Get EDID\n");
err = ch_get_edid(i2cdev, 0, &edid[0]);
if (err < 0) {
fprintf(stderr, "Get EDID Failed (initial block)\n");
exit(1);
}
show_edid_data(stdout, &edid[0], 128, 0);
ext = edid[126]; // Number of extension blocks
if (ext > MAX_EDID_EXT) {
fprintf(stderr, "Too many EDID extensions (%d), using %d\n",
ext, MAX_EDID_EXT);
ext = MAX_EDID_EXT;
}
for(i = 1; i <= ext; i++) {
err = ch_get_edid(i2cdev, i, &edid[i*128]);
if (err < 0) {
fprintf(stderr, "Get EDID Failed (extension block %d)\n", i);
exit(1);
}
show_edid_data(stdout, &edid[i*128], 128, i * 128);
}
show_edid(stdout, &edid[0], ext);
}
break;
case 'a':
{
if (!gpiodev)
fprintf(stderr, "No gpio device to detect attach\n");
else {
while (ch_hdmi_gpio_detected(gpiodev, 1) == 0)
sleep(YIELD_GPIO_DETECT_SECS);
}
break;
}
case 'd':
{
if (!gpiodev)
fprintf(stderr, "No gpio device to detect detatch\n");
else {
while (ch_hdmi_gpio_detected(gpiodev, 1) == 1)
sleep(YIELD_GPIO_DETECT_SECS);
}
break;
}
}
if (argv[arg][1] != 0) {
argv[arg]++;
arg--;
}
}
close(i2cdev);
if (gpiodev) close(gpiodev);
return 0;
}