mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 04:33:26 +02:00
1149 lines
36 KiB
C
1149 lines
36 KiB
C
/*
|
|
* Driver for the STm STiD135 DVB-S/S2/S2X demodulator.
|
|
*
|
|
* Copyright (C) CrazyCat <crazycat69@narod.ru>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* version 2 only, as published by the Free Software Foundation.
|
|
*
|
|
*
|
|
* 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.
|
|
*
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA
|
|
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/moduleparam.h>
|
|
#include <linux/init.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/firmware.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/version.h>
|
|
#include <asm/div64.h>
|
|
|
|
#include <media/dvb_frontend.h>
|
|
#include "stid135.h"
|
|
#include "i2c.h"
|
|
#include "stid135_drv.h"
|
|
|
|
LIST_HEAD(stvlist);
|
|
|
|
static int mode;
|
|
module_param(mode, int, 0444);
|
|
MODULE_PARM_DESC(mode,
|
|
"Multi-switch mode: 0=quattro/quad 1=normal direct connection");
|
|
|
|
static unsigned int rfsource;
|
|
module_param(rfsource, int, 0644);
|
|
MODULE_PARM_DESC(rfsource, "RF source selection for direct connection mode (default:0 - auto)");
|
|
|
|
static unsigned int mc_auto;
|
|
module_param(mc_auto, int, 0644);
|
|
MODULE_PARM_DESC(mc_auto, "Enable auto modcode filtering depend from current C/N (default:0 - disabled)");
|
|
|
|
static unsigned int ts_nosync;
|
|
module_param(ts_nosync, int, 0644);
|
|
MODULE_PARM_DESC(ts_nosync, "TS FIFO Minimum latence mode (default:off)");
|
|
|
|
static unsigned int bbframe;
|
|
module_param(bbframe, int, 0644);
|
|
MODULE_PARM_DESC(bbframe, "BBFrame L3 encapsulation for GCS, GSE-HEM (default:off)");
|
|
|
|
static unsigned int timeout=5;
|
|
module_param(timeout, int, 0644);
|
|
MODULE_PARM_DESC(timeout, "Timeout for signal statistic retrieve 1-20 sec (default:5 sec)");
|
|
|
|
struct stv_base {
|
|
struct list_head stvlist;
|
|
|
|
u8 adr;
|
|
struct i2c_adapter *i2c;
|
|
struct mutex status_lock;
|
|
int count;
|
|
u32 extclk;
|
|
u8 ts_mode;
|
|
|
|
int (*set_voltage)(struct i2c_adapter *i2c,
|
|
enum fe_sec_voltage voltage, u8 rf_in);
|
|
u8 mode;
|
|
|
|
fe_stid135_handle_t handle;
|
|
STCHIP_Handle_t vglna_handle[4];
|
|
|
|
void (*write_properties) (struct i2c_adapter *i2c,u8 reg, u32 buf);
|
|
void (*read_properties) (struct i2c_adapter *i2c,u8 reg, u32 *buf);
|
|
|
|
void (*write_eeprom) (struct i2c_adapter *i2c,u8 reg, u8 buf);
|
|
void (*read_eeprom) (struct i2c_adapter *i2c,u8 reg, u8 *buf);
|
|
|
|
//for tbs6912
|
|
void (*set_TSsampling)(struct i2c_adapter *i2c,int tuner,int time);
|
|
u32 (*set_TSparam)(struct i2c_adapter *i2c,int tuner,int time,bool flag);
|
|
//end
|
|
int vglna;
|
|
bool control_22k; //for 6916
|
|
};
|
|
|
|
struct stv {
|
|
struct stv_base *base;
|
|
struct dvb_frontend fe;
|
|
int nr;
|
|
int rf_in;
|
|
unsigned long stats_time;
|
|
struct fe_sat_signal_info signal_info;
|
|
STCHIP_Handle_t vglna_handle;
|
|
|
|
bool newTP; //for tbs6912
|
|
u32 bit_rate; //for tbs6912;
|
|
int loops ;//for tbs6912
|
|
|
|
bool modcode_filter; //for set the modcode
|
|
struct fe_sat_dvbs2_mode_t modcode_mask[FE_SAT_MODCODE_UNKNOWN*4];
|
|
};
|
|
|
|
I2C_RESULT I2cReadWrite(void *pI2CHost, I2C_MODE mode, u8 ChipAddress, u8 *Data, int NbData)
|
|
{
|
|
struct stv_base *base = (struct stv_base *)pI2CHost;
|
|
struct i2c_msg msg = {.addr = ChipAddress>>1, .flags = 0,
|
|
.buf = Data, .len = NbData};
|
|
int ret;
|
|
|
|
|
|
if (!base) return I2C_ERR_HANDLE;
|
|
|
|
if (mode == I2C_READ)
|
|
msg.flags = I2C_M_RD;
|
|
|
|
ret = i2c_transfer(base->i2c, &msg, 1);
|
|
|
|
return (ret == 1) ? I2C_ERR_NONE : I2C_ERR_ACK;
|
|
}
|
|
|
|
static int stid135_probe(struct stv *state)
|
|
{
|
|
struct fe_stid135_init_param init_params;
|
|
fe_lla_error_t err = FE_LLA_NO_ERROR;
|
|
struct fe_stid135_internal_param *p_params;
|
|
enum device_cut_id cut_id;
|
|
int i;
|
|
|
|
STCHIP_Info_t VGLNAChip;
|
|
SAT_VGLNA_InitParams_t vglna_init_params;
|
|
|
|
dev_warn(&state->base->i2c->dev, "%s\n", FE_STiD135_GetRevision());
|
|
|
|
strcpy(init_params.demod_name,"STiD135");
|
|
init_params.pI2CHost = state->base;
|
|
init_params.demod_i2c_adr = state->base->adr ? state->base->adr<<1 : 0xd0;
|
|
init_params.demod_ref_clk = state->base->extclk ? state->base->extclk : 27;
|
|
init_params.internal_dcdc = FALSE;
|
|
init_params.internal_ldo = TRUE; // LDO supply is internal on Oxford valid board
|
|
init_params.rf_input_type = 0xF; // Single ended RF input on Oxford valid board rev2
|
|
init_params.roll_off = FE_SAT_35; // NYQUIST Filter value (used for DVBS1/DSS, DVBS2 is automatic)
|
|
init_params.tuner_iq_inversion = FE_SAT_IQ_NORMAL;
|
|
init_params.ts_nosync = ts_nosync;
|
|
init_params.bbframe = bbframe;
|
|
err = fe_stid135_init(&init_params,&state->base->handle);
|
|
|
|
if (err != FE_LLA_NO_ERROR) {
|
|
dev_err(&state->base->i2c->dev, "%s: fe_stid135_init error %d !\n", __func__, err);
|
|
return -EINVAL;
|
|
}
|
|
|
|
p_params = state->base->handle;
|
|
p_params->master_lock = &state->base->status_lock;
|
|
|
|
err = fe_stid135_get_cut_id(state->base->handle,&cut_id);
|
|
switch(cut_id)
|
|
{
|
|
case STID135_CUT1_0:
|
|
dev_warn(&state->base->i2c->dev, "%s: cut 1.0\n", __func__);
|
|
break;
|
|
case STID135_CUT1_1:
|
|
dev_warn(&state->base->i2c->dev, "%s: cut 1.1\n", __func__);
|
|
break;
|
|
case STID135_CUT1_X:
|
|
dev_warn(&state->base->i2c->dev, "%s: cut 1.x\n", __func__);
|
|
break;
|
|
case STID135_CUT2_0:
|
|
dev_warn(&state->base->i2c->dev, "%s: cut 2.0 \n", __func__);
|
|
break;
|
|
case STID135_CUT2_1:
|
|
dev_warn(&state->base->i2c->dev, "%s: cut 2.1 \n", __func__);
|
|
break;
|
|
case STID135_CUT2_X_UNFUSED:
|
|
dev_warn(&state->base->i2c->dev, "%s: cut 2.x \n", __func__);
|
|
break;
|
|
default:
|
|
dev_warn(&state->base->i2c->dev, "%s: cut ? \n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (state->base->ts_mode == TS_STFE) {
|
|
dev_warn(&state->base->i2c->dev, "%s: 8xTS to STFE mode init.\n", __func__);
|
|
// for(i=0;i<8;i++) {
|
|
err |= fe_stid135_set_ts_parallel_serial(state->base->handle, FE_SAT_DEMOD_1, FE_TS_PARALLEL_ON_TSOUT_0);
|
|
// err |= fe_stid135_set_maxllr_rate(state->base->handle, i+1, 260);
|
|
// }
|
|
err |= fe_stid135_enable_stfe(state->base->handle,FE_STFE_OUTPUT0);
|
|
err |= fe_stid135_set_stfe(state->base->handle, FE_STFE_TAGGING_MERGING_MODE, FE_STFE_INPUT1 |
|
|
FE_STFE_INPUT2 |FE_STFE_INPUT3 |FE_STFE_INPUT4| FE_STFE_INPUT5 |
|
|
FE_STFE_INPUT6 |FE_STFE_INPUT7 |FE_STFE_INPUT8 ,FE_STFE_OUTPUT0, 0xDE);
|
|
} else if (state->base->ts_mode == TS_8SER) {
|
|
dev_warn(&state->base->i2c->dev, "%s: 8xTS serial mode init.\n", __func__);
|
|
for(i=0;i<8;i++) {
|
|
err |= fe_stid135_set_ts_parallel_serial(state->base->handle, i+1, FE_TS_SERIAL_CONT_CLOCK);
|
|
// err |= fe_stid135_set_maxllr_rate(state->base->handle, i+1, 90);
|
|
}
|
|
} else {
|
|
dev_warn(&state->base->i2c->dev, "%s: 2xTS parallel mode init.\n", __func__);
|
|
err |= fe_stid135_set_ts_parallel_serial(state->base->handle, FE_SAT_DEMOD_3, FE_TS_PARALLEL_PUNCT_CLOCK);
|
|
//err |= fe_stid135_set_maxllr_rate(state->base->handle, FE_SAT_DEMOD_3, 260);
|
|
err |= fe_stid135_set_ts_parallel_serial(state->base->handle, FE_SAT_DEMOD_1, FE_TS_PARALLEL_PUNCT_CLOCK);
|
|
//err |= fe_stid135_set_maxllr_rate(state->base->handle, FE_SAT_DEMOD_1, 260);
|
|
}
|
|
|
|
if (state->base->mode == 0) {
|
|
dev_warn(&state->base->i2c->dev, "%s: multiswitch mode init.\n", __func__);
|
|
err |= fe_stid135_tuner_enable(p_params->handle_demod, AFE_TUNER1);
|
|
err |= fe_stid135_tuner_enable(p_params->handle_demod, AFE_TUNER2);
|
|
err |= fe_stid135_tuner_enable(p_params->handle_demod, AFE_TUNER3);
|
|
err |= fe_stid135_tuner_enable(p_params->handle_demod, AFE_TUNER4);
|
|
err |= fe_stid135_diseqc_init(state->base->handle,AFE_TUNER1, FE_SAT_DISEQC_2_3_PWM);
|
|
err |= fe_stid135_diseqc_init(state->base->handle,AFE_TUNER3, FE_SAT_DISEQC_2_3_PWM);
|
|
if(state->base->control_22k){
|
|
err |= fe_stid135_diseqc_init(state->base->handle,AFE_TUNER2, FE_SAT_22KHZ_Continues);
|
|
err |= fe_stid135_diseqc_init(state->base->handle,AFE_TUNER4, FE_SAT_22KHZ_Continues);
|
|
}
|
|
else{
|
|
err |= fe_stid135_diseqc_init(state->base->handle,AFE_TUNER2, FE_SAT_DISEQC_2_3_PWM);
|
|
err |= fe_stid135_diseqc_init(state->base->handle,AFE_TUNER4, FE_SAT_DISEQC_2_3_PWM);
|
|
}
|
|
if (state->base->set_voltage) {
|
|
state->base->set_voltage(state->base->i2c, SEC_VOLTAGE_13, 0);
|
|
state->base->set_voltage(state->base->i2c, SEC_VOLTAGE_13, 1);
|
|
state->base->set_voltage(state->base->i2c, SEC_VOLTAGE_18, 2);
|
|
state->base->set_voltage(state->base->i2c, SEC_VOLTAGE_18, 3);
|
|
}
|
|
}
|
|
|
|
///////////////////*stvvglna*////////////////////////
|
|
if (state->base->vglna) {
|
|
dev_warn(&state->base->i2c->dev, "%s:Init STVVGLNA \n", __func__);
|
|
|
|
vglna_init_params.Chip = &VGLNAChip;
|
|
vglna_init_params.Chip->pI2CHost = state->base;
|
|
vglna_init_params.Chip->RepeaterHost = NULL;
|
|
vglna_init_params.Chip->Repeater = FALSE;
|
|
vglna_init_params.Chip->I2cAddr = 0xc8;
|
|
vglna_init_params.NbDefVal = STVVGLNA_NBREGS;
|
|
strcpy(vglna_init_params.Chip->Name, "STVVGLNA");
|
|
stvvglna_init(&vglna_init_params, &state->base->vglna_handle[0]);
|
|
stvvglna_set_standby(state->base->vglna_handle[0],0);
|
|
dev_warn(&state->base->i2c->dev, "Initialized STVVGLNA 0 device\n");
|
|
|
|
if (state->base->vglna > 1) {
|
|
vglna_init_params.Chip->I2cAddr = 0xce;
|
|
stvvglna_init(&vglna_init_params, &state->base->vglna_handle[1]);
|
|
stvvglna_set_standby(state->base->vglna_handle[1],0);
|
|
dev_warn(&state->base->i2c->dev, "Initialized STVVGLNA 1 device\n");
|
|
|
|
vglna_init_params.Chip->I2cAddr = 0xcc;
|
|
stvvglna_init(&vglna_init_params, &state->base->vglna_handle[2]);
|
|
stvvglna_set_standby(state->base->vglna_handle[2],0);
|
|
dev_warn(&state->base->i2c->dev, "Initialized STVVGLNA 2 device\n");
|
|
}
|
|
|
|
vglna_init_params.Chip->I2cAddr = 0xca;
|
|
stvvglna_init(&vglna_init_params, &state->base->vglna_handle[3]);
|
|
stvvglna_set_standby(state->base->vglna_handle[3],0);
|
|
dev_warn(&state->base->i2c->dev, "Initialized STVVGLNA 3 device\n");
|
|
}
|
|
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_err(&state->base->i2c->dev, "%s: setup error %d !\n", __func__, err);
|
|
|
|
return err != FE_LLA_NO_ERROR ? -1 : 0;
|
|
}
|
|
|
|
static int stid135_init(struct dvb_frontend *fe)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
fe_lla_error_t err = FE_LLA_NO_ERROR;
|
|
struct fe_stid135_internal_param *p_params = state->base->handle;
|
|
|
|
if (state->base->mode == 0)
|
|
return 0;
|
|
|
|
dev_dbg(&state->base->i2c->dev, "%s: demod %d + tuner %d\n", __func__, state->nr, state->rf_in);
|
|
|
|
mutex_lock(&state->base->status_lock);
|
|
err |= fe_stid135_tuner_enable(p_params->handle_demod, state->rf_in + 1);
|
|
err |= fe_stid135_diseqc_init(state->base->handle, state->rf_in + 1, FE_SAT_DISEQC_2_3_PWM);
|
|
err |= fe_stid135_set_rfmux_path(p_params->handle_demod, state->nr + 1, state->rf_in + 1);
|
|
mutex_unlock(&state->base->status_lock);
|
|
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_err(&state->base->i2c->dev, "%s: enable tuner %d + demod %d error %d !\n", __func__, state->rf_in, state->nr, err);
|
|
|
|
return err != FE_LLA_NO_ERROR ? -1 : 0;
|
|
}
|
|
|
|
static void stid135_release(struct dvb_frontend *fe)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
int i;
|
|
|
|
dev_dbg(&state->base->i2c->dev, "%s: demod %d\n", __func__, state->nr);
|
|
state->base->count--;
|
|
if (state->base->count == 0) {
|
|
for(i = 0; i < 4; i++)
|
|
if (state->base->vglna_handle[i])
|
|
stvvglna_term(state->base->vglna_handle[i]);
|
|
if (state->base->handle)
|
|
FE_STiD135_Term (state->base->handle);
|
|
list_del(&state->base->stvlist);
|
|
kfree(state->base);
|
|
}
|
|
kfree(state);
|
|
}
|
|
|
|
static int stid135_set_parameters(struct dvb_frontend *fe)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
|
fe_lla_error_t err = FE_LLA_NO_ERROR;
|
|
struct fe_stid135_internal_param *p_params = state->base->handle;
|
|
struct fe_sat_search_params search_params;
|
|
struct fe_sat_search_result search_results;
|
|
u32 pls_mode, pls_code;
|
|
s32 rf_power;
|
|
s32 current_llr;
|
|
u32 i, j, m;
|
|
U8 vglna_status;
|
|
S32 vglna_gain;
|
|
|
|
dev_dbg(&state->base->i2c->dev,
|
|
"delivery_system=%u modulation=%u frequency=%u symbol_rate=%u inversion=%u stream_id=%d\n",
|
|
p->delivery_system, p->modulation, p->frequency,
|
|
p->symbol_rate, p->inversion, p->stream_id);
|
|
|
|
mutex_lock(&state->base->status_lock);
|
|
|
|
/* Search parameters */
|
|
search_params.search_algo = FE_SAT_COLD_START;
|
|
search_params.frequency = p->frequency*1000;
|
|
search_params.symbol_rate = p->symbol_rate;
|
|
search_params.modulation = FE_SAT_MOD_UNKNOWN;
|
|
search_params.modcode = FE_SAT_DUMMY_PLF;
|
|
search_params.search_range = 10000000;
|
|
search_params.puncture_rate = FE_SAT_PR_UNKNOWN;
|
|
switch (p->delivery_system)
|
|
{
|
|
case SYS_DSS:
|
|
search_params.standard = FE_SAT_SEARCH_DSS;
|
|
break;
|
|
case SYS_DVBS:
|
|
search_params.standard = FE_SAT_SEARCH_DVBS1;
|
|
break;
|
|
case SYS_DVBS2:
|
|
search_params.standard = FE_SAT_SEARCH_DVBS2;
|
|
break;
|
|
default:
|
|
search_params.standard = FE_SAT_AUTO_SEARCH;
|
|
}
|
|
search_params.iq_inversion = FE_SAT_IQ_AUTO;
|
|
search_params.tuner_index_jump = 0; // ok with narrow band signal
|
|
|
|
err = FE_STiD135_GetLoFreqHz(state->base->handle, &(search_params.lo_frequency));
|
|
search_params.lo_frequency *= 1000000;
|
|
|
|
err |= fe_stid135_unlock(state->base->handle, state->nr + 1);
|
|
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_err(&state->base->i2c->dev, "%s: fe_stid135_unlock error %d !\n", __func__, err);
|
|
|
|
dev_dbg(&state->base->i2c->dev, "%s: demod %d + tuner %d\n", __func__, state->nr, state->rf_in);
|
|
err |= fe_stid135_set_rfmux_path(p_params->handle_demod, state->nr + 1, state->rf_in + 1);
|
|
|
|
if (p->stream_id == NO_STREAM_ID_FILTER) {
|
|
pls_mode = 0;
|
|
pls_code = 1;
|
|
}
|
|
else {
|
|
pls_mode = (p->stream_id>>26) & 0x3;
|
|
pls_code = (p->stream_id>>8) & 0x3FFFF;
|
|
if (pls_mode == 0 && pls_code == 0)
|
|
pls_code = 1;
|
|
}
|
|
|
|
if (p->scrambling_sequence_index) {
|
|
pls_mode = 1;
|
|
pls_code = p->scrambling_sequence_index;
|
|
}
|
|
|
|
/* Set PLS before search */
|
|
dev_dbg(&state->base->i2c->dev, "%s: set pls_mode %d, pls_code %d !\n", __func__, pls_mode, pls_code);
|
|
err |= fe_stid135_set_pls(state->base->handle, state->nr + 1, pls_mode, pls_code);
|
|
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_err(&state->base->i2c->dev, "%s: fe_stid135_set_pls error %d !\n", __func__, err);
|
|
|
|
if(state->modcode_filter){
|
|
err |= fe_stid135_reset_modcodes_filter(state->base->handle, state->nr + 1);
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_err(&state->base->i2c->dev, "%s: fe_stid135_reset_modcodes_filter error %d !\n", __func__, err);
|
|
state->modcode_filter = false;
|
|
}
|
|
state->stats_time = 0;
|
|
state->signal_info.locked = 0;
|
|
p->strength.len = 1;
|
|
p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
|
p->cnr.len = 1;
|
|
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
|
p->pre_bit_error.len =1;
|
|
p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
|
p->pre_bit_count.len =1;
|
|
p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
|
|
|
err |= fe_stid135_search(state->base->handle, state->nr + 1, &search_params, &search_results, 0);
|
|
|
|
if (err != FE_LLA_NO_ERROR)
|
|
{
|
|
mutex_unlock(&state->base->status_lock);
|
|
dev_err(&state->base->i2c->dev, "%s: fe_stid135_search error %d !\n", __func__, err);
|
|
return -1;
|
|
}
|
|
|
|
if (state->base->vglna_handle[state->rf_in]) {
|
|
err |= stvvglna_get_status(state->base->vglna_handle[state->rf_in], &vglna_status);
|
|
err |= stvvglna_get_gain(state->base->vglna_handle[state->rf_in], &vglna_gain);
|
|
dev_dbg(&state->base->i2c->dev, "%s: VGLNA status %i, gain %d dB !\n", __func__, vglna_status, vglna_gain);
|
|
}
|
|
|
|
if (search_results.locked){
|
|
dev_dbg(&state->base->i2c->dev, "%s: locked !\n", __func__);
|
|
//set maxllr,when the signal is dvbs2 and demod locked ,allocation of resources
|
|
if(search_results.standard==FE_SAT_DVBS2_STANDARD)
|
|
get_current_llr(state->base->handle, state->nr +1, ¤t_llr);
|
|
//fe_stid135_set_maxllr_rate(state->base->handle, state->nr +1, 180);
|
|
|
|
//for tbs6912
|
|
state->newTP = true;
|
|
state->loops = 15;
|
|
if(state->base->set_TSsampling)
|
|
state->base->set_TSsampling(state->base->i2c,state->nr/2,4); //for tbs6912
|
|
}
|
|
else {
|
|
err |= fe_stid135_get_band_power_demod_not_locked(state->base->handle, state->nr + 1, &rf_power);
|
|
dev_dbg(&state->base->i2c->dev, "%s: not locked, band rf_power %d dBm !\n", __func__, rf_power / 1000);
|
|
}
|
|
|
|
/* Set modcode after search */
|
|
if (p->modcode != MODCODE_ALL) {
|
|
m = p->modcode;
|
|
j = 0;
|
|
dev_dbg(&state->base->i2c->dev, "%s: set Modcode mask %x!\n", __func__, p->modcode);
|
|
m >>= 1;
|
|
for (i=FE_SAT_QPSK_14; i < FE_SAT_MODCODE_UNKNOWN; i ++) {
|
|
if (m & 1) {
|
|
dev_dbg(&state->base->i2c->dev, "%s: Modcode %02x enabled!\n", __func__, i);
|
|
state->modcode_mask[j].mod_code = i;
|
|
state->modcode_mask[j].pilots = FE_SAT_PILOTS_OFF;
|
|
state->modcode_mask[j].frame_length = FE_SAT_NORMAL_FRAME;
|
|
state->modcode_mask[j+1].mod_code = i;
|
|
state->modcode_mask[j+1].pilots = FE_SAT_PILOTS_ON;
|
|
state->modcode_mask[j+1].frame_length = FE_SAT_NORMAL_FRAME;
|
|
state->modcode_mask[j+2].mod_code = i;
|
|
state->modcode_mask[j+2].pilots = FE_SAT_PILOTS_OFF;
|
|
state->modcode_mask[j+2].frame_length = FE_SAT_SHORT_FRAME;
|
|
state->modcode_mask[j+3].mod_code = i;
|
|
state->modcode_mask[j+3].pilots = FE_SAT_PILOTS_ON;
|
|
state->modcode_mask[j+3].frame_length = FE_SAT_SHORT_FRAME;
|
|
j+=4;
|
|
}
|
|
m >>= 1;
|
|
}
|
|
state->modcode_filter = true;
|
|
err |= fe_stid135_set_modcodes_filter(state->base->handle, state->nr + 1, state->modcode_mask, j);
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_err(&state->base->i2c->dev, "%s: fe_stid135_set_modcodes_filter error %d !\n", __func__, err);
|
|
}
|
|
|
|
/* Set ISI after search */
|
|
if (p->stream_id != NO_STREAM_ID_FILTER) {
|
|
dev_dbg(&state->base->i2c->dev, "%s: set ISI %d !\n", __func__, p->stream_id & 0xFF);
|
|
err |= fe_stid135_set_mis_filtering(state->base->handle, state->nr + 1, TRUE, p->stream_id & 0xFF, 0xFF);
|
|
} else {
|
|
dev_dbg(&state->base->i2c->dev, "%s: disable ISI filtering !\n", __func__);
|
|
err |= fe_stid135_set_mis_filtering(state->base->handle, state->nr + 1, FALSE, 0, 0xFF);
|
|
}
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_err(&state->base->i2c->dev, "%s: fe_stid135_set_mis_filtering error %d !\n", __func__, err);
|
|
|
|
mutex_unlock(&state->base->status_lock);
|
|
return err != FE_LLA_NO_ERROR ? -1 : 0;
|
|
|
|
}
|
|
|
|
static int stid135_get_frontend(struct dvb_frontend *fe, struct dtv_frontend_properties *p)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
|
|
if (!state->signal_info.locked)
|
|
return 0;
|
|
|
|
switch (state->signal_info.standard) {
|
|
case FE_SAT_DSS_STANDARD:
|
|
p->delivery_system = SYS_DSS;
|
|
break;
|
|
case FE_SAT_DVBS2_STANDARD:
|
|
p->delivery_system = SYS_DVBS2;
|
|
break;
|
|
case FE_SAT_DVBS1_STANDARD:
|
|
default:
|
|
p->delivery_system = SYS_DVBS;
|
|
}
|
|
|
|
switch (state->signal_info.modulation) {
|
|
case FE_SAT_MOD_8PSK:
|
|
p->modulation = PSK_8;
|
|
break;
|
|
case FE_SAT_MOD_16APSK:
|
|
p->modulation = APSK_16;
|
|
break;
|
|
case FE_SAT_MOD_32APSK:
|
|
p->modulation = APSK_32;
|
|
break;
|
|
case FE_SAT_MOD_64APSK:
|
|
p->modulation = APSK_64;
|
|
break;
|
|
case FE_SAT_MOD_128APSK:
|
|
p->modulation = APSK_128;
|
|
break;
|
|
case FE_SAT_MOD_256APSK:
|
|
p->modulation = APSK_256;
|
|
break;
|
|
case FE_SAT_MOD_1024APSK:
|
|
p->modulation = APSK_1024;
|
|
break;
|
|
case FE_SAT_MOD_8PSK_L:
|
|
p->modulation = APSK_8L;
|
|
break;
|
|
case FE_SAT_MOD_16APSK_L:
|
|
p->modulation = APSK_16L;
|
|
break;
|
|
case FE_SAT_MOD_32APSK_L:
|
|
p->modulation = APSK_32L;
|
|
break;
|
|
case FE_SAT_MOD_64APSK_L:
|
|
p->modulation = APSK_64L;
|
|
break;
|
|
case FE_SAT_MOD_256APSK_L:
|
|
p->modulation = APSK_256L;
|
|
break;
|
|
case FE_SAT_MOD_QPSK:
|
|
default:
|
|
p->modulation = QPSK;
|
|
}
|
|
|
|
switch (state->signal_info.roll_off) {
|
|
case FE_SAT_05:
|
|
p->rolloff = ROLLOFF_5;
|
|
break;
|
|
case FE_SAT_10:
|
|
p->rolloff = ROLLOFF_10;
|
|
break;
|
|
case FE_SAT_15:
|
|
p->rolloff = ROLLOFF_15;
|
|
break;
|
|
case FE_SAT_20:
|
|
p->rolloff = ROLLOFF_20;
|
|
break;
|
|
case FE_SAT_25:
|
|
p->rolloff = ROLLOFF_25;
|
|
break;
|
|
case FE_SAT_35:
|
|
p->rolloff = ROLLOFF_35;
|
|
break;
|
|
default:
|
|
p->rolloff = ROLLOFF_AUTO;
|
|
}
|
|
|
|
p->inversion = state->signal_info.spectrum == FE_SAT_IQ_SWAPPED ? INVERSION_ON : INVERSION_OFF;
|
|
if (p->delivery_system == SYS_DVBS2) {
|
|
enum fe_code_rate modcod2fec[0x20] = {
|
|
FEC_NONE, FEC_1_4, FEC_1_3, FEC_2_5,
|
|
FEC_1_2, FEC_3_5, FEC_2_3, FEC_3_4,
|
|
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
|
|
FEC_3_5, FEC_2_3, FEC_3_4, FEC_5_6,
|
|
FEC_8_9, FEC_9_10, FEC_2_3, FEC_3_4,
|
|
FEC_4_5, FEC_5_6, FEC_8_9, FEC_9_10,
|
|
FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9,
|
|
FEC_9_10
|
|
};
|
|
|
|
enum fe_code_rate modcodxfec[] = {
|
|
FEC_AUTO, FEC_AUTO, FEC_13_45, FEC_9_20,
|
|
FEC_11_20, FEC_5_9, FEC_26_45, FEC_23_36,
|
|
FEC_25_36, FEC_13_18, FEC_1_2, FEC_8_15,
|
|
FEC_5_9, FEC_26_45, FEC_3_5, FEC_3_5,
|
|
FEC_28_45, FEC_23_36, FEC_2_3, FEC_25_36,
|
|
FEC_13_18, FEC_7_9, FEC_77_90, FEC_2_3,
|
|
FEC_R_58, FEC_32_45, FEC_11_15, FEC_7_9,
|
|
FEC_32_45, FEC_11_15, FEC_R_5E, FEC_7_9,
|
|
FEC_R_60, FEC_4_5, FEC_R_62, FEC_5_6,
|
|
FEC_3_4, FEC_7_9, FEC_29_45, FEC_2_3,
|
|
FEC_31_45, FEC_32_45, FEC_11_15, FEC_3_4,
|
|
FEC_11_45, FEC_4_15, FEC_14_45, FEC_7_15,
|
|
FEC_8_15, FEC_32_45, FEC_7_15, FEC_8_15,
|
|
FEC_26_45, FEC_32_45, FEC_7_15, FEC_8_15,
|
|
FEC_26_45, FEC_3_5, FEC_32_45, FEC_2_3,
|
|
FEC_32_45,FEC_AUTO
|
|
};
|
|
|
|
if (state->signal_info.modcode < FE_SAT_MODCODE_UNKNOWN)
|
|
p->fec_inner = modcod2fec[state->signal_info.modcode];
|
|
else if(state->signal_info.modcode > 0x40)
|
|
p->fec_inner = modcodxfec[state->signal_info.modcode-0x40];
|
|
else
|
|
p->fec_inner = FEC_AUTO;
|
|
|
|
p->pilot = state->signal_info.pilots == FE_SAT_PILOTS_ON ? PILOT_ON : PILOT_OFF;
|
|
}
|
|
else {
|
|
switch (state->signal_info.puncture_rate) {
|
|
case FE_SAT_PR_1_2:
|
|
p->fec_inner = FEC_1_2;
|
|
break;
|
|
case FE_SAT_PR_2_3:
|
|
p->fec_inner = FEC_2_3;
|
|
break;
|
|
case FE_SAT_PR_3_4:
|
|
p->fec_inner = FEC_3_4;
|
|
break;
|
|
case FE_SAT_PR_5_6:
|
|
p->fec_inner = FEC_5_6;
|
|
break;
|
|
case FE_SAT_PR_6_7:
|
|
p->fec_inner = FEC_6_7;
|
|
break;
|
|
case FE_SAT_PR_7_8:
|
|
p->fec_inner = FEC_7_8;
|
|
break;
|
|
default:
|
|
p->fec_inner = FEC_NONE;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int stid135_read_status(struct dvb_frontend *fe, enum fe_status *status)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
|
fe_lla_error_t err = FE_LLA_NO_ERROR;
|
|
u32 speed;
|
|
|
|
*status = 0;
|
|
if (!mutex_trylock(&state->base->status_lock)) {
|
|
if (state->signal_info.locked)
|
|
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER
|
|
| FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
|
|
return 0;
|
|
}
|
|
|
|
err = fe_stid135_get_lock_status(state->base->handle, state->nr + 1, &state->signal_info.locked);
|
|
if (err != FE_LLA_NO_ERROR) {
|
|
dev_err(&state->base->i2c->dev, "fe_stid135_get_lock_status error\n");
|
|
mutex_unlock(&state->base->status_lock);
|
|
return -EIO;
|
|
}
|
|
|
|
if (!state->signal_info.locked) {
|
|
err = fe_stid135_get_band_power_demod_not_locked(state->base->handle, state->nr + 1, &state->signal_info.power);
|
|
|
|
if (err != FE_LLA_NO_ERROR) {
|
|
dev_warn(&state->base->i2c->dev, "%s: fe_stid135_get_band_power_demod_not_locked error %d !\n", __func__, err);
|
|
mutex_unlock(&state->base->status_lock);
|
|
return 0;
|
|
}
|
|
|
|
// if unlocked, set to lowest resource..
|
|
//disable the line, because sometime the demod unstable, get unlock.
|
|
//err |= fe_stid135_set_maxllr_rate(state->base->handle, state->nr +1, 90);
|
|
|
|
*status |= FE_HAS_SIGNAL;
|
|
dev_dbg(&state->base->i2c->dev, "%s: No lock, signal strength %d dBm !\n", __func__,
|
|
state->signal_info.power/1000);
|
|
|
|
p->strength.len = 2;
|
|
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
|
|
p->strength.stat[0].svalue = state->signal_info.power;
|
|
|
|
p->strength.stat[1].scale = FE_SCALE_RELATIVE;
|
|
p->strength.stat[1].uvalue = (100 + state->signal_info.power/1000) * 656;
|
|
mutex_unlock(&state->base->status_lock);
|
|
return 0;
|
|
}
|
|
|
|
if (!state->stats_time ||
|
|
(time_after(jiffies, state->stats_time))) {
|
|
/* Prevent retrieving stats faster than once per n seconds */
|
|
state->stats_time = jiffies + msecs_to_jiffies(timeout*1000);
|
|
|
|
err = fe_stid135_get_signal_info(state->base->handle, state->nr + 1, &state->signal_info, 0);
|
|
|
|
if (err != FE_LLA_NO_ERROR) {
|
|
dev_warn(&state->base->i2c->dev, "%s: fe_stid135_get_signal_info error %d !\n", __func__, err);
|
|
mutex_unlock(&state->base->status_lock);
|
|
return -EIO;
|
|
}
|
|
|
|
dev_dbg(&state->base->i2c->dev, "%s: Locked, signal strength %d dBm, C/N %d dB !\n", __func__,
|
|
state->signal_info.power/1000, state->signal_info.C_N/10);
|
|
|
|
p->strength.len = 2;
|
|
p->strength.stat[0].scale = FE_SCALE_DECIBEL;
|
|
p->strength.stat[0].svalue = state->signal_info.power;
|
|
|
|
p->strength.stat[1].scale = FE_SCALE_RELATIVE;
|
|
p->strength.stat[1].uvalue = (100 + state->signal_info.power/1000) * 656;
|
|
|
|
p->cnr.len = 2;
|
|
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
|
|
p->cnr.stat[0].svalue = state->signal_info.C_N * 100;
|
|
|
|
p->cnr.stat[1].scale = FE_SCALE_RELATIVE;
|
|
p->cnr.stat[1].uvalue = state->signal_info.C_N * 328;
|
|
if (p->cnr.stat[1].uvalue > 0xffff)
|
|
p->cnr.stat[1].uvalue = 0xffff;
|
|
|
|
p->post_bit_error.len = 1;
|
|
p->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
|
|
p->post_bit_error.stat[0].uvalue = state->signal_info.ber;
|
|
|
|
if (mc_auto && state->signal_info.standard == FE_SAT_DVBS2_STANDARD) {
|
|
err = fe_stid135_filter_forbidden_modcodes(state->base->handle, state->nr + 1, state->signal_info.C_N * 10);
|
|
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_warn(&state->base->i2c->dev, "%s: fe_stid135_filter_forbidden_modcodes error %d !\n", __func__, err);
|
|
}
|
|
}
|
|
|
|
//for the tbs6912 ts setting
|
|
if((state->base->set_TSparam)&&(state->newTP)) {
|
|
speed = state->base->set_TSparam(state->base->i2c,state->nr/2,4,0);
|
|
if(!state->bit_rate)
|
|
state->bit_rate = speed;
|
|
if((((speed-state->bit_rate)<160)&&((speed-state->bit_rate)>3))||(state->loops==0)) {
|
|
state->base->set_TSparam(state->base->i2c,state->nr/2,4,1);
|
|
state->newTP = false;
|
|
state->bit_rate = 0;
|
|
}
|
|
else {
|
|
state->bit_rate = speed;
|
|
state->loops--;
|
|
}
|
|
}
|
|
|
|
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER
|
|
| FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
|
|
|
|
mutex_unlock(&state->base->status_lock);
|
|
return 0;
|
|
}
|
|
|
|
static int stid135_tune(struct dvb_frontend *fe, bool re_tune,
|
|
unsigned int mode_flags,
|
|
unsigned int *delay, enum fe_status *status)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
int r;
|
|
|
|
if (re_tune) {
|
|
r = stid135_set_parameters(fe);
|
|
if (r)
|
|
return r;
|
|
}
|
|
|
|
r = stid135_read_status(fe, status);
|
|
if (r)
|
|
return r;
|
|
|
|
if (*status & FE_HAS_LOCK)
|
|
return 0;
|
|
|
|
*delay = HZ;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static enum dvbfe_algo stid135_get_algo(struct dvb_frontend *fe)
|
|
{
|
|
return DVBFE_ALGO_HW;
|
|
}
|
|
|
|
static int stid135_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
|
|
if (state->base->mode == 0)
|
|
{
|
|
if (voltage == SEC_VOLTAGE_18)
|
|
state->rf_in |= 2;
|
|
else
|
|
state->rf_in &= ~2;
|
|
return 0;
|
|
}
|
|
|
|
if (state->base->set_voltage)
|
|
state->base->set_voltage(state->base->i2c, voltage, state->rf_in);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int stid135_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
fe_lla_error_t err = FE_LLA_NO_ERROR;
|
|
|
|
if (state->base->mode == 0)
|
|
{
|
|
if (tone == SEC_TONE_ON)
|
|
state->rf_in |= 1;
|
|
else
|
|
state->rf_in &= ~1;
|
|
|
|
return 0;
|
|
}
|
|
if(state->base->control_22k==false) //for 6916 demod1 ,disable the 22k function.
|
|
return 0;
|
|
mutex_lock(&state->base->status_lock);
|
|
err = fe_stid135_set_22khz_cont(state->base->handle,state->rf_in + 1, tone == SEC_TONE_ON);
|
|
mutex_unlock(&state->base->status_lock);
|
|
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_err(&state->base->i2c->dev, "%s: fe_stid135_set_22khz_cont error %d !\n", __func__, err);
|
|
|
|
return err != FE_LLA_NO_ERROR ? -1 : 0;
|
|
}
|
|
|
|
static int stid135_send_master_cmd(struct dvb_frontend *fe,
|
|
struct dvb_diseqc_master_cmd *cmd)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
fe_lla_error_t err = FE_LLA_NO_ERROR;
|
|
|
|
#if 0
|
|
if (state->base->mode == 0)
|
|
return 0;
|
|
#endif
|
|
|
|
mutex_lock(&state->base->status_lock);
|
|
err |= fe_stid135_diseqc_init(state->base->handle, state->rf_in + 1, FE_SAT_DISEQC_2_3_PWM);
|
|
err |= fe_stid135_diseqc_send(state->base->handle, state->rf_in + 1, cmd->msg, cmd->msg_len);
|
|
mutex_unlock(&state->base->status_lock);
|
|
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_err(&state->base->i2c->dev, "%s: fe_stid135_diseqc_send error %d !\n", __func__, err);
|
|
|
|
return err != FE_LLA_NO_ERROR ? -1 : 0;
|
|
}
|
|
|
|
static int stid135_recv_slave_reply(struct dvb_frontend *fe,
|
|
struct dvb_diseqc_slave_reply *reply)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
fe_lla_error_t err = FE_LLA_NO_ERROR;
|
|
|
|
#if 0
|
|
if (state->base->mode == 0)
|
|
return 0;
|
|
#endif
|
|
|
|
mutex_lock(&state->base->status_lock);
|
|
err = fe_stid135_diseqc_receive(state->base->handle, reply->msg, &reply->msg_len);
|
|
mutex_unlock(&state->base->status_lock);
|
|
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_err(&state->base->i2c->dev, "%s: fe_stid135_diseqc_receive error %d !\n", __func__, err);
|
|
|
|
return err != FE_LLA_NO_ERROR ? -1 : 0;
|
|
}
|
|
|
|
static int stid135_send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd burst)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
fe_lla_error_t err = FE_LLA_NO_ERROR;
|
|
|
|
if (state->base->mode == 0)
|
|
return 0;
|
|
|
|
return err != FE_LLA_NO_ERROR ? -1 : 0;
|
|
}
|
|
|
|
static int stid135_sleep(struct dvb_frontend *fe)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
fe_lla_error_t err = FE_LLA_NO_ERROR;
|
|
struct fe_stid135_internal_param *p_params = state->base->handle;;
|
|
|
|
if (state->base->mode == 0 || state->base->set_voltage)
|
|
return 0;
|
|
|
|
dev_dbg(&state->base->i2c->dev, "%s: tuner %d\n", __func__, state->rf_in);
|
|
|
|
err = FE_STiD135_TunerStandby(p_params->handle_demod, state->rf_in + 1, 0);
|
|
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_warn(&state->base->i2c->dev, "%s: STiD135 standby tuner %d failed!\n", __func__, state->rf_in);
|
|
|
|
return err != FE_LLA_NO_ERROR ? -1 : 0;
|
|
}
|
|
|
|
static int stid135_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
|
{
|
|
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
|
int i;
|
|
|
|
*strength = 0;
|
|
for (i=0; i < p->strength.len; i++) {
|
|
if (p->strength.stat[i].scale == FE_SCALE_RELATIVE)
|
|
*strength = (u16)p->strength.stat[i].uvalue;
|
|
else if (p->strength.stat[i].scale == FE_SCALE_DECIBEL)
|
|
*strength = ((100000 + (s32)p->strength.stat[i].svalue)/1000) * 656;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int stid135_read_snr(struct dvb_frontend *fe, u16 *snr)
|
|
{
|
|
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
|
int i;
|
|
|
|
*snr = 0;
|
|
for (i=0; i < p->cnr.len; i++)
|
|
if (p->cnr.stat[i].scale == FE_SCALE_RELATIVE)
|
|
*snr = (u16)p->cnr.stat[i].uvalue;
|
|
return 0;
|
|
}
|
|
|
|
static int stid135_read_ber(struct dvb_frontend *fe, u32 *ber)
|
|
{
|
|
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
|
int i;
|
|
|
|
*ber = 1;
|
|
for (i=0; i < p->post_bit_error.len; i++)
|
|
if ( p->post_bit_error.stat[0].scale == FE_SCALE_COUNTER )
|
|
*ber = (u32)p->post_bit_error.stat[0].uvalue;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int stid135_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
|
{
|
|
*ucblocks = 0;
|
|
return 0;
|
|
}
|
|
|
|
static void spi_read(struct dvb_frontend *fe, struct ecp3_info *ecp3inf)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
struct i2c_adapter *adapter = state->base->i2c;
|
|
|
|
if (state->base->read_properties)
|
|
state->base->read_properties(adapter,ecp3inf->reg, &(ecp3inf->data));
|
|
return ;
|
|
}
|
|
|
|
static void spi_write(struct dvb_frontend *fe,struct ecp3_info *ecp3inf)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
struct i2c_adapter *adapter = state->base->i2c;
|
|
|
|
if (state->base->write_properties)
|
|
state->base->write_properties(adapter,ecp3inf->reg, ecp3inf->data);
|
|
return ;
|
|
}
|
|
|
|
static void eeprom_read(struct dvb_frontend *fe, struct eeprom_info *eepinf)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
struct i2c_adapter *adapter = state->base->i2c;
|
|
|
|
if (state->base->read_eeprom)
|
|
state->base->read_eeprom(adapter,eepinf->reg, &(eepinf->data));
|
|
return ;
|
|
}
|
|
|
|
static void eeprom_write(struct dvb_frontend *fe,struct eeprom_info *eepinf)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
struct i2c_adapter *adapter = state->base->i2c;
|
|
|
|
if (state->base->write_eeprom)
|
|
state->base->write_eeprom(adapter,eepinf->reg, eepinf->data);
|
|
return ;
|
|
}
|
|
|
|
static int stid135_read_temp(struct dvb_frontend *fe, s16 *temp)
|
|
{
|
|
struct stv *state = fe->demodulator_priv;
|
|
fe_lla_error_t err = FE_LLA_NO_ERROR;
|
|
|
|
mutex_lock(&state->base->status_lock);
|
|
err = fe_stid135_get_soc_temperature(state->base->handle, temp);
|
|
mutex_unlock(&state->base->status_lock);
|
|
|
|
if (err != FE_LLA_NO_ERROR)
|
|
dev_warn(&state->base->i2c->dev, "%s: fe_stid135_get_soc_temperature error %d !\n", __func__, err);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static struct dvb_frontend_ops stid135_ops = {
|
|
.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
|
|
.info = {
|
|
.name = "STiD135 Multistandard",
|
|
.frequency_min_hz = 950 * MHz,
|
|
.frequency_max_hz = 2150 * MHz,
|
|
.symbol_rate_min = 100000,
|
|
.symbol_rate_max = 520000000,
|
|
.caps = FE_CAN_INVERSION_AUTO |
|
|
FE_CAN_FEC_AUTO |
|
|
FE_CAN_QPSK |
|
|
FE_CAN_2G_MODULATION |
|
|
FE_CAN_MULTISTREAM
|
|
},
|
|
.init = stid135_init,
|
|
.sleep = stid135_sleep,
|
|
.release = stid135_release,
|
|
.get_frontend_algo = stid135_get_algo,
|
|
.get_frontend = stid135_get_frontend,
|
|
.tune = stid135_tune,
|
|
.set_tone = stid135_set_tone,
|
|
.set_voltage = stid135_set_voltage,
|
|
|
|
.diseqc_send_master_cmd = stid135_send_master_cmd,
|
|
.diseqc_send_burst = stid135_send_burst,
|
|
.diseqc_recv_slave_reply = stid135_recv_slave_reply,
|
|
|
|
.read_status = stid135_read_status,
|
|
.read_signal_strength = stid135_read_signal_strength,
|
|
.read_snr = stid135_read_snr,
|
|
.read_ber = stid135_read_ber,
|
|
.read_ucblocks = stid135_read_ucblocks,
|
|
.spi_read = spi_read,
|
|
.spi_write = spi_write,
|
|
.eeprom_read = eeprom_read,
|
|
.eeprom_write = eeprom_write,
|
|
.read_temp = stid135_read_temp,
|
|
};
|
|
|
|
static struct stv_base *match_base(struct i2c_adapter *i2c, u8 adr)
|
|
{
|
|
struct stv_base *p;
|
|
|
|
list_for_each_entry(p, &stvlist, stvlist)
|
|
if (p->i2c == i2c && p->adr == adr)
|
|
return p;
|
|
return NULL;
|
|
}
|
|
|
|
struct dvb_frontend *stid135_attach(struct i2c_adapter *i2c,
|
|
struct stid135_cfg *cfg,
|
|
int nr, int rf_in)
|
|
{
|
|
struct stv *state;
|
|
struct stv_base *base;
|
|
|
|
state = kzalloc(sizeof(struct stv), GFP_KERNEL);
|
|
if (!state)
|
|
return NULL;
|
|
|
|
base = match_base(i2c, cfg->adr);
|
|
if (base) {
|
|
base->count++;
|
|
state->base = base;
|
|
} else {
|
|
base = kzalloc(sizeof(struct stv_base), GFP_KERNEL);
|
|
if (!base)
|
|
goto fail;
|
|
base->i2c = i2c;
|
|
base->adr = cfg->adr;
|
|
base->count = 1;
|
|
base->extclk = cfg->clk;
|
|
base->ts_mode = cfg->ts_mode;
|
|
base->set_voltage = cfg->set_voltage;
|
|
base->mode = cfg->set_voltage ? mode : 1;
|
|
base->write_properties = cfg->write_properties;
|
|
base->read_properties = cfg->read_properties;
|
|
base->write_eeprom = cfg->write_eeprom;
|
|
base->read_eeprom = cfg->read_eeprom;
|
|
base->set_TSsampling = cfg->set_TSsampling;
|
|
base->set_TSparam = cfg->set_TSparam;
|
|
base->vglna = cfg->vglna; //for stvvglna 6909x v2 6903x v2
|
|
base->control_22k = cfg->control_22k;
|
|
|
|
mutex_init(&base->status_lock);
|
|
|
|
state->base = base;
|
|
if (stid135_probe(state) < 0) {
|
|
dev_warn(&i2c->dev, "No demod found at adr %02X on %s\n",
|
|
cfg->adr, dev_name(&i2c->dev));
|
|
kfree(base);
|
|
goto fail;
|
|
}
|
|
list_add(&base->stvlist, &stvlist);
|
|
}
|
|
state->fe.ops = stid135_ops;
|
|
state->fe.demodulator_priv = state;
|
|
state->nr = nr;
|
|
state->newTP = false;
|
|
state->bit_rate = 0;
|
|
state->loops = 15;
|
|
state->modcode_filter = false;
|
|
|
|
if (rfsource > 0 && rfsource < 5)
|
|
rf_in = rfsource - 1;
|
|
state->rf_in = base->mode ? rf_in : 0;
|
|
|
|
if (base->mode == 2)
|
|
state->rf_in = 3;
|
|
|
|
if (timeout < 1)
|
|
timeout = 1;
|
|
|
|
if (timeout > 20)
|
|
timeout = 20;
|
|
|
|
dev_info(&i2c->dev, "%s demod found at adr %02X on %s\n",
|
|
state->fe.ops.info.name, cfg->adr, dev_name(&i2c->dev));
|
|
|
|
return &state->fe;
|
|
|
|
fail:
|
|
kfree(state);
|
|
return NULL;
|
|
}
|
|
EXPORT_SYMBOL_GPL(stid135_attach);
|
|
|
|
MODULE_DESCRIPTION("STiD135 driver");
|
|
MODULE_AUTHOR("CrazyCat");
|
|
MODULE_LICENSE("GPL");
|