190ee26fbSBingbu Cao // SPDX-License-Identifier: GPL-2.0 290ee26fbSBingbu Cao // Copyright (C) 2018 Intel Corporation 390ee26fbSBingbu Cao 490ee26fbSBingbu Cao #include <linux/acpi.h> 590ee26fbSBingbu Cao #include <linux/delay.h> 690ee26fbSBingbu Cao #include <linux/i2c.h> 790ee26fbSBingbu Cao #include <linux/module.h> 890ee26fbSBingbu Cao #include <linux/pm_runtime.h> 9*90f7e76eSYassine Oudjana #include <linux/regulator/consumer.h> 1090ee26fbSBingbu Cao #include <media/v4l2-ctrls.h> 1190ee26fbSBingbu Cao #include <media/v4l2-device.h> 1290ee26fbSBingbu Cao 1390ee26fbSBingbu Cao #define AK7375_MAX_FOCUS_POS 4095 1490ee26fbSBingbu Cao /* 1590ee26fbSBingbu Cao * This sets the minimum granularity for the focus positions. 1690ee26fbSBingbu Cao * A value of 1 gives maximum accuracy for a desired focus position 1790ee26fbSBingbu Cao */ 1890ee26fbSBingbu Cao #define AK7375_FOCUS_STEPS 1 1990ee26fbSBingbu Cao /* 2090ee26fbSBingbu Cao * This acts as the minimum granularity of lens movement. 2190ee26fbSBingbu Cao * Keep this value power of 2, so the control steps can be 2290ee26fbSBingbu Cao * uniformly adjusted for gradual lens movement, with desired 2390ee26fbSBingbu Cao * number of control steps. 2490ee26fbSBingbu Cao */ 2590ee26fbSBingbu Cao #define AK7375_CTRL_STEPS 64 2690ee26fbSBingbu Cao #define AK7375_CTRL_DELAY_US 1000 27*90f7e76eSYassine Oudjana /* 28*90f7e76eSYassine Oudjana * The vcm may take up 10 ms (tDELAY) to power on and start taking 29*90f7e76eSYassine Oudjana * I2C messages. Based on AK7371 datasheet. 30*90f7e76eSYassine Oudjana */ 31*90f7e76eSYassine Oudjana #define AK7375_POWER_DELAY_US 10000 3290ee26fbSBingbu Cao 3390ee26fbSBingbu Cao #define AK7375_REG_POSITION 0x0 3490ee26fbSBingbu Cao #define AK7375_REG_CONT 0x2 3590ee26fbSBingbu Cao #define AK7375_MODE_ACTIVE 0x0 3690ee26fbSBingbu Cao #define AK7375_MODE_STANDBY 0x40 3790ee26fbSBingbu Cao 38*90f7e76eSYassine Oudjana static const char * const ak7375_supply_names[] = { 39*90f7e76eSYassine Oudjana "vdd", 40*90f7e76eSYassine Oudjana "vio", 41*90f7e76eSYassine Oudjana }; 42*90f7e76eSYassine Oudjana 4390ee26fbSBingbu Cao /* ak7375 device structure */ 4490ee26fbSBingbu Cao struct ak7375_device { 4590ee26fbSBingbu Cao struct v4l2_ctrl_handler ctrls_vcm; 4690ee26fbSBingbu Cao struct v4l2_subdev sd; 4790ee26fbSBingbu Cao struct v4l2_ctrl *focus; 48*90f7e76eSYassine Oudjana struct regulator_bulk_data supplies[ARRAY_SIZE(ak7375_supply_names)]; 49*90f7e76eSYassine Oudjana 5090ee26fbSBingbu Cao /* active or standby mode */ 5190ee26fbSBingbu Cao bool active; 5290ee26fbSBingbu Cao }; 5390ee26fbSBingbu Cao 5490ee26fbSBingbu Cao static inline struct ak7375_device *to_ak7375_vcm(struct v4l2_ctrl *ctrl) 5590ee26fbSBingbu Cao { 5690ee26fbSBingbu Cao return container_of(ctrl->handler, struct ak7375_device, ctrls_vcm); 5790ee26fbSBingbu Cao } 5890ee26fbSBingbu Cao 5990ee26fbSBingbu Cao static inline struct ak7375_device *sd_to_ak7375_vcm(struct v4l2_subdev *subdev) 6090ee26fbSBingbu Cao { 6190ee26fbSBingbu Cao return container_of(subdev, struct ak7375_device, sd); 6290ee26fbSBingbu Cao } 6390ee26fbSBingbu Cao 6490ee26fbSBingbu Cao static int ak7375_i2c_write(struct ak7375_device *ak7375, 6590ee26fbSBingbu Cao u8 addr, u16 data, u8 size) 6690ee26fbSBingbu Cao { 6790ee26fbSBingbu Cao struct i2c_client *client = v4l2_get_subdevdata(&ak7375->sd); 6890ee26fbSBingbu Cao u8 buf[3]; 6990ee26fbSBingbu Cao int ret; 7090ee26fbSBingbu Cao 7190ee26fbSBingbu Cao if (size != 1 && size != 2) 7290ee26fbSBingbu Cao return -EINVAL; 7390ee26fbSBingbu Cao buf[0] = addr; 7490ee26fbSBingbu Cao buf[size] = data & 0xff; 7590ee26fbSBingbu Cao if (size == 2) 7690ee26fbSBingbu Cao buf[1] = (data >> 8) & 0xff; 7790ee26fbSBingbu Cao ret = i2c_master_send(client, (const char *)buf, size + 1); 7890ee26fbSBingbu Cao if (ret < 0) 7990ee26fbSBingbu Cao return ret; 8090ee26fbSBingbu Cao if (ret != size + 1) 8190ee26fbSBingbu Cao return -EIO; 8290ee26fbSBingbu Cao 8390ee26fbSBingbu Cao return 0; 8490ee26fbSBingbu Cao } 8590ee26fbSBingbu Cao 8690ee26fbSBingbu Cao static int ak7375_set_ctrl(struct v4l2_ctrl *ctrl) 8790ee26fbSBingbu Cao { 8890ee26fbSBingbu Cao struct ak7375_device *dev_vcm = to_ak7375_vcm(ctrl); 8990ee26fbSBingbu Cao 9090ee26fbSBingbu Cao if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) 9190ee26fbSBingbu Cao return ak7375_i2c_write(dev_vcm, AK7375_REG_POSITION, 9290ee26fbSBingbu Cao ctrl->val << 4, 2); 9390ee26fbSBingbu Cao 9490ee26fbSBingbu Cao return -EINVAL; 9590ee26fbSBingbu Cao } 9690ee26fbSBingbu Cao 9790ee26fbSBingbu Cao static const struct v4l2_ctrl_ops ak7375_vcm_ctrl_ops = { 9890ee26fbSBingbu Cao .s_ctrl = ak7375_set_ctrl, 9990ee26fbSBingbu Cao }; 10090ee26fbSBingbu Cao 10190ee26fbSBingbu Cao static int ak7375_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 10290ee26fbSBingbu Cao { 103401b0e5dSMauro Carvalho Chehab return pm_runtime_resume_and_get(sd->dev); 10490ee26fbSBingbu Cao } 10590ee26fbSBingbu Cao 10690ee26fbSBingbu Cao static int ak7375_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) 10790ee26fbSBingbu Cao { 10890ee26fbSBingbu Cao pm_runtime_put(sd->dev); 10990ee26fbSBingbu Cao 11090ee26fbSBingbu Cao return 0; 11190ee26fbSBingbu Cao } 11290ee26fbSBingbu Cao 11390ee26fbSBingbu Cao static const struct v4l2_subdev_internal_ops ak7375_int_ops = { 11490ee26fbSBingbu Cao .open = ak7375_open, 11590ee26fbSBingbu Cao .close = ak7375_close, 11690ee26fbSBingbu Cao }; 11790ee26fbSBingbu Cao 11890ee26fbSBingbu Cao static const struct v4l2_subdev_ops ak7375_ops = { }; 11990ee26fbSBingbu Cao 12090ee26fbSBingbu Cao static void ak7375_subdev_cleanup(struct ak7375_device *ak7375_dev) 12190ee26fbSBingbu Cao { 12290ee26fbSBingbu Cao v4l2_async_unregister_subdev(&ak7375_dev->sd); 12390ee26fbSBingbu Cao v4l2_ctrl_handler_free(&ak7375_dev->ctrls_vcm); 12490ee26fbSBingbu Cao media_entity_cleanup(&ak7375_dev->sd.entity); 12590ee26fbSBingbu Cao } 12690ee26fbSBingbu Cao 12790ee26fbSBingbu Cao static int ak7375_init_controls(struct ak7375_device *dev_vcm) 12890ee26fbSBingbu Cao { 12990ee26fbSBingbu Cao struct v4l2_ctrl_handler *hdl = &dev_vcm->ctrls_vcm; 13090ee26fbSBingbu Cao const struct v4l2_ctrl_ops *ops = &ak7375_vcm_ctrl_ops; 13190ee26fbSBingbu Cao 13290ee26fbSBingbu Cao v4l2_ctrl_handler_init(hdl, 1); 13390ee26fbSBingbu Cao 13490ee26fbSBingbu Cao dev_vcm->focus = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE, 13590ee26fbSBingbu Cao 0, AK7375_MAX_FOCUS_POS, AK7375_FOCUS_STEPS, 0); 13690ee26fbSBingbu Cao 13790ee26fbSBingbu Cao if (hdl->error) 13890ee26fbSBingbu Cao dev_err(dev_vcm->sd.dev, "%s fail error: 0x%x\n", 13990ee26fbSBingbu Cao __func__, hdl->error); 14090ee26fbSBingbu Cao dev_vcm->sd.ctrl_handler = hdl; 14190ee26fbSBingbu Cao 14290ee26fbSBingbu Cao return hdl->error; 14390ee26fbSBingbu Cao } 14490ee26fbSBingbu Cao 14590ee26fbSBingbu Cao static int ak7375_probe(struct i2c_client *client) 14690ee26fbSBingbu Cao { 14790ee26fbSBingbu Cao struct ak7375_device *ak7375_dev; 14890ee26fbSBingbu Cao int ret; 149*90f7e76eSYassine Oudjana unsigned int i; 15090ee26fbSBingbu Cao 15190ee26fbSBingbu Cao ak7375_dev = devm_kzalloc(&client->dev, sizeof(*ak7375_dev), 15290ee26fbSBingbu Cao GFP_KERNEL); 15390ee26fbSBingbu Cao if (!ak7375_dev) 15490ee26fbSBingbu Cao return -ENOMEM; 15590ee26fbSBingbu Cao 156*90f7e76eSYassine Oudjana for (i = 0; i < ARRAY_SIZE(ak7375_supply_names); i++) 157*90f7e76eSYassine Oudjana ak7375_dev->supplies[i].supply = ak7375_supply_names[i]; 158*90f7e76eSYassine Oudjana 159*90f7e76eSYassine Oudjana ret = devm_regulator_bulk_get(&client->dev, 160*90f7e76eSYassine Oudjana ARRAY_SIZE(ak7375_supply_names), 161*90f7e76eSYassine Oudjana ak7375_dev->supplies); 162*90f7e76eSYassine Oudjana if (ret) { 163*90f7e76eSYassine Oudjana dev_err_probe(&client->dev, ret, "Failed to get regulators\n"); 164*90f7e76eSYassine Oudjana return ret; 165*90f7e76eSYassine Oudjana } 166*90f7e76eSYassine Oudjana 16790ee26fbSBingbu Cao v4l2_i2c_subdev_init(&ak7375_dev->sd, client, &ak7375_ops); 16890ee26fbSBingbu Cao ak7375_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 16990ee26fbSBingbu Cao ak7375_dev->sd.internal_ops = &ak7375_int_ops; 17090ee26fbSBingbu Cao ak7375_dev->sd.entity.function = MEDIA_ENT_F_LENS; 17190ee26fbSBingbu Cao 17290ee26fbSBingbu Cao ret = ak7375_init_controls(ak7375_dev); 17390ee26fbSBingbu Cao if (ret) 17490ee26fbSBingbu Cao goto err_cleanup; 17590ee26fbSBingbu Cao 17690ee26fbSBingbu Cao ret = media_entity_pads_init(&ak7375_dev->sd.entity, 0, NULL); 17790ee26fbSBingbu Cao if (ret < 0) 17890ee26fbSBingbu Cao goto err_cleanup; 17990ee26fbSBingbu Cao 18090ee26fbSBingbu Cao ret = v4l2_async_register_subdev(&ak7375_dev->sd); 18190ee26fbSBingbu Cao if (ret < 0) 18290ee26fbSBingbu Cao goto err_cleanup; 18390ee26fbSBingbu Cao 18490ee26fbSBingbu Cao pm_runtime_set_active(&client->dev); 18590ee26fbSBingbu Cao pm_runtime_enable(&client->dev); 18690ee26fbSBingbu Cao pm_runtime_idle(&client->dev); 18790ee26fbSBingbu Cao 18890ee26fbSBingbu Cao return 0; 18990ee26fbSBingbu Cao 19090ee26fbSBingbu Cao err_cleanup: 19190ee26fbSBingbu Cao v4l2_ctrl_handler_free(&ak7375_dev->ctrls_vcm); 19290ee26fbSBingbu Cao media_entity_cleanup(&ak7375_dev->sd.entity); 19390ee26fbSBingbu Cao 19490ee26fbSBingbu Cao return ret; 19590ee26fbSBingbu Cao } 19690ee26fbSBingbu Cao 197ed5c2f5fSUwe Kleine-König static void ak7375_remove(struct i2c_client *client) 19890ee26fbSBingbu Cao { 19990ee26fbSBingbu Cao struct v4l2_subdev *sd = i2c_get_clientdata(client); 20090ee26fbSBingbu Cao struct ak7375_device *ak7375_dev = sd_to_ak7375_vcm(sd); 20190ee26fbSBingbu Cao 20290ee26fbSBingbu Cao ak7375_subdev_cleanup(ak7375_dev); 20390ee26fbSBingbu Cao pm_runtime_disable(&client->dev); 20490ee26fbSBingbu Cao pm_runtime_set_suspended(&client->dev); 20590ee26fbSBingbu Cao } 20690ee26fbSBingbu Cao 20790ee26fbSBingbu Cao /* 20890ee26fbSBingbu Cao * This function sets the vcm position, so it consumes least current 20990ee26fbSBingbu Cao * The lens position is gradually moved in units of AK7375_CTRL_STEPS, 21090ee26fbSBingbu Cao * to make the movements smoothly. 21190ee26fbSBingbu Cao */ 21290ee26fbSBingbu Cao static int __maybe_unused ak7375_vcm_suspend(struct device *dev) 21390ee26fbSBingbu Cao { 214334abb57SKrzysztof Kozlowski struct v4l2_subdev *sd = dev_get_drvdata(dev); 21590ee26fbSBingbu Cao struct ak7375_device *ak7375_dev = sd_to_ak7375_vcm(sd); 21690ee26fbSBingbu Cao int ret, val; 21790ee26fbSBingbu Cao 21890ee26fbSBingbu Cao if (!ak7375_dev->active) 21990ee26fbSBingbu Cao return 0; 22090ee26fbSBingbu Cao 22190ee26fbSBingbu Cao for (val = ak7375_dev->focus->val & ~(AK7375_CTRL_STEPS - 1); 22290ee26fbSBingbu Cao val >= 0; val -= AK7375_CTRL_STEPS) { 22390ee26fbSBingbu Cao ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_POSITION, 22490ee26fbSBingbu Cao val << 4, 2); 22590ee26fbSBingbu Cao if (ret) 22690ee26fbSBingbu Cao dev_err_once(dev, "%s I2C failure: %d\n", 22790ee26fbSBingbu Cao __func__, ret); 22890ee26fbSBingbu Cao usleep_range(AK7375_CTRL_DELAY_US, AK7375_CTRL_DELAY_US + 10); 22990ee26fbSBingbu Cao } 23090ee26fbSBingbu Cao 23190ee26fbSBingbu Cao ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_CONT, 23290ee26fbSBingbu Cao AK7375_MODE_STANDBY, 1); 23390ee26fbSBingbu Cao if (ret) 23490ee26fbSBingbu Cao dev_err(dev, "%s I2C failure: %d\n", __func__, ret); 23590ee26fbSBingbu Cao 236*90f7e76eSYassine Oudjana ret = regulator_bulk_disable(ARRAY_SIZE(ak7375_supply_names), 237*90f7e76eSYassine Oudjana ak7375_dev->supplies); 238*90f7e76eSYassine Oudjana if (ret) 239*90f7e76eSYassine Oudjana return ret; 240*90f7e76eSYassine Oudjana 24190ee26fbSBingbu Cao ak7375_dev->active = false; 24290ee26fbSBingbu Cao 24390ee26fbSBingbu Cao return 0; 24490ee26fbSBingbu Cao } 24590ee26fbSBingbu Cao 24690ee26fbSBingbu Cao /* 24790ee26fbSBingbu Cao * This function sets the vcm position to the value set by the user 24890ee26fbSBingbu Cao * through v4l2_ctrl_ops s_ctrl handler 24990ee26fbSBingbu Cao * The lens position is gradually moved in units of AK7375_CTRL_STEPS, 25090ee26fbSBingbu Cao * to make the movements smoothly. 25190ee26fbSBingbu Cao */ 25290ee26fbSBingbu Cao static int __maybe_unused ak7375_vcm_resume(struct device *dev) 25390ee26fbSBingbu Cao { 254334abb57SKrzysztof Kozlowski struct v4l2_subdev *sd = dev_get_drvdata(dev); 25590ee26fbSBingbu Cao struct ak7375_device *ak7375_dev = sd_to_ak7375_vcm(sd); 25690ee26fbSBingbu Cao int ret, val; 25790ee26fbSBingbu Cao 25890ee26fbSBingbu Cao if (ak7375_dev->active) 25990ee26fbSBingbu Cao return 0; 26090ee26fbSBingbu Cao 261*90f7e76eSYassine Oudjana ret = regulator_bulk_enable(ARRAY_SIZE(ak7375_supply_names), 262*90f7e76eSYassine Oudjana ak7375_dev->supplies); 263*90f7e76eSYassine Oudjana if (ret) 264*90f7e76eSYassine Oudjana return ret; 265*90f7e76eSYassine Oudjana 266*90f7e76eSYassine Oudjana /* Wait for vcm to become ready */ 267*90f7e76eSYassine Oudjana usleep_range(AK7375_POWER_DELAY_US, AK7375_POWER_DELAY_US + 500); 268*90f7e76eSYassine Oudjana 26990ee26fbSBingbu Cao ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_CONT, 27090ee26fbSBingbu Cao AK7375_MODE_ACTIVE, 1); 27190ee26fbSBingbu Cao if (ret) { 27290ee26fbSBingbu Cao dev_err(dev, "%s I2C failure: %d\n", __func__, ret); 27390ee26fbSBingbu Cao return ret; 27490ee26fbSBingbu Cao } 27590ee26fbSBingbu Cao 27690ee26fbSBingbu Cao for (val = ak7375_dev->focus->val % AK7375_CTRL_STEPS; 27790ee26fbSBingbu Cao val <= ak7375_dev->focus->val; 27890ee26fbSBingbu Cao val += AK7375_CTRL_STEPS) { 27990ee26fbSBingbu Cao ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_POSITION, 28090ee26fbSBingbu Cao val << 4, 2); 28190ee26fbSBingbu Cao if (ret) 28290ee26fbSBingbu Cao dev_err_ratelimited(dev, "%s I2C failure: %d\n", 28390ee26fbSBingbu Cao __func__, ret); 28490ee26fbSBingbu Cao usleep_range(AK7375_CTRL_DELAY_US, AK7375_CTRL_DELAY_US + 10); 28590ee26fbSBingbu Cao } 28690ee26fbSBingbu Cao 28790ee26fbSBingbu Cao ak7375_dev->active = true; 28890ee26fbSBingbu Cao 28990ee26fbSBingbu Cao return 0; 29090ee26fbSBingbu Cao } 29190ee26fbSBingbu Cao 29290ee26fbSBingbu Cao static const struct of_device_id ak7375_of_table[] = { 29390ee26fbSBingbu Cao { .compatible = "asahi-kasei,ak7375" }, 29490ee26fbSBingbu Cao { /* sentinel */ } 29590ee26fbSBingbu Cao }; 29690ee26fbSBingbu Cao MODULE_DEVICE_TABLE(of, ak7375_of_table); 29790ee26fbSBingbu Cao 29890ee26fbSBingbu Cao static const struct dev_pm_ops ak7375_pm_ops = { 29990ee26fbSBingbu Cao SET_SYSTEM_SLEEP_PM_OPS(ak7375_vcm_suspend, ak7375_vcm_resume) 30090ee26fbSBingbu Cao SET_RUNTIME_PM_OPS(ak7375_vcm_suspend, ak7375_vcm_resume, NULL) 30190ee26fbSBingbu Cao }; 30290ee26fbSBingbu Cao 30390ee26fbSBingbu Cao static struct i2c_driver ak7375_i2c_driver = { 30490ee26fbSBingbu Cao .driver = { 30590ee26fbSBingbu Cao .name = "ak7375", 30690ee26fbSBingbu Cao .pm = &ak7375_pm_ops, 30790ee26fbSBingbu Cao .of_match_table = ak7375_of_table, 30890ee26fbSBingbu Cao }, 30990ee26fbSBingbu Cao .probe_new = ak7375_probe, 31090ee26fbSBingbu Cao .remove = ak7375_remove, 31190ee26fbSBingbu Cao }; 31290ee26fbSBingbu Cao module_i2c_driver(ak7375_i2c_driver); 31390ee26fbSBingbu Cao 31490ee26fbSBingbu Cao MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@intel.com>"); 31590ee26fbSBingbu Cao MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>"); 31690ee26fbSBingbu Cao MODULE_DESCRIPTION("AK7375 VCM driver"); 31790ee26fbSBingbu Cao MODULE_LICENSE("GPL v2"); 318