These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / media / platform / sti / c8sectpfe / c8sectpfe-dvb.c
1 /*
2  *  c8sectpfe-dvb.c - C8SECTPFE STi DVB driver
3  *
4  * Copyright (c) STMicroelectronics 2015
5  *
6  *  Author Peter Griffin <peter.griffin@linaro.org>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *
17  *  GNU General Public License for more details.
18  */
19 #include <linux/completion.h>
20 #include <linux/delay.h>
21 #include <linux/i2c.h>
22 #include <linux/interrupt.h>
23 #include <linux/version.h>
24
25 #include <dt-bindings/media/c8sectpfe.h>
26
27 #include "c8sectpfe-common.h"
28 #include "c8sectpfe-core.h"
29 #include "c8sectpfe-dvb.h"
30
31 #include "dvb-pll.h"
32 #include "lnbh24.h"
33 #include "stv0367.h"
34 #include "stv0367_priv.h"
35 #include "stv6110x.h"
36 #include "stv090x.h"
37 #include "tda18212.h"
38
39 static inline const char *dvb_card_str(unsigned int c)
40 {
41         switch (c) {
42         case STV0367_TDA18212_NIMA_1:   return "STV0367_TDA18212_NIMA_1";
43         case STV0367_TDA18212_NIMA_2:   return "STV0367_TDA18212_NIMA_2";
44         case STV0367_TDA18212_NIMB_1:   return "STV0367_TDA18212_NIMB_1";
45         case STV0367_TDA18212_NIMB_2:   return "STV0367_TDA18212_NIMB_2";
46         case STV0903_6110_LNB24_NIMA:   return "STV0903_6110_LNB24_NIMA";
47         case STV0903_6110_LNB24_NIMB:   return "STV0903_6110_LNB24_NIMB";
48         default:                        return "unknown dvb frontend card";
49         }
50 }
51
52 static struct stv090x_config stv090x_config = {
53         .device                 = STV0903,
54         .demod_mode             = STV090x_SINGLE,
55         .clk_mode               = STV090x_CLK_EXT,
56         .xtal                   = 16000000,
57         .address                = 0x69,
58
59         .ts1_mode               = STV090x_TSMODE_SERIAL_CONTINUOUS,
60         .ts2_mode               = STV090x_TSMODE_SERIAL_CONTINUOUS,
61
62         .repeater_level         = STV090x_RPTLEVEL_64,
63
64         .tuner_init             = NULL,
65         .tuner_set_mode         = NULL,
66         .tuner_set_frequency    = NULL,
67         .tuner_get_frequency    = NULL,
68         .tuner_set_bandwidth    = NULL,
69         .tuner_get_bandwidth    = NULL,
70         .tuner_set_bbgain       = NULL,
71         .tuner_get_bbgain       = NULL,
72         .tuner_set_refclk       = NULL,
73         .tuner_get_status       = NULL,
74 };
75
76 static struct stv6110x_config stv6110x_config = {
77         .addr                   = 0x60,
78         .refclk                 = 16000000,
79 };
80
81 #define NIMA 0
82 #define NIMB 1
83
84 static struct stv0367_config stv0367_tda18212_config[] = {
85         {
86                 .demod_address = 0x1c,
87                 .xtal = 16000000,
88                 .if_khz = 4500,
89                 .if_iq_mode = FE_TER_NORMAL_IF_TUNER,
90                 .ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
91                 .clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
92         }, {
93                 .demod_address = 0x1d,
94                 .xtal = 16000000,
95                 .if_khz = 4500,
96                 .if_iq_mode = FE_TER_NORMAL_IF_TUNER,
97                 .ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
98                 .clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
99         }, {
100                 .demod_address = 0x1e,
101                 .xtal = 16000000,
102                 .if_khz = 4500,
103                 .if_iq_mode = FE_TER_NORMAL_IF_TUNER,
104                 .ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
105                 .clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
106         },
107 };
108
109 static struct tda18212_config tda18212_conf = {
110         .if_dvbt_6 = 4150,
111         .if_dvbt_7 = 4150,
112         .if_dvbt_8 = 4500,
113         .if_dvbc = 5000,
114 };
115
116 int c8sectpfe_frontend_attach(struct dvb_frontend **fe,
117                 struct c8sectpfe *c8sectpfe,
118                 struct channel_info *tsin, int chan_num)
119 {
120         struct tda18212_config *tda18212;
121         struct stv6110x_devctl *fe2;
122         struct i2c_client *client;
123         struct i2c_board_info tda18212_info = {
124                 .type = "tda18212",
125                 .addr = 0x60,
126         };
127
128         if (!tsin)
129                 return -EINVAL;
130
131         switch (tsin->dvb_card) {
132
133         case STV0367_TDA18212_NIMA_1:
134         case STV0367_TDA18212_NIMA_2:
135         case STV0367_TDA18212_NIMB_1:
136         case STV0367_TDA18212_NIMB_2:
137                 if (tsin->dvb_card == STV0367_TDA18212_NIMA_1)
138                         *fe = dvb_attach(stv0367ter_attach,
139                                  &stv0367_tda18212_config[0],
140                                         tsin->i2c_adapter);
141                 else if (tsin->dvb_card == STV0367_TDA18212_NIMB_1)
142                         *fe = dvb_attach(stv0367ter_attach,
143                                  &stv0367_tda18212_config[1],
144                                         tsin->i2c_adapter);
145                 else
146                         *fe = dvb_attach(stv0367ter_attach,
147                                  &stv0367_tda18212_config[2],
148                                         tsin->i2c_adapter);
149
150                 if (!*fe) {
151                         dev_err(c8sectpfe->device,
152                                 "%s: stv0367ter_attach failed for NIM card %s\n"
153                                 , __func__, dvb_card_str(tsin->dvb_card));
154                         return -ENODEV;
155                 };
156
157                 /*
158                  * init the demod so that i2c gate_ctrl
159                  * to the tuner works correctly
160                  */
161                 (*fe)->ops.init(*fe);
162
163                 /* Allocate the tda18212 structure */
164                 tda18212 = devm_kzalloc(c8sectpfe->device,
165                                         sizeof(struct tda18212_config),
166                                         GFP_KERNEL);
167                 if (!tda18212) {
168                         dev_err(c8sectpfe->device,
169                                 "%s: devm_kzalloc failed\n", __func__);
170                         return -ENOMEM;
171                 }
172
173                 memcpy(tda18212, &tda18212_conf,
174                         sizeof(struct tda18212_config));
175
176                 tda18212->fe = (*fe);
177
178                 tda18212_info.platform_data = tda18212;
179
180                 /* attach tuner */
181                 request_module("tda18212");
182                 client = i2c_new_device(tsin->i2c_adapter, &tda18212_info);
183                 if (!client || !client->dev.driver) {
184                         dvb_frontend_detach(*fe);
185                         return -ENODEV;
186                 }
187
188                 if (!try_module_get(client->dev.driver->owner)) {
189                         i2c_unregister_device(client);
190                         dvb_frontend_detach(*fe);
191                         return -ENODEV;
192                 }
193
194                 tsin->i2c_client = client;
195
196                 break;
197
198         case STV0903_6110_LNB24_NIMA:
199                 *fe = dvb_attach(stv090x_attach,        &stv090x_config,
200                                 tsin->i2c_adapter, STV090x_DEMODULATOR_0);
201                 if (!*fe) {
202                         dev_err(c8sectpfe->device, "%s: stv090x_attach failed\n"
203                                 "\tfor NIM card %s\n",
204                                 __func__, dvb_card_str(tsin->dvb_card));
205                         return -ENODEV;
206                 }
207
208                 fe2 = dvb_attach(stv6110x_attach, *fe,
209                                         &stv6110x_config, tsin->i2c_adapter);
210                 if (!fe2) {
211                         dev_err(c8sectpfe->device,
212                                 "%s: stv6110x_attach failed for NIM card %s\n"
213                                 , __func__, dvb_card_str(tsin->dvb_card));
214                         return -ENODEV;
215                 };
216
217                 stv090x_config.tuner_init = fe2->tuner_init;
218                 stv090x_config.tuner_set_mode = fe2->tuner_set_mode;
219                 stv090x_config.tuner_set_frequency = fe2->tuner_set_frequency;
220                 stv090x_config.tuner_get_frequency = fe2->tuner_get_frequency;
221                 stv090x_config.tuner_set_bandwidth = fe2->tuner_set_bandwidth;
222                 stv090x_config.tuner_get_bandwidth = fe2->tuner_get_bandwidth;
223                 stv090x_config.tuner_set_bbgain = fe2->tuner_set_bbgain;
224                 stv090x_config.tuner_get_bbgain = fe2->tuner_get_bbgain;
225                 stv090x_config.tuner_set_refclk = fe2->tuner_set_refclk;
226                 stv090x_config.tuner_get_status = fe2->tuner_get_status;
227
228                 dvb_attach(lnbh24_attach, *fe, tsin->i2c_adapter, 0, 0, 0x9);
229                 break;
230
231         default:
232                 dev_err(c8sectpfe->device,
233                         "%s: DVB frontend card %s not yet supported\n",
234                         __func__, dvb_card_str(tsin->dvb_card));
235                 return -ENODEV;
236         }
237
238         (*fe)->id = chan_num;
239
240         dev_info(c8sectpfe->device,
241                         "DVB frontend card %s successfully attached",
242                         dvb_card_str(tsin->dvb_card));
243         return 0;
244 }