Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * dw9800w vcm driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) //#define DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/rk-camera-module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/version.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <media/v4l2-ctrls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <media/v4l2-device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/rk_vcm_head.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define DRIVER_VERSION			KERNEL_VERSION(0, 0x01, 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define DW9800W_NAME			"dw9800w"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define DW9800W_MAX_CURRENT		1023U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define DW9800W_MAX_REG			1023U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define DW9800W_DEFAULT_START_CURRENT	553
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define DW9800W_DEFAULT_RATED_CURRENT	853
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define DW9800W_DEFAULT_STEP_MODE	0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define DW9800W_DEFAULT_T_SACT		0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define DW9800W_DEFAULT_T_DIV		0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define REG_NULL			0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define DW9800W_CHIP_ID			0xF2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define DW9800W_REG_CHIP_ID		0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) enum mode_e {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	SAC2_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	SAC3_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	SAC4_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	SAC5_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	DIRECT_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	LSC_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) /* dw9800w device structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) struct dw9800w_device {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	struct v4l2_ctrl_handler ctrls_vcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	struct v4l2_subdev sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	struct v4l2_device vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	u16 current_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	struct gpio_desc *power_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	unsigned short current_related_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	unsigned short current_lens_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	unsigned int start_current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	unsigned int rated_current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	unsigned int step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	unsigned int step_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	unsigned int vcm_movefull_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	unsigned int t_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	unsigned int t_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	struct __kernel_old_timeval start_move_tv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	struct __kernel_old_timeval end_move_tv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	unsigned long move_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	u32 module_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	const char *module_facing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	struct rk_cam_vcm_cfg vcm_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	int max_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) static inline struct dw9800w_device *to_dw9800w_vcm(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	return container_of(ctrl->handler, struct dw9800w_device, ctrls_vcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) static inline struct dw9800w_device *sd_to_dw9800w_vcm(struct v4l2_subdev *subdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	return container_of(subdev, struct dw9800w_device, sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) static int dw9800w_write_reg(struct i2c_client *client, u8 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 			    u32 len, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	u32 buf_i, val_i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	u8 buf[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	u8 *val_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	__be32 val_be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	if (len > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	buf[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	val_be = cpu_to_be32(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	val_p = (u8 *)&val_be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	buf_i = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	val_i = 4 - len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	while (val_i < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		buf[buf_i++] = val_p[val_i++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	if (i2c_master_send(client, buf, len + 1) != len + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		dev_err(&client->dev, "Failed to write 0x%04x,0x%x\n", reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static int dw9800w_read_reg(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			    u8 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 			    unsigned int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 			    u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	struct i2c_msg msgs[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	u8 *data_be_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	__be32 data_be = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	if (len > 4 || !len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	data_be_p = (u8 *)&data_be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	/* Write register address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	msgs[0].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	msgs[0].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	msgs[0].len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	msgs[0].buf = (u8 *)&reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	/* Read data from register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	msgs[1].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	msgs[1].flags = I2C_M_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	msgs[1].len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	msgs[1].buf = &data_be_p[4 - len];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	if (ret != ARRAY_SIZE(msgs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	*val = be32_to_cpu(data_be);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static unsigned int dw9800w_move_time_div(struct dw9800w_device *dev_vcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 					 unsigned int move_time_us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	struct i2c_client *client = dev_vcm->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	unsigned int move_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	switch (dev_vcm->t_div) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		move_time = move_time_us * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		move_time = move_time_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		move_time = move_time_us / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		move_time = move_time_us / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		move_time = move_time_us * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		move_time = move_time_us * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			"%s: t_div parameter err %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			__func__, dev_vcm->t_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	return move_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static unsigned int dw9800w_move_time(struct dw9800w_device *dev_vcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	unsigned int move_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	struct i2c_client *client = dev_vcm->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	unsigned int move_time_us = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	switch (dev_vcm->step_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	case LSC_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		move_time_us = 252 + dev_vcm->t_src * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		move_time_us = move_time_us * move_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	case SAC2_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	case SAC3_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	case SAC4_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	case SAC5_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		move_time_us = 6300 + dev_vcm->t_src * 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		move_time_us = dw9800w_move_time_div(dev_vcm, move_time_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	case DIRECT_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		move_time_us = 30000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			"%s: step_mode is error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			__func__, dev_vcm->step_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		"%s: vcm_movefull_t is: %d us\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		__func__, move_time_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	return move_time_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static int dw9800w_get_pos(struct dw9800w_device *dev_vcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	unsigned int *cur_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	struct i2c_client *client = dev_vcm->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	unsigned int abs_step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	ret = dw9800w_read_reg(client, 0x03, 2, &abs_step);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	if (abs_step <= dev_vcm->start_current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		abs_step = VCMDRV_MAX_LOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	else if ((abs_step > dev_vcm->start_current) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		 (abs_step <= dev_vcm->rated_current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		abs_step = (dev_vcm->rated_current - abs_step) / dev_vcm->step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		abs_step = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	*cur_pos = abs_step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	dev_dbg(&client->dev, "%s: get position %d\n", __func__, *cur_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		"%s: failed with error %d\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static int dw9800w_set_pos(struct dw9800w_device *dev_vcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	unsigned int dest_pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	unsigned int position = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	struct i2c_client *client = dev_vcm->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	u32 is_busy, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	if (dest_pos >= VCMDRV_MAX_LOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		position = dev_vcm->start_current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		position = dev_vcm->start_current +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			   (dev_vcm->step * (VCMDRV_MAX_LOG - dest_pos));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	if (position > DW9800W_MAX_REG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		position = DW9800W_MAX_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	dev_vcm->current_lens_pos = position;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	dev_vcm->current_related_pos = dest_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	for (i = 0; i < 100; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		ret = dw9800w_read_reg(client, 0x05, 1, &is_busy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		if (!ret && !(is_busy & 0x01))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		usleep_range(100, 200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	ret = dw9800w_write_reg(client, 0x03, 2, dev_vcm->current_lens_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		"%s: set reg val %d\n", __func__, dev_vcm->current_lens_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		"%s: failed with error %d\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static int dw9800w_get_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	struct dw9800w_device *dev_vcm = to_dw9800w_vcm(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		return dw9800w_get_pos(dev_vcm, &ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static int dw9800w_set_ctrl(struct v4l2_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	struct dw9800w_device *dev_vcm = to_dw9800w_vcm(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	struct i2c_client *client = dev_vcm->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	unsigned int dest_pos = ctrl->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	int move_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	long mv_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	dev_dbg(&client->dev, "ctrl->id: 0x%x, ctrl->val: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		ctrl->id, ctrl->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		if (dest_pos > VCMDRV_MAX_LOG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 			dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 				"%s dest_pos is error. %d > %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 				__func__, dest_pos, VCMDRV_MAX_LOG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		/* calculate move time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		move_pos = dev_vcm->current_related_pos - dest_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		if (move_pos < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 			move_pos = -move_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		ret = dw9800w_set_pos(dev_vcm, dest_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		if (dev_vcm->step_mode == LSC_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 			dev_vcm->move_us = ((dev_vcm->vcm_movefull_t * (uint32_t)move_pos) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 					   VCMDRV_MAX_LOG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 			dev_vcm->move_us = dev_vcm->vcm_movefull_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		dev_dbg(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 			"dest_pos %d, move_us %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 			dest_pos, dev_vcm->move_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		dev_vcm->start_move_tv = ns_to_kernel_old_timeval(ktime_get_ns());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		mv_us = dev_vcm->start_move_tv.tv_usec +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 				dev_vcm->move_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		if (mv_us >= 1000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 			dev_vcm->end_move_tv.tv_sec =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 				dev_vcm->start_move_tv.tv_sec + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 			dev_vcm->end_move_tv.tv_usec = mv_us - 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 			dev_vcm->end_move_tv.tv_sec =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 					dev_vcm->start_move_tv.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 			dev_vcm->end_move_tv.tv_usec = mv_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static const struct v4l2_ctrl_ops dw9800w_vcm_ctrl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	.g_volatile_ctrl = dw9800w_get_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	.s_ctrl = dw9800w_set_ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static int dw9800w_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	rval = pm_runtime_get_sync(sd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	if (rval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		pm_runtime_put_noidle(sd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static int dw9800w_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	pm_runtime_put(sd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static const struct v4l2_subdev_internal_ops dw9800w_int_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	.open = dw9800w_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	.close = dw9800w_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static void dw9800w_update_vcm_cfg(struct dw9800w_device *dev_vcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	struct i2c_client *client = dev_vcm->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	int cur_dist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	if (dev_vcm->max_ma == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		dev_err(&client->dev, "max current is zero");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	cur_dist = dev_vcm->vcm_cfg.rated_ma - dev_vcm->vcm_cfg.start_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	cur_dist = cur_dist * DW9800W_MAX_REG / dev_vcm->max_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	dev_vcm->step = (cur_dist + (VCMDRV_MAX_LOG - 1)) / VCMDRV_MAX_LOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	dev_vcm->start_current = dev_vcm->vcm_cfg.start_ma *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 				 DW9800W_MAX_REG / dev_vcm->max_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	dev_vcm->rated_current = dev_vcm->vcm_cfg.rated_ma *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 				 DW9800W_MAX_REG / dev_vcm->max_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	dev_vcm->step_mode = dev_vcm->vcm_cfg.step_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		"vcm_cfg: %d, %d, %d, max_ma %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		dev_vcm->vcm_cfg.start_ma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 		dev_vcm->vcm_cfg.rated_ma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		dev_vcm->vcm_cfg.step_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		dev_vcm->max_ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static long dw9800w_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	struct dw9800w_device *dev_vcm = sd_to_dw9800w_vcm(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	struct i2c_client *client = dev_vcm->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	struct rk_cam_vcm_tim *vcm_tim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	struct rk_cam_vcm_cfg *vcm_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	if (cmd == RK_VIDIOC_VCM_TIMEINFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		vcm_tim = (struct rk_cam_vcm_tim *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		vcm_tim->vcm_start_t.tv_sec = dev_vcm->start_move_tv.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		vcm_tim->vcm_start_t.tv_usec =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 				dev_vcm->start_move_tv.tv_usec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		vcm_tim->vcm_end_t.tv_sec = dev_vcm->end_move_tv.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		vcm_tim->vcm_end_t.tv_usec = dev_vcm->end_move_tv.tv_usec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		dev_dbg(&client->dev, "dw9800w_get_move_res 0x%lx, 0x%lx, 0x%lx, 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 			vcm_tim->vcm_start_t.tv_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 			vcm_tim->vcm_start_t.tv_usec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 			vcm_tim->vcm_end_t.tv_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 			vcm_tim->vcm_end_t.tv_usec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	} else if (cmd == RK_VIDIOC_GET_VCM_CFG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		vcm_cfg = (struct rk_cam_vcm_cfg *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		vcm_cfg->start_ma = dev_vcm->vcm_cfg.start_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		vcm_cfg->rated_ma = dev_vcm->vcm_cfg.rated_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		vcm_cfg->step_mode = dev_vcm->vcm_cfg.step_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	} else if (cmd == RK_VIDIOC_SET_VCM_CFG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		vcm_cfg = (struct rk_cam_vcm_cfg *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		if (vcm_cfg->start_ma == 0 && vcm_cfg->rated_ma == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 			dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 				"vcm_cfg err, start_ma %d, rated_ma %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 				vcm_cfg->start_ma, vcm_cfg->rated_ma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 		dev_vcm->vcm_cfg.start_ma = vcm_cfg->start_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		dev_vcm->vcm_cfg.rated_ma = vcm_cfg->rated_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		dev_vcm->vcm_cfg.step_mode = vcm_cfg->step_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		dw9800w_update_vcm_cfg(dev_vcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 		dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 			"cmd 0x%x not supported\n", cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static long dw9800w_compat_ioctl32(struct v4l2_subdev *sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	struct dw9800w_device *dev_vcm = sd_to_dw9800w_vcm(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	struct i2c_client *client = dev_vcm->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	void __user *up = compat_ptr(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	struct rk_cam_compat_vcm_tim compat_vcm_tim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	struct rk_cam_vcm_tim vcm_tim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	struct rk_cam_vcm_cfg vcm_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	if (cmd == RK_VIDIOC_COMPAT_VCM_TIMEINFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		struct rk_cam_compat_vcm_tim __user *p32 = up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		ret = dw9800w_ioctl(sd, RK_VIDIOC_VCM_TIMEINFO, &vcm_tim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		compat_vcm_tim.vcm_start_t.tv_sec = vcm_tim.vcm_start_t.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		compat_vcm_tim.vcm_start_t.tv_usec = vcm_tim.vcm_start_t.tv_usec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		compat_vcm_tim.vcm_end_t.tv_sec = vcm_tim.vcm_end_t.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		compat_vcm_tim.vcm_end_t.tv_usec = vcm_tim.vcm_end_t.tv_usec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		put_user(compat_vcm_tim.vcm_start_t.tv_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 			&p32->vcm_start_t.tv_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		put_user(compat_vcm_tim.vcm_start_t.tv_usec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 			&p32->vcm_start_t.tv_usec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		put_user(compat_vcm_tim.vcm_end_t.tv_sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 			&p32->vcm_end_t.tv_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		put_user(compat_vcm_tim.vcm_end_t.tv_usec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 			&p32->vcm_end_t.tv_usec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	} else if (cmd == RK_VIDIOC_GET_VCM_CFG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		ret = dw9800w_ioctl(sd, RK_VIDIOC_GET_VCM_CFG, &vcm_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 			ret = copy_to_user(up, &vcm_cfg, sizeof(vcm_cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 				ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	} else if (cmd == RK_VIDIOC_SET_VCM_CFG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		ret = copy_from_user(&vcm_cfg, up, sizeof(vcm_cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 			ret = dw9800w_ioctl(sd, cmd, &vcm_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 			ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 			"cmd 0x%x not supported\n", cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static const struct v4l2_subdev_core_ops dw9800w_core_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	.ioctl = dw9800w_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	.compat_ioctl32 = dw9800w_compat_ioctl32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static const struct v4l2_subdev_ops dw9800w_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	.core = &dw9800w_core_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static void dw9800w_subdev_cleanup(struct dw9800w_device *dw9800w_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	v4l2_device_unregister_subdev(&dw9800w_dev->sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	v4l2_device_unregister(&dw9800w_dev->vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	v4l2_ctrl_handler_free(&dw9800w_dev->ctrls_vcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	media_entity_cleanup(&dw9800w_dev->sd.entity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static int dw9800w_init_controls(struct dw9800w_device *dev_vcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	struct v4l2_ctrl_handler *hdl = &dev_vcm->ctrls_vcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	const struct v4l2_ctrl_ops *ops = &dw9800w_vcm_ctrl_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	v4l2_ctrl_handler_init(hdl, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 			  0, VCMDRV_MAX_LOG, 1, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	if (hdl->error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		dev_err(dev_vcm->sd.dev, "%s fail error: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 			__func__, hdl->error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	dev_vcm->sd.ctrl_handler = hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	return hdl->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static int __dw9800w_set_power(struct dw9800w_device *dw9800w_dev, bool on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	if (dw9800w_dev->power_gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		gpiod_direction_output(dw9800w_dev->power_gpio, on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static int dw9800w_check_id(struct dw9800w_device *dw9800w_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	unsigned int pid = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	struct i2c_client *client = dw9800w_dev->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	struct device *dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	__dw9800w_set_power(dw9800w_dev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	ret = dw9800w_read_reg(client, DW9800W_REG_CHIP_ID, 1, &pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	if (pid != DW9800W_CHIP_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", pid, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	dev_info(&dw9800w_dev->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		 "Detected dw9800w vcm id:0x%x\n", DW9800W_CHIP_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static int dw9800w_probe_init(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	/* Default goto power down mode when finished probe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	ret = dw9800w_write_reg(client, 0x02, 1, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	dev_err(&client->dev, "probe init failed with error %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static int dw9800w_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 			const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	struct device_node *np = of_node_get(client->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	struct dw9800w_device *dw9800w_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	unsigned int max_ma, start_ma, rated_ma, step_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	unsigned int t_src, t_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	struct v4l2_subdev *sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	char facing[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	dev_info(&client->dev, "probing...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	if (of_property_read_u32(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 		OF_CAMERA_VCMDRV_MAX_CURRENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 		(unsigned int *)&max_ma)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 		max_ma = DW9800W_MAX_CURRENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 			"could not get module %s from dts!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 			OF_CAMERA_VCMDRV_MAX_CURRENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	if (max_ma == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 		max_ma = DW9800W_MAX_CURRENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	if (of_property_read_u32(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 		OF_CAMERA_VCMDRV_START_CURRENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 		(unsigned int *)&start_ma)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 		start_ma = DW9800W_DEFAULT_START_CURRENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 			"could not get module %s from dts!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 			OF_CAMERA_VCMDRV_START_CURRENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	if (of_property_read_u32(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		OF_CAMERA_VCMDRV_RATED_CURRENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		(unsigned int *)&rated_ma)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 		rated_ma = DW9800W_DEFAULT_RATED_CURRENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 		dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 			"could not get module %s from dts!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 			OF_CAMERA_VCMDRV_RATED_CURRENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	if (of_property_read_u32(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 		OF_CAMERA_VCMDRV_STEP_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 		(unsigned int *)&step_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 		step_mode = DW9800W_DEFAULT_STEP_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 		dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 			"could not get module %s from dts!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 			OF_CAMERA_VCMDRV_STEP_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	if (of_property_read_u32(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 		OF_CAMERA_VCMDRV_T_SRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 		(unsigned int *)&t_src)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 		t_src = DW9800W_DEFAULT_T_SACT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 		dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 			"could not get module %s from dts!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 			OF_CAMERA_VCMDRV_T_SRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	if (of_property_read_u32(np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 		OF_CAMERA_VCMDRV_T_DIV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		(unsigned int *)&t_div)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 		t_div = DW9800W_DEFAULT_T_DIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 		dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 			"could not get module %s from dts!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 			OF_CAMERA_VCMDRV_T_DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	dw9800w_dev = devm_kzalloc(&client->dev, sizeof(*dw9800w_dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 				  GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	if (dw9800w_dev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	ret = of_property_read_u32(np, RKMODULE_CAMERA_MODULE_INDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 				   &dw9800w_dev->module_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	ret |= of_property_read_string(np, RKMODULE_CAMERA_MODULE_FACING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 				       &dw9800w_dev->module_facing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 		dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 			"could not get module information!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	dw9800w_dev->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 	dw9800w_dev->power_gpio = devm_gpiod_get(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 					"power", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	if (IS_ERR(dw9800w_dev->power_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 		dw9800w_dev->power_gpio = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 		dev_warn(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 			"Failed to get power-gpios, maybe no use\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	ret = dw9800w_check_id(dw9800w_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 		goto err_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	/* enter power down mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	dw9800w_probe_init(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	v4l2_i2c_subdev_init(&dw9800w_dev->sd, client, &dw9800w_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	dw9800w_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	dw9800w_dev->sd.internal_ops = &dw9800w_int_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 	ret = dw9800w_init_controls(dw9800w_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 		goto err_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	ret = media_entity_pads_init(&dw9800w_dev->sd.entity, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 		goto err_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	sd = &dw9800w_dev->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 	sd->entity.function = MEDIA_ENT_F_LENS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	memset(facing, 0, sizeof(facing));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	if (strcmp(dw9800w_dev->module_facing, "back") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 		facing[0] = 'b';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 		facing[0] = 'f';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 		 dw9800w_dev->module_index, facing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 		 DW9800W_NAME, dev_name(sd->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	ret = v4l2_async_register_subdev(sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 		dev_err(&client->dev, "v4l2 async register subdev failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 	dw9800w_dev->max_ma = max_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	dw9800w_dev->vcm_cfg.start_ma = start_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	dw9800w_dev->vcm_cfg.rated_ma = rated_ma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 	dw9800w_dev->vcm_cfg.step_mode = step_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	dw9800w_update_vcm_cfg(dw9800w_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	dw9800w_dev->move_us	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	dw9800w_dev->current_related_pos = VCMDRV_MAX_LOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 	dw9800w_dev->start_move_tv = ns_to_kernel_old_timeval(ktime_get_ns());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	dw9800w_dev->end_move_tv = ns_to_kernel_old_timeval(ktime_get_ns());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	dw9800w_dev->t_src = t_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	dw9800w_dev->t_div = t_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	i2c_set_clientdata(client, dw9800w_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	mutex_init(&dw9800w_dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 	dw9800w_dev->vcm_movefull_t =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 		dw9800w_move_time(dw9800w_dev, DW9800W_MAX_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	pm_runtime_set_active(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	pm_runtime_enable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	pm_runtime_idle(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	dev_info(&client->dev, "probing successful\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) err_cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 	dw9800w_subdev_cleanup(dw9800w_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) err_power_off:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	__dw9800w_set_power(dw9800w_dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 	dev_err(&client->dev, "Probe failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static int dw9800w_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 	struct dw9800w_device *dw9800w_dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	mutex_destroy(&dw9800w_dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 	pm_runtime_disable(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 	dw9800w_subdev_cleanup(dw9800w_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) static int dw9800w_init(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	struct dw9800w_device *dev_vcm = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 	u32 ring = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 	u32 mode_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	u32 algo_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 	/* Delay 200us~300us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 	usleep_range(200, 300);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 	ret = dw9800w_write_reg(client, 0x02, 1, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 	usleep_range(100, 200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 	if (dev_vcm->step_mode != DIRECT_MODE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 	    dev_vcm->step_mode != LSC_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 		ring = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 	ret = dw9800w_write_reg(client, 0x02, 1, ring);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 	switch (dev_vcm->step_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 	case SAC2_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 	case SAC3_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 	case SAC4_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 	case SAC5_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 		mode_val |= dev_vcm->step_mode << 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 	case LSC_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 		mode_val |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 	mode_val |= ((dev_vcm->t_div >> 2) & 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 	algo_time = dev_vcm->t_div << 6 | dev_vcm->t_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 	ret = dw9800w_write_reg(client, 0x06, 1, mode_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 	ret = dw9800w_write_reg(client, 0x07, 1, algo_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 	usleep_range(100, 200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 	dev_err(&client->dev, "init failed with error %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) static int __maybe_unused dw9800w_vcm_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 	struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 	/* set to power down mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 	ret = dw9800w_write_reg(client, 0x02, 1, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 		dev_err(&client->dev, "failed to set power down mode!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) static int __maybe_unused dw9800w_vcm_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 	struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 	struct dw9800w_device *dev_vcm = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 	dw9800w_init(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	dw9800w_set_pos(dev_vcm, dev_vcm->current_related_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) static const struct i2c_device_id dw9800w_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 	{ DW9800W_NAME, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 	{ { 0 } }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) MODULE_DEVICE_TABLE(i2c, dw9800w_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static const struct of_device_id dw9800w_of_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	{ .compatible = "dongwoon,dw9800w" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 	{ { 0 } }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) MODULE_DEVICE_TABLE(of, dw9800w_of_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) static const struct dev_pm_ops dw9800w_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 	SET_SYSTEM_SLEEP_PM_OPS(dw9800w_vcm_suspend, dw9800w_vcm_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 	SET_RUNTIME_PM_OPS(dw9800w_vcm_suspend, dw9800w_vcm_resume, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static struct i2c_driver dw9800w_i2c_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 		.name = DW9800W_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 		.pm = &dw9800w_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 		.of_match_table = dw9800w_of_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 	.probe = &dw9800w_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 	.remove = &dw9800w_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 	.id_table = dw9800w_id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) module_i2c_driver(dw9800w_i2c_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) MODULE_DESCRIPTION("DW9800W VCM driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) MODULE_LICENSE("GPL");