DRXJ specific implementation of DRX driver
authors: Dragan Savic, Milos Nikolic, Mihajlo Katona, Tao Ding, Paul Janssen
+
+ The Linux DVB Driver for Micronas DRX39xx family (drx3933j) was
+ written by Devin Heitmueller <devin.heitmueller@kernellabs.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+
+ GNU General Public License for more details.
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*-----------------------------------------------------------------------------
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "drx39xxj.h"
+
#include "drxj.h"
#include "drxj_map.h"
/*=== DEFINES ================================================================*/
/*============================================================================*/
+#define DRX39XX_MAIN_FIRMWARE "dvb-fe-drxj-mc-1.0.8.fw"
+
/**
* \brief Maximum u32 value.
*/
static int power_down_aud(struct drx_demod_instance *demod);
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
static int power_up_aud(struct drx_demod_instance *demod, bool set_standard);
-#endif
static int
aud_ctrl_set_standard(struct drx_demod_instance *demod, enum drx_aud_standard *standard);
+#endif
static int
ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw *pre_saw);
/*============================================================================*/
/*============================================================================*/
+#if 0
/**
* \fn void mult32(u32 a, u32 b, u32 *h, u32 *l)
* \brief 32bitsx32bits signed multiplication
}
}
}
+#endif
/*============================================================================*/
/*============================================================================*/
+#if 0
/**
* \brief Compute: 100 * 10^( gd_b / 200 ).
* \param u32 gd_b Gain in 0.1dB
return (result + 50) / 100;
}
-#ifndef DRXJ_DIGITAL_ONLY
#define FRAC_FLOOR 0
#define FRAC_CEIL 1
#define FRAC_ROUND 2
addr &= (~write_bit);
/* Set up read */
- start_timer = drxbsp_hst_clock();
+ start_timer = jiffies_to_msecs(jiffies);
do {
/* RMW to aud TR IF until request is granted or timeout */
stat = drxj_dap_read_modify_write_reg16(dev_addr,
if (stat != 0)
break;
- current_timer = drxbsp_hst_clock();
+ current_timer = jiffies_to_msecs(jiffies);
delta_timer = current_timer - start_timer;
if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
stat = -EIO;
/* Wait for read ready status or timeout */
if (stat == 0) {
- start_timer = drxbsp_hst_clock();
+ start_timer = jiffies_to_msecs(jiffies);
while ((tr_status & AUD_TOP_TR_CTR_FIFO_RD_RDY__M) !=
AUD_TOP_TR_CTR_FIFO_RD_RDY_READY) {
if (stat != 0)
break;
- current_timer = drxbsp_hst_clock();
+ current_timer = jiffies_to_msecs(jiffies);
delta_timer = current_timer - start_timer;
if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
stat = -EIO;
/* Force write bit */
addr |= write_bit;
- start_timer = drxbsp_hst_clock();
+ start_timer = jiffies_to_msecs(jiffies);
do {
/* RMW to aud TR IF until request is granted or timeout */
stat = drxj_dap_read_modify_write_reg16(dev_addr,
if (stat != 0)
break;
- current_timer = drxbsp_hst_clock();
+ current_timer = jiffies_to_msecs(jiffies);
delta_timer = current_timer - start_timer;
if (delta_timer > DRXJ_DAP_AUDTRIF_TIMEOUT) {
stat = -EIO;
}
if ((cmd->cmd) == SIO_HI_RA_RAM_CMD_RESET)
- drxbsp_hst_sleep(1);
+ msleep(1);
/* Detect power down to ommit reading result */
powerdown_cmd = (bool) ((cmd->cmd == SIO_HI_RA_RAM_CMD_CONFIG) &&
drxbsp_i2c_write_read(&wake_up_addr, 1, &data,
(struct i2c_device_addr *)(NULL), 0,
(u8 *)(NULL));
- drxbsp_hst_sleep(10);
+ msleep(10);
retry_count++;
} while ((drxbsp_i2c_write_read
((struct i2c_device_addr *) (NULL), 0, (u8 *)(NULL), dev_addr, 1,
!= 0) && (retry_count < DRXJ_MAX_RETRIES_POWERUP));
/* Need some recovery time .... */
- drxbsp_hst_sleep(10);
+ msleep(10);
if (retry_count == DRXJ_MAX_RETRIES_POWERUP)
return -EIO;
/*----------------------------------------------------------------------------*/
+#if 0
/**
* \fn int ctrl_get_cfg_mpeg_output()
* \brief Get MPEG output configuration of the device.
rw_error:
return -EIO;
}
+#endif
/*----------------------------------------------------------------------------*/
/* MPEG Output Configuration Functions - end */
* This routine should be called during a set channel of QAM/VSB
*
*/
+#if 0
static int set_mpeg_output_clock_rate(struct drx_demod_instance *demod)
{
struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
rw_error:
return -EIO;
}
+#endif
/*----------------------------------------------------------------------------*/
/**
return -EIO;
}
+#if 0
/*----------------------------------------------------------------------------*/
/**
* \fn int ctrl_set_cfg_mpeg_output_misc()
rw_error:
return -EIO;
}
+#endif
/*----------------------------------------------------------------------------*/
/* miscellaneous configuartions - end */
return -EIO;
}
+#if 0
/*============================================================================*/
/**
* \fn int ctrl_getuio_cfg()
return 0;
}
+#endif
/**
* \fn int ctrl_uio_write()
return -EIO;
}
+#if 0
/**
*\fn int ctrl_uio_read
*\brief Read from a UIO.
rw_error:
return -EIO;
}
+#endif
/*---------------------------------------------------------------------------*/
/* UIO Configuration Functions - end */
return -EIO;
}
+#if 0
/**
* \fn int ctrl_set_cfg_smart_ant()
* \brief Set Smart Antenna.
RR16( dev_addr, SIO_SA_TX_COMMAND__A, &data );
WR16( dev_addr, SIO_SA_TX_COMMAND__A, data | SIO_SA_TX_COMMAND_TX_ENABLE__M );
*/
- start_time = drxbsp_hst_clock();
+ start_time = jiffies_to_msecs(jiffies);
do {
rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_SA_TX_STATUS__A, &data, 0);
if (rc != 0) {
pr_err("error %d\n", rc);
goto rw_error;
}
- } while ((data & SIO_SA_TX_STATUS_BUSY__M) && ((drxbsp_hst_clock() - start_time) < DRXJ_MAX_WAITTIME));
+ } while ((data & SIO_SA_TX_STATUS_BUSY__M) && ((jiffies_to_msecs(jiffies) - start_time) < DRXJ_MAX_WAITTIME));
if (data & SIO_SA_TX_STATUS_BUSY__M)
return -EIO;
rw_error:
return -EIO;
}
+#endif
static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd)
{
}
/* Wait until SCU has processed command */
- start_time = drxbsp_hst_clock();
+ start_time = jiffies_to_msecs(jiffies);
do {
rc = DRXJ_DAP.read_reg16func(dev_addr, SCU_RAM_COMMAND__A, &cur_cmd, 0);
if (rc != 0) {
goto rw_error;
}
} while (!(cur_cmd == DRX_SCU_READY)
- && ((drxbsp_hst_clock() - start_time) < DRXJ_MAX_WAITTIME));
+ && ((jiffies_to_msecs(jiffies) - start_time) < DRXJ_MAX_WAITTIME));
if (cur_cmd != DRX_SCU_READY)
return -EIO;
return rc;
}
-static int
-ctrl_i2c_write_read(struct drx_demod_instance *demod, struct drxi2c_data *i2c_data)
-{
- return -ENOTSUPP;
-}
-
/* -------------------------------------------------------------------------- */
/**
* \brief Measure result of ADC synchronisation
}
/* Wait at least 3*128*(1/sysclk) <<< 1 millisec */
- rc = drxbsp_hst_sleep(1);
- if (rc != 0) {
- pr_err("error %d\n", rc);
- goto rw_error;
- }
+ msleep(1);
*count = 0;
rc = DRXJ_DAP.read_reg16func(dev_addr, IQM_AF_PHASE0__A, &data, 0);
return -EIO;
}
+#if 0
/**
* \brief Configure IQM AF registers
* \param demod instance of demodulator.
return 0;
}
-
-/**
-* \brief Verifies whether microcode can be loaded.
-* \param demod Demodulator instance.
-* \return int.
-*/
-static int ctrl_validate_u_code(struct drx_demod_instance *demod)
-{
- u32 mc_dev, mc_patch;
- u16 ver_type;
-
- /* Check device.
- * Disallow microcode if:
- * - MC has version record AND
- * - device ID in version record is not 0 AND
- * - product ID in version record's device ID does not
- * match DRXJ1 product IDs - 0x393 or 0x394
- */
- ver_type = DRX_ATTR_MCRECORD(demod).aux_type;
- mc_dev = DRX_ATTR_MCRECORD(demod).mc_dev_type;
- mc_patch = DRX_ATTR_MCRECORD(demod).mc_base_version;
-
- if (DRX_ISMCVERTYPE(ver_type)) {
- if ((mc_dev != 0) &&
- (((mc_dev >> 16) & 0xFFF) != 0x393) &&
- (((mc_dev >> 16) & 0xFFF) != 0x394)) {
- /* Microcode is marked for another device - error */
- return -EINVAL;
- } else if (mc_patch != 0) {
- /* Patch not allowed because there is no ROM */
- return -EINVAL;
- }
- }
-
- /* Everything else: OK */
- return 0;
-}
+#endif
/*============================================================================*/
/*== END AUXILIARY FUNCTIONS ==*/
}
break;
#endif
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_FM:
clp_sum_max = 1023;
sns_sum_max = 1023;
return -EIO;
}
+#if 0
/**
* \fn int get_sig_strength()
* \brief Retrieve signal strength for VSB and QAM.
rw_error:
return -EIO;
}
+#endif
/**
* \fn int get_acc_pkt_err()
}
#endif
+#if 0
/**
* \fn int ResetAccPktErr()
* \brief Reset Accumulating packet error count.
*/
static int ctrl_set_cfg_reset_pkt_err(struct drx_demod_instance *demod)
{
-#ifdef DRXJ_SIGNAL_ACCUM_ERR
struct drxj_data *ext_attr = NULL;
int rc;
u16 packet_error = 0;
return 0;
rw_error:
-#endif
return -EIO;
}
rw_error:
return -EIO;
}
+#endif
/*============================================================================*/
ext_attr->qam_rf_agc_cfg = *agc_settings;
break;
#endif
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_PAL_SECAM_BG:
case DRX_STANDARD_PAL_SECAM_DK:
case DRX_STANDARD_PAL_SECAM_I:
return -EIO;
}
+#if 0
/**
* \fn int get_agc_rf ()
* \brief get configuration of RF AGC
*agc_settings = ext_attr->qam_rf_agc_cfg;
break;
#endif
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_PAL_SECAM_BG:
case DRX_STANDARD_PAL_SECAM_DK:
case DRX_STANDARD_PAL_SECAM_I:
rw_error:
return -EIO;
}
+#endif
/**
* \fn int set_agc_if ()
ext_attr->qam_if_agc_cfg = *agc_settings;
break;
#endif
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_PAL_SECAM_BG:
case DRX_STANDARD_PAL_SECAM_DK:
case DRX_STANDARD_PAL_SECAM_I:
return -EIO;
}
+#if 0
/**
* \fn int get_agc_if ()
* \brief get configuration of If AGC
*agc_settings = ext_attr->qam_if_agc_cfg;
break;
#endif
-#ifndef DRXJ_DIGITAL_ONLY
case DRX_STANDARD_PAL_SECAM_BG:
case DRX_STANDARD_PAL_SECAM_DK:
case DRX_STANDARD_PAL_SECAM_I:
case DRX_STANDARD_FM:
*agc_settings = ext_attr->atv_if_agc_cfg;
break;
-#endif
default:
return -EIO;
}
rw_error:
return -EIO;
}
+#endif
/**
* \fn int set_iqm_af ()
return -EIO;
}
+#if 0
/**
* \fn static short get_vsb_symb_err(struct i2c_device_addr *dev_addr, u32 *ber)
* \brief Get the values of ber in VSB mode
rw_error:
return -EIO;
}
+#endif
/**
* \fn static int get_vsbmer(struct i2c_device_addr *dev_addr, u16 *mer)
return -EIO;
}
+#if 0
/*============================================================================*/
/**
* \fn int ctrl_get_vsb_constel()
rw_error:
return -EIO;
}
+#endif
/*============================================================================*/
/*== END 8VSB DATAPATH FUNCTIONS ==*/
/* external attributes for storing aquired channel constellation */
ext_attr = (struct drxj_data *) demod->my_ext_attr;
*lock_status = DRX_NOT_LOCKED;
- start_time = drxbsp_hst_clock();
+ start_time = jiffies_to_msecs(jiffies);
state = NO_LOCK;
do {
rc = ctrl_lock_status(demod, lock_status);
state = DEMOD_LOCKED;
/* some delay to see if fec_lock possible TODO find the right value */
timeout_ofs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; /* see something, waiting longer */
- d_locked_time = drxbsp_hst_clock();
+ d_locked_time = jiffies_to_msecs(jiffies);
}
}
break;
case DEMOD_LOCKED:
if ((*lock_status == DRXJ_DEMOD_LOCK) && /* still demod_lock in 150ms */
- ((drxbsp_hst_clock() - d_locked_time) >
+ ((jiffies_to_msecs(jiffies) - d_locked_time) >
DRXJ_QAM_FEC_LOCK_WAITTIME)) {
rc = DRXJ_DAP.read_reg16func(demod->my_i2c_dev_addr, QAM_SY_TIMEOUT__A, &data, 0);
if (rc != 0) {
goto rw_error;
}
state = SYNC_FLIPPED;
- drxbsp_hst_sleep(10);
+ msleep(10);
}
break;
case SYNC_FLIPPED:
state = SPEC_MIRRORED;
/* reset timer TODO: still need 500ms? */
start_time = d_locked_time =
- drxbsp_hst_clock();
+ jiffies_to_msecs(jiffies);
timeout_ofs = 0;
} else { /* no need to wait lock */
start_time =
- drxbsp_hst_clock() -
+ jiffies_to_msecs(jiffies) -
DRXJ_QAM_MAX_WAITTIME - timeout_ofs;
}
}
break;
case SPEC_MIRRORED:
if ((*lock_status == DRXJ_DEMOD_LOCK) && /* still demod_lock in 150ms */
- ((drxbsp_hst_clock() - d_locked_time) >
+ ((jiffies_to_msecs(jiffies) - d_locked_time) >
DRXJ_QAM_FEC_LOCK_WAITTIME)) {
rc = ctrl_get_qam_sig_quality(demod, &sig_quality);
if (rc != 0) {
}
/* no need to wait lock */
start_time =
- drxbsp_hst_clock() -
+ jiffies_to_msecs(jiffies) -
DRXJ_QAM_MAX_WAITTIME - timeout_ofs;
}
}
default:
break;
}
- drxbsp_hst_sleep(10);
+ msleep(10);
} while
((*lock_status != DRX_LOCKED) &&
(*lock_status != DRX_NEVER_LOCK) &&
- ((drxbsp_hst_clock() - start_time) <
+ ((jiffies_to_msecs(jiffies) - start_time) <
(DRXJ_QAM_MAX_WAITTIME + timeout_ofs))
);
/* Returning control to apllication ... */
/* external attributes for storing aquired channel constellation */
ext_attr = (struct drxj_data *) demod->my_ext_attr;
*lock_status = DRX_NOT_LOCKED;
- start_time = drxbsp_hst_clock();
+ start_time = jiffies_to_msecs(jiffies);
state = NO_LOCK;
do {
rc = ctrl_lock_status(demod, lock_status);
if (sig_quality.MER > 268) {
state = DEMOD_LOCKED;
timeout_ofs += DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME; /* see something, wait longer */
- d_locked_time = drxbsp_hst_clock();
+ d_locked_time = jiffies_to_msecs(jiffies);
}
}
break;
case DEMOD_LOCKED:
if (*lock_status == DRXJ_DEMOD_LOCK) {
if ((channel->mirror == DRX_MIRROR_AUTO) &&
- ((drxbsp_hst_clock() - d_locked_time) >
+ ((jiffies_to_msecs(jiffies) - d_locked_time) >
DRXJ_QAM_FEC_LOCK_WAITTIME)) {
ext_attr->mirror = DRX_MIRROR_YES;
rc = qam_flip_spec(demod, channel);
}
state = SPEC_MIRRORED;
/* reset timer TODO: still need 300ms? */
- start_time = drxbsp_hst_clock();
+ start_time = jiffies_to_msecs(jiffies);
timeout_ofs = -DRXJ_QAM_MAX_WAITTIME / 2;
}
}
default:
break;
}
- drxbsp_hst_sleep(10);
+ msleep(10);
} while
((*lock_status < DRX_LOCKED) &&
(*lock_status != DRX_NEVER_LOCK) &&
- ((drxbsp_hst_clock() - start_time) <
+ ((jiffies_to_msecs(jiffies) - start_time) <
(DRXJ_QAM_MAX_WAITTIME + timeout_ofs)));
return 0;
return -EIO;
}
+#if 0
/**
* \fn int ctrl_get_qam_constel()
* \brief Retreive a QAM constellation point via I2C.
rw_error:
return -EIO;
}
+#endif /* #if 0 */
#endif /* #ifndef DRXJ_VSB_ONLY */
/*============================================================================*/
*/
/* -------------------------------------------------------------------------- */
+#if 0
/**
* \brief Get array index for atv coef (ext_attr->atvTopCoefX[index])
* \param standard
}
/* -------------------------------------------------------------------------- */
-#ifndef DRXJ_DIGITAL_ONLY
/**
* \fn int ctrl_set_cfg_atv_equ_coef()
* \brief Set ATV equalizer coefficients
rw_error:
return -EIO;
}
-#endif /* #ifndef DRXJ_DIGITAL_ONLY */
+#endif
/* -------------------------------------------------------------------------- */
* Assuming that IQM, ATV and AUD blocks have been reset and are in STOP mode
*
*/
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
#define SCU_RAM_ATV_ENABLE_IIR_WA__A 0x831F6D /* TODO remove after done with reg import */
static int
set_atv_standard(struct drx_demod_instance *demod, enum drx_standard *standard)
rw_error:
return -EIO;
}
-#endif
/* -------------------------------------------------------------------------- */
-#ifndef DRXJ_DIGITAL_ONLY
/**
* \fn int set_atv_channel ()
* \brief Set ATV channel.
rw_error:
return -EIO;
}
-#endif
/* -------------------------------------------------------------------------- */
* channel->frequency. Determines the value for channel->bandwidth.
*
*/
-#ifndef DRXJ_DIGITAL_ONLY
static int
get_atv_channel(struct drx_demod_instance *demod,
struct drx_channel *channel, enum drx_standard standard)
rw_error:
return -EIO;
}
-#endif /* DRXJ_DIGITAL_ONLY */
/*============================================================================*/
/*== END ATV DATAPATH FUNCTIONS ==*/
/*============================================================================*/
-#ifndef DRXJ_EXCLUDE_AUDIO
/*===========================================================================*/
/*===========================================================================*/
/*== AUDIO DATAPATH FUNCTIONS ==*/
rw_error:
return -EIO;
}
+#endif
/*============================================================================*/
return -EIO;
}
+#if 0
/*============================================================================*/
/**
* \brief Get Modus data from audio RAM
return -EIO;
}
-#endif
-
/*===========================================================================*/
/*== END AUDIO DATAPATH FUNCTIONS ==*/
/*===========================================================================*/
/*== OOB DATAPATH FUNCTIONS ==*/
/*============================================================================*/
/*============================================================================*/
-#ifndef DRXJ_DIGITAL_ONLY
/**
* \fn int get_oob_lock_status ()
* \brief Get OOB lock status.
rw_error:
return -EIO;
}
-#endif /*#ifndef DRXJ_DIGITAL_ONLY */
+#endif
/**
* \fn int set_orx_nsu_aox()
/* Coefficients for the nyquist fitler (total: 27 taps) */
#define NYQFILTERLEN 27
+#if 0
static int ctrl_set_oob(struct drx_demod_instance *demod, struct drxoob *oob_param)
{
-#ifndef DRXJ_DIGITAL_ONLY
int rc;
s32 freq = 0; /* KHz */
struct i2c_device_addr *dev_addr = NULL;
return 0;
rw_error:
-#endif
return -EIO;
}
static int
ctrl_get_oob(struct drx_demod_instance *demod, struct drxoob_status *oob_status)
{
-#ifndef DRXJ_DIGITAL_ONLY
int rc;
struct i2c_device_addr *dev_addr = NULL;
struct drxj_data *ext_attr = NULL;
return 0;
rw_error:
-#endif
return -EIO;
}
* \param cfg_data Pointer to configuration parameter
* \return Error code
*/
-#ifndef DRXJ_DIGITAL_ONLY
static int
ctrl_set_cfg_oob_pre_saw(struct drx_demod_instance *demod, u16 *cfg_data)
{
rw_error:
return -EIO;
}
-#endif
/**
* \fn int ctrl_get_cfg_oob_pre_saw()
* \param cfg_data Pointer to configuration parameter
* \return Error code
*/
-#ifndef DRXJ_DIGITAL_ONLY
static int
ctrl_get_cfg_oob_pre_saw(struct drx_demod_instance *demod, u16 *cfg_data)
{
return 0;
}
-#endif
/**
* \fn int ctrl_set_cfg_oob_lo_power()
* \brief Configure LO Power value
* \param cfg_data Pointer to enum drxj_cfg_oob_lo_power ** \return Error code
*/
-#ifndef DRXJ_DIGITAL_ONLY
static int
ctrl_set_cfg_oob_lo_power(struct drx_demod_instance *demod, enum drxj_cfg_oob_lo_power *cfg_data)
{
rw_error:
return -EIO;
}
-#endif
/**
* \fn int ctrl_get_cfg_oob_lo_power()
* \brief Configure LO Power value
* \param cfg_data Pointer to enum drxj_cfg_oob_lo_power ** \return Error code
*/
-#ifndef DRXJ_DIGITAL_ONLY
static int
ctrl_get_cfg_oob_lo_power(struct drx_demod_instance *demod, enum drxj_cfg_oob_lo_power *cfg_data)
{
case DRX_STANDARD_ITU_B:
case DRX_STANDARD_ITU_C:
#endif /* DRXJ_VSB_ONLY */
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_NTSC:
case DRX_STANDARD_FM:
case DRX_STANDARD_PAL_SECAM_BG:
case DRX_STANDARD_PAL_SECAM_I:
case DRX_STANDARD_PAL_SECAM_L:
case DRX_STANDARD_PAL_SECAM_LP:
-#endif /* DRXJ_DIGITAL_ONLY */
+#endif
break;
case DRX_STANDARD_UNKNOWN:
default:
return -EINVAL;
}
}
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
if (standard == DRX_STANDARD_PAL_SECAM_BG) {
switch (channel->bandwidth) {
case DRX_BANDWIDTH_7MHZ: /* fall through */
if (demod->my_tuner != NULL) {
/* Determine tuner mode and freq to tune to ... */
switch (standard) {
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_NTSC: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
goto rw_error;
}
break;
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_NTSC: /* fallthrough */
case DRX_STANDARD_FM: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
return -EIO;
}
+#if 0
/*=============================================================================
===== ctrl_get_channel() ==========================================================
===========================================================================*/
}
break;
#endif
-#ifndef DRXJ_DIGITAL_ONLY
case DRX_STANDARD_NTSC: /* fall trough */
case DRX_STANDARD_PAL_SECAM_BG:
case DRX_STANDARD_PAL_SECAM_DK:
goto rw_error;
}
break;
-#endif
case DRX_STANDARD_UNKNOWN: /* fall trough */
default:
return -EIO;
rw_error:
return -EIO;
}
+#endif
/*=============================================================================
===== SigQuality() ==========================================================
max_mer);
break;
#endif
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_PAL_SECAM_BG:
case DRX_STANDARD_PAL_SECAM_DK:
case DRX_STANDARD_PAL_SECAM_I:
SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK;
break;
#endif
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_NTSC:
case DRX_STANDARD_PAL_SECAM_BG:
case DRX_STANDARD_PAL_SECAM_DK:
/*============================================================================*/
+#if 0
/**
* \fn int ctrl_constel()
* \brief Retreive a constellation point via I2C.
rw_error:
return -EIO;
}
+#endif
/*============================================================================*/
goto rw_error;
}
break;
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_NTSC: /* fallthrough */
case DRX_STANDARD_FM: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
goto rw_error;
}
break;
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_NTSC: /* fallthrough */
case DRX_STANDARD_FM: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
return -EIO;
}
+#if 0
/*============================================================================*/
/**
rw_error:
return -EIO;
}
+#endif
/*============================================================================*/
ext_attr->vsb_pre_saw_cfg.reference = 0x07;
ext_attr->vsb_pre_saw_cfg.use_pre_saw = true;
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
/* Initialize default AFE configuartion for ATV */
ext_attr->atv_rf_agc_cfg.standard = DRX_STANDARD_NTSC;
ext_attr->atv_rf_agc_cfg.ctrl_mode = DRX_AGC_CTRL_AUTO;
return -EIO;
}
-/*============================================================================*/
-
-/**
-* \fn int ctrl_version()
-* \brief Report version of microcode and if possible version of device
-* \param demod Pointer to demodulator instance.
-* \param version_list Pointer to pointer of linked list of versions.
-* \return int.
-*
-* Using static structures so no allocation of memory is needed.
-* Filling in all the fields each time, cause you don't know if they are
-* changed by the application.
-*
-* For device:
-* Major version number will be last two digits of family number.
-* Minor number will be full respin number
-* Patch will be metal fix number+1
-* Examples:
-* DRX3942J A2 => number: 42.1.2 text: "DRX3942J:A2"
-* DRX3933J B1 => number: 33.2.1 text: "DRX3933J:B1"
-*
-*/
-static int
-ctrl_version(struct drx_demod_instance *demod, struct drx_version_list **version_list)
-{
- struct drxj_data *ext_attr = (struct drxj_data *) (NULL);
- struct i2c_device_addr *dev_addr = (struct i2c_device_addr *)(NULL);
- struct drx_common_attr *common_attr = (struct drx_common_attr *) (NULL);
- int rc;
- u16 ucode_major_minor = 0; /* BCD Ma:Ma:Ma:Mi */
- u16 ucode_patch = 0; /* BCD Pa:Pa:Pa:Pa */
- u16 major = 0;
- u16 minor = 0;
- u16 patch = 0;
- u16 idx = 0;
- u32 jtag = 0;
- u16 subtype = 0;
- u16 mfx = 0;
- u16 bid = 0;
- u16 key = 0;
- static char ucode_name[] = "Microcode";
- static char device_name[] = "Device";
-
- dev_addr = demod->my_i2c_dev_addr;
- ext_attr = (struct drxj_data *) demod->my_ext_attr;
- common_attr = (struct drx_common_attr *) demod->my_common_attr;
-
- /* Microcode version *************************************** */
-
- ext_attr->v_version[0].module_type = DRX_MODULE_MICROCODE;
- ext_attr->v_version[0].module_name = ucode_name;
- ext_attr->v_version[0].v_string = ext_attr->v_text[0];
-
- if (common_attr->is_opened == true) {
- rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_VERSION_HI__A, &ucode_major_minor, 0);
- if (rc != 0) {
- pr_err("error %d\n", rc);
- goto rw_error;
- }
- rc = drxj_dap_scu_atomic_read_reg16(dev_addr, SCU_RAM_VERSION_LO__A, &ucode_patch, 0);
- if (rc != 0) {
- pr_err("error %d\n", rc);
- goto rw_error;
- }
-
- /* Translate BCD to numbers and string */
- /* TODO: The most significant Ma and Pa will be ignored, check with spec */
- minor = (ucode_major_minor & 0xF);
- ucode_major_minor >>= 4;
- major = (ucode_major_minor & 0xF);
- ucode_major_minor >>= 4;
- major += (10 * (ucode_major_minor & 0xF));
- patch = (ucode_patch & 0xF);
- ucode_patch >>= 4;
- patch += (10 * (ucode_patch & 0xF));
- ucode_patch >>= 4;
- patch += (100 * (ucode_patch & 0xF));
- } else {
- /* No microcode uploaded, No Rom existed, set version to 0.0.0 */
- patch = 0;
- minor = 0;
- major = 0;
- }
- ext_attr->v_version[0].v_major = major;
- ext_attr->v_version[0].v_minor = minor;
- ext_attr->v_version[0].v_patch = patch;
-
- if (major / 10 != 0) {
- ext_attr->v_version[0].v_string[idx++] =
- ((char)(major / 10)) + '0';
- major %= 10;
- }
- ext_attr->v_version[0].v_string[idx++] = ((char)major) + '0';
- ext_attr->v_version[0].v_string[idx++] = '.';
- ext_attr->v_version[0].v_string[idx++] = ((char)minor) + '0';
- ext_attr->v_version[0].v_string[idx++] = '.';
- if (patch / 100 != 0) {
- ext_attr->v_version[0].v_string[idx++] =
- ((char)(patch / 100)) + '0';
- patch %= 100;
- }
- if (patch / 10 != 0) {
- ext_attr->v_version[0].v_string[idx++] =
- ((char)(patch / 10)) + '0';
- patch %= 10;
- }
- ext_attr->v_version[0].v_string[idx++] = ((char)patch) + '0';
- ext_attr->v_version[0].v_string[idx] = '\0';
-
- ext_attr->v_list_elements[0].version = &(ext_attr->v_version[0]);
- ext_attr->v_list_elements[0].next = &(ext_attr->v_list_elements[1]);
-
- /* Device version *************************************** */
- /* Check device id */
- rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, &key, 0);
- if (rc != 0) {
- pr_err("error %d\n", rc);
- goto rw_error;
- }
- rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, 0xFABA, 0);
- if (rc != 0) {
- pr_err("error %d\n", rc);
- goto rw_error;
- }
- rc = DRXJ_DAP.read_reg32func(dev_addr, SIO_TOP_JTAGID_LO__A, &jtag, 0);
- if (rc != 0) {
- pr_err("error %d\n", rc);
- goto rw_error;
- }
- rc = DRXJ_DAP.read_reg16func(dev_addr, SIO_PDR_UIO_IN_HI__A, &bid, 0);
- if (rc != 0) {
- pr_err("error %d\n", rc);
- goto rw_error;
- }
- rc = DRXJ_DAP.write_reg16func(dev_addr, SIO_TOP_COMM_KEY__A, key, 0);
- if (rc != 0) {
- pr_err("error %d\n", rc);
- goto rw_error;
- }
-
- ext_attr->v_version[1].module_type = DRX_MODULE_DEVICE;
- ext_attr->v_version[1].module_name = device_name;
- ext_attr->v_version[1].v_string = ext_attr->v_text[1];
- ext_attr->v_version[1].v_string[0] = 'D';
- ext_attr->v_version[1].v_string[1] = 'R';
- ext_attr->v_version[1].v_string[2] = 'X';
- ext_attr->v_version[1].v_string[3] = '3';
- ext_attr->v_version[1].v_string[4] = '9';
- ext_attr->v_version[1].v_string[7] = 'J';
- ext_attr->v_version[1].v_string[8] = ':';
- ext_attr->v_version[1].v_string[11] = '\0';
-
- /* DRX39xxJ type Ax */
- /* TODO semantics of mfx and spin are unclear */
- subtype = (u16) ((jtag >> 12) & 0xFF);
- mfx = (u16) (jtag >> 29);
- ext_attr->v_version[1].v_minor = 1;
- if (mfx == 0x03)
- ext_attr->v_version[1].v_patch = mfx + 2;
- else
- ext_attr->v_version[1].v_patch = mfx + 1;
- ext_attr->v_version[1].v_string[6] = ((char)(subtype & 0xF)) + '0';
- ext_attr->v_version[1].v_major = (subtype & 0x0F);
- subtype >>= 4;
- ext_attr->v_version[1].v_string[5] = ((char)(subtype & 0xF)) + '0';
- ext_attr->v_version[1].v_major += 10 * subtype;
- ext_attr->v_version[1].v_string[9] = 'A';
- if (mfx == 0x03)
- ext_attr->v_version[1].v_string[10] = ((char)(mfx & 0xF)) + '2';
- else
- ext_attr->v_version[1].v_string[10] = ((char)(mfx & 0xF)) + '1';
-
- ext_attr->v_list_elements[1].version = &(ext_attr->v_version[1]);
- ext_attr->v_list_elements[1].next = (struct drx_version_list *) (NULL);
-
- *version_list = &(ext_attr->v_list_elements[0]);
-
- return 0;
-
-rw_error:
- *version_list = (struct drx_version_list *) (NULL);
- return -EIO;
-
-}
-
+#if 0
/*============================================================================*/
/**
common_attr->current_power_mode = org_power_mode;
return -EIO;
}
+#endif
/*============================================================================*/
/*== CTRL Set/Get Config related functions ===================================*/
/*============================================================================*/
+#if 0
/*===== SigStrength() =========================================================*/
/**
* \fn int ctrl_sig_strength()
goto rw_error;
}
break;
-#ifndef DRXJ_DIGITAL_ONLY
case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
goto rw_error;
}
break;
-#endif
case DRX_STANDARD_UNKNOWN: /* fallthrough */
default:
return -EINVAL;
* \return int.
*
*/
-#ifndef DRXJ_DIGITAL_ONLY
static int
ctrl_get_cfg_oob_misc(struct drx_demod_instance *demod, struct drxj_cfg_oob_misc *misc)
{
rw_error:
return -EIO;
}
-#endif
/**
* \fn int ctrl_get_cfg_vsb_misc()
case DRX_STANDARD_ITU_B: /* fallthrough */
case DRX_STANDARD_ITU_C:
#endif
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
case DRX_STANDARD_ITU_B: /* fallthrough */
case DRX_STANDARD_ITU_C:
#endif
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
case DRX_STANDARD_ITU_B: /* fallthrough */
case DRX_STANDARD_ITU_C:
#endif
-#ifndef DRXJ_DIGITAL_ONLY
case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
case DRX_STANDARD_NTSC: /* fallthrough */
case DRX_STANDARD_FM:
-#endif
return set_agc_rf(demod, agc_settings, true);
case DRX_STANDARD_UNKNOWN:
default:
case DRX_STANDARD_ITU_B: /* fallthrough */
case DRX_STANDARD_ITU_C:
#endif
-#ifndef DRXJ_DIGITAL_ONLY
case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */
case DRX_STANDARD_NTSC: /* fallthrough */
case DRX_STANDARD_FM:
-#endif
return get_agc_rf(demod, agc_settings);
case DRX_STANDARD_UNKNOWN:
default:
}
/*============================================================================*/
+#endif
/**
* \fn int ctrl_set_cfg_pre_saw()
ext_attr->qam_pre_saw_cfg = *pre_saw;
break;
#endif
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
/*============================================================================*/
+#if 0
/**
* \fn int ctrl_get_cfg_pre_saw()
* \brief Get Pre-saw reference setting.
*pre_saw = ext_attr->qam_pre_saw_cfg;
break;
#endif
-#ifndef DRXJ_DIGITAL_ONLY
case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */
case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */
ext_attr->atv_pre_saw_cfg.standard = DRX_STANDARD_FM;
*pre_saw = ext_attr->atv_pre_saw_cfg;
break;
-#endif
+
default:
return -EINVAL;
}
cfg_data));
case DRXJ_CFG_RESET_PACKET_ERR:
return ctrl_set_cfg_reset_pkt_err(demod);
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRXJ_CFG_OOB_PRE_SAW:
return ctrl_set_cfg_oob_pre_saw(demod, (u16 *)(config->cfg_data));
case DRXJ_CFG_OOB_LO_POW:
case DRXJ_CFG_SYMBOL_CLK_OFFSET:
return ctrl_get_cfg_symbol_clock_offset(demod,
(s32 *)config->cfg_data);
-#ifndef DRXJ_DIGITAL_ONLY
+#if 0
case DRXJ_CFG_OOB_MISC:
return ctrl_get_cfg_oob_misc(demod,
(struct drxj_cfg_oob_misc *) config->cfg_data);
rw_error:
return -EIO;
}
+#endif
/*=============================================================================
===== EXPORTED FUNCTIONS ====================================================*/
pr_err("error %d\n", rc);
goto rw_error;
}
- rc = drxbsp_hst_sleep(1);
- if (rc != 0) {
- pr_err("error %d\n", rc);
- goto rw_error;
- }
+ msleep(1);
/* TODO first make sure that everything keeps working before enabling this */
/* PowerDownAnalogBlocks() */
}
}
- rc = drxbsp_tuner_open(demod->my_tuner);
- if (rc != 0) {
- pr_err("error %d\n", rc);
- goto rw_error;
- }
-
if (common_attr->tuner_port_nr == 1) {
bool bridge_closed = false;
rc = ctrl_i2c_bridge(demod, &bridge_closed);
goto rw_error;
}
}
- rc = drxbsp_tuner_close(demod->my_tuner);
- if (rc != 0) {
- pr_err("error %d\n", rc);
- goto rw_error;
- }
if (common_attr->tuner_port_nr == 1) {
bool bridge_closed = false;
rc = ctrl_i2c_bridge(demod, &bridge_closed);
return -EIO;
}
-/*============================================================================*/
-/**
-* \fn drxj_ctrl()
-* \brief DRXJ specific control function
-* \return Status_t Return status.
-*/
-int
-drxj_ctrl(struct drx_demod_instance *demod, u32 ctrl, void *ctrl_data)
-{
- switch (ctrl) {
- /*======================================================================*/
- case DRX_CTRL_SET_CHANNEL:
- {
- return ctrl_set_channel(demod, (struct drx_channel *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_GET_CHANNEL:
- {
- return ctrl_get_channel(demod, (struct drx_channel *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_SIG_QUALITY:
- {
- return ctrl_sig_quality(demod,
- (struct drx_sig_quality *) ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_SIG_STRENGTH:
- {
- return ctrl_sig_strength(demod, (u16 *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_CONSTEL:
- {
- return ctrl_constel(demod, (struct drx_complex *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_SET_CFG:
- {
- return ctrl_set_cfg(demod, (struct drx_cfg *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_GET_CFG:
- {
- return ctrl_get_cfg(demod, (struct drx_cfg *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_I2C_BRIDGE:
- {
- return ctrl_i2c_bridge(demod, (bool *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_LOCK_STATUS:
- {
- return ctrl_lock_status(demod,
- (enum drx_lock_status *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_SET_STANDARD:
- {
- return ctrl_set_standard(demod,
- (enum drx_standard *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_GET_STANDARD:
- {
- return ctrl_get_standard(demod,
- (enum drx_standard *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_POWER_MODE:
- {
- return ctrl_power_mode(demod, (enum drx_power_mode *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_VERSION:
- {
- return ctrl_version(demod,
- (struct drx_version_list **)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_PROBE_DEVICE:
- {
- return ctrl_probe_device(demod);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_SET_OOB:
- {
- return ctrl_set_oob(demod, (struct drxoob *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_GET_OOB:
- {
- return ctrl_get_oob(demod, (struct drxoob_status *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_SET_UIO_CFG:
- {
- return ctrl_set_uio_cfg(demod, (struct drxuio_cfg *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_GET_UIO_CFG:
- {
- return ctrl_getuio_cfg(demod, (struct drxuio_cfg *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_UIO_READ:
- {
- return ctrl_uio_read(demod, (struct drxuio_data *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_UIO_WRITE:
- {
- return ctrl_uio_write(demod, (struct drxuio_data *)ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_AUD_SET_STANDARD:
- {
- return aud_ctrl_set_standard(demod,
- (enum drx_aud_standard *) ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_AUD_GET_STANDARD:
- {
- return aud_ctrl_get_standard(demod,
- (enum drx_aud_standard *) ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_AUD_GET_STATUS:
- {
- return aud_ctrl_get_status(demod,
- (struct drx_aud_status *) ctrl_data);
- }
- break;
- /*======================================================================*/
- case DRX_CTRL_AUD_BEEP:
- {
- return aud_ctrl_beep(demod, (struct drx_aud_beep *)ctrl_data);
- }
- break;
-
- /*======================================================================*/
- case DRX_CTRL_I2C_READWRITE:
- {
- return ctrl_i2c_write_read(demod,
- (struct drxi2c_data *) ctrl_data);
- }
- break;
- case DRX_CTRL_VALIDATE_UCODE:
- {
- return ctrl_validate_u_code(demod);
- }
- break;
- default:
- return -ENOTSUPP;
- }
- return 0;
-}
-
/*
* Microcode related functions
*/
return -EIO;
}
- result =drxbsp_hst_memcmp(curr_ptr,
- mc_data_buffer,
- bytes_to_comp);
+ result = memcmp(curr_ptr, mc_data_buffer,
+ bytes_to_comp);
if (result) {
pr_err("error verifying firmware at pos %u\n",
return rc;
}
+
+/*
+ * The Linux DVB Driver for Micronas DRX39xx family (drx3933j)
+ *
+ * Written by Devin Heitmueller <devin.heitmueller@kernellabs.com>
+ */
+
+static int drx39xxj_set_powerstate(struct dvb_frontend *fe, int enable)
+{
+ struct drx39xxj_state *state = fe->demodulator_priv;
+ struct drx_demod_instance *demod = state->demod;
+ int result;
+ enum drx_power_mode power_mode;
+
+ if (enable)
+ power_mode = DRX_POWER_UP;
+ else
+ power_mode = DRX_POWER_DOWN;
+
+ result = ctrl_power_mode(demod, &power_mode);
+ if (result != 0) {
+ pr_err("Power state change failed\n");
+ return 0;
+ }
+
+ state->powered_up = enable;
+ return 0;
+}
+
+static int drx39xxj_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct drx39xxj_state *state = fe->demodulator_priv;
+ struct drx_demod_instance *demod = state->demod;
+ int result;
+ enum drx_lock_status lock_status;
+
+ *status = 0;
+
+ result = ctrl_lock_status(demod, &lock_status);
+ if (result != 0) {
+ pr_err("drx39xxj: could not get lock status!\n");
+ *status = 0;
+ }
+
+ switch (lock_status) {
+ case DRX_NEVER_LOCK:
+ *status = 0;
+ pr_err("drx says NEVER_LOCK\n");
+ break;
+ case DRX_NOT_LOCKED:
+ *status = 0;
+ break;
+ case DRX_LOCK_STATE_1:
+ case DRX_LOCK_STATE_2:
+ case DRX_LOCK_STATE_3:
+ case DRX_LOCK_STATE_4:
+ case DRX_LOCK_STATE_5:
+ case DRX_LOCK_STATE_6:
+ case DRX_LOCK_STATE_7:
+ case DRX_LOCK_STATE_8:
+ case DRX_LOCK_STATE_9:
+ *status = FE_HAS_SIGNAL
+ | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC;
+ break;
+ case DRX_LOCKED:
+ *status = FE_HAS_SIGNAL
+ | FE_HAS_CARRIER
+ | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ break;
+ default:
+ pr_err("Lock state unknown %d\n", lock_status);
+ }
+
+ return 0;
+}
+
+static int drx39xxj_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct drx39xxj_state *state = fe->demodulator_priv;
+ struct drx_demod_instance *demod = state->demod;
+ int result;
+ struct drx_sig_quality sig_quality;
+
+ result = ctrl_sig_quality(demod, &sig_quality);
+ if (result != 0) {
+ pr_err("drx39xxj: could not get ber!\n");
+ *ber = 0;
+ return 0;
+ }
+
+ *ber = sig_quality.post_reed_solomon_ber;
+ return 0;
+}
+
+static int drx39xxj_read_signal_strength(struct dvb_frontend *fe,
+ u16 *strength)
+{
+ struct drx39xxj_state *state = fe->demodulator_priv;
+ struct drx_demod_instance *demod = state->demod;
+ int result;
+ struct drx_sig_quality sig_quality;
+
+ result = ctrl_sig_quality(demod, &sig_quality);
+ if (result != 0) {
+ pr_err("drx39xxj: could not get signal strength!\n");
+ *strength = 0;
+ return 0;
+ }
+
+ /* 1-100% scaled to 0-65535 */
+ *strength = (sig_quality.indicator * 65535 / 100);
+ return 0;
+}
+
+static int drx39xxj_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct drx39xxj_state *state = fe->demodulator_priv;
+ struct drx_demod_instance *demod = state->demod;
+ int result;
+ struct drx_sig_quality sig_quality;
+
+ result = ctrl_sig_quality(demod, &sig_quality);
+ if (result != 0) {
+ pr_err("drx39xxj: could not read snr!\n");
+ *snr = 0;
+ return 0;
+ }
+
+ *snr = sig_quality.MER;
+ return 0;
+}
+
+static int drx39xxj_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+ struct drx39xxj_state *state = fe->demodulator_priv;
+ struct drx_demod_instance *demod = state->demod;
+ int result;
+ struct drx_sig_quality sig_quality;
+
+ result = ctrl_sig_quality(demod, &sig_quality);
+ if (result != 0) {
+ pr_err("drx39xxj: could not get uc blocks!\n");
+ *ucblocks = 0;
+ return 0;
+ }
+
+ *ucblocks = sig_quality.packet_error;
+ return 0;
+}
+
+static int drx39xxj_set_frontend(struct dvb_frontend *fe)
+{
+#ifdef DJH_DEBUG
+ int i;
+#endif
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+ struct drx39xxj_state *state = fe->demodulator_priv;
+ struct drx_demod_instance *demod = state->demod;
+ enum drx_standard standard = DRX_STANDARD_8VSB;
+ struct drx_channel channel;
+ int result;
+ struct drxuio_data uio_data;
+ static const struct drx_channel def_channel = {
+ /* frequency */ 0,
+ /* bandwidth */ DRX_BANDWIDTH_6MHZ,
+ /* mirror */ DRX_MIRROR_NO,
+ /* constellation */ DRX_CONSTELLATION_AUTO,
+ /* hierarchy */ DRX_HIERARCHY_UNKNOWN,
+ /* priority */ DRX_PRIORITY_UNKNOWN,
+ /* coderate */ DRX_CODERATE_UNKNOWN,
+ /* guard */ DRX_GUARD_UNKNOWN,
+ /* fftmode */ DRX_FFTMODE_UNKNOWN,
+ /* classification */ DRX_CLASSIFICATION_AUTO,
+ /* symbolrate */ 5057000,
+ /* interleavemode */ DRX_INTERLEAVEMODE_UNKNOWN,
+ /* ldpc */ DRX_LDPC_UNKNOWN,
+ /* carrier */ DRX_CARRIER_UNKNOWN,
+ /* frame mode */ DRX_FRAMEMODE_UNKNOWN
+ };
+ u32 constellation = DRX_CONSTELLATION_AUTO;
+
+ /* Bring the demod out of sleep */
+ drx39xxj_set_powerstate(fe, 1);
+
+ /* Now make the tuner do it's thing... */
+ if (fe->ops.tuner_ops.set_params) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ fe->ops.tuner_ops.set_params(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ switch (p->delivery_system) {
+ case SYS_ATSC:
+ standard = DRX_STANDARD_8VSB;
+ break;
+ case SYS_DVBC_ANNEX_B:
+ standard = DRX_STANDARD_ITU_B;
+
+ switch (p->modulation) {
+ case QAM_64:
+ constellation = DRX_CONSTELLATION_QAM64;
+ break;
+ case QAM_256:
+ constellation = DRX_CONSTELLATION_QAM256;
+ break;
+ default:
+ constellation = DRX_CONSTELLATION_AUTO;
+ break;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (standard != state->current_standard || state->powered_up == 0) {
+ /* Set the standard (will be powered up if necessary */
+ result = ctrl_set_standard(demod, &standard);
+ if (result != 0) {
+ pr_err("Failed to set standard! result=%02x\n",
+ result);
+ return -EINVAL;
+ }
+ state->powered_up = 1;
+ state->current_standard = standard;
+ }
+
+ /* set channel parameters */
+ channel = def_channel;
+ channel.frequency = p->frequency / 1000;
+ channel.bandwidth = DRX_BANDWIDTH_6MHZ;
+ channel.constellation = constellation;
+
+ /* program channel */
+ result = ctrl_set_channel(demod, &channel);
+ if (result != 0) {
+ pr_err("Failed to set channel!\n");
+ return -EINVAL;
+ }
+ /* Just for giggles, let's shut off the LNA again.... */
+ uio_data.uio = DRX_UIO1;
+ uio_data.value = false;
+ result = ctrl_uio_write(demod, &uio_data);
+ if (result != 0) {
+ pr_err("Failed to disable LNA!\n");
+ return 0;
+ }
+#ifdef DJH_DEBUG
+ for (i = 0; i < 2000; i++) {
+ fe_status_t status;
+ drx39xxj_read_status(fe, &status);
+ pr_dbg("i=%d status=%d\n", i, status);
+ msleep(100);
+ i += 100;
+ }
+#endif
+
+ return 0;
+}
+
+static int drx39xxj_sleep(struct dvb_frontend *fe)
+{
+ /* power-down the demodulator */
+ return drx39xxj_set_powerstate(fe, 0);
+}
+
+static int drx39xxj_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+ struct drx39xxj_state *state = fe->demodulator_priv;
+ struct drx_demod_instance *demod = state->demod;
+ bool i2c_gate_state;
+ int result;
+
+#ifdef DJH_DEBUG
+ pr_dbg("i2c gate call: enable=%d state=%d\n", enable,
+ state->i2c_gate_open);
+#endif
+
+ if (enable)
+ i2c_gate_state = true;
+ else
+ i2c_gate_state = false;
+
+ if (state->i2c_gate_open == enable) {
+ /* We're already in the desired state */
+ return 0;
+ }
+
+ result = ctrl_i2c_bridge(demod, &i2c_gate_state);
+ if (result != 0) {
+ pr_err("drx39xxj: could not open i2c gate [%d]\n",
+ result);
+ dump_stack();
+ } else {
+ state->i2c_gate_open = enable;
+ }
+ return 0;
+}
+
+static int drx39xxj_init(struct dvb_frontend *fe)
+{
+ /* Bring the demod out of sleep */
+ drx39xxj_set_powerstate(fe, 1);
+
+ return 0;
+}
+
+static int drx39xxj_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 1000;
+ return 0;
+}
+
+static void drx39xxj_release(struct dvb_frontend *fe)
+{
+ struct drx39xxj_state *state = fe->demodulator_priv;
+ struct drx_demod_instance *demod = state->demod;
+
+ kfree(demod->my_ext_attr);
+ kfree(demod->my_common_attr);
+ kfree(demod->my_i2c_dev_addr);
+ if (demod->firmware)
+ release_firmware(demod->firmware);
+ kfree(demod);
+ kfree(state);
+}
+
+static struct dvb_frontend_ops drx39xxj_ops;
+
+struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
+{
+ struct drx39xxj_state *state = NULL;
+
+ struct i2c_device_addr *demod_addr = NULL;
+ struct drx_common_attr *demod_comm_attr = NULL;
+ struct drxj_data *demod_ext_attr = NULL;
+ struct drx_demod_instance *demod = NULL;
+ struct drxuio_cfg uio_cfg;
+ struct drxuio_data uio_data;
+ int result;
+
+ /* allocate memory for the internal state */
+ state = kzalloc(sizeof(struct drx39xxj_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ demod = kmalloc(sizeof(struct drx_demod_instance), GFP_KERNEL);
+ if (demod == NULL)
+ goto error;
+
+ demod_addr = kmalloc(sizeof(struct i2c_device_addr), GFP_KERNEL);
+ if (demod_addr == NULL)
+ goto error;
+ memcpy(demod_addr, &drxj_default_addr_g,
+ sizeof(struct i2c_device_addr));
+
+ demod_comm_attr = kmalloc(sizeof(struct drx_common_attr), GFP_KERNEL);
+ if (demod_comm_attr == NULL)
+ goto error;
+ memcpy(demod_comm_attr, &drxj_default_comm_attr_g,
+ sizeof(struct drx_common_attr));
+
+ demod_ext_attr = kmalloc(sizeof(struct drxj_data), GFP_KERNEL);
+ if (demod_ext_attr == NULL)
+ goto error;
+ memcpy(demod_ext_attr, &drxj_data_g, sizeof(struct drxj_data));
+
+ /* setup the state */
+ state->i2c = i2c;
+ state->demod = demod;
+
+ /* setup the demod data */
+ memcpy(demod, &drxj_default_demod_g, sizeof(struct drx_demod_instance));
+
+ demod->my_i2c_dev_addr = demod_addr;
+ demod->my_common_attr = demod_comm_attr;
+ demod->my_i2c_dev_addr->user_data = state;
+ demod->my_common_attr->microcode_file = DRX39XX_MAIN_FIRMWARE;
+ demod->my_common_attr->verify_microcode = true;
+ demod->my_common_attr->intermediate_freq = 5000;
+ demod->my_ext_attr = demod_ext_attr;
+ ((struct drxj_data *)demod_ext_attr)->uio_sma_tx_mode = DRX_UIO_MODE_READWRITE;
+ demod->my_tuner = NULL;
+ demod->i2c = i2c;
+
+ result = drxj_open(demod);
+ if (result != 0) {
+ pr_err("DRX open failed! Aborting\n");
+ goto error;
+ }
+
+ /* Turn off the LNA */
+ uio_cfg.uio = DRX_UIO1;
+ uio_cfg.mode = DRX_UIO_MODE_READWRITE;
+ /* Configure user-I/O #3: enable read/write */
+ result = ctrl_set_uio_cfg(demod, &uio_cfg);
+ if (result) {
+ pr_err("Failed to setup LNA GPIO!\n");
+ goto error;
+ }
+
+ uio_data.uio = DRX_UIO1;
+ uio_data.value = false;
+ result = ctrl_uio_write(demod, &uio_data);
+ if (result != 0) {
+ pr_err("Failed to disable LNA!\n");
+ goto error;
+ }
+
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &drx39xxj_ops,
+ sizeof(struct dvb_frontend_ops));
+
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error:
+ kfree(demod_ext_attr);
+ kfree(demod_comm_attr);
+ kfree(demod_addr);
+ kfree(demod);
+ kfree(state);
+
+ return NULL;
+}
+EXPORT_SYMBOL(drx39xxj_attach);
+
+static struct dvb_frontend_ops drx39xxj_ops = {
+ .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+ .info = {
+ .name = "Micronas DRX39xxj family Frontend",
+ .frequency_stepsize = 62500,
+ .frequency_min = 51000000,
+ .frequency_max = 858000000,
+ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+ },
+
+ .init = drx39xxj_init,
+ .i2c_gate_ctrl = drx39xxj_i2c_gate_ctrl,
+ .sleep = drx39xxj_sleep,
+ .set_frontend = drx39xxj_set_frontend,
+ .get_tune_settings = drx39xxj_get_tune_settings,
+ .read_status = drx39xxj_read_status,
+ .read_ber = drx39xxj_read_ber,
+ .read_signal_strength = drx39xxj_read_signal_strength,
+ .read_snr = drx39xxj_read_snr,
+ .read_ucblocks = drx39xxj_read_ucblocks,
+ .release = drx39xxj_release,
+};
+
+MODULE_DESCRIPTION("Micronas DRX39xxj Frontend");
+MODULE_AUTHOR("Devin Heitmueller");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(DRX39XX_MAIN_FIRMWARE);