[media] drxk: Make the QAM demodulator command parameters configurable
authorMartin Blumenstingl <martin.blumenstingl@googlemail.com>
Wed, 4 Jul 2012 20:36:55 +0000 (17:36 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 6 Jul 2012 17:54:43 +0000 (14:54 -0300)
Currently there are two different implementations (in the firmware) for
the QAM demodulator command: one takes 4 and the other takes 2
parameters. The driver shows an error in dmesg When using the
4-parameter command with firmware that implements the 2-parameter
command. Unfortunately this happens every time when chaning the
frequency (on DVB-C).

This patch simply makes configurable, how many command parameters will
be used. All existing drxk_config instances using the "drxk_a3.mc" were
updated because this firmware is the only loadable firmware where the
QAM demodulator command takes 4 parameters. Some firmwares in the ROM
might also use it. The drxk instances in the em28xx-dvb driver were also
updated to silence the warnings.

If no qam_demod_parameter_count is given in the drxk_config struct, then
the correct number of parameters will be auto-detected.

[mchehab@redhat.com: Fix a small CodingStyle issue at one comment]
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Tested-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb/ddbridge/ddbridge-core.c
drivers/media/dvb/frontends/drxk.h
drivers/media/dvb/frontends/drxk_hard.c
drivers/media/dvb/frontends/drxk_hard.h
drivers/media/dvb/ngene/ngene-cards.c
drivers/media/video/em28xx/em28xx-dvb.c

index 131b938e9e8178384ab90fa206165c2d20861582..ebf3f05839d2c5416488b77df70c825dc01ae467 100644 (file)
@@ -578,6 +578,7 @@ static int demod_attach_drxk(struct ddb_input *input)
 
        memset(&config, 0, sizeof(config));
        config.microcode_name = "drxk_a3.mc";
+       config.qam_demod_parameter_count = 4;
        config.adr = 0x29 + (input->nr & 1);
 
        fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
index 9d64e4fea066818969ad54a39a7eff03a6e368c2..d615d7d055a29dfba39b3fd6e9879830cd96a080 100644 (file)
  *                     means that 1=DVBC, 0 = DVBT. Zero means the opposite.
  * @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength.
  * @microcode_name:    Name of the firmware file with the microcode
+ * @qam_demod_parameter_count: The number of parameters used for the command
+ *                             to set the demodulator parameters. All
+ *                             firmwares are using the 2-parameter commmand.
+ *                             An exception is the "drxk_a3.mc" firmware,
+ *                             which uses the 4-parameter command.
+ *                             A value of 0 (default) or lower indicates that
+ *                             the correct number of parameters will be
+ *                             automatically detected.
  *
  * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is
  * UIO-3.
@@ -38,7 +46,8 @@ struct drxk_config {
        u8      mpeg_out_clk_strength;
        int     chunk_size;
 
-       const char *microcode_name;
+       const char      *microcode_name;
+       int              qam_demod_parameter_count;
 };
 
 #if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \
index 317530f891c0c7c2269acc6fdd7a39c9f5ca4fa6..f370ec1c9bd3e5974fc12cab3cbc51e336346d32 100644 (file)
@@ -5415,12 +5415,67 @@ static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus)
 #define QAM_LOCKRANGE__M      0x10
 #define QAM_LOCKRANGE_NORMAL  0x10
 
+static int QAMDemodulatorCommand(struct drxk_state *state,
+                                int numberOfParameters)
+{
+       int status;
+       u16 cmdResult;
+       u16 setParamParameters[4] = { 0, 0, 0, 0 };
+
+       setParamParameters[0] = state->m_Constellation; /* modulation     */
+       setParamParameters[1] = DRXK_QAM_I12_J17;       /* interleave mode   */
+
+       if (numberOfParameters == 2) {
+               u16 setEnvParameters[1] = { 0 };
+
+               if (state->m_OperationMode == OM_QAM_ITU_C)
+                       setEnvParameters[0] = QAM_TOP_ANNEX_C;
+               else
+                       setEnvParameters[0] = QAM_TOP_ANNEX_A;
+
+               status = scu_command(state,
+                                    SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV,
+                                    1, setEnvParameters, 1, &cmdResult);
+               if (status < 0)
+                       goto error;
+
+               status = scu_command(state,
+                                    SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
+                                    numberOfParameters, setParamParameters,
+                                    1, &cmdResult);
+       } else if (numberOfParameters == 4) {
+               if (state->m_OperationMode == OM_QAM_ITU_C)
+                       setParamParameters[2] = QAM_TOP_ANNEX_C;
+               else
+                       setParamParameters[2] = QAM_TOP_ANNEX_A;
+
+               setParamParameters[3] |= (QAM_MIRROR_AUTO_ON);
+               /* Env parameters */
+               /* check for LOCKRANGE Extented */
+               /* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */
+
+               status = scu_command(state,
+                                    SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
+                                    numberOfParameters, setParamParameters,
+                                    1, &cmdResult);
+       } else {
+               printk(KERN_WARNING "drxk: Unknown QAM demodulator parameter "
+                       "count %d\n", numberOfParameters);
+       }
+
+error:
+       if (status < 0)
+               printk(KERN_WARNING "drxk: Warning %d on %s\n",
+                      status, __func__);
+       return status;
+}
+
 static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
                  s32 tunerFreqOffset)
 {
        int status;
-       u16 setParamParameters[4] = { 0, 0, 0, 0 };
        u16 cmdResult;
+       int qamDemodParamCount = state->qam_demod_parameter_count;
 
        dprintk(1, "\n");
        /*
@@ -5472,34 +5527,40 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
        }
        if (status < 0)
                goto error;
-       setParamParameters[0] = state->m_Constellation; /* modulation     */
-       setParamParameters[1] = DRXK_QAM_I12_J17;       /* interleave mode   */
-       if (state->m_OperationMode == OM_QAM_ITU_C)
-               setParamParameters[2] = QAM_TOP_ANNEX_C;
-       else
-               setParamParameters[2] = QAM_TOP_ANNEX_A;
-       setParamParameters[3] |= (QAM_MIRROR_AUTO_ON);
-       /* Env parameters */
-       /* check for LOCKRANGE Extented */
-       /* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */
 
-       status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 4, setParamParameters, 1, &cmdResult);
-       if (status < 0) {
-               /* Fall-back to the simpler call */
-               if (state->m_OperationMode == OM_QAM_ITU_C)
-                       setParamParameters[0] = QAM_TOP_ANNEX_C;
-               else
-                       setParamParameters[0] = QAM_TOP_ANNEX_A;
-               status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 1, setParamParameters, 1, &cmdResult);
-               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) {
+               qamDemodParamCount = 4;
+               status = QAMDemodulatorCommand(state, qamDemodParamCount);
+       }
 
-               setParamParameters[0] = state->m_Constellation; /* modulation     */
-               setParamParameters[1] = DRXK_QAM_I12_J17;       /* interleave mode   */
-               status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 2, setParamParameters, 1, &cmdResult);
+       /* 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)) {
+               qamDemodParamCount = 2;
+               status = QAMDemodulatorCommand(state, qamDemodParamCount);
        }
-       if (status < 0)
+
+       if (status < 0) {
+               dprintk(1, "Could not set demodulator parameters. Make "
+                       "sure qam_demod_parameter_count (%d) is correct for "
+                       "your firmware (%s).\n",
+                       state->qam_demod_parameter_count,
+                       state->microcode_name);
                goto error;
+       } else if (!state->qam_demod_parameter_count) {
+               dprintk(1, "Auto-probing the correct QAM demodulator command "
+                       "parameters was successful - using %d parameters.\n",
+                       qamDemodParamCount);
+
+               /* 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 = qamDemodParamCount;
+       }
 
        /*
         * STEP 3: enable the system in a mode where the ADC provides valid
@@ -6502,6 +6563,7 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
        state->demod_address = adr;
        state->single_master = config->single_master;
        state->microcode_name = config->microcode_name;
+       state->qam_demod_parameter_count = config->qam_demod_parameter_count;
        state->no_i2c_bridge = config->no_i2c_bridge;
        state->antenna_gpio = config->antenna_gpio;
        state->antenna_dvbt = config->antenna_dvbt;
index f4177970010623be8b2e5ae8c1fbdc08ee015b19..6bb9fc4a7b96cbeeb6a082503499fbff18feb4d2 100644 (file)
@@ -353,6 +353,7 @@ struct drxk_state {
        const char *microcode_name;
        struct completion fw_wait_load;
        const struct firmware *fw;
+       int qam_demod_parameter_count;
 };
 
 #define NEVER_LOCK 0
index 7539a5d7102964aaa094be28cd0ae7b9de245687..72ee8de0226025618ecd733716fa30f494eb646b 100644 (file)
@@ -217,6 +217,7 @@ static int demod_attach_drxk(struct ngene_channel *chan,
 
        memset(&config, 0, sizeof(config));
        config.microcode_name = "drxk_a3.mc";
+       config.qam_demod_parameter_count = 4;
        config.adr = 0x29 + (chan->number ^ 2);
 
        chan->fe = dvb_attach(drxk_attach, &config, i2c);
index f8ffe102d29584c96b277d890d554fe60fa44330..a16531fa937a1ec395e3490e741e0d46d0a3cccd 100644 (file)
@@ -315,6 +315,7 @@ static struct drxk_config terratec_h5_drxk = {
        .single_master = 1,
        .no_i2c_bridge = 1,
        .microcode_name = "dvb-usb-terratec-h5-drxk.fw",
+       .qam_demod_parameter_count = 2,
 };
 
 static struct drxk_config hauppauge_930c_drxk = {
@@ -323,6 +324,7 @@ static struct drxk_config hauppauge_930c_drxk = {
        .no_i2c_bridge = 1,
        .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
        .chunk_size = 56,
+       .qam_demod_parameter_count = 2,
 };
 
 struct drxk_config terratec_htc_stick_drxk = {
@@ -331,6 +333,7 @@ struct drxk_config terratec_htc_stick_drxk = {
        .no_i2c_bridge = 1,
        .microcode_name = "dvb-usb-terratec-htc-stick-drxk.fw",
        .chunk_size = 54,
+       .qam_demod_parameter_count = 2,
        /* Required for the antenna_gpio to disable LNA. */
        .antenna_dvbt = true,
        /* The windows driver uses the same. This will disable LNA. */
@@ -347,6 +350,7 @@ static struct drxk_config pctv_520e_drxk = {
        .adr = 0x29,
        .single_master = 1,
        .microcode_name = "dvb-demod-drxk-pctv.fw",
+       .qam_demod_parameter_count = 2,
        .chunk_size = 58,
        .antenna_dvbt = true, /* disable LNA */
        .antenna_gpio = (1 << 2), /* disable LNA */