#define dprintk(level, fmt, arg...) do { \ if (debug >= level) \
printk(KERN_DEBUG KBUILD_MODNAME ": %s " fmt, __func__, ##arg); \
} while (0)
staticinline u32 Frac28a(u32 a, u32 c)
{ int i = 0;
u32 Q1 = 0;
u32 R0 = 0;
R0 = (a % c) << 4; /* 32-28 == 4 shifts possible at max */
Q1 = a / c; /* * integer part, only the 4 least significant * bits will be visible in the result
*/
/* division using radix 16, 7 nibbles in the result */ for (i = 0; i < 7; i++) {
Q1 = (Q1 << 4) | (R0 / c);
R0 = (R0 % c) << 4;
} /* rounding */ if ((R0 >> 3) >= c)
Q1++;
staticint power_up_device(struct drxk_state *state)
{ int status;
u8 data = 0;
u16 retry_count = 0;
dprintk(1, "\n");
status = i2c_read1(state, state->demod_address, &data); if (status < 0) { do {
data = 0;
status = i2c_write(state, state->demod_address,
&data, 1);
usleep_range(10000, 11000);
retry_count++; if (status < 0) continue;
status = i2c_read1(state, state->demod_address,
&data);
} while (status < 0 &&
(retry_count < DRXK_MAX_RETRIES_POWERUP)); if (status < 0 && retry_count >= DRXK_MAX_RETRIES_POWERUP) goto error;
}
/* Make sure all clk domains are active */
status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_NONE); if (status < 0) goto error;
status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); if (status < 0) goto error; /* Enable pll lock tests */
status = write16(state, SIO_CC_PLL_LOCK__A, 1); if (status < 0) goto error;
state->m_current_power_mode = DRX_POWER_UP;
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__);
return status;
}
staticint init_state(struct drxk_state *state)
{ /* * FIXME: most (all?) of the values below should be moved into * struct drxk_config, as they are probably board-specific
*/
u32 ul_vsb_if_agc_mode = DRXK_AGC_CTRL_AUTO;
u32 ul_vsb_if_agc_output_level = 0;
u32 ul_vsb_if_agc_min_level = 0;
u32 ul_vsb_if_agc_max_level = 0x7FFF;
u32 ul_vsb_if_agc_speed = 3;
if (!enable) {
desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF;
desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN;
}
status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); if (status >= 0 && data == desired_status) { /* tokenring already has correct status */ return status;
} /* Disable/enable dvbt tokenring bridge */
status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desired_ctrl);
end = jiffies + msecs_to_jiffies(DRXK_OFDM_TR_SHUTDOWN_TIMEOUT); do {
status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); if ((status >= 0 && data == desired_status)
|| time_is_after_jiffies(end)) break;
usleep_range(1000, 2000);
} while (1); if (data != desired_status) {
pr_err("SIO not ready\n"); return -EINVAL;
} return status;
}
staticint mpegts_stop(struct drxk_state *state)
{ int status = 0;
u16 fec_oc_snc_mode = 0;
u16 fec_oc_ipr_mode = 0;
dprintk(1, "\n");
/* Graceful shutdown (byte boundaries) */
status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode); if (status < 0) goto error;
fec_oc_snc_mode |= FEC_OC_SNC_MODE_SHUTDOWN__M;
status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode); if (status < 0) goto error;
/* Suppress MCLK during absence of data */
status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode); if (status < 0) goto error;
fec_oc_ipr_mode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M;
status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode);
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__);
return status;
}
staticint scu_command(struct drxk_state *state,
u16 cmd, u8 parameter_len,
u16 *parameter, u8 result_len, u16 *result)
{ #if (SCU_RAM_PARAM_0__A - SCU_RAM_PARAM_15__A) != 15 #error DRXK register mapping no longer compatible with this routine! #endif
u16 cur_cmd = 0; int status = -EINVAL; unsignedlong end;
u8 buffer[34]; int cnt = 0, ii; constchar *p; char errname[30];
/* assume that the command register is ready
since it is checked afterwards */ if (parameter) { for (ii = parameter_len - 1; ii >= 0; ii -= 1) {
buffer[cnt++] = (parameter[ii] & 0xFF);
buffer[cnt++] = ((parameter[ii] >> 8) & 0xFF);
}
}
buffer[cnt++] = (cmd & 0xFF);
buffer[cnt++] = ((cmd >> 8) & 0xFF);
write_block(state, SCU_RAM_PARAM_0__A -
(parameter_len - 1), cnt, buffer); /* Wait until SCU has processed command */
end = jiffies + msecs_to_jiffies(DRXK_MAX_WAITTIME); do {
usleep_range(1000, 2000);
status = read16(state, SCU_RAM_COMMAND__A, &cur_cmd); if (status < 0) goto error;
} while (!(cur_cmd == DRX_SCU_READY) && (time_is_after_jiffies(end))); if (cur_cmd != DRX_SCU_READY) {
pr_err("SCU not ready\n");
status = -EIO; goto error2;
} /* read results */ if ((result_len > 0) && (result != NULL)) {
s16 err; int ii;
for (ii = result_len - 1; ii >= 0; ii -= 1) {
status = read16(state, SCU_RAM_PARAM_0__A - ii,
&result[ii]); if (status < 0) goto error;
}
/* Check if an error was reported by SCU */
err = (s16)result[0]; if (err >= 0) goto error;
/* check for the known error codes */ switch (err) { case SCU_RESULT_UNKCMD:
p = "SCU_RESULT_UNKCMD"; break; case SCU_RESULT_UNKSTD:
p = "SCU_RESULT_UNKSTD"; break; case SCU_RESULT_SIZE:
p = "SCU_RESULT_SIZE"; break; case SCU_RESULT_INVPAR:
p = "SCU_RESULT_INVPAR"; break; default: /* Other negative values are errors */
sprintf(errname, "ERROR: %d\n", err);
p = errname;
}
pr_err("%s while sending cmd 0x%04x with params:", p, cmd);
print_hex_dump_bytes("drxk: ", DUMP_PREFIX_NONE, buffer, cnt);
status = -EINVAL; goto error2;
}
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__);
error2:
mutex_unlock(&state->mutex); return status;
}
staticint set_iqm_af(struct drxk_state *state, bool active)
{
u16 data = 0; int status;
dprintk(1, "\n");
/* Configure IQM */
status = read16(state, IQM_AF_STDBY__A, &data); if (status < 0) goto error;
if (!active) {
data |= (IQM_AF_STDBY_STDBY_ADC_STANDBY
| IQM_AF_STDBY_STDBY_AMP_STANDBY
| IQM_AF_STDBY_STDBY_PD_STANDBY
| IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY
| IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY);
} else {
data &= ((~IQM_AF_STDBY_STDBY_ADC_STANDBY)
& (~IQM_AF_STDBY_STDBY_AMP_STANDBY)
& (~IQM_AF_STDBY_STDBY_PD_STANDBY)
& (~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY)
& (~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY)
);
}
status = write16(state, IQM_AF_STDBY__A, data);
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
staticint ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode)
{ int status = 0;
u16 sio_cc_pwd_mode = 0;
dprintk(1, "\n");
/* Check arguments */ if (mode == NULL) return -EINVAL;
switch (*mode) { case DRX_POWER_UP:
sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE; break; case DRXK_POWER_DOWN_OFDM:
sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OFDM; break; case DRXK_POWER_DOWN_CORE:
sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK; break; case DRXK_POWER_DOWN_PLL:
sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL; break; case DRX_POWER_DOWN:
sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC; break; default: /* Unknown sleep mode */ return -EINVAL;
}
/* If already in requested power mode, do nothing */ if (state->m_current_power_mode == *mode) return 0;
/* For next steps make sure to start from DRX_POWER_UP mode */ if (state->m_current_power_mode != DRX_POWER_UP) {
status = power_up_device(state); if (status < 0) goto error;
status = dvbt_enable_ofdm_token_ring(state, true); if (status < 0) goto error;
}
if (*mode == DRX_POWER_UP) { /* Restore analog & pin configuration */
} else { /* Power down to requested mode */ /* Backup some register settings */ /* Set pins with possible pull-ups connected
to them in input mode */ /* Analog power down */ /* ADC power down */ /* Power down device */ /* stop all comm_exec */ /* Stop and power down previous standard */ switch (state->m_operation_mode) { case OM_DVBT:
status = mpegts_stop(state); if (status < 0) goto error;
status = power_down_dvbt(state, false); if (status < 0) goto error; break; case OM_QAM_ITU_A: case OM_QAM_ITU_C:
status = mpegts_stop(state); if (status < 0) goto error;
status = power_down_qam(state); if (status < 0) goto error; break; default: break;
}
status = dvbt_enable_ofdm_token_ring(state, false); if (status < 0) goto error;
status = write16(state, SIO_CC_PWD_MODE__A, sio_cc_pwd_mode); if (status < 0) goto error;
status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); if (status < 0) goto error;
if (*mode != DRXK_POWER_DOWN_OFDM) {
state->m_hi_cfg_ctrl |=
SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
status = hi_cfg_command(state); if (status < 0) goto error;
}
}
state->m_current_power_mode = *mode;
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__);
status = read16(state, SCU_COMM_EXEC__A, &data); if (status < 0) goto error; if (data == SCU_COMM_EXEC_ACTIVE) { /* Send OFDM stop command */
status = scu_command(state,
SCU_RAM_COMMAND_STANDARD_OFDM
| SCU_RAM_COMMAND_CMD_DEMOD_STOP,
0, NULL, 1, &cmd_result); if (status < 0) goto error; /* Send OFDM reset command */
status = scu_command(state,
SCU_RAM_COMMAND_STANDARD_OFDM
| SCU_RAM_COMMAND_CMD_DEMOD_RESET,
0, NULL, 1, &cmd_result); if (status < 0) goto error;
}
/* Reset datapath for OFDM, processors first */
status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP); if (status < 0) goto error;
status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP); if (status < 0) goto error;
status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP); if (status < 0) goto error;
/* powerdown AFE */
status = set_iqm_af(state, false); if (status < 0) goto error;
/* powerdown to OFDM mode */ if (set_power_mode) {
status = ctrl_power_mode(state, &power_mode); if (status < 0) goto error;
}
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
staticint setoperation_mode(struct drxk_state *state, enum operation_mode o_mode)
{ int status = 0;
dprintk(1, "\n"); /* Stop and power down previous standard TODO investigate total power down instead of partial power down depending on "previous" standard.
*/
/* disable HW lock indicator */
status = write16(state, SCU_RAM_GPIO__A,
SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error;
/* Device is already at the required mode */ if (state->m_operation_mode == o_mode) return 0;
switch (state->m_operation_mode) { /* OM_NONE was added for start up */ case OM_NONE: break; case OM_DVBT:
status = mpegts_stop(state); if (status < 0) goto error;
status = power_down_dvbt(state, true); if (status < 0) goto error;
state->m_operation_mode = OM_NONE; break; case OM_QAM_ITU_A: case OM_QAM_ITU_C:
status = mpegts_stop(state); if (status < 0) goto error;
status = power_down_qam(state); if (status < 0) goto error;
state->m_operation_mode = OM_NONE; break; case OM_QAM_ITU_B: default:
status = -EINVAL; goto error;
}
/* Power up new standard
*/ switch (o_mode) { case OM_DVBT:
dprintk(1, ": DVB-T\n");
state->m_operation_mode = o_mode;
status = set_dvbt_standard(state, o_mode); if (status < 0) goto error; break; case OM_QAM_ITU_A: case OM_QAM_ITU_C:
dprintk(1, ": DVB-C Annex %c\n",
(state->m_operation_mode == OM_QAM_ITU_A) ? 'A' : 'C');
state->m_operation_mode = o_mode;
status = set_qam_standard(state, o_mode); if (status < 0) goto error; break; case OM_QAM_ITU_B: default:
status = -EINVAL;
}
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
staticint start(struct drxk_state *state, s32 offset_freq,
s32 intermediate_frequency)
{ int status = -EINVAL;
/* Check insertion of the Reed-Solomon parity bytes */
status = read16(state, FEC_OC_MODE__A, &fec_oc_reg_mode); if (status < 0) goto error;
status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode); if (status < 0) goto error;
fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M);
fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); if (state->m_insert_rs_byte) { /* enable parity symbol forward */
fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M; /* MVAL disable during parity bytes */
fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M; /* TS burst length to 204 */
fec_oc_dto_burst_len = 204;
}
/* Check serial or parallel output */
fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); if (!state->m_enable_parallel) { /* MPEG data output is serial -> set ipr_mode[0] */
fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M;
}
switch (o_mode) { case OM_DVBT:
max_bit_rate = state->m_dvbt_bitrate;
fec_oc_tmd_mode = 3;
fec_oc_rcn_ctl_rate = 0xC00000;
static_clk = state->m_dvbt_static_clk; break; case OM_QAM_ITU_A: case OM_QAM_ITU_C:
fec_oc_tmd_mode = 0x0004;
fec_oc_rcn_ctl_rate = 0xD2B4EE; /* good for >63 Mb/s */
max_bit_rate = state->m_dvbc_bitrate;
static_clk = state->m_dvbc_static_clk; break; default:
status = -EINVAL;
} /* switch (standard) */ if (status < 0) goto error;
staticint set_agc_rf(struct drxk_state *state, struct s_cfg_agc *p_agc_cfg, bool is_dtv)
{ int status = -EINVAL;
u16 data = 0; struct s_cfg_agc *p_if_agc_settings;
dprintk(1, "\n");
if (p_agc_cfg == NULL) goto error;
switch (p_agc_cfg->ctrl_mode) { case DRXK_AGC_CTRL_AUTO: /* Enable RF AGC DAC */
status = read16(state, IQM_AF_STDBY__A, &data); if (status < 0) goto error;
data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
status = write16(state, IQM_AF_STDBY__A, data); if (status < 0) goto error;
status = read16(state, SCU_RAM_AGC_CONFIG__A, &data); if (status < 0) goto error;
/* Enable SCU RF AGC loop */
data &= ~SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
/* Polarity */ if (state->m_rf_agc_pol)
data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M; else
data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
status = write16(state, SCU_RAM_AGC_CONFIG__A, data); if (status < 0) goto error;
/* Set speed (using complementary reduction value) */
status = read16(state, SCU_RAM_AGC_KI_RED__A, &data); if (status < 0) goto error;
data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M;
data |= (~(p_agc_cfg->speed <<
SCU_RAM_AGC_KI_RED_RAGC_RED__B)
& SCU_RAM_AGC_KI_RED_RAGC_RED__M);
status = write16(state, SCU_RAM_AGC_KI_RED__A, data); if (status < 0) goto error;
if (is_dvbt(state))
p_if_agc_settings = &state->m_dvbt_if_agc_cfg; elseif (is_qam(state))
p_if_agc_settings = &state->m_qam_if_agc_cfg; else
p_if_agc_settings = &state->m_atv_if_agc_cfg; if (p_if_agc_settings == NULL) {
status = -EINVAL; goto error;
}
/* Set TOP, only if IF-AGC is in AUTO mode */ if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) {
status = write16(state,
SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
p_agc_cfg->top); if (status < 0) goto error;
}
/* Cut-Off current */
status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A,
p_agc_cfg->cut_off_current); if (status < 0) goto error;
/* Max. output level */
status = write16(state, SCU_RAM_AGC_RF_MAX__A,
p_agc_cfg->max_output_level); if (status < 0) goto error;
break;
case DRXK_AGC_CTRL_USER: /* Enable RF AGC DAC */
status = read16(state, IQM_AF_STDBY__A, &data); if (status < 0) goto error;
data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
status = write16(state, IQM_AF_STDBY__A, data); if (status < 0) goto error;
/* Disable SCU RF AGC loop */
status = read16(state, SCU_RAM_AGC_CONFIG__A, &data); if (status < 0) goto error;
data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M; if (state->m_rf_agc_pol)
data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M; else
data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
status = write16(state, SCU_RAM_AGC_CONFIG__A, data); if (status < 0) goto error;
/* SCU c.o.c. to 0, enabling full control range */
status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, 0); if (status < 0) goto error;
/* Write value to output pin */
status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A,
p_agc_cfg->output_level); if (status < 0) goto error; break;
case DRXK_AGC_CTRL_OFF: /* Disable RF AGC DAC */
status = read16(state, IQM_AF_STDBY__A, &data); if (status < 0) goto error;
data |= IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
status = write16(state, IQM_AF_STDBY__A, data); if (status < 0) goto error;
/* Disable SCU RF AGC loop */
status = read16(state, SCU_RAM_AGC_CONFIG__A, &data); if (status < 0) goto error;
data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
status = write16(state, SCU_RAM_AGC_CONFIG__A, data); if (status < 0) goto error; break;
default:
status = -EINVAL;
}
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
#define SCU_RAM_AGC_KI_INV_IF_POL__M 0x2000
staticint set_agc_if(struct drxk_state *state, struct s_cfg_agc *p_agc_cfg, bool is_dtv)
{
u16 data = 0; int status = 0; struct s_cfg_agc *p_rf_agc_settings;
dprintk(1, "\n");
switch (p_agc_cfg->ctrl_mode) { case DRXK_AGC_CTRL_AUTO:
/* Enable IF AGC DAC */
status = read16(state, IQM_AF_STDBY__A, &data); if (status < 0) goto error;
data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
status = write16(state, IQM_AF_STDBY__A, data); if (status < 0) goto error;
status = read16(state, SCU_RAM_AGC_CONFIG__A, &data); if (status < 0) goto error;
/* Enable SCU IF AGC loop */
data &= ~SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
/* Polarity */ if (state->m_if_agc_pol)
data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M; else
data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
status = write16(state, SCU_RAM_AGC_CONFIG__A, data); if (status < 0) goto error;
/* Set speed (using complementary reduction value) */
status = read16(state, SCU_RAM_AGC_KI_RED__A, &data); if (status < 0) goto error;
data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M;
data |= (~(p_agc_cfg->speed <<
SCU_RAM_AGC_KI_RED_IAGC_RED__B)
& SCU_RAM_AGC_KI_RED_IAGC_RED__M);
status = write16(state, SCU_RAM_AGC_KI_RED__A, data); if (status < 0) goto error;
if (is_qam(state))
p_rf_agc_settings = &state->m_qam_rf_agc_cfg; else
p_rf_agc_settings = &state->m_atv_rf_agc_cfg; if (p_rf_agc_settings == NULL) return -1; /* Restore TOP */
status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
p_rf_agc_settings->top); if (status < 0) goto error; break;
case DRXK_AGC_CTRL_USER:
/* Enable IF AGC DAC */
status = read16(state, IQM_AF_STDBY__A, &data); if (status < 0) goto error;
data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
status = write16(state, IQM_AF_STDBY__A, data); if (status < 0) goto error;
status = read16(state, SCU_RAM_AGC_CONFIG__A, &data); if (status < 0) goto error;
/* Disable SCU IF AGC loop */
data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
/* Polarity */ if (state->m_if_agc_pol)
data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M; else
data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
status = write16(state, SCU_RAM_AGC_CONFIG__A, data); if (status < 0) goto error;
/* Write value to output pin */
status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
p_agc_cfg->output_level); if (status < 0) goto error; break;
case DRXK_AGC_CTRL_OFF:
/* Disable If AGC DAC */
status = read16(state, IQM_AF_STDBY__A, &data); if (status < 0) goto error;
data |= IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
status = write16(state, IQM_AF_STDBY__A, data); if (status < 0) goto error;
/* Disable SCU IF AGC loop */
status = read16(state, SCU_RAM_AGC_CONFIG__A, &data); if (status < 0) goto error;
data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
status = write16(state, SCU_RAM_AGC_CONFIG__A, data); if (status < 0) goto error; break;
} /* switch (agcSettingsIf->ctrl_mode) */
/* always set the top to support
configurations without if-loop */
status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_cfg->top);
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
staticint get_qam_signal_to_noise(struct drxk_state *state,
s32 *p_signal_to_noise)
{ int status = 0;
u16 qam_sl_err_power = 0; /* accum. error between
raw and sliced symbols */
u32 qam_sl_sig_power = 0; /* used for MER, depends of
QAM modulation */
u32 qam_sl_mer = 0; /* QAM MER */
dprintk(1, "\n");
/* MER calculation */
/* get the register value needed for MER */
status = read16(state, QAM_SL_ERR_POWER__A, &qam_sl_err_power); if (status < 0) {
pr_err("Error %d on %s\n", status, __func__); return -EINVAL;
}
switch (state->props.modulation) { case QAM_16:
qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM16 << 2; break; case QAM_32:
qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM32 << 2; break; case QAM_64:
qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM64 << 2; break; case QAM_128:
qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM128 << 2; break; default: case QAM_256:
qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM256 << 2; break;
}
status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A,
&eq_reg_td_tps_pwr_ofs); if (status < 0) goto error;
status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A,
&eq_reg_td_req_smb_cnt); if (status < 0) goto error;
status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A,
&eq_reg_td_sqr_err_exp); if (status < 0) goto error;
status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A,
®_data); if (status < 0) goto error; /* Extend SQR_ERR_I operational range */
eq_reg_td_sqr_err_i = (u32) reg_data; if ((eq_reg_td_sqr_err_exp > 11) &&
(eq_reg_td_sqr_err_i < 0x00000FFFUL)) {
eq_reg_td_sqr_err_i += 0x00010000UL;
}
status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, ®_data); if (status < 0) goto error; /* Extend SQR_ERR_Q operational range */
eq_reg_td_sqr_err_q = (u32) reg_data; if ((eq_reg_td_sqr_err_exp > 11) &&
(eq_reg_td_sqr_err_q < 0x00000FFFUL))
eq_reg_td_sqr_err_q += 0x00010000UL;
status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A,
&transmission_params); if (status < 0) goto error;
/* Check input data for MER */
/* MER calculation (in 0.1 dB) without math.h */ if ((eq_reg_td_tps_pwr_ofs == 0) || (eq_reg_td_req_smb_cnt == 0))
i_mer = 0; elseif ((eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) == 0) { /* No error at all, this must be the HW reset value * Apparently no first measurement yet
* Set MER to 0.0 */
i_mer = 0;
} else {
sqr_err_iq = (eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) <<
eq_reg_td_sqr_err_exp; if ((transmission_params &
OFDM_SC_RA_RAM_OP_PARAM_MODE__M)
== OFDM_SC_RA_RAM_OP_PARAM_MODE_2K)
tps_cnt = 17; else
tps_cnt = 68;
/* IMER = 100 * log10 (x) where x = (eq_reg_td_tps_pwr_ofs^2 * eq_reg_td_req_smb_cnt * tps_cnt)/sqr_err_iq
=> IMER = a + b -c where a = 100 * log10 (eq_reg_td_tps_pwr_ofs^2) b = 100 * log10 (eq_reg_td_req_smb_cnt * tps_cnt) c = 100 * log10 (sqr_err_iq)
*/
/* log(x) x = 9bits * 9bits->18 bits */
a = log10times100(eq_reg_td_tps_pwr_ofs *
eq_reg_td_tps_pwr_ofs); /* log(x) x = 16bits * 7bits->23 bits */
b = log10times100(eq_reg_td_req_smb_cnt * tps_cnt); /* log(x) x = (16bits + 16bits) << 15 ->32 bits */
c = log10times100(sqr_err_iq);
i_mer = a + b - c;
}
*p_signal_to_noise = i_mer;
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
*p_signal_to_noise = 0; switch (state->m_operation_mode) { case OM_DVBT: return get_dvbt_signal_to_noise(state, p_signal_to_noise); case OM_QAM_ITU_A: case OM_QAM_ITU_C: return get_qam_signal_to_noise(state, p_signal_to_noise); default: break;
} return 0;
}
#if 0 staticint get_dvbt_quality(struct drxk_state *state, s32 *p_quality)
{ /* SNR Values for quasi errorfree reception rom Nordig 2.2 */ int status = 0;
if (image_to_select)
state->m_iqm_fs_rate_ofs = ~state->m_iqm_fs_rate_ofs + 1;
/* Program frequency shifter with tuner offset compensation */ /* frequency_shift += tuner_freq_offset; TODO */
status = write32(state, IQM_FS_RATE_OFS_LO__A,
state->m_iqm_fs_rate_ofs); if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
/* AGCInit() not available for DVBT; init done in microcode */ if (!is_qam(state)) {
pr_err("%s: mode %d is not DVB-C\n",
__func__, state->m_operation_mode); return -EINVAL;
}
/* FIXME: Analog TV AGC require different settings */
status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A,
fast_clp_ctrl_delay); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingain_tgt); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingain_tgt_min); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A,
if_iaccu_hi_tgt_min); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A,
if_iaccu_hi_tgt_max); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_IF_IACCU_HI__A, 0); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_IF_IACCU_LO__A, 0); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, 0); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_RF_IACCU_LO__A, 0); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A,
ki_innergain_min); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A,
if_iaccu_hi_tgt); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clp_cyclen); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MAX__A, 1023); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MIN__A, (u16) -1023); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clp_sum_min); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, sns_sum_min); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_KI_MIN__A, 0x0117); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_KI_MAX__A, 0x0657); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_CLP_SUM__A, 0); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_CLP_CYCCNT__A, 0); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_CLP_DIR_WD__A, 0); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_CLP_DIR_STP__A, 1); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_SNS_SUM__A, 0); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_SNS_CYCCNT__A, 0); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_SNS_DIR_WD__A, 0); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_SNS_DIR_STP__A, 1); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_SNS_CYCLEN__A, 500); if (status < 0) goto error;
status = write16(state, SCU_RAM_AGC_KI_CYCLEN__A, 500); if (status < 0) goto error;
/* Initialize inner-loop KI gain factors */
status = read16(state, SCU_RAM_AGC_KI__A, &data); if (status < 0) goto error;
data = 0x0657;
data &= ~SCU_RAM_AGC_KI_RF__M;
data |= (DRXK_KI_RAGC_QAM << SCU_RAM_AGC_KI_RF__B);
data &= ~SCU_RAM_AGC_KI_IF__M;
data |= (DRXK_KI_IAGC_QAM << SCU_RAM_AGC_KI_IF__B);
status = write16(state, SCU_RAM_AGC_KI__A, data);
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
staticint dvbtqam_get_acc_pkt_err(struct drxk_state *state, u16 *packet_err)
{ int status;
dprintk(1, "\n"); if (packet_err == NULL)
status = write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0); else
status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A,
packet_err); if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
dprintk(1, "\n");
status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_exec); if (sc_exec != 1) { /* SC is not running */
status = -EINVAL;
} if (status < 0) goto error;
/* Wait until sc is ready to receive command */
retry_cnt = 0; do {
usleep_range(1000, 2000);
status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd);
retry_cnt++;
} while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0)) goto error;
/* Write sub-command */ switch (cmd) { /* All commands using sub-cmd */ case OFDM_SC_RA_RAM_CMD_PROC_START: case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM: case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
status = write16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, subcmd); if (status < 0) goto error; break; default: /* Do nothing */ break;
}
/* Write needed parameters and the command */
status = 0; switch (cmd) { /* All commands using 5 parameters */ /* All commands using 4 parameters */ /* All commands using 3 parameters */ /* All commands using 2 parameters */ case OFDM_SC_RA_RAM_CMD_PROC_START: case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM: case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
status |= write16(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
fallthrough; /* All commands using 1 parameters */ case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING: case OFDM_SC_RA_RAM_CMD_USER_IO:
status |= write16(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
fallthrough; /* All commands using 0 parameters */ case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM: case OFDM_SC_RA_RAM_CMD_NULL: /* Write command */
status |= write16(state, OFDM_SC_RA_RAM_CMD__A, cmd); break; default: /* Unknown command */
status = -EINVAL;
} if (status < 0) goto error;
/* Wait until sc is ready processing command */
retry_cnt = 0; do {
usleep_range(1000, 2000);
status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd);
retry_cnt++;
} while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0)) goto error;
/* Check for illegal cmd */
status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &err_code); if (err_code == 0xFFFF) { /* illegal command */
status = -EINVAL;
} if (status < 0) goto error;
/* Retrieve results parameters from SC */ switch (cmd) { /* All commands yielding 5 results */ /* All commands yielding 4 results */ /* All commands yielding 3 results */ /* All commands yielding 2 results */ /* All commands yielding 1 result */ case OFDM_SC_RA_RAM_CMD_USER_IO: case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
status = read16(state, OFDM_SC_RA_RAM_PARAM0__A, &(param0)); break; /* All commands yielding 0 results */ case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING: case OFDM_SC_RA_RAM_CMD_SET_TIMER: case OFDM_SC_RA_RAM_CMD_PROC_START: case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM: case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM: case OFDM_SC_RA_RAM_CMD_NULL: break; default: /* Unknown command */
status = -EINVAL; break;
} /* switch (cmd->cmd) */
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
/* * \brief Initialize channelswitch-independent settings for DVBT. * \param demod instance of demodulator. * \return DRXStatus_t. * * For ROM code channel filter taps are loaded from the bootloader. For microcode * the DVB-T taps from the drxk_filters.h are used.
*/ staticint set_dvbt_standard(struct drxk_state *state, enum operation_mode o_mode)
{
u16 cmd_result = 0;
u16 data = 0; int status;
/* reset datapath for OFDM, processors first */
status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP); if (status < 0) goto error;
status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP); if (status < 0) goto error;
status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP); if (status < 0) goto error;
/* IQM setup */ /* synchronize on ofdstate->m_festart */
status = write16(state, IQM_AF_UPD_SEL__A, 1); if (status < 0) goto error; /* window size for clipping ADC detection */
status = write16(state, IQM_AF_CLP_LEN__A, 0); if (status < 0) goto error; /* window size for sense pre-SAW detection */
status = write16(state, IQM_AF_SNS_LEN__A, 0); if (status < 0) goto error; /* sense threshold for sense pre-SAW detection */
status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC); if (status < 0) goto error;
status = set_iqm_af(state, true); if (status < 0) goto error;
status = write16(state, IQM_AF_AGC_RF__A, 0); if (status < 0) goto error;
/* Impulse noise cruncher setup */
status = write16(state, IQM_AF_INC_LCT__A, 0); /* crunch in IQM_CF */ if (status < 0) goto error;
status = write16(state, IQM_CF_DET_LCT__A, 0); /* detect in IQM_CF */ if (status < 0) goto error;
status = write16(state, IQM_CF_WND_LEN__A, 3); /* peak detector window length */ if (status < 0) goto error;
status = write16(state, IQM_RC_STRETCH__A, 16); if (status < 0) goto error;
status = write16(state, IQM_CF_OUT_ENA__A, 0x4); /* enable output 2 */ if (status < 0) goto error;
status = write16(state, IQM_CF_DS_ENA__A, 0x4); /* decimate output 2 */ if (status < 0) goto error;
status = write16(state, IQM_CF_SCALE__A, 1600); if (status < 0) goto error;
status = write16(state, IQM_CF_SCALE_SH__A, 0); if (status < 0) goto error;
/* virtual clipping threshold for clipping ADC detection */
status = write16(state, IQM_AF_CLP_TH__A, 448); if (status < 0) goto error;
status = write16(state, IQM_CF_DATATH__A, 495); /* crunching threshold */ if (status < 0) goto error;
status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT,
DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); if (status < 0) goto error;
status = write16(state, IQM_CF_PKDTH__A, 2); /* peak detector threshold */ if (status < 0) goto error;
status = write16(state, IQM_CF_POW_MEAS_LEN__A, 2); if (status < 0) goto error; /* enable power measurement interrupt */
status = write16(state, IQM_CF_COMM_INT_MSK__A, 1); if (status < 0) goto error;
status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE); if (status < 0) goto error;
/* IQM will not be reset from here, sync ADC and update/init AGC */
status = adc_synchronization(state); if (status < 0) goto error;
status = set_pre_saw(state, &state->m_dvbt_pre_saw_cfg); if (status < 0) goto error;
/* Halt SCU to enable safe non-atomic accesses */
status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD); if (status < 0) goto error;
status = set_agc_rf(state, &state->m_dvbt_rf_agc_cfg, true); if (status < 0) goto error;
status = set_agc_if(state, &state->m_dvbt_if_agc_cfg, true); if (status < 0) goto error;
/* Set Noise Estimation notch width and enable DC fix */
status = read16(state, OFDM_SC_RA_RAM_CONFIG__A, &data); if (status < 0) goto error;
data |= OFDM_SC_RA_RAM_CONFIG_NE_FIX_ENABLE__M;
status = write16(state, OFDM_SC_RA_RAM_CONFIG__A, data); if (status < 0) goto error;
/* Activate SCU to enable SCU commands */
status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); if (status < 0) goto error;
if (!state->m_drxk_a3_rom_code) { /* AGCInit() is not done for DVBT, so set agcfast_clip_ctrl_delay */
status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A,
state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay); if (status < 0) goto error;
}
/* OFDM_SC setup */ #ifdef COMPILE_FOR_NONRT
status = write16(state, OFDM_SC_RA_RAM_BE_OPT_DELAY__A, 1); if (status < 0) goto error;
status = write16(state, OFDM_SC_RA_RAM_BE_OPT_INIT_DELAY__A, 2); if (status < 0) goto error; #endif
/* FEC setup */
status = write16(state, FEC_DI_INPUT_CTL__A, 1); /* OFDM input */ if (status < 0) goto error;
#ifdef COMPILE_FOR_NONRT
status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x400); if (status < 0) goto error; #else
status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x1000); if (status < 0) goto error; #endif
status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, 0x0001); if (status < 0) goto error;
/* Setup MPEG bus */
status = mpegts_dto_setup(state, OM_DVBT); if (status < 0) goto error; /* Set DVBT Presets */
status = dvbt_activate_presets(state); if (status < 0) goto error;
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM
| SCU_RAM_COMMAND_CMD_DEMOD_STOP,
0, NULL, 1, &cmd_result); if (status < 0) goto error;
/* Halt SCU to enable safe non-atomic accesses */
status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD); if (status < 0) goto error;
/* Stop processors */
status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP); if (status < 0) goto error;
status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP); if (status < 0) goto error;
/* Mandatory fix, always stop CP, required to set spl offset back to
hardware default (is set to 0 by ucode during pilot detection */
status = write16(state, OFDM_CP_COMM_EXEC__A, OFDM_CP_COMM_EXEC_STOP); if (status < 0) goto error;
/*== Write channel settings to device ================================*/
/* mode */ switch (state->props.transmission_mode) { case TRANSMISSION_MODE_AUTO: case TRANSMISSION_MODE_8K: default:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; break; case TRANSMISSION_MODE_2K:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K; break;
}
/* guard */ switch (state->props.guard_interval) { default: case GUARD_INTERVAL_AUTO: /* try first guess DRX_GUARD_1DIV4 */ case GUARD_INTERVAL_1_4:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; break; case GUARD_INTERVAL_1_32:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32; break; case GUARD_INTERVAL_1_16:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16; break; case GUARD_INTERVAL_1_8:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8; break;
}
/* hierarchy */ switch (state->props.hierarchy) { case HIERARCHY_AUTO: case HIERARCHY_NONE: default: /* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ case HIERARCHY_1:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; break; case HIERARCHY_2:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2; break; case HIERARCHY_4:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4; break;
}
/* modulation */ switch (state->props.modulation) { case QAM_AUTO: default: /* try first guess DRX_CONSTELLATION_QAM64 */ case QAM_64:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; break; case QPSK:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK; break; case QAM_16:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16; break;
} #if 0 /* No hierarchical channels support in BDA */ /* Priority (only for hierarchical channels) */ switch (channel->priority) { case DRX_PRIORITY_LOW:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO;
WR16(dev_addr, OFDM_EC_SB_PRIOR__A,
OFDM_EC_SB_PRIOR_LO); break; case DRX_PRIORITY_HIGH:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
WR16(dev_addr, OFDM_EC_SB_PRIOR__A,
OFDM_EC_SB_PRIOR_HI)); break; case DRX_PRIORITY_UNKNOWN: default:
status = -EINVAL; goto error;
} #else /* Set Priority high */
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
status = write16(state, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI); if (status < 0) goto error; #endif
/* coderate */ switch (state->props.code_rate_HP) { case FEC_AUTO: default: /* try first guess DRX_CODERATE_2DIV3 */ case FEC_2_3:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; break; case FEC_1_2:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2; break; case FEC_3_4:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4; break; case FEC_5_6:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6; break; case FEC_7_8:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8; break;
}
/* * SAW filter selection: normally not necessary, but if wanted * the application can select a SAW filter via the driver by * using UIOs
*/
/* First determine real bandwidth (Hz) */ /* Also set delay for impulse noise cruncher */ /* * Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is * changed by SC for fix for some 8K,1/8 guard but is restored by * InitEC and ResetEC functions
*/ switch (state->props.bandwidth_hz) { case 0:
state->props.bandwidth_hz = 8000000;
fallthrough; case 8000000:
bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ;
status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A,
3052); if (status < 0) goto error; /* cochannel protection for PAL 8 MHz */
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A,
7); if (status < 0) goto error;
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A,
7); if (status < 0) goto error;
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A,
7); if (status < 0) goto error;
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A,
1); if (status < 0) goto error; break; case 7000000:
bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ;
status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A,
3491); if (status < 0) goto error; /* cochannel protection for PAL 7 MHz */
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A,
8); if (status < 0) goto error;
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A,
8); if (status < 0) goto error;
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A,
4); if (status < 0) goto error;
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A,
1); if (status < 0) goto error; break; case 6000000:
bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ;
status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A,
4073); if (status < 0) goto error; /* cochannel protection for NTSC 6 MHz */
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A,
19); if (status < 0) goto error;
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A,
19); if (status < 0) goto error;
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A,
14); if (status < 0) goto error;
status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A,
1); if (status < 0) goto error; break; default:
status = -EINVAL; goto error;
}
iqm_rc_rate_ofs &=
((((u32) IQM_RC_RATE_OFS_HI__M) <<
IQM_RC_RATE_OFS_LO__W) | IQM_RC_RATE_OFS_LO__M);
status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate_ofs); if (status < 0) goto error;
/* Bandwidth setting done */
#if 0
status = dvbt_set_frequency_shift(demod, channel, tuner_offset); if (status < 0) goto error; #endif
status = set_frequency_shifter(state, intermediate_freqk_hz,
tuner_freq_offset, true); if (status < 0) goto error;
/*== start SC, write channel settings to SC ==========================*/
/* Activate SCU to enable SCU commands */
status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); if (status < 0) goto error;
/* Enable SC after setting all other parameters */
status = write16(state, OFDM_SC_COMM_STATE__A, 0); if (status < 0) goto error;
status = write16(state, OFDM_SC_COMM_EXEC__A, 1); if (status < 0) goto error;
status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM
| SCU_RAM_COMMAND_CMD_DEMOD_START,
0, NULL, 1, &cmd_result); if (status < 0) goto error;
/* Write SC parameter registers, set all AUTO flags in operation mode */
param1 = (OFDM_SC_RA_RAM_OP_AUTO_MODE__M |
OFDM_SC_RA_RAM_OP_AUTO_GUARD__M |
OFDM_SC_RA_RAM_OP_AUTO_CONST__M |
OFDM_SC_RA_RAM_OP_AUTO_HIER__M |
OFDM_SC_RA_RAM_OP_AUTO_RATE__M);
status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM,
0, transmission_params, param1, 0, 0, 0); if (status < 0) goto error;
if (!state->m_drxk_a3_rom_code)
status = dvbt_ctrl_set_sqi_speed(state, &state->m_sqi_speed);
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__);
/* * \brief Setup of the QAM Measurement intervals for signal quality * \param demod instance of demod. * \param modulation current modulation. * \return DRXStatus_t. * * NOTE: * Take into account that for certain settings the errorcounters can overflow. * The implementation does not check this. *
*/ staticint set_qam_measurement(struct drxk_state *state, enum e_drxk_constellation modulation,
u32 symbol_rate)
{
u32 fec_bits_desired = 0; /* BER accounting period */
u32 fec_rs_period_total = 0; /* Total period */
u16 fec_rs_prescale = 0; /* ReedSolomon Measurement Prescale */
u16 fec_rs_period = 0; /* Value for corresponding I2C register */ int status = 0;
dprintk(1, "\n");
*p_lock_status = NOT_LOCKED;
status = scu_command(state,
SCU_RAM_COMMAND_STANDARD_QAM |
SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2,
result); if (status < 0)
pr_err("Error %d on %s\n", status, __func__);
if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { /* 0x0000 NOT LOCKED */
} elseif (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) { /* 0x4000 DEMOD LOCKED */
*p_lock_status = DEMOD_LOCK;
} elseif (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) { /* 0x8000 DEMOD + FEC LOCKED (system lock) */
*p_lock_status = MPEG_LOCK;
} else { /* 0xC000 NEVER LOCKED */ /* (system will never be able to lock to the signal) */ /* * TODO: check this, intermediate & standard specific lock * states are not taken into account here
*/
*p_lock_status = NEVER_LOCK;
} return status;
}
error: if (status < 0)
pr_warn("Warning %d on %s\n", status, __func__); return status;
}
staticint set_qam(struct drxk_state *state, u16 intermediate_freqk_hz,
s32 tuner_freq_offset)
{ int status;
u16 cmd_result; int qam_demod_param_count = state->qam_demod_parameter_count;
dprintk(1, "\n"); /* * STEP 1: reset demodulator * resets FEC DI and FEC RS * resets QAM block * resets SCU variables
*/
status = write16(state, FEC_DI_COMM_EXEC__A, FEC_DI_COMM_EXEC_STOP); if (status < 0) goto error;
status = write16(state, FEC_RS_COMM_EXEC__A, FEC_RS_COMM_EXEC_STOP); if (status < 0) goto error;
status = qam_reset_qam(state); if (status < 0) goto error;
/* * STEP 2: configure demodulator * -set params; resets IQM,QAM,FEC HW; initializes some * SCU variables
*/
status = qam_set_symbolrate(state); if (status < 0) goto error;
/* Set params */ switch (state->props.modulation) { case QAM_256:
state->m_constellation = DRX_CONSTELLATION_QAM256; break; case QAM_AUTO: case QAM_64:
state->m_constellation = DRX_CONSTELLATION_QAM64; break; case QAM_16:
state->m_constellation = DRX_CONSTELLATION_QAM16; break; case QAM_32:
state->m_constellation = DRX_CONSTELLATION_QAM32; break; case QAM_128:
state->m_constellation = DRX_CONSTELLATION_QAM128; break; default:
status = -EINVAL; break;
} if (status < 0) goto error;
/* Use the 4-parameter if it's requested or we're probing for
* the correct command. */ if (state->qam_demod_parameter_count == 4
|| !state->qam_demod_parameter_count) {
qam_demod_param_count = 4;
status = qam_demodulator_command(state, qam_demod_param_count);
}
/* Use the 2-parameter command if it was requested or if we're * probing for the correct command and the 4-parameter command
* failed. */ if (state->qam_demod_parameter_count == 2
|| (!state->qam_demod_parameter_count && status < 0)) {
qam_demod_param_count = 2;
status = qam_demodulator_command(state, qam_demod_param_count);
}
if (status < 0) {
dprintk(1, "Could not set demodulator parameters.\n");
dprintk(1, "Make sure qam_demod_parameter_count (%d) is correct for your firmware (%s).\n",
state->qam_demod_parameter_count,
state->microcode_name); goto error;
} elseif (!state->qam_demod_parameter_count) {
dprintk(1, "Auto-probing the QAM command parameters was successful - using %d parameters.\n",
qam_demod_param_count);
/* * One of our commands was successful. We don't need to * auto-probe anymore, now that we got the correct command.
*/
state->qam_demod_parameter_count = qam_demod_param_count;
}
/* * STEP 3: enable the system in a mode where the ADC provides valid * signal setup modulation independent registers
*/ #if 0
status = set_frequency(channel, tuner_freq_offset)); if (status < 0) goto error; #endif
status = set_frequency_shifter(state, intermediate_freqk_hz,
tuner_freq_offset, true); if (status < 0) goto error;
/* Setup BER measurement */
status = set_qam_measurement(state, state->m_constellation,
state->props.symbol_rate); if (status < 0) goto error;
/* Reset default values */
status = write16(state, IQM_CF_SCALE_SH__A, IQM_CF_SCALE_SH__PRE); if (status < 0) goto error;
status = write16(state, QAM_SY_TIMEOUT__A, QAM_SY_TIMEOUT__PRE); if (status < 0) goto error;
/* Reset default LC values */
status = write16(state, QAM_LC_RATE_LIMIT__A, 3); if (status < 0) goto error;
status = write16(state, QAM_LC_LPF_FACTORP__A, 4); if (status < 0) goto error;
status = write16(state, QAM_LC_LPF_FACTORI__A, 4); if (status < 0) goto error;
status = write16(state, QAM_LC_MODE__A, 7); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB0__A, 1); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB1__A, 1); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB2__A, 1); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB3__A, 1); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB4__A, 2); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB5__A, 2); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB6__A, 2); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB8__A, 2); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB9__A, 2); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB10__A, 2); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB12__A, 2); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB15__A, 3); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB16__A, 3); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB20__A, 4); if (status < 0) goto error;
status = write16(state, QAM_LC_QUAL_TAB25__A, 4); if (status < 0) goto error;
/* Mirroring, QAM-block starting point not inverted */
status = write16(state, QAM_SY_SP_INV__A,
QAM_SY_SP_INV_SPECTRUM_INV_DIS); if (status < 0) goto error;
/* Halt SCU to enable safe non-atomic accesses */
status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD); if (status < 0) goto error;
/* STEP 4: modulation specific setup */ switch (state->props.modulation) { case QAM_16:
status = set_qam16(state); break; case QAM_32:
status = set_qam32(state); break; case QAM_AUTO: case QAM_64:
status = set_qam64(state); break; case QAM_128:
status = set_qam128(state); break; case QAM_256:
status = set_qam256(state); break; default:
status = -EINVAL; break;
} if (status < 0) goto error;
/* Activate SCU to enable SCU commands */
status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); if (status < 0) goto error;
/* Re-configure MPEG output, requires knowledge of channel bitrate */ /* extAttr->currentChannel.modulation = channel->modulation; */ /* extAttr->currentChannel.symbolrate = channel->symbolrate; */
status = mpegts_dto_setup(state, state->m_operation_mode); if (status < 0) goto error;
/* start processes */
status = mpegts_start(state); if (status < 0) goto error;
status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE); if (status < 0) goto error;
status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_ACTIVE); if (status < 0) goto error;
status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE); if (status < 0) goto error;
/* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */
status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM
| SCU_RAM_COMMAND_CMD_DEMOD_START,
0, NULL, 1, &cmd_result); if (status < 0) goto error;
/* update global DRXK data container */ /*? extAttr->qamInterleaveMode = DRXK_QAM_I12_J17; */
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
/* Ensure correct power-up mode */
status = power_up_qam(state); if (status < 0) goto error; /* Reset QAM block */
status = qam_reset_qam(state); if (status < 0) goto error;
/* Setup IQM */
status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP); if (status < 0) goto error;
status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC); if (status < 0) goto error;
/* Upload IQM Channel Filter settings by
boot loader from ROM table */ switch (o_mode) { case OM_QAM_ITU_A:
status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A,
DRXK_BLCC_NR_ELEMENTS_TAPS,
DRXK_BLC_TIMEOUT); break; case OM_QAM_ITU_C:
status = bl_direct_cmd(state, IQM_CF_TAP_RE0__A,
DRXK_BL_ROM_OFFSET_TAPS_ITU_C,
DRXK_BLDC_NR_ELEMENTS_TAPS,
DRXK_BLC_TIMEOUT); if (status < 0) goto error;
status = bl_direct_cmd(state,
IQM_CF_TAP_IM0__A,
DRXK_BL_ROM_OFFSET_TAPS_ITU_C,
DRXK_BLDC_NR_ELEMENTS_TAPS,
DRXK_BLC_TIMEOUT); break; default:
status = -EINVAL;
} if (status < 0) goto error;
status = write16(state, IQM_CF_OUT_ENA__A, 1 << IQM_CF_OUT_ENA_QAM__B); if (status < 0) goto error;
status = write16(state, IQM_CF_SYMMETRIC__A, 0); if (status < 0) goto error;
status = write16(state, IQM_CF_MIDTAP__A,
((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B))); if (status < 0) goto error;
status = write16(state, IQM_RC_STRETCH__A, 21); if (status < 0) goto error;
status = write16(state, IQM_AF_CLP_LEN__A, 0); if (status < 0) goto error;
status = write16(state, IQM_AF_CLP_TH__A, 448); if (status < 0) goto error;
status = write16(state, IQM_AF_SNS_LEN__A, 0); if (status < 0) goto error;
status = write16(state, IQM_CF_POW_MEAS_LEN__A, 0); if (status < 0) goto error;
status = write16(state, IQM_FS_ADJ_SEL__A, 1); if (status < 0) goto error;
status = write16(state, IQM_RC_ADJ_SEL__A, 1); if (status < 0) goto error;
status = write16(state, IQM_CF_ADJ_SEL__A, 1); if (status < 0) goto error;
status = write16(state, IQM_AF_UPD_SEL__A, 0); if (status < 0) goto error;
/* IQM Impulse Noise Processing Unit */
status = write16(state, IQM_CF_CLP_VAL__A, 500); if (status < 0) goto error;
status = write16(state, IQM_CF_DATATH__A, 1000); if (status < 0) goto error;
status = write16(state, IQM_CF_BYPASSDET__A, 1); if (status < 0) goto error;
status = write16(state, IQM_CF_DET_LCT__A, 0); if (status < 0) goto error;
status = write16(state, IQM_CF_WND_LEN__A, 1); if (status < 0) goto error;
status = write16(state, IQM_CF_PKDTH__A, 1); if (status < 0) goto error;
status = write16(state, IQM_AF_INC_BYPASS__A, 1); if (status < 0) goto error;
/* turn on IQMAF. Must be done before setAgc**() */
status = set_iqm_af(state, true); if (status < 0) goto error;
status = write16(state, IQM_AF_START_LOCK__A, 0x01); if (status < 0) goto error;
/* IQM will not be reset from here, sync ADC and update/init AGC */
status = adc_synchronization(state); if (status < 0) goto error;
/* Set the FSM step period */
status = write16(state, SCU_RAM_QAM_FSM_STEP_PERIOD__A, 2000); if (status < 0) goto error;
/* Halt SCU to enable safe non-atomic accesses */
status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD); if (status < 0) goto error;
/* No more resets of the IQM, current standard correctly set =>
now AGCs can be configured. */
status = init_agc(state, true); if (status < 0) goto error;
status = set_pre_saw(state, &(state->m_qam_pre_saw_cfg)); if (status < 0) goto error;
/* Configure AGC's */
status = set_agc_rf(state, &(state->m_qam_rf_agc_cfg), true); if (status < 0) goto error;
status = set_agc_if(state, &(state->m_qam_if_agc_cfg), true); if (status < 0) goto error;
/* Activate SCU to enable SCU commands */
status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
staticint write_gpio(struct drxk_state *state)
{ int status;
u16 value = 0;
dprintk(1, "\n"); /* stop lock indicator process */
status = write16(state, SCU_RAM_GPIO__A,
SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error;
/* Write magic word to enable pdr reg write */
status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY); if (status < 0) goto error;
if (state->m_has_sawsw) { if (state->uio_mask & 0x0001) { /* UIO-1 */ /* write to io pad configuration register - output mode */
status = write16(state, SIO_PDR_SMA_TX_CFG__A,
state->m_gpio_cfg); if (status < 0) goto error;
/* use corresponding bit in io data output registar */
status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); if (status < 0) goto error; if ((state->m_gpio & 0x0001) == 0)
value &= 0x7FFF; /* write zero to 15th bit - 1st UIO */ else
value |= 0x8000; /* write one to 15th bit - 1st UIO */ /* write back to io data output register */
status = write16(state, SIO_PDR_UIO_OUT_LO__A, value); if (status < 0) goto error;
} if (state->uio_mask & 0x0002) { /* UIO-2 */ /* write to io pad configuration register - output mode */
status = write16(state, SIO_PDR_SMA_RX_CFG__A,
state->m_gpio_cfg); if (status < 0) goto error;
/* use corresponding bit in io data output registar */
status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); if (status < 0) goto error; if ((state->m_gpio & 0x0002) == 0)
value &= 0xBFFF; /* write zero to 14th bit - 2st UIO */ else
value |= 0x4000; /* write one to 14th bit - 2st UIO */ /* write back to io data output register */
status = write16(state, SIO_PDR_UIO_OUT_LO__A, value); if (status < 0) goto error;
} if (state->uio_mask & 0x0004) { /* UIO-3 */ /* write to io pad configuration register - output mode */
status = write16(state, SIO_PDR_GPIO_CFG__A,
state->m_gpio_cfg); if (status < 0) goto error;
/* use corresponding bit in io data output registar */
status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); if (status < 0) goto error; if ((state->m_gpio & 0x0004) == 0)
value &= 0xFFFB; /* write zero to 2nd bit - 3rd UIO */ else
value |= 0x0004; /* write one to 2nd bit - 3rd UIO */ /* write back to io data output register */
status = write16(state, SIO_PDR_UIO_OUT_LO__A, value); if (status < 0) goto error;
}
} /* Write magic word to disable pdr reg write */
status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
staticint switch_antenna_to_qam(struct drxk_state *state)
{ int status = 0; bool gpio_state;
dprintk(1, "\n");
if (!state->antenna_gpio) return 0;
gpio_state = state->m_gpio & state->antenna_gpio;
if (state->antenna_dvbt ^ gpio_state) { /* Antenna is on DVB-T mode. Switch */ if (state->antenna_dvbt)
state->m_gpio &= ~state->antenna_gpio; else
state->m_gpio |= state->antenna_gpio;
status = write_gpio(state);
} if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
staticint switch_antenna_to_dvbt(struct drxk_state *state)
{ int status = 0; bool gpio_state;
dprintk(1, "\n");
if (!state->antenna_gpio) return 0;
gpio_state = state->m_gpio & state->antenna_gpio;
if (!(state->antenna_dvbt ^ gpio_state)) { /* Antenna is on DVB-C mode. Switch */ if (state->antenna_dvbt)
state->m_gpio |= state->antenna_gpio; else
state->m_gpio &= ~state->antenna_gpio;
status = write_gpio(state);
} if (status < 0)
pr_err("Error %d on %s\n", status, __func__); return status;
}
staticint power_down_device(struct drxk_state *state)
{ /* Power down to requested mode */ /* Backup some register settings */ /* Set pins with possible pull-ups connected to them in input mode */ /* Analog power down */ /* ADC power down */ /* Power down device */ int status;
dprintk(1, "\n"); if (state->m_b_p_down_open_bridge) { /* Open I2C bridge before power down of DRXK */
status = ConfigureI2CBridge(state, true); if (status < 0) goto error;
} /* driver 0.9.0 */
status = dvbt_enable_ofdm_token_ring(state, false); if (status < 0) goto error;
status = write16(state, SIO_CC_PWD_MODE__A,
SIO_CC_PWD_MODE_LEVEL_CLOCK); if (status < 0) goto error;
status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); if (status < 0) goto error;
state->m_hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
status = hi_cfg_command(state);
error: if (status < 0)
pr_err("Error %d on %s\n", status, __func__);
return status;
}
staticint init_drxk(struct drxk_state *state)
{ int status = 0, n = 0; enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM;
u16 driver_version;
dprintk(1, "\n"); if (state->m_drxk_state == DRXK_UNINITIALIZED) {
drxk_i2c_lock(state);
status = power_up_device(state); if (status < 0) goto error;
status = drxx_open(state); if (status < 0) goto error; /* Soft reset of OFDM-, sys- and osc-clockdomain */
status = write16(state, SIO_CC_SOFT_RST__A,
SIO_CC_SOFT_RST_OFDM__M
| SIO_CC_SOFT_RST_SYS__M
| SIO_CC_SOFT_RST_OSC__M); if (status < 0) goto error;
status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); if (status < 0) goto error; /* * TODO is this needed? If yes, how much delay in * worst case scenario
*/
usleep_range(1000, 2000);
state->m_drxk_a3_patch_code = true;
status = get_device_capabilities(state); if (status < 0) goto error;
status = init_hi(state); if (status < 0) goto error; /* disable various processes */ #if NOA1ROM if (!(state->m_DRXK_A1_ROM_CODE)
&& !(state->m_DRXK_A2_ROM_CODE)) #endif
{
status = write16(state, SCU_RAM_GPIO__A,
SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error;
}
/* disable MPEG port */
status = mpegts_disable(state); if (status < 0) goto error;
/* Stop AUD and SCU */
status = write16(state, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP); if (status < 0) goto error;
status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP); if (status < 0) goto error;
/* enable token-ring bus through OFDM block for possible ucode upload */
status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A,
SIO_OFDM_SH_OFDM_RING_ENABLE_ON); if (status < 0) goto error;
/* include boot loader section */
status = write16(state, SIO_BL_COMM_EXEC__A,
SIO_BL_COMM_EXEC_ACTIVE); if (status < 0) goto error;
status = bl_chain_cmd(state, 0, 6, 100); if (status < 0) goto error;
if (state->fw) {
status = download_microcode(state, state->fw->data,
state->fw->size); if (status < 0) goto error;
}
/* disable token-ring bus through OFDM block for possible ucode upload */
status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A,
SIO_OFDM_SH_OFDM_RING_ENABLE_OFF); if (status < 0) goto error;
/* Run SCU for a little while to initialize microcode version numbers */
status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); if (status < 0) goto error;
status = drxx_open(state); if (status < 0) goto error; /* added for test */
msleep(30);
power_mode = DRXK_POWER_DOWN_OFDM;
status = ctrl_power_mode(state, &power_mode); if (status < 0) goto error;
/* Stamp driver version number in SCU data RAM in BCD code Done to enable field application engineers to retrieve drxdriver version via I2C from SCU RAM. Not using SCU command interface for SCU register access since no microcode may be present.
*/
driver_version =
(((DRXK_VERSION_MAJOR / 100) % 10) << 12) +
(((DRXK_VERSION_MAJOR / 10) % 10) << 8) +
((DRXK_VERSION_MAJOR % 10) << 4) +
(DRXK_VERSION_MINOR % 10);
status = write16(state, SCU_RAM_DRIVER_VER_HI__A,
driver_version); if (status < 0) goto error;
driver_version =
(((DRXK_VERSION_PATCH / 1000) % 10) << 12) +
(((DRXK_VERSION_PATCH / 100) % 10) << 8) +
(((DRXK_VERSION_PATCH / 10) % 10) << 4) +
(DRXK_VERSION_PATCH % 10);
status = write16(state, SCU_RAM_DRIVER_VER_LO__A,
driver_version); if (status < 0) goto error;
pr_info("DRXK driver version %d.%d.%d\n",
DRXK_VERSION_MAJOR, DRXK_VERSION_MINOR,
DRXK_VERSION_PATCH);
/* * Dirty fix of default values for ROM/PATCH microcode * Dirty because this fix makes it impossible to setup * suitable values before calling DRX_Open. This solution * requires changes to RF AGC speed to be done via the CTRL * function after calling DRX_Open
*/
/* m_dvbt_rf_agc_cfg.speed = 3; */
/* Reset driver debug flags to 0 */
status = write16(state, SCU_RAM_DRIVER_DEBUG__A, 0); if (status < 0) goto error; /* driver 0.9.0 */ /* Setup FEC OC:
NOTE: No more full FEC resets allowed afterwards!! */
status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP); if (status < 0) goto error; /* MPEGTS functions are still the same */
status = mpegts_dto_init(state); if (status < 0) goto error;
status = mpegts_stop(state); if (status < 0) goto error;
status = mpegts_configure_polarity(state); if (status < 0) goto error;
status = mpegts_configure_pins(state, state->m_enable_mpeg_output); if (status < 0) goto error; /* added: configure GPIO */
status = write_gpio(state); if (status < 0) goto error;
state->m_drxk_state = DRXK_STOPPED;
if (state->m_b_power_down) {
status = power_down_device(state); if (status < 0) goto error;
state->m_drxk_state = DRXK_POWERED_DOWN;
} else
state->m_drxk_state = DRXK_STOPPED;
/* Initialize the supported delivery systems */
n = 0; if (state->m_has_dvbc) {
state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C;
strlcat(state->frontend.ops.info.name, " DVB-C", sizeof(state->frontend.ops.info.name));
} if (state->m_has_dvbt) {
state->frontend.ops.delsys[n++] = SYS_DVBT;
strlcat(state->frontend.ops.info.name, " DVB-T", sizeof(state->frontend.ops.info.name));
}
drxk_i2c_unlock(state);
}
error: if (status < 0) {
state->m_drxk_state = DRXK_NO_DEV;
drxk_i2c_unlock(state);
pr_err("Error %d on %s\n", status, __func__);
}
dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded"); if (!fw) {
pr_err("Could not load firmware file %s.\n",
state->microcode_name);
pr_info("Copy %s to your hotplug directory!\n",
state->microcode_name);
state->microcode_name = NULL;
/* * As firmware is now load asynchronous, it is not possible * anymore to fail at frontend attach. We might silently * return here, and hope that the driver won't crash. * We might also change all DVB callbacks to return -ENODEV * if the device is not initialized. * As the DRX-K devices have their own internal firmware, * let's just hope that it will match a firmware revision * compatible with this driver and proceed.
*/
}
state->fw = fw;
if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV;
if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN;
if (!fe->ops.tuner_ops.get_if_frequency) {
pr_err("Error: get_if_frequency() not defined at tuner. Can't work without it!\n"); return -EINVAL;
}
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); if (fe->ops.tuner_ops.set_params)
fe->ops.tuner_ops.set_params(fe); if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
/* * Convert to 0..65535 scale. * If it can't be measured (AGC is disabled), just show 100%.
*/ if (total_gain > 0)
*strength = (65535UL * atten / total_gain / 100); else
*strength = 65535;
/* BER measurement is valid if at least FEC lock is achieved */
/* * OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be * written to set nr of symbols or bits over which to measure * EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg().
*/
/* Read registers for post/preViterbi BER calculation */
status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, ®16); if (status < 0) goto error;
pre_bit_err_count = reg16;
status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , ®16); if (status < 0) goto error;
pre_bit_count = reg16;
/* Number of bit-errors */
status = read16(state, FEC_RS_NR_BIT_ERRORS__A, ®16); if (status < 0) goto error;
post_bit_err_count = reg16;
status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, ®16); if (status < 0) goto error;
post_bit_error_scale = reg16;
status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, ®16); if (status < 0) goto error;
pkt_count = reg16;
status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, ®16); if (status < 0) goto error;
pkt_error_count = reg16;
write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
post_bit_err_count *= post_bit_error_scale;
post_bit_count = pkt_count * 204 * 8;
/* Store the results */
c->block_error.stat[0].scale = FE_SCALE_COUNTER;
c->block_error.stat[0].uvalue += pkt_error_count;
c->block_count.stat[0].scale = FE_SCALE_COUNTER;
c->block_count.stat[0].uvalue += pkt_count;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.