media: dvb: symbol fixup for dvb_attach()
[platform/kernel/linux-starfive.git] / drivers / media / dvb-frontends / a8293.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Allegro A8293 SEC driver
4  *
5  * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
6  */
7
8 #include "a8293.h"
9
10 #define A8293_FLAG_ODT                  0x10
11
12 struct a8293_dev {
13         struct i2c_client *client;
14         u8 reg[2];
15         int volt_slew_nanos_per_mv;
16 };
17
18 /*
19  * When increasing voltage, do so in minimal steps over time, minimizing
20  * risk of vIN undervoltage.
21  */
22
23 static int a8293_set_voltage_slew(struct a8293_dev *dev,
24                                   struct i2c_client *client,
25                                   enum fe_sec_voltage fe_sec_voltage,
26                                   int min_nanos_per_mv)
27 {
28         int ret;
29         u8 reg0, reg1;
30         int new_volt_idx;
31         const int idx_to_mv[] = {
32                 0,    12709, 13042, 13375, 14042, 15042, 18042, 18709, 19042
33         };
34         const u8 idx_to_reg[] = {
35                 0x00, 0x20,  0x21,  0x22,  0x24,  0x27,  0x28,  0x2A,  0x2B
36         };
37         int this_volt_idx;
38         u8 status;
39         int prev_volt_idx;
40
41         dev_dbg(&client->dev, "set_voltage_slew fe_sec_voltage=%d\n",
42                 fe_sec_voltage);
43
44         /* Read status register to clear any stale faults. */
45         ret = i2c_master_recv(client, &status, 1);
46         if (ret < 0)
47                 goto err;
48
49         /* Determine previous voltage */
50         switch (dev->reg[0] & 0x2F) {
51         case 0x00:
52                 prev_volt_idx = 0;
53                 break;
54         case 0x20:
55                 prev_volt_idx = 1;
56                 break;
57         case 0x21:
58                 prev_volt_idx = 2;
59                 break;
60         case 0x22:
61                 prev_volt_idx = 3;
62                 break;
63         case 0x24:
64                 prev_volt_idx = 4;
65                 break;
66         case 0x27:
67                 prev_volt_idx = 5;
68                 break;
69         case 0x28:
70                 prev_volt_idx = 6;
71                 break;
72         case 0x2A:
73                 prev_volt_idx = 7;
74                 break;
75         case 0x2B:
76                 prev_volt_idx = 8;
77                 break;
78         default:
79                 prev_volt_idx = 0;
80         }
81
82         /* Determine new voltage */
83         switch (fe_sec_voltage) {
84         case SEC_VOLTAGE_OFF:
85                 new_volt_idx = 0;
86                 break;
87         case SEC_VOLTAGE_13:
88                 new_volt_idx = 2;
89                 break;
90         case SEC_VOLTAGE_18:
91                 new_volt_idx = 6;
92                 break;
93         default:
94                 ret = -EINVAL;
95                 goto err;
96         }
97
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;
104
105                         reg0 = idx_to_reg[this_volt_idx+1];
106                         reg0 |= A8293_FLAG_ODT;
107
108                         ret = i2c_master_send(client, &reg0, 1);
109                         if (ret < 0)
110                                 goto err;
111                         dev->reg[0] = reg0;
112                         this_volt_idx++;
113                         usleep_range(min_wait_time, min_wait_time * 2);
114                 }
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, &reg0, 1);
119                 if (ret < 0)
120                         goto err;
121                 dev->reg[0] = reg0;
122         }
123
124         /* TMODE=0, TGATE=1 */
125         reg1 = 0x82;
126         if (reg1 != dev->reg[1]) {
127                 ret = i2c_master_send(client, &reg1, 1);
128                 if (ret < 0)
129                         goto err;
130                 dev->reg[1] = reg1;
131         }
132
133         usleep_range(1500, 5000);
134
135         return 0;
136 err:
137         dev_dbg(&client->dev, "failed=%d\n", ret);
138         return ret;
139 }
140
141
142 static int a8293_set_voltage_noslew(struct dvb_frontend *fe,
143                                     enum fe_sec_voltage fe_sec_voltage)
144 {
145         struct a8293_dev *dev = fe->sec_priv;
146         struct i2c_client *client = dev->client;
147         int ret;
148         u8 reg0, reg1;
149
150         dev_dbg(&client->dev, "set_voltage_noslew fe_sec_voltage=%d\n",
151                 fe_sec_voltage);
152
153         switch (fe_sec_voltage) {
154         case SEC_VOLTAGE_OFF:
155                 /* ENB=0 */
156                 reg0 = 0x10;
157                 break;
158         case SEC_VOLTAGE_13:
159                 /* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/
160                 reg0 = 0x31;
161                 break;
162         case SEC_VOLTAGE_18:
163                 /* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/
164                 reg0 = 0x38;
165                 break;
166         default:
167                 ret = -EINVAL;
168                 goto err;
169         }
170         if (reg0 != dev->reg[0]) {
171                 ret = i2c_master_send(client, &reg0, 1);
172                 if (ret < 0)
173                         goto err;
174                 dev->reg[0] = reg0;
175         }
176
177         /* TMODE=0, TGATE=1 */
178         reg1 = 0x82;
179         if (reg1 != dev->reg[1]) {
180                 ret = i2c_master_send(client, &reg1, 1);
181                 if (ret < 0)
182                         goto err;
183                 dev->reg[1] = reg1;
184         }
185
186         usleep_range(1500, 50000);
187         return 0;
188 err:
189         dev_dbg(&client->dev, "failed=%d\n", ret);
190         return ret;
191 }
192
193 static int a8293_set_voltage(struct dvb_frontend *fe,
194                              enum fe_sec_voltage fe_sec_voltage)
195 {
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;
199
200         dev_dbg(&client->dev, "set_voltage volt_slew_nanos_per_mv=%d\n",
201                 volt_slew_nanos_per_mv);
202
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);
207         else
208                 a8293_set_voltage_noslew(fe, fe_sec_voltage);
209
210         return 0;
211 }
212
213 static int a8293_probe(struct i2c_client *client)
214 {
215         struct a8293_dev *dev;
216         struct a8293_platform_data *pdata = client->dev.platform_data;
217         struct dvb_frontend *fe = pdata->dvb_frontend;
218         int ret;
219         u8 buf[2];
220
221         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
222         if (!dev) {
223                 ret = -ENOMEM;
224                 goto err;
225         }
226
227         dev->client = client;
228         dev->volt_slew_nanos_per_mv = pdata->volt_slew_nanos_per_mv;
229
230         /* check if the SEC is there */
231         ret = i2c_master_recv(client, buf, 2);
232         if (ret < 0)
233                 goto err_kfree;
234
235         /* override frontend ops */
236         fe->ops.set_voltage = a8293_set_voltage;
237         fe->sec_priv = dev;
238         i2c_set_clientdata(client, dev);
239
240         dev_info(&client->dev, "Allegro A8293 SEC successfully attached\n");
241         return 0;
242 err_kfree:
243         kfree(dev);
244 err:
245         dev_dbg(&client->dev, "failed=%d\n", ret);
246         return ret;
247 }
248
249 static void a8293_remove(struct i2c_client *client)
250 {
251         struct a8293_dev *dev = i2c_get_clientdata(client);
252
253         dev_dbg(&client->dev, "\n");
254
255         kfree(dev);
256 }
257
258 static const struct i2c_device_id a8293_id_table[] = {
259         {"a8293", 0},
260         {}
261 };
262 MODULE_DEVICE_TABLE(i2c, a8293_id_table);
263
264 static struct i2c_driver a8293_driver = {
265         .driver = {
266                 .name   = "a8293",
267                 .suppress_bind_attrs = true,
268         },
269         .probe          = a8293_probe,
270         .remove         = a8293_remove,
271         .id_table       = a8293_id_table,
272 };
273
274 module_i2c_driver(a8293_driver);
275
276 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
277 MODULE_DESCRIPTION("Allegro A8293 SEC driver");
278 MODULE_LICENSE("GPL");