summaryrefslogtreecommitdiff
path: root/v4l2-apps/util
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-apps/util')
-rwxr-xr-xv4l2-apps/util/parse_em28xx.pl278
-rw-r--r--v4l2-apps/util/qv4l2/qv4l2.cpp58
-rw-r--r--v4l2-apps/util/qv4l2/qv4l2.h3
-rw-r--r--v4l2-apps/util/v4l2-ctl.cpp37
-rw-r--r--v4l2-apps/util/v4l2-dbg-ac97.h67
-rw-r--r--v4l2-apps/util/v4l2-dbg-em28xx.h16
-rw-r--r--v4l2-apps/util/v4l2-dbg-tvp5150.h97
-rw-r--r--v4l2-apps/util/v4l2-dbg.cpp137
8 files changed, 669 insertions, 24 deletions
diff --git a/v4l2-apps/util/parse_em28xx.pl b/v4l2-apps/util/parse_em28xx.pl
new file mode 100755
index 000000000..d1bbb0f0d
--- /dev/null
+++ b/v4l2-apps/util/parse_em28xx.pl
@@ -0,0 +1,278 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2008 Mauro Carvalho Chehab <mchehab@redhat.com>
+#
+# 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.
+#
+# This small script parses register dumps generated by em28xx driver
+# with debug options enabled, generating a source code with the results
+# of the dump.
+#
+# To use it, you may modprobe em28xx with reg_debug=1, and do:
+# dmesg | ./parse_em28xx.pl
+#
+# Also, there are other utilities that produce similar outputs, and it
+# is not hard to parse some USB analyzers log into the expected format.
+#
+# It will parse anything (including this file) with a format similar to:
+#
+# 40 00 00 00 48 00 01 00 >>> 00
+# 40 00 00 00 12 00 01 00 >>> 37
+# 40 00 00 00 08 00 01 00 >>> 3d
+# 40 00 00 00 08 00 01 00 >>> 2d
+# 40 00 00 00 08 00 01 00 >>> 3d
+# 40 00 00 00 48 00 01 00 >>> 00
+# 40 00 00 00 12 00 01 00 >>> 37
+# 40 00 00 00 08 00 01 00 >>> 3d
+# 40 00 00 00 08 00 01 00 >>> 2d
+# 40 00 00 00 08 00 01 00 >>> 3d
+# c0 00 00 00 43 00 01 00 <<< 00
+# 40 00 00 00 42 00 01 00 >>> fc
+# c0 00 00 00 40 00 02 00 <<< ff ff
+# c0 00 00 00 43 00 01 00 <<< 00
+# 40 00 00 00 42 00 01 00 >>> fe
+# c0 00 00 00 40 00 02 00 <<< ff ff
+# c0 00 00 00 43 00 01 00 <<< 00
+# 40 00 00 00 42 00 01 00 >>> 80
+# c0 00 00 00 40 00 02 00 <<< 90 6a
+#
+# Producing a much easier to understand series of C function calls:
+#
+# em28xx_write_reg(dev, 0x48, 0x00);
+# em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37);
+# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x3d);
+# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x2d);
+# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x3d);
+# em28xx_write_reg(dev, 0x48, 0x00);
+# em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37);
+# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x3d);
+# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x2d);
+# em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x3d);
+# em28xx_read_ac97(dev, AC97_VENDOR_ID1); /* read 0x0xffff */
+# em28xx_read_ac97(dev, AC97_VENDOR_ID2); /* read 0x0xffff */
+# em28xx_read_ac97(dev, AC97_RESET); /* read 0x0x6a90 */
+#
+# This way, it is easier to understand what the em28xx driver is doing.
+#
+# Known limitations:
+# - Currently, the tool only parses em28xx, ac97 and em202 registers.
+# - It is limited to read/write operations with 1 or 2 bytes of
+# arguments;
+# - Not all registers are documented;
+# - It doesn't parse em2800-only registers;
+# - em28xx currently doesn't implement em28xx_read_reg16() or
+# em28xx_write_reg16(). However, this tool uses those two "functions"
+# meaning to read or write 2 consecutive bytes, ordering arguments
+# in big-endian notation.
+#
+
+use strict;
+
+my %reg_map = (
+ "0x00" => "EM28XX_R00_CHIPCFG",
+ "0x04" => "EM2880_R04_GPO",
+ "0x08" => "EM28XX_R08_GPIO",
+ "0x06" => "EM28XX_R06_I2C_CLK",
+ "0x0a" => "EM28XX_R0A_CHIPID",
+ "0x0c" => "EM28XX_R0C_USBSUSP",
+ "0x0e" => "EM28XX_R0E_AUDIOSRC",
+ "0x0f" => "EM28XX_R0F_XCLK",
+ "0x20" => "EM28XX_XCLK_IR_RC5_MODE",
+ "0x10" => "EM28XX_R10_VINMODE",
+ "0x11" => "EM28XX_R11_VINCTRL",
+ "0x12" => "EM28XX_R12_VINENABLE",
+ "0x14" => "EM28XX_R14_GAMMA",
+ "0x15" => "EM28XX_R15_RGAIN",
+ "0x16" => "EM28XX_R16_GGAIN",
+ "0x17" => "EM28XX_R17_BGAIN",
+ "0x18" => "EM28XX_R18_ROFFSET",
+ "0x19" => "EM28XX_R19_GOFFSET",
+ "0x1a" => "EM28XX_R1A_BOFFSET",
+ "0x1b" => "EM28XX_R1B_OFLOW",
+ "0x1c" => "EM28XX_R1C_HSTART",
+ "0x1d" => "EM28XX_R1D_VSTART",
+ "0x1e" => "EM28XX_R1E_CWIDTH",
+ "0x1f" => "EM28XX_R1F_CHEIGHT",
+ "0x20" => "EM28XX_R20_YGAIN",
+ "0x21" => "EM28XX_R21_YOFFSET",
+ "0x22" => "EM28XX_R22_UVGAIN",
+ "0x23" => "EM28XX_R23_UOFFSET",
+ "0x24" => "EM28XX_R24_VOFFSET",
+ "0x25" => "EM28XX_R25_SHARPNESS",
+ "0x26" => "EM28XX_R26_COMPR",
+ "0x27" => "EM28XX_R27_OUTFMT",
+ "0x28" => "EM28XX_R28_XMIN",
+ "0x29" => "EM28XX_R29_XMAX",
+ "0x2a" => "EM28XX_R2A_YMIN",
+ "0x2b" => "EM28XX_R2B_YMAX",
+ "0x30" => "EM28XX_R30_HSCALELOW",
+ "0x31" => "EM28XX_R31_HSCALEHIGH",
+ "0x32" => "EM28XX_R32_VSCALELOW",
+ "0x33" => "EM28XX_R33_VSCALEHIGH",
+ "0x40" => "EM28XX_R40_AC97LSB",
+ "0x41" => "EM28XX_R41_AC97MSB",
+ "0x42" => "EM28XX_R42_AC97ADDR",
+ "0x43" => "EM28XX_R43_AC97BUSY",
+ "0x45" => "EM28XX_R45_IR",
+ "0x50" => "EM2874_R50_IR_CONFIG",
+ "0x51" => "EM2874_R51_IR",
+ "0x5f" => "EM2874_R5F_TS_ENABLE",
+ "0x80" => "EM2874_R80_GPIO",
+);
+
+my %ac97_map = (
+ "0x00" => "AC97_RESET",
+ "0x02" => "AC97_MASTER_VOL",
+ "0x04" => "AC97_LINE_LEVEL_VOL",
+ "0x06" => "AC97_MASTER_MONO_VOL",
+ "0x0a" => "AC97_PC_BEEP_VOL",
+ "0x0c" => "AC97_PHONE_VOL",
+ "0x0e" => "AC97_MIC_VOL",
+ "0x10" => "AC97_LINEIN_VOL",
+ "0x12" => "AC97_CD_VOL",
+ "0x14" => "AC97_VIDEO_VOL",
+ "0x16" => "AC97_AUX_VOL",
+ "0x18" => "AC97_PCM_OUT_VOL",
+ "0x1a" => "AC97_RECORD_SELECT",
+ "0x1c" => "AC97_RECORD_GAIN",
+ "0x20" => "AC97_GENERAL_PURPOSE",
+ "0x22" => "AC97_3D_CTRL",
+ "0x24" => "AC97_AUD_INT_AND_PAG",
+ "0x26" => "AC97_POWER_DOWN_CTRL",
+ "0x28" => "AC97_EXT_AUD_ID",
+ "0x2a" => "AC97_EXT_AUD_CTRL",
+ "0x2c" => "AC97_PCM_OUT_FRONT_SRATE",
+ "0x2e" => "AC97_PCM_OUT_SURR_SRATE",
+ "0x30" => "AC97_PCM_OUT_LFE_SRATE",
+ "0x32" => "AC97_PCM_IN_SRATE",
+ "0x36" => "AC97_LFE_MASTER_VOL",
+ "0x38" => "AC97_SURR_MASTER_VOL",
+ "0x3a" => "AC97_SPDIF_OUT_CTRL",
+ "0x7c" => "AC97_VENDOR_ID1",
+ "0x7e" => "AC97_VENDOR_ID2",
+
+ # em202 specific AC97 registers
+
+ "0x3e" => "EM202_EXT_MODEM_CTRL",
+ "0x4c" => "EM202_GPIO_CONF",
+ "0x4e" => "EM202_GPIO_POLARITY",
+ "0x50" => "EM202_GPIO_STICKY",
+ "0x52" => "EM202_GPIO_MASK",
+ "0x54" => "EM202_GPIO_STATUS",
+ "0x6a" => "EM202_SPDIF_OUT_SEL",
+ "0x72" => "EM202_ANTIPOP",
+ "0x74" => "EM202_EAPD_GPIO_ACCESS",
+);
+
+my ($r40, $r42, $r43, $dir);
+
+sub output_ac97()
+{
+ if (hex($r42) < 0x80) {
+ if ($dir < 0) {
+ return;
+ }
+ $r42 = $ac97_map{$r42} if defined($ac97_map{$r42});
+ printf "em28xx_write_ac97(dev, %s, %s);\n",$r42, $r40;
+ $r43 = 0;
+
+ return;
+ }
+
+ if ($dir > 0) {
+ return;
+ }
+ $r42 = sprintf("0x%02x", hex($r42) - 0x80);
+ $r42 = $ac97_map{$r42} if defined($ac97_map{$r42});
+ printf "em28xx_read_ac97(dev, %s);\t/* read 0x%s */\n",$r42, $r40;
+ $r43 = 0;
+}
+
+while (<>) {
+ tr/A-F/a-f/;
+ if (m/c0 00 00 00 ([0-9a-f].) 00 01 00\s+[\<]+\s+([0-9a-f].)/) {
+ if ($1 eq "43" && $2 eq "00") {
+ $r43 = 1;
+ $r40 = -1;
+ $r42 = -1;
+ $dir = 0;
+ next;
+ }
+
+ my $reg = "0x$1";
+ $reg = $reg_map{$reg} if defined($reg_map{$reg});
+
+ printf "em28xx_read_reg(dev, %s);\t\t/* read 0x%s */\n",
+ $reg, $2;
+ next;
+ }
+ if (m/40 00 00 00 ([0-9a-f].) 00 01 00\s+[\>]+\s+([0-9a-f].)/) {
+ if ($r43 == 1) {
+ if ($1 eq "42") {
+ $r42 = "0x$2";
+ if ($r40 >= 0) {
+ output_ac97();
+ next;
+ }
+ next;
+ }
+ $r43 = 0;
+ }
+
+ my $reg = "0x$1";
+ $reg = $reg_map{$reg} if defined($reg_map{$reg});
+
+ printf "em28xx_write_reg(dev, %s, 0x%s);\n",
+ $reg, $2;
+ next;
+ }
+ if (m/c0 00 00 00 ([0-9a-f].) 00 02 00\s+[\<]+\s+([0-9a-f].) ([0-9a-f].)/) {
+ if ($r43 == 1) {
+ if ($1 eq "40") {
+ $r40 = "0x$3$2";
+ $dir = -1;
+
+ if ($r42 >= 0) {
+ output_ac97();
+ next;
+ }
+ next;
+ }
+ $r43 = 0;
+ }
+ my $reg = "0x$1";
+ $reg = $reg_map{$reg} if defined($reg_map{$reg});
+
+ printf "em28xx_read_reg16(dev, %s);\t\t/*read 0x%s%s */\n",
+ $reg, $3, $2;
+ next;
+ }
+ if (m/40 00 00 00 ([0-9a-f].) 00 02 00\s+[\>]+\s+([0-9a-f].) ([0-9a-f].)/) {
+ if ($r43 == 1) {
+ if ($1 eq "40") {
+ $r40 = "0x$3$2";
+ $dir = 1;
+
+ if ($r42 >= 0) {
+ output_ac97();
+ next;
+ }
+ next;
+ }
+ $r43 = 0;
+ }
+ my $reg = "0x$1";
+ $reg = $reg_map{$reg} if defined($reg_map{$reg});
+
+ printf "em28xx_write_reg16(dev, %s,0x%s%s);\n",
+ $reg, $3, $2;
+ next;
+ }
+}
diff --git a/v4l2-apps/util/qv4l2/qv4l2.cpp b/v4l2-apps/util/qv4l2/qv4l2.cpp
index a93608af2..d144723d9 100644
--- a/v4l2-apps/util/qv4l2/qv4l2.cpp
+++ b/v4l2-apps/util/qv4l2/qv4l2.cpp
@@ -31,6 +31,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
+#include <dirent.h>
#include "fileopen.xpm"
@@ -41,6 +42,7 @@ ApplicationWindow::ApplicationWindow()
fd = -1;
+ videoDevice = NULL;
sigMapper = NULL;
QToolBar * fileTools = new QToolBar( this, "file operations" );
fileTools->setLabel( "File Operations" );
@@ -129,17 +131,57 @@ void ApplicationWindow::setDevice(const QString &device)
setCentralWidget(tabs);
}
-void ApplicationWindow::choose()
+void ApplicationWindow::selectdev(int index)
+{
+ setDevice(videoDevice->text(index));
+}
+
+void ApplicationWindow::add_dirVideoDevice(const char *dirname)
{
- QString fn = QFileDialog::getOpenFileName( "/dev/v4l", QString::null,
- this);
- if ( !fn.isEmpty() ) {
- setDevice(fn);
- }
- else
- statusBar()->message( "Loading aborted", 2000 );
+ DIR *dir;
+ struct dirent *entry;
+ const char *vid = "video";
+ const char *rad = "radio";
+ const char *vbi = "vbi";
+ char name[512], *p;
+
+ dir = opendir(dirname);
+ if (!dir)
+ return;
+
+ strcpy(name, dirname);
+ strcat(name, "/");
+ p = name + strlen(name);
+
+ entry = readdir(dir);
+ while (entry) {
+ if (!strncmp(entry->d_name, vid, strlen(vid)) ||
+ !strncmp(entry->d_name, rad, strlen(rad)) ||
+ !strncmp(entry->d_name, vbi, strlen(vbi))) {
+ strcpy(p, entry->d_name);
+
+ videoDevice->insertItem(name);
+ }
+ entry = readdir(dir);
+ }
+ closedir(dir);
}
+void ApplicationWindow::choose()
+{
+ if (videoDevice)
+ delete videoDevice;
+
+ videoDevice = new QPopupMenu(this);
+
+ add_dirVideoDevice("/dev");
+ add_dirVideoDevice("/dev/v4l");
+
+ connect(videoDevice, SIGNAL(activated(int)), this, SLOT(selectdev(int)));
+
+ videoDevice->show();
+ videoDevice->setFocus();
+}
void ApplicationWindow::closeEvent( QCloseEvent* ce )
{
diff --git a/v4l2-apps/util/qv4l2/qv4l2.h b/v4l2-apps/util/qv4l2/qv4l2.h
index 1a0a8e15d..5421a867d 100644
--- a/v4l2-apps/util/qv4l2/qv4l2.h
+++ b/v4l2-apps/util/qv4l2/qv4l2.h
@@ -59,12 +59,14 @@ protected:
void closeEvent( QCloseEvent* );
private slots:
+ void selectdev(int);
void choose();
void ctrlAction(int);
void about();
private:
+ void add_dirVideoDevice(const char *dirname);
void addTabs();
void finishGrid(QWidget *vbox, QGrid *grid, unsigned ctrl_class, bool odd);
void addCtrl(QGrid *grid, const struct v4l2_queryctrl &qctrl);
@@ -88,6 +90,7 @@ private:
QString filename;
QSignalMapper *sigMapper;
QTabWidget *tabs;
+ QPopupMenu *videoDevice;
int fd;
CtrlMap ctrlMap;
WidgetMap widgetMap;
diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp
index 417721c57..7d5988571 100644
--- a/v4l2-apps/util/v4l2-ctl.cpp
+++ b/v4l2-apps/util/v4l2-ctl.cpp
@@ -1096,6 +1096,7 @@ static void list_devices()
DIR *dp;
struct dirent *ep;
dev_vec files;
+ dev_map links;
dev_map cards;
struct v4l2_capability vcap;
@@ -1119,6 +1120,37 @@ static void list_devices()
}
#endif
+ /* Find device nodes which are links to other device nodes */
+ for (dev_vec::iterator iter = files.begin();
+ iter != files.end(); ) {
+ char link[64+1];
+ int link_len;
+ std::string target;
+
+ link_len = readlink(iter->c_str(), link, 64);
+ if (link_len < 0) { /* Not a link or error */
+ iter++;
+ continue;
+ }
+ link[link_len] = '\0';
+
+ /* Only remove from files list if target itself is in list */
+ if (link[0] != '/') /* Relative link */
+ target = std::string("/dev/");
+ target += link;
+ if (find(files.begin(), files.end(), target) == files.end()) {
+ iter++;
+ continue;
+ }
+
+ /* Move the device node from files to links */
+ if (links[target].empty())
+ links[target] = *iter;
+ else
+ links[target] += ", " + *iter;
+ files.erase(iter);
+ }
+
std::sort(files.begin(), files.end(), sort_on_device_name);
for (dev_vec::iterator iter = files.begin();
@@ -1133,7 +1165,10 @@ static void list_devices()
bus_info = (const char *)vcap.bus_info;
if (cards[bus_info].empty())
cards[bus_info] += std::string((char *)vcap.card) + " (" + bus_info + "):\n";
- cards[bus_info] += "\t" + (*iter) + "\n";
+ cards[bus_info] += "\t" + (*iter);
+ if (!(links[*iter].empty()))
+ cards[bus_info] += " <- " + links[*iter];
+ cards[bus_info] += "\n";
}
for (dev_map::iterator iter = cards.begin();
iter != cards.end(); ++iter) {
diff --git a/v4l2-apps/util/v4l2-dbg-ac97.h b/v4l2-apps/util/v4l2-dbg-ac97.h
new file mode 100644
index 000000000..809abe469
--- /dev/null
+++ b/v4l2-apps/util/v4l2-dbg-ac97.h
@@ -0,0 +1,67 @@
+/*
+ Copyright (C) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
+ 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
+ */
+
+#include "v4l2-dbg.h"
+
+#define AC97_IDENT "ac97"
+
+/* Register name prefix */
+#define AC97_PREFIX "AC97_"
+#define EM202_PREFIX "EM202_"
+
+static struct board_regs ac97_regs[] = {
+ /* general ac97 registers */
+ {0x00, AC97_PREFIX "RESET", 2},
+ {0x02, AC97_PREFIX "MASTER_VOL", 2},
+ {0x04, AC97_PREFIX "LINE_LEVEL_VOL", 2},
+ {0x06, AC97_PREFIX "MASTER_MONO_VOL", 2},
+ {0x0a, AC97_PREFIX "PC_BEEP_VOL", 2},
+ {0x0c, AC97_PREFIX "PHONE_VOL", 2},
+ {0x0e, AC97_PREFIX "MIC_VOL", 2},
+ {0x10, AC97_PREFIX "LINEIN_VOL", 2},
+ {0x12, AC97_PREFIX "CD_VOL", 2},
+ {0x14, AC97_PREFIX "VIDEO_VOL", 2},
+ {0x16, AC97_PREFIX "AUX_VOL", 2},
+ {0x18, AC97_PREFIX "PCM_OUT_VOL", 2},
+ {0x1a, AC97_PREFIX "RECORD_SELECT", 2},
+ {0x1c, AC97_PREFIX "RECORD_GAIN", 2},
+ {0x20, AC97_PREFIX "GENERAL_PURPOSE", 2},
+ {0x22, AC97_PREFIX "3D_CTRL", 2},
+ {0x24, AC97_PREFIX "AUD_INT_AND_PAG", 2},
+ {0x26, AC97_PREFIX "POWER_DOWN_CTRL", 2},
+ {0x28, AC97_PREFIX "EXT_AUD_ID", 2},
+ {0x2a, AC97_PREFIX "EXT_AUD_CTRL", 2},
+ {0x2c, AC97_PREFIX "PCM_OUT_FRONT_SRATE", 2},
+ {0x2e, AC97_PREFIX "PCM_OUT_SURR_SRATE", 2},
+ {0x30, AC97_PREFIX "PCM_OUT_LFE_SRATE", 2},
+ {0x32, AC97_PREFIX "PCM_IN_SRATE", 2},
+ {0x36, AC97_PREFIX "LFE_MASTER_VOL", 2},
+ {0x38, AC97_PREFIX "SURR_MASTER_VOL", 2},
+ {0x3a, AC97_PREFIX "SPDIF_OUT_CTRL", 2},
+ {0x7c, AC97_PREFIX "VENDOR_ID1", 2},
+ {0x7e, AC97_PREFIX "VENDOR_ID2", 2},
+
+ /* em202 vendor specific registers */
+ {0x3e, EM202_PREFIX "EXT_MODEM_CTRL", 2},
+ {0x4c, EM202_PREFIX "GPIO_CONF", 2},
+ {0x4e, EM202_PREFIX "GPIO_POLARITY", 2},
+ {0x50, EM202_PREFIX "GPIO_STICKY", 2},
+ {0x52, EM202_PREFIX "GPIO_MASK", 2},
+ {0x54, EM202_PREFIX "GPIO_STATUS", 2},
+ {0x6a, EM202_PREFIX "SPDIF_OUT_SEL", 2},
+ {0x72, EM202_PREFIX "ANTIPOP", 2},
+ {0x74, EM202_PREFIX "EAPD_GPIO_ACCESS", 2},
+};
diff --git a/v4l2-apps/util/v4l2-dbg-em28xx.h b/v4l2-apps/util/v4l2-dbg-em28xx.h
index c5117c6e7..ae83a3181 100644
--- a/v4l2-apps/util/v4l2-dbg-em28xx.h
+++ b/v4l2-apps/util/v4l2-dbg-em28xx.h
@@ -20,11 +20,12 @@
/* Register name prefix */
#define EM2800_PREFIX "EM2800_"
+#define EM2874_PREFIX "EM2874_"
#define EM2880_PREFIX "EM2880_"
#define EM28XX_PREFIX "EM28XX_"
static struct board_regs em28xx_regs[] = {
- {0x08, EM2800_PREFIX "AUDIOSRC", 1},
+ {0x00, EM28XX_PREFIX "CHIPCFG", 1},
{0x04, EM2880_PREFIX "GPO", 1},
{0x08, EM28XX_PREFIX "GPIO", 1},
@@ -78,7 +79,14 @@ static struct board_regs em28xx_regs[] = {
{0x42, EM28XX_PREFIX "AC97ADDR", 1},
{0x43, EM28XX_PREFIX "AC97BUSY", 1},
- {0x02, EM28XX_PREFIX "MASTER_AC97", 1},
- {0x10, EM28XX_PREFIX "LINE_IN_AC97", 1},
- {0x14, EM28XX_PREFIX "VIDEO_AC97", 1},
+ {0x45, EM28XX_PREFIX "IR", 1},
+
+ {0x50, EM2874_PREFIX "IR_CONFIG", 1},
+ {0x51, EM2874_PREFIX "IR", 1},
+ {0x5f, EM2874_PREFIX "TS_ENABLE", 1},
+ {0x80, EM2874_PREFIX "GPIO", 1},
+};
+
+static struct board_regs em28xx_alt_regs[] = {
+ {0x08, EM2800_PREFIX "AUDIOSRC", 1},
};
diff --git a/v4l2-apps/util/v4l2-dbg-tvp5150.h b/v4l2-apps/util/v4l2-dbg-tvp5150.h
new file mode 100644
index 000000000..ed5793b72
--- /dev/null
+++ b/v4l2-apps/util/v4l2-dbg-tvp5150.h
@@ -0,0 +1,97 @@
+/*
+ Copyright (C) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
+ 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
+ */
+
+#include "v4l2-dbg.h"
+
+#define TVP5150_IDENT "tvp5150"
+
+/* Register name prefix */
+#define TVP5150_PREFIX "TVP5150_"
+
+static struct board_regs tvp5150_regs[] = {
+ {0x00, TVP5150_PREFIX "VD_IN_SRC_SEL_1", 1},
+ {0x01, TVP5150_PREFIX "ANAL_CHL_CTL", 1},
+ {0x02, TVP5150_PREFIX "OP_MODE_CTL", 1},
+ {0x03, TVP5150_PREFIX "MISC_CTL", 1},
+ {0x04, TVP5150_PREFIX "AUTOSW_MSK", 1},
+ {0x06, TVP5150_PREFIX "COLOR_KIL_THSH_CTL", 1},
+ {0x07, TVP5150_PREFIX "LUMA_PROC_CTL_1", 1},
+ {0x08, TVP5150_PREFIX "LUMA_PROC_CTL_2", 1},
+ {0x09, TVP5150_PREFIX "BRIGHT_CTL", 1},
+ {0x0a, TVP5150_PREFIX "SATURATION_CTL", 1},
+ {0x0b, TVP5150_PREFIX "HUE_CTL", 1},
+ {0x0c, TVP5150_PREFIX "CONTRAST_CTL", 1},
+ {0x0d, TVP5150_PREFIX "DATA_RATE_SEL", 1},
+ {0x0e, TVP5150_PREFIX "LUMA_PROC_CTL_3", 1},
+ {0x0f, TVP5150_PREFIX "CONF_SHARED_PIN", 1},
+ {0x11, TVP5150_PREFIX "ACT_VD_CROP_ST_MSB", 1},
+ {0x12, TVP5150_PREFIX "ACT_VD_CROP_ST_LSB", 1},
+ {0x13, TVP5150_PREFIX "ACT_VD_CROP_STP_MSB", 1},
+ {0x14, TVP5150_PREFIX "ACT_VD_CROP_STP_LSB", 1},
+ {0x15, TVP5150_PREFIX "GENLOCK", 1},
+ {0x16, TVP5150_PREFIX "HORIZ_SYNC_START", 1},
+ {0x18, TVP5150_PREFIX "VERT_BLANKING_START", 1},
+ {0x19, TVP5150_PREFIX "VERT_BLANKING_STOP", 1},
+ {0x1a, TVP5150_PREFIX "CHROMA_PROC_CTL_1", 1},
+ {0x1b, TVP5150_PREFIX "CHROMA_PROC_CTL_2", 1},
+ {0x1c, TVP5150_PREFIX "INT_RESET_REG_B", 1},
+ {0x1d, TVP5150_PREFIX "INT_ENABLE_REG_B", 1},
+ {0x1e, TVP5150_PREFIX "INTT_CONFIG_REG_B", 1},
+ {0x28, TVP5150_PREFIX "VIDEO_STD", 1},
+ {0x2c, TVP5150_PREFIX "CB_GAIN_FACT", 1},
+ {0x2d, TVP5150_PREFIX "CR_GAIN_FACTOR", 1},
+ {0x2e, TVP5150_PREFIX "MACROVISION_ON_CTR", 1},
+ {0x2f, TVP5150_PREFIX "MACROVISION_OFF_CTR", 1},
+ {0x30, TVP5150_PREFIX "REV_SELECT", 1},
+ {0x80, TVP5150_PREFIX "MSB_DEV_ID", 1},
+ {0x81, TVP5150_PREFIX "LSB_DEV_ID", 1},
+ {0x82, TVP5150_PREFIX "ROM_MAJOR_VER", 1},
+ {0x83, TVP5150_PREFIX "ROM_MINOR_VER", 1},
+ {0x84, TVP5150_PREFIX "VERT_LN_COUNT_MSB", 1},
+ {0x85, TVP5150_PREFIX "VERT_LN_COUNT_LSB", 1},
+ {0x86, TVP5150_PREFIX "INT_STATUS_REG_B", 1},
+ {0x87, TVP5150_PREFIX "INT_ACTIVE_REG_B", 1},
+ {0x88, TVP5150_PREFIX "STATUS_REG_1", 1},
+ {0x89, TVP5150_PREFIX "STATUS_REG_2", 1},
+ {0x8a, TVP5150_PREFIX "STATUS_REG_3", 1},
+ {0x8b, TVP5150_PREFIX "STATUS_REG_4", 1},
+ {0x8c, TVP5150_PREFIX "STATUS_REG_5", 1},
+ {0x90, TVP5150_PREFIX "CC_DATA", 4},
+ {0x94, TVP5150_PREFIX "WSS_DATA", 6},
+ {0x9a, TVP5150_PREFIX "VPS_DATA", 13},
+ {0xa7, TVP5150_PREFIX "VITC_DATA", 9},
+ {0xb0, TVP5150_PREFIX "VBI_FIFO_READ_DATA", 1},
+ {0xb1, TVP5150_PREFIX "TELETEXT_FIL1", 5},
+ {0xb6, TVP5150_PREFIX "TELETEXT_FIL2", 5},
+ {0xbb, TVP5150_PREFIX "TELETEXT_FIL_ENA", 1},
+ {0xc0, TVP5150_PREFIX "INT_STATUS_REG_A", 1},
+ {0xc1, TVP5150_PREFIX "INT_ENABLE_REG_A", 1},
+ {0xc2, TVP5150_PREFIX "INT_CONF", 1},
+ {0xc3, TVP5150_PREFIX "VDP_CONF_RAM_DATA", 1},
+ {0xc4, TVP5150_PREFIX "CONF_RAM_ADDR_LOW", 1},
+ {0xc5, TVP5150_PREFIX "CONF_RAM_ADDR_HIGH", 1},
+ {0xc6, TVP5150_PREFIX "VDP_STATUS_REG", 1},
+ {0xc7, TVP5150_PREFIX "FIFO_WORD_COUNT", 1},
+ {0xc8, TVP5150_PREFIX "FIFO_INT_THRESHOLD", 1},
+ {0xc9, TVP5150_PREFIX "FIFO_RESET", 1},
+ {0xca, TVP5150_PREFIX "LINE_NUMBER_INT", 1},
+ {0xcb, TVP5150_PREFIX "PIX_ALIGN_REG_LOW", 1},
+ {0xcc, TVP5150_PREFIX "PIX_ALIGN_REG_HIGH", 1},
+ {0xcd, TVP5150_PREFIX "FIFO_OUT_CTRL", 1},
+ {0xcf, TVP5150_PREFIX "FULL_FIELD_ENA", 1},
+ {0xd0, TVP5150_PREFIX "LINE_MODE", 43},
+ {0xfc, TVP5150_PREFIX "FULL_FIELD_MODE_REG", 1},
+};
diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp
index e0d6153fe..577c8585e 100644
--- a/v4l2-apps/util/v4l2-dbg.cpp
+++ b/v4l2-apps/util/v4l2-dbg.cpp
@@ -45,6 +45,8 @@
#include "v4l2-dbg-bttv.h"
#include "v4l2-dbg-saa7134.h"
#include "v4l2-dbg-em28xx.h"
+#include "v4l2-dbg-ac97.h"
+#include "v4l2-dbg-tvp5150.h"
#define ARRAY_SIZE(arr) ((int)(sizeof(arr) / sizeof((arr)[0])))
@@ -58,6 +60,15 @@ struct board_list {
};
static const struct board_list boards[] = {
+#define AC97_BOARD 0
+ { /* From ac97-dbg.h */
+ AC97_IDENT,
+ sizeof(AC97_PREFIX) - 1,
+ ac97_regs,
+ ARRAY_SIZE(ac97_regs),
+ NULL,
+ 0,
+ },
{ /* From bttv-dbg.h */
BTTV_IDENT,
sizeof(BTTV_PREFIX) - 1,
@@ -79,6 +90,14 @@ static const struct board_list boards[] = {
sizeof(EM28XX_PREFIX) - 1,
em28xx_regs,
ARRAY_SIZE(em28xx_regs),
+ em28xx_alt_regs,
+ ARRAY_SIZE(em28xx_alt_regs),
+ },
+ { /* From tvp5150-dbg.h */
+ TVP5150_IDENT,
+ sizeof(TVP5150_PREFIX) - 1,
+ tvp5150_regs,
+ ARRAY_SIZE(tvp5150_regs),
NULL,
0,
},
@@ -136,7 +155,7 @@ static struct option long_options[] = {
{"set-register", required_argument, 0, OptSetRegister},
{"chip", required_argument, 0, OptChip},
{"scan-chip-idents", no_argument, 0, OptScanChipIdents},
- {"get-chip-ident", required_argument, 0, OptGetChipIdent},
+ {"get-chip-ident", no_argument, 0, OptGetChipIdent},
{"info", no_argument, 0, OptGetDriverInfo},
{"verbose", no_argument, 0, OptVerbose},
{"log-status", no_argument, 0, OptLogStatus},
@@ -158,6 +177,7 @@ static void usage(void)
" It can be one of:\n"
" I2C driver ID (see --list-driverids)\n"
" I2C 7-bit address\n"
+ " AC97: for ac97 anciliary mixer\n"
" host<num>: host chip number <num>\n"
" host (default): same as host0\n"
" -l, --list-registers[=min=<addr>[,max=<addr>]]\n"
@@ -293,6 +313,21 @@ static unsigned long long parse_reg(const struct board_list *curr_bd, const std:
return strtoull(reg.c_str(), NULL, 0);
}
+static const char *reg_name(const struct board_list *curr_bd, unsigned long long reg)
+{
+ if (curr_bd) {
+ for (int i = 0; i < curr_bd->regs_size; i++) {
+ if (reg == curr_bd->regs[i].reg)
+ return curr_bd->regs[i].name;
+ }
+ for (int i = 0; i < curr_bd->alt_regs_size; i++) {
+ if (reg == curr_bd->regs[i].reg)
+ return curr_bd->regs[i].name;
+ }
+ }
+ return NULL;
+}
+
static const char *binary(unsigned long long val)
{
static char bin[80];
@@ -380,6 +415,7 @@ int main(int argc, char **argv)
std::vector<std::string> get_regs;
int match_type = V4L2_CHIP_MATCH_HOST;
int match_chip = 0;
+ char driver[255];
memset(&set_reg, 0, sizeof(set_reg));
memset(&get_reg, 0, sizeof(get_reg));
@@ -433,7 +469,12 @@ int main(int argc, char **argv)
match_chip = strtoul(optarg + 4, NULL, 0);
break;
}
+ if (!strcasecmp(optarg, "ac97")) {
+ match_type = V4L2_CHIP_MATCH_AC97;
+ break;
+ }
match_type = V4L2_CHIP_MATCH_I2C_DRIVER;
+ strcpy(driver, optarg);
match_chip = parse_chip(optarg);
if (!match_chip) {
fprintf(stderr, "unknown driver ID %s\n", optarg);
@@ -457,6 +498,7 @@ int main(int argc, char **argv)
subs = optarg;
if (subs == NULL)
break;
+
while (*subs != '\0') {
static const char * const subopts[] = {
"min",
@@ -516,10 +558,21 @@ int main(int argc, char **argv)
printf("%s", cap2s(vcap.capabilities).c_str());
}
- for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) {
- if (!strcasecmp((char *)vcap.driver, boards[board].name)) {
- curr_bd = &boards[board];
- break;
+ if (match_type == V4L2_CHIP_MATCH_AC97) {
+ curr_bd = &boards[AC97_BOARD];
+ } else if (match_type == V4L2_CHIP_MATCH_HOST) {
+ for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) {
+ if (!strcasecmp((char *)vcap.driver, boards[board].name)) {
+ curr_bd = &boards[board];
+ break;
+ }
+ }
+ } else if (match_type == V4L2_CHIP_MATCH_I2C_DRIVER) {
+ for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) {
+ if (!strcasecmp(driver, boards[board].name)) {
+ curr_bd = &boards[board];
+ break;
+ }
}
}
@@ -534,8 +587,21 @@ int main(int argc, char **argv)
while (optind < argc) {
set_reg.val = strtoull(argv[optind++], NULL, 0);
if (doioctl(fd, VIDIOC_DBG_S_REGISTER, &set_reg,
- "VIDIOC_DBG_S_REGISTER") == 0)
- printf("register 0x%llx set to 0x%llx\n", set_reg.reg, set_reg.val);
+ "VIDIOC_DBG_S_REGISTER") >= 0) {
+ const char *name = reg_name(curr_bd, set_reg.reg);
+
+ printf("Register ");
+
+ if (name)
+ printf("%s (0x%08llx)", name, set_reg.reg);
+ else
+ printf("0x%08llx", set_reg.reg);
+
+ printf(" set to 0x%llx\n", set_reg.val);
+ } else {
+ printf("Failed to set register 0x%08llx value 0x%llx\n",
+ set_reg.reg, set_reg.val);
+ }
set_reg.reg++;
}
}
@@ -582,9 +648,19 @@ int main(int argc, char **argv)
if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &get_reg) < 0)
fprintf(stderr, "ioctl: VIDIOC_DBG_G_REGISTER "
"failed for 0x%llx\n", get_reg.reg);
- else
- printf("%llx = %llxh = %lldd = %sb\n", get_reg.reg,
+ else {
+ const char *name = reg_name(curr_bd, get_reg.reg);
+
+ printf("Register ");
+
+ if (name)
+ printf("%s (0x%08llx)", name, get_reg.reg);
+ else
+ printf("0x%08llx", get_reg.reg);
+
+ printf(" = %llxh (%lldd %sb)\n",
get_reg.val, get_reg.val, binary(get_reg.val));
+ }
}
}
@@ -593,6 +669,7 @@ int main(int argc, char **argv)
get_reg.match_type = match_type;
get_reg.match_chip = match_chip;
+
if (forcedstride) {
stride = forcedstride;
} else {
@@ -601,6 +678,43 @@ int main(int argc, char **argv)
}
printf("ioctl: VIDIOC_DBG_G_REGISTER\n");
+ if (curr_bd) {
+ if (reg_min_arg.empty())
+ reg_min = 0;
+ else
+ reg_min = parse_reg(curr_bd, reg_min_arg);
+
+
+ if (reg_max_arg.empty())
+ reg_max = 1<<31 - 1;
+ else
+ reg_max = parse_reg(curr_bd, reg_max_arg);
+
+ for (int i = 0; i < curr_bd->regs_size; i++) {
+ if (reg_min_arg.empty() || ((curr_bd->regs[i].reg >= reg_min) && curr_bd->regs[i].reg <= reg_max)) {
+ get_reg.reg = curr_bd->regs[i].reg;
+
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &get_reg) < 0)
+ fprintf(stderr, "ioctl: VIDIOC_DBG_G_REGISTER "
+ "failed for 0x%llx\n", get_reg.reg);
+ else {
+ const char *name = reg_name(curr_bd, get_reg.reg);
+
+ printf("Register ");
+
+ if (name)
+ printf("%s (0x%08llx)", name, get_reg.reg);
+ else
+ printf("0x%08llx", get_reg.reg);
+
+ printf(" = %llxh (%lldd %sb)\n",
+ get_reg.val, get_reg.val, binary(get_reg.val));
+ }
+ }
+ }
+ goto list_done;
+ }
+
if (!reg_min_arg.empty()) {
reg_min = parse_reg(curr_bd, reg_min_arg);
if (reg_max_arg.empty())
@@ -611,6 +725,7 @@ int main(int argc, char **argv)
print_regs(fd, &get_reg, reg_min, reg_max, stride);
goto list_done;
}
+
/* try to match the i2c chip */
switch (get_reg.match_chip) {
case I2C_DRIVERID_SAA711X:
@@ -706,9 +821,9 @@ list_done:
else {
printf("Symbols for driver %s:\n", vcap.driver);
for (int i = 0; i < curr_bd->regs_size; i++)
- printf("0x%08x: %s\n", curr_bd->regs[i], curr_bd->regs[i].name);
+ printf("0x%08x: %s\n", curr_bd->regs[i].reg, curr_bd->regs[i].name);
for (int i = 0; i < curr_bd->alt_regs_size; i++)
- printf("0x%08x: %s\n", curr_bd->alt_regs[i], curr_bd->alt_regs[i].name);
+ printf("0x%08x: %s\n", curr_bd->alt_regs[i].reg, curr_bd->alt_regs[i].name);
}
}