|
@@ -61,13 +61,20 @@ static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr)
|
|
|
int rc;
|
|
|
|
|
|
buffer[0] = addr;
|
|
|
- if (1 != (rc = i2c_master_send(c, buffer, 1)))
|
|
|
- v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 1)\n", rc);
|
|
|
+
|
|
|
+ rc = i2c_master_send(c, buffer, 1);
|
|
|
+ if (rc < 0) {
|
|
|
+ v4l2_err(sd, "i2c i/o error: rc == %d (should be 1)\n", rc);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
|
|
|
msleep(10);
|
|
|
|
|
|
- if (1 != (rc = i2c_master_recv(c, buffer, 1)))
|
|
|
- v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 1)\n", rc);
|
|
|
+ rc = i2c_master_recv(c, buffer, 1);
|
|
|
+ if (rc < 0) {
|
|
|
+ v4l2_err(sd, "i2c i/o error: rc == %d (should be 1)\n", rc);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
|
|
|
v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]);
|
|
|
|
|
@@ -279,6 +286,11 @@ static inline void tvp5150_selmux(struct v4l2_subdev *sd)
|
|
|
* For Composite and TV, it should be the reverse
|
|
|
*/
|
|
|
val = tvp5150_read(sd, TVP5150_MISC_CTL);
|
|
|
+ if (val < 0) {
|
|
|
+ v4l2_err(sd, "%s: failed with error = %d\n", __func__, val);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
if (decoder->input == TVP5150_SVIDEO)
|
|
|
val = (val & ~0x40) | 0x10;
|
|
|
else
|
|
@@ -676,6 +688,7 @@ static int tvp5150_get_vbi(struct v4l2_subdev *sd,
|
|
|
v4l2_std_id std = decoder->norm;
|
|
|
u8 reg;
|
|
|
int pos, type = 0;
|
|
|
+ int i, ret = 0;
|
|
|
|
|
|
if (std == V4L2_STD_ALL) {
|
|
|
v4l2_err(sd, "VBI can't be configured without knowing number of lines\n");
|
|
@@ -690,13 +703,17 @@ static int tvp5150_get_vbi(struct v4l2_subdev *sd,
|
|
|
|
|
|
reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI;
|
|
|
|
|
|
- pos = tvp5150_read(sd, reg) & 0x0f;
|
|
|
- if (pos < 0x0f)
|
|
|
- type = regs[pos].type.vbi_type;
|
|
|
-
|
|
|
- pos = tvp5150_read(sd, reg + 1) & 0x0f;
|
|
|
- if (pos < 0x0f)
|
|
|
- type |= regs[pos].type.vbi_type;
|
|
|
+ for (i = 0; i <= 1; i++) {
|
|
|
+ ret = tvp5150_read(sd, reg + i);
|
|
|
+ if (ret < 0) {
|
|
|
+ v4l2_err(sd, "%s: failed with error = %d\n",
|
|
|
+ __func__, ret);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ pos = ret & 0x0f;
|
|
|
+ if (pos < 0x0f)
|
|
|
+ type |= regs[pos].type.vbi_type;
|
|
|
+ }
|
|
|
|
|
|
return type;
|
|
|
}
|
|
@@ -1031,13 +1048,21 @@ static int tvp5150_g_chip_ident(struct v4l2_subdev *sd,
|
|
|
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
|
|
static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
|
|
|
{
|
|
|
+ int res;
|
|
|
+
|
|
|
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
|
|
|
|
|
if (!v4l2_chip_match_i2c_client(client, ®->match))
|
|
|
return -EINVAL;
|
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
|
return -EPERM;
|
|
|
- reg->val = tvp5150_read(sd, reg->reg & 0xff);
|
|
|
+ res = tvp5150_read(sd, reg->reg & 0xff);
|
|
|
+ if (res < 0) {
|
|
|
+ v4l2_err(sd, "%s: failed with error = %d\n", __func__, res);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ reg->val = res;
|
|
|
reg->size = 1;
|
|
|
return 0;
|
|
|
}
|
|
@@ -1126,7 +1151,8 @@ static int tvp5150_probe(struct i2c_client *c,
|
|
|
{
|
|
|
struct tvp5150 *core;
|
|
|
struct v4l2_subdev *sd;
|
|
|
- u8 msb_id, lsb_id, msb_rom, lsb_rom;
|
|
|
+ int tvp5150_id[4];
|
|
|
+ int i, res;
|
|
|
|
|
|
/* Check if the adapter supports the needed features */
|
|
|
if (!i2c_check_functionality(c->adapter,
|
|
@@ -1139,26 +1165,37 @@ static int tvp5150_probe(struct i2c_client *c,
|
|
|
}
|
|
|
sd = &core->sd;
|
|
|
v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID,
|
|
|
+ * TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER
|
|
|
+ */
|
|
|
+ for (i = 0; i < 4; i++) {
|
|
|
+ res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i);
|
|
|
+ if (res < 0)
|
|
|
+ goto free_core;
|
|
|
+ tvp5150_id[i] = res;
|
|
|
+ }
|
|
|
+
|
|
|
v4l_info(c, "chip found @ 0x%02x (%s)\n",
|
|
|
c->addr << 1, c->adapter->name);
|
|
|
|
|
|
- msb_id = tvp5150_read(sd, TVP5150_MSB_DEV_ID);
|
|
|
- lsb_id = tvp5150_read(sd, TVP5150_LSB_DEV_ID);
|
|
|
- msb_rom = tvp5150_read(sd, TVP5150_ROM_MAJOR_VER);
|
|
|
- lsb_rom = tvp5150_read(sd, TVP5150_ROM_MINOR_VER);
|
|
|
-
|
|
|
- if (msb_rom == 4 && lsb_rom == 0) { /* Is TVP5150AM1 */
|
|
|
- v4l2_info(sd, "tvp%02x%02xam1 detected.\n", msb_id, lsb_id);
|
|
|
+ if (tvp5150_id[2] == 4 && tvp5150_id[3] == 0) { /* Is TVP5150AM1 */
|
|
|
+ v4l2_info(sd, "tvp%02x%02xam1 detected.\n",
|
|
|
+ tvp5150_id[0], tvp5150_id[1]);
|
|
|
|
|
|
/* ITU-T BT.656.4 timing */
|
|
|
tvp5150_write(sd, TVP5150_REV_SELECT, 0);
|
|
|
} else {
|
|
|
- if (msb_rom == 3 || lsb_rom == 0x21) { /* Is TVP5150A */
|
|
|
- v4l2_info(sd, "tvp%02x%02xa detected.\n", msb_id, lsb_id);
|
|
|
+ /* Is TVP5150A */
|
|
|
+ if (tvp5150_id[2] == 3 || tvp5150_id[3] == 0x21) {
|
|
|
+ v4l2_info(sd, "tvp%02x%02xa detected.\n",
|
|
|
+ tvp5150_id[2], tvp5150_id[3]);
|
|
|
} else {
|
|
|
v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n",
|
|
|
- msb_id, lsb_id);
|
|
|
- v4l2_info(sd, "*** Rom ver is %d.%d\n", msb_rom, lsb_rom);
|
|
|
+ tvp5150_id[2], tvp5150_id[3]);
|
|
|
+ v4l2_info(sd, "*** Rom ver is %d.%d\n",
|
|
|
+ tvp5150_id[2], tvp5150_id[3]);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1177,11 +1214,9 @@ static int tvp5150_probe(struct i2c_client *c,
|
|
|
V4L2_CID_HUE, -128, 127, 1, 0);
|
|
|
sd->ctrl_handler = &core->hdl;
|
|
|
if (core->hdl.error) {
|
|
|
- int err = core->hdl.error;
|
|
|
-
|
|
|
+ res = core->hdl.error;
|
|
|
v4l2_ctrl_handler_free(&core->hdl);
|
|
|
- kfree(core);
|
|
|
- return err;
|
|
|
+ goto free_core;
|
|
|
}
|
|
|
v4l2_ctrl_handler_setup(&core->hdl);
|
|
|
|
|
@@ -1197,6 +1232,10 @@ static int tvp5150_probe(struct i2c_client *c,
|
|
|
if (debug > 1)
|
|
|
tvp5150_log_status(sd);
|
|
|
return 0;
|
|
|
+
|
|
|
+free_core:
|
|
|
+ kfree(core);
|
|
|
+ return res;
|
|
|
}
|
|
|
|
|
|
static int tvp5150_remove(struct i2c_client *c)
|