2 * Driver for OV5642 CMOS Image Sensor from Omnivision
4 * Copyright (C) 2011, Bastian Hecht <hechtb@gmail.com>
6 * Based on Sony IMX074 Camera Driver
7 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
9 * Based on Omnivision OV7670 Camera Driver
10 * Copyright (C) 2006-7 Jonathan Corbet <corbet@lwn.net>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
17 #include <linux/delay.h>
18 #include <linux/i2c.h>
19 #include <linux/slab.h>
20 #include <linux/videodev2.h>
21 #include <linux/module.h>
23 #include <media/soc_camera.h>
24 #include <media/soc_mediabus.h>
25 #include <media/v4l2-chip-ident.h>
26 #include <media/v4l2-subdev.h>
28 /* OV5642 registers */
29 #define REG_CHIP_ID_HIGH 0x300a
30 #define REG_CHIP_ID_LOW 0x300b
32 #define REG_WINDOW_START_X_HIGH 0x3800
33 #define REG_WINDOW_START_X_LOW 0x3801
34 #define REG_WINDOW_START_Y_HIGH 0x3802
35 #define REG_WINDOW_START_Y_LOW 0x3803
36 #define REG_WINDOW_WIDTH_HIGH 0x3804
37 #define REG_WINDOW_WIDTH_LOW 0x3805
38 #define REG_WINDOW_HEIGHT_HIGH 0x3806
39 #define REG_WINDOW_HEIGHT_LOW 0x3807
40 #define REG_OUT_WIDTH_HIGH 0x3808
41 #define REG_OUT_WIDTH_LOW 0x3809
42 #define REG_OUT_HEIGHT_HIGH 0x380a
43 #define REG_OUT_HEIGHT_LOW 0x380b
44 #define REG_OUT_TOTAL_WIDTH_HIGH 0x380c
45 #define REG_OUT_TOTAL_WIDTH_LOW 0x380d
46 #define REG_OUT_TOTAL_HEIGHT_HIGH 0x380e
47 #define REG_OUT_TOTAL_HEIGHT_LOW 0x380f
50 * define standard resolution.
51 * Works currently only for up to 720 lines
52 * eg. 320x240, 640x480, 800x600, 1280x720, 2048x720
55 #define OV5642_WIDTH 1280
56 #define OV5642_HEIGHT 720
57 #define OV5642_TOTAL_WIDTH 3200
58 #define OV5642_TOTAL_HEIGHT 2000
59 #define OV5642_SENSOR_SIZE_X 2592
60 #define OV5642_SENSOR_SIZE_Y 1944
67 static struct regval_list ov5642_default_regs_init
[] = {
528 static struct regval_list ov5642_default_regs_finalise
[] = {
561 { 0x4300, 0x32 }, /* UYVY */
577 struct ov5642_datafmt
{
578 enum v4l2_mbus_pixelcode code
;
579 enum v4l2_colorspace colorspace
;
583 struct v4l2_subdev subdev
;
584 const struct ov5642_datafmt
*fmt
;
587 static const struct ov5642_datafmt ov5642_colour_fmts
[] = {
588 {V4L2_MBUS_FMT_UYVY8_2X8
, V4L2_COLORSPACE_JPEG
},
591 static struct ov5642
*to_ov5642(const struct i2c_client
*client
)
593 return container_of(i2c_get_clientdata(client
), struct ov5642
, subdev
);
596 /* Find a data format by a pixel code in an array */
597 static const struct ov5642_datafmt
598 *ov5642_find_datafmt(enum v4l2_mbus_pixelcode code
)
602 for (i
= 0; i
< ARRAY_SIZE(ov5642_colour_fmts
); i
++)
603 if (ov5642_colour_fmts
[i
].code
== code
)
604 return ov5642_colour_fmts
+ i
;
609 static int reg_read(struct i2c_client
*client
, u16 reg
, u8
*val
)
612 /* We have 16-bit i2c addresses - care for endianess */
613 unsigned char data
[2] = { reg
>> 8, reg
& 0xff };
615 ret
= i2c_master_send(client
, data
, 2);
617 dev_err(&client
->dev
, "%s: i2c read error, reg: %x\n",
619 return ret
< 0 ? ret
: -EIO
;
622 ret
= i2c_master_recv(client
, val
, 1);
624 dev_err(&client
->dev
, "%s: i2c read error, reg: %x\n",
626 return ret
< 0 ? ret
: -EIO
;
631 static int reg_write(struct i2c_client
*client
, u16 reg
, u8 val
)
634 unsigned char data
[3] = { reg
>> 8, reg
& 0xff, val
};
636 ret
= i2c_master_send(client
, data
, 3);
638 dev_err(&client
->dev
, "%s: i2c write error, reg: %x\n",
640 return ret
< 0 ? ret
: -EIO
;
645 #ifdef CONFIG_VIDEO_ADV_DEBUG
646 static int ov5642_get_register(struct v4l2_subdev
*sd
, struct v4l2_dbg_register
*reg
)
648 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
652 if (reg
->reg
& ~0xffff)
657 ret
= reg_read(client
, reg
->reg
, &val
);
659 reg
->val
= (__u64
)val
;
664 static int ov5642_set_register(struct v4l2_subdev
*sd
, struct v4l2_dbg_register
*reg
)
666 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
668 if (reg
->reg
& ~0xffff || reg
->val
& ~0xff)
671 return reg_write(client
, reg
->reg
, reg
->val
);
675 static int ov5642_write_array(struct i2c_client
*client
,
676 struct regval_list
*vals
)
678 while (vals
->reg_num
!= 0xffff || vals
->value
!= 0xff) {
679 int ret
= reg_write(client
, vals
->reg_num
, vals
->value
);
684 dev_dbg(&client
->dev
, "Register list loaded\n");
688 static int ov5642_set_resolution(struct i2c_client
*client
)
691 u8 start_x_high
= ((OV5642_SENSOR_SIZE_X
- OV5642_WIDTH
) / 2) >> 8;
692 u8 start_x_low
= ((OV5642_SENSOR_SIZE_X
- OV5642_WIDTH
) / 2) & 0xff;
693 u8 start_y_high
= ((OV5642_SENSOR_SIZE_Y
- OV5642_HEIGHT
) / 2) >> 8;
694 u8 start_y_low
= ((OV5642_SENSOR_SIZE_Y
- OV5642_HEIGHT
) / 2) & 0xff;
696 u8 width_high
= OV5642_WIDTH
>> 8;
697 u8 width_low
= OV5642_WIDTH
& 0xff;
698 u8 height_high
= OV5642_HEIGHT
>> 8;
699 u8 height_low
= OV5642_HEIGHT
& 0xff;
701 u8 total_width_high
= OV5642_TOTAL_WIDTH
>> 8;
702 u8 total_width_low
= OV5642_TOTAL_WIDTH
& 0xff;
703 u8 total_height_high
= OV5642_TOTAL_HEIGHT
>> 8;
704 u8 total_height_low
= OV5642_TOTAL_HEIGHT
& 0xff;
706 ret
= reg_write(client
, REG_WINDOW_START_X_HIGH
, start_x_high
);
708 ret
= reg_write(client
, REG_WINDOW_START_X_LOW
, start_x_low
);
710 ret
= reg_write(client
, REG_WINDOW_START_Y_HIGH
, start_y_high
);
712 ret
= reg_write(client
, REG_WINDOW_START_Y_LOW
, start_y_low
);
715 ret
= reg_write(client
, REG_WINDOW_WIDTH_HIGH
, width_high
);
717 ret
= reg_write(client
, REG_WINDOW_WIDTH_LOW
, width_low
);
719 ret
= reg_write(client
, REG_WINDOW_HEIGHT_HIGH
, height_high
);
721 ret
= reg_write(client
, REG_WINDOW_HEIGHT_LOW
, height_low
);
724 ret
= reg_write(client
, REG_OUT_WIDTH_HIGH
, width_high
);
726 ret
= reg_write(client
, REG_OUT_WIDTH_LOW
, width_low
);
728 ret
= reg_write(client
, REG_OUT_HEIGHT_HIGH
, height_high
);
730 ret
= reg_write(client
, REG_OUT_HEIGHT_LOW
, height_low
);
733 ret
= reg_write(client
, REG_OUT_TOTAL_WIDTH_HIGH
, total_width_high
);
735 ret
= reg_write(client
, REG_OUT_TOTAL_WIDTH_LOW
, total_width_low
);
737 ret
= reg_write(client
, REG_OUT_TOTAL_HEIGHT_HIGH
, total_height_high
);
739 ret
= reg_write(client
, REG_OUT_TOTAL_HEIGHT_LOW
, total_height_low
);
744 static int ov5642_try_fmt(struct v4l2_subdev
*sd
,
745 struct v4l2_mbus_framefmt
*mf
)
747 const struct ov5642_datafmt
*fmt
= ov5642_find_datafmt(mf
->code
);
749 dev_dbg(sd
->v4l2_dev
->dev
, "%s(%u) width: %u heigth: %u\n",
750 __func__
, mf
->code
, mf
->width
, mf
->height
);
753 mf
->code
= ov5642_colour_fmts
[0].code
;
754 mf
->colorspace
= ov5642_colour_fmts
[0].colorspace
;
757 mf
->width
= OV5642_WIDTH
;
758 mf
->height
= OV5642_HEIGHT
;
759 mf
->field
= V4L2_FIELD_NONE
;
764 static int ov5642_s_fmt(struct v4l2_subdev
*sd
,
765 struct v4l2_mbus_framefmt
*mf
)
767 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
768 struct ov5642
*priv
= to_ov5642(client
);
770 dev_dbg(sd
->v4l2_dev
->dev
, "%s(%u)\n", __func__
, mf
->code
);
772 /* MIPI CSI could have changed the format, double-check */
773 if (!ov5642_find_datafmt(mf
->code
))
776 ov5642_try_fmt(sd
, mf
);
778 priv
->fmt
= ov5642_find_datafmt(mf
->code
);
780 ov5642_write_array(client
, ov5642_default_regs_init
);
781 ov5642_set_resolution(client
);
782 ov5642_write_array(client
, ov5642_default_regs_finalise
);
787 static int ov5642_g_fmt(struct v4l2_subdev
*sd
,
788 struct v4l2_mbus_framefmt
*mf
)
790 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
791 struct ov5642
*priv
= to_ov5642(client
);
793 const struct ov5642_datafmt
*fmt
= priv
->fmt
;
795 mf
->code
= fmt
->code
;
796 mf
->colorspace
= fmt
->colorspace
;
797 mf
->width
= OV5642_WIDTH
;
798 mf
->height
= OV5642_HEIGHT
;
799 mf
->field
= V4L2_FIELD_NONE
;
804 static int ov5642_enum_fmt(struct v4l2_subdev
*sd
, unsigned int index
,
805 enum v4l2_mbus_pixelcode
*code
)
807 if (index
>= ARRAY_SIZE(ov5642_colour_fmts
))
810 *code
= ov5642_colour_fmts
[index
].code
;
814 static int ov5642_g_chip_ident(struct v4l2_subdev
*sd
,
815 struct v4l2_dbg_chip_ident
*id
)
817 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
819 if (id
->match
.type
!= V4L2_CHIP_MATCH_I2C_ADDR
)
822 if (id
->match
.addr
!= client
->addr
)
825 id
->ident
= V4L2_IDENT_OV5642
;
831 static int ov5642_g_crop(struct v4l2_subdev
*sd
, struct v4l2_crop
*a
)
833 struct v4l2_rect
*rect
= &a
->c
;
835 a
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
838 rect
->width
= OV5642_WIDTH
;
839 rect
->height
= OV5642_HEIGHT
;
844 static int ov5642_cropcap(struct v4l2_subdev
*sd
, struct v4l2_cropcap
*a
)
848 a
->bounds
.width
= OV5642_WIDTH
;
849 a
->bounds
.height
= OV5642_HEIGHT
;
850 a
->defrect
= a
->bounds
;
851 a
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
852 a
->pixelaspect
.numerator
= 1;
853 a
->pixelaspect
.denominator
= 1;
858 static int ov5642_g_mbus_config(struct v4l2_subdev
*sd
,
859 struct v4l2_mbus_config
*cfg
)
861 cfg
->type
= V4L2_MBUS_CSI2
;
862 cfg
->flags
= V4L2_MBUS_CSI2_2_LANE
|
863 V4L2_MBUS_CSI2_CHANNEL_0
|
864 V4L2_MBUS_CSI2_CONTINUOUS_CLOCK
;
869 static struct v4l2_subdev_video_ops ov5642_subdev_video_ops
= {
870 .s_mbus_fmt
= ov5642_s_fmt
,
871 .g_mbus_fmt
= ov5642_g_fmt
,
872 .try_mbus_fmt
= ov5642_try_fmt
,
873 .enum_mbus_fmt
= ov5642_enum_fmt
,
874 .g_crop
= ov5642_g_crop
,
875 .cropcap
= ov5642_cropcap
,
876 .g_mbus_config
= ov5642_g_mbus_config
,
879 static struct v4l2_subdev_core_ops ov5642_subdev_core_ops
= {
880 .g_chip_ident
= ov5642_g_chip_ident
,
881 #ifdef CONFIG_VIDEO_ADV_DEBUG
882 .g_register
= ov5642_get_register
,
883 .s_register
= ov5642_set_register
,
887 static struct v4l2_subdev_ops ov5642_subdev_ops
= {
888 .core
= &ov5642_subdev_core_ops
,
889 .video
= &ov5642_subdev_video_ops
,
892 static int ov5642_video_probe(struct soc_camera_device
*icd
,
893 struct i2c_client
*client
)
899 /* Read sensor Model ID */
900 ret
= reg_read(client
, REG_CHIP_ID_HIGH
, &id_high
);
906 ret
= reg_read(client
, REG_CHIP_ID_LOW
, &id_low
);
912 dev_info(&client
->dev
, "Chip ID 0x%04x detected\n", id
);
920 static int ov5642_probe(struct i2c_client
*client
,
921 const struct i2c_device_id
*did
)
924 struct soc_camera_device
*icd
= client
->dev
.platform_data
;
925 struct soc_camera_link
*icl
;
929 dev_err(&client
->dev
, "OV5642: missing soc-camera data!\n");
933 icl
= to_soc_camera_link(icd
);
935 dev_err(&client
->dev
, "OV5642: missing platform data!\n");
939 priv
= kzalloc(sizeof(struct ov5642
), GFP_KERNEL
);
943 v4l2_i2c_subdev_init(&priv
->subdev
, client
, &ov5642_subdev_ops
);
946 priv
->fmt
= &ov5642_colour_fmts
[0];
948 ret
= ov5642_video_probe(icd
, client
);
959 static int ov5642_remove(struct i2c_client
*client
)
961 struct ov5642
*priv
= to_ov5642(client
);
962 struct soc_camera_device
*icd
= client
->dev
.platform_data
;
963 struct soc_camera_link
*icl
= to_soc_camera_link(icd
);
972 static const struct i2c_device_id ov5642_id
[] = {
976 MODULE_DEVICE_TABLE(i2c
, ov5642_id
);
978 static struct i2c_driver ov5642_i2c_driver
= {
982 .probe
= ov5642_probe
,
983 .remove
= ov5642_remove
,
984 .id_table
= ov5642_id
,
987 static int __init
ov5642_mod_init(void)
989 return i2c_add_driver(&ov5642_i2c_driver
);
992 static void __exit
ov5642_mod_exit(void)
994 i2c_del_driver(&ov5642_i2c_driver
);
997 module_init(ov5642_mod_init
);
998 module_exit(ov5642_mod_exit
);
1000 MODULE_DESCRIPTION("Omnivision OV5642 Camera driver");
1001 MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>");
1002 MODULE_LICENSE("GPL v2");