struct clk *sensor_clk;
int csi;
- void (*io_init)(void);
+ void (*io_init)(struct ov5640 *);
+ int pwn_gpio, rst_gpio;
};
-/*!
- * Maintains the information on the current state of the sesor.
- */
-static struct ov5640 ov5640_data;
-static int pwn_gpio, rst_gpio;
-
static struct reg_value ov5640_init_parm[] = {
{0x3008, 0x42, 0, 0},
const struct i2c_device_id *device_id);
static int ov5640_remove(struct i2c_client *client);
-static s32 ov5640_read_reg(u16 reg, u8 *val);
-static s32 ov5640_write_reg(u16 reg, u8 val);
+static s32 ov5640_read_reg(struct ov5640 *sensor, u16 reg, u8 *val);
+static s32 ov5640_write_reg(struct ov5640 *sensor, u16 reg, u8 val);
static const struct i2c_device_id ov5640_id[] = {
{"ov5640_mipi_v3", 0},
return NULL;
}
-static inline void ov5640_power_down(int enable)
+static inline void ov5640_power_down(struct ov5640 *sensor, int enable)
{
- gpio_set_value_cansleep(pwn_gpio, enable);
+ gpio_set_value_cansleep(sensor->pwn_gpio, enable);
udelay(2000);
}
-static inline void ov5640_reset(void)
+static inline void ov5640_reset(struct ov5640 *sensor)
{
- gpio_set_value_cansleep(pwn_gpio, 1);
- gpio_set_value_cansleep(rst_gpio, 0);
+ gpio_set_value_cansleep(sensor->pwn_gpio, 1);
+ gpio_set_value_cansleep(sensor->rst_gpio, 0);
udelay(5000);
- gpio_set_value_cansleep(pwn_gpio, 0);
+ gpio_set_value_cansleep(sensor->pwn_gpio, 0);
udelay(1000);
- gpio_set_value_cansleep(rst_gpio, 1);
+ gpio_set_value_cansleep(sensor->rst_gpio, 1);
msleep(20);
}
return ret;
}
-static s32 ov5640_write_reg(u16 reg, u8 val)
+static s32 ov5640_write_reg(struct ov5640 *sensor, u16 reg, u8 val)
{
+ struct device *dev = &sensor->i2c_client->dev;
u8 au8Buf[3] = {0};
au8Buf[0] = reg >> 8;
au8Buf[1] = reg & 0xff;
au8Buf[2] = val;
- if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) {
- pr_err("%s:write reg error:reg=%x,val=%x\n",
- __func__, reg, val);
+ if (i2c_master_send(sensor->i2c_client, au8Buf, 3) < 0) {
+ dev_err(dev, "Write reg error: reg=%x, val=%x\n", reg, val);
return -1;
}
return 0;
}
-static s32 ov5640_read_reg(u16 reg, u8 *val)
+static s32 ov5640_read_reg(struct ov5640 *sensor, u16 reg, u8 *val)
{
+ struct device *dev = &sensor->i2c_client->dev;
u8 au8RegBuf[2] = {0};
u8 u8RdVal = 0;
au8RegBuf[0] = reg >> 8;
au8RegBuf[1] = reg & 0xff;
- if (i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2) != 2) {
- pr_err("%s:write reg error:reg=%x\n",
- __func__, reg);
+ if (i2c_master_send(sensor->i2c_client, au8RegBuf, 2) != 2) {
+ dev_err(dev, "Read reg error: reg=%x\n", reg);
return -1;
}
- if (i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1) != 1) {
- pr_err("%s:read reg error:reg=%x,val=%x\n",
- __func__, reg, u8RdVal);
+ if (i2c_master_recv(sensor->i2c_client, &u8RdVal, 1) != 1) {
+ dev_err(dev, "Read reg error: reg=%x, val=%x\n", reg, u8RdVal);
return -1;
}
return u8RdVal;
}
-static int ov5640_set_clk_rate(void)
+static int ov5640_set_clk_rate(struct ov5640 *sensor)
{
u32 tgt_xclk; /* target xclk */
int ret;
/* mclk */
- tgt_xclk = ov5640_data.mclk;
+ tgt_xclk = sensor->mclk;
tgt_xclk = min_t(u32, tgt_xclk, (u32)OV5640_XCLK_MAX);
tgt_xclk = max_t(u32, tgt_xclk, (u32)OV5640_XCLK_MIN);
- ov5640_data.mclk = tgt_xclk;
+ sensor->mclk = tgt_xclk;
pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
- ret = clk_set_rate(ov5640_data.sensor_clk, ov5640_data.mclk);
+ ret = clk_set_rate(sensor->sensor_clk, sensor->mclk);
if (ret < 0)
- pr_debug("set rate filed, rate=%d\n", ov5640_data.mclk);
+ pr_debug("set rate filed, rate=%d\n", sensor->mclk);
return ret;
}
/* download ov5640 settings to sensor through i2c */
-static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize)
+static int ov5640_download_firmware(struct ov5640 *sensor,
+ struct reg_value *pModeSetting, s32 ArySize)
{
register u32 Delay_ms = 0;
register u16 RegAddr = 0;
Mask = pModeSetting->u8Mask;
if (Mask) {
- retval = ov5640_read_reg(RegAddr, &RegVal);
+ retval = ov5640_read_reg(sensor, RegAddr, &RegVal);
if (retval < 0)
goto err;
Val |= RegVal;
}
- retval = ov5640_write_reg(RegAddr, Val);
+ retval = ov5640_write_reg(sensor, RegAddr, Val);
if (retval < 0)
goto err;
return retval;
}
-static void ov5640_soft_reset(void)
+static void ov5640_soft_reset(struct ov5640 *sensor)
{
/* sysclk from pad */
- ov5640_write_reg(0x3103, 0x11);
+ ov5640_write_reg(sensor, 0x3103, 0x11);
/* software reset */
- ov5640_write_reg(0x3008, 0x82);
+ ov5640_write_reg(sensor, 0x3008, 0x82);
/* delay at least 5ms */
msleep(10);
}
-static int ov5640_config_init(void)
+static int ov5640_config_init(struct ov5640 *sensor)
{
struct reg_value *pModeSetting = NULL;
int ArySize = 0, retval = 0;
pModeSetting = ov5640_init_parm;
ArySize = ARRAY_SIZE(ov5640_init_parm);
- retval = ov5640_download_firmware(pModeSetting, ArySize);
+ retval = ov5640_download_firmware(sensor, pModeSetting, ArySize);
if (retval < 0)
return retval;
return 0;
}
-static int ov5640_config_resolution(enum ov5640_mode mode)
+static int ov5640_config_resolution(struct ov5640 *sensor,
+ enum ov5640_mode mode)
{
struct reg_value *pModeSetting = NULL;
int ArySize = 0, retval = 0;
return -EINVAL;
if (mode == ov5640_mode_1080P_1920_1080) {
- ov5640_write_reg(0x3709, 0x12);
- ov5640_write_reg(0x3821, 0x06);
+ ov5640_write_reg(sensor, 0x3709, 0x12);
+ ov5640_write_reg(sensor, 0x3821, 0x06);
}
if (mode == ov5640_mode_480_272) {
pModeSetting = ov5640_mode_info_data[mode].init_data_ptr;
ArySize = ov5640_mode_info_data[mode].init_data_size;
- retval = ov5640_download_firmware(pModeSetting, ArySize);
+ retval = ov5640_download_firmware(sensor, pModeSetting, ArySize);
if (retval < 0)
return retval;
return 0;
}
-static int ov5640_config_others(enum ov5640_frame_rate rate,
- enum ov5640_mode mode)
+static int ov5640_config_others(struct ov5640 *sensor,
+ enum ov5640_frame_rate rate, enum ov5640_mode mode)
{
struct reg_value *pModeSetting = NULL;
int ArySize = 0, retval = 0;
ov5640_mode_VGA_640_480 : mode;
pModeSetting = ov5640_mipi_pll_info_data[rate][mode].init_data_ptr;
ArySize = ov5640_mipi_pll_info_data[rate][mode].init_data_size;
- retval = ov5640_download_firmware(pModeSetting, ArySize);
+ retval = ov5640_download_firmware(sensor, pModeSetting, ArySize);
if (retval < 0)
return retval;
/* Configure ov5640 initial parm */
pModeSetting = ov5640_mipi_config;
ArySize = ARRAY_SIZE(ov5640_mipi_config);
- retval = ov5640_download_firmware(pModeSetting, ArySize);
+ retval = ov5640_download_firmware(sensor, pModeSetting, ArySize);
if (retval < 0)
return retval;
return 0;
}
-static void ov5640_start(void)
+static void ov5640_start(struct ov5640 *sensor)
{
- ov5640_write_reg(0x3008, 0x02);
- ov5640_write_reg(0x3008, 0x02);
+ ov5640_write_reg(sensor, 0x3008, 0x02);
+ ov5640_write_reg(sensor, 0x3008, 0x02);
udelay(1000);
}
-static int ov5640_change_mode(enum ov5640_frame_rate rate,
- enum ov5640_mode mode)
+static int ov5640_change_mode(struct ov5640 *sensor,
+ enum ov5640_frame_rate rate, enum ov5640_mode mode)
{
int retval;
rate = ov5640_15_fps;
}
- retval = ov5640_config_resolution(mode);
+ retval = ov5640_config_resolution(sensor, mode);
if (retval < 0) {
pr_err("%s config resolution fail\n", __func__);
return -EINVAL;
}
- retval = ov5640_config_others(rate, mode);
+ retval = ov5640_config_others(sensor, rate, mode);
if (retval < 0) {
pr_err("%s config others fail\n", __func__);
return -EINVAL;
return 0;
}
-static int init_device(void)
+static int init_device(struct ov5640 *sensor)
{
int retval;
- ov5640_soft_reset();
- retval = ov5640_config_init();
+ ov5640_soft_reset(sensor);
+ retval = ov5640_config_init(sensor);
if (retval < 0)
return retval;
- retval = ov5640_config_resolution(ov5640_mode_VGA_640_480);
+ retval = ov5640_config_resolution(sensor, ov5640_mode_VGA_640_480);
if (retval < 0)
return retval;
- retval = ov5640_config_others(ov5640_30_fps, ov5640_mode_VGA_640_480);
+ retval = ov5640_config_others(sensor, ov5640_30_fps,
+ ov5640_mode_VGA_640_480);
if (retval < 0)
return retval;
- ov5640_start();
+ ov5640_start(sensor);
return 0;
}
-static void ov5640_stop(void)
+static void ov5640_stop(struct ov5640 *sensor)
{
- ov5640_write_reg(0x3008, 0x42);
+ ov5640_write_reg(sensor, 0x3008, 0x42);
udelay(1000);
}
struct ov5640 *sensor = to_ov5640(client);
if (on)
- clk_prepare_enable(ov5640_data.sensor_clk);
+ clk_prepare_enable(sensor->sensor_clk);
else
- clk_disable_unprepare(ov5640_data.sensor_clk);
+ clk_disable_unprepare(sensor->sensor_clk);
sensor->on = on;
return 0;
goto error;
}
- ret = ov5640_change_mode(frame_rate, mode);
+ ret = ov5640_change_mode(sensor, frame_rate, mode);
if (ret < 0)
goto error;
struct ov5640 *sensor = to_ov5640(client);
if (enable)
- ov5640_start();
+ ov5640_start(sensor);
else
- ov5640_stop();
+ ov5640_stop(sensor);
sensor->on = enable;
return 0;
return -EINVAL;
if (!fmt) {
- mf->code = ov5640_colour_fmts[1].code;
- mf->colorspace = ov5640_colour_fmts[1].colorspace;
+ mf->code = ov5640_colour_fmts[1].code;
+ mf->colorspace = ov5640_colour_fmts[1].colorspace;
}
- mf->field = V4L2_FIELD_NONE;
+ mf->field = V4L2_FIELD_NONE;
if (format->which == V4L2_SUBDEV_FORMAT_TRY)
return 0;
struct v4l2_subdev *sd;
int retval;
u8 chip_id_high, chip_id_low;
+ struct ov5640 *sensor;
+
+ sensor = kmalloc(sizeof(*sensor), GFP_KERNEL);
+ /* Set initial values for the sensor struct. */
+ memset(sensor, 0, sizeof(*sensor));
/* ov5640 pinctrl */
pinctrl = devm_pinctrl_get_select_default(dev);
}
/* request power down pin */
- pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
- if (!gpio_is_valid(pwn_gpio)) {
- dev_err(dev, "no sensor pwdn pin available\n");
- return -ENODEV;
+ sensor->pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
+ if (!gpio_is_valid(sensor->pwn_gpio))
+ dev_warn(dev, "No sensor pwdn pin available");
+ else {
+ retval = devm_gpio_request_one(dev, sensor->pwn_gpio,
+ GPIOF_OUT_INIT_HIGH, "ov5640_mipi_pwdn");
+ if (retval < 0) {
+ dev_warn(dev, "Failed to set power pin\n");
+ dev_warn(dev, "retval=%d\n", retval);
+ return retval;
+ }
}
- retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
- "ov5640_pwdn");
- if (retval < 0)
- return retval;
/* request reset pin */
- rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
- if (!gpio_is_valid(rst_gpio)) {
- dev_err(dev, "no sensor reset pin available\n");
- devm_gpio_free(dev, rst_gpio);
- return -EINVAL;
- }
- retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_LOW,
- "ov5640_reset");
- if (retval < 0) {
- devm_gpio_free(dev, pwn_gpio);
- return retval;
+ sensor->rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
+ if (!gpio_is_valid(sensor->rst_gpio))
+ dev_warn(dev, "No sensor reset pin available");
+ else {
+ retval = devm_gpio_request_one(dev, sensor->rst_gpio,
+ GPIOF_OUT_INIT_HIGH, "ov5640_mipi_reset");
+ if (retval < 0) {
+ dev_warn(dev, "Failed to set reset pin\n");
+ return retval;
+ }
}
/* Set initial values for the sensor struct. */
- memset(&ov5640_data, 0, sizeof(ov5640_data));
- ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
- if (IS_ERR(ov5640_data.sensor_clk)) {
- dev_err(dev, "get mclk failed\n");
- devm_gpio_free(dev, pwn_gpio);
- devm_gpio_free(dev, rst_gpio);
- return PTR_ERR(ov5640_data.sensor_clk);
+ sensor->sensor_clk = devm_clk_get(dev, "csi_mclk");
+ if (IS_ERR(sensor->sensor_clk)) {
+ /* assuming clock enabled by default */
+ sensor->sensor_clk = NULL;
+ dev_err(dev, "clock-frequency missing or invalid\n");
+ return PTR_ERR(sensor->sensor_clk);
}
retval = of_property_read_u32(dev->of_node, "mclk",
- &ov5640_data.mclk);
+ &(sensor->mclk));
if (retval) {
- dev_err(dev, "mclk frequency is invalid\n");
+ dev_err(dev, "mclk missing or invalid\n");
return retval;
}
retval = of_property_read_u32(dev->of_node, "mclk_source",
- (u32 *) &(ov5640_data.mclk_source));
+ (u32 *) &(sensor->mclk_source));
if (retval) {
- dev_err(dev, "mclk_source invalid\n");
+ dev_err(dev, "mclk_source missing or invalid\n");
return retval;
}
retval = of_property_read_u32(dev->of_node, "csi_id",
- &(ov5640_data.csi));
+ &(sensor->csi));
if (retval) {
- dev_err(dev, "csi_id invalid\n");
+ dev_err(dev, "csi id missing or invalid\n");
return retval;
}
/* Set mclk rate before clk on */
- ov5640_set_clk_rate();
+ ov5640_set_clk_rate(sensor);
- retval = clk_prepare_enable(ov5640_data.sensor_clk);
+ retval = clk_prepare_enable(sensor->sensor_clk);
if (retval < 0) {
dev_err(dev, "%s: enable sensor clk fail\n", __func__);
return -EINVAL;
}
- ov5640_data.io_init = ov5640_reset;
- ov5640_data.i2c_client = client;
+ sensor->io_init = ov5640_reset;
+ sensor->i2c_client = client;
- ov5640_data.pix.pixelformat = V4L2_PIX_FMT_UYVY;
- ov5640_data.pix.width = ov5640_mode_info_data[0].width;
- ov5640_data.pix.height = ov5640_mode_info_data[0].height;
- ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
+ sensor->pix.pixelformat = V4L2_PIX_FMT_UYVY;
+ sensor->pix.width = ov5640_mode_info_data[0].width;
+ sensor->pix.height = ov5640_mode_info_data[0].height;
+ sensor->streamcap.capability = V4L2_MODE_HIGHQUALITY |
V4L2_CAP_TIMEPERFRAME;
- ov5640_data.streamcap.capturemode = 0;
- ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
- ov5640_data.streamcap.timeperframe.numerator = 1;
+ sensor->streamcap.capturemode = 0;
+ sensor->streamcap.timeperframe.denominator = DEFAULT_FPS;
+ sensor->streamcap.timeperframe.numerator = 1;
ov5640_regulator_enable(&client->dev);
- ov5640_reset();
+ ov5640_reset(sensor);
- retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high);
+ retval = ov5640_read_reg(sensor, OV5640_CHIP_ID_HIGH_BYTE,
+ &chip_id_high);
if (retval < 0 || chip_id_high != 0x56) {
- clk_disable_unprepare(ov5640_data.sensor_clk);
+ clk_disable_unprepare(sensor->sensor_clk);
pr_warn("camera ov5640 is not found\n");
return -ENODEV;
}
- retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low);
+ retval = ov5640_read_reg(sensor, OV5640_CHIP_ID_LOW_BYTE,
+ &chip_id_low);
if (retval < 0 || chip_id_low != 0x40) {
- clk_disable_unprepare(ov5640_data.sensor_clk);
+ clk_disable_unprepare(sensor->sensor_clk);
pr_warn("camera ov5640 is not found\n");
return -ENODEV;
}
- retval = init_device();
+ retval = init_device(sensor);
if (retval < 0) {
- clk_disable_unprepare(ov5640_data.sensor_clk);
+ clk_disable_unprepare(sensor->sensor_clk);
pr_warn("camera ov5640 init fail\n");
return -ENODEV;
}
- sd = &ov5640_data.subdev;
+ sd = &sensor->subdev;
v4l2_i2c_subdev_init(sd, client, &ov5640_subdev_ops);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
- ov5640_data.pads[OV5640_SENS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+ sensor->pads[OV5640_SENS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
retval = media_entity_pads_init(&sd->entity, OV5640_SENS_PADS_NUM,
- ov5640_data.pads);
+ sensor->pads);
sd->entity.ops = &ov5640_sd_media_ops;
if (retval < 0)
return retval;
retval = v4l2_async_register_subdev(sd);
if (retval < 0) {
dev_err(&client->dev,
- "%s--Async register failed, ret=%d\n", __func__, retval);
+ "%s--Async register failed, ret=%d\n", __func__, retval);
media_entity_cleanup(&sd->entity);
}
- clk_disable_unprepare(ov5640_data.sensor_clk);
+ clk_disable_unprepare(sensor->sensor_clk);
pr_info("%s camera mipi ov5640, is found\n", __func__);
return retval;
static int ov5640_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct ov5640 *sensor = to_ov5640(client);
v4l2_async_unregister_subdev(sd);
- clk_unprepare(ov5640_data.sensor_clk);
+ clk_unprepare(sensor->sensor_clk);
- ov5640_power_down(1);
+ ov5640_power_down(sensor, 1);
if (analog_regulator)
regulator_disable(analog_regulator);