1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2012 Intel Corporation 3 4 /* 5 * Based on linux/modules/camera/drivers/media/i2c/imx/dw9719.c from: 6 * https://github.com/ZenfoneArea/android_kernel_asus_zenfone5 and 7 * latte-l-oss/drivers/external_drivers/camera/drivers/media/i2c/micam/dw9761.c 8 * from: https://github.com/MiCode/Xiaomi_Kernel_OpenSource/ 9 */ 10 11 #include <linux/delay.h> 12 #include <linux/i2c.h> 13 #include <linux/pm_runtime.h> 14 #include <linux/regulator/consumer.h> 15 #include <linux/types.h> 16 17 #include <media/v4l2-cci.h> 18 #include <media/v4l2-common.h> 19 #include <media/v4l2-ctrls.h> 20 #include <media/v4l2-subdev.h> 21 22 #define DW9719_MAX_FOCUS_POS 1023 23 #define DW9719_CTRL_STEPS 16 24 #define DW9719_CTRL_DELAY_US 1000 25 26 #define DW9719_INFO CCI_REG8(0) 27 #define DW9719_ID 0xF1 28 #define DW9761_ID 0xF4 29 30 #define DW9719_CONTROL CCI_REG8(2) 31 #define DW9719_STANDBY 0x00 32 #define DW9719_SHUTDOWN 0x01 33 #define DW9719_ENABLE_RINGING 0x02 34 35 #define DW9719_VCM_CURRENT CCI_REG16(3) 36 37 #define DW9719_STATUS CCI_REG16(5) 38 #define DW9719_STATUS_BUSY BIT(0) 39 40 #define DW9719_MODE CCI_REG8(6) 41 #define DW9719_MODE_SAC_SHIFT 4 42 #define DW9719_DEFAULT_SAC 4 43 #define DW9761_DEFAULT_SAC 6 44 45 #define DW9719_VCM_FREQ CCI_REG8(7) 46 #define DW9719_DEFAULT_VCM_FREQ 0x60 47 #define DW9761_DEFAULT_VCM_FREQ 0x3E 48 49 #define DW9761_VCM_PRELOAD CCI_REG8(8) 50 #define DW9761_DEFAULT_VCM_PRELOAD 0x73 51 52 53 #define to_dw9719_device(x) container_of(x, struct dw9719_device, sd) 54 55 enum dw9719_model { 56 DW9719, 57 DW9761, 58 }; 59 60 struct dw9719_device { 61 struct v4l2_subdev sd; 62 struct device *dev; 63 struct regmap *regmap; 64 struct regulator *regulator; 65 enum dw9719_model model; 66 u32 mode_low_bits; 67 u32 sac_mode; 68 u32 vcm_freq; 69 70 struct dw9719_v4l2_ctrls { 71 struct v4l2_ctrl_handler handler; 72 struct v4l2_ctrl *focus; 73 } ctrls; 74 }; 75 76 static int dw9719_power_down(struct dw9719_device *dw9719) 77 { 78 return regulator_disable(dw9719->regulator); 79 } 80 81 static int dw9719_power_up(struct dw9719_device *dw9719, bool detect) 82 { 83 u64 val; 84 int ret; 85 86 ret = regulator_enable(dw9719->regulator); 87 if (ret) 88 return ret; 89 90 /* Jiggle SCL pin to wake up device */ 91 cci_write(dw9719->regmap, DW9719_CONTROL, DW9719_SHUTDOWN, &ret); 92 fsleep(100); 93 cci_write(dw9719->regmap, DW9719_CONTROL, DW9719_STANDBY, &ret); 94 /* Need 100us to transit from SHUTDOWN to STANDBY */ 95 fsleep(100); 96 97 if (detect) { 98 ret = cci_read(dw9719->regmap, DW9719_INFO, &val, NULL); 99 if (ret < 0) 100 return ret; 101 102 switch (val) { 103 case DW9719_ID: 104 dw9719->model = DW9719; 105 dw9719->mode_low_bits = 0x00; 106 dw9719->sac_mode = DW9719_DEFAULT_SAC; 107 dw9719->vcm_freq = DW9719_DEFAULT_VCM_FREQ; 108 break; 109 case DW9761_ID: 110 dw9719->model = DW9761; 111 dw9719->mode_low_bits = 0x01; 112 dw9719->sac_mode = DW9761_DEFAULT_SAC; 113 dw9719->vcm_freq = DW9761_DEFAULT_VCM_FREQ; 114 break; 115 default: 116 dev_err(dw9719->dev, 117 "Error unknown device id 0x%02llx\n", val); 118 return -ENXIO; 119 } 120 121 /* Optional indication of SAC mode select */ 122 device_property_read_u32(dw9719->dev, "dongwoon,sac-mode", 123 &dw9719->sac_mode); 124 125 /* Optional indication of VCM frequency */ 126 device_property_read_u32(dw9719->dev, "dongwoon,vcm-freq", 127 &dw9719->vcm_freq); 128 } 129 130 cci_write(dw9719->regmap, DW9719_CONTROL, DW9719_ENABLE_RINGING, &ret); 131 cci_write(dw9719->regmap, DW9719_MODE, dw9719->mode_low_bits | 132 (dw9719->sac_mode << DW9719_MODE_SAC_SHIFT), &ret); 133 cci_write(dw9719->regmap, DW9719_VCM_FREQ, dw9719->vcm_freq, &ret); 134 135 if (dw9719->model == DW9761) 136 cci_write(dw9719->regmap, DW9761_VCM_PRELOAD, 137 DW9761_DEFAULT_VCM_PRELOAD, &ret); 138 139 if (ret) 140 dw9719_power_down(dw9719); 141 142 return ret; 143 } 144 145 static int dw9719_t_focus_abs(struct dw9719_device *dw9719, s32 value) 146 { 147 return cci_write(dw9719->regmap, DW9719_VCM_CURRENT, value, NULL); 148 } 149 150 static int dw9719_set_ctrl(struct v4l2_ctrl *ctrl) 151 { 152 struct dw9719_device *dw9719 = container_of(ctrl->handler, 153 struct dw9719_device, 154 ctrls.handler); 155 int ret; 156 157 /* Only apply changes to the controls if the device is powered up */ 158 if (!pm_runtime_get_if_in_use(dw9719->dev)) 159 return 0; 160 161 switch (ctrl->id) { 162 case V4L2_CID_FOCUS_ABSOLUTE: 163 ret = dw9719_t_focus_abs(dw9719, ctrl->val); 164 break; 165 default: 166 ret = -EINVAL; 167 } 168 169 pm_runtime_put(dw9719->dev); 170 171 return ret; 172 } 173 174 static const struct v4l2_ctrl_ops dw9719_ctrl_ops = { 175 .s_ctrl = dw9719_set_ctrl, 176 }; 177 178 static int dw9719_suspend(struct device *dev) 179 { 180 struct v4l2_subdev *sd = dev_get_drvdata(dev); 181 struct dw9719_device *dw9719 = to_dw9719_device(sd); 182 int ret; 183 int val; 184 185 for (val = dw9719->ctrls.focus->val; val >= 0; 186 val -= DW9719_CTRL_STEPS) { 187 ret = dw9719_t_focus_abs(dw9719, val); 188 if (ret) 189 return ret; 190 191 usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10); 192 } 193 194 return dw9719_power_down(dw9719); 195 } 196 197 static int dw9719_resume(struct device *dev) 198 { 199 struct v4l2_subdev *sd = dev_get_drvdata(dev); 200 struct dw9719_device *dw9719 = to_dw9719_device(sd); 201 int current_focus = dw9719->ctrls.focus->val; 202 int ret; 203 int val; 204 205 ret = dw9719_power_up(dw9719, false); 206 if (ret) 207 return ret; 208 209 for (val = current_focus % DW9719_CTRL_STEPS; val < current_focus; 210 val += DW9719_CTRL_STEPS) { 211 ret = dw9719_t_focus_abs(dw9719, val); 212 if (ret) 213 goto err_power_down; 214 215 usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10); 216 } 217 218 return 0; 219 220 err_power_down: 221 dw9719_power_down(dw9719); 222 return ret; 223 } 224 225 static int dw9719_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 226 { 227 return pm_runtime_resume_and_get(sd->dev); 228 } 229 230 static int dw9719_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 231 { 232 pm_runtime_put(sd->dev); 233 234 return 0; 235 } 236 237 static const struct v4l2_subdev_internal_ops dw9719_internal_ops = { 238 .open = dw9719_open, 239 .close = dw9719_close, 240 }; 241 242 static int dw9719_init_controls(struct dw9719_device *dw9719) 243 { 244 const struct v4l2_ctrl_ops *ops = &dw9719_ctrl_ops; 245 int ret; 246 247 v4l2_ctrl_handler_init(&dw9719->ctrls.handler, 1); 248 249 dw9719->ctrls.focus = v4l2_ctrl_new_std(&dw9719->ctrls.handler, ops, 250 V4L2_CID_FOCUS_ABSOLUTE, 0, 251 DW9719_MAX_FOCUS_POS, 1, 0); 252 253 if (dw9719->ctrls.handler.error) { 254 dev_err(dw9719->dev, "Error initialising v4l2 ctrls\n"); 255 ret = dw9719->ctrls.handler.error; 256 goto err_free_handler; 257 } 258 259 dw9719->sd.ctrl_handler = &dw9719->ctrls.handler; 260 return 0; 261 262 err_free_handler: 263 v4l2_ctrl_handler_free(&dw9719->ctrls.handler); 264 return ret; 265 } 266 267 static const struct v4l2_subdev_ops dw9719_ops = { }; 268 269 static int dw9719_probe(struct i2c_client *client) 270 { 271 struct dw9719_device *dw9719; 272 int ret; 273 274 dw9719 = devm_kzalloc(&client->dev, sizeof(*dw9719), GFP_KERNEL); 275 if (!dw9719) 276 return -ENOMEM; 277 278 dw9719->regmap = devm_cci_regmap_init_i2c(client, 8); 279 if (IS_ERR(dw9719->regmap)) 280 return PTR_ERR(dw9719->regmap); 281 282 dw9719->dev = &client->dev; 283 284 dw9719->regulator = devm_regulator_get(&client->dev, "vdd"); 285 if (IS_ERR(dw9719->regulator)) 286 return dev_err_probe(&client->dev, PTR_ERR(dw9719->regulator), 287 "getting regulator\n"); 288 289 v4l2_i2c_subdev_init(&dw9719->sd, client, &dw9719_ops); 290 dw9719->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 291 dw9719->sd.internal_ops = &dw9719_internal_ops; 292 293 ret = dw9719_init_controls(dw9719); 294 if (ret) 295 return ret; 296 297 ret = media_entity_pads_init(&dw9719->sd.entity, 0, NULL); 298 if (ret < 0) 299 goto err_free_ctrl_handler; 300 301 dw9719->sd.entity.function = MEDIA_ENT_F_LENS; 302 303 /* 304 * We need the driver to work in the event that pm runtime is disable in 305 * the kernel, so power up and verify the chip now. In the event that 306 * runtime pm is disabled this will leave the chip on, so that the lens 307 * will work. 308 */ 309 310 ret = dw9719_power_up(dw9719, true); 311 if (ret) 312 goto err_cleanup_media; 313 314 pm_runtime_set_active(&client->dev); 315 pm_runtime_get_noresume(&client->dev); 316 pm_runtime_enable(&client->dev); 317 318 ret = v4l2_async_register_subdev(&dw9719->sd); 319 if (ret < 0) 320 goto err_pm_runtime; 321 322 pm_runtime_set_autosuspend_delay(&client->dev, 1000); 323 pm_runtime_use_autosuspend(&client->dev); 324 pm_runtime_put_autosuspend(&client->dev); 325 326 return ret; 327 328 err_pm_runtime: 329 pm_runtime_disable(&client->dev); 330 pm_runtime_put_noidle(&client->dev); 331 dw9719_power_down(dw9719); 332 err_cleanup_media: 333 media_entity_cleanup(&dw9719->sd.entity); 334 err_free_ctrl_handler: 335 v4l2_ctrl_handler_free(&dw9719->ctrls.handler); 336 337 return ret; 338 } 339 340 static void dw9719_remove(struct i2c_client *client) 341 { 342 struct v4l2_subdev *sd = i2c_get_clientdata(client); 343 struct dw9719_device *dw9719 = 344 container_of(sd, struct dw9719_device, sd); 345 346 v4l2_async_unregister_subdev(sd); 347 v4l2_ctrl_handler_free(&dw9719->ctrls.handler); 348 media_entity_cleanup(&dw9719->sd.entity); 349 350 pm_runtime_disable(&client->dev); 351 if (!pm_runtime_status_suspended(&client->dev)) 352 dw9719_power_down(dw9719); 353 pm_runtime_set_suspended(&client->dev); 354 } 355 356 static const struct i2c_device_id dw9719_id_table[] = { 357 { "dw9719" }, 358 { "dw9761" }, 359 { } 360 }; 361 MODULE_DEVICE_TABLE(i2c, dw9719_id_table); 362 363 static DEFINE_RUNTIME_DEV_PM_OPS(dw9719_pm_ops, dw9719_suspend, dw9719_resume, 364 NULL); 365 366 static struct i2c_driver dw9719_i2c_driver = { 367 .driver = { 368 .name = "dw9719", 369 .pm = pm_sleep_ptr(&dw9719_pm_ops), 370 }, 371 .probe = dw9719_probe, 372 .remove = dw9719_remove, 373 .id_table = dw9719_id_table, 374 }; 375 module_i2c_driver(dw9719_i2c_driver); 376 377 MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>"); 378 MODULE_DESCRIPTION("DW9719 VCM Driver"); 379 MODULE_LICENSE("GPL"); 380