summaryrefslogtreecommitdiff
path: root/drivers/stream_input/parser/demux/hw_demux/frontend.c (plain)
blob: 90a70c4a9bcbaa9c7f1f01a89be1ff7f0a8f44c2
1/*
2* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful, but WITHOUT
10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12* more details.
13*
14* You should have received a copy of the GNU General Public License along
15* with this program; if not, write to the Free Software Foundation, Inc.,
16* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17*
18* Description:
19*/
20#include <linux/version.h>
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/mutex.h>
24#include <linux/wait.h>
25#include <linux/string.h>
26#include <linux/interrupt.h>
27#include <linux/fs.h>
28#include <linux/cdev.h>
29#include <linux/device.h>
30#include <linux/spinlock.h>
31#include <linux/fcntl.h>
32//#include <asm/irq.h>
33#include <linux/uaccess.h>
34#include <linux/poll.h>
35#include <linux/delay.h>
36#include <linux/platform_device.h>
37#include <linux/gpio.h>
38#include <linux/string.h>
39#include <linux/pinctrl/consumer.h>
40#include <linux/reset.h>
41#include <linux/of_gpio.h>
42#include <linux/amlogic/media/utils/amstream.h>
43//#include <linux/clk.h>
44#include "c_stb_define.h"
45#include "c_stb_regs_define.h"
46#include "../aml_dvb.h"
47#include "dvb_reg.h"
48
49#include "demod_gt.h"
50#include "../../../../common/media_clock/switch/amports_gate.h"
51
52#define pr_error(fmt, args...) printk("DVB: " fmt, ## args)
53#define pr_inf(fmt, args...) printk("DVB: " fmt, ## args)
54
55static struct dvb_frontend *frontend[FE_DEV_COUNT] = {NULL, NULL};
56static enum dtv_demod_type s_demod_type[FE_DEV_COUNT] = {AM_DTV_DEMOD_NONE, AM_DTV_DEMOD_NONE};
57static enum tuner_type s_tuner_type[FE_DEV_COUNT] = {AM_TUNER_NONE, AM_TUNER_NONE};
58
59
60ssize_t stb_show_tuner_setting(struct class *class,
61 struct class_attribute *attr, char *buf)
62{
63 struct aml_dvb *dvb = aml_get_dvb_device();
64
65 if (dvb->tuner_cur >= 0)
66 pr_inf("dvb current attatch tuner %d, id: %d\n",
67 dvb->tuner_cur, dvb->tuners[dvb->tuner_cur].cfg.id);
68 else
69 pr_inf("dvb has no attatch tuner.\n");
70
71 return 0;
72}
73
74ssize_t stb_store_tuner_setting(struct class *class,
75 struct class_attribute *attr,
76 const char *buf, size_t count)
77{
78 int n = 0, i = 0, val = 0;
79 unsigned long tmp = 0;
80 char *buf_orig = NULL, *ps = NULL, *token = NULL;
81 char *parm[4] = { NULL };
82 struct aml_dvb *dvb = aml_get_dvb_device();
83 int tuner_id = 0;
84 struct aml_tuner *tuner = NULL;
85
86 buf_orig = kstrdup(buf, GFP_KERNEL);
87 ps = buf_orig;
88
89 while (1) {
90 token = strsep(&ps, "\n ");
91 if (token == NULL)
92 break;
93 if (*token == '\0')
94 continue;
95 parm[n++] = token;
96 }
97
98 if (parm[0] && kstrtoul(parm[0], 10, &tmp) == 0) {
99 val = tmp;
100
101 for (i = 0; i < dvb->tuner_num; ++i) {
102 if (dvb->tuners[i].cfg.id == val) {
103 tuner_id = dvb->tuners[i].cfg.id;
104 break;
105 }
106 }
107
108 if (tuner_id == 0 || dvb->tuner_cur == i) {
109 pr_error("%s: set nonsupport or the same tuner %d.\n",
110 __func__, val);
111 goto EXIT;
112 }
113
114 dvb->tuner_cur = i;
115
116 for (i = 0; i < FE_DEV_COUNT; i++) {
117 tuner = &dvb->tuners[dvb->tuner_cur];
118
119 if (frontend[i] == NULL)
120 continue;
121
122 if (aml_attach_tuner(tuner->cfg.id, frontend[i], &tuner->cfg) == NULL) {
123 s_tuner_type[i] = AM_TUNER_NONE;
124 pr_error("tuner[%d] [type = %d] attach error.\n", dvb->tuner_cur, tuner->cfg.id);
125 goto EXIT;
126 } else {
127 s_tuner_type[i] = tuner->cfg.id;
128 pr_error("tuner[%d] [type = %d] attach sucess.\n", dvb->tuner_cur, tuner->cfg.id);
129 }
130 }
131
132 pr_error("%s: attach tuner %d done.\n", __func__, dvb->tuners[dvb->tuner_cur].cfg.id);
133 }
134
135EXIT:
136
137 return count;
138}
139
140
141int frontend_probe(struct platform_device *pdev)
142{
143 struct demod_config config;
144 struct tuner_config *tuner_cfg = NULL;
145 char buf[32];
146 const char *str = NULL;
147 struct device_node *node_tuner = NULL;
148 struct device_node *node_i2c = NULL;
149 u32 i2c_addr = 0xFFFFFFFF;
150 u32 value = 0;
151 int i = 0;
152 int ret =0;
153 int j = 0;
154 struct aml_dvb *advb = aml_get_dvb_device();
155
156 for (i=0; i<FE_DEV_COUNT; i++) {
157 memset(&config, 0, sizeof(struct demod_config));
158
159 memset(buf, 0, 32);
160 snprintf(buf, sizeof(buf), "fe%d_mode", i);
161 ret = of_property_read_string(pdev->dev.of_node, buf, &str);
162 if (ret) {
163 continue;
164 }
165
166 if (!strcmp(str, "internal")) {
167 config.mode = 0;
168 config.id = AM_DTV_DEMOD_AMLDTV;
169 frontend[i] = aml_attach_dtvdemod(config.id, &config);
170 if (frontend[i] == NULL) {
171 s_demod_type[i] = AM_DTV_DEMOD_NONE;
172 pr_error("internal dtvdemod [type = %d] attach error.\n", config.id);
173 goto error_fe;
174 } else {
175 s_demod_type[i] = config.id;
176 pr_error("internal dtvdemod [type = %d] attach success.\n", config.id);
177 }
178
179 memset(buf, 0, 32);
180 snprintf(buf, sizeof(buf), "fe%d_tuner",i);
181 node_tuner = of_parse_phandle(pdev->dev.of_node, buf, 0);
182 if (!node_tuner){
183 pr_err("can't find tuner.\n");
184 goto error_fe;
185 }
186 ret = of_property_read_u32(node_tuner, "tuner_num", &value);
187 if (ret) {
188 pr_err("can't find tuner_num.\n");
189 goto error_fe;
190 } else
191 advb->tuner_num = value;
192
193 advb->tuners = kzalloc(sizeof(struct aml_tuner) * advb->tuner_num, GFP_KERNEL);
194 if (!advb->tuners) {
195 pr_err("can't kzalloc for tuners.\n");
196 goto error_fe;
197 }
198
199 ret = of_property_read_u32(node_tuner, "tuner_cur", &value);
200 if (ret) {
201 pr_err("can't find tuner_cur, use default 0.\n");
202 advb->tuner_cur = -1;
203 } else
204 advb->tuner_cur = value;
205
206 for (j = 0; j < advb->tuner_num; ++j) {
207 snprintf(buf, sizeof(buf), "tuner_name_%d", j);
208 ret = of_property_read_string(node_tuner, buf, &str);
209 if (ret) {
210 //pr_error("tuner%d type error\n",i);
211 ret = 0;
212 continue;
213 } else {
214 advb->tuners[j].cfg.id = aml_get_tuner_type(str);
215 if (advb->tuners[j].cfg.id == AM_TUNER_NONE)
216 pr_err("can't support tuner: %s.\n", str);
217 }
218
219 snprintf(buf, sizeof(buf), "tuner_i2c_adap_%d", j);
220 node_i2c = of_parse_phandle(node_tuner, buf, 0);
221 if (!node_i2c) {
222 pr_error("tuner_i2c_adap_id error\n");
223 } else {
224 advb->tuners[j].cfg.i2c_adap = of_find_i2c_adapter_by_node(node_i2c);
225 of_node_put(node_i2c);
226 if (advb->tuners[j].cfg.i2c_adap == NULL) {
227 pr_error("i2c_get_adapter error\n");
228 of_node_put(node_tuner);
229 goto error_fe;
230 }
231 }
232
233 snprintf(buf, sizeof(buf), "tuner_i2c_addr_%d", j);
234 ret = of_property_read_u32(node_tuner, buf, &i2c_addr);
235 if (ret) {
236 pr_error("i2c_addr error\n");
237 }
238 else
239 advb->tuners[j].cfg.i2c_addr = i2c_addr;
240
241 snprintf(buf, sizeof(buf), "tuner_xtal_%d", j);
242 ret = of_property_read_u32(node_tuner, buf, &value);
243 if (ret)
244 pr_err("tuner_xtal error.\n");
245 else
246 advb->tuners[j].cfg.xtal = value;
247
248 snprintf(buf, sizeof(buf), "tuner_xtal_mode_%d", j);
249 ret = of_property_read_u32(node_tuner, buf, &value);
250 if (ret)
251 pr_err("tuner_xtal_mode error.\n");
252 else
253 advb->tuners[j].cfg.xtal_mode = value;
254
255 snprintf(buf, sizeof(buf), "tuner_xtal_cap_%d", j);
256 ret = of_property_read_u32(node_tuner, buf, &value);
257 if (ret)
258 pr_err("tuner_xtal_cap error.\n");
259 else
260 advb->tuners[j].cfg.xtal_cap = value;
261 }
262
263 of_node_put(node_tuner);
264
265 /* define general-purpose callback pointer */
266 frontend[i]->callback = NULL;
267
268 if (advb->tuner_cur >= 0) {
269 tuner_cfg = &advb->tuners[advb->tuner_cur].cfg;
270 if (aml_attach_tuner(tuner_cfg->id, frontend[i], tuner_cfg) == NULL) {
271 s_tuner_type[i] = AM_TUNER_NONE;
272 pr_error("tuner [type = %d] attach error.\n", tuner_cfg->id);
273 goto error_fe;
274 } else {
275 s_tuner_type[i] = tuner_cfg->id;
276 pr_error("tuner [type = %d] attach sucess.\n", tuner_cfg->id);
277 }
278 }
279
280 ret = dvb_register_frontend(&advb->dvb_adapter, frontend[i]);
281 if (ret) {
282 pr_error("register dvb frontend failed\n");
283 goto error_fe;
284 }
285 } else if(!strcmp(str, "external")) {
286 config.mode = 1;
287 config.id = AM_DTV_DEMOD_NONE;
288 ret = aml_get_dts_demod_config(pdev->dev.of_node, &config, i);
289 if (ret) {
290 pr_err("can't find demod %d.\n", i);
291 continue;
292 }
293
294 memset(buf, 0, 32);
295 snprintf(buf, sizeof(buf), "fe%d_tuner", i);
296 node_tuner = of_parse_phandle(pdev->dev.of_node, buf, 0);
297 if (node_tuner) {
298 aml_get_dts_tuner_config(node_tuner, &config.tuner0, 0);
299 aml_get_dts_tuner_config(node_tuner, &config.tuner1, 1);
300 } else
301 pr_err("can't find %s.\n", buf);
302
303 of_node_put(node_tuner);
304
305 frontend[i] = aml_attach_dtvdemod(config.id, &config);
306 if (frontend[i] == NULL) {
307 s_demod_type[i] = AM_DTV_DEMOD_NONE;
308 pr_error("external dtvdemod [type = %d] attach error.\n", config.id);
309 goto error_fe;
310 } else {
311 s_demod_type[i] = config.id;
312 pr_error("external dtvdemod [type = %d] attach success.\n", config.id);
313 }
314
315 if (frontend[i]) {
316 ret = dvb_register_frontend(&advb->dvb_adapter, frontend[i]);
317 if (ret) {
318 pr_error("register dvb frontend failed\n");
319 goto error_fe;
320 }
321 }
322 }
323 }
324 if (advb->tuners)
325 kfree(advb->tuners);
326 return 0;
327error_fe:
328 for (i=0; i<FE_DEV_COUNT; i++) {
329 aml_detach_dtvdemod(s_demod_type[i]);
330 frontend[i] = NULL;
331 s_demod_type[i] = AM_DTV_DEMOD_NONE;
332
333 aml_detach_tuner(s_tuner_type[i]);
334 s_tuner_type[i] = AM_TUNER_NONE;
335 }
336
337 if (advb->tuners)
338 kfree(advb->tuners);
339
340 return 0;
341}
342
343int frontend_remove(void)
344{
345 int i;
346
347 for (i=0; i<FE_DEV_COUNT; i++) {
348 aml_detach_dtvdemod(s_demod_type[i]);
349
350 aml_detach_tuner(s_tuner_type[i]);
351
352 if (frontend[i] &&
353 ((s_tuner_type[i] == AM_TUNER_SI2151)
354 || (s_tuner_type[i] == AM_TUNER_MXL661)
355 || (s_tuner_type[i] == AM_TUNER_SI2159)
356 || (s_tuner_type[i] == AM_TUNER_R842)
357 || (s_tuner_type[i] == AM_TUNER_R840)
358 || (s_tuner_type[i] == AM_TUNER_ATBM2040))) {
359 dvb_unregister_frontend(frontend[i]);
360 dvb_frontend_detach(frontend[i]);
361 }
362
363 frontend[i] = NULL;
364 s_demod_type[i] = AM_DTV_DEMOD_NONE;
365 s_tuner_type[i] = AM_TUNER_NONE;
366
367 }
368 return 0;
369}
370
371