1*9746b117SMartina Krasteva // SPDX-License-Identifier: GPL-2.0-only 2*9746b117SMartina Krasteva /* 3*9746b117SMartina Krasteva * Sony imx334 sensor driver 4*9746b117SMartina Krasteva * 5*9746b117SMartina Krasteva * Copyright (C) 2021 Intel Corporation 6*9746b117SMartina Krasteva */ 7*9746b117SMartina Krasteva #include <asm/unaligned.h> 8*9746b117SMartina Krasteva 9*9746b117SMartina Krasteva #include <linux/clk.h> 10*9746b117SMartina Krasteva #include <linux/delay.h> 11*9746b117SMartina Krasteva #include <linux/i2c.h> 12*9746b117SMartina Krasteva #include <linux/module.h> 13*9746b117SMartina Krasteva #include <linux/pm_runtime.h> 14*9746b117SMartina Krasteva 15*9746b117SMartina Krasteva #include <media/v4l2-ctrls.h> 16*9746b117SMartina Krasteva #include <media/v4l2-fwnode.h> 17*9746b117SMartina Krasteva #include <media/v4l2-subdev.h> 18*9746b117SMartina Krasteva 19*9746b117SMartina Krasteva /* Streaming Mode */ 20*9746b117SMartina Krasteva #define IMX334_REG_MODE_SELECT 0x3000 21*9746b117SMartina Krasteva #define IMX334_MODE_STANDBY 0x01 22*9746b117SMartina Krasteva #define IMX334_MODE_STREAMING 0x00 23*9746b117SMartina Krasteva 24*9746b117SMartina Krasteva /* Lines per frame */ 25*9746b117SMartina Krasteva #define IMX334_REG_LPFR 0x3030 26*9746b117SMartina Krasteva 27*9746b117SMartina Krasteva /* Chip ID */ 28*9746b117SMartina Krasteva #define IMX334_REG_ID 0x3044 29*9746b117SMartina Krasteva #define IMX334_ID 0x1e 30*9746b117SMartina Krasteva 31*9746b117SMartina Krasteva /* Exposure control */ 32*9746b117SMartina Krasteva #define IMX334_REG_SHUTTER 0x3058 33*9746b117SMartina Krasteva #define IMX334_EXPOSURE_MIN 1 34*9746b117SMartina Krasteva #define IMX334_EXPOSURE_OFFSET 5 35*9746b117SMartina Krasteva #define IMX334_EXPOSURE_STEP 1 36*9746b117SMartina Krasteva #define IMX334_EXPOSURE_DEFAULT 0x0648 37*9746b117SMartina Krasteva 38*9746b117SMartina Krasteva /* Analog gain control */ 39*9746b117SMartina Krasteva #define IMX334_REG_AGAIN 0x30e8 40*9746b117SMartina Krasteva #define IMX334_AGAIN_MIN 0 41*9746b117SMartina Krasteva #define IMX334_AGAIN_MAX 240 42*9746b117SMartina Krasteva #define IMX334_AGAIN_STEP 1 43*9746b117SMartina Krasteva #define IMX334_AGAIN_DEFAULT 0 44*9746b117SMartina Krasteva 45*9746b117SMartina Krasteva /* Group hold register */ 46*9746b117SMartina Krasteva #define IMX334_REG_HOLD 0x3001 47*9746b117SMartina Krasteva 48*9746b117SMartina Krasteva /* Input clock rate */ 49*9746b117SMartina Krasteva #define IMX334_INCLK_RATE 24000000 50*9746b117SMartina Krasteva 51*9746b117SMartina Krasteva /* CSI2 HW configuration */ 52*9746b117SMartina Krasteva #define IMX334_LINK_FREQ 891000000 53*9746b117SMartina Krasteva #define IMX334_NUM_DATA_LANES 4 54*9746b117SMartina Krasteva 55*9746b117SMartina Krasteva #define IMX334_REG_MIN 0x00 56*9746b117SMartina Krasteva #define IMX334_REG_MAX 0xfffff 57*9746b117SMartina Krasteva 58*9746b117SMartina Krasteva /** 59*9746b117SMartina Krasteva * struct imx334_reg - imx334 sensor register 60*9746b117SMartina Krasteva * @address: Register address 61*9746b117SMartina Krasteva * @val: Register value 62*9746b117SMartina Krasteva */ 63*9746b117SMartina Krasteva struct imx334_reg { 64*9746b117SMartina Krasteva u16 address; 65*9746b117SMartina Krasteva u8 val; 66*9746b117SMartina Krasteva }; 67*9746b117SMartina Krasteva 68*9746b117SMartina Krasteva /** 69*9746b117SMartina Krasteva * struct imx334_reg_list - imx334 sensor register list 70*9746b117SMartina Krasteva * @num_of_regs: Number of registers in the list 71*9746b117SMartina Krasteva * @regs: Pointer to register list 72*9746b117SMartina Krasteva */ 73*9746b117SMartina Krasteva struct imx334_reg_list { 74*9746b117SMartina Krasteva u32 num_of_regs; 75*9746b117SMartina Krasteva const struct imx334_reg *regs; 76*9746b117SMartina Krasteva }; 77*9746b117SMartina Krasteva 78*9746b117SMartina Krasteva /** 79*9746b117SMartina Krasteva * struct imx334_mode - imx334 sensor mode structure 80*9746b117SMartina Krasteva * @width: Frame width 81*9746b117SMartina Krasteva * @height: Frame height 82*9746b117SMartina Krasteva * @code: Format code 83*9746b117SMartina Krasteva * @hblank: Horizontal blanking in lines 84*9746b117SMartina Krasteva * @vblank: Vertical blanking in lines 85*9746b117SMartina Krasteva * @vblank_min: Minimal vertical blanking in lines 86*9746b117SMartina Krasteva * @vblank_max: Maximum vertical blanking in lines 87*9746b117SMartina Krasteva * @pclk: Sensor pixel clock 88*9746b117SMartina Krasteva * @link_freq_idx: Link frequency index 89*9746b117SMartina Krasteva * @reg_list: Register list for sensor mode 90*9746b117SMartina Krasteva */ 91*9746b117SMartina Krasteva struct imx334_mode { 92*9746b117SMartina Krasteva u32 width; 93*9746b117SMartina Krasteva u32 height; 94*9746b117SMartina Krasteva u32 code; 95*9746b117SMartina Krasteva u32 hblank; 96*9746b117SMartina Krasteva u32 vblank; 97*9746b117SMartina Krasteva u32 vblank_min; 98*9746b117SMartina Krasteva u32 vblank_max; 99*9746b117SMartina Krasteva u64 pclk; 100*9746b117SMartina Krasteva u32 link_freq_idx; 101*9746b117SMartina Krasteva struct imx334_reg_list reg_list; 102*9746b117SMartina Krasteva }; 103*9746b117SMartina Krasteva 104*9746b117SMartina Krasteva /** 105*9746b117SMartina Krasteva * struct imx334 - imx334 sensor device structure 106*9746b117SMartina Krasteva * @dev: Pointer to generic device 107*9746b117SMartina Krasteva * @client: Pointer to i2c client 108*9746b117SMartina Krasteva * @sd: V4L2 sub-device 109*9746b117SMartina Krasteva * @pad: Media pad. Only one pad supported 110*9746b117SMartina Krasteva * @reset_gpio: Sensor reset gpio 111*9746b117SMartina Krasteva * @inclk: Sensor input clock 112*9746b117SMartina Krasteva * @ctrl_handler: V4L2 control handler 113*9746b117SMartina Krasteva * @link_freq_ctrl: Pointer to link frequency control 114*9746b117SMartina Krasteva * @pclk_ctrl: Pointer to pixel clock control 115*9746b117SMartina Krasteva * @hblank_ctrl: Pointer to horizontal blanking control 116*9746b117SMartina Krasteva * @vblank_ctrl: Pointer to vertical blanking control 117*9746b117SMartina Krasteva * @exp_ctrl: Pointer to exposure control 118*9746b117SMartina Krasteva * @again_ctrl: Pointer to analog gain control 119*9746b117SMartina Krasteva * @vblank: Vertical blanking in lines 120*9746b117SMartina Krasteva * @cur_mode: Pointer to current selected sensor mode 121*9746b117SMartina Krasteva * @mutex: Mutex for serializing sensor controls 122*9746b117SMartina Krasteva * @streaming: Flag indicating streaming state 123*9746b117SMartina Krasteva */ 124*9746b117SMartina Krasteva struct imx334 { 125*9746b117SMartina Krasteva struct device *dev; 126*9746b117SMartina Krasteva struct i2c_client *client; 127*9746b117SMartina Krasteva struct v4l2_subdev sd; 128*9746b117SMartina Krasteva struct media_pad pad; 129*9746b117SMartina Krasteva struct gpio_desc *reset_gpio; 130*9746b117SMartina Krasteva struct clk *inclk; 131*9746b117SMartina Krasteva struct v4l2_ctrl_handler ctrl_handler; 132*9746b117SMartina Krasteva struct v4l2_ctrl *link_freq_ctrl; 133*9746b117SMartina Krasteva struct v4l2_ctrl *pclk_ctrl; 134*9746b117SMartina Krasteva struct v4l2_ctrl *hblank_ctrl; 135*9746b117SMartina Krasteva struct v4l2_ctrl *vblank_ctrl; 136*9746b117SMartina Krasteva struct { 137*9746b117SMartina Krasteva struct v4l2_ctrl *exp_ctrl; 138*9746b117SMartina Krasteva struct v4l2_ctrl *again_ctrl; 139*9746b117SMartina Krasteva }; 140*9746b117SMartina Krasteva u32 vblank; 141*9746b117SMartina Krasteva const struct imx334_mode *cur_mode; 142*9746b117SMartina Krasteva struct mutex mutex; 143*9746b117SMartina Krasteva bool streaming; 144*9746b117SMartina Krasteva }; 145*9746b117SMartina Krasteva 146*9746b117SMartina Krasteva static const s64 link_freq[] = { 147*9746b117SMartina Krasteva IMX334_LINK_FREQ, 148*9746b117SMartina Krasteva }; 149*9746b117SMartina Krasteva 150*9746b117SMartina Krasteva /* Sensor mode registers */ 151*9746b117SMartina Krasteva static const struct imx334_reg mode_3840x2160_regs[] = { 152*9746b117SMartina Krasteva {0x3000, 0x01}, 153*9746b117SMartina Krasteva {0x3002, 0x00}, 154*9746b117SMartina Krasteva {0x3018, 0x04}, 155*9746b117SMartina Krasteva {0x37b0, 0x36}, 156*9746b117SMartina Krasteva {0x304c, 0x00}, 157*9746b117SMartina Krasteva {0x300c, 0x3b}, 158*9746b117SMartina Krasteva {0x300d, 0x2a}, 159*9746b117SMartina Krasteva {0x3034, 0x26}, 160*9746b117SMartina Krasteva {0x3035, 0x02}, 161*9746b117SMartina Krasteva {0x314c, 0x29}, 162*9746b117SMartina Krasteva {0x314d, 0x01}, 163*9746b117SMartina Krasteva {0x315a, 0x02}, 164*9746b117SMartina Krasteva {0x3168, 0xa0}, 165*9746b117SMartina Krasteva {0x316a, 0x7e}, 166*9746b117SMartina Krasteva {0x3288, 0x21}, 167*9746b117SMartina Krasteva {0x328a, 0x02}, 168*9746b117SMartina Krasteva {0x302c, 0x3c}, 169*9746b117SMartina Krasteva {0x302e, 0x00}, 170*9746b117SMartina Krasteva {0x302f, 0x0f}, 171*9746b117SMartina Krasteva {0x3076, 0x70}, 172*9746b117SMartina Krasteva {0x3077, 0x08}, 173*9746b117SMartina Krasteva {0x3090, 0x70}, 174*9746b117SMartina Krasteva {0x3091, 0x08}, 175*9746b117SMartina Krasteva {0x30d8, 0x20}, 176*9746b117SMartina Krasteva {0x30d9, 0x12}, 177*9746b117SMartina Krasteva {0x3308, 0x70}, 178*9746b117SMartina Krasteva {0x3309, 0x08}, 179*9746b117SMartina Krasteva {0x3414, 0x05}, 180*9746b117SMartina Krasteva {0x3416, 0x18}, 181*9746b117SMartina Krasteva {0x35ac, 0x0e}, 182*9746b117SMartina Krasteva {0x3648, 0x01}, 183*9746b117SMartina Krasteva {0x364a, 0x04}, 184*9746b117SMartina Krasteva {0x364c, 0x04}, 185*9746b117SMartina Krasteva {0x3678, 0x01}, 186*9746b117SMartina Krasteva {0x367c, 0x31}, 187*9746b117SMartina Krasteva {0x367e, 0x31}, 188*9746b117SMartina Krasteva {0x3708, 0x02}, 189*9746b117SMartina Krasteva {0x3714, 0x01}, 190*9746b117SMartina Krasteva {0x3715, 0x02}, 191*9746b117SMartina Krasteva {0x3716, 0x02}, 192*9746b117SMartina Krasteva {0x3717, 0x02}, 193*9746b117SMartina Krasteva {0x371c, 0x3d}, 194*9746b117SMartina Krasteva {0x371d, 0x3f}, 195*9746b117SMartina Krasteva {0x372c, 0x00}, 196*9746b117SMartina Krasteva {0x372d, 0x00}, 197*9746b117SMartina Krasteva {0x372e, 0x46}, 198*9746b117SMartina Krasteva {0x372f, 0x00}, 199*9746b117SMartina Krasteva {0x3730, 0x89}, 200*9746b117SMartina Krasteva {0x3731, 0x00}, 201*9746b117SMartina Krasteva {0x3732, 0x08}, 202*9746b117SMartina Krasteva {0x3733, 0x01}, 203*9746b117SMartina Krasteva {0x3734, 0xfe}, 204*9746b117SMartina Krasteva {0x3735, 0x05}, 205*9746b117SMartina Krasteva {0x375d, 0x00}, 206*9746b117SMartina Krasteva {0x375e, 0x00}, 207*9746b117SMartina Krasteva {0x375f, 0x61}, 208*9746b117SMartina Krasteva {0x3760, 0x06}, 209*9746b117SMartina Krasteva {0x3768, 0x1b}, 210*9746b117SMartina Krasteva {0x3769, 0x1b}, 211*9746b117SMartina Krasteva {0x376a, 0x1a}, 212*9746b117SMartina Krasteva {0x376b, 0x19}, 213*9746b117SMartina Krasteva {0x376c, 0x18}, 214*9746b117SMartina Krasteva {0x376d, 0x14}, 215*9746b117SMartina Krasteva {0x376e, 0x0f}, 216*9746b117SMartina Krasteva {0x3776, 0x00}, 217*9746b117SMartina Krasteva {0x3777, 0x00}, 218*9746b117SMartina Krasteva {0x3778, 0x46}, 219*9746b117SMartina Krasteva {0x3779, 0x00}, 220*9746b117SMartina Krasteva {0x377a, 0x08}, 221*9746b117SMartina Krasteva {0x377b, 0x01}, 222*9746b117SMartina Krasteva {0x377c, 0x45}, 223*9746b117SMartina Krasteva {0x377d, 0x01}, 224*9746b117SMartina Krasteva {0x377e, 0x23}, 225*9746b117SMartina Krasteva {0x377f, 0x02}, 226*9746b117SMartina Krasteva {0x3780, 0xd9}, 227*9746b117SMartina Krasteva {0x3781, 0x03}, 228*9746b117SMartina Krasteva {0x3782, 0xf5}, 229*9746b117SMartina Krasteva {0x3783, 0x06}, 230*9746b117SMartina Krasteva {0x3784, 0xa5}, 231*9746b117SMartina Krasteva {0x3788, 0x0f}, 232*9746b117SMartina Krasteva {0x378a, 0xd9}, 233*9746b117SMartina Krasteva {0x378b, 0x03}, 234*9746b117SMartina Krasteva {0x378c, 0xeb}, 235*9746b117SMartina Krasteva {0x378d, 0x05}, 236*9746b117SMartina Krasteva {0x378e, 0x87}, 237*9746b117SMartina Krasteva {0x378f, 0x06}, 238*9746b117SMartina Krasteva {0x3790, 0xf5}, 239*9746b117SMartina Krasteva {0x3792, 0x43}, 240*9746b117SMartina Krasteva {0x3794, 0x7a}, 241*9746b117SMartina Krasteva {0x3796, 0xa1}, 242*9746b117SMartina Krasteva {0x3e04, 0x0e}, 243*9746b117SMartina Krasteva {0x3a00, 0x01}, 244*9746b117SMartina Krasteva }; 245*9746b117SMartina Krasteva 246*9746b117SMartina Krasteva /* Supported sensor mode configurations */ 247*9746b117SMartina Krasteva static const struct imx334_mode supported_mode = { 248*9746b117SMartina Krasteva .width = 3840, 249*9746b117SMartina Krasteva .height = 2160, 250*9746b117SMartina Krasteva .hblank = 560, 251*9746b117SMartina Krasteva .vblank = 2340, 252*9746b117SMartina Krasteva .vblank_min = 90, 253*9746b117SMartina Krasteva .vblank_max = 132840, 254*9746b117SMartina Krasteva .pclk = 594000000, 255*9746b117SMartina Krasteva .link_freq_idx = 0, 256*9746b117SMartina Krasteva .code = MEDIA_BUS_FMT_SRGGB12_1X12, 257*9746b117SMartina Krasteva .reg_list = { 258*9746b117SMartina Krasteva .num_of_regs = ARRAY_SIZE(mode_3840x2160_regs), 259*9746b117SMartina Krasteva .regs = mode_3840x2160_regs, 260*9746b117SMartina Krasteva }, 261*9746b117SMartina Krasteva }; 262*9746b117SMartina Krasteva 263*9746b117SMartina Krasteva /** 264*9746b117SMartina Krasteva * to_imx334() - imv334 V4L2 sub-device to imx334 device. 265*9746b117SMartina Krasteva * @subdev: pointer to imx334 V4L2 sub-device 266*9746b117SMartina Krasteva * 267*9746b117SMartina Krasteva * Return: pointer to imx334 device 268*9746b117SMartina Krasteva */ 269*9746b117SMartina Krasteva static inline struct imx334 *to_imx334(struct v4l2_subdev *subdev) 270*9746b117SMartina Krasteva { 271*9746b117SMartina Krasteva return container_of(subdev, struct imx334, sd); 272*9746b117SMartina Krasteva } 273*9746b117SMartina Krasteva 274*9746b117SMartina Krasteva /** 275*9746b117SMartina Krasteva * imx334_read_reg() - Read registers. 276*9746b117SMartina Krasteva * @imx334: pointer to imx334 device 277*9746b117SMartina Krasteva * @reg: register address 278*9746b117SMartina Krasteva * @len: length of bytes to read. Max supported bytes is 4 279*9746b117SMartina Krasteva * @val: pointer to register value to be filled. 280*9746b117SMartina Krasteva * 281*9746b117SMartina Krasteva * Big endian register addresses with little endian values. 282*9746b117SMartina Krasteva * 283*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 284*9746b117SMartina Krasteva */ 285*9746b117SMartina Krasteva static int imx334_read_reg(struct imx334 *imx334, u16 reg, u32 len, u32 *val) 286*9746b117SMartina Krasteva { 287*9746b117SMartina Krasteva struct i2c_client *client = v4l2_get_subdevdata(&imx334->sd); 288*9746b117SMartina Krasteva struct i2c_msg msgs[2] = {0}; 289*9746b117SMartina Krasteva u8 addr_buf[2] = {0}; 290*9746b117SMartina Krasteva u8 data_buf[4] = {0}; 291*9746b117SMartina Krasteva int ret; 292*9746b117SMartina Krasteva 293*9746b117SMartina Krasteva if (WARN_ON(len > 4)) 294*9746b117SMartina Krasteva return -EINVAL; 295*9746b117SMartina Krasteva 296*9746b117SMartina Krasteva put_unaligned_be16(reg, addr_buf); 297*9746b117SMartina Krasteva 298*9746b117SMartina Krasteva /* Write register address */ 299*9746b117SMartina Krasteva msgs[0].addr = client->addr; 300*9746b117SMartina Krasteva msgs[0].flags = 0; 301*9746b117SMartina Krasteva msgs[0].len = ARRAY_SIZE(addr_buf); 302*9746b117SMartina Krasteva msgs[0].buf = addr_buf; 303*9746b117SMartina Krasteva 304*9746b117SMartina Krasteva /* Read data from register */ 305*9746b117SMartina Krasteva msgs[1].addr = client->addr; 306*9746b117SMartina Krasteva msgs[1].flags = I2C_M_RD; 307*9746b117SMartina Krasteva msgs[1].len = len; 308*9746b117SMartina Krasteva msgs[1].buf = data_buf; 309*9746b117SMartina Krasteva 310*9746b117SMartina Krasteva ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 311*9746b117SMartina Krasteva if (ret != ARRAY_SIZE(msgs)) 312*9746b117SMartina Krasteva return -EIO; 313*9746b117SMartina Krasteva 314*9746b117SMartina Krasteva *val = get_unaligned_le32(data_buf); 315*9746b117SMartina Krasteva 316*9746b117SMartina Krasteva return 0; 317*9746b117SMartina Krasteva } 318*9746b117SMartina Krasteva 319*9746b117SMartina Krasteva /** 320*9746b117SMartina Krasteva * imx334_write_reg() - Write register 321*9746b117SMartina Krasteva * @imx334: pointer to imx334 device 322*9746b117SMartina Krasteva * @reg: register address 323*9746b117SMartina Krasteva * @len: length of bytes. Max supported bytes is 4 324*9746b117SMartina Krasteva * @val: register value 325*9746b117SMartina Krasteva * 326*9746b117SMartina Krasteva * Big endian register addresses with little endian values. 327*9746b117SMartina Krasteva * 328*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 329*9746b117SMartina Krasteva */ 330*9746b117SMartina Krasteva static int imx334_write_reg(struct imx334 *imx334, u16 reg, u32 len, u32 val) 331*9746b117SMartina Krasteva { 332*9746b117SMartina Krasteva struct i2c_client *client = v4l2_get_subdevdata(&imx334->sd); 333*9746b117SMartina Krasteva u8 buf[6] = {0}; 334*9746b117SMartina Krasteva 335*9746b117SMartina Krasteva if (WARN_ON(len > 4)) 336*9746b117SMartina Krasteva return -EINVAL; 337*9746b117SMartina Krasteva 338*9746b117SMartina Krasteva put_unaligned_be16(reg, buf); 339*9746b117SMartina Krasteva put_unaligned_le32(val, buf + 2); 340*9746b117SMartina Krasteva if (i2c_master_send(client, buf, len + 2) != len + 2) 341*9746b117SMartina Krasteva return -EIO; 342*9746b117SMartina Krasteva 343*9746b117SMartina Krasteva return 0; 344*9746b117SMartina Krasteva } 345*9746b117SMartina Krasteva 346*9746b117SMartina Krasteva /** 347*9746b117SMartina Krasteva * imx334_write_regs() - Write a list of registers 348*9746b117SMartina Krasteva * @imx334: pointer to imx334 device 349*9746b117SMartina Krasteva * @regs: list of registers to be written 350*9746b117SMartina Krasteva * @len: length of registers array 351*9746b117SMartina Krasteva * 352*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 353*9746b117SMartina Krasteva */ 354*9746b117SMartina Krasteva static int imx334_write_regs(struct imx334 *imx334, 355*9746b117SMartina Krasteva const struct imx334_reg *regs, u32 len) 356*9746b117SMartina Krasteva { 357*9746b117SMartina Krasteva unsigned int i; 358*9746b117SMartina Krasteva int ret; 359*9746b117SMartina Krasteva 360*9746b117SMartina Krasteva for (i = 0; i < len; i++) { 361*9746b117SMartina Krasteva ret = imx334_write_reg(imx334, regs[i].address, 1, regs[i].val); 362*9746b117SMartina Krasteva if (ret) 363*9746b117SMartina Krasteva return ret; 364*9746b117SMartina Krasteva } 365*9746b117SMartina Krasteva 366*9746b117SMartina Krasteva return 0; 367*9746b117SMartina Krasteva } 368*9746b117SMartina Krasteva 369*9746b117SMartina Krasteva /** 370*9746b117SMartina Krasteva * imx334_update_controls() - Update control ranges based on streaming mode 371*9746b117SMartina Krasteva * @imx334: pointer to imx334 device 372*9746b117SMartina Krasteva * @mode: pointer to imx334_mode sensor mode 373*9746b117SMartina Krasteva * 374*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 375*9746b117SMartina Krasteva */ 376*9746b117SMartina Krasteva static int imx334_update_controls(struct imx334 *imx334, 377*9746b117SMartina Krasteva const struct imx334_mode *mode) 378*9746b117SMartina Krasteva { 379*9746b117SMartina Krasteva int ret; 380*9746b117SMartina Krasteva 381*9746b117SMartina Krasteva ret = __v4l2_ctrl_s_ctrl(imx334->link_freq_ctrl, mode->link_freq_idx); 382*9746b117SMartina Krasteva if (ret) 383*9746b117SMartina Krasteva return ret; 384*9746b117SMartina Krasteva 385*9746b117SMartina Krasteva ret = __v4l2_ctrl_s_ctrl(imx334->hblank_ctrl, mode->hblank); 386*9746b117SMartina Krasteva if (ret) 387*9746b117SMartina Krasteva return ret; 388*9746b117SMartina Krasteva 389*9746b117SMartina Krasteva return __v4l2_ctrl_modify_range(imx334->vblank_ctrl, mode->vblank_min, 390*9746b117SMartina Krasteva mode->vblank_max, 1, mode->vblank); 391*9746b117SMartina Krasteva } 392*9746b117SMartina Krasteva 393*9746b117SMartina Krasteva /** 394*9746b117SMartina Krasteva * imx334_update_exp_gain() - Set updated exposure and gain 395*9746b117SMartina Krasteva * @imx334: pointer to imx334 device 396*9746b117SMartina Krasteva * @exposure: updated exposure value 397*9746b117SMartina Krasteva * @gain: updated analog gain value 398*9746b117SMartina Krasteva * 399*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 400*9746b117SMartina Krasteva */ 401*9746b117SMartina Krasteva static int imx334_update_exp_gain(struct imx334 *imx334, u32 exposure, u32 gain) 402*9746b117SMartina Krasteva { 403*9746b117SMartina Krasteva u32 lpfr, shutter; 404*9746b117SMartina Krasteva int ret; 405*9746b117SMartina Krasteva 406*9746b117SMartina Krasteva lpfr = imx334->vblank + imx334->cur_mode->height; 407*9746b117SMartina Krasteva shutter = lpfr - exposure; 408*9746b117SMartina Krasteva 409*9746b117SMartina Krasteva dev_dbg(imx334->dev, "Set long exp %u analog gain %u sh0 %u lpfr %u", 410*9746b117SMartina Krasteva exposure, gain, shutter, lpfr); 411*9746b117SMartina Krasteva 412*9746b117SMartina Krasteva ret = imx334_write_reg(imx334, IMX334_REG_HOLD, 1, 1); 413*9746b117SMartina Krasteva if (ret) 414*9746b117SMartina Krasteva return ret; 415*9746b117SMartina Krasteva 416*9746b117SMartina Krasteva ret = imx334_write_reg(imx334, IMX334_REG_LPFR, 3, lpfr); 417*9746b117SMartina Krasteva if (ret) 418*9746b117SMartina Krasteva goto error_release_group_hold; 419*9746b117SMartina Krasteva 420*9746b117SMartina Krasteva ret = imx334_write_reg(imx334, IMX334_REG_SHUTTER, 3, shutter); 421*9746b117SMartina Krasteva if (ret) 422*9746b117SMartina Krasteva goto error_release_group_hold; 423*9746b117SMartina Krasteva 424*9746b117SMartina Krasteva ret = imx334_write_reg(imx334, IMX334_REG_AGAIN, 1, gain); 425*9746b117SMartina Krasteva 426*9746b117SMartina Krasteva error_release_group_hold: 427*9746b117SMartina Krasteva imx334_write_reg(imx334, IMX334_REG_HOLD, 1, 0); 428*9746b117SMartina Krasteva 429*9746b117SMartina Krasteva return ret; 430*9746b117SMartina Krasteva } 431*9746b117SMartina Krasteva 432*9746b117SMartina Krasteva /** 433*9746b117SMartina Krasteva * imx334_set_ctrl() - Set subdevice control 434*9746b117SMartina Krasteva * @ctrl: pointer to v4l2_ctrl structure 435*9746b117SMartina Krasteva * 436*9746b117SMartina Krasteva * Supported controls: 437*9746b117SMartina Krasteva * - V4L2_CID_VBLANK 438*9746b117SMartina Krasteva * - cluster controls: 439*9746b117SMartina Krasteva * - V4L2_CID_ANALOGUE_GAIN 440*9746b117SMartina Krasteva * - V4L2_CID_EXPOSURE 441*9746b117SMartina Krasteva * 442*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 443*9746b117SMartina Krasteva */ 444*9746b117SMartina Krasteva static int imx334_set_ctrl(struct v4l2_ctrl *ctrl) 445*9746b117SMartina Krasteva { 446*9746b117SMartina Krasteva struct imx334 *imx334 = 447*9746b117SMartina Krasteva container_of(ctrl->handler, struct imx334, ctrl_handler); 448*9746b117SMartina Krasteva u32 analog_gain; 449*9746b117SMartina Krasteva u32 exposure; 450*9746b117SMartina Krasteva int ret; 451*9746b117SMartina Krasteva 452*9746b117SMartina Krasteva switch (ctrl->id) { 453*9746b117SMartina Krasteva case V4L2_CID_VBLANK: 454*9746b117SMartina Krasteva imx334->vblank = imx334->vblank_ctrl->val; 455*9746b117SMartina Krasteva 456*9746b117SMartina Krasteva dev_dbg(imx334->dev, "Received vblank %u, new lpfr %u", 457*9746b117SMartina Krasteva imx334->vblank, 458*9746b117SMartina Krasteva imx334->vblank + imx334->cur_mode->height); 459*9746b117SMartina Krasteva 460*9746b117SMartina Krasteva ret = __v4l2_ctrl_modify_range(imx334->exp_ctrl, 461*9746b117SMartina Krasteva IMX334_EXPOSURE_MIN, 462*9746b117SMartina Krasteva imx334->vblank + 463*9746b117SMartina Krasteva imx334->cur_mode->height - 464*9746b117SMartina Krasteva IMX334_EXPOSURE_OFFSET, 465*9746b117SMartina Krasteva 1, IMX334_EXPOSURE_DEFAULT); 466*9746b117SMartina Krasteva break; 467*9746b117SMartina Krasteva case V4L2_CID_EXPOSURE: 468*9746b117SMartina Krasteva 469*9746b117SMartina Krasteva /* Set controls only if sensor is in power on state */ 470*9746b117SMartina Krasteva if (!pm_runtime_get_if_in_use(imx334->dev)) 471*9746b117SMartina Krasteva return 0; 472*9746b117SMartina Krasteva 473*9746b117SMartina Krasteva exposure = ctrl->val; 474*9746b117SMartina Krasteva analog_gain = imx334->again_ctrl->val; 475*9746b117SMartina Krasteva 476*9746b117SMartina Krasteva dev_dbg(imx334->dev, "Received exp %u analog gain %u", 477*9746b117SMartina Krasteva exposure, analog_gain); 478*9746b117SMartina Krasteva 479*9746b117SMartina Krasteva ret = imx334_update_exp_gain(imx334, exposure, analog_gain); 480*9746b117SMartina Krasteva 481*9746b117SMartina Krasteva pm_runtime_put(imx334->dev); 482*9746b117SMartina Krasteva 483*9746b117SMartina Krasteva break; 484*9746b117SMartina Krasteva default: 485*9746b117SMartina Krasteva dev_err(imx334->dev, "Invalid control %d", ctrl->id); 486*9746b117SMartina Krasteva ret = -EINVAL; 487*9746b117SMartina Krasteva } 488*9746b117SMartina Krasteva 489*9746b117SMartina Krasteva return ret; 490*9746b117SMartina Krasteva } 491*9746b117SMartina Krasteva 492*9746b117SMartina Krasteva /* V4l2 subdevice control ops*/ 493*9746b117SMartina Krasteva static const struct v4l2_ctrl_ops imx334_ctrl_ops = { 494*9746b117SMartina Krasteva .s_ctrl = imx334_set_ctrl, 495*9746b117SMartina Krasteva }; 496*9746b117SMartina Krasteva 497*9746b117SMartina Krasteva /** 498*9746b117SMartina Krasteva * imx334_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes 499*9746b117SMartina Krasteva * @sd: pointer to imx334 V4L2 sub-device structure 500*9746b117SMartina Krasteva * @cfg: V4L2 sub-device pad configuration 501*9746b117SMartina Krasteva * @code: V4L2 sub-device code enumeration need to be filled 502*9746b117SMartina Krasteva * 503*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 504*9746b117SMartina Krasteva */ 505*9746b117SMartina Krasteva static int imx334_enum_mbus_code(struct v4l2_subdev *sd, 506*9746b117SMartina Krasteva struct v4l2_subdev_pad_config *cfg, 507*9746b117SMartina Krasteva struct v4l2_subdev_mbus_code_enum *code) 508*9746b117SMartina Krasteva { 509*9746b117SMartina Krasteva if (code->index > 0) 510*9746b117SMartina Krasteva return -EINVAL; 511*9746b117SMartina Krasteva 512*9746b117SMartina Krasteva code->code = supported_mode.code; 513*9746b117SMartina Krasteva 514*9746b117SMartina Krasteva return 0; 515*9746b117SMartina Krasteva } 516*9746b117SMartina Krasteva 517*9746b117SMartina Krasteva /** 518*9746b117SMartina Krasteva * imx334_enum_frame_size() - Enumerate V4L2 sub-device frame sizes 519*9746b117SMartina Krasteva * @sd: pointer to imx334 V4L2 sub-device structure 520*9746b117SMartina Krasteva * @cfg: V4L2 sub-device pad configuration 521*9746b117SMartina Krasteva * @fsize: V4L2 sub-device size enumeration need to be filled 522*9746b117SMartina Krasteva * 523*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 524*9746b117SMartina Krasteva */ 525*9746b117SMartina Krasteva static int imx334_enum_frame_size(struct v4l2_subdev *sd, 526*9746b117SMartina Krasteva struct v4l2_subdev_pad_config *cfg, 527*9746b117SMartina Krasteva struct v4l2_subdev_frame_size_enum *fsize) 528*9746b117SMartina Krasteva { 529*9746b117SMartina Krasteva if (fsize->index > 0) 530*9746b117SMartina Krasteva return -EINVAL; 531*9746b117SMartina Krasteva 532*9746b117SMartina Krasteva if (fsize->code != supported_mode.code) 533*9746b117SMartina Krasteva return -EINVAL; 534*9746b117SMartina Krasteva 535*9746b117SMartina Krasteva fsize->min_width = supported_mode.width; 536*9746b117SMartina Krasteva fsize->max_width = fsize->min_width; 537*9746b117SMartina Krasteva fsize->min_height = supported_mode.height; 538*9746b117SMartina Krasteva fsize->max_height = fsize->min_height; 539*9746b117SMartina Krasteva 540*9746b117SMartina Krasteva return 0; 541*9746b117SMartina Krasteva } 542*9746b117SMartina Krasteva 543*9746b117SMartina Krasteva /** 544*9746b117SMartina Krasteva * imx334_fill_pad_format() - Fill subdevice pad format 545*9746b117SMartina Krasteva * from selected sensor mode 546*9746b117SMartina Krasteva * @imx334: pointer to imx334 device 547*9746b117SMartina Krasteva * @mode: pointer to imx334_mode sensor mode 548*9746b117SMartina Krasteva * @fmt: V4L2 sub-device format need to be filled 549*9746b117SMartina Krasteva */ 550*9746b117SMartina Krasteva static void imx334_fill_pad_format(struct imx334 *imx334, 551*9746b117SMartina Krasteva const struct imx334_mode *mode, 552*9746b117SMartina Krasteva struct v4l2_subdev_format *fmt) 553*9746b117SMartina Krasteva { 554*9746b117SMartina Krasteva fmt->format.width = mode->width; 555*9746b117SMartina Krasteva fmt->format.height = mode->height; 556*9746b117SMartina Krasteva fmt->format.code = mode->code; 557*9746b117SMartina Krasteva fmt->format.field = V4L2_FIELD_NONE; 558*9746b117SMartina Krasteva fmt->format.colorspace = V4L2_COLORSPACE_RAW; 559*9746b117SMartina Krasteva fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 560*9746b117SMartina Krasteva fmt->format.quantization = V4L2_QUANTIZATION_DEFAULT; 561*9746b117SMartina Krasteva fmt->format.xfer_func = V4L2_XFER_FUNC_NONE; 562*9746b117SMartina Krasteva } 563*9746b117SMartina Krasteva 564*9746b117SMartina Krasteva /** 565*9746b117SMartina Krasteva * imx334_get_pad_format() - Get subdevice pad format 566*9746b117SMartina Krasteva * @sd: pointer to imx334 V4L2 sub-device structure 567*9746b117SMartina Krasteva * @cfg: V4L2 sub-device pad configuration 568*9746b117SMartina Krasteva * @fmt: V4L2 sub-device format need to be set 569*9746b117SMartina Krasteva * 570*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 571*9746b117SMartina Krasteva */ 572*9746b117SMartina Krasteva static int imx334_get_pad_format(struct v4l2_subdev *sd, 573*9746b117SMartina Krasteva struct v4l2_subdev_pad_config *cfg, 574*9746b117SMartina Krasteva struct v4l2_subdev_format *fmt) 575*9746b117SMartina Krasteva { 576*9746b117SMartina Krasteva struct imx334 *imx334 = to_imx334(sd); 577*9746b117SMartina Krasteva 578*9746b117SMartina Krasteva mutex_lock(&imx334->mutex); 579*9746b117SMartina Krasteva 580*9746b117SMartina Krasteva if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { 581*9746b117SMartina Krasteva struct v4l2_mbus_framefmt *framefmt; 582*9746b117SMartina Krasteva 583*9746b117SMartina Krasteva framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); 584*9746b117SMartina Krasteva fmt->format = *framefmt; 585*9746b117SMartina Krasteva } else { 586*9746b117SMartina Krasteva imx334_fill_pad_format(imx334, imx334->cur_mode, fmt); 587*9746b117SMartina Krasteva } 588*9746b117SMartina Krasteva 589*9746b117SMartina Krasteva mutex_unlock(&imx334->mutex); 590*9746b117SMartina Krasteva 591*9746b117SMartina Krasteva return 0; 592*9746b117SMartina Krasteva } 593*9746b117SMartina Krasteva 594*9746b117SMartina Krasteva /** 595*9746b117SMartina Krasteva * imx334_set_pad_format() - Set subdevice pad format 596*9746b117SMartina Krasteva * @sd: pointer to imx334 V4L2 sub-device structure 597*9746b117SMartina Krasteva * @cfg: V4L2 sub-device pad configuration 598*9746b117SMartina Krasteva * @fmt: V4L2 sub-device format need to be set 599*9746b117SMartina Krasteva * 600*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 601*9746b117SMartina Krasteva */ 602*9746b117SMartina Krasteva static int imx334_set_pad_format(struct v4l2_subdev *sd, 603*9746b117SMartina Krasteva struct v4l2_subdev_pad_config *cfg, 604*9746b117SMartina Krasteva struct v4l2_subdev_format *fmt) 605*9746b117SMartina Krasteva { 606*9746b117SMartina Krasteva struct imx334 *imx334 = to_imx334(sd); 607*9746b117SMartina Krasteva const struct imx334_mode *mode; 608*9746b117SMartina Krasteva int ret = 0; 609*9746b117SMartina Krasteva 610*9746b117SMartina Krasteva mutex_lock(&imx334->mutex); 611*9746b117SMartina Krasteva 612*9746b117SMartina Krasteva mode = &supported_mode; 613*9746b117SMartina Krasteva imx334_fill_pad_format(imx334, mode, fmt); 614*9746b117SMartina Krasteva 615*9746b117SMartina Krasteva if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { 616*9746b117SMartina Krasteva struct v4l2_mbus_framefmt *framefmt; 617*9746b117SMartina Krasteva 618*9746b117SMartina Krasteva framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); 619*9746b117SMartina Krasteva *framefmt = fmt->format; 620*9746b117SMartina Krasteva } else { 621*9746b117SMartina Krasteva ret = imx334_update_controls(imx334, mode); 622*9746b117SMartina Krasteva if (!ret) 623*9746b117SMartina Krasteva imx334->cur_mode = mode; 624*9746b117SMartina Krasteva } 625*9746b117SMartina Krasteva 626*9746b117SMartina Krasteva mutex_unlock(&imx334->mutex); 627*9746b117SMartina Krasteva 628*9746b117SMartina Krasteva return ret; 629*9746b117SMartina Krasteva } 630*9746b117SMartina Krasteva 631*9746b117SMartina Krasteva /** 632*9746b117SMartina Krasteva * imx334_init_pad_cfg() - Initialize sub-device pad configuration 633*9746b117SMartina Krasteva * @sd: pointer to imx334 V4L2 sub-device structure 634*9746b117SMartina Krasteva * @cfg: V4L2 sub-device pad configuration 635*9746b117SMartina Krasteva * 636*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 637*9746b117SMartina Krasteva */ 638*9746b117SMartina Krasteva static int imx334_init_pad_cfg(struct v4l2_subdev *sd, 639*9746b117SMartina Krasteva struct v4l2_subdev_pad_config *cfg) 640*9746b117SMartina Krasteva { 641*9746b117SMartina Krasteva struct imx334 *imx334 = to_imx334(sd); 642*9746b117SMartina Krasteva struct v4l2_subdev_format fmt = { 0 }; 643*9746b117SMartina Krasteva 644*9746b117SMartina Krasteva fmt.which = cfg ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; 645*9746b117SMartina Krasteva imx334_fill_pad_format(imx334, &supported_mode, &fmt); 646*9746b117SMartina Krasteva 647*9746b117SMartina Krasteva return imx334_set_pad_format(sd, cfg, &fmt); 648*9746b117SMartina Krasteva } 649*9746b117SMartina Krasteva 650*9746b117SMartina Krasteva /** 651*9746b117SMartina Krasteva * imx334_start_streaming() - Start sensor stream 652*9746b117SMartina Krasteva * @imx334: pointer to imx334 device 653*9746b117SMartina Krasteva * 654*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 655*9746b117SMartina Krasteva */ 656*9746b117SMartina Krasteva static int imx334_start_streaming(struct imx334 *imx334) 657*9746b117SMartina Krasteva { 658*9746b117SMartina Krasteva const struct imx334_reg_list *reg_list; 659*9746b117SMartina Krasteva int ret; 660*9746b117SMartina Krasteva 661*9746b117SMartina Krasteva /* Write sensor mode registers */ 662*9746b117SMartina Krasteva reg_list = &imx334->cur_mode->reg_list; 663*9746b117SMartina Krasteva ret = imx334_write_regs(imx334, reg_list->regs, 664*9746b117SMartina Krasteva reg_list->num_of_regs); 665*9746b117SMartina Krasteva if (ret) { 666*9746b117SMartina Krasteva dev_err(imx334->dev, "fail to write initial registers"); 667*9746b117SMartina Krasteva return ret; 668*9746b117SMartina Krasteva } 669*9746b117SMartina Krasteva 670*9746b117SMartina Krasteva /* Setup handler will write actual exposure and gain */ 671*9746b117SMartina Krasteva ret = __v4l2_ctrl_handler_setup(imx334->sd.ctrl_handler); 672*9746b117SMartina Krasteva if (ret) { 673*9746b117SMartina Krasteva dev_err(imx334->dev, "fail to setup handler"); 674*9746b117SMartina Krasteva return ret; 675*9746b117SMartina Krasteva } 676*9746b117SMartina Krasteva 677*9746b117SMartina Krasteva /* Start streaming */ 678*9746b117SMartina Krasteva ret = imx334_write_reg(imx334, IMX334_REG_MODE_SELECT, 679*9746b117SMartina Krasteva 1, IMX334_MODE_STREAMING); 680*9746b117SMartina Krasteva if (ret) { 681*9746b117SMartina Krasteva dev_err(imx334->dev, "fail to start streaming"); 682*9746b117SMartina Krasteva return ret; 683*9746b117SMartina Krasteva } 684*9746b117SMartina Krasteva 685*9746b117SMartina Krasteva return 0; 686*9746b117SMartina Krasteva } 687*9746b117SMartina Krasteva 688*9746b117SMartina Krasteva /** 689*9746b117SMartina Krasteva * imx334_stop_streaming() - Stop sensor stream 690*9746b117SMartina Krasteva * @imx334: pointer to imx334 device 691*9746b117SMartina Krasteva * 692*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 693*9746b117SMartina Krasteva */ 694*9746b117SMartina Krasteva static int imx334_stop_streaming(struct imx334 *imx334) 695*9746b117SMartina Krasteva { 696*9746b117SMartina Krasteva return imx334_write_reg(imx334, IMX334_REG_MODE_SELECT, 697*9746b117SMartina Krasteva 1, IMX334_MODE_STANDBY); 698*9746b117SMartina Krasteva } 699*9746b117SMartina Krasteva 700*9746b117SMartina Krasteva /** 701*9746b117SMartina Krasteva * imx334_set_stream() - Enable sensor streaming 702*9746b117SMartina Krasteva * @sd: pointer to imx334 subdevice 703*9746b117SMartina Krasteva * @enable: set to enable sensor streaming 704*9746b117SMartina Krasteva * 705*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 706*9746b117SMartina Krasteva */ 707*9746b117SMartina Krasteva static int imx334_set_stream(struct v4l2_subdev *sd, int enable) 708*9746b117SMartina Krasteva { 709*9746b117SMartina Krasteva struct imx334 *imx334 = to_imx334(sd); 710*9746b117SMartina Krasteva int ret; 711*9746b117SMartina Krasteva 712*9746b117SMartina Krasteva mutex_lock(&imx334->mutex); 713*9746b117SMartina Krasteva 714*9746b117SMartina Krasteva if (imx334->streaming == enable) { 715*9746b117SMartina Krasteva mutex_unlock(&imx334->mutex); 716*9746b117SMartina Krasteva return 0; 717*9746b117SMartina Krasteva } 718*9746b117SMartina Krasteva 719*9746b117SMartina Krasteva if (enable) { 720*9746b117SMartina Krasteva ret = pm_runtime_get_sync(imx334->dev); 721*9746b117SMartina Krasteva if (ret) 722*9746b117SMartina Krasteva goto error_power_off; 723*9746b117SMartina Krasteva 724*9746b117SMartina Krasteva ret = imx334_start_streaming(imx334); 725*9746b117SMartina Krasteva if (ret) 726*9746b117SMartina Krasteva goto error_power_off; 727*9746b117SMartina Krasteva } else { 728*9746b117SMartina Krasteva imx334_stop_streaming(imx334); 729*9746b117SMartina Krasteva pm_runtime_put(imx334->dev); 730*9746b117SMartina Krasteva } 731*9746b117SMartina Krasteva 732*9746b117SMartina Krasteva imx334->streaming = enable; 733*9746b117SMartina Krasteva 734*9746b117SMartina Krasteva mutex_unlock(&imx334->mutex); 735*9746b117SMartina Krasteva 736*9746b117SMartina Krasteva return 0; 737*9746b117SMartina Krasteva 738*9746b117SMartina Krasteva error_power_off: 739*9746b117SMartina Krasteva pm_runtime_put(imx334->dev); 740*9746b117SMartina Krasteva mutex_unlock(&imx334->mutex); 741*9746b117SMartina Krasteva 742*9746b117SMartina Krasteva return ret; 743*9746b117SMartina Krasteva } 744*9746b117SMartina Krasteva 745*9746b117SMartina Krasteva /** 746*9746b117SMartina Krasteva * imx334_detect() - Detect imx334 sensor 747*9746b117SMartina Krasteva * @imx334: pointer to imx334 device 748*9746b117SMartina Krasteva * 749*9746b117SMartina Krasteva * Return: 0 if successful, -EIO if sensor id does not match 750*9746b117SMartina Krasteva */ 751*9746b117SMartina Krasteva static int imx334_detect(struct imx334 *imx334) 752*9746b117SMartina Krasteva { 753*9746b117SMartina Krasteva int ret; 754*9746b117SMartina Krasteva u32 val; 755*9746b117SMartina Krasteva 756*9746b117SMartina Krasteva ret = imx334_read_reg(imx334, IMX334_REG_ID, 2, &val); 757*9746b117SMartina Krasteva if (ret) 758*9746b117SMartina Krasteva return ret; 759*9746b117SMartina Krasteva 760*9746b117SMartina Krasteva if (val != IMX334_ID) { 761*9746b117SMartina Krasteva dev_err(imx334->dev, "chip id mismatch: %x!=%x", 762*9746b117SMartina Krasteva IMX334_ID, val); 763*9746b117SMartina Krasteva return -ENXIO; 764*9746b117SMartina Krasteva } 765*9746b117SMartina Krasteva 766*9746b117SMartina Krasteva return 0; 767*9746b117SMartina Krasteva } 768*9746b117SMartina Krasteva 769*9746b117SMartina Krasteva /** 770*9746b117SMartina Krasteva * imx334_parse_hw_config() - Parse HW configuration and check if supported 771*9746b117SMartina Krasteva * @imx334: pointer to imx334 device 772*9746b117SMartina Krasteva * 773*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 774*9746b117SMartina Krasteva */ 775*9746b117SMartina Krasteva static int imx334_parse_hw_config(struct imx334 *imx334) 776*9746b117SMartina Krasteva { 777*9746b117SMartina Krasteva struct fwnode_handle *fwnode = dev_fwnode(imx334->dev); 778*9746b117SMartina Krasteva struct v4l2_fwnode_endpoint bus_cfg = { 779*9746b117SMartina Krasteva .bus_type = V4L2_MBUS_CSI2_DPHY 780*9746b117SMartina Krasteva }; 781*9746b117SMartina Krasteva struct fwnode_handle *ep; 782*9746b117SMartina Krasteva unsigned long rate; 783*9746b117SMartina Krasteva int ret; 784*9746b117SMartina Krasteva int i; 785*9746b117SMartina Krasteva 786*9746b117SMartina Krasteva if (!fwnode) 787*9746b117SMartina Krasteva return -ENXIO; 788*9746b117SMartina Krasteva 789*9746b117SMartina Krasteva /* Request optional reset pin */ 790*9746b117SMartina Krasteva imx334->reset_gpio = devm_gpiod_get_optional(imx334->dev, "reset", 791*9746b117SMartina Krasteva GPIOD_OUT_LOW); 792*9746b117SMartina Krasteva if (IS_ERR(imx334->reset_gpio)) { 793*9746b117SMartina Krasteva dev_err(imx334->dev, "failed to get reset gpio %d", ret); 794*9746b117SMartina Krasteva return PTR_ERR(imx334->reset_gpio); 795*9746b117SMartina Krasteva } 796*9746b117SMartina Krasteva 797*9746b117SMartina Krasteva /* Get sensor input clock */ 798*9746b117SMartina Krasteva imx334->inclk = devm_clk_get(imx334->dev, NULL); 799*9746b117SMartina Krasteva if (IS_ERR(imx334->inclk)) { 800*9746b117SMartina Krasteva dev_err(imx334->dev, "could not get inclk"); 801*9746b117SMartina Krasteva return PTR_ERR(imx334->inclk); 802*9746b117SMartina Krasteva } 803*9746b117SMartina Krasteva 804*9746b117SMartina Krasteva rate = clk_get_rate(imx334->inclk); 805*9746b117SMartina Krasteva if (rate != IMX334_INCLK_RATE) { 806*9746b117SMartina Krasteva dev_err(imx334->dev, "inclk frequency mismatch"); 807*9746b117SMartina Krasteva return -EINVAL; 808*9746b117SMartina Krasteva } 809*9746b117SMartina Krasteva 810*9746b117SMartina Krasteva ep = fwnode_graph_get_next_endpoint(fwnode, NULL); 811*9746b117SMartina Krasteva if (!ep) 812*9746b117SMartina Krasteva return -ENXIO; 813*9746b117SMartina Krasteva 814*9746b117SMartina Krasteva ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); 815*9746b117SMartina Krasteva fwnode_handle_put(ep); 816*9746b117SMartina Krasteva if (ret) 817*9746b117SMartina Krasteva return ret; 818*9746b117SMartina Krasteva 819*9746b117SMartina Krasteva if (bus_cfg.bus.mipi_csi2.num_data_lanes != IMX334_NUM_DATA_LANES) { 820*9746b117SMartina Krasteva dev_err(imx334->dev, 821*9746b117SMartina Krasteva "number of CSI2 data lanes %d is not supported", 822*9746b117SMartina Krasteva bus_cfg.bus.mipi_csi2.num_data_lanes); 823*9746b117SMartina Krasteva ret = -EINVAL; 824*9746b117SMartina Krasteva goto done_endpoint_free; 825*9746b117SMartina Krasteva } 826*9746b117SMartina Krasteva 827*9746b117SMartina Krasteva if (!bus_cfg.nr_of_link_frequencies) { 828*9746b117SMartina Krasteva dev_err(imx334->dev, "no link frequencies defined"); 829*9746b117SMartina Krasteva ret = -EINVAL; 830*9746b117SMartina Krasteva goto done_endpoint_free; 831*9746b117SMartina Krasteva } 832*9746b117SMartina Krasteva 833*9746b117SMartina Krasteva for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) 834*9746b117SMartina Krasteva if (bus_cfg.link_frequencies[i] == IMX334_LINK_FREQ) 835*9746b117SMartina Krasteva goto done_endpoint_free; 836*9746b117SMartina Krasteva 837*9746b117SMartina Krasteva ret = -EINVAL; 838*9746b117SMartina Krasteva 839*9746b117SMartina Krasteva done_endpoint_free: 840*9746b117SMartina Krasteva v4l2_fwnode_endpoint_free(&bus_cfg); 841*9746b117SMartina Krasteva 842*9746b117SMartina Krasteva return ret; 843*9746b117SMartina Krasteva } 844*9746b117SMartina Krasteva 845*9746b117SMartina Krasteva /* V4l2 subdevice ops */ 846*9746b117SMartina Krasteva static const struct v4l2_subdev_video_ops imx334_video_ops = { 847*9746b117SMartina Krasteva .s_stream = imx334_set_stream, 848*9746b117SMartina Krasteva }; 849*9746b117SMartina Krasteva 850*9746b117SMartina Krasteva static const struct v4l2_subdev_pad_ops imx334_pad_ops = { 851*9746b117SMartina Krasteva .init_cfg = imx334_init_pad_cfg, 852*9746b117SMartina Krasteva .enum_mbus_code = imx334_enum_mbus_code, 853*9746b117SMartina Krasteva .enum_frame_size = imx334_enum_frame_size, 854*9746b117SMartina Krasteva .get_fmt = imx334_get_pad_format, 855*9746b117SMartina Krasteva .set_fmt = imx334_set_pad_format, 856*9746b117SMartina Krasteva }; 857*9746b117SMartina Krasteva 858*9746b117SMartina Krasteva static const struct v4l2_subdev_ops imx334_subdev_ops = { 859*9746b117SMartina Krasteva .video = &imx334_video_ops, 860*9746b117SMartina Krasteva .pad = &imx334_pad_ops, 861*9746b117SMartina Krasteva }; 862*9746b117SMartina Krasteva 863*9746b117SMartina Krasteva /** 864*9746b117SMartina Krasteva * imx334_power_on() - Sensor power on sequence 865*9746b117SMartina Krasteva * @dev: pointer to i2c device 866*9746b117SMartina Krasteva * 867*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 868*9746b117SMartina Krasteva */ 869*9746b117SMartina Krasteva static int imx334_power_on(struct device *dev) 870*9746b117SMartina Krasteva { 871*9746b117SMartina Krasteva struct v4l2_subdev *sd = dev_get_drvdata(dev); 872*9746b117SMartina Krasteva struct imx334 *imx334 = to_imx334(sd); 873*9746b117SMartina Krasteva int ret; 874*9746b117SMartina Krasteva 875*9746b117SMartina Krasteva gpiod_set_value_cansleep(imx334->reset_gpio, 1); 876*9746b117SMartina Krasteva 877*9746b117SMartina Krasteva ret = clk_prepare_enable(imx334->inclk); 878*9746b117SMartina Krasteva if (ret) { 879*9746b117SMartina Krasteva dev_err(imx334->dev, "fail to enable inclk"); 880*9746b117SMartina Krasteva goto error_reset; 881*9746b117SMartina Krasteva } 882*9746b117SMartina Krasteva 883*9746b117SMartina Krasteva usleep_range(18000, 20000); 884*9746b117SMartina Krasteva 885*9746b117SMartina Krasteva return 0; 886*9746b117SMartina Krasteva 887*9746b117SMartina Krasteva error_reset: 888*9746b117SMartina Krasteva gpiod_set_value_cansleep(imx334->reset_gpio, 0); 889*9746b117SMartina Krasteva 890*9746b117SMartina Krasteva return ret; 891*9746b117SMartina Krasteva } 892*9746b117SMartina Krasteva 893*9746b117SMartina Krasteva /** 894*9746b117SMartina Krasteva * imx334_power_off() - Sensor power off sequence 895*9746b117SMartina Krasteva * @dev: pointer to i2c device 896*9746b117SMartina Krasteva * 897*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 898*9746b117SMartina Krasteva */ 899*9746b117SMartina Krasteva static int imx334_power_off(struct device *dev) 900*9746b117SMartina Krasteva { 901*9746b117SMartina Krasteva struct v4l2_subdev *sd = dev_get_drvdata(dev); 902*9746b117SMartina Krasteva struct imx334 *imx334 = to_imx334(sd); 903*9746b117SMartina Krasteva 904*9746b117SMartina Krasteva gpiod_set_value_cansleep(imx334->reset_gpio, 0); 905*9746b117SMartina Krasteva 906*9746b117SMartina Krasteva clk_disable_unprepare(imx334->inclk); 907*9746b117SMartina Krasteva 908*9746b117SMartina Krasteva return 0; 909*9746b117SMartina Krasteva } 910*9746b117SMartina Krasteva 911*9746b117SMartina Krasteva /** 912*9746b117SMartina Krasteva * imx334_init_controls() - Initialize sensor subdevice controls 913*9746b117SMartina Krasteva * @imx334: pointer to imx334 device 914*9746b117SMartina Krasteva * 915*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 916*9746b117SMartina Krasteva */ 917*9746b117SMartina Krasteva static int imx334_init_controls(struct imx334 *imx334) 918*9746b117SMartina Krasteva { 919*9746b117SMartina Krasteva struct v4l2_ctrl_handler *ctrl_hdlr = &imx334->ctrl_handler; 920*9746b117SMartina Krasteva const struct imx334_mode *mode = imx334->cur_mode; 921*9746b117SMartina Krasteva u32 lpfr; 922*9746b117SMartina Krasteva int ret; 923*9746b117SMartina Krasteva 924*9746b117SMartina Krasteva ret = v4l2_ctrl_handler_init(ctrl_hdlr, 6); 925*9746b117SMartina Krasteva if (ret) 926*9746b117SMartina Krasteva return ret; 927*9746b117SMartina Krasteva 928*9746b117SMartina Krasteva /* Serialize controls with sensor device */ 929*9746b117SMartina Krasteva ctrl_hdlr->lock = &imx334->mutex; 930*9746b117SMartina Krasteva 931*9746b117SMartina Krasteva /* Initialize exposure and gain */ 932*9746b117SMartina Krasteva lpfr = mode->vblank + mode->height; 933*9746b117SMartina Krasteva imx334->exp_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, 934*9746b117SMartina Krasteva &imx334_ctrl_ops, 935*9746b117SMartina Krasteva V4L2_CID_EXPOSURE, 936*9746b117SMartina Krasteva IMX334_EXPOSURE_MIN, 937*9746b117SMartina Krasteva lpfr - IMX334_EXPOSURE_OFFSET, 938*9746b117SMartina Krasteva IMX334_EXPOSURE_STEP, 939*9746b117SMartina Krasteva IMX334_EXPOSURE_DEFAULT); 940*9746b117SMartina Krasteva 941*9746b117SMartina Krasteva imx334->again_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, 942*9746b117SMartina Krasteva &imx334_ctrl_ops, 943*9746b117SMartina Krasteva V4L2_CID_ANALOGUE_GAIN, 944*9746b117SMartina Krasteva IMX334_AGAIN_MIN, 945*9746b117SMartina Krasteva IMX334_AGAIN_MAX, 946*9746b117SMartina Krasteva IMX334_AGAIN_STEP, 947*9746b117SMartina Krasteva IMX334_AGAIN_DEFAULT); 948*9746b117SMartina Krasteva 949*9746b117SMartina Krasteva v4l2_ctrl_cluster(2, &imx334->exp_ctrl); 950*9746b117SMartina Krasteva 951*9746b117SMartina Krasteva imx334->vblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, 952*9746b117SMartina Krasteva &imx334_ctrl_ops, 953*9746b117SMartina Krasteva V4L2_CID_VBLANK, 954*9746b117SMartina Krasteva mode->vblank_min, 955*9746b117SMartina Krasteva mode->vblank_max, 956*9746b117SMartina Krasteva 1, mode->vblank); 957*9746b117SMartina Krasteva 958*9746b117SMartina Krasteva /* Read only controls */ 959*9746b117SMartina Krasteva imx334->pclk_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, 960*9746b117SMartina Krasteva &imx334_ctrl_ops, 961*9746b117SMartina Krasteva V4L2_CID_PIXEL_RATE, 962*9746b117SMartina Krasteva mode->pclk, mode->pclk, 963*9746b117SMartina Krasteva 1, mode->pclk); 964*9746b117SMartina Krasteva 965*9746b117SMartina Krasteva imx334->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, 966*9746b117SMartina Krasteva &imx334_ctrl_ops, 967*9746b117SMartina Krasteva V4L2_CID_LINK_FREQ, 968*9746b117SMartina Krasteva ARRAY_SIZE(link_freq) - 969*9746b117SMartina Krasteva 1, 970*9746b117SMartina Krasteva mode->link_freq_idx, 971*9746b117SMartina Krasteva link_freq); 972*9746b117SMartina Krasteva if (imx334->link_freq_ctrl) 973*9746b117SMartina Krasteva imx334->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; 974*9746b117SMartina Krasteva 975*9746b117SMartina Krasteva imx334->hblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, 976*9746b117SMartina Krasteva &imx334_ctrl_ops, 977*9746b117SMartina Krasteva V4L2_CID_HBLANK, 978*9746b117SMartina Krasteva IMX334_REG_MIN, 979*9746b117SMartina Krasteva IMX334_REG_MAX, 980*9746b117SMartina Krasteva 1, mode->hblank); 981*9746b117SMartina Krasteva if (imx334->hblank_ctrl) 982*9746b117SMartina Krasteva imx334->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; 983*9746b117SMartina Krasteva 984*9746b117SMartina Krasteva if (ctrl_hdlr->error) { 985*9746b117SMartina Krasteva dev_err(imx334->dev, "control init failed: %d", 986*9746b117SMartina Krasteva ctrl_hdlr->error); 987*9746b117SMartina Krasteva v4l2_ctrl_handler_free(ctrl_hdlr); 988*9746b117SMartina Krasteva return ctrl_hdlr->error; 989*9746b117SMartina Krasteva } 990*9746b117SMartina Krasteva 991*9746b117SMartina Krasteva imx334->sd.ctrl_handler = ctrl_hdlr; 992*9746b117SMartina Krasteva 993*9746b117SMartina Krasteva return 0; 994*9746b117SMartina Krasteva } 995*9746b117SMartina Krasteva 996*9746b117SMartina Krasteva /** 997*9746b117SMartina Krasteva * imx334_probe() - I2C client device binding 998*9746b117SMartina Krasteva * @client: pointer to i2c client device 999*9746b117SMartina Krasteva * 1000*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 1001*9746b117SMartina Krasteva */ 1002*9746b117SMartina Krasteva static int imx334_probe(struct i2c_client *client) 1003*9746b117SMartina Krasteva { 1004*9746b117SMartina Krasteva struct imx334 *imx334; 1005*9746b117SMartina Krasteva int ret; 1006*9746b117SMartina Krasteva 1007*9746b117SMartina Krasteva imx334 = devm_kzalloc(&client->dev, sizeof(*imx334), GFP_KERNEL); 1008*9746b117SMartina Krasteva if (!imx334) 1009*9746b117SMartina Krasteva return -ENOMEM; 1010*9746b117SMartina Krasteva 1011*9746b117SMartina Krasteva imx334->dev = &client->dev; 1012*9746b117SMartina Krasteva 1013*9746b117SMartina Krasteva /* Initialize subdev */ 1014*9746b117SMartina Krasteva v4l2_i2c_subdev_init(&imx334->sd, client, &imx334_subdev_ops); 1015*9746b117SMartina Krasteva 1016*9746b117SMartina Krasteva ret = imx334_parse_hw_config(imx334); 1017*9746b117SMartina Krasteva if (ret) { 1018*9746b117SMartina Krasteva dev_err(imx334->dev, "HW configuration is not supported"); 1019*9746b117SMartina Krasteva return ret; 1020*9746b117SMartina Krasteva } 1021*9746b117SMartina Krasteva 1022*9746b117SMartina Krasteva mutex_init(&imx334->mutex); 1023*9746b117SMartina Krasteva 1024*9746b117SMartina Krasteva ret = imx334_power_on(imx334->dev); 1025*9746b117SMartina Krasteva if (ret) { 1026*9746b117SMartina Krasteva dev_err(imx334->dev, "failed to power-on the sensor"); 1027*9746b117SMartina Krasteva goto error_mutex_destroy; 1028*9746b117SMartina Krasteva } 1029*9746b117SMartina Krasteva 1030*9746b117SMartina Krasteva /* Check module identity */ 1031*9746b117SMartina Krasteva ret = imx334_detect(imx334); 1032*9746b117SMartina Krasteva if (ret) { 1033*9746b117SMartina Krasteva dev_err(imx334->dev, "failed to find sensor: %d", ret); 1034*9746b117SMartina Krasteva goto error_power_off; 1035*9746b117SMartina Krasteva } 1036*9746b117SMartina Krasteva 1037*9746b117SMartina Krasteva /* Set default mode to max resolution */ 1038*9746b117SMartina Krasteva imx334->cur_mode = &supported_mode; 1039*9746b117SMartina Krasteva imx334->vblank = imx334->cur_mode->vblank; 1040*9746b117SMartina Krasteva 1041*9746b117SMartina Krasteva ret = imx334_init_controls(imx334); 1042*9746b117SMartina Krasteva if (ret) { 1043*9746b117SMartina Krasteva dev_err(imx334->dev, "failed to init controls: %d", ret); 1044*9746b117SMartina Krasteva goto error_power_off; 1045*9746b117SMartina Krasteva } 1046*9746b117SMartina Krasteva 1047*9746b117SMartina Krasteva /* Initialize subdev */ 1048*9746b117SMartina Krasteva imx334->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 1049*9746b117SMartina Krasteva imx334->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; 1050*9746b117SMartina Krasteva 1051*9746b117SMartina Krasteva /* Initialize source pad */ 1052*9746b117SMartina Krasteva imx334->pad.flags = MEDIA_PAD_FL_SOURCE; 1053*9746b117SMartina Krasteva ret = media_entity_pads_init(&imx334->sd.entity, 1, &imx334->pad); 1054*9746b117SMartina Krasteva if (ret) { 1055*9746b117SMartina Krasteva dev_err(imx334->dev, "failed to init entity pads: %d", ret); 1056*9746b117SMartina Krasteva goto error_handler_free; 1057*9746b117SMartina Krasteva } 1058*9746b117SMartina Krasteva 1059*9746b117SMartina Krasteva ret = v4l2_async_register_subdev_sensor_common(&imx334->sd); 1060*9746b117SMartina Krasteva if (ret < 0) { 1061*9746b117SMartina Krasteva dev_err(imx334->dev, 1062*9746b117SMartina Krasteva "failed to register async subdev: %d", ret); 1063*9746b117SMartina Krasteva goto error_media_entity; 1064*9746b117SMartina Krasteva } 1065*9746b117SMartina Krasteva 1066*9746b117SMartina Krasteva pm_runtime_set_active(imx334->dev); 1067*9746b117SMartina Krasteva pm_runtime_enable(imx334->dev); 1068*9746b117SMartina Krasteva pm_runtime_idle(imx334->dev); 1069*9746b117SMartina Krasteva 1070*9746b117SMartina Krasteva return 0; 1071*9746b117SMartina Krasteva 1072*9746b117SMartina Krasteva error_media_entity: 1073*9746b117SMartina Krasteva media_entity_cleanup(&imx334->sd.entity); 1074*9746b117SMartina Krasteva error_handler_free: 1075*9746b117SMartina Krasteva v4l2_ctrl_handler_free(imx334->sd.ctrl_handler); 1076*9746b117SMartina Krasteva error_power_off: 1077*9746b117SMartina Krasteva imx334_power_off(imx334->dev); 1078*9746b117SMartina Krasteva error_mutex_destroy: 1079*9746b117SMartina Krasteva mutex_destroy(&imx334->mutex); 1080*9746b117SMartina Krasteva 1081*9746b117SMartina Krasteva return ret; 1082*9746b117SMartina Krasteva } 1083*9746b117SMartina Krasteva 1084*9746b117SMartina Krasteva /** 1085*9746b117SMartina Krasteva * imx334_remove() - I2C client device unbinding 1086*9746b117SMartina Krasteva * @client: pointer to I2C client device 1087*9746b117SMartina Krasteva * 1088*9746b117SMartina Krasteva * Return: 0 if successful, error code otherwise. 1089*9746b117SMartina Krasteva */ 1090*9746b117SMartina Krasteva static int imx334_remove(struct i2c_client *client) 1091*9746b117SMartina Krasteva { 1092*9746b117SMartina Krasteva struct v4l2_subdev *sd = i2c_get_clientdata(client); 1093*9746b117SMartina Krasteva struct imx334 *imx334 = to_imx334(sd); 1094*9746b117SMartina Krasteva 1095*9746b117SMartina Krasteva v4l2_async_unregister_subdev(sd); 1096*9746b117SMartina Krasteva media_entity_cleanup(&sd->entity); 1097*9746b117SMartina Krasteva v4l2_ctrl_handler_free(sd->ctrl_handler); 1098*9746b117SMartina Krasteva 1099*9746b117SMartina Krasteva pm_runtime_disable(&client->dev); 1100*9746b117SMartina Krasteva pm_runtime_suspended(&client->dev); 1101*9746b117SMartina Krasteva 1102*9746b117SMartina Krasteva mutex_destroy(&imx334->mutex); 1103*9746b117SMartina Krasteva 1104*9746b117SMartina Krasteva return 0; 1105*9746b117SMartina Krasteva } 1106*9746b117SMartina Krasteva 1107*9746b117SMartina Krasteva static const struct dev_pm_ops imx334_pm_ops = { 1108*9746b117SMartina Krasteva SET_RUNTIME_PM_OPS(imx334_power_off, imx334_power_on, NULL) 1109*9746b117SMartina Krasteva }; 1110*9746b117SMartina Krasteva 1111*9746b117SMartina Krasteva static const struct of_device_id imx334_of_match[] = { 1112*9746b117SMartina Krasteva { .compatible = "sony,imx334" }, 1113*9746b117SMartina Krasteva { } 1114*9746b117SMartina Krasteva }; 1115*9746b117SMartina Krasteva 1116*9746b117SMartina Krasteva MODULE_DEVICE_TABLE(of, imx334_of_match); 1117*9746b117SMartina Krasteva 1118*9746b117SMartina Krasteva static struct i2c_driver imx334_driver = { 1119*9746b117SMartina Krasteva .probe_new = imx334_probe, 1120*9746b117SMartina Krasteva .remove = imx334_remove, 1121*9746b117SMartina Krasteva .driver = { 1122*9746b117SMartina Krasteva .name = "imx334", 1123*9746b117SMartina Krasteva .pm = &imx334_pm_ops, 1124*9746b117SMartina Krasteva .of_match_table = imx334_of_match, 1125*9746b117SMartina Krasteva }, 1126*9746b117SMartina Krasteva }; 1127*9746b117SMartina Krasteva 1128*9746b117SMartina Krasteva module_i2c_driver(imx334_driver); 1129*9746b117SMartina Krasteva 1130*9746b117SMartina Krasteva MODULE_DESCRIPTION("Sony imx334 sensor driver"); 1131*9746b117SMartina Krasteva MODULE_LICENSE("GPL"); 1132