blob: 8070584ee66f078eed4203ab9604e5445b0841b5 [file] [log] [blame]
/*
* drivers/amlogic/media/dtv_demod/amlfrontend.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
/*****************************************************************
** author :
** Shijie.Rong@amlogic.com
** version :
** v1.0 12/3/13
** v2.0 15/10/12
** v3.0 17/11/15
*****************************************************************/
#define __DVB_CORE__ /*ary 2018-1-31*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/err.h> /*IS_ERR*/
#include <linux/clk.h> /*clk tree*/
#include <linux/of_device.h>
#include <linux/of_reserved_mem.h>
#ifdef ARC_700
#include <asm/arch/am_regs.h>
#else
/* #include <mach/am_regs.h> */
#endif
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/dvb/aml_demod.h>
#include "demod_func.h"
/*dma_get_cma_size_int_byte*/
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include <linux/dma-contiguous.h>
#include <linux/amlogic/media/frame_provider/tvin/tvin.h>
MODULE_PARM_DESC(debug_aml, "\n\t\t Enable frontend debug information");
static int debug_aml = 1;
module_param(debug_aml, int, 0644);
MODULE_PARM_DESC(auto_search_std, "\n\t\t atsc-c std&hrc search");
static unsigned int auto_search_std;
module_param(auto_search_std, int, 0644);
MODULE_PARM_DESC(std_lock_timeout, "\n\t\t atsc-c std lock timeout");
static unsigned int std_lock_timeout = 1000;
module_param(std_lock_timeout, int, 0644);
/*0.001for field,0.002 for performance
*0.04: new method of tl1 dvbc channel fast search(Hisense project)
*/
static char *demod_version = "V0.04";
int aml_demod_debug = DBG_INFO;
/*use this flag to mark the new method for dvbc channel fast search
*it's disabled as default, can be enabled if needed
*we can make it always enabled after all testing are passed
*/
static unsigned int demod_dvbc_speedup_en;
#if 0
#define PR_DBG(fmt, args ...) \
do { \
if (aml_demod_debug & DBG_INFO) { \
pr_info("dtv_dmd:"fmt, ##args); \
} \
} while (0)
#endif
/* debug info------------------------*/
module_param(aml_demod_debug, int, 0644);
MODULE_PARM_DESC(aml_demod_debug, "set debug level (info=bit1, reg=bit2, atsc=bit4,");
/*-----------------------------------*/
struct amldtvdemod_device_s *dtvdd_devp;
static int last_lock = -1; /*debug only*/
#define DEMOD_DEVICE_NAME "Amlogic_Demod"
static int cci_thread;
static int freq_dvbc;
static struct aml_demod_sta demod_status;
static enum fe_modulation atsc_mode = VSB_8;
static struct aml_demod_para para_demod;
static int atsc_flag;
static int memstart = 0x1ef00000;/* move to aml_dtv_demod*/
long *mem_buf;
MODULE_PARM_DESC(frontend_mode, "\n\t\t Frontend mode 0-DVBC, 1-DVBT");
static int frontend_mode = -1;
module_param(frontend_mode, int, 0444);
MODULE_PARM_DESC(frontend_i2c, "\n\t\t IIc adapter id of frontend");
static int frontend_i2c = -1;
module_param(frontend_i2c, int, 0444);
MODULE_PARM_DESC(frontend_tuner,
"\n\t\t Frontend tuner type 0-NULL, 1-DCT7070, 2-Maxliner, 3-FJ2207, 4-TD1316");
static int frontend_tuner = -1;
module_param(frontend_tuner, int, 0444);
MODULE_PARM_DESC(frontend_tuner_addr, "\n\t\t Tuner IIC address of frontend");
static int frontend_tuner_addr = -1;
module_param(frontend_tuner_addr, int, 0444);
MODULE_PARM_DESC(demod_thread, "\n\t\t demod thread");
static int demod_thread = 1;
module_param(demod_thread, int, 0644);
static int dvb_tuner_delay = 100;
module_param(dvb_tuner_delay, int, 0644);
MODULE_PARM_DESC(dvb_atsc_count, "dvb_tuner_delay");
#define THRD_TUNER_STRENTH_ATSC (-87)
#define THRD_TUNER_STRENTH_J83 (-76)
static int autoflags, autoFlagsTrig;
/*static struct mutex aml_lock;move to dtvdd_devp->lock*/
const char *name_reg[] = {
"demod",
"iohiu",
"aobus",
"reset",
};
/*also see: IC_VER_NUB*/
const char *name_ic[] = {
"gxtvbb",
"txl",
"txlx",
"gxlx",
"txhd",
"tl1",
};
#define END_SYS_DELIVERY 19
const char *name_fe_delivery_system[] = {
"UNDEFINED",
"DVBC_ANNEX_A",
"DVBC_ANNEX_B",
"DVBT",
"DSS",
"DVBS",
"DVBS2",
"DVBH",
"ISDBT",
"ISDBS",
"ISDBC",
"ATSC",
"ATSCMH",
"DTMB",
"CMMB",
"DAB",
"DVBT2",
"TURBO",
"DVBC_ANNEX_C",
"ANALOG", /*19*/
};
static const char * const name_fe_n_mode[] = {
"AM_FE_UNKNOWN_N",
"AM_FE_QPSK_N",
"AM_FE_QAM_N",
"AM_FE_OFDM_N",
"AM_FE_ATSC_N",
"AM_FE_DTMB_N",
"AM_FE_ISDBT_N",
"AM_FE_NUM",
};
static void dtvdemod_vdac_enable(bool on);
static void dtvdemod_set_agc_pinmux(int on);
static int Gxtv_Demod_Dvbc_Init(/*struct aml_fe_dev *dev, */int mode);
static ssize_t dvbc_auto_sym_show(struct class *cls,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "dvbc_autoflags: %s\n", autoflags ? "on" : "off");
}
static ssize_t dvbc_auto_sym_store(struct class *cls,
struct class_attribute *attr,
const char *buf, size_t count)
{
return 0;
}
static unsigned int dtmb_mode;
static unsigned int atsc_mode_para;
static enum demod_md demod_mode_para;
enum {
DTMB_READ_STRENGTH = 0,
DTMB_READ_SNR = 1,
DTMB_READ_LOCK = 2,
DTMB_READ_BCH = 3,
};
enum {
ATSC_READ_STRENGTH = 0,
ATSC_READ_SNR = 1,
ATSC_READ_LOCK = 2,
ATSC_READ_SER = 3,
ATSC_READ_FREQ = 4,
};
enum demod_md demod_get_current_mode(void)
{
return demod_mode_para;
}
int convert_snr(int in_snr)
{
int out_snr;
static int calce_snr[40] = {
5, 6, 8, 10, 13,
16, 20, 25, 32, 40,
50, 63, 80, 100, 126,
159, 200, 252, 318, 400,
504, 634, 798, 1005, 1265,
1592, 2005, 2524, 3177, 4000,
5036, 6340, 7981, 10048, 12649,
15924, 20047, 25238, 31773, 40000};
for (out_snr = 1 ; out_snr < 40; out_snr++)
if (in_snr <= calce_snr[out_snr])
break;
return out_snr;
}
static int freq_p;
static ssize_t atsc_para_show(struct class *cls,
struct class_attribute *attr, char *buf)
{
int snr, lock_status, ser;
struct dvb_frontend *dvbfe;
int strength = 0;
if (atsc_mode != VSB_8)
return 0;
if (atsc_mode_para == ATSC_READ_STRENGTH) {
dvbfe = aml_get_fe();/*get_si2177_tuner();*/
#if 0
if (dvbfe != NULL) {
if (dvbfe->ops.tuner_ops.get_strength) {
strength =
dvbfe->ops.tuner_ops.get_strength(dvbfe);
}
strength -= 100;
}
#else
strength = tuner_get_ch_power2();
#endif
return sprintf(buf, "strength is %d\n", strength);
} else if (atsc_mode_para == ATSC_READ_SNR) {
snr = atsc_read_snr();
return sprintf(buf, "snr is %d\n", snr);
} else if (atsc_mode_para == ATSC_READ_LOCK) {
lock_status =
atsc_read_reg(0x0980);
return sprintf(buf, "lock_status is %x\n", lock_status);
} else if (atsc_mode_para == ATSC_READ_SER) {
ser = atsc_read_ser();
return sprintf(buf, "ser is %d\n", ser);
} else if (atsc_mode_para == ATSC_READ_FREQ) {
return sprintf(buf, "freq is %d\n", freq_p);
} else {
return sprintf(buf, "atsc_para_show can't match mode\n");
}
}
static ssize_t atsc_para_store(struct class *cls,
struct class_attribute *attr,
const char *buf, size_t count)
{
if (buf[0] == '0')
atsc_mode_para = ATSC_READ_STRENGTH;
else if (buf[0] == '1')
atsc_mode_para = ATSC_READ_SNR;
else if (buf[0] == '2')
atsc_mode_para = ATSC_READ_LOCK;
else if (buf[0] == '3')
atsc_mode_para = ATSC_READ_SER;
else if (buf[0] == '4')
atsc_mode_para = ATSC_READ_FREQ;
return count;
}
static ssize_t demod_para_store(struct class *cls,
struct class_attribute *attr,
const char *buf, size_t count)
{
if (buf[0] == '0')
demod_mode_para = UNKNOWN;
else if (buf[0] == '1')
demod_mode_para = AML_DVBC;
else if (buf[0] == '2')
demod_mode_para = AML_DTMB;
else if (buf[0] == '3')
demod_mode_para = AML_DVBT;
else if (buf[0] == '4')
demod_mode_para = AML_ATSC;
else if (buf[0] == '5')
demod_mode_para = AML_J83B;
else if (buf[0] == '6')
demod_mode_para = AML_ISDBT;
else if (buf[0] == '7')
demod_mode_para = AML_DVBT2;
return count;
}
void store_dvbc_qam_mode(int qam_mode, int symbolrate)
{
int qam_para;
switch (qam_mode) {
case QAM_16:
qam_para = 4;
break;
case QAM_32:
qam_para = 5;
break;
case QAM_64:
qam_para = 6;
break;
case QAM_128:
qam_para = 7;
break;
case QAM_256:
qam_para = 8;
break;
case QAM_AUTO:
qam_para = 6;
break;
default:
qam_para = 6;
break;
}
para_demod.dvbc_qam = qam_para;
para_demod.dvbc_symbol = symbolrate;
PR_DBG("dvbc_qam is %d, symbolrate is %d\n",
para_demod.dvbc_qam, para_demod.dvbc_symbol);
}
static ssize_t demod_para_show(struct class *cls,
struct class_attribute *attr, char *buf)
{
int rate, symolrate, qam, coderate, a;
if (demod_mode_para == AML_DVBC) {
symolrate = para_demod.dvbc_symbol;
qam = para_demod.dvbc_qam;
rate = 944*symolrate*qam;
rate /= 1000;
} else if (demod_mode_para == AML_DTMB) {
coderate = para_demod.dtmb_coderate;
qam = para_demod.dtmb_qam;
a = 4725;
rate = 25614*qam*coderate/a;
rate *= 1024;
} else if (demod_mode_para == AML_DVBT) {
rate = 19855;
} else if (demod_mode_para == AML_ATSC) {
if (atsc_mode == VSB_8)
rate = 19855;
else if (atsc_mode == QAM_64)
rate = 27617;
else if (atsc_mode == QAM_256)
rate = 39741;
else
rate = 19855;
} else {
return sprintf(buf, "can't match mode\n");
}
return sprintf(buf, "rate %d\n", rate);
}
static ssize_t dtmb_para_show(struct class *cls,
struct class_attribute *attr, char *buf)
{
int snr, lock_status, bch, agc_if_gain[3];
struct dvb_frontend *dvbfe;
int strength = 0;
if (dtmb_mode == DTMB_READ_STRENGTH) {
dvbfe = aml_get_fe();/*get_si2177_tuner();*/
#if 0
if (dvbfe != NULL)
if (dvbfe->ops.tuner_ops.get_strength) {
strength =
dvbfe->ops.tuner_ops.get_strength(dvbfe);
}
#else
strength = tuner_get_ch_power2();
#endif
if (strength <= -56) {
dtmb_read_agc(DTMB_D9_IF_GAIN, &agc_if_gain[0]);
strength = dtmb_get_power_strength(agc_if_gain[0]);
}
return sprintf(buf, "strength is %d\n", strength);
} else if (dtmb_mode == DTMB_READ_SNR) {
/*snr = dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR) & 0x3fff;*/
snr = dtmb_reg_r_che_snr();
snr = convert_snr(snr);
return sprintf(buf, "snr is %d\n", snr);
} else if (dtmb_mode == DTMB_READ_LOCK) {
lock_status = dtmb_reg_r_fec_lock();
return sprintf(buf, "lock_status is %d\n", lock_status);
} else if (dtmb_mode == DTMB_READ_BCH) {
bch = dtmb_reg_r_bch();
return sprintf(buf, "bch is %d\n", bch);
} else {
return sprintf(buf, "dtmb_para_show can't match mode\n");
}
}
static ssize_t dtmb_para_store(struct class *cls,
struct class_attribute *attr,
const char *buf, size_t count)
{
if (buf[0] == '0')
dtmb_mode = DTMB_READ_STRENGTH;
else if (buf[0] == '1')
dtmb_mode = DTMB_READ_SNR;
else if (buf[0] == '2')
dtmb_mode = DTMB_READ_LOCK;
else if (buf[0] == '3')
dtmb_mode = DTMB_READ_BCH;
return count;
}
static int readregdata;
static ssize_t dvbc_reg_show(struct class *cls, struct class_attribute *attr,
char *buf)
{
/* int readregaddr=0;*/
char *pbuf = buf;
pbuf += sprintf(pbuf, "%x", readregdata);
PR_INFO("read dvbc_reg\n");
return pbuf - buf;
}
static ssize_t dvbc_reg_store(struct class *cls, struct class_attribute *attr,
const char *buf, size_t count)
{
return 0;
}
static ssize_t info_show(struct class *cls,
struct class_attribute *attr, char *buf)
{
int pos = 0;
unsigned int size = PAGE_SIZE;
int snr, lock_status, bch, agc_if_gain[3], ser;
struct dvb_frontend *dvbfe;
int strength = 0;
pos += snprintf(buf+pos, size-pos, "dtv demod info:\n");
switch (demod_mode_para) {
case AML_DVBC:
pos += snprintf(buf+pos, size-pos, "mode:AML_DVBC\n");
break;
case AML_DTMB:
pos += snprintf(buf+pos, size-pos, "mode:AML_DTMB\n");
/* DTMB_READ_STRENGTH */
dvbfe = aml_get_fe();/*get_si2177_tuner();*/
#if 0
if (dvbfe != NULL)
if (dvbfe->ops.tuner_ops.get_strength) {
strength =
dvbfe->ops.tuner_ops.get_strength(dvbfe);
}
#else
strength = tuner_get_ch_power2();
#endif
if (strength <= -56) {
dtmb_read_agc(DTMB_D9_IF_GAIN, &agc_if_gain[0]);
strength = dtmb_get_power_strength(agc_if_gain[0]);
}
pos += snprintf(buf+pos, size-pos,
"strength: %d\n", strength);
/* DTMB_READ_SNR */
/*snr = dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR) & 0x3fff;*/
snr = dtmb_reg_r_che_snr();
snr = convert_snr(snr);
pos += snprintf(buf+pos, size-pos, "snr: %d\n", snr);
/* DTMB_READ_LOCK */
/*lock_status = */
/* (dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR) >> 14) & 0x1;*/
lock_status = dtmb_reg_r_fec_lock();
pos += snprintf(buf+pos, size-pos, "lock: %d\n", lock_status);
/* DTMB_READ_BCH */
bch = dtmb_reg_r_bch();
pos += snprintf(buf+pos, size-pos, "bch: %d\n", bch);
break;
case AML_DVBT:
pos += snprintf(buf+pos, size-pos, "mode:AML_DVBT\n");
break;
case AML_ATSC:
pos += snprintf(buf+pos, size-pos, "mode:AML_ATSC\n");
if (atsc_mode != VSB_8)
return pos;
/* ATSC_READ_STRENGTH */
dvbfe = aml_get_fe();/*get_si2177_tuner();*/
if (dvbfe != NULL) {
#if 0
if (dvbfe->ops.tuner_ops.get_strength) {
strength =
dvbfe->ops.tuner_ops.get_strength(dvbfe);
}
#else
strength = tuner_get_ch_power2();
#endif
/*strength -= 100;*/
}
pos += snprintf(buf+pos, size-pos, "strength: %d\n", strength);
/* ATSC_READ_SNR */
snr = atsc_read_snr();
pos += snprintf(buf+pos, size-pos, "snr: %d\n", snr);
/* ATSC_READ_LOCK */
lock_status = atsc_read_reg(0x0980);
pos += snprintf(buf+pos, size-pos, "lock: %d\n", lock_status);
/* ATSC_READ_SER */
ser = atsc_read_ser();
pos += snprintf(buf+pos, size-pos, "ser: %d\n", ser);
/* ATSC_READ_FREQ */
pos += snprintf(buf+pos, size-pos, "freq: %d\n", freq_p);
break;
case AML_J83B:
pos += snprintf(buf+pos, size-pos, "mode:AML_J83B\n");
break;
case AML_ISDBT:
pos += snprintf(buf+pos, size-pos, "mode:AML_ISDBT\n");
break;
case AML_DVBT2:
pos += snprintf(buf+pos, size-pos, "mode:AML_DVBT2\n");
break;
default:
pos += snprintf(buf+pos, size-pos, "mode:Unknown\n");
break;
}
return pos;
}
static CLASS_ATTR(auto_sym, 0644, dvbc_auto_sym_show, dvbc_auto_sym_store);
static CLASS_ATTR(dtmb_para, 0644, dtmb_para_show, dtmb_para_store);
/*from 666 to 644*/
static CLASS_ATTR(dvbc_reg, 0644, dvbc_reg_show, dvbc_reg_store);
static CLASS_ATTR(atsc_para, 0644, atsc_para_show, atsc_para_store);
static CLASS_ATTR(demod_rate, 0644, demod_para_show, demod_para_store);
/* DebugInfo */
static CLASS_ATTR(info, 0444, info_show, NULL);
/*static void dtvdemod_version(struct aml_fe_dev *dev)*/
static void dtvdemod_version(struct amldtvdemod_device_s *dev)
{
char soc_version[20];
char *atsc_version = "1";
int ic_v = get_ic_ver();
if (dev->atsc_version == 1)
atsc_version = "1";
else if (dev->atsc_version == 2)
atsc_version = "2";
else
atsc_version = "1";
atsc_set_version(dev->atsc_version);
if (ic_v < IC_VER_NUB && strlen(name_ic[ic_v]) < 10) {
strcpy(soc_version, name_ic[ic_v]);
strcat(soc_version, "-");
} else {
strcpy(soc_version, "other-");
}
if (strlen(demod_version) < 8)
strcat(soc_version, demod_version);
strcat(soc_version, atsc_version);
PR_INFO("[dtvdemod_version] [%s]\n", soc_version);
}
static int amdemod_qam(enum fe_modulation qam)
{
switch (qam) {
case QAM_16:
return 0;
case QAM_32:
return 1;
case QAM_64:
return 2;
case QAM_128:
return 3;
case QAM_256:
return 4;
case VSB_8:
return 5;
case QAM_AUTO:
return 6;
default:
return 2;
}
return 2;
}
static int amdemod_stat_islock(/*struct aml_fe_dev *dev,*/ int mode)
{
struct aml_demod_sts demod_sts;
int lock_status;
int dvbt_status1;
int atsc_fsm;
int ret = 0;
if (mode == 0) {
/*DVBC*/
demod_sts.ch_sts = dvbc_get_ch_sts();
return demod_sts.ch_sts & 0x1;
} else if (mode == 1) {
/*DVBT*/
dvbt_status1 =
((dvbt_read_reg((0x0a << 2)) >> 20) & 0x3ff);
lock_status = (dvbt_read_reg((0x2a << 2))) & 0xf;
if ((((lock_status) == 9) || ((lock_status) == 10))
&& ((dvbt_status1) != 0))
return 1;
else
return 0;
/*((apb_read_reg(DVBT_BASE+0x0)>>12)&0x1);// */
/* dvbt_get_status_ops()->get_status(&demod_sts, &demod_sta);*/
} else if (mode == 2) {
} else if (mode == 3) {
/*ATSC*/
if ((atsc_mode == QAM_64) || (atsc_mode == QAM_256)) {
/*return (atsc_read_iqr_reg() >> 16) == 0x1f;*/
if ((atsc_read_iqr_reg() >> 16) == 0x1f)
ret = 1;
} else if (atsc_mode == VSB_8) {
if (is_ic_ver(IC_VER_TL1)) {
if (atsc_read_reg_v4(0x2e) >= 0x76)
ret = 1;
} else {
atsc_fsm = atsc_read_reg(0x0980);
PR_DBGL("atsc status [%x]\n", atsc_fsm);
/*return atsc_read_reg(0x0980) >= 0x79;*/
if (atsc_read_reg(0x0980) >= 0x79)
ret = 1;
}
} else {
atsc_fsm = atsc_read_reg(0x0980);
PR_DBGL("atsc status [%x]\n", atsc_fsm);
/*return atsc_read_reg(0x0980) >= 0x79;*/
if (atsc_read_reg(0x0980) >= 0x79)
ret = 1;
}
return ret;
} else if (mode == 4) {
/*DTMB*/
/*return (dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR) >> 14) & 0x1;*/
return dtmb_reg_r_fec_lock();
}
return 0;
}
#define amdemod_dvbc_stat_islock() amdemod_stat_islock(0)
#define amdemod_dvbt_stat_islock() amdemod_stat_islock(1)
#define amdemod_isdbt_stat_islock() amdemod_stat_islock(2)
#define amdemod_atsc_stat_islock() amdemod_stat_islock(3)
#define amdemod_dtmb_stat_islock() amdemod_stat_islock(4)
#if 0
/*this function is not use for txlx*/
static int gxtv_demod_dvbc_set_qam_mode(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct aml_demod_dvbc param; /*mode 0:16, 1:32, 2:64, 3:128, 4:256*/
memset(&param, 0, sizeof(param));
param.mode = amdemod_qam(c->modulation);
dvbc_set_qam_mode(param.mode);
return 0;
}
static int aml_dtvdm_set_qam_mode(struct dvb_frontend *fe)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
int ret = 0;
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
ret = gxtv_demod_dvbc_set_qam_mode(fe);
break;
case AM_FE_OFDM_N:
break;
case AM_FE_ATSC_N:
ret = gxtv_demod_atsc_set_qam_mode(fe);
break;
case AM_FE_DTMB_N:
break;
case AM_FE_UNKNOWN_N:
default:
break;
}
return ret;
}
static int gxtv_demod_atsc_set_qam_mode(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct aml_demod_atsc param; /*mode 3:64, 5:256, 7:vsb*/
enum fe_modulation mode;
memset(&param, 0, sizeof(param));
mode = c->modulation;
/*pr_dbg("mode is %d\n", mode);*/
PR_ATSC("mode is %d\n", mode);
atsc_qam_set(mode);
return 0;
}
#endif
static void gxtv_demod_dvbc_release(struct dvb_frontend *fe)
{
}
#if 0
static int gxtv_demod_dvbc_read_status
(struct dvb_frontend *fe, enum fe_status *status)
{
/* struct aml_fe_dev *dev = afe->dtv_demod;*/
struct aml_demod_sts demod_sts;
struct aml_demod_sta demod_sta;
/*struct aml_demod_i2c demod_i2c;*/
int ilock;
/*demod_sts.ch_sts = qam_read_reg(0x6);*/
demod_sts.ch_sts = dvbc_get_ch_sts();
dvbc_status(&demod_sta, /*&demod_i2c,*/ &demod_sts);
if (demod_sts.ch_sts & 0x1) {
ilock = 1;
*status =
FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC;
} else {
ilock = 0;
*status = FE_TIMEDOUT;
}
if (last_lock != ilock) {
PR_DBG("%s.\n",
ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!");
last_lock = ilock;
}
return 0;
}
#endif
struct timer_t {
int enable;
unsigned int start;
unsigned int max;
};
static struct timer_t gtimer[4];
enum ddemod_timer_s {
D_TIMER_DETECT,
D_TIMER_SET,
D_TIMER_DBG1,
D_TIMER_DBG2,
};
int timer_set_max(enum ddemod_timer_s tmid, unsigned int max_val)
{
gtimer[tmid].max = max_val;
return 0;
}
int timer_begain(enum ddemod_timer_s tmid)
{
gtimer[tmid].start = jiffies_to_msecs(jiffies);
gtimer[tmid].enable = 1;
PR_DBG("st %d=%d\n", tmid, (int)gtimer[tmid].start);
return 0;
}
int timer_disable(enum ddemod_timer_s tmid)
{
gtimer[tmid].enable = 0;
return 0;
}
int timer_is_en(enum ddemod_timer_s tmid)
{
return gtimer[tmid].enable;
}
int timer_not_enough(enum ddemod_timer_s tmid)
{
int ret = 0;
unsigned int time;
if (gtimer[tmid].enable) {
time = jiffies_to_msecs(jiffies);
if ((time - gtimer[tmid].start) < gtimer[tmid].max) {
PR_DBG("now=%d\n", (int)time);
ret = 1;
}
}
return ret;
}
int timer_is_enough(enum ddemod_timer_s tmid)
{
int ret = 0;
unsigned int time;
/*Signal stability takes 200ms */
if (gtimer[tmid].enable) {
time = jiffies_to_msecs(jiffies);
if ((time - gtimer[tmid].start) >= gtimer[tmid].max) {
PR_DBG("now=%d\n", (int)time);
ret = 1;
}
}
return ret;
}
int timer_tuner_not_enough(void)
{
int ret = 0;
unsigned int time;
enum ddemod_timer_s tmid;
tmid = D_TIMER_DETECT;
/*Signal stability takes 200ms */
if (gtimer[tmid].enable) {
time = jiffies_to_msecs(jiffies);
if ((time - gtimer[tmid].start) < 200) {
PR_DBG("nowt=%d\n", (int)time);
ret = 1;
}
}
return ret;
}
unsigned int demod_get_adc_clk(void)
{
return demod_status.adc_freq;
}
static int gxtv_demod_dvbc_read_status_timer
(struct dvb_frontend *fe, enum fe_status *status)
{
struct aml_demod_sts demod_sts;
struct aml_demod_sta demod_sta;
int strenth;
int ilock = 0;
/*check tuner*/
if (!timer_tuner_not_enough()) {
strenth = tuner_get_ch_power2();
/*agc control,fine tune strength*/
if (is_ic_ver(IC_VER_TL1) && (dtvdd_devp->pin_name != NULL) &&
(strncmp(fe->ops.tuner_ops.info.name, "r842", 4)
== 0)) {
strenth += 22;
if (strenth <= -80)
strenth = dvbc_get_power_strength(
qam_read_reg(0x27) & 0x7ff, strenth);
}
if (strenth < -87) {
*status = FE_TIMEDOUT;
return 0;
}
}
/*demod_sts.ch_sts = qam_read_reg(0x6);*/
demod_sts.ch_sts = dvbc_get_ch_sts();
dvbc_status(&demod_sta, /*&demod_i2c,*/ &demod_sts);
if (demod_sts.ch_sts & 0x1) {
ilock = 1;
*status =
FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC;
} else {
ilock = 0;
if (timer_not_enough(D_TIMER_DETECT)) {
*status = 0;
PR_DBG("s=0\n");
} else {
*status = FE_TIMEDOUT;
timer_disable(D_TIMER_DETECT);
}
}
if (last_lock != ilock) {
PR_DBG("%s.\n",
ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!");
last_lock = ilock;
}
return 0;
}
static int demod_dvbc_speed_up(enum fe_status *status)
{
unsigned int cnt, i, sts, check_ok = 0;
struct aml_demod_sts demod_sts;
const int dvbc_count = 5;
int ilock = 0;
if (*status == 0) {
for (cnt = 0; cnt < 10; cnt++) {
demod_sts.ch_sts = dvbc_get_ch_sts();
if (demod_sts.ch_sts & 0x1) {
/*have signal*/
*status =
FE_HAS_LOCK | FE_HAS_SIGNAL |
FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC;
ilock = 1;
check_ok = 1;
} else {
for (i = 0; i < dvbc_count; i++) {
msleep(25);
sts = dvbc_get_status();
if (sts >= 0x3)
break;
}
PR_DBG("[rsj]dvbc_status is 0x%x\n", sts);
if (sts < 0x3) {
*status = FE_TIMEDOUT;
ilock = 0;
check_ok = 1;
timer_disable(D_TIMER_DETECT);
}
}
if (check_ok == 1)
break;
msleep(20);
}
}
if (last_lock != ilock) {
PR_DBG("%s : %s.\n", __func__,
ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!");
last_lock = ilock;
}
return 0;
}
static int gxtv_demod_dvbc_read_ber(struct dvb_frontend *fe, u32 *ber)
{
/*struct aml_fe_dev *dev = afe->dtv_demod;*/
struct aml_demod_sts demod_sts;
/*struct aml_demod_i2c demod_i2c;*/
struct aml_demod_sta demod_sta;
dvbc_status(&demod_sta, /*&demod_i2c,*/ &demod_sts);
*ber = demod_sts.ch_ber;
return 0;
}
static int gxtv_demod_dvbc_read_signal_strength
(struct dvb_frontend *fe, u16 *strength)
{
int tuner_sr;
#if 0
if (fe->ops.tuner_ops.get_strength)
tn_strength = fe->ops.tuner_ops.get_strength(fe);
*strength = 256 - tn_strength;
#else
if (is_ic_ver(IC_VER_TL1) &&
(dtvdd_devp->pin_name != NULL) &&
(strncmp(fe->ops.tuner_ops.info.name, "r842", 4) == 0)) {
tuner_sr = tuner_get_ch_power2();
tuner_sr += 22;
if (tuner_sr <= -80)
tuner_sr = dvbc_get_power_strength(
qam_read_reg(0x27) & 0x7ff, tuner_sr);
if (tuner_sr < -100)
*strength = 0;
else
*strength = tuner_sr + 100;
} else
*strength = tuner_get_ch_power3();
#endif
return 0;
}
static int gxtv_demod_dvbc_read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct aml_demod_sts demod_sts;
/*struct aml_demod_i2c demod_i2c;*/
struct aml_demod_sta demod_sta;
dvbc_status(&demod_sta, /*&demod_i2c,*/ &demod_sts);
*snr = demod_sts.ch_snr / 100;
return 0;
}
static int gxtv_demod_dvbc_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
*ucblocks = 0;
return 0;
}
/*extern int aml_fe_analog_set_frontend(struct dvb_frontend *fe);*/
static int gxtv_demod_dvbc_set_frontend(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct aml_demod_dvbc param; /*mode 0:16, 1:32, 2:64, 3:128, 4:256*/
struct aml_demod_sts demod_sts;
PR_INFO("%s\n", __func__);
/*timer_set_max(D_TIMER_DETECT, 4000);*/
/*timer_begain(D_TIMER_DETECT);*/
memset(&param, 0, sizeof(param));
param.ch_freq = c->frequency / 1000;
param.mode = amdemod_qam(c->modulation);
param.symb_rate = c->symbol_rate / 1000;
store_dvbc_qam_mode(c->modulation, param.symb_rate);
if (!is_ic_ver(IC_VER_TL1)) {
if ((param.mode == 3) && (demod_status.tmp != Adc_mode)) {
Gxtv_Demod_Dvbc_Init(/*dev,*/ Adc_mode);
/*pr_dbg("Gxtv_Demod_Dvbc_Init,Adc_mode\n");*/
} else {
/*Gxtv_Demod_Dvbc_Init(dev,Cry_mode);*/
}
}
if (autoflags == 0) {
/*pr_dbg("QAM_TUNING mode\n");*/
/*flag=0;*/
}
if ((autoflags == 1) && (autoFlagsTrig == 0)
&& (freq_dvbc == param.ch_freq)) {
PR_DBG("now is auto symbrating\n");
return 0;
}
autoFlagsTrig = 0;
last_lock = -1;
PR_DBG("[gxtv_demod_dvbc_set_frontend]PARA\t"
"param.ch_freq is %d||||param.symb_rate is %d,\t"
"param.mode is %d\n",
param.ch_freq, param.symb_rate, param.mode);
tuner_set_params(fe);/*aml_fe_analog_set_frontend(fe);*/
dvbc_set_ch(&demod_status, /*&demod_i2c,*/ &param);
/*0xf33 dvbc mode, 0x10f33 j.83b mode*/
#if 0
if (is_meson_txlx_cpu() || is_meson_gxlx_cpu())
/*qam_write_reg(0x7, 0xf33);*/
dvbc_init_reg_ext();
#endif
if (is_dvbc_ver(IC_DVBC_V3))
dvbc_init_reg_ext();
if (autoflags == 1) {
PR_DBG("QAM_PLAYING mode,start auto sym\n");
dvbc_set_auto_symtrack();
/* flag=1;*/
}
dvbc_status(&demod_status, /*&demod_i2c,*/ &demod_sts);
freq_dvbc = param.ch_freq;
PR_DBG("AML amldemod => frequency=%d,symbol_rate=%d\r\n", c->frequency,
c->symbol_rate);
return 0;
}
static int gxtv_demod_dvbc_get_frontend(struct dvb_frontend *fe)
{
#if 0
/*these content will be writed into eeprom .*/
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u32 qam_mode;
qam_mode = dvbc_get_qam_mode();
c->modulation = qam_mode + 1;
PR_DBG("[mode] is %d\n", c->modulation);
#endif
return 0;
}
static int Gxtv_Demod_Dvbc_Init(/*struct aml_fe_dev *dev, */int mode)
{
struct aml_demod_sys sys;
/*struct aml_demod_i2c i2c;*/
PR_DBG("%s\n", __func__);
memset(&sys, 0, sizeof(sys));
/*memset(&i2c, 0, sizeof(i2c));*/
/*i2c.tuner = dev->drv->id;*/
/*i2c.addr = dev->i2c_addr;*/
/* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/
demod_status.dvb_mode = Gxtv_Dvbc;
if (mode == Adc_mode) {
sys.adc_clk = Adc_Clk_25M;
sys.demod_clk = Demod_Clk_200M;
demod_status.tmp = Adc_mode;
} else {
sys.adc_clk = Adc_Clk_24M;
sys.demod_clk = Demod_Clk_72M;
demod_status.tmp = Cry_mode;
}
if (is_ic_ver(IC_VER_TL1)) {
sys.adc_clk = Adc_Clk_24M;
sys.demod_clk = Demod_Clk_167M;
demod_status.tmp = Cry_mode;
}
demod_status.ch_if = Si2176_5M_If * 1000;
PR_DBG("[%s]adc_clk is %d,demod_clk is %d\n", __func__, sys.adc_clk,
sys.demod_clk);
autoFlagsTrig = 0;
/*demod_set_sys(&demod_status, &i2c, &sys);*/
demod_set_sys(&demod_status, &sys);
demod_mode_para = AML_DVBC;
return 0;
}
static void gxtv_demod_dvbt_release(struct dvb_frontend *fe)
{
}
static int gxtv_demod_dvbt_read_status
(struct dvb_frontend *fe, enum fe_status *status)
{
/* struct aml_fe *afe = fe->demodulator_priv;*/
/*struct aml_demod_i2c demod_i2c;*/
struct aml_demod_sta demod_sta;
int ilock;
unsigned char s = 0;
s = dvbt_get_status_ops()->get_status(&demod_sta/*, &demod_i2c*/);
if (s == 1) {
ilock = 1;
*status =
FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC;
} else {
if (timer_not_enough(D_TIMER_DETECT)) {
ilock = 0;
*status = 0;
PR_INFO("timer not enough\n");
} else {
ilock = 0;
*status = FE_TIMEDOUT;
timer_disable(D_TIMER_DETECT);
}
}
if (last_lock != ilock) {
PR_INFO("%s.\n",
ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!");
last_lock = ilock;
}
return 0;
}
static int gxtv_demod_dvbt_read_ber(struct dvb_frontend *fe, u32 *ber)
{
/* struct aml_fe *afe = fe->demodulator_priv;*/
/*struct aml_demod_i2c demod_i2c;*/
struct aml_demod_sta demod_sta;
*ber = dvbt_get_status_ops()->get_ber(&demod_sta) & 0xffff;
return 0;
}
static int gxtv_demod_dvbt_read_signal_strength
(struct dvb_frontend *fe, u16 *strength)
{
/*struct aml_fe *afe = fe->demodulator_priv;*/
/*struct aml_fe_dev *dev = afe->dtv_demod;*/
/**strength = 256 - tuner_get_ch_power(fe);*/
*strength = tuner_get_ch_power3();
PR_DBGL("[RSJ]tuner strength is %d dbm\n", *strength);
return 0;
}
static int gxtv_demod_dvbt_read_snr(struct dvb_frontend *fe, u16 *snr)
{
/* struct aml_fe *afe = fe->demodulator_priv;*/
/* struct aml_demod_sts demod_sts;*/
/* struct aml_demod_i2c demod_i2c;*/
struct aml_demod_sta demod_sta;
*snr = dvbt_get_status_ops()->get_snr(&demod_sta/*, &demod_i2c*/);
*snr /= 8;
PR_DBGL("[RSJ]snr is %d dbm\n", *snr);
return 0;
}
static int gxtv_demod_dvbt_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
*ucblocks = 0;
return 0;
}
int convert_bandwidth(unsigned int input)
{
/*int output;*/
enum fe_bandwidth output;
output = 3;
switch (input) {
case 10000000:
output = BANDWIDTH_10_MHZ;
break;
case 8000000:
output = BANDWIDTH_8_MHZ;
break;
case 7000000:
output = BANDWIDTH_7_MHZ;
break;
case 6000000:
output = BANDWIDTH_6_MHZ;
break;
case 5000000:
output = BANDWIDTH_5_MHZ;
break;
case 1712000:
output = BANDWIDTH_1_712_MHZ;
break;
case 0:
output = BANDWIDTH_AUTO;
break;
}
return output;
}
static int gxtv_demod_dvbt_set_frontend(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
/*struct aml_demod_sts demod_sts;*/
struct aml_demod_dvbt param;
/*////////////////////////////////////*/
/* bw == 0 : 8M*/
/* 1 : 7M*/
/* 2 : 6M*/
/* 3 : 5M*/
/* agc_mode == 0: single AGC*/
/* 1: dual AGC*/
/*////////////////////////////////////*/
memset(&param, 0, sizeof(param));
param.ch_freq = c->frequency / 1000;
//param.bw = c->bandwidth_hz;
param.bw = convert_bandwidth(c->bandwidth_hz);
PR_INFO("%s:bw=%d\n", __func__, c->bandwidth_hz);
param.agc_mode = 1;
/*ISDBT or DVBT : 0 is QAM, 1 is DVBT, 2 is ISDBT,*/
/* 3 is DTMB, 4 is ATSC */
param.dat0 = 1;
last_lock = -1;
tuner_set_params(fe);/*aml_fe_analog_set_frontend(fe);*/
dvbt_set_ch(&demod_status, /*&demod_i2c,*/ &param);
/*pr_dbg("AML amldemod => frequency=%d,symbol_rate=%d\r\n",*/
/* p->frequency,p->u.qam.symbol_rate);*/
return 0;
}
static int gxtv_demod_dvbt_get_frontend(struct dvb_frontend *fe)
{ /*these content will be writed into eeprom .*/
return 0;
}
/*int Gxtv_Demod_Dvbt_Init(struct aml_fe_dev *dev)*/
int Gxtv_Demod_Dvbt_Init(void)
{
struct aml_demod_sys sys;
PR_DBG("AML Demod DVB-T init\r\n");
memset(&sys, 0, sizeof(sys));
memset(&demod_status, 0, sizeof(demod_status));
/* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/
demod_status.dvb_mode = Gxtv_Dvbt_Isdbt;
sys.adc_clk = Adc_Clk_24M;
sys.demod_clk = Demod_Clk_60M;
demod_status.ch_if = Si2176_5M_If * 1000;
demod_set_sys(&demod_status, &sys);
demod_mode_para = AML_DVBT;
return 0;
}
static void gxtv_demod_atsc_release(struct dvb_frontend *fe)
{
}
static int gxtv_demod_atsc_get_frontend_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}
static int gxtv_demod_txlx_get_frontend_algo(struct dvb_frontend *fe)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
int ret = DVBFE_ALGO_HW;
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
/*dvbc*/
ret = DVBFE_ALGO_HW;
break;
case AM_FE_OFDM_N:
case AM_FE_ISDBT_N:
/*dvbt*/
ret = DVBFE_ALGO_HW;
break;
case AM_FE_ATSC_N:
ret = DVBFE_ALGO_HW;
break;
case AM_FE_DTMB_N:
ret = DVBFE_ALGO_HW;
break;
case AM_FE_UNKNOWN_N:
default:
break;
}
return ret;
}
unsigned int ats_thread_flg;
static int gxtv_demod_atsc_read_status
(struct dvb_frontend *fe, enum fe_status *status)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct aml_demod_sts demod_sts;
/*struct aml_demod_i2c demod_i2c;*/
struct aml_demod_sta demod_sta;
int ilock;
/*struct dvb_frontend *dvbfe;*/
unsigned char s = 0;
int strength = 0;
/*debug only*/
static enum fe_status dbg_lst_status; /* last status */
if (!demod_thread) {
ilock = 1;
*status =
FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC;
return 0;
}
if (!get_dtvpll_init_flag())
return 0;
if ((c->modulation <= QAM_AUTO) && (c->modulation != QPSK)
&& (atsc_flag == QAM_AUTO)) {
s = amdemod_dvbc_stat_islock();
dvbc_status(&demod_sta,/* &demod_i2c, */&demod_sts);
} else if ((c->modulation > QAM_AUTO)
&& (atsc_flag == VSB_8)) {
/*atsc_thread();*/
s = amdemod_atsc_stat_islock();
if (!is_ic_ver(IC_VER_TL1)) {
if ((s == 0) && (last_lock == 1)
&& (atsc_read_reg(0x0980) >= 0x76)) {
s = 1;
PR_ATSC("[rsj] unlock,but fsm >= 0x76\n");
}
}
}
#if 0 /*debug only move to end*/
dvbfe = get_si2177_tuner();
if (dvbfe != NULL)
if (dvbfe->ops.tuner_ops.get_strength) {
strength =
dvbfe->ops.tuner_ops.get_strength(dvbfe);
}
/*strength -= 100;*/
pr_dbg("[rsj_test]freq[%d] strength[%d]\n", freq_p, strength);
#endif
if (s == 1) {
ilock = 1;
*status =
FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC;
} else {
ilock = 0;
if (is_ic_ver(IC_VER_TL1)) {
if (timer_not_enough(D_TIMER_DETECT)) {
*status = 0;
PR_DBG("s=0\n");
} else {
*status = FE_TIMEDOUT;
timer_disable(D_TIMER_DETECT);
}
} else {
*status = FE_TIMEDOUT;
}
#if 0
if (ats_thread_flg)
*status = FE_TIMEDOUT;
else
*status = 0;
#endif
}
#if 1 /*debug only*/
if (last_lock != ilock) {
PR_INFO("%s.\n",
ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!");
last_lock = ilock;
}
#endif
/*debug only*/
if (aml_demod_debug & DBG_ATSC) {
if ((dbg_lst_status != s) || (last_lock != ilock)) {
/* check tuner */
strength = tuner_get_ch_power2();
PR_ATSC("s=%d(1 is lock),lock=%d\n", s, ilock);
PR_ATSC("[rsj_test]freq[%d] strength[%d]\n",
freq_p, strength);
/*update */
dbg_lst_status = s;
last_lock = ilock;
}
/*aml_dbgatscl(".");*/
}
return 0;
}
static int gxtv_demod_atsc_read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
if (!get_dtvpll_init_flag())
return 0;
if ((c->modulation > QAM_AUTO)
&& (atsc_flag == VSB_8))
*ber = atsc_read_reg(0x980)&0xffff;
else if (((c->modulation == QAM_256)
|| (c->modulation == QAM_64))
&& (atsc_flag == QAM_AUTO))
*ber = dvbc_get_status();
return 0;
}
static int gxtv_demod_atsc_read_signal_strength
(struct dvb_frontend *fe, u16 *strength)
{
int strenth;
strenth = tuner_get_ch_power(fe);
/* struct aml_fe *afe = fe->demodulator_priv;*/
/*struct aml_fe_dev *dev = afe->dtv_demod; */
if (is_ic_ver(IC_VER_TL1) && (dtvdd_devp->pin_name != NULL) &&
(strncmp(fe->ops.tuner_ops.info.name, "r842", 4) == 0)) {
if ((fe->dtv_property_cache.modulation <= QAM_AUTO) &&
(fe->dtv_property_cache.modulation != QPSK))
strenth += 18;
else {
strenth += 15;
if (strenth <= -80)
strenth = atsc_get_power_strength(
atsc_read_reg_v4(0x44) & 0xfff,
strenth);
}
if (strenth < -100)
*strength = 0;
else
*strength = strenth + 100;
} else
*strength = tuner_get_ch_power3();
if (*strength > 100)
*strength = 100;
return 0;
}
static int gxtv_demod_atsc_read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct aml_demod_sts demod_sts;
/*struct aml_demod_i2c demod_i2c;*/
struct aml_demod_sta demod_sta;
if ((c->modulation <= QAM_AUTO)
&& (c->modulation != QPSK)
&& (atsc_flag == QAM_AUTO)) {
dvbc_status(&demod_sta, /*&demod_i2c, */&demod_sts);
*snr = demod_sts.ch_snr / 100;
} else if ((c->modulation > QAM_AUTO)
&& (atsc_flag == VSB_8))
*snr = atsc_read_snr();
return 0;
}
static int gxtv_demod_atsc_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
if (!demod_thread)
return 0;
if ((c->modulation > QAM_AUTO)
&& (atsc_flag == VSB_8))
atsc_thread();
*ucblocks = 0;
return 0;
}
static int gxtv_demod_atsc_set_frontend(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct aml_demod_atsc param_atsc;
struct aml_demod_dvbc param_j83b;
int temp_freq = 0;
union ATSC_DEMOD_REG_0X6A_BITS Val_0x6a;
union ATSC_CNTR_REG_0X20_BITS Val_0x20;
int nco_rate;
/*[0]: specturm inverse(1),normal(0); [1]:if_frequency*/
unsigned int tuner_freq[2] = {0};
memset(&param_atsc, 0, sizeof(param_atsc));
memset(&param_j83b, 0, sizeof(param_j83b));
if (!demod_thread)
return 0;
freq_p = c->frequency / 1000;
PR_INFO("c->modulation is %d,freq_p is %d, atsc_flag is %d\n",
c->modulation, freq_p, atsc_flag);
last_lock = -1;
atsc_mode = c->modulation;
/* param.mode = amdemod_qam(p->u.vsb.modulation);*/
tuner_set_params(fe);/*aml_fe_analog_set_frontend(fe);*/
if ((c->modulation <= QAM_AUTO) && (c->modulation != QPSK)) {
if (atsc_flag != QAM_AUTO)
atsc_flag = QAM_AUTO;
/* demod_set_demod_reg(0x502, TXLX_ADC_REG6);*/
//sys_clk=167M
dd_tvafe_hiu_reg_write(D_HHI_DEMOD_CLK_CNTL, 0x502);
demod_set_mode_ts(Gxtv_Dvbc);
param_j83b.ch_freq = c->frequency / 1000;
param_j83b.mode = amdemod_qam(c->modulation);
if (c->modulation == QAM_64)
param_j83b.symb_rate = 5057;
else if (c->modulation == QAM_256)
param_j83b.symb_rate = 5361;
else
param_j83b.symb_rate = 5361;
if (is_ic_ver(IC_VER_TL1)) {
//for timeshift mosaic
demod_status.clk_freq = Demod_Clk_167M;
nco_rate = (demod_status.adc_freq * 256)
/ demod_status.clk_freq + 2;
front_write_reg_v4(0x20,
((front_read_reg_v4(0x20) & ~0xff)
| (nco_rate & 0xff)));
front_write_reg_v4(0x2f, 0x5);//for timeshift mosaic
}
dvbc_set_ch(&demod_status, /*&demod_i2c, */&param_j83b);
if (is_ic_ver(IC_VER_TL1)) {
qam_write_reg(0x7, 0x10f33);
set_j83b_filter_reg_v4();
qam_write_reg(0x12, 0x50e1000);
qam_write_reg(0x30, 0x41f2f69);
}
} else if (c->modulation > QAM_AUTO) {
if (is_ic_ver(IC_VER_TL1)) {
Val_0x6a.bits = atsc_read_reg_v4(ATSC_DEMOD_REG_0X6A);
Val_0x6a.b.peak_thd = 0x6;//Let CCFO Quality over 6
atsc_write_reg_v4(ATSC_DEMOD_REG_0X6A, Val_0x6a.bits);
atsc_write_reg_v4(ATSC_EQ_REG_0XA5, 0x8c);
if (fe->ops.tuner_ops.get_if_frequency)
fe->ops.tuner_ops.
get_if_frequency(fe, tuner_freq);
/*bit 2: invert specturm, for r842 tuner AGC control*/
if (tuner_freq[0] == 1)
atsc_write_reg_v4(ATSC_DEMOD_REG_0X56, 0x4);
else
atsc_write_reg_v4(ATSC_DEMOD_REG_0X56, 0x0);
if (demod_status.adc_freq == Adc_Clk_24M) {
atsc_write_reg_v4(ATSC_DEMOD_REG_0X54,
0x1aaaaa);
atsc_write_reg_v4(ATSC_DEMOD_REG_0X55,
0x3ae28d);
atsc_write_reg_v4(ATSC_DEMOD_REG_0X6E,
0x16e3600);
}
atsc_write_reg_v4(0x12, 0x18);//for timeshift mosaic
Val_0x20.bits = atsc_read_reg_v4(ATSC_CNTR_REG_0X20);
Val_0x20.b.cpu_rst = 1;
atsc_write_reg_v4(ATSC_CNTR_REG_0X20, Val_0x20.bits);
Val_0x20.b.cpu_rst = 0;
atsc_write_reg_v4(ATSC_CNTR_REG_0X20, Val_0x20.bits);
usleep_range(5000, 5001);
} else {
if (atsc_flag != VSB_8)
atsc_flag = VSB_8;
/*demod_set_demod_reg(0x507, TXLX_ADC_REG6);*/
dd_tvafe_hiu_reg_write(D_HHI_DEMOD_CLK_CNTL, 0x507);
demod_set_mode_ts(Gxtv_Atsc);
param_atsc.ch_freq = c->frequency / 1000;
param_atsc.mode = c->modulation;
atsc_set_ch(&demod_status, /*&demod_i2c,*/ &param_atsc);
}
}
if ((auto_search_std == 1) && ((c->modulation <= QAM_AUTO)
&& (c->modulation != QPSK))) {
unsigned char s = 0;
msleep(std_lock_timeout);
s = amdemod_dvbc_stat_islock();
if (s == 1) {
PR_DBG("atsc std mode is %d locked\n", atsc_mode);
return 0;
}
if ((c->frequency == 79000000) || (c->frequency == 85000000)) {
temp_freq = (c->frequency + 2000000) / 1000;
param_j83b.ch_freq = temp_freq;
PR_DBG("irc fre:%d\n", param_j83b.ch_freq);
c->frequency = param_j83b.ch_freq * 1000;
tuner_set_params(fe);
demod_set_mode_ts(Gxtv_Dvbc);
param_j83b.mode = amdemod_qam(c->modulation);
if (c->modulation == QAM_64)
param_j83b.symb_rate = 5057;
else if (c->modulation == QAM_256)
param_j83b.symb_rate = 5361;
else
param_j83b.symb_rate = 5361;
dvbc_set_ch(&demod_status, /*&demod_i2c,*/
&param_j83b);
msleep(std_lock_timeout);
s = amdemod_dvbc_stat_islock();
if (s == 1) {
PR_DBG("irc mode is %d locked\n", atsc_mode);
} else {
temp_freq = (c->frequency - 1250000) / 1000;
param_j83b.ch_freq = temp_freq;
PR_DBG("hrc fre:%d\n", param_j83b.ch_freq);
c->frequency = param_j83b.ch_freq * 1000;
tuner_set_params(fe);
demod_set_mode_ts(Gxtv_Dvbc);
param_j83b.mode = amdemod_qam(c->modulation);
if (c->modulation == QAM_64)
param_j83b.symb_rate = 5057;
else if (c->modulation == QAM_256)
param_j83b.symb_rate = 5361;
else
param_j83b.symb_rate = 5361;
dvbc_set_ch(&demod_status, /*&demod_i2c,*/
&param_j83b);
}
} else {
param_j83b.ch_freq = (c->frequency - 1250000) / 1000;
PR_DBG("hrc fre:%d\n", param_j83b.ch_freq);
c->frequency = param_j83b.ch_freq * 1000;
demod_set_mode_ts(Gxtv_Dvbc);
param_j83b.mode = amdemod_qam(c->modulation);
if (c->modulation == QAM_64)
param_j83b.symb_rate = 5057;
else if (c->modulation == QAM_256)
param_j83b.symb_rate = 5361;
else
param_j83b.symb_rate = 5361;
dvbc_set_ch(&demod_status, /*&demod_i2c,*/
&param_j83b);
}
}
PR_DBG("atsc_mode is %d\n", atsc_mode);
/*pr_dbg("AML amldemod => frequency=%d,symbol_rate=%d\r\n",*/
/* p->frequency,p->u.qam.symbol_rate);*/
return 0;
}
static int gxtv_demod_atsc_get_frontend(struct dvb_frontend *fe)
{ /*these content will be writed into eeprom .*/
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
PR_DBG("c->frequency is %d\n", c->frequency);
return 0;
}
void atsc_detect_first(struct dvb_frontend *fe, enum fe_status *status)
{
unsigned int ucblocks;
unsigned int atsc_status;
enum fe_status s;
int strenth;
int cnt;
int check_ok;
/*tuner strength*/
if (dvb_tuner_delay > 9)
msleep(dvb_tuner_delay);
strenth = tuner_get_ch_power(fe);
/*agc control,fine tune strength*/
if (is_ic_ver(IC_VER_TL1) && (dtvdd_devp->pin_name != NULL) &&
(strncmp(fe->ops.tuner_ops.info.name, "r842", 4) == 0)) {
strenth += 15;
if (strenth <= -80)
strenth = atsc_get_power_strength(
atsc_read_reg_v4(0x44) & 0xfff, strenth);
}
if (strenth < THRD_TUNER_STRENTH_ATSC) {
*status = FE_TIMEDOUT;
PR_ATSC("tuner:no signal!\n");
return;
}
#define CNT_FIRST_ATSC (2)
check_ok = 0;
for (cnt = 0; cnt < CNT_FIRST_ATSC; cnt++) {
if (!is_ic_ver(IC_VER_TL1))
gxtv_demod_atsc_read_ucblocks(fe, &ucblocks);
gxtv_demod_atsc_read_status(fe, &s);
if (is_ic_ver(IC_VER_TL1)) {
*status = s;
break;
}
// *status = s;
if (s != 0x1f) {
gxtv_demod_atsc_read_ber(fe, &atsc_status);
if ((atsc_status < 0x60)) {
*status = FE_TIMEDOUT;
check_ok = 1;
}
} else {
check_ok = 1;
*status = s;
}
if (check_ok)
break;
}
PR_ATSC("%s,detect=0x%x,cnt=%d\n", __func__,
(unsigned int)*status, cnt);
}
static int dvb_j83b_count = 5;
module_param(dvb_j83b_count, int, 0644);
MODULE_PARM_DESC(dvb_atsc_count, "dvb_j83b_count");
/*come from j83b_speedup_func*/
static int atsc_j83b_detect_first(struct dvb_frontend *fe, enum fe_status *s)
{
int j83b_status, i;
/*struct dvb_frontend_private *fepriv = fe->frontend_priv;*/
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int strenth;
enum fe_status cs;
int cnt;
int check_ok;
j83b_status = 0;
/*tuner:*/
if (dvb_tuner_delay > 9)
msleep(dvb_tuner_delay);
strenth = tuner_get_ch_power(fe);
/*agc control,fine tune strength*/
if (is_ic_ver(IC_VER_TL1) && (dtvdd_devp->pin_name != NULL) &&
(strncmp(fe->ops.tuner_ops.info.name, "r842", 4) == 0))
strenth += 18;
if (strenth < THRD_TUNER_STRENTH_J83) {
*s = FE_TIMEDOUT;
PR_ATSC("tuner:no signal!j83\n");
return 0;
}
check_ok = 0;
/*first check signal max time*/
#define CNT_FIRST (10)
for (cnt = 0; cnt < CNT_FIRST; cnt++) {
gxtv_demod_atsc_read_status(fe, &cs);
if (cs != 0x1f) {
/*msleep(200);*/
PR_DBG("[j.83b] 1\n");
for (i = 0; i < dvb_j83b_count; i++) {
msleep(25);
gxtv_demod_atsc_read_ber(fe, &j83b_status);
/*J.83 status >=0x38,has signal*/
if (j83b_status >= 0x3)
break;
}
PR_DBG("[rsj]j.83b_status is %x,modulation is %d\n",
j83b_status,
c->modulation);
if (j83b_status < 0x3) {
*s = FE_TIMEDOUT;
check_ok = 1;
}
} else {
/*have signal*/
*s = cs;
check_ok = 1;
}
if (check_ok)
break;
msleep(50);
}
if (!check_ok)
*s = FE_TIMEDOUT;
PR_ATSC("j83 first:cnt:%d,sgn:0x%x\n", cnt, *s);
return 0;
}
static int atsc_j83b_polling(struct dvb_frontend *fe, enum fe_status *s)
{
int j83b_status, i;
/*struct dvb_frontend_private *fepriv = fe->frontend_priv;*/
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int strenth;
PR_DBG("+7+");
j83b_status = 0;
strenth = tuner_get_ch_power(fe);
if (strenth < THRD_TUNER_STRENTH_J83) {
*s = FE_TIMEDOUT;
PR_DBGL("tuner:no signal!j83\n");
return 0;
}
gxtv_demod_atsc_read_status(fe, s);
if (*s != 0x1f) {
/*msleep(200);*/
PR_DBG("[j.83b] 1\n");
for (i = 0; i < dvb_j83b_count; i++) {
msleep(25);
gxtv_demod_atsc_read_ber(fe, &j83b_status);
/*J.83 status >=0x38,has signal*/
if (j83b_status >= 0x3)
break;
}
PR_DBG("[rsj]j.83b_status is %x,modulation is %d\n",
j83b_status,
c->modulation);
if (j83b_status < 0x3)
*s = FE_TIMEDOUT;
}
return 0;
}
void atsc_polling(struct dvb_frontend *fe, enum fe_status *status)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
if (!demod_thread)
return;
if (c->modulation == QPSK) {
PR_DBG("mode is qpsk, return;\n");
/*return;*/
} else if (c->modulation <= QAM_AUTO) {
atsc_j83b_polling(fe, status);
} else {
atsc_thread();
gxtv_demod_atsc_read_status(fe, status);
}
}
static int gxtv_demod_atsc_tune(struct dvb_frontend *fe, bool re_tune,
unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
{
/*
* It is safe to discard "params" here, as the DVB core will sync
* fe->dtv_property_cache with fepriv->parameters_in, where the
* DVBv3 params are stored. The only practical usage for it indicate
* that re-tuning is needed, e. g. (fepriv->state & FESTATE_RETUNE) is
* true.
*/
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
/*int ret = 0;*/
PR_ATSC("%s:\n", __func__);
*delay = HZ/2;
if (re_tune) {
dtvdd_devp->en_detect = 1; /*fist set*/
/*c->delivery_system = aml_demod_delivery_sys;*/
/*PR_ATSC("delivery_system=%d\n", aml_demod_delivery_sys);*/
gxtv_demod_atsc_set_frontend(fe);
if (is_ic_ver(IC_VER_TL1))
timer_begain(D_TIMER_DETECT);
if (c->modulation == QPSK) {
PR_ATSC("modulation is QPSK do nothing!");
} else if (c->modulation <= QAM_AUTO) {
PR_ATSC("j83\n");
atsc_j83b_detect_first(fe, status);
} else if (c->modulation > QAM_AUTO) {
atsc_detect_first(fe, status);
}
return 0;
}
#if 1
if (!dtvdd_devp->en_detect) {
PR_DBGL("tune:not enable\n");
return 0;
}
#endif
if (is_ic_ver(IC_VER_TL1)) {
if (c->modulation > QAM_AUTO)
atsc_detect_first(fe, status);
else if (c->modulation <= QAM_AUTO &&
(c->modulation != QPSK))
atsc_j83b_detect_first(fe, status);
} else {
atsc_polling(fe, status);
}
return 0;
}
static int gxtv_demod_dvbt_tune(struct dvb_frontend *fe, bool re_tune,
unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
{
/*
* It is safe to discard "params" here, as the DVB core will sync
* fe->dtv_property_cache with fepriv->parameters_in, where the
* DVBv3 params are stored. The only practical usage for it indicate
* that re-tuning is needed, e. g. (fepriv->state & FESTATE_RETUNE) is
* true.
*/
*delay = HZ/2;
/*PR_ATSC("%s:\n", __func__);*/
#if 1
if (re_tune) {
timer_begain(D_TIMER_DETECT);
PR_INFO("%s:\n", __func__);
dtvdd_devp->en_detect = 1; /*fist set*/
gxtv_demod_dvbt_set_frontend(fe);
gxtv_demod_dvbt_read_status(fe, status);
return 0;
}
#endif
if (!dtvdd_devp->en_detect) {
PR_DBGL("tune:not enable\n");
return 0;
}
/*polling*/
gxtv_demod_dvbt_read_status(fe, status);
if (*status & FE_HAS_LOCK) {
timer_disable(D_TIMER_SET);
} else {
if (!timer_is_en(D_TIMER_SET))
timer_begain(D_TIMER_SET);
}
if (timer_is_enough(D_TIMER_SET)) {
gxtv_demod_dvbt_set_frontend(fe);
timer_disable(D_TIMER_SET);
}
return 0;
}
int Gxtv_Demod_Atsc_Init(void/*struct aml_fe_dev *dev*/)
{
struct aml_demod_sys sys;
/*struct aml_demod_i2c i2c;*/
PR_DBG("%s\n", __func__);
memset(&sys, 0, sizeof(sys));
/*memset(&i2c, 0, sizeof(i2c));*/
memset(&demod_status, 0, sizeof(demod_status));
/* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/
demod_status.dvb_mode = Gxtv_Atsc;
sys.adc_clk = Adc_Clk_24M; /*Adc_Clk_26M;*/
if (is_ic_ver(IC_VER_TL1))
sys.demod_clk = Demod_Clk_250M;
else
sys.demod_clk = Demod_Clk_225M;
demod_status.ch_if = 5000;
demod_status.tmp = Adc_mode;
/*demod_set_sys(&demod_status, &i2c, &sys);*/
demod_set_sys(&demod_status, &sys);
demod_mode_para = AML_ATSC;
atsc_flag = VSB_8;
return 0;
}
static void gxtv_demod_dtmb_release(struct dvb_frontend *fe)
{
}
static int gxtv_demod_dtmb_read_status
(struct dvb_frontend *fe, enum fe_status *status)
{
struct poll_machie_s *pollm = &dtvdd_devp->poll_machie;
*status = pollm->last_s;
return 0;
}
void dtmb_save_status(unsigned int s)
{
struct poll_machie_s *pollm = &dtvdd_devp->poll_machie;
if (s) {
pollm->last_s =
FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC;
} else {
pollm->last_s = FE_TIMEDOUT;
}
}
void dtmb_poll_start(void)
{
struct poll_machie_s *pollm = &dtvdd_devp->poll_machie;
pollm->last_s = 0;
pollm->flg_restart = 1;
/*pr_dbg("dtmb_poll_start!\n");*/
PR_DTMB("dtmb_poll_start2\n");
}
void dtmb_poll_stop(void)
{
struct poll_machie_s *pollm = &dtvdd_devp->poll_machie;
pollm->flg_stop = 1;
}
void dtmb_set_delay(unsigned int delay)
{
struct poll_machie_s *pollm = &dtvdd_devp->poll_machie;
pollm->delayms = delay;
pollm->flg_updelay = 1;
}
unsigned int dtmb_is_update_delay(void)
{
struct poll_machie_s *pollm = &dtvdd_devp->poll_machie;
return pollm->flg_updelay;
}
unsigned int dtmb_get_delay_clear(void)
{
struct poll_machie_s *pollm = &dtvdd_devp->poll_machie;
pollm->flg_updelay = 0;
return pollm->delayms;
}
void dtmb_poll_clear(void)
{
struct poll_machie_s *pollm = &dtvdd_devp->poll_machie;
memset(pollm, 0, sizeof(struct poll_machie_s));
}
#define DTMBM_NO_SIGNEL_CHECK 0x01
#define DTMBM_HV_SIGNEL_CHECK 0x02
#define DTMBM_BCH_OVER_CHEK 0x04
#define DTMBM_CHEK_NO (DTMBM_NO_SIGNEL_CHECK)
#define DTMBM_CHEK_HV (DTMBM_HV_SIGNEL_CHECK | DTMBM_BCH_OVER_CHEK)
#define DTMBM_WORK (DTMBM_NO_SIGNEL_CHECK | DTMBM_HV_SIGNEL_CHECK\
| DTMBM_BCH_OVER_CHEK)
#define DTMBM_POLL_CNT_NO_SIGNAL (10)
#define DTMBM_POLL_CNT_WAIT_LOCK (3) /*from 30 to 3 */
#define DTMBM_POLL_DELAY_NO_SIGNAL (120)
#define DTMBM_POLL_DELAY_HAVE_SIGNAL (100)
/*dtmb_poll_v3 is same as dtmb_check_status_txl*/
void dtmb_poll_v3(void)
{
struct poll_machie_s *pollm = &dtvdd_devp->poll_machie;
unsigned int bch_tmp;
unsigned int s;
if (!pollm->state) {
/* idle */
/* idle -> start check */
if (!pollm->flg_restart) {
PR_DBG("x");
return;
}
} else {
if (pollm->flg_stop) {
PR_DBG("dtmb poll stop !\n");
dtmb_poll_clear();
dtmb_set_delay(3*HZ);
return;
}
}
/* restart: clear */
if (pollm->flg_restart) {
PR_DBG("dtmb poll restart!\n");
dtmb_poll_clear();
}
PR_DBG("-");
s = check_dtmb_fec_lock();
/* bch exceed the threshold: wait lock*/
if (pollm->state & DTMBM_BCH_OVER_CHEK) {
if (pollm->crrcnt < DTMBM_POLL_CNT_WAIT_LOCK) {
pollm->crrcnt++;
if (s) {
PR_DBG("after reset get lock again!cnt=%d\n",
pollm->crrcnt);
dtmb_constell_check();
pollm->state = DTMBM_HV_SIGNEL_CHECK;
pollm->crrcnt = 0;
pollm->bch = dtmb_reg_r_bch();
dtmb_save_status(s);
}
} else {
PR_DBG("can't lock after reset!\n");
pollm->state = DTMBM_NO_SIGNEL_CHECK;
pollm->crrcnt = 0;
/* to no signal*/
dtmb_save_status(s);
}
return;
}
if (s) {
/*have signal*/
if (!pollm->state) {
pollm->state = DTMBM_CHEK_NO;
PR_DBG("from idle to have signal wait 1\n");
return;
}
if (pollm->state & DTMBM_CHEK_NO) {
/*no to have*/
PR_DBG("poll machie: from no signal to have signal\n");
pollm->bch = dtmb_reg_r_bch();
pollm->state = DTMBM_HV_SIGNEL_CHECK;
dtmb_set_delay(DTMBM_POLL_DELAY_HAVE_SIGNAL);
return;
}
bch_tmp = dtmb_reg_r_bch();
if (bch_tmp > (pollm->bch + 50)) {
pollm->state = DTMBM_BCH_OVER_CHEK;
PR_DBG("bch add ,need reset,wait not to reset\n");
dtmb_reset();
pollm->crrcnt = 0;
dtmb_set_delay(DTMBM_POLL_DELAY_HAVE_SIGNAL);
} else {
pollm->bch = bch_tmp;
pollm->state = DTMBM_HV_SIGNEL_CHECK;
dtmb_save_status(s);
/*have signale to have signal*/
dtmb_set_delay(300);
}
return;
}
/*no signal */
if (!pollm->state) {
/* idle -> no signal */
PR_DBG("poll machie: from idle to no signal\n");
pollm->crrcnt = 0;
pollm->state = DTMBM_NO_SIGNEL_CHECK;
} else if (pollm->state & DTMBM_CHEK_HV) {
/*have signal -> no signal*/
PR_DBG("poll machie: from have signal to no signal\n");
pollm->crrcnt = 0;
pollm->state = DTMBM_NO_SIGNEL_CHECK;
dtmb_save_status(s);
}
/*no siganel check process */
if (pollm->crrcnt < DTMBM_POLL_CNT_NO_SIGNAL) {
dtmb_no_signal_check_v3();
pollm->crrcnt++;
dtmb_set_delay(DTMBM_POLL_DELAY_NO_SIGNAL);
} else {
dtmb_no_signal_check_finishi_v3();
pollm->crrcnt = 0;
dtmb_save_status(s);
/*no signal to no signal*/
dtmb_set_delay(300);
}
}
void dtmb_poll_start_tune(unsigned int state)
{
struct poll_machie_s *pollm = &dtvdd_devp->poll_machie;
dtmb_poll_clear();
pollm->state = state;
if (state & DTMBM_NO_SIGNEL_CHECK)
dtmb_save_status(0);
else
dtmb_save_status(1);
PR_DTMB("dtmb_poll_start tune to %d\n", state);
}
/*come from gxtv_demod_dtmb_read_status, have ms_delay*/
int dtmb_poll_v2(struct dvb_frontend *fe, enum fe_status *status)
{
int ilock;
unsigned char s = 0;
s = dtmb_check_status_gxtv(fe);
if (s == 1) {
ilock = 1;
*status =
FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC;
} else {
ilock = 0;
*status = FE_TIMEDOUT;
}
if (last_lock != ilock) {
PR_INFO("%s.\n",
ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!");
last_lock = ilock;
}
return 0;
}
/*this is ori gxtv_demod_dtmb_read_status*/
static int gxtv_demod_dtmb_read_status_old
(struct dvb_frontend *fe, enum fe_status *status)
{
int ilock;
unsigned char s = 0;
if (is_dtmb_ver(IC_DTMB_V2)) {
s = dtmb_check_status_gxtv(fe);
} else if (is_dtmb_ver(IC_DTMB_V3)) {
if (!is_ic_ver(IC_VER_TL1))
s = dtmb_check_status_txl(fe);
} else {
PR_ERR("%s:not support %d!\n", __func__, get_dtmb_ver());
return -1;
}
s = amdemod_dtmb_stat_islock();
if (s == 1) {
ilock = 1;
*status =
FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC;
} else {
ilock = 0;
*status = FE_TIMEDOUT;
}
if (last_lock != ilock) {
PR_INFO("%s.\n",
ilock ? "!! >> LOCK << !!" : "!! >> UNLOCK << !!");
last_lock = ilock;
}
return 0;
}
static int gxtv_demod_dtmb_read_ber(struct dvb_frontend *fe, u32 *ber)
{
*ber = 0;
return 0;
}
static int gxtv_demod_dtmb_read_signal_strength
(struct dvb_frontend *fe, u16 *strength)
{
int tuner_sr;
if (is_ic_ver(IC_VER_TL1) &&
(dtvdd_devp->pin_name != NULL) &&
(strncmp(fe->ops.tuner_ops.info.name, "r842", 4) == 0)) {
tuner_sr = tuner_get_ch_power2();
tuner_sr += 16;
if (tuner_sr < -100)
*strength = 0;
else
*strength = tuner_sr + 100;
} else
*strength = tuner_get_ch_power3();
return 0;
}
static int gxtv_demod_dtmb_read_snr(struct dvb_frontend *fe, u16 *snr)
{
int tmp, snr_avg;
tmp = snr_avg = 0;
/* tmp = dtmb_read_reg(DTMB_TOP_FEC_LOCK_SNR);*/
tmp = dtmb_reg_r_che_snr();
*snr = convert_snr(tmp);
return 0;
}
static int gxtv_demod_dtmb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
*ucblocks = 0;
return 0;
}
static int gxtv_demod_dtmb_set_frontend(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct aml_demod_dtmb param;
int times;
times = 2;
PR_DBG("gxtv_demod_dtmb_set_frontend,freq is %d\n", c->frequency);
memset(&param, 0, sizeof(param));
param.ch_freq = c->frequency / 1000;
last_lock = -1;
/* demod_power_switch(PWR_OFF); */
tuner_set_params(fe); /*aml_fe_analog_set_frontend(fe);*/
msleep(100);
/* demod_power_switch(PWR_ON); */
dtmb_set_ch(&demod_status, /*&demod_i2c,*/ &param);
return 0;
}
static int gxtv_demod_dtmb_get_frontend(struct dvb_frontend *fe)
{ /*these content will be writed into eeprom .*/
return 0;
}
/*int Gxtv_Demod_Dtmb_Init(struct aml_fe_dev *dev)*/
int Gxtv_Demod_Dtmb_Init(struct amldtvdemod_device_s *dev)
{
struct aml_demod_sys sys;
/*struct aml_demod_i2c i2c;*/
PR_DBG("AML Demod DTMB init\r\n");
memset(&sys, 0, sizeof(sys));
/*memset(&i2c, 0, sizeof(i2c));*/
memset(&demod_status, 0, sizeof(demod_status));
/* 0 -DVBC, 1-DVBT, ISDBT, 2-ATSC*/
demod_status.dvb_mode = Gxtv_Dtmb;
if (is_dtmb_ver(IC_DTMB_V2)) {
sys.adc_clk = Adc_Clk_25M; /*Adc_Clk_26M;*/
sys.demod_clk = Demod_Clk_200M;
} else if (is_dtmb_ver(IC_DTMB_V3)) {
if (is_ic_ver(IC_VER_TXL)) {
sys.adc_clk = Adc_Clk_25M;
sys.demod_clk = Demod_Clk_225M;
} else if (is_ic_ver(IC_VER_TL1)) {
sys.adc_clk = Adc_Clk_24M;
sys.demod_clk = Demod_Clk_250M;
} else {
sys.adc_clk = Adc_Clk_24M;
sys.demod_clk = Demod_Clk_225M;
}
} else {
PR_ERR("%s:not support %d\n", __func__, get_dtmb_ver());
return -1;
}
demod_status.ch_if = Si2176_5M_If;
demod_status.tmp = Adc_mode;
demod_status.spectrum = dev->spectrum;
/*demod_set_sys(&demod_status, &i2c, &sys);*/
demod_set_sys(&demod_status, &sys);
demod_mode_para = AML_DTMB;
return 0;
}
#ifdef DVB_CORE_ORI
unsigned int demod_dvbc_get_fast_search(void)
{
return demod_dvbc_speedup_en;
}
void demod_dvbc_set_fast_search(unsigned int en)
{
if (en)
demod_dvbc_speedup_en = 1;
else
demod_dvbc_speedup_en = 0;
}
void demod_dvbc_fsm_reset(void)
{
//qam_write_reg(0x7, 0xf23);
qam_write_reg(0x7, qam_read_reg(0x7) & ~(1 << 4));
qam_write_reg(0x3a, 0x0);
//qam_write_reg(0x7, 0xf33);
qam_write_reg(0x7, qam_read_reg(0x7) | (1 << 4));
qam_write_reg(0x3a, 0x4);
}
//return val : 0=no signal,1=has signal,2=waiting
unsigned int demod_dvbc_64_256_auto_fast(unsigned int *delay)
{
static unsigned int times, no_sig_cnt;
static unsigned int qam64 = 1;
if (tuner_get_ch_power2() < -87)
return 0;
times++;
PR_DVBC("fast search : times = %d\n", times);
if (times < 6)
*delay = HZ / 8;//125ms
else
*delay = HZ / 2;//500ms
if ((qam_read_reg(0x31) & 0xf) < 3) {
no_sig_cnt++;
if (no_sig_cnt == 2 && times == 2) {//250ms
no_sig_cnt = 0;
times = 0;
*delay = HZ / 4;
qam64 = 1;
return 0;
}
} else if ((qam_read_reg(0x31) & 0xf) == 5) {
no_sig_cnt = 0;
times = 0;
*delay = HZ / 4;
qam64 = 1;
return 1;
}
if (times == 14) {
times = 0;
no_sig_cnt = 0;
*delay = HZ / 4;
qam64 = 1;
return 0;
}
qam64 = !qam64;
PR_DVBC("fast search : qam64 = %d\n", qam64);
if (qam64)
demod_dvbc_set_qam(2);//64qam
else
demod_dvbc_set_qam(4);//256qam
demod_dvbc_fsm_reset();
return 2;
}
//return val : 0=no signal,1=has signal,2=waiting
unsigned int demod_dvbc_fast_search(unsigned int *delay)
{
static unsigned int times, no_sig_cnt;
if (tuner_get_ch_power2() < -87)
return 0;
times++;
PR_DVBC("fast search : times = %d\n", times);
if (times < 3)
*delay = HZ / 8;//125ms
else
*delay = HZ / 2;//500ms
if ((qam_read_reg(0x31) & 0xf) < 3) {
no_sig_cnt++;
if (no_sig_cnt == 2 && times == 2) {//250ms
no_sig_cnt = 0;
times = 0;
*delay = HZ / 4;
return 0;
}
} else if ((qam_read_reg(0x31) & 0xf) == 5) {
no_sig_cnt = 0;
times = 0;
*delay = HZ / 4;
return 1;
}
if (times == 7) {
times = 0;
no_sig_cnt = 0;
*delay = HZ / 4;
return 0;
}
demod_dvbc_fsm_reset();
return 2;
}
static int gxtv_demod_dvbc_tune(struct dvb_frontend *fe, bool re_tune,
unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
{
/*struct dtv_frontend_properties *c = &fe->dtv_property_cache;*/
int ret = 0;
unsigned int sig_flg;
static unsigned int fast_search_finish = 1;
/*unsigned int up_delay;*/
/*unsigned int firstdetet;*/
*delay = HZ / 4;
if (!demod_thread)
return 0;
if (re_tune) {
/*first*/
dtvdd_devp->en_detect = 1;
gxtv_demod_dvbc_set_frontend(fe);
if (demod_dvbc_speedup_en == 1) {
fast_search_finish = 0;
*status = 0;
*delay = HZ / 8;
qam_write_reg(0x65, 0x400c);
qam_write_reg(0x60, 0x10466000);
qam_write_reg(0xac, (qam_read_reg(0xac) & (~0xff00))
| 0x800);
qam_write_reg(0xae, (qam_read_reg(0xae)
& (~0xff000000)) | 0x8000000);
if (fe->dtv_property_cache.modulation == QAM_AUTO)
demod_dvbc_set_qam(2);//64 QAM
} else
qam_write_reg(0x65, 0x800c);
if (demod_dvbc_speedup_en == 1)
return 0;
/*timer_set_max(D_TIMER_DETECT, 4000);*/
timer_begain(D_TIMER_DETECT);
gxtv_demod_dvbc_read_status_timer(fe, status);
if (is_ic_ver(IC_VER_TL1))
demod_dvbc_speed_up(status);
PR_DBG("tune finish!\n");
return ret;
}
if (!dtvdd_devp->en_detect) {
PR_DBGL("tune:not enable\n");
return ret;
}
if (demod_dvbc_speedup_en == 1) {
if (!fast_search_finish) {
if (fe->dtv_property_cache.modulation == QAM_AUTO)
sig_flg = demod_dvbc_64_256_auto_fast(delay);
else
sig_flg = demod_dvbc_fast_search(delay);
switch (sig_flg) {
case 0:
*status = FE_TIMEDOUT;
fast_search_finish = 1;
PR_DVBC(">>>unlock<<<\n");
break;
case 1:
*status =
FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC;
fast_search_finish = 1;
PR_DVBC(">>>lock<<<\n");
break;
case 2:
*status = 0;
break;
default:
PR_DVBC("wrong return value\n");
break;
}
} else {
gxtv_demod_dvbc_read_status_timer(fe, status);
}
} else {
gxtv_demod_dvbc_read_status_timer(fe, status);
}
if (demod_dvbc_speedup_en == 1)
return 0;
#if 0
if (is_ic_ver(IC_VER_TL1))
return ret;
#endif
if (*status & FE_HAS_LOCK) {
timer_disable(D_TIMER_SET);
} else {
if (!timer_is_en(D_TIMER_SET))
timer_begain(D_TIMER_SET);
}
if (timer_is_enough(D_TIMER_SET)) {
gxtv_demod_dvbc_set_frontend(fe);
timer_disable(D_TIMER_SET);
}
return ret;
}
static int gxtv_demod_dtmb_tune(struct dvb_frontend *fe, bool re_tune,
unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
{
/*struct dtv_frontend_properties *c = &fe->dtv_property_cache;*/
int ret = 0;
// unsigned int up_delay;
unsigned int firstdetet;
if (re_tune) {
/*first*/
dtvdd_devp->en_detect = 1;
*delay = HZ / 4;
gxtv_demod_dtmb_set_frontend(fe);
firstdetet = dtmb_detect_first();
if (firstdetet == 1) {
*status = FE_TIMEDOUT;
/*polling mode*/
dtmb_poll_start_tune(DTMBM_NO_SIGNEL_CHECK);
} else if (firstdetet == 2) { /*need check*/
*status = FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC;
dtmb_poll_start_tune(DTMBM_HV_SIGNEL_CHECK);
} else if (firstdetet == 0) {
PR_DBG("use read_status\n");
gxtv_demod_dtmb_read_status_old(fe, status);
if (*status == (0x1f))
dtmb_poll_start_tune(DTMBM_HV_SIGNEL_CHECK);
else
dtmb_poll_start_tune(DTMBM_NO_SIGNEL_CHECK);
}
PR_DBG("tune finish!\n");
return ret;
}
if (!dtvdd_devp->en_detect) {
PR_DBG("tune:not enable\n");
return ret;
}
#if 1 /**/
*delay = HZ / 4;
gxtv_demod_dtmb_read_status_old(fe, status);
if (*status == (FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC))
dtmb_poll_start_tune(DTMBM_HV_SIGNEL_CHECK);
else
dtmb_poll_start_tune(DTMBM_NO_SIGNEL_CHECK);
#else /*try polling*/
/*pr_dbg("+");*/
if (is_dtmb_ver(IC_DTMB_V3)) {
dtmb_poll_v3();
gxtv_demod_dtmb_read_status(fe, status);
if (dtmb_is_update_delay()) {
up_delay = (dtmb_get_delay_clear()*HZ)/1000;
if (up_delay > 0)
*delay = up_delay;
else
PR_DBG("warning:delay is 0\n");
}
} else if (is_dtmb_ver(IC_DTMB_V2)) {
*delay = HZ / 3;
dtmb_poll_v2(fe, status);
}
#endif
return ret;
}
#endif
#ifdef CONFIG_CMA
/*void dtmb_cma_alloc(struct aml_fe_dev *devp)*/
bool dtmb_cma_alloc(struct amldtvdemod_device_s *devp)
{
bool ret;
unsigned int mem_size = devp->cma_mem_size;
/* dma_alloc_from_contiguous*/
devp->venc_pages =
dma_alloc_from_contiguous(&(devp->this_pdev->dev),
mem_size >> PAGE_SHIFT, 0);
PR_DBG("[cma]mem_size is %d,%d\n",
mem_size, mem_size >> PAGE_SHIFT);
if (devp->venc_pages) {
devp->mem_start = page_to_phys(devp->venc_pages);
devp->mem_size = mem_size;
devp->flg_cma_allc = true;
PR_DBG("demod mem_start = 0x%x, mem_size = 0x%x\n",
devp->mem_start, devp->mem_size);
PR_DBG("demod cma alloc ok!\n");
ret = true;
} else {
PR_DBG("demod cma mem undefined2.\n");
ret = false;
}
return ret;
}
/*void dtmb_cma_release(struct aml_fe_dev *devp)*/
void dtmb_cma_release(struct amldtvdemod_device_s *devp)
{
/* dma_release_from_contiguous*/
dma_release_from_contiguous(&(devp->this_pdev->dev),
devp->venc_pages,
devp->cma_mem_size>>PAGE_SHIFT);
PR_DBG("demod cma release ok!\n");
devp->mem_start = 0;
devp->mem_size = 0;
}
#endif
static bool enter_mode(enum aml_fe_n_mode_t mode)
{
/*struct aml_fe_dev *dev = fe->dtv_demod;*/
struct amldtvdemod_device_s *devn = dtvdd_devp;
int memstart_dtmb;
bool ret = true;
if (mode < AM_FE_NUM)
PR_INFO("%s:%s\n", __func__, name_fe_n_mode[mode]);
else
PR_ERR("%s:%d\n", __func__, mode);
dtvdemod_set_agc_pinmux(1);
/*-------------------*/
/* must enable the adc ref signal for demod, */
/*vdac_enable(1, 0x2);*/
dtvdemod_vdac_enable(1);/*on*/
dtvdd_devp->en_detect = 0;/**/
dtvdd_devp->n_mode = mode;
dtmb_poll_stop();/*polling mode*/
autoFlagsTrig = 1;
if (cci_thread)
if (dvbc_get_cci_task() == 1)
dvbc_create_cci_task();
/*mem_buf = (long *)phys_to_virt(memstart);*/
if (mode == AM_FE_DTMB_N) {
Gxtv_Demod_Dtmb_Init(devn);
if (devn->cma_flag == 1) {
PR_DBG("CMA MODE, cma flag is %d,mem size is %d",
devn->cma_flag, devn->cma_mem_size);
if (dtmb_cma_alloc(devn)) {
memstart_dtmb = devn->mem_start;
} else {
ret = false;
return ret;
}
} else {
memstart_dtmb = devn->mem_start;/*??*/
}
devn->act_dtmb = true;
dtmb_set_mem_st(memstart_dtmb);
//?, already set in Gxtv_Demod_Dtmb_Init()
if (!is_ic_ver(IC_VER_TL1))
demod_write_reg(DEMOD_TOP_REGC, 0x8);
} else if (mode == AM_FE_QAM_N) {
Gxtv_Demod_Dvbc_Init(/*dev,*/ Adc_mode);
/*The maximum time of signal detection is 3s*/
timer_set_max(D_TIMER_DETECT, 3000);
/*reset is 4s*/
timer_set_max(D_TIMER_SET, 4000);
} else if (mode == AM_FE_ATSC_N) {
Gxtv_Demod_Atsc_Init();
if (is_ic_ver(IC_VER_TL1))
timer_set_max(D_TIMER_DETECT, 4000);
} else if (mode == AM_FE_OFDM_N || mode == AM_FE_ISDBT_N) {
Gxtv_Demod_Dvbt_Init();
/*The maximum time of signal detection is 2s */
timer_set_max(D_TIMER_DETECT, 2000);
/*reset is 4s*/
timer_set_max(D_TIMER_SET, 4000);
if (devn->cma_flag == 1) {
PR_DBG("CMA MODE, cma flag is %d,mem size is %d",
devn->cma_flag,
devn->cma_mem_size);
if (dtmb_cma_alloc(devn)) {
memstart_dtmb = devn->mem_start;
} else {
ret = false;
return ret;
}
} else {
memstart_dtmb = devn->mem_start;/*??*/
}
PR_DBG("[im]memstart is %x\n", memstart_dtmb);
dvbt_write_reg((0x10 << 2), memstart_dtmb);
}
return ret;
}
static int leave_mode(enum aml_fe_n_mode_t mode)
{
/* struct aml_fe_dev *dev = fe->dtv_demod;*/
struct amldtvdemod_device_s *devn = dtvdd_devp;
if (mode < AM_FE_NUM)
PR_INFO("%s:%s\n", __func__, name_fe_n_mode[mode]);
else
PR_ERR("%s:%d\n", __func__, mode);
dtvdd_devp->en_detect = 0;
dtvdd_devp->last_delsys = SYS_UNDEFINED;
dtvdd_devp->n_mode = AM_FE_UNKNOWN_N;
dtvpll_init_flag(0);
/*dvbc_timer_exit();*/
if (cci_thread)
dvbc_kill_cci_task();
if (mode == AM_FE_DTMB_N) {
if (dtvdd_devp->act_dtmb) {
dtmb_poll_stop(); /*polling mode*/
/* close arbit */
demod_write_reg(DEMOD_TOP_REGC, 0x0);
dtvdd_devp->act_dtmb = false;
}
if ((devn->cma_flag == 1) && dtvdd_devp->flg_cma_allc) {
dtmb_cma_release(devn);
dtvdd_devp->flg_cma_allc = false;
}
} else if (mode == AM_FE_OFDM_N || mode == AM_FE_ISDBT_N) {
if ((devn->cma_flag == 1) && dtvdd_devp->flg_cma_allc) {
dtmb_cma_release(devn);
dtvdd_devp->flg_cma_allc = false;
}
}
adc_set_pll_cntl(0, 0x4, NULL);
adc_set_pll_cntl(0, 0x8, NULL);
demod_mode_para = UNKNOWN;
/* should disable the adc ref signal for demod */
/*vdac_enable(0, 0x2);*/
dtvdemod_vdac_enable(0);/*off*/
dtvdemod_set_agc_pinmux(0);
msleep(200);
return 0;
}
/* when can't get ic_config by dts, use this*/
const struct meson_ddemod_data data_gxtvbb = {
.name = "ddmode_gxtvbb",
.icver = {
.atsc = IC_MD_NONE,
.dvbt = IC_MD_NONE,
.dtmb = IC_DTMB_V2,
.dvbc = IC_DVBC_V2,
.reserved = 0,
.offset = IC_OFFS_V2,
.ic = IC_VER_GTVBB,
},
};
const struct meson_ddemod_data data_txl = {
.name = "ddmode_txl",
.icver = {
.atsc = IC_MD_NONE,
.dvbt = IC_MD_NONE,
.dtmb = IC_DTMB_V3,
.dvbc = IC_DVBC_V2,
.reserved = 0,
.offset = IC_OFFS_V2,
.ic = IC_VER_TXL,
},
};
const struct meson_ddemod_data data_txlx = {
.name = "ddmode_txlx",
.icver = {
.atsc = IC_ATSC_V2,
.dvbt = IC_DVBT_V2,
.dtmb = IC_MD_NONE,
.dvbc = IC_DVBC_V3,
.reserved = 0,
.offset = IC_OFFS_V3,
.ic = IC_VER_TXLX,
},
};
const struct meson_ddemod_data data_gxlx = {
.name = "ddmode_gxlx",
.icver = {
.atsc = IC_MD_NONE,
.dvbt = IC_MD_NONE,
.dtmb = IC_MD_NONE,
.dvbc = IC_DVBC_V3,
.reserved = 0,
.offset = IC_OFFS_V3,
.ic = IC_VER_GXLX,
},
};
const struct meson_ddemod_data data_txhd = {
.name = "ddmode_txhd",
.icver = {
.atsc = IC_MD_NONE,
.dvbt = IC_MD_NONE,
.dtmb = IC_DTMB_V3,
.dvbc = IC_MD_NONE,
.reserved = 0,
.offset = IC_OFFS_V3,
.ic = IC_VER_TXHD,
},
};
const struct meson_ddemod_data data_tl1 = {
.name = "ddmode_tl1",
.icver = {
.atsc = IC_ATSC_V2,
.dvbt = IC_MD_NONE,
.dtmb = IC_DTMB_V3,
.dvbc = IC_DVBC_V3,
.reserved = 0,
.offset = IC_OFFS_V4,
.ic = IC_VER_TL1,
},
};
static const struct of_device_id meson_ddemod_match[] = {
{
.compatible = "amlogic, ddemod-gxtvbb",
.data = &data_gxtvbb,
}, {
.compatible = "amlogic, ddemod-txl",
.data = &data_txl,
}, {
.compatible = "amlogic, ddemod-txlx",
.data = &data_txlx,
}, {
.compatible = "amlogic, ddemod-gxlx",
.data = &data_gxlx,
}, {
.compatible = "amlogic, ddemod-txhd",
.data = &data_txhd,
}, {
.compatible = "amlogic, ddemod-tl1",
.data = &data_tl1,
},
{},
};
/*
* dds_init_reg_map - physical addr map
*
* map physical address of I/O memory resources
* into the core virtual address space
*/
static int dds_init_reg_map(struct platform_device *pdev)
{
struct ss_reg_phy *preg = &dtvdd_devp->reg_p[0];
struct ss_reg_vt *pv = &dtvdd_devp->reg_v[0];
int i;
struct resource *res = 0;
int size = 0;
int ret = 0;
for (i = 0; i < ES_MAP_ADDR_NUM; i++) {
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res) {
PR_ERR("%s: res %d is faile\n", __func__, i);
ret = -ENOMEM;
break;
}
size = resource_size(res);
preg[i].size = size;
preg[i].phy_addr = res->start;
pv[i].v = devm_ioremap_nocache(&pdev->dev,
res->start, size);
}
return ret;
}
int dtvdemod_set_iccfg_by_dts(struct platform_device *pdev)
{
/*struct ic_cfg_s *ic_cfg = &dtvdd_devp->iccfg;*/
/*int size_io_reg;*/
u32 value;
int ret;
/*struct resource *res = &dtvdemod_mem;*/
PR_DBG("%s:\n", __func__);
ret = of_reserved_mem_device_init(&pdev->dev);
if (ret != 0)
PR_INFO("no reserved mem.\n");
/*agc pinmux: option*/
ret = of_property_read_string(pdev->dev.of_node, "pinctrl-names",
&dtvdd_devp->pin_name);
if (ret)
PR_INFO("pinmux:not define in dts\n");
else
PR_INFO("pinmux name:%s\n", dtvdd_devp->pin_name);
/*move from aml_fe*/
/*snprintf(buf, sizeof(buf), "%s%d_spectrum", name, id);*/
#ifdef CONFIG_OF
ret = of_property_read_u32(pdev->dev.of_node, "spectrum", &value);
if (!ret) {
dtvdd_devp->spectrum = value;
PR_INFO("spectrum: %d\n", value);
} else {
dtvdd_devp->spectrum = 2;
}
#else /*CONFIG_OF */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "spectrum");
if (res) {
int spectrum = res->start;
dtvdd_devp->spectrum = spectrum;
} else {
dtvdd_devp->spectrum = 0;
}
#endif
/*snprintf(buf, sizeof(buf), "%s%d_cma_flag", name, id);*/
#ifdef CONFIG_OF
ret = of_property_read_u32(pdev->dev.of_node, "cma_flag", &value);
if (!ret) {
dtvdd_devp->cma_flag = value;
PR_INFO("cma_flag: %d\n", value);
} else {
dtvdd_devp->cma_flag = 0;
}
#else /*CONFIG_OF */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cma_flag");
if (res) {
int cma_flag = res->start;
dtvdd_devp->cma_flag = cma_flag;
} else {
dtvdd_devp->cma_flag = 0;
}
#endif
/*snprintf(buf, sizeof(buf), "%s%d_atsc_version", name, id);*/
#ifdef CONFIG_OF
ret = of_property_read_u32(pdev->dev.of_node, "atsc_version", &value);
if (!ret) {
dtvdd_devp->atsc_version = value;
PR_INFO("atsc_version: %d\n", value);
} else {
dtvdd_devp->atsc_version = 0;
}
#else /*CONFIG_OF */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"atsc_version");
if (res) {
int atsc_version = res->start;
dtvdd_devp->atsc_version = atsc_version;
} else {
dtvdd_devp->atsc_version = 0;
}
#endif
if (dtvdd_devp->cma_flag == 1) {
/*snprintf(buf, sizeof(buf), "%s%d_cma_mem_size", name, id);*/
#ifdef CONFIG_CMA
#ifdef CONFIG_OF
ret = of_property_read_u32(pdev->dev.of_node,
"cma_mem_size", &value);
if (!ret) {
dtvdd_devp->cma_mem_size = value;
PR_INFO("cma_mem_size: %d\n", value);
} else {
dtvdd_devp->cma_mem_size = 0;
}
#else /*CONFIG_OF */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"cma_mem_size");
if (res) {
int cma_mem_size = res->start;
dtvdd_devp->cma_mem_size = cma_mem_size;
} else {
dtvdd_devp->cma_mem_size = 0;
}
#endif
dtvdd_devp->cma_mem_size =
dma_get_cma_size_int_byte(&pdev->dev);
dtvdd_devp->this_pdev = pdev;
dtvdd_devp->cma_mem_alloc = 0;
PR_INFO("[cma]demod cma_mem_size = %d MB\n",
(u32)dtvdd_devp->cma_mem_size/SZ_1M);
#endif
} else {
#ifdef CONFIG_OF
dtvdd_devp->mem_start = memstart;
#endif
}
/*end-------------*/
return 0;
}
#if (defined CONFIG_AMLOGIC_DTV_DEMOD) /*move to aml_dtv_demod*/
static int rmem_demod_device_init(struct reserved_mem *rmem, struct device *dev)
{
unsigned int demod_mem_start;
unsigned int demod_mem_size;
demod_mem_start = rmem->base;
demod_mem_size = rmem->size;
memstart = demod_mem_start;
pr_info("demod reveser memory 0x%x, size %dMB.\n",
demod_mem_start, (demod_mem_size >> 20));
return 1;
}
static void rmem_demod_device_release(struct reserved_mem *rmem,
struct device *dev)
{
}
static const struct reserved_mem_ops rmem_demod_ops = {
.device_init = rmem_demod_device_init,
.device_release = rmem_demod_device_release,
};
static int __init rmem_demod_setup(struct reserved_mem *rmem)
{
/*
* struct cma *cma;
* int err;
* pr_info("%s setup.\n",__func__);
* err = cma_init_reserved_mem(rmem->base, rmem->size, 0, &cma);
* if (err) {
* pr_err("Reserved memory: unable to setup CMA region\n");
* return err;
* }
*/
rmem->ops = &rmem_demod_ops;
/* rmem->priv = cma; */
pr_info
("DTV demod reserved memory: %pa, size %ld MiB\n",
&rmem->base, (unsigned long)rmem->size / SZ_1M);
return 0;
}
RESERVEDMEM_OF_DECLARE(demod, "amlogic, demod-mem", rmem_demod_setup);
#endif
int dtvdemod_init_regaddr_byversion(struct platform_device *pdev)
{
struct ic_ver *pic = &dtvdd_devp->icver; /*in*/
struct ddemod_reg_off *ireg = &dtvdd_devp->ireg; /*set*/
unsigned int off_ver = pic->offset;
int ret = 0;
/*clear*/
ireg->off_demod_top = 0x00;
ireg->off_dvbc = 0x00;
ireg->off_dtmb = 0x00;
ireg->off_dvbt = 0x00;
ireg->off_atsc = 0x00;
ireg->off_front = 0x00;
ireg->off_isdbt = 0x00;
if (is_offset_ver(IC_OFFS_V2)) {
ireg->off_demod_top = 0xc00;
ireg->off_dvbc = 0x400;
ireg->off_dtmb = 0x00;
} else if (is_offset_ver(IC_OFFS_V3)) {
ireg->off_demod_top = 0xf00;
ireg->off_dvbc = 0xc00;
ireg->off_dtmb = 0x000;
ireg->off_dvbt = 0x400;
ireg->off_isdbt = ireg->off_dvbt;
ireg->off_atsc = 0x800;
} else if (is_offset_ver(IC_OFFS_V4)) {
ireg->off_demod_top = 0x3c00;
ireg->off_dvbc = 0x1000;
ireg->off_dtmb = 0x0000;
ireg->off_dvbt = 0x0400;
ireg->off_isdbt = 0x0800;
ireg->off_atsc = 0x0c00;
ireg->off_front = 0x3800;
} else {
PR_ERR("ic_offset_version[%d] is not support!\n", off_ver);
ireg->off_demod_top = 0xf00;
ireg->off_dvbc = 0xc00;
ireg->off_dtmb = 0x000;
ireg->off_dvbt = 0x400;
ireg->off_atsc = 0x800;
ret = -1;
}
return ret;
}
/* It's a correspondence with enum es_map_addr*/
void dbg_ic_cfg(void)
{
struct ic_ver *pic = &dtvdd_devp->icver;
struct ss_reg_phy *preg = &dtvdd_devp->reg_p[0];
int i;
PR_INFO("ic_version=0x%x\n", pic->ic);
PR_INFO("\tver_dvbc:\t%d\n", pic->dvbc);
PR_INFO("\tver_dtmb:\t%d\n", pic->dtmb);
PR_INFO("\tver_dvbt:\t%d\n", pic->dvbt);
PR_INFO("\tver_atsc:\t%d\n", pic->atsc);
PR_INFO("\tver_offset:\t%d\n", pic->offset);
for (i = 0; i < ES_MAP_ADDR_NUM; i++)
PR_INFO("reg:%s:st=0x%x,size=0x%x\n",
name_reg[i], preg[i].phy_addr, preg[i].size);
}
void dbg_reg_addr(void)
{
struct ddemod_reg_off *ireg = &dtvdd_devp->ireg;
struct ss_reg_vt *regv = &dtvdd_devp->reg_v[0];
int i;
PR_INFO("%s\n", __func__);
PR_INFO("reg address offset:\n");
PR_INFO("\tdemod top:\t0x%x\n", ireg->off_demod_top);
PR_INFO("\tdvbc:\t0x%x\n", ireg->off_dvbc);
PR_INFO("\tdtmb:\t0x%x\n", ireg->off_dtmb);
PR_INFO("\tdvbt:\t0x%x\n", ireg->off_dvbt);
PR_INFO("\tisdbt:\t0x%x\n", ireg->off_isdbt);
PR_INFO("\tatsc:\t0x%x\n", ireg->off_atsc);
PR_INFO("\tfront:\t0x%x\n", ireg->off_front);
PR_INFO("virtual addr:\n");
for (i = 0; i < ES_MAP_ADDR_NUM; i++)
PR_INFO("\t%s:\t0x%p\n", name_reg[i], regv[i].v);
}
static void dtvdemod_set_agc_pinmux(int on)
{
if (dtvdd_devp->pin_name == NULL) {
PR_INFO("no pinmux control\n");
return;
}
if (on) {
dtvdd_devp->pin = devm_pinctrl_get_select(dtvdd_devp->dev,
dtvdd_devp->pin_name);
if (IS_ERR(dtvdd_devp->pin)) {
dtvdd_devp->pin = NULL;
PR_ERR("get agc pins fail\n");
}
} else {
/*off*/
if (!IS_ERR_OR_NULL(dtvdd_devp->pin)) {
devm_pinctrl_put(dtvdd_devp->pin);
dtvdd_devp->pin = NULL;
}
}
}
static void dtvdemod_clktree_probe(struct device *dev)
{
dtvdd_devp->clk_gate_state = 0;
dtvdd_devp->vdac_clk_gate = devm_clk_get(dev, "vdac_clk_gate");
if (IS_ERR(dtvdd_devp->vdac_clk_gate))
PR_ERR("error: %s: clk vdac_clk_gate\n", __func__);
}
static void dtvdemod_clktree_remove(struct device *dev)
{
if (!IS_ERR(dtvdd_devp->vdac_clk_gate))
devm_clk_put(dev, dtvdd_devp->vdac_clk_gate);
}
static void vdac_clk_gate_ctrl(int status)
{
if (status) {
if (dtvdd_devp->clk_gate_state) {
PR_INFO("clk_gate is already on\n");
return;
}
if (IS_ERR(dtvdd_devp->vdac_clk_gate))
PR_ERR("error: %s: vdac_clk_gate\n", __func__);
else
clk_prepare_enable(dtvdd_devp->vdac_clk_gate);
dtvdd_devp->clk_gate_state = 1;
} else {
if (dtvdd_devp->clk_gate_state == 0) {
PR_INFO("clk_gate is already off\n");
return;
}
if (IS_ERR(dtvdd_devp->vdac_clk_gate))
PR_ERR("error: %s: vdac_clk_gate\n", __func__);
else
clk_disable_unprepare(dtvdd_devp->vdac_clk_gate);
dtvdd_devp->clk_gate_state = 0;
}
}
/*
* use dtvdemod_vdac_enable replace vdac_enable
*/
static void dtvdemod_vdac_enable(bool on)
{
if (on) {
vdac_clk_gate_ctrl(1);
vdac_enable(1, 0x02);
} else {
vdac_clk_gate_ctrl(0);
vdac_enable(0, 0x02);
}
}
/* platform driver*/
static int aml_dtvdemod_probe(struct platform_device *pdev)
{
int ret = 0;
const struct of_device_id *match;
PR_INFO("%s\n", __func__);
/*memory*/
dtvdd_devp = kzalloc(sizeof(struct amldtvdemod_device_s),
GFP_KERNEL);
if (!dtvdd_devp)
goto fail_alloc_region;
dtvdd_devp->state = DTVDEMOD_ST_NOT_INI;
/*class attr */
dtvdd_devp->clsp = class_create(THIS_MODULE, DEMOD_DEVICE_NAME);
if (!dtvdd_devp->clsp)
goto fail_create_class;
ret = class_create_file(dtvdd_devp->clsp, &class_attr_auto_sym);
if (ret)
goto fail_class_create_file;
ret = class_create_file(dtvdd_devp->clsp, &class_attr_dtmb_para);
if (ret)
goto fail_class_create_file;
ret = class_create_file(dtvdd_devp->clsp, &class_attr_dvbc_reg);
if (ret)
goto fail_class_create_file;
ret = class_create_file(dtvdd_devp->clsp, &class_attr_atsc_para);
if (ret)
goto fail_class_create_file;
ret = class_create_file(dtvdd_devp->clsp, &class_attr_demod_rate);
if (ret)
goto fail_class_create_file;
ret = class_create_file(dtvdd_devp->clsp, &class_attr_info);
if (ret)
goto fail_class_create_file;
/**/
match = of_match_device(meson_ddemod_match, &pdev->dev);
if (match == NULL) {
PR_ERR("%s,no matched table\n", __func__);
goto fail_ic_config;
}
dtvdd_devp->data = (struct meson_ddemod_data *)match->data;
dtvdd_devp->icver = dtvdd_devp->data->icver;
/*reg*/
ret = dds_init_reg_map(pdev);
if (ret)
goto fail_ic_config;
/*mem info from dts*/
ret = dtvdemod_set_iccfg_by_dts(pdev);
if (ret)
goto fail_ic_config;
/*dtvdemod_set_iccfg_by_cputype();*/
ret = dtvdemod_init_regaddr_byversion(pdev);
if (ret)
goto fail_ic_config;
/*debug:*/
dbg_ic_cfg();
dbg_reg_addr();
/**/
dtvpll_lock_init();
/* init */
/*dtvdemod_base_add_init();*/
mutex_init(&dtvdd_devp->lock);
dtvdd_devp->dev = &pdev->dev;
dtvdemod_clktree_probe(&pdev->dev);
dtvdd_devp->state = DTVDEMOD_ST_IDLE;
dtvdemod_version(dtvdd_devp);
dtvdd_devp->flg_cma_allc = false;
dtvdd_devp->act_dtmb = false;
//ary temp:
aml_demod_init();
PR_INFO("[amldtvdemod.] : probe ok.\n");
return 0;
fail_ic_config:
PR_ERR("ic config error.\n");
fail_class_create_file:
PR_ERR("dtvdemod class file create error.\n");
class_destroy(dtvdd_devp->clsp);
fail_create_class:
PR_ERR("dtvdemod class create error.\n");
kfree(dtvdd_devp);
fail_alloc_region:
PR_ERR("dtvdemod alloc error.\n");
PR_ERR("dtvdemod_init fail.\n");
return ret;
}
static int __exit aml_dtvdemod_remove(struct platform_device *pdev)
{
if (dtvdd_devp == NULL)
return -1;
dtvdemod_clktree_remove(&pdev->dev);
mutex_destroy(&dtvdd_devp->lock);
class_remove_file(dtvdd_devp->clsp, &class_attr_auto_sym);
class_remove_file(dtvdd_devp->clsp, &class_attr_dtmb_para);
class_remove_file(dtvdd_devp->clsp, &class_attr_dvbc_reg);
class_remove_file(dtvdd_devp->clsp, &class_attr_atsc_para);
class_remove_file(dtvdd_devp->clsp, &class_attr_demod_rate);
class_remove_file(dtvdd_devp->clsp, &class_attr_info);
class_destroy(dtvdd_devp->clsp);
kfree(dtvdd_devp);
PR_INFO("%s:remove.\n", __func__);
aml_demod_exit();//ary temp
return 0;
}
static void aml_dtvdemod_shutdown(struct platform_device *pdev)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
pr_info("%s\n", __func__);
if (dtvdd_devp->state != DTVDEMOD_ST_IDLE) {
if (nmode != AM_FE_UNKNOWN_N)
leave_mode(nmode);
dtvdd_devp->state = DTVDEMOD_ST_IDLE;
}
adc_pll_down();
}
static int aml_dtvdemod_suspend(struct platform_device *pdev,
pm_message_t state)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
PR_INFO("%s, mode = %d\n", __func__, nmode);
if (nmode != AM_FE_UNKNOWN_N)
leave_mode(nmode);
return 0;
}
static int aml_dtvdemod_resume(struct platform_device *pdev)
{
PR_INFO("%s is called\n", __func__);
return 0;
}
static struct platform_driver aml_dtvdemod_driver = {
.driver = {
.name = "aml_dtv_demod",
.owner = THIS_MODULE,
/*aml_dtvdemod_dt_match*/
.of_match_table = meson_ddemod_match,
},
.shutdown = aml_dtvdemod_shutdown,
.probe = aml_dtvdemod_probe,
.remove = __exit_p(aml_dtvdemod_remove),
#ifdef CONFIG_PM
.suspend = aml_dtvdemod_suspend,
.resume = aml_dtvdemod_resume,
#endif
};
static int __init aml_dtvdemod_init(void)
{
if (platform_driver_register(&aml_dtvdemod_driver)) {
pr_err("failed to register amldtvdemod driver module\n");
return -ENODEV;
}
PR_INFO("[amldtvdemod..]%s.\n", __func__);
return 0;
}
static void __exit aml_dtvdemod_exit(void)
{
platform_driver_unregister(&aml_dtvdemod_driver);
PR_INFO("[amldtvdemod..]%s: driver removed ok.\n", __func__);
}
#if 0
static int delsys_confirm(struct dvb_frontend *fe)
{
enum fe_delivery_system ldelsys = dtvdd_devp->last_delsys;
enum fe_delivery_system cdelsys;
int ncaps, support;
enum aml_fe_n_mode_t mode = AM_FE_UNKNOWN_N;
cdelsys = fe->dtv_property_cache.delivery_system;
/*same*/
if (ldelsys == cdelsys) {
//PR_DBG("delsys is same, do nothing\n");
return 0;
}
/*support ?*/
ncaps = 0;
support = 0;
while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
if (fe->ops.delsys[ncaps] == cdelsys) {
support = 1;
break;
}
ncaps++;
}
if (!support) {
PR_INFO("delsys:%d is not support!\n", cdelsys);
return 0;
}
PR_DBG("%s:l=%d,c=%d\n", __func__, ldelsys, cdelsys);
switch (cdelsys) {
case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C:
/*dvbc*/
if (ldelsys == SYS_DVBC_ANNEX_A
|| ldelsys == SYS_DVBC_ANNEX_C) {
break;
}
mode = AM_FE_QAM_N;
break;
case SYS_ATSC:
case SYS_ATSCMH:
case SYS_DVBC_ANNEX_B:
/*atsc*/
if (ldelsys == SYS_ATSC
|| ldelsys == SYS_ATSCMH
|| ldelsys == SYS_DVBC_ANNEX_B) {
break;
}
mode = AM_FE_ATSC_N;
break;
case SYS_DVBT:
case SYS_DVBT2:
/*dvbt, OFDM*/
if (ldelsys == SYS_DVBT
|| ldelsys == SYS_DVBT2) {
break;
}
mode = AM_FE_OFDM_N;
break;
case SYS_ISDBT:
if (ldelsys != SYS_ISDBT)
mode = AM_FE_ISDBT_N;
break;
case SYS_DTMB:
/*dtmb*/
mode = AM_FE_DTMB_N;
break;
case SYS_DVBS:
case SYS_DVBS2:
/*QPSK*/
if (ldelsys == SYS_DVBS
|| ldelsys == SYS_DVBS2) {
break;
}
mode = AM_FE_QPSK_N;
break;
case SYS_DSS:
case SYS_DVBH:
case SYS_ISDBS:
case SYS_ISDBC:
case SYS_CMMB:
case SYS_DAB:
case SYS_TURBO:
case SYS_UNDEFINED:
#ifdef CONFIG_AMLOGIC_DVB_COMPAT
case SYS_ANALOG:
#endif
mode = AM_FE_UNKNOWN_N;
PR_INFO("delsys not support!%d=\n", cdelsys);
return 0;
}
if (mode != AM_FE_UNKNOWN_N)
enter_mode(mode);
if (!get_dtvpll_init_flag()) {
PR_INFO("pll is not set!\n");
leave_mode(mode);
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
dtvdd_devp->last_delsys = SYS_UNDEFINED;
dtvdd_devp->n_mode = AM_FE_UNKNOWN_N;
return 0;
}
dtvdd_devp->last_delsys = cdelsys;
return 0;
}
#endif
static int delsys_set(struct dvb_frontend *fe, unsigned int delsys)
{
enum fe_delivery_system ldelsys = dtvdd_devp->last_delsys;
enum fe_delivery_system cdelsys;
int ncaps, support;
enum aml_fe_n_mode_t mode = AM_FE_UNKNOWN_N;
enum aml_fe_n_mode_t lmode = dtvdd_devp->n_mode;
cdelsys = delsys; /*diff*/
/*same*/
if (ldelsys == cdelsys) {
//PR_DBG("delsys is same, do nothing\n");
return 0;
}
/*support ?*/
ncaps = 0;
support = 0;
while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
if (fe->ops.delsys[ncaps] == cdelsys) {
support = 1;
break;
}
ncaps++;
}
if (!support) {
#if 0
if (get_dtvpll_init_flag()) {
/**/
PR_INFO("delsys:%d is not support!\n", cdelsys);
leave_mode(lmode);
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
dtvdd_devp->last_delsys = SYS_UNDEFINED;
dtvdd_devp->n_mode = AM_FE_UNKNOWN_N;
}
#endif
PR_INFO("delsys:%d is not support!\n", cdelsys);
return 0;
}
if (ldelsys <= END_SYS_DELIVERY && cdelsys <= END_SYS_DELIVERY) {
PR_DBG("%s:l=%s,c=%s\n", __func__,
name_fe_delivery_system[ldelsys],
name_fe_delivery_system[cdelsys]);
} else
PR_ERR("%s:last=%d,cur=%d\n", __func__, ldelsys, cdelsys);
switch (cdelsys) {
case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C:
/*dvbc*/
if (ldelsys == SYS_DVBC_ANNEX_A
|| ldelsys == SYS_DVBC_ANNEX_C) {
break;
}
mode = AM_FE_QAM_N;
break;
case SYS_ATSC:
case SYS_ATSCMH:
case SYS_DVBC_ANNEX_B:
/*atsc*/
if (ldelsys == SYS_ATSC
|| ldelsys == SYS_ATSCMH
|| ldelsys == SYS_DVBC_ANNEX_B) {
break;
}
mode = AM_FE_ATSC_N;
break;
case SYS_DVBT:
case SYS_DVBT2:
/*dvbt, OFDM*/
if (ldelsys == SYS_DVBT
|| ldelsys == SYS_DVBT2) {
break;
}
mode = AM_FE_OFDM_N;
break;
case SYS_ISDBT:
if (ldelsys != SYS_ISDBT)
mode = AM_FE_ISDBT_N;
break;
case SYS_DTMB:
/*dtmb*/
mode = AM_FE_DTMB_N;
break;
case SYS_DVBS:
case SYS_DVBS2:
/*QPSK*/
if (ldelsys == SYS_DVBS
|| ldelsys == SYS_DVBS2) {
break;
}
mode = AM_FE_QPSK_N;
break;
case SYS_DSS:
case SYS_DVBH:
case SYS_ISDBS:
case SYS_ISDBC:
case SYS_CMMB:
case SYS_DAB:
case SYS_TURBO:
case SYS_UNDEFINED:
return 0;
#ifdef CONFIG_AMLOGIC_DVB_COMPAT
case SYS_ANALOG:
if (get_dtvpll_init_flag()) {
PR_INFO("delsys not support : %d\n", cdelsys);
leave_mode(lmode);
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
}
return 0;
#endif
}
if (mode != AM_FE_UNKNOWN_N) {
if (lmode != AM_FE_UNKNOWN_N) {
leave_mode(lmode);
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
}
if (!enter_mode(mode)) {
PR_INFO("enter_mode failed,leave!\n");
leave_mode(mode);
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
return 0;
}
}
if (!get_dtvpll_init_flag()) {
PR_INFO("pll is not set!\n");
leave_mode(mode);
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
return 0;
}
dtvdd_devp->last_delsys = cdelsys;
PR_INFO("info type:%d", fe->ops.info.type);
if (mode == AM_FE_ATSC_N)
fe->ops.info.type = FE_ATSC;
else if (mode == AM_FE_OFDM_N)
fe->ops.info.type = FE_OFDM;
else if (mode == AM_FE_DTMB_N)
fe->ops.info.type = FE_DTMB;
else if (mode == AM_FE_QAM_N)
fe->ops.info.type = FE_QAM;
else if (mode == AM_FE_ISDBT_N)
fe->ops.info.type = FE_ISDBT;
if (fe->ops.tuner_ops.set_config)
fe->ops.tuner_ops.set_config(fe, NULL);
return 0;
}
static int is_not_active(struct dvb_frontend *fe)
{
enum fe_delivery_system cdelsys;
enum fe_delivery_system ldelsys = dtvdd_devp->last_delsys;
if (!get_dtvpll_init_flag())
return 1;
cdelsys = fe->dtv_property_cache.delivery_system;
if (ldelsys != cdelsys)
return 2;
return 0;/*active*/
}
/*ko attach==============================*/
static int aml_dtvdm_init(struct dvb_frontend *fe)
{
return 0;
}
static int aml_dtvdm_sleep(struct dvb_frontend *fe)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
if (get_dtvpll_init_flag()) {
PR_INFO("%s\n", __func__);
if (nmode != AM_FE_UNKNOWN_N)
leave_mode(nmode);
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
}
return 0;
}
static int aml_dtvdm_set_parameters(struct dvb_frontend *fe)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
int ret = 0;
PR_INFO("%s", __func__);
/*delsys_confirm(fe);*/
if (is_not_active(fe)) {
PR_DBG("set parm:not active\n");
return 0;
}
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
PR_INFO("FE_QAM\n");
timer_begain(D_TIMER_DETECT);
dtvdd_devp->en_detect = 1; /*fist set*/
ret = gxtv_demod_dvbc_set_frontend(fe);
break;
case AM_FE_OFDM_N:
PR_INFO("FE_OFDM\n");
timer_begain(D_TIMER_DETECT);
dtvdd_devp->en_detect = 1; /*fist set*/
ret = gxtv_demod_dvbt_set_frontend(fe);
break;
case AM_FE_ISDBT_N: /*same as dvbt*/
PR_INFO("FE_ISDBT\n");
timer_begain(D_TIMER_DETECT);
dtvdd_devp->en_detect = 1; /*fist set*/
ret = gxtv_demod_dvbt_set_frontend(fe);
break;
case AM_FE_ATSC_N:
PR_INFO("FE_ATSC\n");
ret = gxtv_demod_atsc_set_frontend(fe);
break;
case AM_FE_DTMB_N:
PR_INFO("FE_DTMB\n");
ret = gxtv_demod_dtmb_set_frontend(fe);
break;
case AM_FE_UNKNOWN_N:
default:
break;
}
return ret;
}
static int aml_dtvdm_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
int ret = 0;
if (is_not_active(fe)) {
PR_DBGL("get parm:not active\n");
return 0;
}
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
ret = gxtv_demod_dvbc_get_frontend(fe);
break;
case AM_FE_OFDM_N:
ret = gxtv_demod_dvbt_get_frontend(fe);
break;
case AM_FE_ISDBT_N: /*same as dvbt*/
ret = gxtv_demod_dvbt_get_frontend(fe);
break;
case AM_FE_ATSC_N:
ret = gxtv_demod_atsc_get_frontend(fe);
break;
case AM_FE_DTMB_N:
ret = gxtv_demod_dtmb_get_frontend(fe);
break;
case AM_FE_UNKNOWN_N:
default:
break;
}
return ret;
}
static int aml_dtvdm_get_tune_settings(struct dvb_frontend *fe,
struct dvb_frontend_tune_settings
*fe_tune_settings)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
int ret = 0;
if (is_not_active(fe)) {
PR_DBGL("get parm:not active\n");
return 0;
}
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
fe_tune_settings->min_delay_ms = 300;
fe_tune_settings->step_size = 0; /* no zigzag */
fe_tune_settings->max_drift = 0;
break;
case AM_FE_OFDM_N:
/*dvbt*/
fe_tune_settings->min_delay_ms = 500;
fe_tune_settings->step_size = 0;
fe_tune_settings->max_drift = 0;
break;
case AM_FE_ISDBT_N: /*same as dvbt*/
/*isdbt*/
fe_tune_settings->min_delay_ms = 300;
fe_tune_settings->step_size = 0;
fe_tune_settings->max_drift = 0;
break;
case AM_FE_ATSC_N:
break;
case AM_FE_DTMB_N:
break;
case AM_FE_UNKNOWN_N:
default:
break;
}
return ret;
}
static int aml_dtvdm_read_status(struct dvb_frontend *fe,
enum fe_status *status)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
int ret = 0;
if (nmode == AM_FE_UNKNOWN_N)
return 0;
if (is_not_active(fe)) {
PR_DBGL("read status:not active\n");
return 0;
}
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
ret = gxtv_demod_dvbc_read_status_timer(fe, status);
break;
case AM_FE_OFDM_N:
ret = gxtv_demod_dvbt_read_status(fe, status);
break;
case AM_FE_ISDBT_N:
ret = gxtv_demod_dvbt_read_status(fe, status);
break;
case AM_FE_ATSC_N:
ret = gxtv_demod_atsc_read_status(fe, status);
break;
case AM_FE_DTMB_N:
ret = gxtv_demod_dtmb_read_status(fe, status);
break;
/*case AM_FE_UNKNOWN_N:*/
default:
break;
}
return ret;
}
static int aml_dtvdm_read_ber(struct dvb_frontend *fe, u32 *ber)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
int ret = 0;
if (is_not_active(fe)) {
PR_DBGL("read ber:not active\n");
return 0;
}
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
ret = gxtv_demod_dvbc_read_ber(fe, ber);
break;
case AM_FE_OFDM_N:
ret = gxtv_demod_dvbt_read_ber(fe, ber);
break;
case AM_FE_ISDBT_N: /*same as dvbt*/
ret = gxtv_demod_dvbt_read_ber(fe, ber);
break;
case AM_FE_ATSC_N:
ret = gxtv_demod_atsc_read_ber(fe, ber);
break;
case AM_FE_DTMB_N:
ret = gxtv_demod_dtmb_read_ber(fe, ber);
break;
case AM_FE_UNKNOWN_N:
default:
break;
}
return ret;
}
static int aml_dtvdm_read_signal_strength(struct dvb_frontend *fe,
u16 *strength)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
int ret = 0;
if (is_not_active(fe)) {
PR_DBGL("read strength:not active\n");
return 0;
}
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
ret = gxtv_demod_dvbc_read_signal_strength(fe, strength);
break;
case AM_FE_OFDM_N:
ret = gxtv_demod_dvbt_read_signal_strength(fe, strength);
break;
case AM_FE_ISDBT_N: /*same as dvbt*/
ret = gxtv_demod_dvbt_read_signal_strength(fe, strength);
break;
case AM_FE_ATSC_N:
ret = gxtv_demod_atsc_read_signal_strength(fe, strength);
break;
case AM_FE_DTMB_N:
ret = gxtv_demod_dtmb_read_signal_strength(fe, strength);
break;
case AM_FE_UNKNOWN_N:
default:
break;
}
return ret;
}
static int aml_dtvdm_read_snr(struct dvb_frontend *fe, u16 *snr)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
int ret = 0;
if (is_not_active(fe)) {
PR_DBGL("read snr :not active\n");
return 0;
}
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
ret = gxtv_demod_dvbc_read_snr(fe, snr);
break;
case AM_FE_OFDM_N:
ret = gxtv_demod_dvbt_read_snr(fe, snr);
break;
case AM_FE_ISDBT_N:
ret = gxtv_demod_dvbt_read_snr(fe, snr);
break;
case AM_FE_ATSC_N:
ret = gxtv_demod_atsc_read_snr(fe, snr);
break;
case AM_FE_DTMB_N:
ret = gxtv_demod_dtmb_read_snr(fe, snr);
break;
case AM_FE_UNKNOWN_N:
default:
break;
}
return ret;
}
static int aml_dtvdm_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
int ret = 0;
if (is_not_active(fe)) {
PR_DBGL("read ucblocks :not active\n");
return 0;
}
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
ret = gxtv_demod_dvbc_read_ucblocks(fe, ucblocks);
break;
case AM_FE_OFDM_N:
ret = gxtv_demod_dvbt_read_ucblocks(fe, ucblocks);
break;
case AM_FE_ISDBT_N:
ret = gxtv_demod_dvbt_read_ucblocks(fe, ucblocks);
break;
case AM_FE_ATSC_N:
ret = gxtv_demod_atsc_read_ucblocks(fe, ucblocks);
break;
case AM_FE_DTMB_N:
ret = gxtv_demod_dtmb_read_ucblocks(fe, ucblocks);
break;
case AM_FE_UNKNOWN_N:
default:
break;
}
return ret;
}
static void aml_dtvdm_release(struct dvb_frontend *fe)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
gxtv_demod_dvbc_release(fe);
break;
case AM_FE_OFDM_N:
case AM_FE_ISDBT_N:
gxtv_demod_dvbt_release(fe);
break;
case AM_FE_ATSC_N:
gxtv_demod_atsc_release(fe);
break;
case AM_FE_DTMB_N:
gxtv_demod_dtmb_release(fe);
break;
case AM_FE_UNKNOWN_N:
default:
break;
}
if (get_dtvpll_init_flag()) {
PR_INFO("%s\n", __func__);
if (nmode != AM_FE_UNKNOWN_N)
leave_mode(nmode);
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
}
}
static int aml_dtvdm_tune(struct dvb_frontend *fe, bool re_tune,
unsigned int mode_flags, unsigned int *delay, enum fe_status *status)
{
enum aml_fe_n_mode_t nmode = dtvdd_devp->n_mode;
int ret = 0;
static int flg; /*debug only*/
if (re_tune)
;//delsys_confirm(fe);
if (nmode == AM_FE_UNKNOWN_N) {
*delay = HZ * 5;
*status = 0;
return 0;
}
if (is_not_active(fe)) {
*status = 0;
PR_DBGL("tune :not active\n");
return 0;
}
if ((flg > 0) && (flg < 5))
PR_INFO("%s\n", __func__);
switch (nmode) {
case AM_FE_QPSK_N:
break;
case AM_FE_QAM_N:
gxtv_demod_dvbc_tune(fe, re_tune, mode_flags,
delay, status);
break;
case AM_FE_OFDM_N:
case AM_FE_ISDBT_N:
ret = gxtv_demod_dvbt_tune(fe, re_tune, mode_flags,
delay, status);
break;
case AM_FE_ATSC_N:
ret = gxtv_demod_atsc_tune(fe, re_tune, mode_flags,
delay, status);
flg++;
break;
case AM_FE_DTMB_N:
ret = gxtv_demod_dtmb_tune(fe, re_tune, mode_flags,
delay, status);
break;
/*case AM_FE_UNKNOWN_N:*/
default:
flg = 0;
break;
}
return ret;
}
static int aml_dtvdm_set_property(struct dvb_frontend *dev,
struct dtv_property *tvp)
{
int r = 0;
u32 delsys;
switch (tvp->cmd) {
case DTV_DELIVERY_SYSTEM:
delsys = tvp->u.data;
delsys_set(dev, delsys);
break;
default:
break;
}
return r;
}
static int aml_dtvdm_get_property(struct dvb_frontend *dev,
struct dtv_property *tvp)
{
return 0;
}
static struct dvb_frontend_ops aml_dtvdm_gxtvbb_ops = {
.delsys = { SYS_DVBC_ANNEX_A, SYS_DTMB},
.info = {
/*in aml_fe, it is 'amlogic dvb frontend' */
.name = "amlogic dtv demod txlx",
.frequency_min = 51000000,
.frequency_max = 900000000,
.frequency_stepsize = 0,
.frequency_tolerance = 0, /**/
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS
},
.init = aml_dtvdm_init,
.sleep = aml_dtvdm_sleep,
.set_frontend = aml_dtvdm_set_parameters,
.get_frontend = aml_dtvdm_get_frontend,
.get_tune_settings = aml_dtvdm_get_tune_settings,
.read_status = aml_dtvdm_read_status,
.read_ber = aml_dtvdm_read_ber,
.read_signal_strength = aml_dtvdm_read_signal_strength,
.read_snr = aml_dtvdm_read_snr,
.read_ucblocks = aml_dtvdm_read_ucblocks,
.release = aml_dtvdm_release,
.set_property = aml_dtvdm_set_property,
.get_property = aml_dtvdm_get_property,
/*-------------*/
.tune = aml_dtvdm_tune,
.get_frontend_algo = gxtv_demod_atsc_get_frontend_algo,
};
static struct dvb_frontend_ops aml_dtvdm_txl_ops = {
.delsys = { SYS_DVBC_ANNEX_A, SYS_DTMB, SYS_ANALOG},
.info = {
/*in aml_fe, it is 'amlogic dvb frontend' */
.name = "amlogic dtv demod txl",
.frequency_min = 51000000,
.frequency_max = 900000000,
.frequency_stepsize = 0,
.frequency_tolerance = 0, /**/
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS
},
.init = aml_dtvdm_init,
.sleep = aml_dtvdm_sleep,
.set_frontend = aml_dtvdm_set_parameters,
.get_frontend = aml_dtvdm_get_frontend,
.get_tune_settings = aml_dtvdm_get_tune_settings,
.read_status = aml_dtvdm_read_status,
.read_ber = aml_dtvdm_read_ber,
.read_signal_strength = aml_dtvdm_read_signal_strength,
.read_snr = aml_dtvdm_read_snr,
.read_ucblocks = aml_dtvdm_read_ucblocks,
.release = aml_dtvdm_release,
.set_property = aml_dtvdm_set_property,
.get_property = aml_dtvdm_get_property,
/*-------------*/
.tune = aml_dtvdm_tune,
.get_frontend_algo = gxtv_demod_atsc_get_frontend_algo,
};
static struct dvb_frontend_ops aml_dtvdm_txlx_ops = {
#ifdef CONFIG_AMLOGIC_DVB_COMPAT
.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_A, SYS_DVBT,
SYS_ANALOG, SYS_ISDBT},
#else
.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_A, SYS_DVBT},
#endif
.info = {
/*in aml_fe, it is 'amlogic dvb frontend' */
.name = "amlogic dtv demod txlx",
.frequency_min = 51000000,
.frequency_max = 900000000,
.frequency_stepsize = 0,
.frequency_tolerance = 0, /**/
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS
},
.init = aml_dtvdm_init,
.sleep = aml_dtvdm_sleep,
.set_frontend = aml_dtvdm_set_parameters,
.get_frontend = aml_dtvdm_get_frontend,
.get_tune_settings = aml_dtvdm_get_tune_settings,
.read_status = aml_dtvdm_read_status,
.read_ber = aml_dtvdm_read_ber,
.read_signal_strength = aml_dtvdm_read_signal_strength,
.read_snr = aml_dtvdm_read_snr,
.read_ucblocks = aml_dtvdm_read_ucblocks,
.release = aml_dtvdm_release,
.set_property = aml_dtvdm_set_property,
.get_property = aml_dtvdm_get_property,
/*-------------*/
.tune = aml_dtvdm_tune,
.get_frontend_algo = gxtv_demod_txlx_get_frontend_algo,
};
static struct dvb_frontend_ops aml_dtvdm_gxlx_ops = {
.delsys = { SYS_DVBC_ANNEX_A },
.info = {
/*in aml_fe, it is 'amlogic dvb frontend' */
.name = "amlogic dtv demod txlx",
.frequency_min = 51000000,
.frequency_max = 900000000,
.frequency_stepsize = 0,
.frequency_tolerance = 0, /**/
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS
},
.init = aml_dtvdm_init,
.sleep = aml_dtvdm_sleep,
.set_frontend = aml_dtvdm_set_parameters,
.get_frontend = aml_dtvdm_get_frontend,
.get_tune_settings = aml_dtvdm_get_tune_settings,
.read_status = aml_dtvdm_read_status,
.read_ber = aml_dtvdm_read_ber,
.read_signal_strength = aml_dtvdm_read_signal_strength,
.read_snr = aml_dtvdm_read_snr,
.read_ucblocks = aml_dtvdm_read_ucblocks,
.release = aml_dtvdm_release,
.set_property = aml_dtvdm_set_property,
.get_property = aml_dtvdm_get_property,
/*-------------*/
.tune = aml_dtvdm_tune,
.get_frontend_algo = gxtv_demod_atsc_get_frontend_algo,
};
static struct dvb_frontend_ops aml_dtvdm_txhd_ops = {
.delsys = { SYS_DTMB },
.info = {
/*in aml_fe, it is 'amlogic dvb frontend' */
.name = "amlogic dtv demod txlx",
.frequency_min = 51000000,
.frequency_max = 900000000,
.frequency_stepsize = 0,
.frequency_tolerance = 0, /**/
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS
},
.init = aml_dtvdm_init,
.sleep = aml_dtvdm_sleep,
.set_frontend = aml_dtvdm_set_parameters,
.get_frontend = aml_dtvdm_get_frontend,
.get_tune_settings = aml_dtvdm_get_tune_settings,
.read_status = aml_dtvdm_read_status,
.read_ber = aml_dtvdm_read_ber,
.read_signal_strength = aml_dtvdm_read_signal_strength,
.read_snr = aml_dtvdm_read_snr,
.read_ucblocks = aml_dtvdm_read_ucblocks,
.release = aml_dtvdm_release,
.set_property = aml_dtvdm_set_property,
.get_property = aml_dtvdm_get_property,
/*-------------*/
.tune = aml_dtvdm_tune,
.get_frontend_algo = gxtv_demod_atsc_get_frontend_algo,
};
static struct dvb_frontend_ops aml_dtvdm_tl1_ops = {
#ifdef CONFIG_AMLOGIC_DVB_COMPAT
.delsys = {SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_ATSC, SYS_DTMB,
SYS_ANALOG},
#else
.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B, SYS_DVBC_ANNEX_A, SYS_DVBT},
#endif
.info = {
/*in aml_fe, it is 'amlogic dvb frontend' */
.name = "amlogic dtv demod tl1",
.frequency_min = 51000000,
.frequency_max = 900000000,
.frequency_stepsize = 0,
.frequency_tolerance = 0, /**/
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
FE_CAN_RECOVER | FE_CAN_MUTE_TS
},
.init = aml_dtvdm_init,
.sleep = aml_dtvdm_sleep,
.set_frontend = aml_dtvdm_set_parameters,
.get_frontend = aml_dtvdm_get_frontend,
.get_tune_settings = aml_dtvdm_get_tune_settings,
.read_status = aml_dtvdm_read_status,
.read_ber = aml_dtvdm_read_ber,
.read_signal_strength = aml_dtvdm_read_signal_strength,
.read_snr = aml_dtvdm_read_snr,
.read_ucblocks = aml_dtvdm_read_ucblocks,
.release = aml_dtvdm_release,
.set_property = aml_dtvdm_set_property,
.get_property = aml_dtvdm_get_property,
/*-------------*/
.tune = aml_dtvdm_tune,
.get_frontend_algo = gxtv_demod_txlx_get_frontend_algo,
};
struct dvb_frontend *aml_dtvdm_attach(const struct amlfe_exp_config *config)
{
int ic_version = get_ic_ver();
/*mem setting is in prob*/
struct dvb_frontend *fe = &dtvdd_devp->frontend;
/* mem of dvb_frontend is define in aml_fe*/
switch (ic_version) {
case IC_VER_GTVBB:
memcpy(&fe->ops, &aml_dtvdm_gxtvbb_ops,
sizeof(struct dvb_frontend_ops));
break;
case IC_VER_TXL:
memcpy(&fe->ops, &aml_dtvdm_txl_ops,
sizeof(struct dvb_frontend_ops));
break;
case IC_VER_TXLX:
memcpy(&fe->ops, &aml_dtvdm_txlx_ops,
sizeof(struct dvb_frontend_ops));
break;
case IC_VER_GXLX:
memcpy(&fe->ops, &aml_dtvdm_gxlx_ops,
sizeof(struct dvb_frontend_ops));
break;
case IC_VER_TXHD:
memcpy(&fe->ops, &aml_dtvdm_txhd_ops,
sizeof(struct dvb_frontend_ops));
break;
case IC_VER_TL1:
memcpy(&fe->ops, &aml_dtvdm_tl1_ops,
sizeof(struct dvb_frontend_ops));
break;
default:
PR_ERR("attach fail! ic=%d\n", ic_version);
/*return NULL;*/
fe = NULL;
break;
}
/* mem of dvb_frontend is define in aml_fe*/
dtvdd_devp->last_delsys = SYS_UNDEFINED;
return fe;
}
EXPORT_SYMBOL(aml_dtvdm_attach);
/*-------------------------*/
static struct aml_exp_func aml_exp_ops = {
.leave_mode = leave_mode,
};
struct aml_exp_func *aml_dtvdm_exp_attach(struct aml_exp_func *exp)
{
if (exp) {
memcpy(exp, &aml_exp_ops, sizeof(struct aml_exp_func));
} else {
PR_ERR("%s:fail!\n", __func__);
return NULL;
}
return exp;
}
EXPORT_SYMBOL(aml_dtvdm_exp_attach);
/*-------------------------*/
struct dvb_frontend *aml_get_fe(void)
{
return &dtvdd_devp->frontend;
}
void aml_exp_attach(struct aml_exp_func *afe)
{
}
EXPORT_SYMBOL(aml_exp_attach);
/*=======================================*/
fs_initcall(aml_dtvdemod_init);
module_exit(aml_dtvdemod_exit);
MODULE_DESCRIPTION("gxtv_demod DVB-T/DVB-C/DTMB Demodulator driver");
MODULE_AUTHOR("RSJ");
MODULE_LICENSE("GPL");