1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Allegro A8293 SEC driver
5 * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
10 #define A8293_FLAG_ODT 0x10
13 struct i2c_client
*client
;
15 int volt_slew_nanos_per_mv
;
19 * When increasing voltage, do so in minimal steps over time, minimizing
20 * risk of vIN undervoltage.
23 static int a8293_set_voltage_slew(struct a8293_dev
*dev
,
24 struct i2c_client
*client
,
25 enum fe_sec_voltage fe_sec_voltage
,
31 const int idx_to_mv
[] = {
32 0, 12709, 13042, 13375, 14042, 15042, 18042, 18709, 19042
34 const u8 idx_to_reg
[] = {
35 0x00, 0x20, 0x21, 0x22, 0x24, 0x27, 0x28, 0x2A, 0x2B
41 dev_dbg(&client
->dev
, "set_voltage_slew fe_sec_voltage=%d\n",
44 /* Read status register to clear any stale faults. */
45 ret
= i2c_master_recv(client
, &status
, 1);
49 /* Determine previous voltage */
50 switch (dev
->reg
[0] & 0x2F) {
82 /* Determine new voltage */
83 switch (fe_sec_voltage
) {
98 /* Slew to new voltage if new voltage is greater than current voltage */
99 this_volt_idx
= prev_volt_idx
;
100 if (this_volt_idx
< new_volt_idx
) {
101 while (this_volt_idx
< new_volt_idx
) {
102 int delta_mv
= idx_to_mv
[this_volt_idx
+1] - idx_to_mv
[this_volt_idx
];
103 int min_wait_time
= delta_mv
* min_nanos_per_mv
;
105 reg0
= idx_to_reg
[this_volt_idx
+1];
106 reg0
|= A8293_FLAG_ODT
;
108 ret
= i2c_master_send(client
, ®0
, 1);
113 usleep_range(min_wait_time
, min_wait_time
* 2);
115 } else { /* Else just set the voltage */
116 reg0
= idx_to_reg
[new_volt_idx
];
117 reg0
|= A8293_FLAG_ODT
;
118 ret
= i2c_master_send(client
, ®0
, 1);
124 /* TMODE=0, TGATE=1 */
126 if (reg1
!= dev
->reg
[1]) {
127 ret
= i2c_master_send(client
, ®1
, 1);
133 usleep_range(1500, 5000);
137 dev_dbg(&client
->dev
, "failed=%d\n", ret
);
142 static int a8293_set_voltage_noslew(struct dvb_frontend
*fe
,
143 enum fe_sec_voltage fe_sec_voltage
)
145 struct a8293_dev
*dev
= fe
->sec_priv
;
146 struct i2c_client
*client
= dev
->client
;
150 dev_dbg(&client
->dev
, "set_voltage_noslew fe_sec_voltage=%d\n",
153 switch (fe_sec_voltage
) {
154 case SEC_VOLTAGE_OFF
:
159 /* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/
163 /* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/
170 if (reg0
!= dev
->reg
[0]) {
171 ret
= i2c_master_send(client
, ®0
, 1);
177 /* TMODE=0, TGATE=1 */
179 if (reg1
!= dev
->reg
[1]) {
180 ret
= i2c_master_send(client
, ®1
, 1);
186 usleep_range(1500, 50000);
189 dev_dbg(&client
->dev
, "failed=%d\n", ret
);
193 static int a8293_set_voltage(struct dvb_frontend
*fe
,
194 enum fe_sec_voltage fe_sec_voltage
)
196 struct a8293_dev
*dev
= fe
->sec_priv
;
197 struct i2c_client
*client
= dev
->client
;
198 int volt_slew_nanos_per_mv
= dev
->volt_slew_nanos_per_mv
;
200 dev_dbg(&client
->dev
, "set_voltage volt_slew_nanos_per_mv=%d\n",
201 volt_slew_nanos_per_mv
);
203 /* Use slew version if slew rate is set to a sane value */
204 if (volt_slew_nanos_per_mv
> 0 && volt_slew_nanos_per_mv
< 1600)
205 a8293_set_voltage_slew(dev
, client
, fe_sec_voltage
,
206 volt_slew_nanos_per_mv
);
208 a8293_set_voltage_noslew(fe
, fe_sec_voltage
);
213 static int a8293_probe(struct i2c_client
*client
)
215 struct a8293_dev
*dev
;
216 struct a8293_platform_data
*pdata
= client
->dev
.platform_data
;
217 struct dvb_frontend
*fe
= pdata
->dvb_frontend
;
221 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
227 dev
->client
= client
;
228 dev
->volt_slew_nanos_per_mv
= pdata
->volt_slew_nanos_per_mv
;
230 /* check if the SEC is there */
231 ret
= i2c_master_recv(client
, buf
, 2);
235 /* override frontend ops */
236 fe
->ops
.set_voltage
= a8293_set_voltage
;
238 i2c_set_clientdata(client
, dev
);
240 dev_info(&client
->dev
, "Allegro A8293 SEC successfully attached\n");
245 dev_dbg(&client
->dev
, "failed=%d\n", ret
);
249 static void a8293_remove(struct i2c_client
*client
)
251 struct a8293_dev
*dev
= i2c_get_clientdata(client
);
253 dev_dbg(&client
->dev
, "\n");
258 static const struct i2c_device_id a8293_id_table
[] = {
262 MODULE_DEVICE_TABLE(i2c
, a8293_id_table
);
264 static struct i2c_driver a8293_driver
= {
267 .suppress_bind_attrs
= true,
269 .probe
= a8293_probe
,
270 .remove
= a8293_remove
,
271 .id_table
= a8293_id_table
,
274 module_i2c_driver(a8293_driver
);
276 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
277 MODULE_DESCRIPTION("Allegro A8293 SEC driver");
278 MODULE_LICENSE("GPL");