1c4c0283aSBenoit Parrot /* 2c4c0283aSBenoit Parrot * Omnivision OV2659 CMOS Image Sensor driver 3c4c0283aSBenoit Parrot * 4c4c0283aSBenoit Parrot * Copyright (C) 2015 Texas Instruments, Inc. 5c4c0283aSBenoit Parrot * 6c4c0283aSBenoit Parrot * Benoit Parrot <bparrot@ti.com> 7c4c0283aSBenoit Parrot * Lad, Prabhakar <prabhakar.csengg@gmail.com> 8c4c0283aSBenoit Parrot * 9c4c0283aSBenoit Parrot * This program is free software; you may redistribute it and/or modify 10c4c0283aSBenoit Parrot * it under the terms of the GNU General Public License as published by 11c4c0283aSBenoit Parrot * the Free Software Foundation; version 2 of the License. 12c4c0283aSBenoit Parrot * 13c4c0283aSBenoit Parrot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14c4c0283aSBenoit Parrot * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15c4c0283aSBenoit Parrot * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16c4c0283aSBenoit Parrot * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 17c4c0283aSBenoit Parrot * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 18c4c0283aSBenoit Parrot * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19c4c0283aSBenoit Parrot * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20c4c0283aSBenoit Parrot * SOFTWARE. 21c4c0283aSBenoit Parrot */ 22c4c0283aSBenoit Parrot 23c4c0283aSBenoit Parrot #include <linux/clk.h> 24c4c0283aSBenoit Parrot #include <linux/delay.h> 25c4c0283aSBenoit Parrot #include <linux/err.h> 26c4c0283aSBenoit Parrot #include <linux/init.h> 27c4c0283aSBenoit Parrot #include <linux/interrupt.h> 28c4c0283aSBenoit Parrot #include <linux/io.h> 29c4c0283aSBenoit Parrot #include <linux/i2c.h> 30c4c0283aSBenoit Parrot #include <linux/kernel.h> 31c4c0283aSBenoit Parrot #include <linux/media.h> 32c4c0283aSBenoit Parrot #include <linux/module.h> 33c4c0283aSBenoit Parrot #include <linux/of.h> 34c4c0283aSBenoit Parrot #include <linux/of_graph.h> 35c4c0283aSBenoit Parrot #include <linux/slab.h> 36c4c0283aSBenoit Parrot #include <linux/uaccess.h> 37c4c0283aSBenoit Parrot #include <linux/videodev2.h> 38c4c0283aSBenoit Parrot 39c4c0283aSBenoit Parrot #include <media/media-entity.h> 40b5dcee22SMauro Carvalho Chehab #include <media/i2c/ov2659.h> 41c4c0283aSBenoit Parrot #include <media/v4l2-common.h> 42c4c0283aSBenoit Parrot #include <media/v4l2-ctrls.h> 43c4c0283aSBenoit Parrot #include <media/v4l2-device.h> 44c4c0283aSBenoit Parrot #include <media/v4l2-event.h> 45859969b3SSakari Ailus #include <media/v4l2-fwnode.h> 46c4c0283aSBenoit Parrot #include <media/v4l2-image-sizes.h> 47c4c0283aSBenoit Parrot #include <media/v4l2-mediabus.h> 48c4c0283aSBenoit Parrot #include <media/v4l2-subdev.h> 49c4c0283aSBenoit Parrot 50c4c0283aSBenoit Parrot #define DRIVER_NAME "ov2659" 51c4c0283aSBenoit Parrot 52c4c0283aSBenoit Parrot /* 53c4c0283aSBenoit Parrot * OV2659 register definitions 54c4c0283aSBenoit Parrot */ 55c4c0283aSBenoit Parrot #define REG_SOFTWARE_STANDBY 0x0100 56c4c0283aSBenoit Parrot #define REG_SOFTWARE_RESET 0x0103 57c4c0283aSBenoit Parrot #define REG_IO_CTRL00 0x3000 58c4c0283aSBenoit Parrot #define REG_IO_CTRL01 0x3001 59c4c0283aSBenoit Parrot #define REG_IO_CTRL02 0x3002 60c4c0283aSBenoit Parrot #define REG_OUTPUT_VALUE00 0x3008 61c4c0283aSBenoit Parrot #define REG_OUTPUT_VALUE01 0x3009 62c4c0283aSBenoit Parrot #define REG_OUTPUT_VALUE02 0x300d 63c4c0283aSBenoit Parrot #define REG_OUTPUT_SELECT00 0x300e 64c4c0283aSBenoit Parrot #define REG_OUTPUT_SELECT01 0x300f 65c4c0283aSBenoit Parrot #define REG_OUTPUT_SELECT02 0x3010 66c4c0283aSBenoit Parrot #define REG_OUTPUT_DRIVE 0x3011 67c4c0283aSBenoit Parrot #define REG_INPUT_READOUT00 0x302d 68c4c0283aSBenoit Parrot #define REG_INPUT_READOUT01 0x302e 69c4c0283aSBenoit Parrot #define REG_INPUT_READOUT02 0x302f 70c4c0283aSBenoit Parrot 71c4c0283aSBenoit Parrot #define REG_SC_PLL_CTRL0 0x3003 72c4c0283aSBenoit Parrot #define REG_SC_PLL_CTRL1 0x3004 73c4c0283aSBenoit Parrot #define REG_SC_PLL_CTRL2 0x3005 74c4c0283aSBenoit Parrot #define REG_SC_PLL_CTRL3 0x3006 75c4c0283aSBenoit Parrot #define REG_SC_CHIP_ID_H 0x300a 76c4c0283aSBenoit Parrot #define REG_SC_CHIP_ID_L 0x300b 77c4c0283aSBenoit Parrot #define REG_SC_PWC 0x3014 78c4c0283aSBenoit Parrot #define REG_SC_CLKRST0 0x301a 79c4c0283aSBenoit Parrot #define REG_SC_CLKRST1 0x301b 80c4c0283aSBenoit Parrot #define REG_SC_CLKRST2 0x301c 81c4c0283aSBenoit Parrot #define REG_SC_CLKRST3 0x301d 82c4c0283aSBenoit Parrot #define REG_SC_SUB_ID 0x302a 83c4c0283aSBenoit Parrot #define REG_SC_SCCB_ID 0x302b 84c4c0283aSBenoit Parrot 85c4c0283aSBenoit Parrot #define REG_GROUP_ADDRESS_00 0x3200 86c4c0283aSBenoit Parrot #define REG_GROUP_ADDRESS_01 0x3201 87c4c0283aSBenoit Parrot #define REG_GROUP_ADDRESS_02 0x3202 88c4c0283aSBenoit Parrot #define REG_GROUP_ADDRESS_03 0x3203 89c4c0283aSBenoit Parrot #define REG_GROUP_ACCESS 0x3208 90c4c0283aSBenoit Parrot 91c4c0283aSBenoit Parrot #define REG_AWB_R_GAIN_H 0x3400 92c4c0283aSBenoit Parrot #define REG_AWB_R_GAIN_L 0x3401 93c4c0283aSBenoit Parrot #define REG_AWB_G_GAIN_H 0x3402 94c4c0283aSBenoit Parrot #define REG_AWB_G_GAIN_L 0x3403 95c4c0283aSBenoit Parrot #define REG_AWB_B_GAIN_H 0x3404 96c4c0283aSBenoit Parrot #define REG_AWB_B_GAIN_L 0x3405 97c4c0283aSBenoit Parrot #define REG_AWB_MANUAL_CONTROL 0x3406 98c4c0283aSBenoit Parrot 99c4c0283aSBenoit Parrot #define REG_TIMING_HS_H 0x3800 100c4c0283aSBenoit Parrot #define REG_TIMING_HS_L 0x3801 101c4c0283aSBenoit Parrot #define REG_TIMING_VS_H 0x3802 102c4c0283aSBenoit Parrot #define REG_TIMING_VS_L 0x3803 103c4c0283aSBenoit Parrot #define REG_TIMING_HW_H 0x3804 104c4c0283aSBenoit Parrot #define REG_TIMING_HW_L 0x3805 105c4c0283aSBenoit Parrot #define REG_TIMING_VH_H 0x3806 106c4c0283aSBenoit Parrot #define REG_TIMING_VH_L 0x3807 107c4c0283aSBenoit Parrot #define REG_TIMING_DVPHO_H 0x3808 108c4c0283aSBenoit Parrot #define REG_TIMING_DVPHO_L 0x3809 109c4c0283aSBenoit Parrot #define REG_TIMING_DVPVO_H 0x380a 110c4c0283aSBenoit Parrot #define REG_TIMING_DVPVO_L 0x380b 111c4c0283aSBenoit Parrot #define REG_TIMING_HTS_H 0x380c 112c4c0283aSBenoit Parrot #define REG_TIMING_HTS_L 0x380d 113c4c0283aSBenoit Parrot #define REG_TIMING_VTS_H 0x380e 114c4c0283aSBenoit Parrot #define REG_TIMING_VTS_L 0x380f 115c4c0283aSBenoit Parrot #define REG_TIMING_HOFFS_H 0x3810 116c4c0283aSBenoit Parrot #define REG_TIMING_HOFFS_L 0x3811 117c4c0283aSBenoit Parrot #define REG_TIMING_VOFFS_H 0x3812 118c4c0283aSBenoit Parrot #define REG_TIMING_VOFFS_L 0x3813 119c4c0283aSBenoit Parrot #define REG_TIMING_XINC 0x3814 120c4c0283aSBenoit Parrot #define REG_TIMING_YINC 0x3815 121c4c0283aSBenoit Parrot #define REG_TIMING_VERT_FORMAT 0x3820 122c4c0283aSBenoit Parrot #define REG_TIMING_HORIZ_FORMAT 0x3821 123c4c0283aSBenoit Parrot 124c4c0283aSBenoit Parrot #define REG_FORMAT_CTRL00 0x4300 125c4c0283aSBenoit Parrot 126c4c0283aSBenoit Parrot #define REG_VFIFO_READ_START_H 0x4608 127c4c0283aSBenoit Parrot #define REG_VFIFO_READ_START_L 0x4609 128c4c0283aSBenoit Parrot 129c4c0283aSBenoit Parrot #define REG_DVP_CTRL02 0x4708 130c4c0283aSBenoit Parrot 131c4c0283aSBenoit Parrot #define REG_ISP_CTRL00 0x5000 132c4c0283aSBenoit Parrot #define REG_ISP_CTRL01 0x5001 133c4c0283aSBenoit Parrot #define REG_ISP_CTRL02 0x5002 134c4c0283aSBenoit Parrot 135c4c0283aSBenoit Parrot #define REG_LENC_RED_X0_H 0x500c 136c4c0283aSBenoit Parrot #define REG_LENC_RED_X0_L 0x500d 137c4c0283aSBenoit Parrot #define REG_LENC_RED_Y0_H 0x500e 138c4c0283aSBenoit Parrot #define REG_LENC_RED_Y0_L 0x500f 139c4c0283aSBenoit Parrot #define REG_LENC_RED_A1 0x5010 140c4c0283aSBenoit Parrot #define REG_LENC_RED_B1 0x5011 141c4c0283aSBenoit Parrot #define REG_LENC_RED_A2_B2 0x5012 142c4c0283aSBenoit Parrot #define REG_LENC_GREEN_X0_H 0x5013 143c4c0283aSBenoit Parrot #define REG_LENC_GREEN_X0_L 0x5014 144c4c0283aSBenoit Parrot #define REG_LENC_GREEN_Y0_H 0x5015 145c4c0283aSBenoit Parrot #define REG_LENC_GREEN_Y0_L 0x5016 146c4c0283aSBenoit Parrot #define REG_LENC_GREEN_A1 0x5017 147c4c0283aSBenoit Parrot #define REG_LENC_GREEN_B1 0x5018 148c4c0283aSBenoit Parrot #define REG_LENC_GREEN_A2_B2 0x5019 149c4c0283aSBenoit Parrot #define REG_LENC_BLUE_X0_H 0x501a 150c4c0283aSBenoit Parrot #define REG_LENC_BLUE_X0_L 0x501b 151c4c0283aSBenoit Parrot #define REG_LENC_BLUE_Y0_H 0x501c 152c4c0283aSBenoit Parrot #define REG_LENC_BLUE_Y0_L 0x501d 153c4c0283aSBenoit Parrot #define REG_LENC_BLUE_A1 0x501e 154c4c0283aSBenoit Parrot #define REG_LENC_BLUE_B1 0x501f 155c4c0283aSBenoit Parrot #define REG_LENC_BLUE_A2_B2 0x5020 156c4c0283aSBenoit Parrot 157c4c0283aSBenoit Parrot #define REG_AWB_CTRL00 0x5035 158c4c0283aSBenoit Parrot #define REG_AWB_CTRL01 0x5036 159c4c0283aSBenoit Parrot #define REG_AWB_CTRL02 0x5037 160c4c0283aSBenoit Parrot #define REG_AWB_CTRL03 0x5038 161c4c0283aSBenoit Parrot #define REG_AWB_CTRL04 0x5039 162c4c0283aSBenoit Parrot #define REG_AWB_LOCAL_LIMIT 0x503a 163c4c0283aSBenoit Parrot #define REG_AWB_CTRL12 0x5049 164c4c0283aSBenoit Parrot #define REG_AWB_CTRL13 0x504a 165c4c0283aSBenoit Parrot #define REG_AWB_CTRL14 0x504b 166c4c0283aSBenoit Parrot 167c4c0283aSBenoit Parrot #define REG_SHARPENMT_THRESH1 0x5064 168c4c0283aSBenoit Parrot #define REG_SHARPENMT_THRESH2 0x5065 169c4c0283aSBenoit Parrot #define REG_SHARPENMT_OFFSET1 0x5066 170c4c0283aSBenoit Parrot #define REG_SHARPENMT_OFFSET2 0x5067 171c4c0283aSBenoit Parrot #define REG_DENOISE_THRESH1 0x5068 172c4c0283aSBenoit Parrot #define REG_DENOISE_THRESH2 0x5069 173c4c0283aSBenoit Parrot #define REG_DENOISE_OFFSET1 0x506a 174c4c0283aSBenoit Parrot #define REG_DENOISE_OFFSET2 0x506b 175c4c0283aSBenoit Parrot #define REG_SHARPEN_THRESH1 0x506c 176c4c0283aSBenoit Parrot #define REG_SHARPEN_THRESH2 0x506d 177c4c0283aSBenoit Parrot #define REG_CIP_CTRL00 0x506e 178c4c0283aSBenoit Parrot #define REG_CIP_CTRL01 0x506f 179c4c0283aSBenoit Parrot 180c4c0283aSBenoit Parrot #define REG_CMX_SIGN 0x5079 181c4c0283aSBenoit Parrot #define REG_CMX_MISC_CTRL 0x507a 182c4c0283aSBenoit Parrot 183c4c0283aSBenoit Parrot #define REG_PRE_ISP_CTRL00 0x50a0 184c4c0283aSBenoit Parrot #define TEST_PATTERN_ENABLE BIT(7) 185c4c0283aSBenoit Parrot #define VERTICAL_COLOR_BAR_MASK 0x53 186c4c0283aSBenoit Parrot 187c4c0283aSBenoit Parrot #define REG_NULL 0x0000 /* Array end token */ 188c4c0283aSBenoit Parrot 189c4c0283aSBenoit Parrot #define OV265X_ID(_msb, _lsb) ((_msb) << 8 | (_lsb)) 190c4c0283aSBenoit Parrot #define OV2659_ID 0x2656 191c4c0283aSBenoit Parrot 192c4c0283aSBenoit Parrot struct sensor_register { 193c4c0283aSBenoit Parrot u16 addr; 194c4c0283aSBenoit Parrot u8 value; 195c4c0283aSBenoit Parrot }; 196c4c0283aSBenoit Parrot 197c4c0283aSBenoit Parrot struct ov2659_framesize { 198c4c0283aSBenoit Parrot u16 width; 199c4c0283aSBenoit Parrot u16 height; 200c4c0283aSBenoit Parrot u16 max_exp_lines; 201c4c0283aSBenoit Parrot const struct sensor_register *regs; 202c4c0283aSBenoit Parrot }; 203c4c0283aSBenoit Parrot 204c4c0283aSBenoit Parrot struct ov2659_pll_ctrl { 205c4c0283aSBenoit Parrot u8 ctrl1; 206c4c0283aSBenoit Parrot u8 ctrl2; 207c4c0283aSBenoit Parrot u8 ctrl3; 208c4c0283aSBenoit Parrot }; 209c4c0283aSBenoit Parrot 210c4c0283aSBenoit Parrot struct ov2659_pixfmt { 211c4c0283aSBenoit Parrot u32 code; 212c4c0283aSBenoit Parrot /* Output format Register Value (REG_FORMAT_CTRL00) */ 213c4c0283aSBenoit Parrot struct sensor_register *format_ctrl_regs; 214c4c0283aSBenoit Parrot }; 215c4c0283aSBenoit Parrot 216c4c0283aSBenoit Parrot struct pll_ctrl_reg { 217c4c0283aSBenoit Parrot unsigned int div; 218c4c0283aSBenoit Parrot unsigned char reg; 219c4c0283aSBenoit Parrot }; 220c4c0283aSBenoit Parrot 221c4c0283aSBenoit Parrot struct ov2659 { 222c4c0283aSBenoit Parrot struct v4l2_subdev sd; 223c4c0283aSBenoit Parrot struct media_pad pad; 224c4c0283aSBenoit Parrot struct v4l2_mbus_framefmt format; 225c4c0283aSBenoit Parrot unsigned int xvclk_frequency; 226c4c0283aSBenoit Parrot const struct ov2659_platform_data *pdata; 227c4c0283aSBenoit Parrot struct mutex lock; 228c4c0283aSBenoit Parrot struct i2c_client *client; 229c4c0283aSBenoit Parrot struct v4l2_ctrl_handler ctrls; 230c4c0283aSBenoit Parrot struct v4l2_ctrl *link_frequency; 231c4c0283aSBenoit Parrot const struct ov2659_framesize *frame_size; 232c4c0283aSBenoit Parrot struct sensor_register *format_ctrl_regs; 233c4c0283aSBenoit Parrot struct ov2659_pll_ctrl pll; 234c4c0283aSBenoit Parrot int streaming; 235c4c0283aSBenoit Parrot }; 236c4c0283aSBenoit Parrot 237c4c0283aSBenoit Parrot static const struct sensor_register ov2659_init_regs[] = { 238c4c0283aSBenoit Parrot { REG_IO_CTRL00, 0x03 }, 239c4c0283aSBenoit Parrot { REG_IO_CTRL01, 0xff }, 240c4c0283aSBenoit Parrot { REG_IO_CTRL02, 0xe0 }, 241c4c0283aSBenoit Parrot { 0x3633, 0x3d }, 242c4c0283aSBenoit Parrot { 0x3620, 0x02 }, 243c4c0283aSBenoit Parrot { 0x3631, 0x11 }, 244c4c0283aSBenoit Parrot { 0x3612, 0x04 }, 245c4c0283aSBenoit Parrot { 0x3630, 0x20 }, 246c4c0283aSBenoit Parrot { 0x4702, 0x02 }, 247c4c0283aSBenoit Parrot { 0x370c, 0x34 }, 248c4c0283aSBenoit Parrot { REG_TIMING_HS_H, 0x00 }, 249c4c0283aSBenoit Parrot { REG_TIMING_HS_L, 0x00 }, 250c4c0283aSBenoit Parrot { REG_TIMING_VS_H, 0x00 }, 251c4c0283aSBenoit Parrot { REG_TIMING_VS_L, 0x00 }, 252c4c0283aSBenoit Parrot { REG_TIMING_HW_H, 0x06 }, 253c4c0283aSBenoit Parrot { REG_TIMING_HW_L, 0x5f }, 254c4c0283aSBenoit Parrot { REG_TIMING_VH_H, 0x04 }, 255c4c0283aSBenoit Parrot { REG_TIMING_VH_L, 0xb7 }, 256c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_H, 0x03 }, 257c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_L, 0x20 }, 258c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_H, 0x02 }, 259c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_L, 0x58 }, 260c4c0283aSBenoit Parrot { REG_TIMING_HTS_H, 0x05 }, 261c4c0283aSBenoit Parrot { REG_TIMING_HTS_L, 0x14 }, 262c4c0283aSBenoit Parrot { REG_TIMING_VTS_H, 0x02 }, 263c4c0283aSBenoit Parrot { REG_TIMING_VTS_L, 0x68 }, 264c4c0283aSBenoit Parrot { REG_TIMING_HOFFS_L, 0x08 }, 265c4c0283aSBenoit Parrot { REG_TIMING_VOFFS_L, 0x02 }, 266c4c0283aSBenoit Parrot { REG_TIMING_XINC, 0x31 }, 267c4c0283aSBenoit Parrot { REG_TIMING_YINC, 0x31 }, 268c4c0283aSBenoit Parrot { 0x3a02, 0x02 }, 269c4c0283aSBenoit Parrot { 0x3a03, 0x68 }, 270c4c0283aSBenoit Parrot { 0x3a08, 0x00 }, 271c4c0283aSBenoit Parrot { 0x3a09, 0x5c }, 272c4c0283aSBenoit Parrot { 0x3a0a, 0x00 }, 273c4c0283aSBenoit Parrot { 0x3a0b, 0x4d }, 274c4c0283aSBenoit Parrot { 0x3a0d, 0x08 }, 275c4c0283aSBenoit Parrot { 0x3a0e, 0x06 }, 276c4c0283aSBenoit Parrot { 0x3a14, 0x02 }, 277c4c0283aSBenoit Parrot { 0x3a15, 0x28 }, 278c4c0283aSBenoit Parrot { REG_DVP_CTRL02, 0x01 }, 279c4c0283aSBenoit Parrot { 0x3623, 0x00 }, 280c4c0283aSBenoit Parrot { 0x3634, 0x76 }, 281c4c0283aSBenoit Parrot { 0x3701, 0x44 }, 282c4c0283aSBenoit Parrot { 0x3702, 0x18 }, 283c4c0283aSBenoit Parrot { 0x3703, 0x24 }, 284c4c0283aSBenoit Parrot { 0x3704, 0x24 }, 285c4c0283aSBenoit Parrot { 0x3705, 0x0c }, 286c4c0283aSBenoit Parrot { REG_TIMING_VERT_FORMAT, 0x81 }, 287c4c0283aSBenoit Parrot { REG_TIMING_HORIZ_FORMAT, 0x01 }, 288c4c0283aSBenoit Parrot { 0x370a, 0x52 }, 289c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_H, 0x00 }, 290c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_L, 0x80 }, 291c4c0283aSBenoit Parrot { REG_FORMAT_CTRL00, 0x30 }, 292c4c0283aSBenoit Parrot { 0x5086, 0x02 }, 293c4c0283aSBenoit Parrot { REG_ISP_CTRL00, 0xfb }, 294c4c0283aSBenoit Parrot { REG_ISP_CTRL01, 0x1f }, 295c4c0283aSBenoit Parrot { REG_ISP_CTRL02, 0x00 }, 296c4c0283aSBenoit Parrot { 0x5025, 0x0e }, 297c4c0283aSBenoit Parrot { 0x5026, 0x18 }, 298c4c0283aSBenoit Parrot { 0x5027, 0x34 }, 299c4c0283aSBenoit Parrot { 0x5028, 0x4c }, 300c4c0283aSBenoit Parrot { 0x5029, 0x62 }, 301c4c0283aSBenoit Parrot { 0x502a, 0x74 }, 302c4c0283aSBenoit Parrot { 0x502b, 0x85 }, 303c4c0283aSBenoit Parrot { 0x502c, 0x92 }, 304c4c0283aSBenoit Parrot { 0x502d, 0x9e }, 305c4c0283aSBenoit Parrot { 0x502e, 0xb2 }, 306c4c0283aSBenoit Parrot { 0x502f, 0xc0 }, 307c4c0283aSBenoit Parrot { 0x5030, 0xcc }, 308c4c0283aSBenoit Parrot { 0x5031, 0xe0 }, 309c4c0283aSBenoit Parrot { 0x5032, 0xee }, 310c4c0283aSBenoit Parrot { 0x5033, 0xf6 }, 311c4c0283aSBenoit Parrot { 0x5034, 0x11 }, 312c4c0283aSBenoit Parrot { 0x5070, 0x1c }, 313c4c0283aSBenoit Parrot { 0x5071, 0x5b }, 314c4c0283aSBenoit Parrot { 0x5072, 0x05 }, 315c4c0283aSBenoit Parrot { 0x5073, 0x20 }, 316c4c0283aSBenoit Parrot { 0x5074, 0x94 }, 317c4c0283aSBenoit Parrot { 0x5075, 0xb4 }, 318c4c0283aSBenoit Parrot { 0x5076, 0xb4 }, 319c4c0283aSBenoit Parrot { 0x5077, 0xaf }, 320c4c0283aSBenoit Parrot { 0x5078, 0x05 }, 321c4c0283aSBenoit Parrot { REG_CMX_SIGN, 0x98 }, 322c4c0283aSBenoit Parrot { REG_CMX_MISC_CTRL, 0x21 }, 323c4c0283aSBenoit Parrot { REG_AWB_CTRL00, 0x6a }, 324c4c0283aSBenoit Parrot { REG_AWB_CTRL01, 0x11 }, 325c4c0283aSBenoit Parrot { REG_AWB_CTRL02, 0x92 }, 326c4c0283aSBenoit Parrot { REG_AWB_CTRL03, 0x21 }, 327c4c0283aSBenoit Parrot { REG_AWB_CTRL04, 0xe1 }, 328c4c0283aSBenoit Parrot { REG_AWB_LOCAL_LIMIT, 0x01 }, 329c4c0283aSBenoit Parrot { 0x503c, 0x05 }, 330c4c0283aSBenoit Parrot { 0x503d, 0x08 }, 331c4c0283aSBenoit Parrot { 0x503e, 0x08 }, 332c4c0283aSBenoit Parrot { 0x503f, 0x64 }, 333c4c0283aSBenoit Parrot { 0x5040, 0x58 }, 334c4c0283aSBenoit Parrot { 0x5041, 0x2a }, 335c4c0283aSBenoit Parrot { 0x5042, 0xc5 }, 336c4c0283aSBenoit Parrot { 0x5043, 0x2e }, 337c4c0283aSBenoit Parrot { 0x5044, 0x3a }, 338c4c0283aSBenoit Parrot { 0x5045, 0x3c }, 339c4c0283aSBenoit Parrot { 0x5046, 0x44 }, 340c4c0283aSBenoit Parrot { 0x5047, 0xf8 }, 341c4c0283aSBenoit Parrot { 0x5048, 0x08 }, 342c4c0283aSBenoit Parrot { REG_AWB_CTRL12, 0x70 }, 343c4c0283aSBenoit Parrot { REG_AWB_CTRL13, 0xf0 }, 344c4c0283aSBenoit Parrot { REG_AWB_CTRL14, 0xf0 }, 345c4c0283aSBenoit Parrot { REG_LENC_RED_X0_H, 0x03 }, 346c4c0283aSBenoit Parrot { REG_LENC_RED_X0_L, 0x20 }, 347c4c0283aSBenoit Parrot { REG_LENC_RED_Y0_H, 0x02 }, 348c4c0283aSBenoit Parrot { REG_LENC_RED_Y0_L, 0x5c }, 349c4c0283aSBenoit Parrot { REG_LENC_RED_A1, 0x48 }, 350c4c0283aSBenoit Parrot { REG_LENC_RED_B1, 0x00 }, 351c4c0283aSBenoit Parrot { REG_LENC_RED_A2_B2, 0x66 }, 352c4c0283aSBenoit Parrot { REG_LENC_GREEN_X0_H, 0x03 }, 353c4c0283aSBenoit Parrot { REG_LENC_GREEN_X0_L, 0x30 }, 354c4c0283aSBenoit Parrot { REG_LENC_GREEN_Y0_H, 0x02 }, 355c4c0283aSBenoit Parrot { REG_LENC_GREEN_Y0_L, 0x7c }, 356c4c0283aSBenoit Parrot { REG_LENC_GREEN_A1, 0x40 }, 357c4c0283aSBenoit Parrot { REG_LENC_GREEN_B1, 0x00 }, 358c4c0283aSBenoit Parrot { REG_LENC_GREEN_A2_B2, 0x66 }, 359c4c0283aSBenoit Parrot { REG_LENC_BLUE_X0_H, 0x03 }, 360c4c0283aSBenoit Parrot { REG_LENC_BLUE_X0_L, 0x10 }, 361c4c0283aSBenoit Parrot { REG_LENC_BLUE_Y0_H, 0x02 }, 362c4c0283aSBenoit Parrot { REG_LENC_BLUE_Y0_L, 0x7c }, 363c4c0283aSBenoit Parrot { REG_LENC_BLUE_A1, 0x3a }, 364c4c0283aSBenoit Parrot { REG_LENC_BLUE_B1, 0x00 }, 365c4c0283aSBenoit Parrot { REG_LENC_BLUE_A2_B2, 0x66 }, 366c4c0283aSBenoit Parrot { REG_CIP_CTRL00, 0x44 }, 367c4c0283aSBenoit Parrot { REG_SHARPENMT_THRESH1, 0x08 }, 368c4c0283aSBenoit Parrot { REG_SHARPENMT_THRESH2, 0x10 }, 369c4c0283aSBenoit Parrot { REG_SHARPENMT_OFFSET1, 0x12 }, 370c4c0283aSBenoit Parrot { REG_SHARPENMT_OFFSET2, 0x02 }, 371c4c0283aSBenoit Parrot { REG_SHARPEN_THRESH1, 0x08 }, 372c4c0283aSBenoit Parrot { REG_SHARPEN_THRESH2, 0x10 }, 373c4c0283aSBenoit Parrot { REG_CIP_CTRL01, 0xa6 }, 374c4c0283aSBenoit Parrot { REG_DENOISE_THRESH1, 0x08 }, 375c4c0283aSBenoit Parrot { REG_DENOISE_THRESH2, 0x10 }, 376c4c0283aSBenoit Parrot { REG_DENOISE_OFFSET1, 0x04 }, 377c4c0283aSBenoit Parrot { REG_DENOISE_OFFSET2, 0x12 }, 378c4c0283aSBenoit Parrot { 0x507e, 0x40 }, 379c4c0283aSBenoit Parrot { 0x507f, 0x20 }, 380c4c0283aSBenoit Parrot { 0x507b, 0x02 }, 381c4c0283aSBenoit Parrot { REG_CMX_MISC_CTRL, 0x01 }, 382c4c0283aSBenoit Parrot { 0x5084, 0x0c }, 383c4c0283aSBenoit Parrot { 0x5085, 0x3e }, 384c4c0283aSBenoit Parrot { 0x5005, 0x80 }, 385c4c0283aSBenoit Parrot { 0x3a0f, 0x30 }, 386c4c0283aSBenoit Parrot { 0x3a10, 0x28 }, 387c4c0283aSBenoit Parrot { 0x3a1b, 0x32 }, 388c4c0283aSBenoit Parrot { 0x3a1e, 0x26 }, 389c4c0283aSBenoit Parrot { 0x3a11, 0x60 }, 390c4c0283aSBenoit Parrot { 0x3a1f, 0x14 }, 391c4c0283aSBenoit Parrot { 0x5060, 0x69 }, 392c4c0283aSBenoit Parrot { 0x5061, 0x7d }, 393c4c0283aSBenoit Parrot { 0x5062, 0x7d }, 394c4c0283aSBenoit Parrot { 0x5063, 0x69 }, 395c4c0283aSBenoit Parrot { REG_NULL, 0x00 }, 396c4c0283aSBenoit Parrot }; 397c4c0283aSBenoit Parrot 398c4c0283aSBenoit Parrot /* 1280X720 720p */ 399c4c0283aSBenoit Parrot static struct sensor_register ov2659_720p[] = { 400c4c0283aSBenoit Parrot { REG_TIMING_HS_H, 0x00 }, 401c4c0283aSBenoit Parrot { REG_TIMING_HS_L, 0xa0 }, 402c4c0283aSBenoit Parrot { REG_TIMING_VS_H, 0x00 }, 403c4c0283aSBenoit Parrot { REG_TIMING_VS_L, 0xf0 }, 404c4c0283aSBenoit Parrot { REG_TIMING_HW_H, 0x05 }, 405c4c0283aSBenoit Parrot { REG_TIMING_HW_L, 0xbf }, 406c4c0283aSBenoit Parrot { REG_TIMING_VH_H, 0x03 }, 407c4c0283aSBenoit Parrot { REG_TIMING_VH_L, 0xcb }, 408c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_H, 0x05 }, 409c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_L, 0x00 }, 410c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_H, 0x02 }, 411c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_L, 0xd0 }, 412c4c0283aSBenoit Parrot { REG_TIMING_HTS_H, 0x06 }, 413c4c0283aSBenoit Parrot { REG_TIMING_HTS_L, 0x4c }, 414c4c0283aSBenoit Parrot { REG_TIMING_VTS_H, 0x02 }, 415c4c0283aSBenoit Parrot { REG_TIMING_VTS_L, 0xe8 }, 416c4c0283aSBenoit Parrot { REG_TIMING_HOFFS_L, 0x10 }, 417c4c0283aSBenoit Parrot { REG_TIMING_VOFFS_L, 0x06 }, 418c4c0283aSBenoit Parrot { REG_TIMING_XINC, 0x11 }, 419c4c0283aSBenoit Parrot { REG_TIMING_YINC, 0x11 }, 420c4c0283aSBenoit Parrot { REG_TIMING_VERT_FORMAT, 0x80 }, 421c4c0283aSBenoit Parrot { REG_TIMING_HORIZ_FORMAT, 0x00 }, 422c4c0283aSBenoit Parrot { 0x3a03, 0xe8 }, 423c4c0283aSBenoit Parrot { 0x3a09, 0x6f }, 424c4c0283aSBenoit Parrot { 0x3a0b, 0x5d }, 425c4c0283aSBenoit Parrot { 0x3a15, 0x9a }, 426c4c0283aSBenoit Parrot { REG_NULL, 0x00 }, 427c4c0283aSBenoit Parrot }; 428c4c0283aSBenoit Parrot 429c4c0283aSBenoit Parrot /* 1600X1200 UXGA */ 430c4c0283aSBenoit Parrot static struct sensor_register ov2659_uxga[] = { 431c4c0283aSBenoit Parrot { REG_TIMING_HS_H, 0x00 }, 432c4c0283aSBenoit Parrot { REG_TIMING_HS_L, 0x00 }, 433c4c0283aSBenoit Parrot { REG_TIMING_VS_H, 0x00 }, 434c4c0283aSBenoit Parrot { REG_TIMING_VS_L, 0x00 }, 435c4c0283aSBenoit Parrot { REG_TIMING_HW_H, 0x06 }, 436c4c0283aSBenoit Parrot { REG_TIMING_HW_L, 0x5f }, 437c4c0283aSBenoit Parrot { REG_TIMING_VH_H, 0x04 }, 438c4c0283aSBenoit Parrot { REG_TIMING_VH_L, 0xbb }, 439c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_H, 0x06 }, 440c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_L, 0x40 }, 441c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_H, 0x04 }, 442c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_L, 0xb0 }, 443c4c0283aSBenoit Parrot { REG_TIMING_HTS_H, 0x07 }, 444c4c0283aSBenoit Parrot { REG_TIMING_HTS_L, 0x9f }, 445c4c0283aSBenoit Parrot { REG_TIMING_VTS_H, 0x04 }, 446c4c0283aSBenoit Parrot { REG_TIMING_VTS_L, 0xd0 }, 447c4c0283aSBenoit Parrot { REG_TIMING_HOFFS_L, 0x10 }, 448c4c0283aSBenoit Parrot { REG_TIMING_VOFFS_L, 0x06 }, 449c4c0283aSBenoit Parrot { REG_TIMING_XINC, 0x11 }, 450c4c0283aSBenoit Parrot { REG_TIMING_YINC, 0x11 }, 451c4c0283aSBenoit Parrot { 0x3a02, 0x04 }, 452c4c0283aSBenoit Parrot { 0x3a03, 0xd0 }, 453c4c0283aSBenoit Parrot { 0x3a08, 0x00 }, 454c4c0283aSBenoit Parrot { 0x3a09, 0xb8 }, 455c4c0283aSBenoit Parrot { 0x3a0a, 0x00 }, 456c4c0283aSBenoit Parrot { 0x3a0b, 0x9a }, 457c4c0283aSBenoit Parrot { 0x3a0d, 0x08 }, 458c4c0283aSBenoit Parrot { 0x3a0e, 0x06 }, 459c4c0283aSBenoit Parrot { 0x3a14, 0x04 }, 460c4c0283aSBenoit Parrot { 0x3a15, 0x50 }, 461c4c0283aSBenoit Parrot { 0x3623, 0x00 }, 462c4c0283aSBenoit Parrot { 0x3634, 0x44 }, 463c4c0283aSBenoit Parrot { 0x3701, 0x44 }, 464c4c0283aSBenoit Parrot { 0x3702, 0x30 }, 465c4c0283aSBenoit Parrot { 0x3703, 0x48 }, 466c4c0283aSBenoit Parrot { 0x3704, 0x48 }, 467c4c0283aSBenoit Parrot { 0x3705, 0x18 }, 468c4c0283aSBenoit Parrot { REG_TIMING_VERT_FORMAT, 0x80 }, 469c4c0283aSBenoit Parrot { REG_TIMING_HORIZ_FORMAT, 0x00 }, 470c4c0283aSBenoit Parrot { 0x370a, 0x12 }, 471c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_H, 0x00 }, 472c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_L, 0x80 }, 473c4c0283aSBenoit Parrot { REG_ISP_CTRL02, 0x00 }, 474c4c0283aSBenoit Parrot { REG_NULL, 0x00 }, 475c4c0283aSBenoit Parrot }; 476c4c0283aSBenoit Parrot 477c4c0283aSBenoit Parrot /* 1280X1024 SXGA */ 478c4c0283aSBenoit Parrot static struct sensor_register ov2659_sxga[] = { 479c4c0283aSBenoit Parrot { REG_TIMING_HS_H, 0x00 }, 480c4c0283aSBenoit Parrot { REG_TIMING_HS_L, 0x00 }, 481c4c0283aSBenoit Parrot { REG_TIMING_VS_H, 0x00 }, 482c4c0283aSBenoit Parrot { REG_TIMING_VS_L, 0x00 }, 483c4c0283aSBenoit Parrot { REG_TIMING_HW_H, 0x06 }, 484c4c0283aSBenoit Parrot { REG_TIMING_HW_L, 0x5f }, 485c4c0283aSBenoit Parrot { REG_TIMING_VH_H, 0x04 }, 486c4c0283aSBenoit Parrot { REG_TIMING_VH_L, 0xb7 }, 487c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_H, 0x05 }, 488c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_L, 0x00 }, 489c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_H, 0x04 }, 490c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_L, 0x00 }, 491c4c0283aSBenoit Parrot { REG_TIMING_HTS_H, 0x07 }, 492c4c0283aSBenoit Parrot { REG_TIMING_HTS_L, 0x9c }, 493c4c0283aSBenoit Parrot { REG_TIMING_VTS_H, 0x04 }, 494c4c0283aSBenoit Parrot { REG_TIMING_VTS_L, 0xd0 }, 495c4c0283aSBenoit Parrot { REG_TIMING_HOFFS_L, 0x10 }, 496c4c0283aSBenoit Parrot { REG_TIMING_VOFFS_L, 0x06 }, 497c4c0283aSBenoit Parrot { REG_TIMING_XINC, 0x11 }, 498c4c0283aSBenoit Parrot { REG_TIMING_YINC, 0x11 }, 499c4c0283aSBenoit Parrot { 0x3a02, 0x02 }, 500c4c0283aSBenoit Parrot { 0x3a03, 0x68 }, 501c4c0283aSBenoit Parrot { 0x3a08, 0x00 }, 502c4c0283aSBenoit Parrot { 0x3a09, 0x5c }, 503c4c0283aSBenoit Parrot { 0x3a0a, 0x00 }, 504c4c0283aSBenoit Parrot { 0x3a0b, 0x4d }, 505c4c0283aSBenoit Parrot { 0x3a0d, 0x08 }, 506c4c0283aSBenoit Parrot { 0x3a0e, 0x06 }, 507c4c0283aSBenoit Parrot { 0x3a14, 0x02 }, 508c4c0283aSBenoit Parrot { 0x3a15, 0x28 }, 509c4c0283aSBenoit Parrot { 0x3623, 0x00 }, 510c4c0283aSBenoit Parrot { 0x3634, 0x76 }, 511c4c0283aSBenoit Parrot { 0x3701, 0x44 }, 512c4c0283aSBenoit Parrot { 0x3702, 0x18 }, 513c4c0283aSBenoit Parrot { 0x3703, 0x24 }, 514c4c0283aSBenoit Parrot { 0x3704, 0x24 }, 515c4c0283aSBenoit Parrot { 0x3705, 0x0c }, 516c4c0283aSBenoit Parrot { REG_TIMING_VERT_FORMAT, 0x80 }, 517c4c0283aSBenoit Parrot { REG_TIMING_HORIZ_FORMAT, 0x00 }, 518c4c0283aSBenoit Parrot { 0x370a, 0x52 }, 519c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_H, 0x00 }, 520c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_L, 0x80 }, 521c4c0283aSBenoit Parrot { REG_ISP_CTRL02, 0x00 }, 522c4c0283aSBenoit Parrot { REG_NULL, 0x00 }, 523c4c0283aSBenoit Parrot }; 524c4c0283aSBenoit Parrot 525c4c0283aSBenoit Parrot /* 1024X768 SXGA */ 526c4c0283aSBenoit Parrot static struct sensor_register ov2659_xga[] = { 527c4c0283aSBenoit Parrot { REG_TIMING_HS_H, 0x00 }, 528c4c0283aSBenoit Parrot { REG_TIMING_HS_L, 0x00 }, 529c4c0283aSBenoit Parrot { REG_TIMING_VS_H, 0x00 }, 530c4c0283aSBenoit Parrot { REG_TIMING_VS_L, 0x00 }, 531c4c0283aSBenoit Parrot { REG_TIMING_HW_H, 0x06 }, 532c4c0283aSBenoit Parrot { REG_TIMING_HW_L, 0x5f }, 533c4c0283aSBenoit Parrot { REG_TIMING_VH_H, 0x04 }, 534c4c0283aSBenoit Parrot { REG_TIMING_VH_L, 0xb7 }, 535c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_H, 0x04 }, 536c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_L, 0x00 }, 537c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_H, 0x03 }, 538c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_L, 0x00 }, 539c4c0283aSBenoit Parrot { REG_TIMING_HTS_H, 0x07 }, 540c4c0283aSBenoit Parrot { REG_TIMING_HTS_L, 0x9c }, 541c4c0283aSBenoit Parrot { REG_TIMING_VTS_H, 0x04 }, 542c4c0283aSBenoit Parrot { REG_TIMING_VTS_L, 0xd0 }, 543c4c0283aSBenoit Parrot { REG_TIMING_HOFFS_L, 0x10 }, 544c4c0283aSBenoit Parrot { REG_TIMING_VOFFS_L, 0x06 }, 545c4c0283aSBenoit Parrot { REG_TIMING_XINC, 0x11 }, 546c4c0283aSBenoit Parrot { REG_TIMING_YINC, 0x11 }, 547c4c0283aSBenoit Parrot { 0x3a02, 0x02 }, 548c4c0283aSBenoit Parrot { 0x3a03, 0x68 }, 549c4c0283aSBenoit Parrot { 0x3a08, 0x00 }, 550c4c0283aSBenoit Parrot { 0x3a09, 0x5c }, 551c4c0283aSBenoit Parrot { 0x3a0a, 0x00 }, 552c4c0283aSBenoit Parrot { 0x3a0b, 0x4d }, 553c4c0283aSBenoit Parrot { 0x3a0d, 0x08 }, 554c4c0283aSBenoit Parrot { 0x3a0e, 0x06 }, 555c4c0283aSBenoit Parrot { 0x3a14, 0x02 }, 556c4c0283aSBenoit Parrot { 0x3a15, 0x28 }, 557c4c0283aSBenoit Parrot { 0x3623, 0x00 }, 558c4c0283aSBenoit Parrot { 0x3634, 0x76 }, 559c4c0283aSBenoit Parrot { 0x3701, 0x44 }, 560c4c0283aSBenoit Parrot { 0x3702, 0x18 }, 561c4c0283aSBenoit Parrot { 0x3703, 0x24 }, 562c4c0283aSBenoit Parrot { 0x3704, 0x24 }, 563c4c0283aSBenoit Parrot { 0x3705, 0x0c }, 564c4c0283aSBenoit Parrot { REG_TIMING_VERT_FORMAT, 0x80 }, 565c4c0283aSBenoit Parrot { REG_TIMING_HORIZ_FORMAT, 0x00 }, 566c4c0283aSBenoit Parrot { 0x370a, 0x52 }, 567c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_H, 0x00 }, 568c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_L, 0x80 }, 569c4c0283aSBenoit Parrot { REG_ISP_CTRL02, 0x00 }, 570c4c0283aSBenoit Parrot { REG_NULL, 0x00 }, 571c4c0283aSBenoit Parrot }; 572c4c0283aSBenoit Parrot 573c4c0283aSBenoit Parrot /* 800X600 SVGA */ 574c4c0283aSBenoit Parrot static struct sensor_register ov2659_svga[] = { 575c4c0283aSBenoit Parrot { REG_TIMING_HS_H, 0x00 }, 576c4c0283aSBenoit Parrot { REG_TIMING_HS_L, 0x00 }, 577c4c0283aSBenoit Parrot { REG_TIMING_VS_H, 0x00 }, 578c4c0283aSBenoit Parrot { REG_TIMING_VS_L, 0x00 }, 579c4c0283aSBenoit Parrot { REG_TIMING_HW_H, 0x06 }, 580c4c0283aSBenoit Parrot { REG_TIMING_HW_L, 0x5f }, 581c4c0283aSBenoit Parrot { REG_TIMING_VH_H, 0x04 }, 582c4c0283aSBenoit Parrot { REG_TIMING_VH_L, 0xb7 }, 583c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_H, 0x03 }, 584c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_L, 0x20 }, 585c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_H, 0x02 }, 586c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_L, 0x58 }, 587c4c0283aSBenoit Parrot { REG_TIMING_HTS_H, 0x05 }, 588c4c0283aSBenoit Parrot { REG_TIMING_HTS_L, 0x14 }, 589c4c0283aSBenoit Parrot { REG_TIMING_VTS_H, 0x02 }, 590c4c0283aSBenoit Parrot { REG_TIMING_VTS_L, 0x68 }, 591c4c0283aSBenoit Parrot { REG_TIMING_HOFFS_L, 0x08 }, 592c4c0283aSBenoit Parrot { REG_TIMING_VOFFS_L, 0x02 }, 593c4c0283aSBenoit Parrot { REG_TIMING_XINC, 0x31 }, 594c4c0283aSBenoit Parrot { REG_TIMING_YINC, 0x31 }, 595c4c0283aSBenoit Parrot { 0x3a02, 0x02 }, 596c4c0283aSBenoit Parrot { 0x3a03, 0x68 }, 597c4c0283aSBenoit Parrot { 0x3a08, 0x00 }, 598c4c0283aSBenoit Parrot { 0x3a09, 0x5c }, 599c4c0283aSBenoit Parrot { 0x3a0a, 0x00 }, 600c4c0283aSBenoit Parrot { 0x3a0b, 0x4d }, 601c4c0283aSBenoit Parrot { 0x3a0d, 0x08 }, 602c4c0283aSBenoit Parrot { 0x3a0e, 0x06 }, 603c4c0283aSBenoit Parrot { 0x3a14, 0x02 }, 604c4c0283aSBenoit Parrot { 0x3a15, 0x28 }, 605c4c0283aSBenoit Parrot { 0x3623, 0x00 }, 606c4c0283aSBenoit Parrot { 0x3634, 0x76 }, 607c4c0283aSBenoit Parrot { 0x3701, 0x44 }, 608c4c0283aSBenoit Parrot { 0x3702, 0x18 }, 609c4c0283aSBenoit Parrot { 0x3703, 0x24 }, 610c4c0283aSBenoit Parrot { 0x3704, 0x24 }, 611c4c0283aSBenoit Parrot { 0x3705, 0x0c }, 612c4c0283aSBenoit Parrot { REG_TIMING_VERT_FORMAT, 0x81 }, 613c4c0283aSBenoit Parrot { REG_TIMING_HORIZ_FORMAT, 0x01 }, 614c4c0283aSBenoit Parrot { 0x370a, 0x52 }, 615c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_H, 0x00 }, 616c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_L, 0x80 }, 617c4c0283aSBenoit Parrot { REG_ISP_CTRL02, 0x00 }, 618c4c0283aSBenoit Parrot { REG_NULL, 0x00 }, 619c4c0283aSBenoit Parrot }; 620c4c0283aSBenoit Parrot 621c4c0283aSBenoit Parrot /* 640X480 VGA */ 622c4c0283aSBenoit Parrot static struct sensor_register ov2659_vga[] = { 623c4c0283aSBenoit Parrot { REG_TIMING_HS_H, 0x00 }, 624c4c0283aSBenoit Parrot { REG_TIMING_HS_L, 0x00 }, 625c4c0283aSBenoit Parrot { REG_TIMING_VS_H, 0x00 }, 626c4c0283aSBenoit Parrot { REG_TIMING_VS_L, 0x00 }, 627c4c0283aSBenoit Parrot { REG_TIMING_HW_H, 0x06 }, 628c4c0283aSBenoit Parrot { REG_TIMING_HW_L, 0x5f }, 629c4c0283aSBenoit Parrot { REG_TIMING_VH_H, 0x04 }, 630c4c0283aSBenoit Parrot { REG_TIMING_VH_L, 0xb7 }, 631c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_H, 0x02 }, 632c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_L, 0x80 }, 633c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_H, 0x01 }, 634c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_L, 0xe0 }, 635c4c0283aSBenoit Parrot { REG_TIMING_HTS_H, 0x05 }, 636c4c0283aSBenoit Parrot { REG_TIMING_HTS_L, 0x14 }, 637c4c0283aSBenoit Parrot { REG_TIMING_VTS_H, 0x02 }, 638c4c0283aSBenoit Parrot { REG_TIMING_VTS_L, 0x68 }, 639c4c0283aSBenoit Parrot { REG_TIMING_HOFFS_L, 0x08 }, 640c4c0283aSBenoit Parrot { REG_TIMING_VOFFS_L, 0x02 }, 641c4c0283aSBenoit Parrot { REG_TIMING_XINC, 0x31 }, 642c4c0283aSBenoit Parrot { REG_TIMING_YINC, 0x31 }, 643c4c0283aSBenoit Parrot { 0x3a02, 0x02 }, 644c4c0283aSBenoit Parrot { 0x3a03, 0x68 }, 645c4c0283aSBenoit Parrot { 0x3a08, 0x00 }, 646c4c0283aSBenoit Parrot { 0x3a09, 0x5c }, 647c4c0283aSBenoit Parrot { 0x3a0a, 0x00 }, 648c4c0283aSBenoit Parrot { 0x3a0b, 0x4d }, 649c4c0283aSBenoit Parrot { 0x3a0d, 0x08 }, 650c4c0283aSBenoit Parrot { 0x3a0e, 0x06 }, 651c4c0283aSBenoit Parrot { 0x3a14, 0x02 }, 652c4c0283aSBenoit Parrot { 0x3a15, 0x28 }, 653c4c0283aSBenoit Parrot { 0x3623, 0x00 }, 654c4c0283aSBenoit Parrot { 0x3634, 0x76 }, 655c4c0283aSBenoit Parrot { 0x3701, 0x44 }, 656c4c0283aSBenoit Parrot { 0x3702, 0x18 }, 657c4c0283aSBenoit Parrot { 0x3703, 0x24 }, 658c4c0283aSBenoit Parrot { 0x3704, 0x24 }, 659c4c0283aSBenoit Parrot { 0x3705, 0x0c }, 660c4c0283aSBenoit Parrot { REG_TIMING_VERT_FORMAT, 0x81 }, 661c4c0283aSBenoit Parrot { REG_TIMING_HORIZ_FORMAT, 0x01 }, 662c4c0283aSBenoit Parrot { 0x370a, 0x52 }, 663c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_H, 0x00 }, 664c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_L, 0x80 }, 665c4c0283aSBenoit Parrot { REG_ISP_CTRL02, 0x10 }, 666c4c0283aSBenoit Parrot { REG_NULL, 0x00 }, 667c4c0283aSBenoit Parrot }; 668c4c0283aSBenoit Parrot 669c4c0283aSBenoit Parrot /* 320X240 QVGA */ 670c4c0283aSBenoit Parrot static struct sensor_register ov2659_qvga[] = { 671c4c0283aSBenoit Parrot { REG_TIMING_HS_H, 0x00 }, 672c4c0283aSBenoit Parrot { REG_TIMING_HS_L, 0x00 }, 673c4c0283aSBenoit Parrot { REG_TIMING_VS_H, 0x00 }, 674c4c0283aSBenoit Parrot { REG_TIMING_VS_L, 0x00 }, 675c4c0283aSBenoit Parrot { REG_TIMING_HW_H, 0x06 }, 676c4c0283aSBenoit Parrot { REG_TIMING_HW_L, 0x5f }, 677c4c0283aSBenoit Parrot { REG_TIMING_VH_H, 0x04 }, 678c4c0283aSBenoit Parrot { REG_TIMING_VH_L, 0xb7 }, 679c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_H, 0x01 }, 680c4c0283aSBenoit Parrot { REG_TIMING_DVPHO_L, 0x40 }, 681c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_H, 0x00 }, 682c4c0283aSBenoit Parrot { REG_TIMING_DVPVO_L, 0xf0 }, 683c4c0283aSBenoit Parrot { REG_TIMING_HTS_H, 0x05 }, 684c4c0283aSBenoit Parrot { REG_TIMING_HTS_L, 0x14 }, 685c4c0283aSBenoit Parrot { REG_TIMING_VTS_H, 0x02 }, 686c4c0283aSBenoit Parrot { REG_TIMING_VTS_L, 0x68 }, 687c4c0283aSBenoit Parrot { REG_TIMING_HOFFS_L, 0x08 }, 688c4c0283aSBenoit Parrot { REG_TIMING_VOFFS_L, 0x02 }, 689c4c0283aSBenoit Parrot { REG_TIMING_XINC, 0x31 }, 690c4c0283aSBenoit Parrot { REG_TIMING_YINC, 0x31 }, 691c4c0283aSBenoit Parrot { 0x3a02, 0x02 }, 692c4c0283aSBenoit Parrot { 0x3a03, 0x68 }, 693c4c0283aSBenoit Parrot { 0x3a08, 0x00 }, 694c4c0283aSBenoit Parrot { 0x3a09, 0x5c }, 695c4c0283aSBenoit Parrot { 0x3a0a, 0x00 }, 696c4c0283aSBenoit Parrot { 0x3a0b, 0x4d }, 697c4c0283aSBenoit Parrot { 0x3a0d, 0x08 }, 698c4c0283aSBenoit Parrot { 0x3a0e, 0x06 }, 699c4c0283aSBenoit Parrot { 0x3a14, 0x02 }, 700c4c0283aSBenoit Parrot { 0x3a15, 0x28 }, 701c4c0283aSBenoit Parrot { 0x3623, 0x00 }, 702c4c0283aSBenoit Parrot { 0x3634, 0x76 }, 703c4c0283aSBenoit Parrot { 0x3701, 0x44 }, 704c4c0283aSBenoit Parrot { 0x3702, 0x18 }, 705c4c0283aSBenoit Parrot { 0x3703, 0x24 }, 706c4c0283aSBenoit Parrot { 0x3704, 0x24 }, 707c4c0283aSBenoit Parrot { 0x3705, 0x0c }, 708c4c0283aSBenoit Parrot { REG_TIMING_VERT_FORMAT, 0x81 }, 709c4c0283aSBenoit Parrot { REG_TIMING_HORIZ_FORMAT, 0x01 }, 710c4c0283aSBenoit Parrot { 0x370a, 0x52 }, 711c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_H, 0x00 }, 712c4c0283aSBenoit Parrot { REG_VFIFO_READ_START_L, 0x80 }, 713c4c0283aSBenoit Parrot { REG_ISP_CTRL02, 0x10 }, 714c4c0283aSBenoit Parrot { REG_NULL, 0x00 }, 715c4c0283aSBenoit Parrot }; 716c4c0283aSBenoit Parrot 717c4c0283aSBenoit Parrot static const struct pll_ctrl_reg ctrl3[] = { 718c4c0283aSBenoit Parrot { 1, 0x00 }, 719c4c0283aSBenoit Parrot { 2, 0x02 }, 720c4c0283aSBenoit Parrot { 3, 0x03 }, 721c4c0283aSBenoit Parrot { 4, 0x06 }, 722c4c0283aSBenoit Parrot { 6, 0x0d }, 723c4c0283aSBenoit Parrot { 8, 0x0e }, 724c4c0283aSBenoit Parrot { 12, 0x0f }, 725c4c0283aSBenoit Parrot { 16, 0x12 }, 726c4c0283aSBenoit Parrot { 24, 0x13 }, 727c4c0283aSBenoit Parrot { 32, 0x16 }, 728c4c0283aSBenoit Parrot { 48, 0x1b }, 729c4c0283aSBenoit Parrot { 64, 0x1e }, 730c4c0283aSBenoit Parrot { 96, 0x1f }, 731c4c0283aSBenoit Parrot { 0, 0x00 }, 732c4c0283aSBenoit Parrot }; 733c4c0283aSBenoit Parrot 734c4c0283aSBenoit Parrot static const struct pll_ctrl_reg ctrl1[] = { 735c4c0283aSBenoit Parrot { 2, 0x10 }, 736c4c0283aSBenoit Parrot { 4, 0x20 }, 737c4c0283aSBenoit Parrot { 6, 0x30 }, 738c4c0283aSBenoit Parrot { 8, 0x40 }, 739c4c0283aSBenoit Parrot { 10, 0x50 }, 740c4c0283aSBenoit Parrot { 12, 0x60 }, 741c4c0283aSBenoit Parrot { 14, 0x70 }, 742c4c0283aSBenoit Parrot { 16, 0x80 }, 743c4c0283aSBenoit Parrot { 18, 0x90 }, 744c4c0283aSBenoit Parrot { 20, 0xa0 }, 745c4c0283aSBenoit Parrot { 22, 0xb0 }, 746c4c0283aSBenoit Parrot { 24, 0xc0 }, 747c4c0283aSBenoit Parrot { 26, 0xd0 }, 748c4c0283aSBenoit Parrot { 28, 0xe0 }, 749c4c0283aSBenoit Parrot { 30, 0xf0 }, 750c4c0283aSBenoit Parrot { 0, 0x00 }, 751c4c0283aSBenoit Parrot }; 752c4c0283aSBenoit Parrot 753c4c0283aSBenoit Parrot static const struct ov2659_framesize ov2659_framesizes[] = { 754c4c0283aSBenoit Parrot { /* QVGA */ 755c4c0283aSBenoit Parrot .width = 320, 756c4c0283aSBenoit Parrot .height = 240, 757c4c0283aSBenoit Parrot .regs = ov2659_qvga, 758c4c0283aSBenoit Parrot .max_exp_lines = 248, 759c4c0283aSBenoit Parrot }, { /* VGA */ 760c4c0283aSBenoit Parrot .width = 640, 761c4c0283aSBenoit Parrot .height = 480, 762c4c0283aSBenoit Parrot .regs = ov2659_vga, 763c4c0283aSBenoit Parrot .max_exp_lines = 498, 764c4c0283aSBenoit Parrot }, { /* SVGA */ 765c4c0283aSBenoit Parrot .width = 800, 766c4c0283aSBenoit Parrot .height = 600, 767c4c0283aSBenoit Parrot .regs = ov2659_svga, 768c4c0283aSBenoit Parrot .max_exp_lines = 498, 769c4c0283aSBenoit Parrot }, { /* XGA */ 770c4c0283aSBenoit Parrot .width = 1024, 771c4c0283aSBenoit Parrot .height = 768, 772c4c0283aSBenoit Parrot .regs = ov2659_xga, 773c4c0283aSBenoit Parrot .max_exp_lines = 498, 774c4c0283aSBenoit Parrot }, { /* 720P */ 775c4c0283aSBenoit Parrot .width = 1280, 776c4c0283aSBenoit Parrot .height = 720, 777c4c0283aSBenoit Parrot .regs = ov2659_720p, 778c4c0283aSBenoit Parrot .max_exp_lines = 498, 779c4c0283aSBenoit Parrot }, { /* SXGA */ 780c4c0283aSBenoit Parrot .width = 1280, 781c4c0283aSBenoit Parrot .height = 1024, 782c4c0283aSBenoit Parrot .regs = ov2659_sxga, 783c4c0283aSBenoit Parrot .max_exp_lines = 1048, 784c4c0283aSBenoit Parrot }, { /* UXGA */ 785c4c0283aSBenoit Parrot .width = 1600, 786c4c0283aSBenoit Parrot .height = 1200, 787c4c0283aSBenoit Parrot .regs = ov2659_uxga, 788c4c0283aSBenoit Parrot .max_exp_lines = 498, 789c4c0283aSBenoit Parrot }, 790c4c0283aSBenoit Parrot }; 791c4c0283aSBenoit Parrot 792c4c0283aSBenoit Parrot /* YUV422 YUYV*/ 793c4c0283aSBenoit Parrot static struct sensor_register ov2659_format_yuyv[] = { 794c4c0283aSBenoit Parrot { REG_FORMAT_CTRL00, 0x30 }, 795c4c0283aSBenoit Parrot { REG_NULL, 0x0 }, 796c4c0283aSBenoit Parrot }; 797c4c0283aSBenoit Parrot 798c4c0283aSBenoit Parrot /* YUV422 UYVY */ 799c4c0283aSBenoit Parrot static struct sensor_register ov2659_format_uyvy[] = { 800c4c0283aSBenoit Parrot { REG_FORMAT_CTRL00, 0x32 }, 801c4c0283aSBenoit Parrot { REG_NULL, 0x0 }, 802c4c0283aSBenoit Parrot }; 803c4c0283aSBenoit Parrot 804c4c0283aSBenoit Parrot /* Raw Bayer BGGR */ 805c4c0283aSBenoit Parrot static struct sensor_register ov2659_format_bggr[] = { 806c4c0283aSBenoit Parrot { REG_FORMAT_CTRL00, 0x00 }, 807c4c0283aSBenoit Parrot { REG_NULL, 0x0 }, 808c4c0283aSBenoit Parrot }; 809c4c0283aSBenoit Parrot 810c4c0283aSBenoit Parrot /* RGB565 */ 811c4c0283aSBenoit Parrot static struct sensor_register ov2659_format_rgb565[] = { 812c4c0283aSBenoit Parrot { REG_FORMAT_CTRL00, 0x60 }, 813c4c0283aSBenoit Parrot { REG_NULL, 0x0 }, 814c4c0283aSBenoit Parrot }; 815c4c0283aSBenoit Parrot 816c4c0283aSBenoit Parrot static const struct ov2659_pixfmt ov2659_formats[] = { 817c4c0283aSBenoit Parrot { 818c4c0283aSBenoit Parrot .code = MEDIA_BUS_FMT_YUYV8_2X8, 819c4c0283aSBenoit Parrot .format_ctrl_regs = ov2659_format_yuyv, 820c4c0283aSBenoit Parrot }, { 821c4c0283aSBenoit Parrot .code = MEDIA_BUS_FMT_UYVY8_2X8, 822c4c0283aSBenoit Parrot .format_ctrl_regs = ov2659_format_uyvy, 823c4c0283aSBenoit Parrot }, { 824c4c0283aSBenoit Parrot .code = MEDIA_BUS_FMT_RGB565_2X8_BE, 825c4c0283aSBenoit Parrot .format_ctrl_regs = ov2659_format_rgb565, 826c4c0283aSBenoit Parrot }, { 827c4c0283aSBenoit Parrot .code = MEDIA_BUS_FMT_SBGGR8_1X8, 828c4c0283aSBenoit Parrot .format_ctrl_regs = ov2659_format_bggr, 829c4c0283aSBenoit Parrot }, 830c4c0283aSBenoit Parrot }; 831c4c0283aSBenoit Parrot 832c4c0283aSBenoit Parrot static inline struct ov2659 *to_ov2659(struct v4l2_subdev *sd) 833c4c0283aSBenoit Parrot { 834c4c0283aSBenoit Parrot return container_of(sd, struct ov2659, sd); 835c4c0283aSBenoit Parrot } 836c4c0283aSBenoit Parrot 837c4c0283aSBenoit Parrot /* sensor register write */ 838c4c0283aSBenoit Parrot static int ov2659_write(struct i2c_client *client, u16 reg, u8 val) 839c4c0283aSBenoit Parrot { 840c4c0283aSBenoit Parrot struct i2c_msg msg; 841c4c0283aSBenoit Parrot u8 buf[3]; 842c4c0283aSBenoit Parrot int ret; 843c4c0283aSBenoit Parrot 844c4c0283aSBenoit Parrot buf[0] = reg >> 8; 845c4c0283aSBenoit Parrot buf[1] = reg & 0xFF; 846c4c0283aSBenoit Parrot buf[2] = val; 847c4c0283aSBenoit Parrot 848c4c0283aSBenoit Parrot msg.addr = client->addr; 849c4c0283aSBenoit Parrot msg.flags = client->flags; 850c4c0283aSBenoit Parrot msg.buf = buf; 851c4c0283aSBenoit Parrot msg.len = sizeof(buf); 852c4c0283aSBenoit Parrot 853c4c0283aSBenoit Parrot ret = i2c_transfer(client->adapter, &msg, 1); 854c4c0283aSBenoit Parrot if (ret >= 0) 855c4c0283aSBenoit Parrot return 0; 856c4c0283aSBenoit Parrot 857c4c0283aSBenoit Parrot dev_dbg(&client->dev, 858c4c0283aSBenoit Parrot "ov2659 write reg(0x%x val:0x%x) failed !\n", reg, val); 859c4c0283aSBenoit Parrot 860c4c0283aSBenoit Parrot return ret; 861c4c0283aSBenoit Parrot } 862c4c0283aSBenoit Parrot 863c4c0283aSBenoit Parrot /* sensor register read */ 864c4c0283aSBenoit Parrot static int ov2659_read(struct i2c_client *client, u16 reg, u8 *val) 865c4c0283aSBenoit Parrot { 866c4c0283aSBenoit Parrot struct i2c_msg msg[2]; 867c4c0283aSBenoit Parrot u8 buf[2]; 868c4c0283aSBenoit Parrot int ret; 869c4c0283aSBenoit Parrot 870c4c0283aSBenoit Parrot buf[0] = reg >> 8; 871c4c0283aSBenoit Parrot buf[1] = reg & 0xFF; 872c4c0283aSBenoit Parrot 873c4c0283aSBenoit Parrot msg[0].addr = client->addr; 874c4c0283aSBenoit Parrot msg[0].flags = client->flags; 875c4c0283aSBenoit Parrot msg[0].buf = buf; 876c4c0283aSBenoit Parrot msg[0].len = sizeof(buf); 877c4c0283aSBenoit Parrot 878c4c0283aSBenoit Parrot msg[1].addr = client->addr; 879c4c0283aSBenoit Parrot msg[1].flags = client->flags | I2C_M_RD; 880c4c0283aSBenoit Parrot msg[1].buf = buf; 881c4c0283aSBenoit Parrot msg[1].len = 1; 882c4c0283aSBenoit Parrot 883c4c0283aSBenoit Parrot ret = i2c_transfer(client->adapter, msg, 2); 884c4c0283aSBenoit Parrot if (ret >= 0) { 885c4c0283aSBenoit Parrot *val = buf[0]; 886c4c0283aSBenoit Parrot return 0; 887c4c0283aSBenoit Parrot } 888c4c0283aSBenoit Parrot 889c4c0283aSBenoit Parrot dev_dbg(&client->dev, 890c4c0283aSBenoit Parrot "ov2659 read reg(0x%x val:0x%x) failed !\n", reg, *val); 891c4c0283aSBenoit Parrot 892c4c0283aSBenoit Parrot return ret; 893c4c0283aSBenoit Parrot } 894c4c0283aSBenoit Parrot 895c4c0283aSBenoit Parrot static int ov2659_write_array(struct i2c_client *client, 896c4c0283aSBenoit Parrot const struct sensor_register *regs) 897c4c0283aSBenoit Parrot { 898c4c0283aSBenoit Parrot int i, ret = 0; 899c4c0283aSBenoit Parrot 900c4c0283aSBenoit Parrot for (i = 0; ret == 0 && regs[i].addr; i++) 901c4c0283aSBenoit Parrot ret = ov2659_write(client, regs[i].addr, regs[i].value); 902c4c0283aSBenoit Parrot 903c4c0283aSBenoit Parrot return ret; 904c4c0283aSBenoit Parrot } 905c4c0283aSBenoit Parrot 906c4c0283aSBenoit Parrot static void ov2659_pll_calc_params(struct ov2659 *ov2659) 907c4c0283aSBenoit Parrot { 908c4c0283aSBenoit Parrot const struct ov2659_platform_data *pdata = ov2659->pdata; 909c4c0283aSBenoit Parrot u8 ctrl1_reg = 0, ctrl2_reg = 0, ctrl3_reg = 0; 910c4c0283aSBenoit Parrot struct i2c_client *client = ov2659->client; 911c4c0283aSBenoit Parrot unsigned int desired = pdata->link_frequency; 912c4c0283aSBenoit Parrot u32 prediv, postdiv, mult; 913c4c0283aSBenoit Parrot u32 bestdelta = -1; 914c4c0283aSBenoit Parrot u32 delta, actual; 915c4c0283aSBenoit Parrot int i, j; 916c4c0283aSBenoit Parrot 917c4c0283aSBenoit Parrot for (i = 0; ctrl1[i].div != 0; i++) { 918c4c0283aSBenoit Parrot postdiv = ctrl1[i].div; 919c4c0283aSBenoit Parrot for (j = 0; ctrl3[j].div != 0; j++) { 920c4c0283aSBenoit Parrot prediv = ctrl3[j].div; 921c4c0283aSBenoit Parrot for (mult = 1; mult <= 63; mult++) { 922c4c0283aSBenoit Parrot actual = ov2659->xvclk_frequency; 923c4c0283aSBenoit Parrot actual *= mult; 924c4c0283aSBenoit Parrot actual /= prediv; 925c4c0283aSBenoit Parrot actual /= postdiv; 926c4c0283aSBenoit Parrot delta = actual - desired; 927c4c0283aSBenoit Parrot delta = abs(delta); 928c4c0283aSBenoit Parrot 929c4c0283aSBenoit Parrot if ((delta < bestdelta) || (bestdelta == -1)) { 930c4c0283aSBenoit Parrot bestdelta = delta; 931c4c0283aSBenoit Parrot ctrl1_reg = ctrl1[i].reg; 932c4c0283aSBenoit Parrot ctrl2_reg = mult; 933c4c0283aSBenoit Parrot ctrl3_reg = ctrl3[j].reg; 934c4c0283aSBenoit Parrot } 935c4c0283aSBenoit Parrot } 936c4c0283aSBenoit Parrot } 937c4c0283aSBenoit Parrot } 938c4c0283aSBenoit Parrot 939c4c0283aSBenoit Parrot ov2659->pll.ctrl1 = ctrl1_reg; 940c4c0283aSBenoit Parrot ov2659->pll.ctrl2 = ctrl2_reg; 941c4c0283aSBenoit Parrot ov2659->pll.ctrl3 = ctrl3_reg; 942c4c0283aSBenoit Parrot 943c4c0283aSBenoit Parrot dev_dbg(&client->dev, 944c4c0283aSBenoit Parrot "Actual reg config: ctrl1_reg: %02x ctrl2_reg: %02x ctrl3_reg: %02x\n", 945c4c0283aSBenoit Parrot ctrl1_reg, ctrl2_reg, ctrl3_reg); 946c4c0283aSBenoit Parrot } 947c4c0283aSBenoit Parrot 948c4c0283aSBenoit Parrot static int ov2659_set_pixel_clock(struct ov2659 *ov2659) 949c4c0283aSBenoit Parrot { 950c4c0283aSBenoit Parrot struct i2c_client *client = ov2659->client; 951c4c0283aSBenoit Parrot struct sensor_register pll_regs[] = { 952c4c0283aSBenoit Parrot {REG_SC_PLL_CTRL1, ov2659->pll.ctrl1}, 953c4c0283aSBenoit Parrot {REG_SC_PLL_CTRL2, ov2659->pll.ctrl2}, 954c4c0283aSBenoit Parrot {REG_SC_PLL_CTRL3, ov2659->pll.ctrl3}, 955c4c0283aSBenoit Parrot {REG_NULL, 0x00}, 956c4c0283aSBenoit Parrot }; 957c4c0283aSBenoit Parrot 958c4c0283aSBenoit Parrot dev_dbg(&client->dev, "%s\n", __func__); 959c4c0283aSBenoit Parrot 960c4c0283aSBenoit Parrot return ov2659_write_array(client, pll_regs); 961c4c0283aSBenoit Parrot }; 962c4c0283aSBenoit Parrot 963c4c0283aSBenoit Parrot static void ov2659_get_default_format(struct v4l2_mbus_framefmt *format) 964c4c0283aSBenoit Parrot { 965c4c0283aSBenoit Parrot format->width = ov2659_framesizes[2].width; 966c4c0283aSBenoit Parrot format->height = ov2659_framesizes[2].height; 967c4c0283aSBenoit Parrot format->colorspace = V4L2_COLORSPACE_SRGB; 968c4c0283aSBenoit Parrot format->code = ov2659_formats[0].code; 969c4c0283aSBenoit Parrot format->field = V4L2_FIELD_NONE; 970c4c0283aSBenoit Parrot } 971c4c0283aSBenoit Parrot 972c4c0283aSBenoit Parrot static void ov2659_set_streaming(struct ov2659 *ov2659, int on) 973c4c0283aSBenoit Parrot { 974c4c0283aSBenoit Parrot struct i2c_client *client = ov2659->client; 975c4c0283aSBenoit Parrot int ret; 976c4c0283aSBenoit Parrot 977c4c0283aSBenoit Parrot on = !!on; 978c4c0283aSBenoit Parrot 979c4c0283aSBenoit Parrot dev_dbg(&client->dev, "%s: on: %d\n", __func__, on); 980c4c0283aSBenoit Parrot 981c4c0283aSBenoit Parrot ret = ov2659_write(client, REG_SOFTWARE_STANDBY, on); 982c4c0283aSBenoit Parrot if (ret) 983c4c0283aSBenoit Parrot dev_err(&client->dev, "ov2659 soft standby failed\n"); 984c4c0283aSBenoit Parrot } 985c4c0283aSBenoit Parrot 986c4c0283aSBenoit Parrot static int ov2659_init(struct v4l2_subdev *sd, u32 val) 987c4c0283aSBenoit Parrot { 988c4c0283aSBenoit Parrot struct i2c_client *client = v4l2_get_subdevdata(sd); 989c4c0283aSBenoit Parrot 990c4c0283aSBenoit Parrot return ov2659_write_array(client, ov2659_init_regs); 991c4c0283aSBenoit Parrot } 992c4c0283aSBenoit Parrot 993c4c0283aSBenoit Parrot /* 994c4c0283aSBenoit Parrot * V4L2 subdev video and pad level operations 995c4c0283aSBenoit Parrot */ 996c4c0283aSBenoit Parrot 997c4c0283aSBenoit Parrot static int ov2659_enum_mbus_code(struct v4l2_subdev *sd, 998c4c0283aSBenoit Parrot struct v4l2_subdev_pad_config *cfg, 999c4c0283aSBenoit Parrot struct v4l2_subdev_mbus_code_enum *code) 1000c4c0283aSBenoit Parrot { 1001c4c0283aSBenoit Parrot struct i2c_client *client = v4l2_get_subdevdata(sd); 1002c4c0283aSBenoit Parrot 1003c4c0283aSBenoit Parrot dev_dbg(&client->dev, "%s:\n", __func__); 1004c4c0283aSBenoit Parrot 1005c4c0283aSBenoit Parrot if (code->index >= ARRAY_SIZE(ov2659_formats)) 1006c4c0283aSBenoit Parrot return -EINVAL; 1007c4c0283aSBenoit Parrot 1008c4c0283aSBenoit Parrot code->code = ov2659_formats[code->index].code; 1009c4c0283aSBenoit Parrot 1010c4c0283aSBenoit Parrot return 0; 1011c4c0283aSBenoit Parrot } 1012c4c0283aSBenoit Parrot 1013c4c0283aSBenoit Parrot static int ov2659_enum_frame_sizes(struct v4l2_subdev *sd, 1014c4c0283aSBenoit Parrot struct v4l2_subdev_pad_config *cfg, 1015c4c0283aSBenoit Parrot struct v4l2_subdev_frame_size_enum *fse) 1016c4c0283aSBenoit Parrot { 1017c4c0283aSBenoit Parrot struct i2c_client *client = v4l2_get_subdevdata(sd); 1018c4c0283aSBenoit Parrot int i = ARRAY_SIZE(ov2659_formats); 1019c4c0283aSBenoit Parrot 1020c4c0283aSBenoit Parrot dev_dbg(&client->dev, "%s:\n", __func__); 1021c4c0283aSBenoit Parrot 1022c4c0283aSBenoit Parrot if (fse->index >= ARRAY_SIZE(ov2659_framesizes)) 1023c4c0283aSBenoit Parrot return -EINVAL; 1024c4c0283aSBenoit Parrot 1025c4c0283aSBenoit Parrot while (--i) 1026c4c0283aSBenoit Parrot if (fse->code == ov2659_formats[i].code) 1027c4c0283aSBenoit Parrot break; 1028c4c0283aSBenoit Parrot 1029c4c0283aSBenoit Parrot fse->code = ov2659_formats[i].code; 1030c4c0283aSBenoit Parrot 1031c4c0283aSBenoit Parrot fse->min_width = ov2659_framesizes[fse->index].width; 1032c4c0283aSBenoit Parrot fse->max_width = fse->min_width; 1033c4c0283aSBenoit Parrot fse->max_height = ov2659_framesizes[fse->index].height; 1034c4c0283aSBenoit Parrot fse->min_height = fse->max_height; 1035c4c0283aSBenoit Parrot 1036c4c0283aSBenoit Parrot return 0; 1037c4c0283aSBenoit Parrot } 1038c4c0283aSBenoit Parrot 1039c4c0283aSBenoit Parrot static int ov2659_get_fmt(struct v4l2_subdev *sd, 1040c4c0283aSBenoit Parrot struct v4l2_subdev_pad_config *cfg, 1041c4c0283aSBenoit Parrot struct v4l2_subdev_format *fmt) 1042c4c0283aSBenoit Parrot { 1043c4c0283aSBenoit Parrot struct i2c_client *client = v4l2_get_subdevdata(sd); 1044c4c0283aSBenoit Parrot struct ov2659 *ov2659 = to_ov2659(sd); 1045c4c0283aSBenoit Parrot 1046c4c0283aSBenoit Parrot dev_dbg(&client->dev, "ov2659_get_fmt\n"); 1047c4c0283aSBenoit Parrot 1048c4c0283aSBenoit Parrot if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { 1049fa8cb644SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 1050fa8cb644SMauro Carvalho Chehab struct v4l2_mbus_framefmt *mf; 1051fa8cb644SMauro Carvalho Chehab 1052c4c0283aSBenoit Parrot mf = v4l2_subdev_get_try_format(sd, cfg, 0); 1053c4c0283aSBenoit Parrot mutex_lock(&ov2659->lock); 1054c4c0283aSBenoit Parrot fmt->format = *mf; 1055c4c0283aSBenoit Parrot mutex_unlock(&ov2659->lock); 1056c4c0283aSBenoit Parrot return 0; 1057fa8cb644SMauro Carvalho Chehab #else 1058fa8cb644SMauro Carvalho Chehab return -ENOTTY; 1059fa8cb644SMauro Carvalho Chehab #endif 1060c4c0283aSBenoit Parrot } 1061c4c0283aSBenoit Parrot 1062c4c0283aSBenoit Parrot mutex_lock(&ov2659->lock); 1063c4c0283aSBenoit Parrot fmt->format = ov2659->format; 1064c4c0283aSBenoit Parrot mutex_unlock(&ov2659->lock); 1065c4c0283aSBenoit Parrot 1066c4c0283aSBenoit Parrot dev_dbg(&client->dev, "ov2659_get_fmt: %x %dx%d\n", 1067c4c0283aSBenoit Parrot ov2659->format.code, ov2659->format.width, 1068c4c0283aSBenoit Parrot ov2659->format.height); 1069c4c0283aSBenoit Parrot 1070c4c0283aSBenoit Parrot return 0; 1071c4c0283aSBenoit Parrot } 1072c4c0283aSBenoit Parrot 1073c4c0283aSBenoit Parrot static void __ov2659_try_frame_size(struct v4l2_mbus_framefmt *mf, 1074c4c0283aSBenoit Parrot const struct ov2659_framesize **size) 1075c4c0283aSBenoit Parrot { 1076c4c0283aSBenoit Parrot const struct ov2659_framesize *fsize = &ov2659_framesizes[0]; 1077c4c0283aSBenoit Parrot const struct ov2659_framesize *match = NULL; 1078c4c0283aSBenoit Parrot int i = ARRAY_SIZE(ov2659_framesizes); 1079c4c0283aSBenoit Parrot unsigned int min_err = UINT_MAX; 1080c4c0283aSBenoit Parrot 1081c4c0283aSBenoit Parrot while (i--) { 1082c4c0283aSBenoit Parrot int err = abs(fsize->width - mf->width) 1083c4c0283aSBenoit Parrot + abs(fsize->height - mf->height); 1084c4c0283aSBenoit Parrot if ((err < min_err) && (fsize->regs[0].addr)) { 1085c4c0283aSBenoit Parrot min_err = err; 1086c4c0283aSBenoit Parrot match = fsize; 1087c4c0283aSBenoit Parrot } 1088c4c0283aSBenoit Parrot fsize++; 1089c4c0283aSBenoit Parrot } 1090c4c0283aSBenoit Parrot 1091c4c0283aSBenoit Parrot if (!match) 1092c4c0283aSBenoit Parrot match = &ov2659_framesizes[2]; 1093c4c0283aSBenoit Parrot 1094c4c0283aSBenoit Parrot mf->width = match->width; 1095c4c0283aSBenoit Parrot mf->height = match->height; 1096c4c0283aSBenoit Parrot 1097c4c0283aSBenoit Parrot if (size) 1098c4c0283aSBenoit Parrot *size = match; 1099c4c0283aSBenoit Parrot } 1100c4c0283aSBenoit Parrot 1101c4c0283aSBenoit Parrot static int ov2659_set_fmt(struct v4l2_subdev *sd, 1102c4c0283aSBenoit Parrot struct v4l2_subdev_pad_config *cfg, 1103c4c0283aSBenoit Parrot struct v4l2_subdev_format *fmt) 1104c4c0283aSBenoit Parrot { 1105c4c0283aSBenoit Parrot struct i2c_client *client = v4l2_get_subdevdata(sd); 11065f5859d1SDan Carpenter int index = ARRAY_SIZE(ov2659_formats); 1107c4c0283aSBenoit Parrot struct v4l2_mbus_framefmt *mf = &fmt->format; 1108c4c0283aSBenoit Parrot const struct ov2659_framesize *size = NULL; 1109c4c0283aSBenoit Parrot struct ov2659 *ov2659 = to_ov2659(sd); 1110c4c0283aSBenoit Parrot int ret = 0; 1111c4c0283aSBenoit Parrot 1112c4c0283aSBenoit Parrot dev_dbg(&client->dev, "ov2659_set_fmt\n"); 1113c4c0283aSBenoit Parrot 1114c4c0283aSBenoit Parrot __ov2659_try_frame_size(mf, &size); 1115c4c0283aSBenoit Parrot 1116c4c0283aSBenoit Parrot while (--index >= 0) 1117c4c0283aSBenoit Parrot if (ov2659_formats[index].code == mf->code) 1118c4c0283aSBenoit Parrot break; 1119c4c0283aSBenoit Parrot 1120bccb89cfSAkinobu Mita if (index < 0) { 1121bccb89cfSAkinobu Mita index = 0; 1122bccb89cfSAkinobu Mita mf->code = ov2659_formats[index].code; 1123bccb89cfSAkinobu Mita } 1124c4c0283aSBenoit Parrot 1125c4c0283aSBenoit Parrot mf->colorspace = V4L2_COLORSPACE_SRGB; 1126c4c0283aSBenoit Parrot mf->field = V4L2_FIELD_NONE; 1127c4c0283aSBenoit Parrot 1128c4c0283aSBenoit Parrot mutex_lock(&ov2659->lock); 1129c4c0283aSBenoit Parrot 1130c4c0283aSBenoit Parrot if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { 1131fa8cb644SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 1132c4c0283aSBenoit Parrot mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); 1133c4c0283aSBenoit Parrot *mf = fmt->format; 1134fa8cb644SMauro Carvalho Chehab #else 1135fa8cb644SMauro Carvalho Chehab return -ENOTTY; 1136fa8cb644SMauro Carvalho Chehab #endif 1137c4c0283aSBenoit Parrot } else { 1138c4c0283aSBenoit Parrot s64 val; 1139c4c0283aSBenoit Parrot 1140c4c0283aSBenoit Parrot if (ov2659->streaming) { 1141c4c0283aSBenoit Parrot mutex_unlock(&ov2659->lock); 1142c4c0283aSBenoit Parrot return -EBUSY; 1143c4c0283aSBenoit Parrot } 1144c4c0283aSBenoit Parrot 1145c4c0283aSBenoit Parrot ov2659->frame_size = size; 1146c4c0283aSBenoit Parrot ov2659->format = fmt->format; 1147c4c0283aSBenoit Parrot ov2659->format_ctrl_regs = 1148c4c0283aSBenoit Parrot ov2659_formats[index].format_ctrl_regs; 1149c4c0283aSBenoit Parrot 1150c4c0283aSBenoit Parrot if (ov2659->format.code != MEDIA_BUS_FMT_SBGGR8_1X8) 1151c4c0283aSBenoit Parrot val = ov2659->pdata->link_frequency / 2; 1152c4c0283aSBenoit Parrot else 1153c4c0283aSBenoit Parrot val = ov2659->pdata->link_frequency; 1154c4c0283aSBenoit Parrot 1155c4c0283aSBenoit Parrot ret = v4l2_ctrl_s_ctrl_int64(ov2659->link_frequency, val); 1156c4c0283aSBenoit Parrot if (ret < 0) 1157c4c0283aSBenoit Parrot dev_warn(&client->dev, 1158c4c0283aSBenoit Parrot "failed to set link_frequency rate (%d)\n", 1159c4c0283aSBenoit Parrot ret); 1160c4c0283aSBenoit Parrot } 1161c4c0283aSBenoit Parrot 1162c4c0283aSBenoit Parrot mutex_unlock(&ov2659->lock); 1163c4c0283aSBenoit Parrot return ret; 1164c4c0283aSBenoit Parrot } 1165c4c0283aSBenoit Parrot 1166c4c0283aSBenoit Parrot static int ov2659_set_frame_size(struct ov2659 *ov2659) 1167c4c0283aSBenoit Parrot { 1168c4c0283aSBenoit Parrot struct i2c_client *client = ov2659->client; 1169c4c0283aSBenoit Parrot 1170c4c0283aSBenoit Parrot dev_dbg(&client->dev, "%s\n", __func__); 1171c4c0283aSBenoit Parrot 1172c4c0283aSBenoit Parrot return ov2659_write_array(ov2659->client, ov2659->frame_size->regs); 1173c4c0283aSBenoit Parrot } 1174c4c0283aSBenoit Parrot 1175c4c0283aSBenoit Parrot static int ov2659_set_format(struct ov2659 *ov2659) 1176c4c0283aSBenoit Parrot { 1177c4c0283aSBenoit Parrot struct i2c_client *client = ov2659->client; 1178c4c0283aSBenoit Parrot 1179c4c0283aSBenoit Parrot dev_dbg(&client->dev, "%s\n", __func__); 1180c4c0283aSBenoit Parrot 1181c4c0283aSBenoit Parrot return ov2659_write_array(ov2659->client, ov2659->format_ctrl_regs); 1182c4c0283aSBenoit Parrot } 1183c4c0283aSBenoit Parrot 1184c4c0283aSBenoit Parrot static int ov2659_s_stream(struct v4l2_subdev *sd, int on) 1185c4c0283aSBenoit Parrot { 1186c4c0283aSBenoit Parrot struct i2c_client *client = v4l2_get_subdevdata(sd); 1187c4c0283aSBenoit Parrot struct ov2659 *ov2659 = to_ov2659(sd); 1188c4c0283aSBenoit Parrot int ret = 0; 1189c4c0283aSBenoit Parrot 1190c4c0283aSBenoit Parrot dev_dbg(&client->dev, "%s: on: %d\n", __func__, on); 1191c4c0283aSBenoit Parrot 1192c4c0283aSBenoit Parrot mutex_lock(&ov2659->lock); 1193c4c0283aSBenoit Parrot 1194c4c0283aSBenoit Parrot on = !!on; 1195c4c0283aSBenoit Parrot 1196c4c0283aSBenoit Parrot if (ov2659->streaming == on) 1197c4c0283aSBenoit Parrot goto unlock; 1198c4c0283aSBenoit Parrot 1199c4c0283aSBenoit Parrot if (!on) { 1200c4c0283aSBenoit Parrot /* Stop Streaming Sequence */ 1201c4c0283aSBenoit Parrot ov2659_set_streaming(ov2659, 0); 1202c4c0283aSBenoit Parrot ov2659->streaming = on; 1203c4c0283aSBenoit Parrot goto unlock; 1204c4c0283aSBenoit Parrot } 1205c4c0283aSBenoit Parrot 1206c4c0283aSBenoit Parrot ov2659_set_pixel_clock(ov2659); 1207c4c0283aSBenoit Parrot ov2659_set_frame_size(ov2659); 1208c4c0283aSBenoit Parrot ov2659_set_format(ov2659); 1209c4c0283aSBenoit Parrot ov2659_set_streaming(ov2659, 1); 1210c4c0283aSBenoit Parrot ov2659->streaming = on; 1211c4c0283aSBenoit Parrot 1212c4c0283aSBenoit Parrot unlock: 1213c4c0283aSBenoit Parrot mutex_unlock(&ov2659->lock); 1214c4c0283aSBenoit Parrot return ret; 1215c4c0283aSBenoit Parrot } 1216c4c0283aSBenoit Parrot 1217c4c0283aSBenoit Parrot static int ov2659_set_test_pattern(struct ov2659 *ov2659, int value) 1218c4c0283aSBenoit Parrot { 1219c4c0283aSBenoit Parrot struct i2c_client *client = v4l2_get_subdevdata(&ov2659->sd); 1220c4c0283aSBenoit Parrot int ret; 1221c4c0283aSBenoit Parrot u8 val; 1222c4c0283aSBenoit Parrot 1223c4c0283aSBenoit Parrot ret = ov2659_read(client, REG_PRE_ISP_CTRL00, &val); 1224c4c0283aSBenoit Parrot if (ret < 0) 1225c4c0283aSBenoit Parrot return ret; 1226c4c0283aSBenoit Parrot 1227c4c0283aSBenoit Parrot switch (value) { 1228c4c0283aSBenoit Parrot case 0: 1229c4c0283aSBenoit Parrot val &= ~TEST_PATTERN_ENABLE; 1230c4c0283aSBenoit Parrot break; 1231c4c0283aSBenoit Parrot case 1: 1232c4c0283aSBenoit Parrot val &= VERTICAL_COLOR_BAR_MASK; 1233c4c0283aSBenoit Parrot val |= TEST_PATTERN_ENABLE; 1234c4c0283aSBenoit Parrot break; 1235c4c0283aSBenoit Parrot } 1236c4c0283aSBenoit Parrot 1237c4c0283aSBenoit Parrot return ov2659_write(client, REG_PRE_ISP_CTRL00, val); 1238c4c0283aSBenoit Parrot } 1239c4c0283aSBenoit Parrot 1240c4c0283aSBenoit Parrot static int ov2659_s_ctrl(struct v4l2_ctrl *ctrl) 1241c4c0283aSBenoit Parrot { 1242c4c0283aSBenoit Parrot struct ov2659 *ov2659 = 1243c4c0283aSBenoit Parrot container_of(ctrl->handler, struct ov2659, ctrls); 1244c4c0283aSBenoit Parrot 1245c4c0283aSBenoit Parrot switch (ctrl->id) { 1246c4c0283aSBenoit Parrot case V4L2_CID_TEST_PATTERN: 1247c4c0283aSBenoit Parrot return ov2659_set_test_pattern(ov2659, ctrl->val); 1248c4c0283aSBenoit Parrot } 1249c4c0283aSBenoit Parrot 1250c4c0283aSBenoit Parrot return 0; 1251c4c0283aSBenoit Parrot } 1252c4c0283aSBenoit Parrot 1253217bdb07SJulia Lawall static const struct v4l2_ctrl_ops ov2659_ctrl_ops = { 1254c4c0283aSBenoit Parrot .s_ctrl = ov2659_s_ctrl, 1255c4c0283aSBenoit Parrot }; 1256c4c0283aSBenoit Parrot 1257c4c0283aSBenoit Parrot static const char * const ov2659_test_pattern_menu[] = { 1258c4c0283aSBenoit Parrot "Disabled", 1259c4c0283aSBenoit Parrot "Vertical Color Bars", 1260c4c0283aSBenoit Parrot }; 1261c4c0283aSBenoit Parrot 1262c4c0283aSBenoit Parrot /* ----------------------------------------------------------------------------- 1263c4c0283aSBenoit Parrot * V4L2 subdev internal operations 1264c4c0283aSBenoit Parrot */ 1265c4c0283aSBenoit Parrot 1266fa8cb644SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 1267c4c0283aSBenoit Parrot static int ov2659_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 1268c4c0283aSBenoit Parrot { 1269c4c0283aSBenoit Parrot struct i2c_client *client = v4l2_get_subdevdata(sd); 1270c4c0283aSBenoit Parrot struct v4l2_mbus_framefmt *format = 1271c4c0283aSBenoit Parrot v4l2_subdev_get_try_format(sd, fh->pad, 0); 1272c4c0283aSBenoit Parrot 1273c4c0283aSBenoit Parrot dev_dbg(&client->dev, "%s:\n", __func__); 1274c4c0283aSBenoit Parrot 1275c4c0283aSBenoit Parrot ov2659_get_default_format(format); 1276c4c0283aSBenoit Parrot 1277c4c0283aSBenoit Parrot return 0; 1278c4c0283aSBenoit Parrot } 1279fa8cb644SMauro Carvalho Chehab #endif 1280c4c0283aSBenoit Parrot 1281c4c0283aSBenoit Parrot static const struct v4l2_subdev_core_ops ov2659_subdev_core_ops = { 1282c4c0283aSBenoit Parrot .log_status = v4l2_ctrl_subdev_log_status, 1283c4c0283aSBenoit Parrot .subscribe_event = v4l2_ctrl_subdev_subscribe_event, 1284c4c0283aSBenoit Parrot .unsubscribe_event = v4l2_event_subdev_unsubscribe, 1285c4c0283aSBenoit Parrot }; 1286c4c0283aSBenoit Parrot 1287c4c0283aSBenoit Parrot static const struct v4l2_subdev_video_ops ov2659_subdev_video_ops = { 1288c4c0283aSBenoit Parrot .s_stream = ov2659_s_stream, 1289c4c0283aSBenoit Parrot }; 1290c4c0283aSBenoit Parrot 1291c4c0283aSBenoit Parrot static const struct v4l2_subdev_pad_ops ov2659_subdev_pad_ops = { 1292c4c0283aSBenoit Parrot .enum_mbus_code = ov2659_enum_mbus_code, 1293c4c0283aSBenoit Parrot .enum_frame_size = ov2659_enum_frame_sizes, 1294c4c0283aSBenoit Parrot .get_fmt = ov2659_get_fmt, 1295c4c0283aSBenoit Parrot .set_fmt = ov2659_set_fmt, 1296c4c0283aSBenoit Parrot }; 1297c4c0283aSBenoit Parrot 1298fa8cb644SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 1299c4c0283aSBenoit Parrot static const struct v4l2_subdev_ops ov2659_subdev_ops = { 1300c4c0283aSBenoit Parrot .core = &ov2659_subdev_core_ops, 1301c4c0283aSBenoit Parrot .video = &ov2659_subdev_video_ops, 1302c4c0283aSBenoit Parrot .pad = &ov2659_subdev_pad_ops, 1303c4c0283aSBenoit Parrot }; 1304c4c0283aSBenoit Parrot 1305c4c0283aSBenoit Parrot static const struct v4l2_subdev_internal_ops ov2659_subdev_internal_ops = { 1306c4c0283aSBenoit Parrot .open = ov2659_open, 1307c4c0283aSBenoit Parrot }; 1308fa8cb644SMauro Carvalho Chehab #endif 1309c4c0283aSBenoit Parrot 1310c4c0283aSBenoit Parrot static int ov2659_detect(struct v4l2_subdev *sd) 1311c4c0283aSBenoit Parrot { 1312c4c0283aSBenoit Parrot struct i2c_client *client = v4l2_get_subdevdata(sd); 1313e1082d28SGustavo A. R. Silva u8 pid = 0; 1314e1082d28SGustavo A. R. Silva u8 ver = 0; 1315c4c0283aSBenoit Parrot int ret; 1316c4c0283aSBenoit Parrot 1317c4c0283aSBenoit Parrot dev_dbg(&client->dev, "%s:\n", __func__); 1318c4c0283aSBenoit Parrot 1319c4c0283aSBenoit Parrot ret = ov2659_write(client, REG_SOFTWARE_RESET, 0x01); 1320c4c0283aSBenoit Parrot if (ret != 0) { 1321c4c0283aSBenoit Parrot dev_err(&client->dev, "Sensor soft reset failed\n"); 1322c4c0283aSBenoit Parrot return -ENODEV; 1323c4c0283aSBenoit Parrot } 1324c4c0283aSBenoit Parrot usleep_range(1000, 2000); 1325c4c0283aSBenoit Parrot 1326c4c0283aSBenoit Parrot /* Check sensor revision */ 1327c4c0283aSBenoit Parrot ret = ov2659_read(client, REG_SC_CHIP_ID_H, &pid); 1328c4c0283aSBenoit Parrot if (!ret) 1329c4c0283aSBenoit Parrot ret = ov2659_read(client, REG_SC_CHIP_ID_L, &ver); 1330c4c0283aSBenoit Parrot 1331c4c0283aSBenoit Parrot if (!ret) { 1332c4c0283aSBenoit Parrot unsigned short id; 1333c4c0283aSBenoit Parrot 1334c4c0283aSBenoit Parrot id = OV265X_ID(pid, ver); 1335c4c0283aSBenoit Parrot if (id != OV2659_ID) 1336c4c0283aSBenoit Parrot dev_err(&client->dev, 1337c4c0283aSBenoit Parrot "Sensor detection failed (%04X, %d)\n", 1338c4c0283aSBenoit Parrot id, ret); 13392e490139SGrygorii Strashko else { 1340c4c0283aSBenoit Parrot dev_info(&client->dev, "Found OV%04X sensor\n", id); 13412e490139SGrygorii Strashko ret = ov2659_init(sd, 0); 13422e490139SGrygorii Strashko } 1343c4c0283aSBenoit Parrot } 1344c4c0283aSBenoit Parrot 1345c4c0283aSBenoit Parrot return ret; 1346c4c0283aSBenoit Parrot } 1347c4c0283aSBenoit Parrot 1348c4c0283aSBenoit Parrot static struct ov2659_platform_data * 1349c4c0283aSBenoit Parrot ov2659_get_pdata(struct i2c_client *client) 1350c4c0283aSBenoit Parrot { 1351c4c0283aSBenoit Parrot struct ov2659_platform_data *pdata; 13526970d37cSSakari Ailus struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; 1353c4c0283aSBenoit Parrot struct device_node *endpoint; 13546970d37cSSakari Ailus int ret; 1355c4c0283aSBenoit Parrot 1356c4c0283aSBenoit Parrot if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) 1357c4c0283aSBenoit Parrot return client->dev.platform_data; 1358c4c0283aSBenoit Parrot 1359c4c0283aSBenoit Parrot endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL); 1360c4c0283aSBenoit Parrot if (!endpoint) 1361c4c0283aSBenoit Parrot return NULL; 1362c4c0283aSBenoit Parrot 13636970d37cSSakari Ailus ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(endpoint), 13646970d37cSSakari Ailus &bus_cfg); 13656970d37cSSakari Ailus if (ret) { 1366b3ab190fSLad, Prabhakar pdata = NULL; 1367b3ab190fSLad, Prabhakar goto done; 1368b3ab190fSLad, Prabhakar } 1369b3ab190fSLad, Prabhakar 1370c4c0283aSBenoit Parrot pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); 1371c4c0283aSBenoit Parrot if (!pdata) 1372c4c0283aSBenoit Parrot goto done; 1373c4c0283aSBenoit Parrot 13746970d37cSSakari Ailus if (!bus_cfg.nr_of_link_frequencies) { 1375b3ab190fSLad, Prabhakar dev_err(&client->dev, 1376b3ab190fSLad, Prabhakar "link-frequencies property not found or too many\n"); 1377c4c0283aSBenoit Parrot pdata = NULL; 1378b3ab190fSLad, Prabhakar goto done; 1379c4c0283aSBenoit Parrot } 1380c4c0283aSBenoit Parrot 13816970d37cSSakari Ailus pdata->link_frequency = bus_cfg.link_frequencies[0]; 1382b3ab190fSLad, Prabhakar 1383c4c0283aSBenoit Parrot done: 13846970d37cSSakari Ailus v4l2_fwnode_endpoint_free(&bus_cfg); 1385c4c0283aSBenoit Parrot of_node_put(endpoint); 1386c4c0283aSBenoit Parrot return pdata; 1387c4c0283aSBenoit Parrot } 1388c4c0283aSBenoit Parrot 1389c4c0283aSBenoit Parrot static int ov2659_probe(struct i2c_client *client, 1390c4c0283aSBenoit Parrot const struct i2c_device_id *id) 1391c4c0283aSBenoit Parrot { 1392c4c0283aSBenoit Parrot const struct ov2659_platform_data *pdata = ov2659_get_pdata(client); 1393c4c0283aSBenoit Parrot struct v4l2_subdev *sd; 1394c4c0283aSBenoit Parrot struct ov2659 *ov2659; 1395c4c0283aSBenoit Parrot struct clk *clk; 1396c4c0283aSBenoit Parrot int ret; 1397c4c0283aSBenoit Parrot 1398c4c0283aSBenoit Parrot if (!pdata) { 1399c4c0283aSBenoit Parrot dev_err(&client->dev, "platform data not specified\n"); 1400c4c0283aSBenoit Parrot return -EINVAL; 1401c4c0283aSBenoit Parrot } 1402c4c0283aSBenoit Parrot 1403c4c0283aSBenoit Parrot ov2659 = devm_kzalloc(&client->dev, sizeof(*ov2659), GFP_KERNEL); 1404c4c0283aSBenoit Parrot if (!ov2659) 1405c4c0283aSBenoit Parrot return -ENOMEM; 1406c4c0283aSBenoit Parrot 1407c4c0283aSBenoit Parrot ov2659->pdata = pdata; 1408c4c0283aSBenoit Parrot ov2659->client = client; 1409c4c0283aSBenoit Parrot 1410c4c0283aSBenoit Parrot clk = devm_clk_get(&client->dev, "xvclk"); 1411c4c0283aSBenoit Parrot if (IS_ERR(clk)) 1412c4c0283aSBenoit Parrot return PTR_ERR(clk); 1413c4c0283aSBenoit Parrot 1414c4c0283aSBenoit Parrot ov2659->xvclk_frequency = clk_get_rate(clk); 1415c4c0283aSBenoit Parrot if (ov2659->xvclk_frequency < 6000000 || 1416c4c0283aSBenoit Parrot ov2659->xvclk_frequency > 27000000) 1417c4c0283aSBenoit Parrot return -EINVAL; 1418c4c0283aSBenoit Parrot 1419c4c0283aSBenoit Parrot v4l2_ctrl_handler_init(&ov2659->ctrls, 2); 1420c4c0283aSBenoit Parrot ov2659->link_frequency = 1421c4c0283aSBenoit Parrot v4l2_ctrl_new_std(&ov2659->ctrls, &ov2659_ctrl_ops, 1422c4c0283aSBenoit Parrot V4L2_CID_PIXEL_RATE, 1423c4c0283aSBenoit Parrot pdata->link_frequency / 2, 1424c4c0283aSBenoit Parrot pdata->link_frequency, 1, 1425c4c0283aSBenoit Parrot pdata->link_frequency); 1426c4c0283aSBenoit Parrot v4l2_ctrl_new_std_menu_items(&ov2659->ctrls, &ov2659_ctrl_ops, 1427c4c0283aSBenoit Parrot V4L2_CID_TEST_PATTERN, 1428c4c0283aSBenoit Parrot ARRAY_SIZE(ov2659_test_pattern_menu) - 1, 1429c4c0283aSBenoit Parrot 0, 0, ov2659_test_pattern_menu); 1430c4c0283aSBenoit Parrot ov2659->sd.ctrl_handler = &ov2659->ctrls; 1431c4c0283aSBenoit Parrot 1432c4c0283aSBenoit Parrot if (ov2659->ctrls.error) { 1433c4c0283aSBenoit Parrot dev_err(&client->dev, "%s: control initialization error %d\n", 1434c4c0283aSBenoit Parrot __func__, ov2659->ctrls.error); 1435c4c0283aSBenoit Parrot return ov2659->ctrls.error; 1436c4c0283aSBenoit Parrot } 1437c4c0283aSBenoit Parrot 1438c4c0283aSBenoit Parrot sd = &ov2659->sd; 1439c4c0283aSBenoit Parrot client->flags |= I2C_CLIENT_SCCB; 1440fa8cb644SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API 1441c4c0283aSBenoit Parrot v4l2_i2c_subdev_init(sd, client, &ov2659_subdev_ops); 1442c4c0283aSBenoit Parrot 1443c4c0283aSBenoit Parrot sd->internal_ops = &ov2659_subdev_internal_ops; 1444c4c0283aSBenoit Parrot sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | 1445c4c0283aSBenoit Parrot V4L2_SUBDEV_FL_HAS_EVENTS; 1446fa8cb644SMauro Carvalho Chehab #endif 1447c4c0283aSBenoit Parrot 1448c4c0283aSBenoit Parrot #if defined(CONFIG_MEDIA_CONTROLLER) 1449c4c0283aSBenoit Parrot ov2659->pad.flags = MEDIA_PAD_FL_SOURCE; 14504ca72efaSMauro Carvalho Chehab sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; 1451ab22e77cSMauro Carvalho Chehab ret = media_entity_pads_init(&sd->entity, 1, &ov2659->pad); 1452c4c0283aSBenoit Parrot if (ret < 0) { 1453c4c0283aSBenoit Parrot v4l2_ctrl_handler_free(&ov2659->ctrls); 1454c4c0283aSBenoit Parrot return ret; 1455c4c0283aSBenoit Parrot } 1456c4c0283aSBenoit Parrot #endif 1457c4c0283aSBenoit Parrot 1458c4c0283aSBenoit Parrot mutex_init(&ov2659->lock); 1459c4c0283aSBenoit Parrot 1460c4c0283aSBenoit Parrot ov2659_get_default_format(&ov2659->format); 1461c4c0283aSBenoit Parrot ov2659->frame_size = &ov2659_framesizes[2]; 1462c4c0283aSBenoit Parrot ov2659->format_ctrl_regs = ov2659_formats[0].format_ctrl_regs; 1463c4c0283aSBenoit Parrot 1464c4c0283aSBenoit Parrot ret = ov2659_detect(sd); 1465c4c0283aSBenoit Parrot if (ret < 0) 1466c4c0283aSBenoit Parrot goto error; 1467c4c0283aSBenoit Parrot 1468c4c0283aSBenoit Parrot /* Calculate the PLL register value needed */ 1469c4c0283aSBenoit Parrot ov2659_pll_calc_params(ov2659); 1470c4c0283aSBenoit Parrot 1471c4c0283aSBenoit Parrot ret = v4l2_async_register_subdev(&ov2659->sd); 1472c4c0283aSBenoit Parrot if (ret) 1473c4c0283aSBenoit Parrot goto error; 1474c4c0283aSBenoit Parrot 1475c4c0283aSBenoit Parrot dev_info(&client->dev, "%s sensor driver registered !!\n", sd->name); 1476c4c0283aSBenoit Parrot 1477c4c0283aSBenoit Parrot return 0; 1478c4c0283aSBenoit Parrot 1479c4c0283aSBenoit Parrot error: 1480c4c0283aSBenoit Parrot v4l2_ctrl_handler_free(&ov2659->ctrls); 1481c4c0283aSBenoit Parrot media_entity_cleanup(&sd->entity); 1482c4c0283aSBenoit Parrot mutex_destroy(&ov2659->lock); 1483c4c0283aSBenoit Parrot return ret; 1484c4c0283aSBenoit Parrot } 1485c4c0283aSBenoit Parrot 1486c4c0283aSBenoit Parrot static int ov2659_remove(struct i2c_client *client) 1487c4c0283aSBenoit Parrot { 1488c4c0283aSBenoit Parrot struct v4l2_subdev *sd = i2c_get_clientdata(client); 1489c4c0283aSBenoit Parrot struct ov2659 *ov2659 = to_ov2659(sd); 1490c4c0283aSBenoit Parrot 1491c4c0283aSBenoit Parrot v4l2_ctrl_handler_free(&ov2659->ctrls); 1492c4c0283aSBenoit Parrot v4l2_async_unregister_subdev(sd); 1493c4c0283aSBenoit Parrot media_entity_cleanup(&sd->entity); 1494c4c0283aSBenoit Parrot mutex_destroy(&ov2659->lock); 1495c4c0283aSBenoit Parrot 1496c4c0283aSBenoit Parrot return 0; 1497c4c0283aSBenoit Parrot } 1498c4c0283aSBenoit Parrot 1499c4c0283aSBenoit Parrot static const struct i2c_device_id ov2659_id[] = { 1500c4c0283aSBenoit Parrot { "ov2659", 0 }, 1501c4c0283aSBenoit Parrot { /* sentinel */ }, 1502c4c0283aSBenoit Parrot }; 1503c4c0283aSBenoit Parrot MODULE_DEVICE_TABLE(i2c, ov2659_id); 1504c4c0283aSBenoit Parrot 1505c4c0283aSBenoit Parrot #if IS_ENABLED(CONFIG_OF) 1506c4c0283aSBenoit Parrot static const struct of_device_id ov2659_of_match[] = { 1507c4c0283aSBenoit Parrot { .compatible = "ovti,ov2659", }, 1508c4c0283aSBenoit Parrot { /* sentinel */ }, 1509c4c0283aSBenoit Parrot }; 1510c4c0283aSBenoit Parrot MODULE_DEVICE_TABLE(of, ov2659_of_match); 1511c4c0283aSBenoit Parrot #endif 1512c4c0283aSBenoit Parrot 1513c4c0283aSBenoit Parrot static struct i2c_driver ov2659_i2c_driver = { 1514c4c0283aSBenoit Parrot .driver = { 1515c4c0283aSBenoit Parrot .name = DRIVER_NAME, 1516c4c0283aSBenoit Parrot .of_match_table = of_match_ptr(ov2659_of_match), 1517c4c0283aSBenoit Parrot }, 1518c4c0283aSBenoit Parrot .probe = ov2659_probe, 1519c4c0283aSBenoit Parrot .remove = ov2659_remove, 1520c4c0283aSBenoit Parrot .id_table = ov2659_id, 1521c4c0283aSBenoit Parrot }; 1522c4c0283aSBenoit Parrot 1523c4c0283aSBenoit Parrot module_i2c_driver(ov2659_i2c_driver); 1524c4c0283aSBenoit Parrot 1525c4c0283aSBenoit Parrot MODULE_AUTHOR("Benoit Parrot <bparrot@ti.com>"); 1526c4c0283aSBenoit Parrot MODULE_DESCRIPTION("OV2659 CMOS Image Sensor driver"); 1527c4c0283aSBenoit Parrot MODULE_LICENSE("GPL v2"); 1528