summaryrefslogtreecommitdiff
path: root/drivers/stream_input/parser/demux/hw_demux/frontend.c (plain)
blob: 2e40179b77bea1058cfd1f090f5c8b83820a1192
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/amlogic/media/utils/amstream.h>
42//#include <linux/clk.h>
43#include "c_stb_define.h"
44#include "c_stb_regs_define.h"
45#include "../aml_dvb.h"
46#include "dvb_reg.h"
47
48#include "../../../tv_frontend/aml_fe.h"
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
55typedef enum __demod_type
56{
57 DEMOD_INVALID,
58 DEMOD_INTERNAL,
59 DEMOD_ATBM8881,
60 DEMOD_MAX_NUM
61}demod_type;
62
63typedef enum __tuner_type
64{
65 TUNER_INVALID,
66 TUNER_SI2151,
67 TUNER_MXL661,
68 TUNER_SI2159,
69 TUNER_R842,
70 TUNER_R840,
71 TUNER_MAX_NUM
72}tuner_type;
73
74static struct dvb_frontend *frontend[FE_DEV_COUNT] = {NULL, NULL};
75static demod_type s_demod_type[FE_DEV_COUNT] = {DEMOD_INVALID, DEMOD_INVALID};
76static tuner_type s_tuner_type[FE_DEV_COUNT] = {TUNER_INVALID, TUNER_INVALID};
77
78static int dvb_attach_tuner(struct dvb_frontend *fe, struct aml_tuner *tuner, tuner_type *type)
79{
80 struct tuner_config *cfg = &tuner->cfg;
81 struct i2c_adapter *i2c_adap = tuner->i2c_adp;
82
83 switch (cfg->id) {
84 case AM_TUNER_R840:
85 if (!dvb_attach(r840_attach, fe, i2c_adap, cfg)) {
86 pr_error("dvb attach r840_attach tuner error\n");
87 return -1;
88 } else {
89 pr_inf("r840_attach attach sucess\n");
90 *type = TUNER_R840;
91 }
92 break;
93 case AM_TUNER_R842:
94 if (!dvb_attach(r842_attach, fe, i2c_adap, cfg)) {
95 pr_error("dvb attach r842_attach tuner error\n");
96 return -1;
97 } else {
98 pr_inf("r842_attach attach sucess\n");
99 *type = TUNER_R842;
100 }
101 break;
102 case AM_TUNER_SI2151:
103 if (!dvb_attach(si2151_attach, fe, i2c_adap, cfg)) {
104 pr_error("dvb attach tuner error\n");
105 return -1;
106 } else {
107 pr_inf("si2151 attach sucess\n");
108 *type = TUNER_SI2151;
109 }
110 break;
111 case AM_TUNER_SI2159:
112 if (!dvb_attach(si2159_attach, fe, i2c_adap, cfg)) {
113 pr_error("dvb attach si2159_attach tuner error\n");
114 return -1;
115 } else {
116 pr_inf("si2159_attach attach sucess\n");
117 *type = TUNER_SI2159;
118 }
119 break;
120 case AM_TUNER_MXL661:
121 if (!dvb_attach(mxl661_attach, fe, i2c_adap, cfg)) {
122 pr_error("dvb attach mxl661_attach tuner error\n");
123 return -1;
124 } else {
125 pr_inf("mxl661_attach attach sucess\n");
126 *type = TUNER_MXL661;
127 }
128 break;
129 default:
130 pr_error("can't support tuner type: %d\n", cfg->id);
131 break;
132 }
133
134 return 0;
135}
136
137ssize_t stb_show_tuner_setting(struct class *class,
138 struct class_attribute *attr, char *buf)
139{
140 struct aml_dvb *dvb = aml_get_dvb_device();
141
142 if (dvb->tuner_cur >= 0)
143 pr_inf("dvb current attatch tuner %d, id: %d\n",
144 dvb->tuner_cur, dvb->tuners[dvb->tuner_cur].cfg.id);
145 else
146 pr_inf("dvb has no attatch tuner.\n");
147
148 return 0;
149}
150
151ssize_t stb_store_tuner_setting(struct class *class,
152 struct class_attribute *attr,
153 const char *buf, size_t count)
154{
155 int n = 0, i = 0, val = 0;
156 unsigned long tmp = 0;
157 char *buf_orig = NULL, *ps = NULL, *token = NULL;
158 char *parm[4] = { NULL };
159 struct aml_dvb *dvb = aml_get_dvb_device();
160 int tuner_id = 0;
161 struct aml_tuner *tuner = NULL;
162
163 buf_orig = kstrdup(buf, GFP_KERNEL);
164 ps = buf_orig;
165
166 while (1) {
167 token = strsep(&ps, "\n ");
168 if (token == NULL)
169 break;
170 if (*token == '\0')
171 continue;
172 parm[n++] = token;
173 }
174
175 if (parm[0] && kstrtoul(parm[0], 10, &tmp) == 0) {
176 val = tmp;
177
178 for (i = 0; i < dvb->tuner_num; ++i) {
179 if (dvb->tuners[i].cfg.id == val) {
180 tuner_id = dvb->tuners[i].cfg.id;
181 break;
182 }
183 }
184
185 if (tuner_id == 0 || dvb->tuner_cur == i) {
186 pr_error("%s: set nonsupport or the same tuner %d.\n",
187 __func__, val);
188 goto EXIT;
189 }
190
191 dvb->tuner_cur = i;
192
193 for (i = 0; i < FE_DEV_COUNT; i++) {
194 tuner = &dvb->tuners[dvb->tuner_cur];
195
196 if (frontend[i] == NULL)
197 continue;
198
199 if (dvb_attach_tuner(frontend[i], tuner, &s_tuner_type[i]) < 0) {
200 pr_error("attach tuner %d failed\n", dvb->tuner_cur);
201 goto EXIT;
202 }
203 }
204
205 pr_error("%s: attach tuner %d done.\n", __func__, dvb->tuners[dvb->tuner_cur].cfg.id);
206 }
207
208EXIT:
209
210 return count;
211}
212
213
214int frontend_probe(struct platform_device *pdev)
215{
216 struct amlfe_exp_config config;
217 char buf[32];
218 const char *str = NULL;
219 struct device_node *node_tuner = NULL;
220 struct device_node *node_i2c = NULL;
221 u32 i2c_addr = 0xFFFFFFFF;
222 struct tuner_config *cfg = NULL;
223 u32 value = 0;
224 int i = 0;
225 int ret =0;
226 int j = 0;
227 struct aml_dvb *advb = aml_get_dvb_device();
228
229 for (i=0; i<FE_DEV_COUNT; i++) {
230 memset(buf, 0, 32);
231 snprintf(buf, sizeof(buf), "fe%d_mode", i);
232 ret = of_property_read_string(pdev->dev.of_node, buf, &str);
233 if (ret) {
234 continue;
235 }
236 if (!strcmp(str,"internal"))
237 {
238 config.set_mode = 0;
239 frontend[i] = dvb_attach(aml_dtvdm_attach,&config);
240 if (frontend[i] == NULL) {
241 pr_error("dvb attach demod error\n");
242 goto error_fe;
243 } else {
244 pr_inf("dtvdemod attatch sucess\n");
245 s_demod_type[i] = DEMOD_INTERNAL;
246 }
247
248 memset(&cfg, 0, sizeof(struct tuner_config));
249 memset(buf, 0, 32);
250 snprintf(buf, sizeof(buf), "fe%d_tuner",i);
251 node_tuner = of_parse_phandle(pdev->dev.of_node, buf, 0);
252 if (!node_tuner){
253 pr_err("can't find tuner.\n");
254 goto error_fe;
255 }
256 ret = of_property_read_u32(node_tuner, "tuner_num", &value);
257 if (ret) {
258 pr_err("can't find tuner_num.\n");
259 goto error_fe;
260 } else
261 advb->tuner_num = value;
262
263 advb->tuners = kzalloc(sizeof(struct aml_tuner) * advb->tuner_num, GFP_KERNEL);
264 if (!advb->tuners) {
265 pr_err("can't kzalloc for tuners.\n");
266 goto error_fe;
267 }
268
269 ret = of_property_read_u32(node_tuner, "tuner_cur", &value);
270 if (ret) {
271 pr_err("can't find tuner_cur, use default 0.\n");
272 advb->tuner_cur = -1;
273 } else
274 advb->tuner_cur = value;
275
276 for (j = 0; j < advb->tuner_num; ++j) {
277 snprintf(buf, sizeof(buf), "tuner_name_%d", j);
278 ret = of_property_read_string(node_tuner, buf, &str);
279 if (ret) {
280 //pr_error("tuner%d type error\n",i);
281 ret = 0;
282 continue;
283 } else {
284 if (!strncmp(str, "mxl661_tuner", 12))
285 advb->tuners[j].cfg.id = AM_TUNER_MXL661;
286 else if (!strncmp(str, "si2151_tuner", 12))
287 advb->tuners[j].cfg.id = AM_TUNER_SI2151;
288 else if (!strncmp(str, "si2159_tuner", 12))
289 advb->tuners[j].cfg.id = AM_TUNER_SI2159;
290 else if (!strncmp(str, "r840_tuner", 10))
291 advb->tuners[j].cfg.id = AM_TUNER_R840;
292 else if (!strncmp(str, "r842_tuner", 10))
293 advb->tuners[j].cfg.id = AM_TUNER_R842;
294 else {
295 pr_err("nonsupport tuner: %s.\n", str);
296 advb->tuners[j].cfg.id = AM_TUNER_NONE;
297 }
298 }
299
300 snprintf(buf, sizeof(buf), "tuner_i2c_adap_%d", j);
301 node_i2c = of_parse_phandle(node_tuner, buf, 0);
302 if (!node_i2c) {
303 pr_error("tuner_i2c_adap_id error\n");
304 } else {
305 advb->tuners[j].i2c_adp = of_find_i2c_adapter_by_node(node_i2c);
306 of_node_put(node_i2c);
307 if (advb->tuners[j].i2c_adp == NULL) {
308 pr_error("i2c_get_adapter error\n");
309 of_node_put(node_tuner);
310 goto error_fe;
311 }
312 }
313
314 snprintf(buf, sizeof(buf), "tuner_i2c_addr_%d", j);
315 ret = of_property_read_u32(node_tuner, buf, &i2c_addr);
316 if (ret) {
317 pr_error("i2c_addr error\n");
318 }
319 else
320 advb->tuners[j].cfg.i2c_addr = i2c_addr;
321
322 snprintf(buf, sizeof(buf), "tuner_xtal_%d", j);
323 ret = of_property_read_u32(node_tuner, buf, &value);
324 if (ret)
325 pr_err("tuner_xtal error.\n");
326 else
327 advb->tuners[j].cfg.xtal = value;
328
329 snprintf(buf, sizeof(buf), "tuner_xtal_mode_%d", j);
330 ret = of_property_read_u32(node_tuner, buf, &value);
331 if (ret)
332 pr_err("tuner_xtal_mode error.\n");
333 else
334 advb->tuners[j].cfg.xtal_mode = value;
335
336 snprintf(buf, sizeof(buf), "tuner_xtal_cap_%d", j);
337 ret = of_property_read_u32(node_tuner, buf, &value);
338 if (ret)
339 pr_err("tuner_xtal_cap error.\n");
340 else
341 advb->tuners[j].cfg.xtal_cap = value;
342 }
343
344 of_node_put(node_tuner);
345
346 /* define general-purpose callback pointer */
347 frontend[i]->callback = NULL;
348
349 if (advb->tuner_cur >= 0) {
350 if (dvb_attach_tuner(frontend[i], &advb->tuners[advb->tuner_cur], &s_tuner_type[i]) < 0) {
351 pr_error("attach tuner failed\n");
352 goto error_fe;
353 }
354 }
355
356 ret = dvb_register_frontend(&advb->dvb_adapter, frontend[i]);
357 if (ret) {
358 pr_error("register dvb frontend failed\n");
359 goto error_fe;
360 }
361 } else if(!strcmp(str,"external")) {
362 const char *name = NULL;
363 struct amlfe_demod_config config;
364
365 config.dev_id = i;
366 memset(buf, 0, 32);
367 snprintf(buf, sizeof(buf), "fe%d_demod",i);
368 ret = of_property_read_string(pdev->dev.of_node, buf, &name);
369 if (ret) {
370 ret = 0;
371 continue;
372 }
373
374 memset(buf, 0, 32);
375 snprintf(buf, sizeof(buf), "fe%d_i2c_adap_id",i);
376 node_i2c = of_parse_phandle(pdev->dev.of_node,buf,0);
377 if (!node_i2c) {
378 pr_error("demod%d_i2c_adap_id error\n", i);
379 } else {
380 config.i2c_adap = of_find_i2c_adapter_by_node(node_i2c);
381 of_node_put(node_i2c);
382 if (config.i2c_adap == NULL) {
383 pr_error("i2c_get_adapter error\n");
384 goto error_fe;
385 }
386 }
387
388 memset(buf, 0, 32);
389 snprintf(buf, sizeof(buf), "fe%d_demod_i2c_addr",i);
390 ret = of_property_read_u32(pdev->dev.of_node, buf,&config.i2c_addr);
391 if (ret) {
392 pr_error("i2c_addr error\n");
393 goto error_fe;
394 }
395
396 memset(buf, 0, 32);
397 snprintf(buf, sizeof(buf), "fe%d_ts",i);
398 ret = of_property_read_u32(pdev->dev.of_node, buf,&config.ts);
399 if (ret) {
400 pr_error("ts error\n");
401 goto error_fe;
402 }
403
404 memset(buf, 0, 32);
405 snprintf(buf, sizeof(buf), "fe%d_reset_gpio",i);
406 ret = of_property_read_string(pdev->dev.of_node, buf, &str);
407 if (!ret) {
408 config.reset_gpio =
409 of_get_named_gpio_flags(pdev->dev.of_node,
410 buf, 0, NULL);
411 pr_inf("%s: %d\n", buf, config.reset_gpio);
412 } else {
413 config.reset_gpio = -1;
414 pr_error("cannot find resource \"%s\"\n", buf);
415 goto error_fe;
416 }
417
418 memset(buf, 0, 32);
419 snprintf(buf, sizeof(buf), "fe%d_reset_value",i);
420 ret = of_property_read_u32(pdev->dev.of_node, buf,&config.reset_value);
421 if (ret) {
422 pr_error("reset_value error\n");
423 goto error_fe;
424 }
425
426 if (!strcmp(name,"Atbm8881")) {
427 frontend[i] = dvb_attach(atbm8881_attach,&config);
428 if (frontend[i] == NULL) {
429 pr_error("dvb attach demod error\n");
430 goto error_fe;
431 } else {
432 pr_inf("dtvdemod attatch sucess\n");
433 s_demod_type[i] = DEMOD_ATBM8881;
434 }
435 }
436 if (frontend[i]) {
437 ret = dvb_register_frontend(&advb->dvb_adapter, frontend[i]);
438 if (ret) {
439 pr_error("register dvb frontend failed\n");
440 goto error_fe;
441 }
442 }
443 }
444 }
445 if (advb->tuners)
446 kfree(advb->tuners);
447 return 0;
448error_fe:
449 for (i=0; i<FE_DEV_COUNT; i++) {
450 if (s_demod_type[i] == DEMOD_INTERNAL) {
451 dvb_detach(aml_dtvdm_attach);
452 frontend[i] = NULL;
453 s_demod_type[i] = DEMOD_INVALID;
454 }else if (s_demod_type[i] == DEMOD_ATBM8881) {
455 dvb_detach(atbm8881_attach);
456 frontend[i] = NULL;
457 s_demod_type[i] = DEMOD_INVALID;
458 }
459 if (s_tuner_type[i] == TUNER_SI2151) {
460 dvb_detach(si2151_attach);
461 s_tuner_type[i] = TUNER_INVALID;
462 }else if (s_tuner_type[i] == TUNER_MXL661) {
463 dvb_detach(mxl661_attach);
464 s_tuner_type[i] = TUNER_INVALID;
465 }else if (s_tuner_type[i] == TUNER_SI2159) {
466 dvb_detach(si2159_attach);
467 s_tuner_type[i] = TUNER_INVALID;
468 }else if (s_tuner_type[i] == TUNER_R842) {
469 dvb_detach(r842_attach);
470 s_tuner_type[i] = TUNER_INVALID;
471 }else if (s_tuner_type[i] == TUNER_R840) {
472 dvb_detach(r840_attach);
473 s_tuner_type[i] = TUNER_INVALID;
474 }
475 }
476
477 if (advb->tuners)
478 kfree(advb->tuners);
479
480 return 0;
481}
482
483int frontend_remove(void)
484{
485 int i;
486
487 for (i=0; i<FE_DEV_COUNT; i++) {
488 if (s_demod_type[i] == DEMOD_INTERNAL) {
489 dvb_detach(aml_dtvdm_attach);
490 }else if (s_demod_type[i] == DEMOD_ATBM8881) {
491 dvb_detach(atbm8881_attach);
492 }
493 if (s_tuner_type[i] == TUNER_SI2151) {
494 dvb_detach(si2151_attach);
495 }else if (s_tuner_type[i] == TUNER_MXL661) {
496 dvb_detach(mxl661_attach);
497 }else if (s_tuner_type[i] == TUNER_SI2159) {
498 dvb_detach(si2159_attach);
499 }else if (s_tuner_type[i] == TUNER_R842) {
500 dvb_detach(r842_attach);
501 }else if (s_tuner_type[i] == TUNER_R840) {
502 dvb_detach(r840_attach);
503 }
504
505 if (frontend[i] && \
506 ( (s_tuner_type[i] == TUNER_SI2151) || (s_tuner_type[i] == TUNER_MXL661) || (s_tuner_type[i] == TUNER_SI2159) || (s_tuner_type[i] == TUNER_R842) || (s_tuner_type[i] == TUNER_R840)) \
507 )
508 {
509 dvb_unregister_frontend(frontend[i]);
510 dvb_frontend_detach(frontend[i]);
511 }
512 frontend[i] = NULL;
513 s_demod_type[i] = DEMOD_INVALID;
514 s_tuner_type[i] = TUNER_INVALID;
515
516 }
517 return 0;
518}
519
520