- patches.suse/slab-handle-memoryless-nodes-v2a.patch: Refresh.
[linux-flexiantxendom0-3.2.10.git] / drivers / media / common / tuners / xc5000.c
index f4ffcdc..432003d 100644 (file)
@@ -61,6 +61,7 @@ struct xc5000_priv {
        u32 bandwidth;
        u8  video_standard;
        u8  rf_mode;
+       u8  radio_input;
 };
 
 /* Misc Defines */
@@ -632,8 +633,12 @@ static int xc5000_set_params(struct dvb_frontend *fe,
        struct xc5000_priv *priv = fe->tuner_priv;
        int ret;
 
-       if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
-               xc_load_fw_and_init_tuner(fe);
+       if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
+               if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
+                       dprintk(1, "Unable to load firmware and init tuner\n");
+                       return -EINVAL;
+               }
+       }
 
        dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
 
@@ -739,15 +744,12 @@ static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
        return ret;
 }
 
-static int xc5000_set_analog_params(struct dvb_frontend *fe,
+static int xc5000_set_tv_freq(struct dvb_frontend *fe,
        struct analog_parameters *params)
 {
        struct xc5000_priv *priv = fe->tuner_priv;
        int ret;
 
-       if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
-               xc_load_fw_and_init_tuner(fe);
-
        dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
                __func__, params->frequency);
 
@@ -827,6 +829,86 @@ tune_channel:
        return 0;
 }
 
+static int xc5000_set_radio_freq(struct dvb_frontend *fe,
+       struct analog_parameters *params)
+{
+       struct xc5000_priv *priv = fe->tuner_priv;
+       int ret = -EINVAL;
+       u8 radio_input;
+
+       dprintk(1, "%s() frequency=%d (in units of khz)\n",
+               __func__, params->frequency);
+
+       if (priv->radio_input == XC5000_RADIO_NOT_CONFIGURED) {
+               dprintk(1, "%s() radio input not configured\n", __func__);
+               return -EINVAL;
+       }
+
+       if (priv->radio_input == XC5000_RADIO_FM1)
+               radio_input = FM_Radio_INPUT1;
+       else if  (priv->radio_input == XC5000_RADIO_FM2)
+               radio_input = FM_Radio_INPUT2;
+       else {
+               dprintk(1, "%s() unknown radio input %d\n", __func__,
+                       priv->radio_input);
+               return -EINVAL;
+       }
+
+       priv->freq_hz = params->frequency * 125 / 2;
+
+       priv->rf_mode = XC_RF_MODE_AIR;
+
+       ret = xc_SetTVStandard(priv, XC5000_Standard[radio_input].VideoMode,
+                              XC5000_Standard[radio_input].AudioMode);
+
+       if (ret != XC_RESULT_SUCCESS) {
+               printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
+               return -EREMOTEIO;
+       }
+
+       ret = xc_SetSignalSource(priv, priv->rf_mode);
+       if (ret != XC_RESULT_SUCCESS) {
+               printk(KERN_ERR
+                       "xc5000: xc_SetSignalSource(%d) failed\n",
+                       priv->rf_mode);
+               return -EREMOTEIO;
+       }
+
+       xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
+
+       return 0;
+}
+
+static int xc5000_set_analog_params(struct dvb_frontend *fe,
+                            struct analog_parameters *params)
+{
+       struct xc5000_priv *priv = fe->tuner_priv;
+       int ret = -EINVAL;
+
+       if (priv->i2c_props.adap == NULL)
+               return -EINVAL;
+
+       if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
+               if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
+                       dprintk(1, "Unable to load firmware and init tuner\n");
+                       return -EINVAL;
+               }
+       }
+
+       switch (params->mode) {
+       case V4L2_TUNER_RADIO:
+               ret = xc5000_set_radio_freq(fe, params);
+               break;
+       case V4L2_TUNER_ANALOG_TV:
+       case V4L2_TUNER_DIGITAL_TV:
+               ret = xc5000_set_tv_freq(fe, params);
+               break;
+       }
+
+       return ret;
+}
+
+
 static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
 {
        struct xc5000_priv *priv = fe->tuner_priv;
@@ -1000,6 +1082,9 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
                priv->if_khz = cfg->if_khz;
        }
 
+       if (priv->radio_input == 0)
+               priv->radio_input = cfg->radio_input;
+
        /* Check if firmware has been loaded. It is possible that another
           instance of the driver has loaded the firmware.
         */