]> Git Repo - linux.git/blob - drivers/media/dvb-frontends/si2168.c
selinux: Remove security_ops extern
[linux.git] / drivers / media / dvb-frontends / si2168.c
1 /*
2  * Silicon Labs Si2168 DVB-T/T2/C demodulator driver
3  *
4  * Copyright (C) 2014 Antti Palosaari <[email protected]>
5  *
6  *    This program is free software; you can redistribute it and/or modify
7  *    it under the terms of the GNU General Public License as published by
8  *    the Free Software Foundation; either version 2 of the License, or
9  *    (at your option) any later version.
10  *
11  *    This program is distributed in the hope that it will be useful,
12  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *    GNU General Public License for more details.
15  */
16
17 #include "si2168_priv.h"
18
19 static const struct dvb_frontend_ops si2168_ops;
20
21 /* execute firmware command */
22 static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
23 {
24         int ret;
25         unsigned long timeout;
26
27         mutex_lock(&s->i2c_mutex);
28
29         if (cmd->wlen) {
30                 /* write cmd and args for firmware */
31                 ret = i2c_master_send(s->client, cmd->args, cmd->wlen);
32                 if (ret < 0) {
33                         goto err_mutex_unlock;
34                 } else if (ret != cmd->wlen) {
35                         ret = -EREMOTEIO;
36                         goto err_mutex_unlock;
37                 }
38         }
39
40         if (cmd->rlen) {
41                 /* wait cmd execution terminate */
42                 #define TIMEOUT 50
43                 timeout = jiffies + msecs_to_jiffies(TIMEOUT);
44                 while (!time_after(jiffies, timeout)) {
45                         ret = i2c_master_recv(s->client, cmd->args, cmd->rlen);
46                         if (ret < 0) {
47                                 goto err_mutex_unlock;
48                         } else if (ret != cmd->rlen) {
49                                 ret = -EREMOTEIO;
50                                 goto err_mutex_unlock;
51                         }
52
53                         /* firmware ready? */
54                         if ((cmd->args[0] >> 7) & 0x01)
55                                 break;
56                 }
57
58                 dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n",
59                                 __func__,
60                                 jiffies_to_msecs(jiffies) -
61                                 (jiffies_to_msecs(timeout) - TIMEOUT));
62
63                 if (!((cmd->args[0] >> 7) & 0x01)) {
64                         ret = -ETIMEDOUT;
65                         goto err_mutex_unlock;
66                 }
67         }
68
69         ret = 0;
70
71 err_mutex_unlock:
72         mutex_unlock(&s->i2c_mutex);
73         if (ret)
74                 goto err;
75
76         return 0;
77 err:
78         dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
79         return ret;
80 }
81
82 static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
83 {
84         struct si2168 *s = fe->demodulator_priv;
85         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
86         int ret;
87         struct si2168_cmd cmd;
88
89         *status = 0;
90
91         if (!s->active) {
92                 ret = -EAGAIN;
93                 goto err;
94         }
95
96         switch (c->delivery_system) {
97         case SYS_DVBT:
98                 cmd.args[0] = 0xa0;
99                 cmd.args[1] = 0x01;
100                 cmd.wlen = 2;
101                 cmd.rlen = 13;
102                 break;
103         case SYS_DVBC_ANNEX_A:
104                 cmd.args[0] = 0x90;
105                 cmd.args[1] = 0x01;
106                 cmd.wlen = 2;
107                 cmd.rlen = 9;
108                 break;
109         case SYS_DVBT2:
110                 cmd.args[0] = 0x50;
111                 cmd.args[1] = 0x01;
112                 cmd.wlen = 2;
113                 cmd.rlen = 14;
114                 break;
115         default:
116                 ret = -EINVAL;
117                 goto err;
118         }
119
120         ret = si2168_cmd_execute(s, &cmd);
121         if (ret)
122                 goto err;
123
124         /*
125          * Possible values seen, in order from strong signal to weak:
126          * 16 0001 0110 full lock
127          * 1e 0001 1110 partial lock
128          * 1a 0001 1010 partial lock
129          * 18 0001 1000 no lock
130          *
131          * [b3:b1] lock bits
132          * [b4] statistics ready? Set in a few secs after lock is gained.
133          */
134
135         switch ((cmd.args[2] >> 1) & 0x03) {
136         case 0x01:
137                 *status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
138                 break;
139         case 0x03:
140                 *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
141                                 FE_HAS_SYNC | FE_HAS_LOCK;
142                 break;
143         }
144
145         s->fe_status = *status;
146
147         dev_dbg(&s->client->dev, "%s: status=%02x args=%*ph\n",
148                         __func__, *status, cmd.rlen, cmd.args);
149
150         return 0;
151 err:
152         dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
153         return ret;
154 }
155
156 static int si2168_set_frontend(struct dvb_frontend *fe)
157 {
158         struct si2168 *s = fe->demodulator_priv;
159         struct dtv_frontend_properties *c = &fe->dtv_property_cache;
160         int ret;
161         struct si2168_cmd cmd;
162         u8 bandwidth, delivery_system;
163
164         dev_dbg(&s->client->dev,
165                         "%s: delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u\n",
166                         __func__, c->delivery_system, c->modulation,
167                         c->frequency, c->bandwidth_hz, c->symbol_rate,
168                         c->inversion);
169
170         if (!s->active) {
171                 ret = -EAGAIN;
172                 goto err;
173         }
174
175         switch (c->delivery_system) {
176         case SYS_DVBT:
177                 delivery_system = 0x20;
178                 break;
179         case SYS_DVBC_ANNEX_A:
180                 delivery_system = 0x30;
181                 break;
182         case SYS_DVBT2:
183                 delivery_system = 0x70;
184                 break;
185         default:
186                 ret = -EINVAL;
187                 goto err;
188         }
189
190         if (c->bandwidth_hz <= 5000000)
191                 bandwidth = 0x05;
192         else if (c->bandwidth_hz <= 6000000)
193                 bandwidth = 0x06;
194         else if (c->bandwidth_hz <= 7000000)
195                 bandwidth = 0x07;
196         else if (c->bandwidth_hz <= 8000000)
197                 bandwidth = 0x08;
198         else if (c->bandwidth_hz <= 9000000)
199                 bandwidth = 0x09;
200         else if (c->bandwidth_hz <= 10000000)
201                 bandwidth = 0x0a;
202         else
203                 bandwidth = 0x0f;
204
205         /* program tuner */
206         if (fe->ops.tuner_ops.set_params) {
207                 ret = fe->ops.tuner_ops.set_params(fe);
208                 if (ret)
209                         goto err;
210         }
211
212         memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5);
213         cmd.wlen = 5;
214         cmd.rlen = 5;
215         ret = si2168_cmd_execute(s, &cmd);
216         if (ret)
217                 goto err;
218
219         /* that has no big effect */
220         if (c->delivery_system == SYS_DVBT)
221                 memcpy(cmd.args, "\x89\x21\x06\x11\xff\x98", 6);
222         else if (c->delivery_system == SYS_DVBC_ANNEX_A)
223                 memcpy(cmd.args, "\x89\x21\x06\x11\x89\xf0", 6);
224         else if (c->delivery_system == SYS_DVBT2)
225                 memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6);
226         cmd.wlen = 6;
227         cmd.rlen = 3;
228         ret = si2168_cmd_execute(s, &cmd);
229         if (ret)
230                 goto err;
231
232         memcpy(cmd.args, "\x51\x03", 2);
233         cmd.wlen = 2;
234         cmd.rlen = 12;
235         ret = si2168_cmd_execute(s, &cmd);
236         if (ret)
237                 goto err;
238
239         memcpy(cmd.args, "\x12\x08\x04", 3);
240         cmd.wlen = 3;
241         cmd.rlen = 3;
242         ret = si2168_cmd_execute(s, &cmd);
243         if (ret)
244                 goto err;
245
246         memcpy(cmd.args, "\x14\x00\x01\x04\x00\x00", 6);
247         cmd.wlen = 6;
248         cmd.rlen = 1;
249         ret = si2168_cmd_execute(s, &cmd);
250         if (ret)
251                 goto err;
252
253         memcpy(cmd.args, "\x14\x00\x03\x10\x17\x00", 6);
254         cmd.wlen = 6;
255         cmd.rlen = 1;
256         ret = si2168_cmd_execute(s, &cmd);
257         if (ret)
258                 goto err;
259
260         memcpy(cmd.args, "\x14\x00\x02\x10\x15\x00", 6);
261         cmd.wlen = 6;
262         cmd.rlen = 1;
263         ret = si2168_cmd_execute(s, &cmd);
264         if (ret)
265                 goto err;
266
267         memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6);
268         cmd.wlen = 6;
269         cmd.rlen = 1;
270         ret = si2168_cmd_execute(s, &cmd);
271         if (ret)
272                 goto err;
273
274         memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6);
275         cmd.wlen = 6;
276         cmd.rlen = 1;
277         ret = si2168_cmd_execute(s, &cmd);
278         if (ret)
279                 goto err;
280
281         memcpy(cmd.args, "\x14\x00\x0b\x10\x88\x13", 6);
282         cmd.wlen = 6;
283         cmd.rlen = 1;
284         ret = si2168_cmd_execute(s, &cmd);
285         if (ret)
286                 goto err;
287
288         memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6);
289         cmd.wlen = 6;
290         cmd.rlen = 1;
291         ret = si2168_cmd_execute(s, &cmd);
292         if (ret)
293                 goto err;
294
295         memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6);
296         cmd.args[4] = delivery_system | bandwidth;
297         cmd.wlen = 6;
298         cmd.rlen = 1;
299         ret = si2168_cmd_execute(s, &cmd);
300         if (ret)
301                 goto err;
302
303         memcpy(cmd.args, "\x14\x00\x04\x10\x15\x00", 6);
304         cmd.wlen = 6;
305         cmd.rlen = 1;
306         ret = si2168_cmd_execute(s, &cmd);
307         if (ret)
308                 goto err;
309
310         memcpy(cmd.args, "\x14\x00\x05\x10\xa1\x00", 6);
311         cmd.wlen = 6;
312         cmd.rlen = 1;
313         ret = si2168_cmd_execute(s, &cmd);
314         if (ret)
315                 goto err;
316
317         memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6);
318         cmd.wlen = 6;
319         cmd.rlen = 1;
320         ret = si2168_cmd_execute(s, &cmd);
321         if (ret)
322                 goto err;
323
324         memcpy(cmd.args, "\x14\x00\x0d\x10\xd0\x02", 6);
325         cmd.wlen = 6;
326         cmd.rlen = 1;
327         ret = si2168_cmd_execute(s, &cmd);
328         if (ret)
329                 goto err;
330
331         memcpy(cmd.args, "\x14\x00\x01\x10\x00\x00", 6);
332         cmd.wlen = 6;
333         cmd.rlen = 1;
334         ret = si2168_cmd_execute(s, &cmd);
335         if (ret)
336                 goto err;
337
338         memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6);
339         cmd.wlen = 6;
340         cmd.rlen = 1;
341         ret = si2168_cmd_execute(s, &cmd);
342         if (ret)
343                 goto err;
344
345         memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6);
346         cmd.wlen = 6;
347         cmd.rlen = 1;
348         ret = si2168_cmd_execute(s, &cmd);
349         if (ret)
350                 goto err;
351
352         memcpy(cmd.args, "\x14\x00\x04\x03\x00\x00", 6);
353         cmd.wlen = 6;
354         cmd.rlen = 1;
355         ret = si2168_cmd_execute(s, &cmd);
356         if (ret)
357                 goto err;
358
359         memcpy(cmd.args, "\x14\x00\x03\x03\x00\x00", 6);
360         cmd.wlen = 6;
361         cmd.rlen = 1;
362         ret = si2168_cmd_execute(s, &cmd);
363         if (ret)
364                 goto err;
365
366         memcpy(cmd.args, "\x14\x00\x08\x03\x00\x00", 6);
367         cmd.wlen = 6;
368         cmd.rlen = 1;
369         ret = si2168_cmd_execute(s, &cmd);
370         if (ret)
371                 goto err;
372
373         memcpy(cmd.args, "\x14\x00\x07\x03\x01\x02", 6);
374         cmd.wlen = 6;
375         cmd.rlen = 1;
376         ret = si2168_cmd_execute(s, &cmd);
377         if (ret)
378                 goto err;
379
380         memcpy(cmd.args, "\x14\x00\x06\x03\x00\x00", 6);
381         cmd.wlen = 6;
382         cmd.rlen = 1;
383         ret = si2168_cmd_execute(s, &cmd);
384         if (ret)
385                 goto err;
386
387         memcpy(cmd.args, "\x14\x00\x05\x03\x00\x00", 6);
388         cmd.wlen = 6;
389         cmd.rlen = 1;
390         ret = si2168_cmd_execute(s, &cmd);
391         if (ret)
392                 goto err;
393
394         memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x40", 6);
395         cmd.wlen = 6;
396         cmd.rlen = 1;
397         ret = si2168_cmd_execute(s, &cmd);
398         if (ret)
399                 goto err;
400
401         memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6);
402         cmd.wlen = 6;
403         cmd.rlen = 1;
404         ret = si2168_cmd_execute(s, &cmd);
405         if (ret)
406                 goto err;
407
408         memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
409         cmd.wlen = 6;
410         cmd.rlen = 1;
411         ret = si2168_cmd_execute(s, &cmd);
412         if (ret)
413                 goto err;
414
415         cmd.args[0] = 0x85;
416         cmd.wlen = 1;
417         cmd.rlen = 1;
418         ret = si2168_cmd_execute(s, &cmd);
419         if (ret)
420                 goto err;
421
422         s->delivery_system = c->delivery_system;
423
424         return 0;
425 err:
426         dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
427         return ret;
428 }
429
430 static int si2168_init(struct dvb_frontend *fe)
431 {
432         struct si2168 *s = fe->demodulator_priv;
433         int ret, len, remaining;
434         const struct firmware *fw = NULL;
435         u8 *fw_file = SI2168_FIRMWARE;
436         const unsigned int i2c_wr_max = 8;
437         struct si2168_cmd cmd;
438
439         dev_dbg(&s->client->dev, "%s:\n", __func__);
440
441         cmd.args[0] = 0x13;
442         cmd.wlen = 1;
443         cmd.rlen = 0;
444         ret = si2168_cmd_execute(s, &cmd);
445         if (ret)
446                 goto err;
447
448         cmd.args[0] = 0xc0;
449         cmd.args[1] = 0x12;
450         cmd.args[2] = 0x00;
451         cmd.args[3] = 0x0c;
452         cmd.args[4] = 0x00;
453         cmd.args[5] = 0x0d;
454         cmd.args[6] = 0x16;
455         cmd.args[7] = 0x00;
456         cmd.args[8] = 0x00;
457         cmd.args[9] = 0x00;
458         cmd.args[10] = 0x00;
459         cmd.args[11] = 0x00;
460         cmd.args[12] = 0x00;
461         cmd.wlen = 13;
462         cmd.rlen = 0;
463         ret = si2168_cmd_execute(s, &cmd);
464         if (ret)
465                 goto err;
466
467         cmd.args[0] = 0xc0;
468         cmd.args[1] = 0x06;
469         cmd.args[2] = 0x01;
470         cmd.args[3] = 0x0f;
471         cmd.args[4] = 0x00;
472         cmd.args[5] = 0x20;
473         cmd.args[6] = 0x20;
474         cmd.args[7] = 0x01;
475         cmd.wlen = 8;
476         cmd.rlen = 1;
477         ret = si2168_cmd_execute(s, &cmd);
478         if (ret)
479                 goto err;
480
481         cmd.args[0] = 0x02;
482         cmd.wlen = 1;
483         cmd.rlen = 13;
484         ret = si2168_cmd_execute(s, &cmd);
485         if (ret)
486                 goto err;
487
488         /* cold state - try to download firmware */
489         dev_info(&s->client->dev, "%s: found a '%s' in cold state\n",
490                         KBUILD_MODNAME, si2168_ops.info.name);
491
492         /* request the firmware, this will block and timeout */
493         ret = request_firmware(&fw, fw_file, &s->client->dev);
494         if (ret) {
495                 dev_err(&s->client->dev, "%s: firmare file '%s' not found\n",
496                                 KBUILD_MODNAME, fw_file);
497                 goto err;
498         }
499
500         dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n",
501                         KBUILD_MODNAME, fw_file);
502
503         for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) {
504                 len = remaining;
505                 if (len > i2c_wr_max)
506                         len = i2c_wr_max;
507
508                 memcpy(cmd.args, &fw->data[fw->size - remaining], len);
509                 cmd.wlen = len;
510                 cmd.rlen = 1;
511                 ret = si2168_cmd_execute(s, &cmd);
512                 if (ret) {
513                         dev_err(&s->client->dev,
514                                         "%s: firmware download failed=%d\n",
515                                         KBUILD_MODNAME, ret);
516                         goto err;
517                 }
518         }
519
520         release_firmware(fw);
521         fw = NULL;
522
523         cmd.args[0] = 0x01;
524         cmd.args[1] = 0x01;
525         cmd.wlen = 2;
526         cmd.rlen = 1;
527         ret = si2168_cmd_execute(s, &cmd);
528         if (ret)
529                 goto err;
530
531         dev_info(&s->client->dev, "%s: found a '%s' in warm state\n",
532                         KBUILD_MODNAME, si2168_ops.info.name);
533
534         s->active = true;
535
536         return 0;
537 err:
538         if (fw)
539                 release_firmware(fw);
540
541         dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
542         return ret;
543 }
544
545 static int si2168_sleep(struct dvb_frontend *fe)
546 {
547         struct si2168 *s = fe->demodulator_priv;
548
549         dev_dbg(&s->client->dev, "%s:\n", __func__);
550
551         s->active = false;
552
553         return 0;
554 }
555
556 static int si2168_get_tune_settings(struct dvb_frontend *fe,
557         struct dvb_frontend_tune_settings *s)
558 {
559         s->min_delay_ms = 900;
560
561         return 0;
562 }
563
564 /*
565  * I2C gate logic
566  * We must use unlocked i2c_transfer() here because I2C lock is already taken
567  * by tuner driver.
568  */
569 static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
570 {
571         struct si2168 *s = mux_priv;
572         int ret;
573         struct i2c_msg gate_open_msg = {
574                 .addr = s->client->addr,
575                 .flags = 0,
576                 .len = 3,
577                 .buf = "\xc0\x0d\x01",
578         };
579
580         mutex_lock(&s->i2c_mutex);
581
582         /* open tuner I2C gate */
583         ret = __i2c_transfer(s->client->adapter, &gate_open_msg, 1);
584         if (ret != 1) {
585                 dev_warn(&s->client->dev, "%s: i2c write failed=%d\n",
586                                 KBUILD_MODNAME, ret);
587                 if (ret >= 0)
588                         ret = -EREMOTEIO;
589         } else {
590                 ret = 0;
591         }
592
593         return ret;
594 }
595
596 static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
597 {
598         struct si2168 *s = mux_priv;
599         int ret;
600         struct i2c_msg gate_close_msg = {
601                 .addr = s->client->addr,
602                 .flags = 0,
603                 .len = 3,
604                 .buf = "\xc0\x0d\x00",
605         };
606
607         /* close tuner I2C gate */
608         ret = __i2c_transfer(s->client->adapter, &gate_close_msg, 1);
609         if (ret != 1) {
610                 dev_warn(&s->client->dev, "%s: i2c write failed=%d\n",
611                                 KBUILD_MODNAME, ret);
612                 if (ret >= 0)
613                         ret = -EREMOTEIO;
614         } else {
615                 ret = 0;
616         }
617
618         mutex_unlock(&s->i2c_mutex);
619
620         return ret;
621 }
622
623 static const struct dvb_frontend_ops si2168_ops = {
624         .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A},
625         .info = {
626                 .name = "Silicon Labs Si2168",
627                 .caps = FE_CAN_FEC_1_2 |
628                         FE_CAN_FEC_2_3 |
629                         FE_CAN_FEC_3_4 |
630                         FE_CAN_FEC_5_6 |
631                         FE_CAN_FEC_7_8 |
632                         FE_CAN_FEC_AUTO |
633                         FE_CAN_QPSK |
634                         FE_CAN_QAM_16 |
635                         FE_CAN_QAM_32 |
636                         FE_CAN_QAM_64 |
637                         FE_CAN_QAM_128 |
638                         FE_CAN_QAM_256 |
639                         FE_CAN_QAM_AUTO |
640                         FE_CAN_TRANSMISSION_MODE_AUTO |
641                         FE_CAN_GUARD_INTERVAL_AUTO |
642                         FE_CAN_HIERARCHY_AUTO |
643                         FE_CAN_MUTE_TS |
644                         FE_CAN_2G_MODULATION
645         },
646
647         .get_tune_settings = si2168_get_tune_settings,
648
649         .init = si2168_init,
650         .sleep = si2168_sleep,
651
652         .set_frontend = si2168_set_frontend,
653
654         .read_status = si2168_read_status,
655 };
656
657 static int si2168_probe(struct i2c_client *client,
658                 const struct i2c_device_id *id)
659 {
660         struct si2168_config *config = client->dev.platform_data;
661         struct si2168 *s;
662         int ret;
663         struct si2168_cmd cmd;
664
665         dev_dbg(&client->dev, "%s:\n", __func__);
666
667         s = kzalloc(sizeof(struct si2168), GFP_KERNEL);
668         if (!s) {
669                 ret = -ENOMEM;
670                 dev_err(&client->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
671                 goto err;
672         }
673
674         s->client = client;
675         mutex_init(&s->i2c_mutex);
676
677         /* check if the demod is there */
678         cmd.wlen = 0;
679         cmd.rlen = 1;
680         ret = si2168_cmd_execute(s, &cmd);
681         if (ret)
682                 goto err;
683
684         /* create mux i2c adapter for tuner */
685         s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s,
686                         0, 0, 0, si2168_select, si2168_deselect);
687         if (s->adapter == NULL)
688                 goto err;
689
690         /* create dvb_frontend */
691         memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
692         s->fe.demodulator_priv = s;
693
694         *config->i2c_adapter = s->adapter;
695         *config->fe = &s->fe;
696
697         i2c_set_clientdata(client, s);
698
699         dev_info(&s->client->dev,
700                         "%s: Silicon Labs Si2168 successfully attached\n",
701                         KBUILD_MODNAME);
702         return 0;
703 err:
704         kfree(s);
705         dev_dbg(&client->dev, "%s: failed=%d\n", __func__, ret);
706         return ret;
707 }
708
709 static int si2168_remove(struct i2c_client *client)
710 {
711         struct si2168 *s = i2c_get_clientdata(client);
712
713         dev_dbg(&client->dev, "%s:\n", __func__);
714
715         i2c_del_mux_adapter(s->adapter);
716
717         s->fe.ops.release = NULL;
718         s->fe.demodulator_priv = NULL;
719
720         kfree(s);
721
722         return 0;
723 }
724
725 static const struct i2c_device_id si2168_id[] = {
726         {"si2168", 0},
727         {}
728 };
729 MODULE_DEVICE_TABLE(i2c, si2168_id);
730
731 static struct i2c_driver si2168_driver = {
732         .driver = {
733                 .owner  = THIS_MODULE,
734                 .name   = "si2168",
735         },
736         .probe          = si2168_probe,
737         .remove         = si2168_remove,
738         .id_table       = si2168_id,
739 };
740
741 module_i2c_driver(si2168_driver);
742
743 MODULE_AUTHOR("Antti Palosaari <[email protected]>");
744 MODULE_DESCRIPTION("Silicon Labs Si2168 DVB-T/T2/C demodulator driver");
745 MODULE_LICENSE("GPL");
746 MODULE_FIRMWARE(SI2168_FIRMWARE);
This page took 0.077193 seconds and 4 git commands to generate.