2323#define DW9719_CTRL_STEPS 16
2424#define DW9719_CTRL_DELAY_US 1000
2525
26+ #define DW9718S_PD CCI_REG8(0)
27+
28+ #define DW9718S_CONTROL CCI_REG8(1)
29+ #define DW9718S_CONTROL_SW_LINEAR BIT(0)
30+ #define DW9718S_CONTROL_SAC_SHIFT 1
31+ #define DW9718S_CONTROL_SAC_MASK 0x7
32+ #define DW9718S_CONTROL_OCP_DISABLE BIT(4)
33+ #define DW9718S_CONTROL_UVLO_DISABLE BIT(5)
34+ #define DW9718S_DEFAULT_SAC 4
35+
36+ #define DW9718S_VCM_CURRENT CCI_REG16(2)
37+
38+ #define DW9718S_SW CCI_REG8(4)
39+ #define DW9718S_SW_VCM_FREQ_MASK 0xF
40+ #define DW9718S_DEFAULT_VCM_FREQ 0
41+
42+ #define DW9718S_SACT CCI_REG8(5)
43+ #define DW9718S_SACT_PERIOD_8_8MS 0x19
44+
2645#define DW9719_INFO CCI_REG8(0)
2746#define DW9719_ID 0xF1
2847#define DW9761_ID 0xF4
5372#define to_dw9719_device (x ) container_of(x, struct dw9719_device, sd)
5473
5574enum dw9719_model {
75+ DW9718S ,
5676 DW9719 ,
5777 DW9761 ,
5878};
@@ -80,6 +100,7 @@ static int dw9719_power_down(struct dw9719_device *dw9719)
80100
81101static int dw9719_power_up (struct dw9719_device * dw9719 , bool detect )
82102{
103+ u32 reg_pwr ;
83104 u64 val ;
84105 int ret ;
85106 int err ;
@@ -89,13 +110,21 @@ static int dw9719_power_up(struct dw9719_device *dw9719, bool detect)
89110 return ret ;
90111
91112 /* Jiggle SCL pin to wake up device */
92- cci_write (dw9719 -> regmap , DW9719_CONTROL , DW9719_SHUTDOWN , & ret );
113+ reg_pwr = dw9719 -> model == DW9718S ? DW9718S_PD : DW9719_CONTROL ;
114+ cci_write (dw9719 -> regmap , reg_pwr , DW9719_SHUTDOWN , & ret );
93115 fsleep (100 );
94- cci_write (dw9719 -> regmap , DW9719_CONTROL , DW9719_STANDBY , & ret );
116+ cci_write (dw9719 -> regmap , reg_pwr , DW9719_STANDBY , & ret );
95117 /* Need 100us to transit from SHUTDOWN to STANDBY */
96118 fsleep (100 );
97119
98120 if (detect ) {
121+ /* This model does not have an INFO register */
122+ if (dw9719 -> model == DW9718S ) {
123+ dw9719 -> sac_mode = DW9718S_DEFAULT_SAC ;
124+ dw9719 -> vcm_freq = DW9718S_DEFAULT_VCM_FREQ ;
125+ goto props ;
126+ }
127+
99128 ret = cci_read (dw9719 -> regmap , DW9719_INFO , & val , NULL );
100129 if (ret < 0 )
101130 return ret ;
@@ -119,6 +148,7 @@ static int dw9719_power_up(struct dw9719_device *dw9719, bool detect)
119148 return - ENXIO ;
120149 }
121150
151+ props :
122152 /* Optional indication of SAC mode select */
123153 device_property_read_u32 (dw9719 -> dev , "dongwoon,sac-mode" ,
124154 & dw9719 -> sac_mode );
@@ -134,14 +164,30 @@ static int dw9719_power_up(struct dw9719_device *dw9719, bool detect)
134164 & dw9719 -> vcm_freq );
135165 }
136166
137- cci_write (dw9719 -> regmap , DW9719_CONTROL , DW9719_ENABLE_RINGING , & ret );
138- cci_write (dw9719 -> regmap , DW9719_MODE , dw9719 -> mode_low_bits |
139- (dw9719 -> sac_mode << DW9719_MODE_SAC_SHIFT ), & ret );
140- cci_write (dw9719 -> regmap , DW9719_VCM_FREQ , dw9719 -> vcm_freq , & ret );
141-
142- if (dw9719 -> model == DW9761 )
167+ switch (dw9719 -> model ) {
168+ case DW9718S :
169+ /* Datasheet says [OCP/UVLO] should be disabled below 2.5V */
170+ dw9719 -> sac_mode &= DW9718S_CONTROL_SAC_MASK ;
171+ cci_write (dw9719 -> regmap , DW9718S_CONTROL ,
172+ DW9718S_CONTROL_SW_LINEAR |
173+ (dw9719 -> sac_mode << DW9718S_CONTROL_SAC_SHIFT ) |
174+ DW9718S_CONTROL_OCP_DISABLE |
175+ DW9718S_CONTROL_UVLO_DISABLE , & ret );
176+ cci_write (dw9719 -> regmap , DW9718S_SACT ,
177+ DW9718S_SACT_PERIOD_8_8MS , & ret );
178+ cci_write (dw9719 -> regmap , DW9718S_SW ,
179+ dw9719 -> vcm_freq & DW9718S_SW_VCM_FREQ_MASK , & ret );
180+ break ;
181+ case DW9761 :
143182 cci_write (dw9719 -> regmap , DW9761_VCM_PRELOAD ,
144183 DW9761_DEFAULT_VCM_PRELOAD , & ret );
184+ fallthrough ;
185+ case DW9719 :
186+ cci_write (dw9719 -> regmap , DW9719_CONTROL , DW9719_ENABLE_RINGING , & ret );
187+ cci_write (dw9719 -> regmap , DW9719_MODE , dw9719 -> mode_low_bits |
188+ (dw9719 -> sac_mode << DW9719_MODE_SAC_SHIFT ), & ret );
189+ cci_write (dw9719 -> regmap , DW9719_VCM_FREQ , dw9719 -> vcm_freq , & ret );
190+ }
145191
146192 if (ret )
147193 dw9719_power_down (dw9719 );
@@ -151,7 +197,9 @@ static int dw9719_power_up(struct dw9719_device *dw9719, bool detect)
151197
152198static int dw9719_t_focus_abs (struct dw9719_device * dw9719 , s32 value )
153199{
154- return cci_write (dw9719 -> regmap , DW9719_VCM_CURRENT , value , NULL );
200+ u32 reg = dw9719 -> model == DW9718S ? DW9718S_VCM_CURRENT
201+ : DW9719_VCM_CURRENT ;
202+ return cci_write (dw9719 -> regmap , reg , value , NULL );
155203}
156204
157205static int dw9719_set_ctrl (struct v4l2_ctrl * ctrl )
@@ -363,6 +411,7 @@ static void dw9719_remove(struct i2c_client *client)
363411}
364412
365413static const struct of_device_id dw9719_of_table [] = {
414+ { .compatible = "dongwoon,dw9718s" , .data = (const void * )DW9718S },
366415 { .compatible = "dongwoon,dw9719" , .data = (const void * )DW9719 },
367416 { .compatible = "dongwoon,dw9761" , .data = (const void * )DW9761 },
368417 { }
0 commit comments