xref: /openbmc/linux/drivers/media/i2c/dw9768.c (revision aaeb31c0)
185989122SDongchun Zhu // SPDX-License-Identifier: GPL-2.0
285989122SDongchun Zhu // Copyright (c) 2020 MediaTek Inc.
385989122SDongchun Zhu 
485989122SDongchun Zhu #include <linux/delay.h>
585989122SDongchun Zhu #include <linux/i2c.h>
685989122SDongchun Zhu #include <linux/module.h>
785989122SDongchun Zhu #include <linux/pm_runtime.h>
885989122SDongchun Zhu #include <linux/regulator/consumer.h>
985989122SDongchun Zhu #include <media/v4l2-async.h>
1085989122SDongchun Zhu #include <media/v4l2-ctrls.h>
1185989122SDongchun Zhu #include <media/v4l2-device.h>
1285989122SDongchun Zhu #include <media/v4l2-fwnode.h>
1385989122SDongchun Zhu #include <media/v4l2-subdev.h>
1485989122SDongchun Zhu 
1585989122SDongchun Zhu #define DW9768_NAME				"dw9768"
1685989122SDongchun Zhu #define DW9768_MAX_FOCUS_POS			(1024 - 1)
1785989122SDongchun Zhu /*
1885989122SDongchun Zhu  * This sets the minimum granularity for the focus positions.
1985989122SDongchun Zhu  * A value of 1 gives maximum accuracy for a desired focus position
2085989122SDongchun Zhu  */
2185989122SDongchun Zhu #define DW9768_FOCUS_STEPS			1
2285989122SDongchun Zhu 
2385989122SDongchun Zhu /*
2485989122SDongchun Zhu  * Ring control and Power control register
2585989122SDongchun Zhu  * Bit[1] RING_EN
2685989122SDongchun Zhu  * 0: Direct mode
2785989122SDongchun Zhu  * 1: AAC mode (ringing control mode)
2885989122SDongchun Zhu  * Bit[0] PD
2985989122SDongchun Zhu  * 0: Normal operation mode
3085989122SDongchun Zhu  * 1: Power down mode
3185989122SDongchun Zhu  * DW9768 requires waiting time of Topr after PD reset takes place.
3285989122SDongchun Zhu  */
3385989122SDongchun Zhu #define DW9768_RING_PD_CONTROL_REG		0x02
3485989122SDongchun Zhu #define DW9768_PD_MODE_OFF			0x00
3585989122SDongchun Zhu #define DW9768_PD_MODE_EN			BIT(0)
3685989122SDongchun Zhu #define DW9768_AAC_MODE_EN			BIT(1)
3785989122SDongchun Zhu 
3885989122SDongchun Zhu /*
3985989122SDongchun Zhu  * DW9768 separates two registers to control the VCM position.
4085989122SDongchun Zhu  * One for MSB value, another is LSB value.
4185989122SDongchun Zhu  * DAC_MSB: D[9:8] (ADD: 0x03)
4285989122SDongchun Zhu  * DAC_LSB: D[7:0] (ADD: 0x04)
4385989122SDongchun Zhu  * D[9:0] DAC data input: positive output current = D[9:0] / 1023 * 100[mA]
4485989122SDongchun Zhu  */
4585989122SDongchun Zhu #define DW9768_MSB_ADDR				0x03
4685989122SDongchun Zhu #define DW9768_LSB_ADDR				0x04
4785989122SDongchun Zhu #define DW9768_STATUS_ADDR			0x05
4885989122SDongchun Zhu 
4985989122SDongchun Zhu /*
5085989122SDongchun Zhu  * AAC mode control & prescale register
5185989122SDongchun Zhu  * Bit[7:5] Namely AC[2:0], decide the VCM mode and operation time.
5285989122SDongchun Zhu  * 001 AAC2 0.48 x Tvib
5385989122SDongchun Zhu  * 010 AAC3 0.70 x Tvib
5485989122SDongchun Zhu  * 011 AAC4 0.75 x Tvib
5585989122SDongchun Zhu  * 101 AAC8 1.13 x Tvib
5685989122SDongchun Zhu  * Bit[2:0] Namely PRESC[2:0], set the internal clock dividing rate as follow.
5785989122SDongchun Zhu  * 000 2
5885989122SDongchun Zhu  * 001 1
5985989122SDongchun Zhu  * 010 1/2
6085989122SDongchun Zhu  * 011 1/4
6185989122SDongchun Zhu  * 100 8
6285989122SDongchun Zhu  * 101 4
6385989122SDongchun Zhu  */
6485989122SDongchun Zhu #define DW9768_AAC_PRESC_REG			0x06
6585989122SDongchun Zhu #define DW9768_AAC_MODE_SEL_MASK		GENMASK(7, 5)
6685989122SDongchun Zhu #define DW9768_CLOCK_PRE_SCALE_SEL_MASK		GENMASK(2, 0)
6785989122SDongchun Zhu 
6885989122SDongchun Zhu /*
6985989122SDongchun Zhu  * VCM period of vibration register
7085989122SDongchun Zhu  * Bit[5:0] Defined as VCM rising periodic time (Tvib) together with PRESC[2:0]
7185989122SDongchun Zhu  * Tvib = (6.3ms + AACT[5:0] * 0.1ms) * Dividing Rate
7285989122SDongchun Zhu  * Dividing Rate is the internal clock dividing rate that is defined at
7385989122SDongchun Zhu  * PRESCALE register (ADD: 0x06)
7485989122SDongchun Zhu  */
7585989122SDongchun Zhu #define DW9768_AAC_TIME_REG			0x07
7685989122SDongchun Zhu 
7785989122SDongchun Zhu /*
7885989122SDongchun Zhu  * DW9768 requires waiting time (delay time) of t_OPR after power-up,
7985989122SDongchun Zhu  * or in the case of PD reset taking place.
8085989122SDongchun Zhu  */
8185989122SDongchun Zhu #define DW9768_T_OPR_US				1000
8285989122SDongchun Zhu #define DW9768_TVIB_MS_BASE10			(64 - 1)
8385989122SDongchun Zhu #define DW9768_AAC_MODE_DEFAULT			2
8485989122SDongchun Zhu #define DW9768_AAC_TIME_DEFAULT			0x20
8585989122SDongchun Zhu #define DW9768_CLOCK_PRE_SCALE_DEFAULT		1
8685989122SDongchun Zhu 
8785989122SDongchun Zhu /*
8885989122SDongchun Zhu  * This acts as the minimum granularity of lens movement.
8985989122SDongchun Zhu  * Keep this value power of 2, so the control steps can be
9085989122SDongchun Zhu  * uniformly adjusted for gradual lens movement, with desired
9185989122SDongchun Zhu  * number of control steps.
9285989122SDongchun Zhu  */
9385989122SDongchun Zhu #define DW9768_MOVE_STEPS			16
9485989122SDongchun Zhu 
9585989122SDongchun Zhu static const char * const dw9768_supply_names[] = {
9685989122SDongchun Zhu 	"vin",	/* Digital I/O power */
9785989122SDongchun Zhu 	"vdd",	/* Digital core power */
9885989122SDongchun Zhu };
9985989122SDongchun Zhu 
10085989122SDongchun Zhu /* dw9768 device structure */
10185989122SDongchun Zhu struct dw9768 {
10285989122SDongchun Zhu 	struct regulator_bulk_data supplies[ARRAY_SIZE(dw9768_supply_names)];
10385989122SDongchun Zhu 	struct v4l2_ctrl_handler ctrls;
10485989122SDongchun Zhu 	struct v4l2_ctrl *focus;
10585989122SDongchun Zhu 	struct v4l2_subdev sd;
10685989122SDongchun Zhu 
10785989122SDongchun Zhu 	u32 aac_mode;
10885989122SDongchun Zhu 	u32 aac_timing;
10985989122SDongchun Zhu 	u32 clock_presc;
11085989122SDongchun Zhu 	u32 move_delay_us;
11185989122SDongchun Zhu };
11285989122SDongchun Zhu 
sd_to_dw9768(struct v4l2_subdev * subdev)11385989122SDongchun Zhu static inline struct dw9768 *sd_to_dw9768(struct v4l2_subdev *subdev)
11485989122SDongchun Zhu {
11585989122SDongchun Zhu 	return container_of(subdev, struct dw9768, sd);
11685989122SDongchun Zhu }
11785989122SDongchun Zhu 
11885989122SDongchun Zhu struct regval_list {
11985989122SDongchun Zhu 	u8 reg_num;
12085989122SDongchun Zhu 	u8 value;
12185989122SDongchun Zhu };
12285989122SDongchun Zhu 
12385989122SDongchun Zhu struct dw9768_aac_mode_ot_multi {
12485989122SDongchun Zhu 	u32 aac_mode_enum;
12585989122SDongchun Zhu 	u32 ot_multi_base100;
12685989122SDongchun Zhu };
12785989122SDongchun Zhu 
12885989122SDongchun Zhu struct dw9768_clk_presc_dividing_rate {
12985989122SDongchun Zhu 	u32 clk_presc_enum;
13085989122SDongchun Zhu 	u32 dividing_rate_base100;
13185989122SDongchun Zhu };
13285989122SDongchun Zhu 
13385989122SDongchun Zhu static const struct dw9768_aac_mode_ot_multi aac_mode_ot_multi[] = {
13485989122SDongchun Zhu 	{1,  48},
13585989122SDongchun Zhu 	{2,  70},
13685989122SDongchun Zhu 	{3,  75},
13785989122SDongchun Zhu 	{5, 113},
13885989122SDongchun Zhu };
13985989122SDongchun Zhu 
14085989122SDongchun Zhu static const struct dw9768_clk_presc_dividing_rate presc_dividing_rate[] = {
14185989122SDongchun Zhu 	{0, 200},
14285989122SDongchun Zhu 	{1, 100},
14385989122SDongchun Zhu 	{2,  50},
14485989122SDongchun Zhu 	{3,  25},
14585989122SDongchun Zhu 	{4, 800},
14685989122SDongchun Zhu 	{5, 400},
14785989122SDongchun Zhu };
14885989122SDongchun Zhu 
dw9768_find_ot_multi(u32 aac_mode_param)14985989122SDongchun Zhu static u32 dw9768_find_ot_multi(u32 aac_mode_param)
15085989122SDongchun Zhu {
15185989122SDongchun Zhu 	u32 cur_ot_multi_base100 = 70;
15285989122SDongchun Zhu 	unsigned int i;
15385989122SDongchun Zhu 
15485989122SDongchun Zhu 	for (i = 0; i < ARRAY_SIZE(aac_mode_ot_multi); i++) {
15585989122SDongchun Zhu 		if (aac_mode_ot_multi[i].aac_mode_enum == aac_mode_param) {
15685989122SDongchun Zhu 			cur_ot_multi_base100 =
15785989122SDongchun Zhu 				aac_mode_ot_multi[i].ot_multi_base100;
15885989122SDongchun Zhu 		}
15985989122SDongchun Zhu 	}
16085989122SDongchun Zhu 
16185989122SDongchun Zhu 	return cur_ot_multi_base100;
16285989122SDongchun Zhu }
16385989122SDongchun Zhu 
dw9768_find_dividing_rate(u32 presc_param)16485989122SDongchun Zhu static u32 dw9768_find_dividing_rate(u32 presc_param)
16585989122SDongchun Zhu {
16685989122SDongchun Zhu 	u32 cur_clk_dividing_rate_base100 = 100;
16785989122SDongchun Zhu 	unsigned int i;
16885989122SDongchun Zhu 
16985989122SDongchun Zhu 	for (i = 0; i < ARRAY_SIZE(presc_dividing_rate); i++) {
17085989122SDongchun Zhu 		if (presc_dividing_rate[i].clk_presc_enum == presc_param) {
17185989122SDongchun Zhu 			cur_clk_dividing_rate_base100 =
17285989122SDongchun Zhu 				presc_dividing_rate[i].dividing_rate_base100;
17385989122SDongchun Zhu 		}
17485989122SDongchun Zhu 	}
17585989122SDongchun Zhu 
17685989122SDongchun Zhu 	return cur_clk_dividing_rate_base100;
17785989122SDongchun Zhu }
17885989122SDongchun Zhu 
17985989122SDongchun Zhu /*
18085989122SDongchun Zhu  * DW9768_AAC_PRESC_REG & DW9768_AAC_TIME_REG determine VCM operation time.
18185989122SDongchun Zhu  * For current VCM mode: AAC3, Operation Time would be 0.70 x Tvib.
18285989122SDongchun Zhu  * Tvib = (6.3ms + AACT[5:0] * 0.1MS) * Dividing Rate.
18385989122SDongchun Zhu  * Below is calculation of the operation delay for each step.
18485989122SDongchun Zhu  */
dw9768_cal_move_delay(u32 aac_mode_param,u32 presc_param,u32 aac_timing_param)18585989122SDongchun Zhu static inline u32 dw9768_cal_move_delay(u32 aac_mode_param, u32 presc_param,
18685989122SDongchun Zhu 					u32 aac_timing_param)
18785989122SDongchun Zhu {
18885989122SDongchun Zhu 	u32 Tvib_us;
18985989122SDongchun Zhu 	u32 ot_multi_base100;
19085989122SDongchun Zhu 	u32 clk_dividing_rate_base100;
19185989122SDongchun Zhu 
19285989122SDongchun Zhu 	ot_multi_base100 = dw9768_find_ot_multi(aac_mode_param);
19385989122SDongchun Zhu 
19485989122SDongchun Zhu 	clk_dividing_rate_base100 = dw9768_find_dividing_rate(presc_param);
19585989122SDongchun Zhu 
19685989122SDongchun Zhu 	Tvib_us = (DW9768_TVIB_MS_BASE10 + aac_timing_param) *
19785989122SDongchun Zhu 		  clk_dividing_rate_base100;
19885989122SDongchun Zhu 
19985989122SDongchun Zhu 	return Tvib_us * ot_multi_base100 / 100;
20085989122SDongchun Zhu }
20185989122SDongchun Zhu 
dw9768_mod_reg(struct dw9768 * dw9768,u8 reg,u8 mask,u8 val)20285989122SDongchun Zhu static int dw9768_mod_reg(struct dw9768 *dw9768, u8 reg, u8 mask, u8 val)
20385989122SDongchun Zhu {
20485989122SDongchun Zhu 	struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd);
20585989122SDongchun Zhu 	int ret;
20685989122SDongchun Zhu 
20785989122SDongchun Zhu 	ret = i2c_smbus_read_byte_data(client, reg);
20885989122SDongchun Zhu 	if (ret < 0)
20985989122SDongchun Zhu 		return ret;
21085989122SDongchun Zhu 
21185989122SDongchun Zhu 	val = ((unsigned char)ret & ~mask) | (val & mask);
21285989122SDongchun Zhu 
21385989122SDongchun Zhu 	return i2c_smbus_write_byte_data(client, reg, val);
21485989122SDongchun Zhu }
21585989122SDongchun Zhu 
dw9768_set_dac(struct dw9768 * dw9768,u16 val)21685989122SDongchun Zhu static int dw9768_set_dac(struct dw9768 *dw9768, u16 val)
21785989122SDongchun Zhu {
21885989122SDongchun Zhu 	struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd);
21985989122SDongchun Zhu 
22085989122SDongchun Zhu 	/* Write VCM position to registers */
22185989122SDongchun Zhu 	return i2c_smbus_write_word_swapped(client, DW9768_MSB_ADDR, val);
22285989122SDongchun Zhu }
22385989122SDongchun Zhu 
dw9768_init(struct dw9768 * dw9768)22485989122SDongchun Zhu static int dw9768_init(struct dw9768 *dw9768)
22585989122SDongchun Zhu {
22685989122SDongchun Zhu 	struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd);
22785989122SDongchun Zhu 	int ret, val;
22885989122SDongchun Zhu 
22985989122SDongchun Zhu 	/* Reset DW9768_RING_PD_CONTROL_REG to default status 0x00 */
23085989122SDongchun Zhu 	ret = i2c_smbus_write_byte_data(client, DW9768_RING_PD_CONTROL_REG,
23185989122SDongchun Zhu 					DW9768_PD_MODE_OFF);
23285989122SDongchun Zhu 	if (ret < 0)
23385989122SDongchun Zhu 		return ret;
23485989122SDongchun Zhu 
23585989122SDongchun Zhu 	/*
23685989122SDongchun Zhu 	 * DW9769 requires waiting delay time of t_OPR
23785989122SDongchun Zhu 	 * after PD reset takes place.
23885989122SDongchun Zhu 	 */
23985989122SDongchun Zhu 	usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100);
24085989122SDongchun Zhu 
24185989122SDongchun Zhu 	/* Set DW9768_RING_PD_CONTROL_REG to DW9768_AAC_MODE_EN(0x01) */
24285989122SDongchun Zhu 	ret = i2c_smbus_write_byte_data(client, DW9768_RING_PD_CONTROL_REG,
24385989122SDongchun Zhu 					DW9768_AAC_MODE_EN);
24485989122SDongchun Zhu 	if (ret < 0)
24585989122SDongchun Zhu 		return ret;
24685989122SDongchun Zhu 
24785989122SDongchun Zhu 	/* Set AAC mode */
24885989122SDongchun Zhu 	ret = dw9768_mod_reg(dw9768, DW9768_AAC_PRESC_REG,
24985989122SDongchun Zhu 			     DW9768_AAC_MODE_SEL_MASK,
25085989122SDongchun Zhu 			     dw9768->aac_mode << 5);
25185989122SDongchun Zhu 	if (ret < 0)
25285989122SDongchun Zhu 		return ret;
25385989122SDongchun Zhu 
25485989122SDongchun Zhu 	/* Set clock presc */
25585989122SDongchun Zhu 	if (dw9768->clock_presc != DW9768_CLOCK_PRE_SCALE_DEFAULT) {
25685989122SDongchun Zhu 		ret = dw9768_mod_reg(dw9768, DW9768_AAC_PRESC_REG,
25785989122SDongchun Zhu 				     DW9768_CLOCK_PRE_SCALE_SEL_MASK,
25885989122SDongchun Zhu 				     dw9768->clock_presc);
25985989122SDongchun Zhu 		if (ret < 0)
26085989122SDongchun Zhu 			return ret;
26185989122SDongchun Zhu 	}
26285989122SDongchun Zhu 
26385989122SDongchun Zhu 	/* Set AAC Timing */
26485989122SDongchun Zhu 	if (dw9768->aac_timing != DW9768_AAC_TIME_DEFAULT) {
26585989122SDongchun Zhu 		ret = i2c_smbus_write_byte_data(client, DW9768_AAC_TIME_REG,
26685989122SDongchun Zhu 						dw9768->aac_timing);
26785989122SDongchun Zhu 		if (ret < 0)
26885989122SDongchun Zhu 			return ret;
26985989122SDongchun Zhu 	}
27085989122SDongchun Zhu 
27185989122SDongchun Zhu 	for (val = dw9768->focus->val % DW9768_MOVE_STEPS;
27285989122SDongchun Zhu 	     val <= dw9768->focus->val;
27385989122SDongchun Zhu 	     val += DW9768_MOVE_STEPS) {
27485989122SDongchun Zhu 		ret = dw9768_set_dac(dw9768, val);
27585989122SDongchun Zhu 		if (ret) {
27685989122SDongchun Zhu 			dev_err(&client->dev, "I2C failure: %d", ret);
27785989122SDongchun Zhu 			return ret;
27885989122SDongchun Zhu 		}
27985989122SDongchun Zhu 		usleep_range(dw9768->move_delay_us,
28085989122SDongchun Zhu 			     dw9768->move_delay_us + 1000);
28185989122SDongchun Zhu 	}
28285989122SDongchun Zhu 
28385989122SDongchun Zhu 	return 0;
28485989122SDongchun Zhu }
28585989122SDongchun Zhu 
dw9768_release(struct dw9768 * dw9768)28685989122SDongchun Zhu static int dw9768_release(struct dw9768 *dw9768)
28785989122SDongchun Zhu {
28885989122SDongchun Zhu 	struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd);
28985989122SDongchun Zhu 	int ret, val;
29085989122SDongchun Zhu 
29185989122SDongchun Zhu 	val = round_down(dw9768->focus->val, DW9768_MOVE_STEPS);
29285989122SDongchun Zhu 	for ( ; val >= 0; val -= DW9768_MOVE_STEPS) {
29385989122SDongchun Zhu 		ret = dw9768_set_dac(dw9768, val);
29485989122SDongchun Zhu 		if (ret) {
29585989122SDongchun Zhu 			dev_err(&client->dev, "I2C write fail: %d", ret);
29685989122SDongchun Zhu 			return ret;
29785989122SDongchun Zhu 		}
29885989122SDongchun Zhu 		usleep_range(dw9768->move_delay_us,
29985989122SDongchun Zhu 			     dw9768->move_delay_us + 1000);
30085989122SDongchun Zhu 	}
30185989122SDongchun Zhu 
30285989122SDongchun Zhu 	ret = i2c_smbus_write_byte_data(client, DW9768_RING_PD_CONTROL_REG,
30385989122SDongchun Zhu 					DW9768_PD_MODE_EN);
30485989122SDongchun Zhu 	if (ret < 0)
30585989122SDongchun Zhu 		return ret;
30685989122SDongchun Zhu 
30785989122SDongchun Zhu 	/*
30885989122SDongchun Zhu 	 * DW9769 requires waiting delay time of t_OPR
30985989122SDongchun Zhu 	 * after PD reset takes place.
31085989122SDongchun Zhu 	 */
31185989122SDongchun Zhu 	usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100);
31285989122SDongchun Zhu 
31385989122SDongchun Zhu 	return 0;
31485989122SDongchun Zhu }
31585989122SDongchun Zhu 
dw9768_runtime_suspend(struct device * dev)31685989122SDongchun Zhu static int dw9768_runtime_suspend(struct device *dev)
31785989122SDongchun Zhu {
31892172a31SKrzysztof Kozlowski 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
31985989122SDongchun Zhu 	struct dw9768 *dw9768 = sd_to_dw9768(sd);
32085989122SDongchun Zhu 
32185989122SDongchun Zhu 	dw9768_release(dw9768);
32285989122SDongchun Zhu 	regulator_bulk_disable(ARRAY_SIZE(dw9768_supply_names),
32385989122SDongchun Zhu 			       dw9768->supplies);
32485989122SDongchun Zhu 
32585989122SDongchun Zhu 	return 0;
32685989122SDongchun Zhu }
32785989122SDongchun Zhu 
dw9768_runtime_resume(struct device * dev)32885989122SDongchun Zhu static int dw9768_runtime_resume(struct device *dev)
32985989122SDongchun Zhu {
33092172a31SKrzysztof Kozlowski 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
33185989122SDongchun Zhu 	struct dw9768 *dw9768 = sd_to_dw9768(sd);
33285989122SDongchun Zhu 	int ret;
33385989122SDongchun Zhu 
33485989122SDongchun Zhu 	ret = regulator_bulk_enable(ARRAY_SIZE(dw9768_supply_names),
33585989122SDongchun Zhu 				    dw9768->supplies);
33685989122SDongchun Zhu 	if (ret < 0) {
33785989122SDongchun Zhu 		dev_err(dev, "failed to enable regulators\n");
33885989122SDongchun Zhu 		return ret;
33985989122SDongchun Zhu 	}
34085989122SDongchun Zhu 
34185989122SDongchun Zhu 	/*
34285989122SDongchun Zhu 	 * The datasheet refers to t_OPR that needs to be waited before sending
34385989122SDongchun Zhu 	 * I2C commands after power-up.
34485989122SDongchun Zhu 	 */
34585989122SDongchun Zhu 	usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100);
34685989122SDongchun Zhu 
34785989122SDongchun Zhu 	ret = dw9768_init(dw9768);
34885989122SDongchun Zhu 	if (ret < 0)
34985989122SDongchun Zhu 		goto disable_regulator;
35085989122SDongchun Zhu 
35185989122SDongchun Zhu 	return 0;
35285989122SDongchun Zhu 
35385989122SDongchun Zhu disable_regulator:
35485989122SDongchun Zhu 	regulator_bulk_disable(ARRAY_SIZE(dw9768_supply_names),
35585989122SDongchun Zhu 			       dw9768->supplies);
35685989122SDongchun Zhu 
35785989122SDongchun Zhu 	return ret;
35885989122SDongchun Zhu }
35985989122SDongchun Zhu 
dw9768_set_ctrl(struct v4l2_ctrl * ctrl)36085989122SDongchun Zhu static int dw9768_set_ctrl(struct v4l2_ctrl *ctrl)
36185989122SDongchun Zhu {
36285989122SDongchun Zhu 	struct dw9768 *dw9768 = container_of(ctrl->handler,
36385989122SDongchun Zhu 					     struct dw9768, ctrls);
36485989122SDongchun Zhu 
36585989122SDongchun Zhu 	if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE)
36685989122SDongchun Zhu 		return dw9768_set_dac(dw9768, ctrl->val);
36785989122SDongchun Zhu 
36885989122SDongchun Zhu 	return 0;
36985989122SDongchun Zhu }
37085989122SDongchun Zhu 
37185989122SDongchun Zhu static const struct v4l2_ctrl_ops dw9768_ctrl_ops = {
37285989122SDongchun Zhu 	.s_ctrl = dw9768_set_ctrl,
37385989122SDongchun Zhu };
37485989122SDongchun Zhu 
dw9768_open(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)37585989122SDongchun Zhu static int dw9768_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
37685989122SDongchun Zhu {
377ed8f47b0SMauro Carvalho Chehab 	return pm_runtime_resume_and_get(sd->dev);
37885989122SDongchun Zhu }
37985989122SDongchun Zhu 
dw9768_close(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)38085989122SDongchun Zhu static int dw9768_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
38185989122SDongchun Zhu {
38285989122SDongchun Zhu 	pm_runtime_put(sd->dev);
38385989122SDongchun Zhu 
38485989122SDongchun Zhu 	return 0;
38585989122SDongchun Zhu }
38685989122SDongchun Zhu 
38785989122SDongchun Zhu static const struct v4l2_subdev_internal_ops dw9768_int_ops = {
38885989122SDongchun Zhu 	.open = dw9768_open,
38985989122SDongchun Zhu 	.close = dw9768_close,
39085989122SDongchun Zhu };
39185989122SDongchun Zhu 
39285989122SDongchun Zhu static const struct v4l2_subdev_ops dw9768_ops = { };
39385989122SDongchun Zhu 
dw9768_init_controls(struct dw9768 * dw9768)39485989122SDongchun Zhu static int dw9768_init_controls(struct dw9768 *dw9768)
39585989122SDongchun Zhu {
39685989122SDongchun Zhu 	struct v4l2_ctrl_handler *hdl = &dw9768->ctrls;
39785989122SDongchun Zhu 	const struct v4l2_ctrl_ops *ops = &dw9768_ctrl_ops;
39885989122SDongchun Zhu 
39985989122SDongchun Zhu 	v4l2_ctrl_handler_init(hdl, 1);
40085989122SDongchun Zhu 
40185989122SDongchun Zhu 	dw9768->focus = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE, 0,
40285989122SDongchun Zhu 					  DW9768_MAX_FOCUS_POS,
40385989122SDongchun Zhu 					  DW9768_FOCUS_STEPS, 0);
40485989122SDongchun Zhu 
40585989122SDongchun Zhu 	if (hdl->error)
40685989122SDongchun Zhu 		return hdl->error;
40785989122SDongchun Zhu 
40885989122SDongchun Zhu 	dw9768->sd.ctrl_handler = hdl;
40985989122SDongchun Zhu 
41085989122SDongchun Zhu 	return 0;
41185989122SDongchun Zhu }
41285989122SDongchun Zhu 
dw9768_probe(struct i2c_client * client)41385989122SDongchun Zhu static int dw9768_probe(struct i2c_client *client)
41485989122SDongchun Zhu {
41585989122SDongchun Zhu 	struct device *dev = &client->dev;
41685989122SDongchun Zhu 	struct dw9768 *dw9768;
4175f9a089bSSakari Ailus 	bool full_power;
41885989122SDongchun Zhu 	unsigned int i;
41985989122SDongchun Zhu 	int ret;
42085989122SDongchun Zhu 
42185989122SDongchun Zhu 	dw9768 = devm_kzalloc(dev, sizeof(*dw9768), GFP_KERNEL);
42285989122SDongchun Zhu 	if (!dw9768)
42385989122SDongchun Zhu 		return -ENOMEM;
42485989122SDongchun Zhu 
42585989122SDongchun Zhu 	/* Initialize subdev */
42685989122SDongchun Zhu 	v4l2_i2c_subdev_init(&dw9768->sd, client, &dw9768_ops);
42785989122SDongchun Zhu 
42885989122SDongchun Zhu 	dw9768->aac_mode = DW9768_AAC_MODE_DEFAULT;
42985989122SDongchun Zhu 	dw9768->aac_timing = DW9768_AAC_TIME_DEFAULT;
43085989122SDongchun Zhu 	dw9768->clock_presc = DW9768_CLOCK_PRE_SCALE_DEFAULT;
43185989122SDongchun Zhu 
43285989122SDongchun Zhu 	/* Optional indication of AAC mode select */
43385989122SDongchun Zhu 	fwnode_property_read_u32(dev_fwnode(dev), "dongwoon,aac-mode",
43485989122SDongchun Zhu 				 &dw9768->aac_mode);
43585989122SDongchun Zhu 
43685989122SDongchun Zhu 	/* Optional indication of clock pre-scale select */
43785989122SDongchun Zhu 	fwnode_property_read_u32(dev_fwnode(dev), "dongwoon,clock-presc",
43885989122SDongchun Zhu 				 &dw9768->clock_presc);
43985989122SDongchun Zhu 
44085989122SDongchun Zhu 	/* Optional indication of AAC Timing */
44185989122SDongchun Zhu 	fwnode_property_read_u32(dev_fwnode(dev), "dongwoon,aac-timing",
44285989122SDongchun Zhu 				 &dw9768->aac_timing);
44385989122SDongchun Zhu 
44485989122SDongchun Zhu 	dw9768->move_delay_us = dw9768_cal_move_delay(dw9768->aac_mode,
44585989122SDongchun Zhu 						      dw9768->clock_presc,
44685989122SDongchun Zhu 						      dw9768->aac_timing);
44785989122SDongchun Zhu 
44885989122SDongchun Zhu 	for (i = 0; i < ARRAY_SIZE(dw9768_supply_names); i++)
44985989122SDongchun Zhu 		dw9768->supplies[i].supply = dw9768_supply_names[i];
45085989122SDongchun Zhu 
45185989122SDongchun Zhu 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dw9768_supply_names),
45285989122SDongchun Zhu 				      dw9768->supplies);
45385989122SDongchun Zhu 	if (ret) {
45485989122SDongchun Zhu 		dev_err(dev, "failed to get regulators\n");
45585989122SDongchun Zhu 		return ret;
45685989122SDongchun Zhu 	}
45785989122SDongchun Zhu 
45885989122SDongchun Zhu 	/* Initialize controls */
45985989122SDongchun Zhu 	ret = dw9768_init_controls(dw9768);
46085989122SDongchun Zhu 	if (ret)
46185989122SDongchun Zhu 		goto err_free_handler;
46285989122SDongchun Zhu 
46385989122SDongchun Zhu 	/* Initialize subdev */
46485989122SDongchun Zhu 	dw9768->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
46585989122SDongchun Zhu 	dw9768->sd.internal_ops = &dw9768_int_ops;
46685989122SDongchun Zhu 
46785989122SDongchun Zhu 	ret = media_entity_pads_init(&dw9768->sd.entity, 0, NULL);
46885989122SDongchun Zhu 	if (ret < 0)
46985989122SDongchun Zhu 		goto err_free_handler;
47085989122SDongchun Zhu 
47185989122SDongchun Zhu 	dw9768->sd.entity.function = MEDIA_ENT_F_LENS;
47285989122SDongchun Zhu 
4735f9a089bSSakari Ailus 	/*
4745f9a089bSSakari Ailus 	 * Figure out whether we're going to power up the device here. Generally
4755f9a089bSSakari Ailus 	 * this is done if CONFIG_PM is disabled in a DT system or the device is
4765f9a089bSSakari Ailus 	 * to be powered on in an ACPI system. Similarly for power off in
4775f9a089bSSakari Ailus 	 * remove.
4785f9a089bSSakari Ailus 	 */
47985989122SDongchun Zhu 	pm_runtime_enable(dev);
4805f9a089bSSakari Ailus 	full_power = (is_acpi_node(dev_fwnode(dev)) &&
4815f9a089bSSakari Ailus 		      acpi_dev_state_d0(dev)) ||
4825f9a089bSSakari Ailus 		     (is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev));
4835f9a089bSSakari Ailus 	if (full_power) {
48485989122SDongchun Zhu 		ret = dw9768_runtime_resume(dev);
48585989122SDongchun Zhu 		if (ret < 0) {
48685989122SDongchun Zhu 			dev_err(dev, "failed to power on: %d\n", ret);
48785989122SDongchun Zhu 			goto err_clean_entity;
48885989122SDongchun Zhu 		}
4895f9a089bSSakari Ailus 		pm_runtime_set_active(dev);
49085989122SDongchun Zhu 	}
49185989122SDongchun Zhu 
49285989122SDongchun Zhu 	ret = v4l2_async_register_subdev(&dw9768->sd);
49385989122SDongchun Zhu 	if (ret < 0) {
49485989122SDongchun Zhu 		dev_err(dev, "failed to register V4L2 subdev: %d", ret);
49585989122SDongchun Zhu 		goto err_power_off;
49685989122SDongchun Zhu 	}
49785989122SDongchun Zhu 
4985f9a089bSSakari Ailus 	pm_runtime_idle(dev);
4995f9a089bSSakari Ailus 
50085989122SDongchun Zhu 	return 0;
50185989122SDongchun Zhu 
50285989122SDongchun Zhu err_power_off:
5035f9a089bSSakari Ailus 	if (full_power) {
50485989122SDongchun Zhu 		dw9768_runtime_suspend(dev);
5055f9a089bSSakari Ailus 		pm_runtime_set_suspended(dev);
5065f9a089bSSakari Ailus 	}
50785989122SDongchun Zhu err_clean_entity:
5085f9a089bSSakari Ailus 	pm_runtime_disable(dev);
50985989122SDongchun Zhu 	media_entity_cleanup(&dw9768->sd.entity);
51085989122SDongchun Zhu err_free_handler:
51185989122SDongchun Zhu 	v4l2_ctrl_handler_free(&dw9768->ctrls);
51285989122SDongchun Zhu 
51385989122SDongchun Zhu 	return ret;
51485989122SDongchun Zhu }
51585989122SDongchun Zhu 
dw9768_remove(struct i2c_client * client)516ed5c2f5fSUwe Kleine-König static void dw9768_remove(struct i2c_client *client)
51785989122SDongchun Zhu {
51885989122SDongchun Zhu 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
51985989122SDongchun Zhu 	struct dw9768 *dw9768 = sd_to_dw9768(sd);
5205f9a089bSSakari Ailus 	struct device *dev = &client->dev;
52185989122SDongchun Zhu 
52285989122SDongchun Zhu 	v4l2_async_unregister_subdev(&dw9768->sd);
52385989122SDongchun Zhu 	v4l2_ctrl_handler_free(&dw9768->ctrls);
52485989122SDongchun Zhu 	media_entity_cleanup(&dw9768->sd.entity);
5255f9a089bSSakari Ailus 	if ((is_acpi_node(dev_fwnode(dev)) && acpi_dev_state_d0(dev)) ||
5265f9a089bSSakari Ailus 	    (is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev))) {
5275f9a089bSSakari Ailus 		dw9768_runtime_suspend(dev);
5285f9a089bSSakari Ailus 		pm_runtime_set_suspended(dev);
5295f9a089bSSakari Ailus 	}
5305f9a089bSSakari Ailus 	pm_runtime_disable(dev);
53185989122SDongchun Zhu }
53285989122SDongchun Zhu 
53385989122SDongchun Zhu static const struct of_device_id dw9768_of_table[] = {
53485989122SDongchun Zhu 	{ .compatible = "dongwoon,dw9768" },
53585989122SDongchun Zhu 	{ .compatible = "giantec,gt9769" },
53685989122SDongchun Zhu 	{}
53785989122SDongchun Zhu };
53885989122SDongchun Zhu MODULE_DEVICE_TABLE(of, dw9768_of_table);
53985989122SDongchun Zhu 
54085989122SDongchun Zhu static const struct dev_pm_ops dw9768_pm_ops = {
54185989122SDongchun Zhu 	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
54285989122SDongchun Zhu 				pm_runtime_force_resume)
54385989122SDongchun Zhu 	SET_RUNTIME_PM_OPS(dw9768_runtime_suspend, dw9768_runtime_resume, NULL)
54485989122SDongchun Zhu };
54585989122SDongchun Zhu 
54685989122SDongchun Zhu static struct i2c_driver dw9768_i2c_driver = {
54785989122SDongchun Zhu 	.driver = {
54885989122SDongchun Zhu 		.name = DW9768_NAME,
54985989122SDongchun Zhu 		.pm = &dw9768_pm_ops,
55085989122SDongchun Zhu 		.of_match_table = dw9768_of_table,
55185989122SDongchun Zhu 	},
552*aaeb31c0SUwe Kleine-König 	.probe = dw9768_probe,
55385989122SDongchun Zhu 	.remove = dw9768_remove,
55485989122SDongchun Zhu };
55585989122SDongchun Zhu module_i2c_driver(dw9768_i2c_driver);
55685989122SDongchun Zhu 
55785989122SDongchun Zhu MODULE_AUTHOR("Dongchun Zhu <dongchun.zhu@mediatek.com>");
55885989122SDongchun Zhu MODULE_DESCRIPTION("DW9768 VCM driver");
55985989122SDongchun Zhu MODULE_LICENSE("GPL v2");
560