summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-cards.c161
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-core.c3
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-video.c10
-rw-r--r--v4l2-apps/util/v4l2-dbg-micron.h46
-rw-r--r--v4l2-apps/util/v4l2-dbg.cpp19
5 files changed, 156 insertions, 83 deletions
diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c
index 9a09df296..4b7526fa2 100644
--- a/linux/drivers/media/video/em28xx/em28xx-cards.c
+++ b/linux/drivers/media/video/em28xx/em28xx-cards.c
@@ -231,7 +231,7 @@ static struct em28xx_reg_seq silvercrest_reg_seq[] = {
struct em28xx_board em28xx_boards[] = {
[EM2750_BOARD_UNKNOWN] = {
.name = "EM2710/EM2750/EM2751 webcam grabber",
- .xclk = EM28XX_XCLK_FREQUENCY_48MHZ,
+ .xclk = EM28XX_XCLK_FREQUENCY_20MHZ,
.tuner_type = TUNER_ABSENT,
.is_webcam = 1,
.no_audio = 1,
@@ -1838,6 +1838,7 @@ static int em28xx_hint_sensor(struct em28xx *dev)
__be16 version_be;
u16 version;
+ /* Micron sensor detection */
dev->i2c_client.addr = 0xba >> 1;
cmd = 0;
i2c_master_send(&dev->i2c_client, &cmd, 1);
@@ -1846,16 +1847,27 @@ static int em28xx_hint_sensor(struct em28xx *dev)
return -EINVAL;
version = be16_to_cpu(version_be);
-
switch (version) {
case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */
case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */
dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
+ em28xx_set_model(dev);
+
sensor_name = "mt9v011";
dev->em28xx_sensor = EM28XX_MT9V011;
dev->sensor_xres = 640;
dev->sensor_yres = 480;
- dev->sensor_xtal = 12150000;
+ /*
+ * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
+ * the Silvercrest cam I have here for testing - for higher
+ * resolutions, a high clock cause horizontal artifacts, so we
+ * need to use a lower xclk frequency.
+ * Yet, it would be possible to adjust xclk depending on the
+ * desired resolution, since this affects directly the
+ * frame rate.
+ */
+ dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
+ dev->sensor_xtal = 4300000;
/* probably means GRGB 16 bit bayer */
dev->vinmode = 0x0d;
@@ -1868,6 +1880,8 @@ static int em28xx_hint_sensor(struct em28xx *dev)
#endif
case 0x8431:
dev->model = EM2750_BOARD_UNKNOWN;
+ em28xx_set_model(dev);
+
sensor_name = "mt9m001";
dev->em28xx_sensor = EM28XX_MT9M001;
em28xx_initialize_mt9m001(dev);
@@ -1884,6 +1898,9 @@ static int em28xx_hint_sensor(struct em28xx *dev)
return -EINVAL;
}
+ /* Setup webcam defaults */
+ em28xx_pre_card_setup(dev);
+
em28xx_errdev("Sensor is %s, using model %s entry.\n",
sensor_name, em28xx_boards[dev->model].name);
@@ -1895,63 +1912,6 @@ static int em28xx_hint_sensor(struct em28xx *dev)
*/
void em28xx_pre_card_setup(struct em28xx *dev)
{
- int rc;
-
- em28xx_set_model(dev);
-
- em28xx_info("Identified as %s (card=%d)\n",
- dev->board.name, dev->model);
-
- /* Set the default GPO/GPIO for legacy devices */
- dev->reg_gpo_num = EM2880_R04_GPO;
- dev->reg_gpio_num = EM28XX_R08_GPIO;
-
- dev->wait_after_write = 5;
-
- /* Based on the Chip ID, set the device configuration */
- rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
- if (rc > 0) {
- dev->chip_id = rc;
-
- switch (dev->chip_id) {
- case CHIP_ID_EM2710:
- em28xx_info("chip ID is em2710\n");
- break;
- case CHIP_ID_EM2750:
- em28xx_info("chip ID is em2750\n");
- break;
- case CHIP_ID_EM2820:
- em28xx_info("chip ID is em2820 (or em2710)\n");
- break;
- case CHIP_ID_EM2840:
- em28xx_info("chip ID is em2840\n");
- break;
- case CHIP_ID_EM2860:
- em28xx_info("chip ID is em2860\n");
- break;
- case CHIP_ID_EM2870:
- em28xx_info("chip ID is em2870\n");
- dev->wait_after_write = 0;
- break;
- case CHIP_ID_EM2874:
- em28xx_info("chip ID is em2874\n");
- dev->reg_gpio_num = EM2874_R80_GPIO;
- dev->wait_after_write = 0;
- break;
- case CHIP_ID_EM2883:
- em28xx_info("chip ID is em2882/em2883\n");
- dev->wait_after_write = 0;
- break;
- default:
- em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
- }
- }
-
- /* Prepopulate cached GPO register content */
- rc = em28xx_read_reg(dev, dev->reg_gpo_num);
- if (rc >= 0)
- dev->reg_gpo = rc;
-
/* Set the initial XCLK and I2C clock values based on the board
definition */
em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f);
@@ -2334,7 +2294,20 @@ void em28xx_register_i2c_ir(struct em28xx *dev)
void em28xx_card_setup(struct em28xx *dev)
{
- em28xx_set_model(dev);
+ /*
+ * If the device can be a webcam, seek for a sensor.
+ * If sensor is not found, then it isn't a webcam.
+ */
+ if (dev->board.is_webcam) {
+ if (em28xx_hint_sensor(dev) < 0)
+ dev->board.is_webcam = 0;
+ else
+ dev->progressive = 1;
+ } else
+ em28xx_set_model(dev);
+
+ em28xx_info("Identified as %s (card=%d)\n",
+ dev->board.name, dev->model);
dev->tuner_type = em28xx_boards[dev->model].tuner_type;
if (em28xx_boards[dev->model].tuner_addr)
@@ -2564,7 +2537,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
int minor)
{
struct em28xx *dev = *devhandle;
- int retval = -ENOMEM;
+ int retval;
int errCode;
dev->udev = udev;
@@ -2581,6 +2554,58 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->em28xx_read_reg_req = em28xx_read_reg_req;
dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800;
+ em28xx_set_model(dev);
+
+ /* Set the default GPO/GPIO for legacy devices */
+ dev->reg_gpo_num = EM2880_R04_GPO;
+ dev->reg_gpio_num = EM28XX_R08_GPIO;
+
+ dev->wait_after_write = 5;
+
+ /* Based on the Chip ID, set the device configuration */
+ retval = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
+ if (retval > 0) {
+ dev->chip_id = retval;
+
+ switch (dev->chip_id) {
+ case CHIP_ID_EM2710:
+ em28xx_info("chip ID is em2710\n");
+ break;
+ case CHIP_ID_EM2750:
+ em28xx_info("chip ID is em2750\n");
+ break;
+ case CHIP_ID_EM2820:
+ em28xx_info("chip ID is em2820 (or em2710)\n");
+ break;
+ case CHIP_ID_EM2840:
+ em28xx_info("chip ID is em2840\n");
+ break;
+ case CHIP_ID_EM2860:
+ em28xx_info("chip ID is em2860\n");
+ break;
+ case CHIP_ID_EM2870:
+ em28xx_info("chip ID is em2870\n");
+ dev->wait_after_write = 0;
+ break;
+ case CHIP_ID_EM2874:
+ em28xx_info("chip ID is em2874\n");
+ dev->reg_gpio_num = EM2874_R80_GPIO;
+ dev->wait_after_write = 0;
+ break;
+ case CHIP_ID_EM2883:
+ em28xx_info("chip ID is em2882/em2883\n");
+ dev->wait_after_write = 0;
+ break;
+ default:
+ em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
+ }
+ }
+
+ /* Prepopulate cached GPO register content */
+ retval = em28xx_read_reg(dev, dev->reg_gpo_num);
+ if (retval >= 0)
+ dev->reg_gpo = retval;
+
em28xx_pre_card_setup(dev);
if (!dev->board.is_em2800) {
@@ -2615,18 +2640,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->vinmode = 0x10;
dev->vinctl = 0x11;
- /*
- * If the device can be a webcam, seek for a sensor.
- * If sensor is not found, then it isn't a webcam.
- */
- if (dev->board.is_webcam)
- if (em28xx_hint_sensor(dev) < 0)
- dev->board.is_webcam = 0;
-
- /* It makes no sense to use de-interlacing mode on webcams */
- if (dev->board.is_webcam)
- dev->progressive = 1;
-
/* Do board specific init and eeprom reading */
em28xx_card_setup(dev);
diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c
index 10da3ad82..46cb13182 100644
--- a/linux/drivers/media/video/em28xx/em28xx-core.c
+++ b/linux/drivers/media/video/em28xx/em28xx-core.c
@@ -632,6 +632,9 @@ int em28xx_capture_start(struct em28xx *dev, int start)
return rc;
}
+ if (dev->board.is_webcam)
+ rc = em28xx_write_reg(dev, 0x13, 0x0c);
+
/* enable video capture */
rc = em28xx_write_reg(dev, 0x48, 0x00);
diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c
index 77ec51dad..c7d723a03 100644
--- a/linux/drivers/media/video/em28xx/em28xx-video.c
+++ b/linux/drivers/media/video/em28xx/em28xx-video.c
@@ -1342,8 +1342,9 @@ static int vidioc_g_register(struct file *file, void *priv,
v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
return 0;
case V4L2_CHIP_MATCH_I2C_ADDR:
- /* Not supported yet */
- return -EINVAL;
+ /* TODO: is this correct? */
+ v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
+ return 0;
default:
if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
@@ -1394,8 +1395,9 @@ static int vidioc_s_register(struct file *file, void *priv,
v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
return 0;
case V4L2_CHIP_MATCH_I2C_ADDR:
- /* Not supported yet */
- return -EINVAL;
+ /* TODO: is this correct? */
+ v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
+ return 0;
default:
if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
diff --git a/v4l2-apps/util/v4l2-dbg-micron.h b/v4l2-apps/util/v4l2-dbg-micron.h
new file mode 100644
index 000000000..8466322bf
--- /dev/null
+++ b/v4l2-apps/util/v4l2-dbg-micron.h
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2009 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 MT9V011_IDENT "mt9v011"
+
+/* Register name prefix */
+#define MT9V011_PREFIX "MT9V011_"
+
+static struct board_regs mt9v011_regs[] = {
+ {0x00, MT9V011_PREFIX "CHIP_VERSION"},
+ {0x01, MT9V011_PREFIX "ROWSTART"},
+ {0x02, MT9V011_PREFIX "COLSTART"},
+ {0x03, MT9V011_PREFIX "HEIGHT"},
+ {0x04, MT9V011_PREFIX "WIDTH"},
+ {0x05, MT9V011_PREFIX "HBLANK"},
+ {0x06, MT9V011_PREFIX "VBLANK"},
+ {0x07, MT9V011_PREFIX "OUT_CTRL"},
+ {0x09, MT9V011_PREFIX "SHUTTER_WIDTH"},
+ {0x0a, MT9V011_PREFIX "CLK_SPEED"},
+ {0x0b, MT9V011_PREFIX "RESTART"},
+ {0x0c, MT9V011_PREFIX "SHUTTER_DELAY"},
+ {0x0d, MT9V011_PREFIX "RESET"},
+ {0x1e, MT9V011_PREFIX "DIGITAL_ZOOM"},
+ {0x20, MT9V011_PREFIX "READ_MODE"},
+ {0x2b, MT9V011_PREFIX "GREEN_1_GAIN"},
+ {0x2c, MT9V011_PREFIX "BLUE_GAIN"},
+ {0x2d, MT9V011_PREFIX "RED_GAIN"},
+ {0x2e, MT9V011_PREFIX "GREEN_2_GAIN"},
+ {0x35, MT9V011_PREFIX "GLOBAL_GAIN"},
+ {0xf1, MT9V011_PREFIX "CHIP_ENABLE"},
+};
diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp
index 424b0fffe..1a481c04c 100644
--- a/v4l2-apps/util/v4l2-dbg.cpp
+++ b/v4l2-apps/util/v4l2-dbg.cpp
@@ -47,6 +47,7 @@
#include "v4l2-dbg-em28xx.h"
#include "v4l2-dbg-ac97.h"
#include "v4l2-dbg-tvp5150.h"
+#include "v4l2-dbg-micron.h"
#define ARRAY_SIZE(arr) ((int)(sizeof(arr) / sizeof((arr)[0])))
@@ -61,7 +62,7 @@ struct board_list {
static const struct board_list boards[] = {
#define AC97_BOARD 0
- { /* From ac97-dbg.h */
+ { /* From v4l2-dbg-ac97.h */
AC97_IDENT,
sizeof(AC97_PREFIX) - 1,
ac97_regs,
@@ -69,7 +70,7 @@ static const struct board_list boards[] = {
NULL,
0,
},
- { /* From bttv-dbg.h */
+ { /* From v4l2-dbg-bttv.h */
BTTV_IDENT,
sizeof(BTTV_PREFIX) - 1,
bt8xx_regs,
@@ -77,7 +78,7 @@ static const struct board_list boards[] = {
bt8xx_regs_other,
ARRAY_SIZE(bt8xx_regs_other),
},
- { /* From saa7134-dbg.h */
+ { /* From v4l2-dbg-saa7134.h */
SAA7134_IDENT,
sizeof(SAA7134_PREFIX) - 1,
saa7134_regs,
@@ -85,7 +86,7 @@ static const struct board_list boards[] = {
NULL,
0,
},
- { /* From em28xx-dbg.h */
+ { /* From v4l2-dbg-em28xx.h */
EM28XX_IDENT,
sizeof(EM28XX_PREFIX) - 1,
em28xx_regs,
@@ -93,7 +94,7 @@ static const struct board_list boards[] = {
em28xx_alt_regs,
ARRAY_SIZE(em28xx_alt_regs),
},
- { /* From tvp5150-dbg.h */
+ { /* From v4l2-dbg-tvp5150.h */
TVP5150_IDENT,
sizeof(TVP5150_PREFIX) - 1,
tvp5150_regs,
@@ -101,6 +102,14 @@ static const struct board_list boards[] = {
NULL,
0,
},
+ { /* From v4l2-dbg-micron.h */
+ MT9V011_IDENT,
+ sizeof(MT9V011_PREFIX) - 1,
+ mt9v011_regs,
+ ARRAY_SIZE(mt9v011_regs),
+ NULL,
+ 0,
+ },
};
struct chipid {