Merge tag 'pci-v5.3-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
[sfrench/cifs-2.6.git] / drivers / media / dvb-frontends / cxd2820r_t.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Sony CXD2820R demodulator driver
4  *
5  * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
6  */
7
8
9 #include "cxd2820r_priv.h"
10
11 int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
12 {
13         struct cxd2820r_priv *priv = fe->demodulator_priv;
14         struct i2c_client *client = priv->client[0];
15         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
16         int ret, bw_i;
17         unsigned int utmp;
18         u32 if_frequency;
19         u8 buf[3], bw_param;
20         u8 bw_params1[][5] = {
21                 { 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
22                 { 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
23                 { 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
24         };
25         u8 bw_params2[][2] = {
26                 { 0x1f, 0xdc }, /* 6 MHz */
27                 { 0x12, 0xf8 }, /* 7 MHz */
28                 { 0x01, 0xe0 }, /* 8 MHz */
29         };
30         struct reg_val_mask tab[] = {
31                 { 0x00080, 0x00, 0xff },
32                 { 0x00081, 0x03, 0xff },
33                 { 0x00085, 0x07, 0xff },
34                 { 0x00088, 0x01, 0xff },
35
36                 { 0x00070, priv->ts_mode, 0xff },
37                 { 0x00071, !priv->ts_clk_inv << 4, 0x10 },
38                 { 0x000cb, priv->if_agc_polarity << 6, 0x40 },
39                 { 0x000a5, 0x00, 0x01 },
40                 { 0x00082, 0x20, 0x60 },
41                 { 0x000c2, 0xc3, 0xff },
42                 { 0x0016a, 0x50, 0xff },
43                 { 0x00427, 0x41, 0xff },
44         };
45
46         dev_dbg(&client->dev,
47                 "delivery_system=%d modulation=%d frequency=%u bandwidth_hz=%u inversion=%d\n",
48                 c->delivery_system, c->modulation, c->frequency,
49                 c->bandwidth_hz, c->inversion);
50
51         switch (c->bandwidth_hz) {
52         case 6000000:
53                 bw_i = 0;
54                 bw_param = 2;
55                 break;
56         case 7000000:
57                 bw_i = 1;
58                 bw_param = 1;
59                 break;
60         case 8000000:
61                 bw_i = 2;
62                 bw_param = 0;
63                 break;
64         default:
65                 return -EINVAL;
66         }
67
68         /* program tuner */
69         if (fe->ops.tuner_ops.set_params)
70                 fe->ops.tuner_ops.set_params(fe);
71
72         if (priv->delivery_system != SYS_DVBT) {
73                 ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
74                 if (ret)
75                         goto error;
76         }
77
78         priv->delivery_system = SYS_DVBT;
79         priv->ber_running = false; /* tune stops BER counter */
80
81         /* program IF frequency */
82         if (fe->ops.tuner_ops.get_if_frequency) {
83                 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
84                 if (ret)
85                         goto error;
86                 dev_dbg(&client->dev, "if_frequency=%u\n", if_frequency);
87         } else {
88                 ret = -EINVAL;
89                 goto error;
90         }
91
92         utmp = DIV_ROUND_CLOSEST_ULL((u64)if_frequency * 0x1000000, CXD2820R_CLK);
93         buf[0] = (utmp >> 16) & 0xff;
94         buf[1] = (utmp >>  8) & 0xff;
95         buf[2] = (utmp >>  0) & 0xff;
96         ret = regmap_bulk_write(priv->regmap[0], 0x00b6, buf, 3);
97         if (ret)
98                 goto error;
99
100         ret = regmap_bulk_write(priv->regmap[0], 0x009f, bw_params1[bw_i], 5);
101         if (ret)
102                 goto error;
103
104         ret = regmap_update_bits(priv->regmap[0], 0x00d7, 0xc0, bw_param << 6);
105         if (ret)
106                 goto error;
107
108         ret = regmap_bulk_write(priv->regmap[0], 0x00d9, bw_params2[bw_i], 2);
109         if (ret)
110                 goto error;
111
112         ret = regmap_write(priv->regmap[0], 0x00ff, 0x08);
113         if (ret)
114                 goto error;
115
116         ret = regmap_write(priv->regmap[0], 0x00fe, 0x01);
117         if (ret)
118                 goto error;
119
120         return ret;
121 error:
122         dev_dbg(&client->dev, "failed=%d\n", ret);
123         return ret;
124 }
125
126 int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
127                             struct dtv_frontend_properties *c)
128 {
129         struct cxd2820r_priv *priv = fe->demodulator_priv;
130         struct i2c_client *client = priv->client[0];
131         int ret;
132         unsigned int utmp;
133         u8 buf[2];
134
135         dev_dbg(&client->dev, "\n");
136
137         ret = regmap_bulk_read(priv->regmap[0], 0x002f, buf, sizeof(buf));
138         if (ret)
139                 goto error;
140
141         switch ((buf[0] >> 6) & 0x03) {
142         case 0:
143                 c->modulation = QPSK;
144                 break;
145         case 1:
146                 c->modulation = QAM_16;
147                 break;
148         case 2:
149                 c->modulation = QAM_64;
150                 break;
151         }
152
153         switch ((buf[1] >> 1) & 0x03) {
154         case 0:
155                 c->transmission_mode = TRANSMISSION_MODE_2K;
156                 break;
157         case 1:
158                 c->transmission_mode = TRANSMISSION_MODE_8K;
159                 break;
160         }
161
162         switch ((buf[1] >> 3) & 0x03) {
163         case 0:
164                 c->guard_interval = GUARD_INTERVAL_1_32;
165                 break;
166         case 1:
167                 c->guard_interval = GUARD_INTERVAL_1_16;
168                 break;
169         case 2:
170                 c->guard_interval = GUARD_INTERVAL_1_8;
171                 break;
172         case 3:
173                 c->guard_interval = GUARD_INTERVAL_1_4;
174                 break;
175         }
176
177         switch ((buf[0] >> 3) & 0x07) {
178         case 0:
179                 c->hierarchy = HIERARCHY_NONE;
180                 break;
181         case 1:
182                 c->hierarchy = HIERARCHY_1;
183                 break;
184         case 2:
185                 c->hierarchy = HIERARCHY_2;
186                 break;
187         case 3:
188                 c->hierarchy = HIERARCHY_4;
189                 break;
190         }
191
192         switch ((buf[0] >> 0) & 0x07) {
193         case 0:
194                 c->code_rate_HP = FEC_1_2;
195                 break;
196         case 1:
197                 c->code_rate_HP = FEC_2_3;
198                 break;
199         case 2:
200                 c->code_rate_HP = FEC_3_4;
201                 break;
202         case 3:
203                 c->code_rate_HP = FEC_5_6;
204                 break;
205         case 4:
206                 c->code_rate_HP = FEC_7_8;
207                 break;
208         }
209
210         switch ((buf[1] >> 5) & 0x07) {
211         case 0:
212                 c->code_rate_LP = FEC_1_2;
213                 break;
214         case 1:
215                 c->code_rate_LP = FEC_2_3;
216                 break;
217         case 2:
218                 c->code_rate_LP = FEC_3_4;
219                 break;
220         case 3:
221                 c->code_rate_LP = FEC_5_6;
222                 break;
223         case 4:
224                 c->code_rate_LP = FEC_7_8;
225                 break;
226         }
227
228         ret = regmap_read(priv->regmap[0], 0x07c6, &utmp);
229         if (ret)
230                 goto error;
231
232         switch ((utmp >> 0) & 0x01) {
233         case 0:
234                 c->inversion = INVERSION_OFF;
235                 break;
236         case 1:
237                 c->inversion = INVERSION_ON;
238                 break;
239         }
240
241         return ret;
242 error:
243         dev_dbg(&client->dev, "failed=%d\n", ret);
244         return ret;
245 }
246
247 int cxd2820r_read_status_t(struct dvb_frontend *fe, enum fe_status *status)
248 {
249         struct cxd2820r_priv *priv = fe->demodulator_priv;
250         struct i2c_client *client = priv->client[0];
251         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
252         int ret;
253         unsigned int utmp, utmp1, utmp2;
254         u8 buf[3];
255
256         /* Lock detection */
257         ret = regmap_bulk_read(priv->regmap[0], 0x0010, &buf[0], 1);
258         if (ret)
259                 goto error;
260         ret = regmap_bulk_read(priv->regmap[0], 0x0073, &buf[1], 1);
261         if (ret)
262                 goto error;
263
264         utmp1 = (buf[0] >> 0) & 0x07;
265         utmp2 = (buf[1] >> 3) & 0x01;
266
267         if (utmp1 == 6 && utmp2 == 1) {
268                 *status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
269                           FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
270         } else if (utmp1 == 6 || utmp2 == 1) {
271                 *status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
272                           FE_HAS_VITERBI | FE_HAS_SYNC;
273         } else {
274                 *status = 0;
275         }
276
277         dev_dbg(&client->dev, "status=%02x raw=%*ph sync=%u ts=%u\n",
278                 *status, 2, buf, utmp1, utmp2);
279
280         /* Signal strength */
281         if (*status & FE_HAS_SIGNAL) {
282                 unsigned int strength;
283
284                 ret = regmap_bulk_read(priv->regmap[0], 0x0026, buf, 2);
285                 if (ret)
286                         goto error;
287
288                 utmp = buf[0] << 8 | buf[1] << 0;
289                 utmp = ~utmp & 0x0fff;
290                 /* Scale value to 0x0000-0xffff */
291                 strength = utmp << 4 | utmp >> 8;
292
293                 c->strength.len = 1;
294                 c->strength.stat[0].scale = FE_SCALE_RELATIVE;
295                 c->strength.stat[0].uvalue = strength;
296         } else {
297                 c->strength.len = 1;
298                 c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
299         }
300
301         /* CNR */
302         if (*status & FE_HAS_VITERBI) {
303                 unsigned int cnr;
304
305                 ret = regmap_bulk_read(priv->regmap[0], 0x002c, buf, 2);
306                 if (ret)
307                         goto error;
308
309                 utmp = buf[0] << 8 | buf[1] << 0;
310                 if (utmp)
311                         cnr = div_u64((u64)(intlog10(utmp)
312                                       - intlog10(32000 - utmp) + 55532585)
313                                       * 10000, (1 << 24));
314                 else
315                         cnr = 0;
316
317                 c->cnr.len = 1;
318                 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
319                 c->cnr.stat[0].svalue = cnr;
320         } else {
321                 c->cnr.len = 1;
322                 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
323         }
324
325         /* BER */
326         if (*status & FE_HAS_SYNC) {
327                 unsigned int post_bit_error;
328                 bool start_ber;
329
330                 if (priv->ber_running) {
331                         ret = regmap_bulk_read(priv->regmap[0], 0x0076, buf, 3);
332                         if (ret)
333                                 goto error;
334
335                         if ((buf[2] >> 7) & 0x01) {
336                                 post_bit_error = buf[2] << 16 | buf[1] << 8 |
337                                                  buf[0] << 0;
338                                 post_bit_error &= 0x0fffff;
339                                 start_ber = true;
340                         } else {
341                                 post_bit_error = 0;
342                                 start_ber = false;
343                         }
344                 } else {
345                         post_bit_error = 0;
346                         start_ber = true;
347                 }
348
349                 if (start_ber) {
350                         ret = regmap_write(priv->regmap[0], 0x0079, 0x01);
351                         if (ret)
352                                 goto error;
353                         priv->ber_running = true;
354                 }
355
356                 priv->post_bit_error += post_bit_error;
357
358                 c->post_bit_error.len = 1;
359                 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
360                 c->post_bit_error.stat[0].uvalue = priv->post_bit_error;
361         } else {
362                 c->post_bit_error.len = 1;
363                 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
364         }
365
366         return ret;
367 error:
368         dev_dbg(&client->dev, "failed=%d\n", ret);
369         return ret;
370 }
371
372 int cxd2820r_init_t(struct dvb_frontend *fe)
373 {
374         struct cxd2820r_priv *priv = fe->demodulator_priv;
375         struct i2c_client *client = priv->client[0];
376         int ret;
377
378         dev_dbg(&client->dev, "\n");
379
380         ret = regmap_write(priv->regmap[0], 0x0085, 0x07);
381         if (ret)
382                 goto error;
383
384         return ret;
385 error:
386         dev_dbg(&client->dev, "failed=%d\n", ret);
387         return ret;
388 }
389
390 int cxd2820r_sleep_t(struct dvb_frontend *fe)
391 {
392         struct cxd2820r_priv *priv = fe->demodulator_priv;
393         struct i2c_client *client = priv->client[0];
394         int ret;
395         struct reg_val_mask tab[] = {
396                 { 0x000ff, 0x1f, 0xff },
397                 { 0x00085, 0x00, 0xff },
398                 { 0x00088, 0x01, 0xff },
399                 { 0x00081, 0x00, 0xff },
400                 { 0x00080, 0x00, 0xff },
401         };
402
403         dev_dbg(&client->dev, "\n");
404
405         priv->delivery_system = SYS_UNDEFINED;
406
407         ret = cxd2820r_wr_reg_val_mask_tab(priv, tab, ARRAY_SIZE(tab));
408         if (ret)
409                 goto error;
410
411         return ret;
412 error:
413         dev_dbg(&client->dev, "failed=%d\n", ret);
414         return ret;
415 }
416
417 int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
418         struct dvb_frontend_tune_settings *s)
419 {
420         s->min_delay_ms = 500;
421         s->step_size = fe->ops.info.frequency_stepsize_hz * 2;
422         s->max_drift = (fe->ops.info.frequency_stepsize_hz * 2) + 1;
423
424         return 0;
425 }