static int ov9640_video_probe(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); struct ov9640_priv *priv = to_ov9640_sensor(sd); u8 pid, ver, midh, midl; const char *devname; int ret; ret = ov9640_s_power(&priv->subdev, 1); if (ret < 0) return ret; /* * check and show product ID and manufacturer ID */ ret = ov9640_reg_read(client, OV9640_PID, &pid); if (!ret) ret = ov9640_reg_read(client, OV9640_VER, &ver); if (!ret) ret = ov9640_reg_read(client, OV9640_MIDH, &midh); if (!ret) ret = ov9640_reg_read(client, OV9640_MIDL, &midl); if (ret) goto done; switch (VERSION(pid, ver)) { case OV9640_V2: devname = "ov9640"; priv->model = V4L2_IDENT_OV9640; priv->revision = 2; break; case OV9640_V3: devname = "ov9640"; priv->model = V4L2_IDENT_OV9640; priv->revision = 3; break; default: dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); ret = -ENODEV; goto done; } dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", devname, pid, ver, midh, midl); ret = v4l2_ctrl_handler_setup(&priv->hdl); done: ov9640_s_power(&priv->subdev, 0); return ret; }
static int ov9640_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; u8 val; if (reg->reg & ~0xff) return -EINVAL; reg->size = 1; ret = ov9640_reg_read(client, reg->reg, &val); if (ret) return ret; reg->val = (__u64)val; return 0; }
/* read a register */ static int ov9640_reg_read(struct i2c_client *client, u8 reg, u8 *val) { int ret; u8 data = reg; struct i2c_msg msg = { .addr = client->addr, .flags = 0, .len = 1, .buf = &data, }; ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) goto err; msg.flags = I2C_M_RD; ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) goto err; *val = data; return 0; err: dev_err(&client->dev, "Failed reading register 0x%02x!\n", reg); return ret; } /* write a register */ static int ov9640_reg_write(struct i2c_client *client, u8 reg, u8 val) { int ret; u8 _val; unsigned char data[2] = { reg, val }; struct i2c_msg msg = { .addr = client->addr, .flags = 0, .len = 2, .buf = data, }; ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) { dev_err(&client->dev, "Failed writing register 0x%02x!\n", reg); return ret; } /* we have to read the register back ... no idea why, maybe HW bug */ ret = ov9640_reg_read(client, reg, &_val); if (ret) dev_err(&client->dev, "Failed reading back register 0x%02x!\n", reg); return 0; } /* Read a register, alter its bits, write it back */ static int ov9640_reg_rmw(struct i2c_client *client, u8 reg, u8 set, u8 unset) { u8 val; int ret; ret = ov9640_reg_read(client, reg, &val); if (ret) { dev_err(&client->dev, "[Read]-Modify-Write of register %02x failed!\n", reg); return val; } val |= set; val &= ~unset; ret = ov9640_reg_write(client, reg, val); if (ret) dev_err(&client->dev, "Read-Modify-[Write] of register %02x failed!\n", reg); return ret; }