fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / media / dvb / frontends / sp887x.c
index d868a69..5c2f8f4 100644 (file)
@@ -5,7 +5,8 @@
 /*
  * This driver needs external firmware. Please use the command
  * "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
  */
 #define SP887X_DEFAULT_FIRMWARE "dvb-fe-sp887x.fw"
 
@@ -14,6 +15,8 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "dvb_frontend.h"
 #include "sp887x.h"
@@ -21,7 +24,6 @@
 
 struct sp887x_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        const struct sp887x_config* config;
        struct dvb_frontend frontend;
 
@@ -78,7 +80,7 @@ static int sp887x_readreg (struct sp887x_state* state, u16 reg)
        u8 b1 [2];
        int ret;
        struct i2c_msg msg[] = {{ .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
-                        { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }};
+                        { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }};
 
        if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
                printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
@@ -205,15 +207,6 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
        /* bit 0x010: enable data valid signal */
        sp887x_writereg(state, 0xd00, 0x010);
        sp887x_writereg(state, 0x0d1, 0x000);
-
-       /* setup the PLL */
-       if (state->config->pll_init) {
-               sp887x_writereg(state, 0x206, 0x001);
-               state->config->pll_init(fe);
-               sp887x_writereg(state, 0x206, 0x000);
-       }
-
-       printk ("done.\n");
        return 0;
 };
 
@@ -359,9 +352,16 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
        sp887x_microcontroller_stop(state);
 
        /* setup the PLL */
-       sp887x_writereg(state, 0x206, 0x001);
-       actual_freq = state->config->pll_set(fe, p);
-       sp887x_writereg(state, 0x206, 0x000);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+       if (fe->ops.tuner_ops.get_frequency) {
+               fe->ops.tuner_ops.get_frequency(fe, &actual_freq);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       } else {
+               actual_freq = p->frequency;
+       }
 
        /* read status reg in order to clear <pending irqs */
        sp887x_readreg(state, 0x200);
@@ -483,6 +483,17 @@ static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        return 0;
 }
 
+static int sp887x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct sp887x_state* state = fe->demodulator_priv;
+
+       if (enable) {
+               return sp887x_writereg(state, 0x206, 0x001);
+       } else {
+               return sp887x_writereg(state, 0x206, 0x000);
+       }
+}
+
 static int sp887x_sleep(struct dvb_frontend* fe)
 {
        struct sp887x_state* state = fe->demodulator_priv;
@@ -496,7 +507,7 @@ static int sp887x_sleep(struct dvb_frontend* fe)
 static int sp887x_init(struct dvb_frontend* fe)
 {
        struct sp887x_state* state = fe->demodulator_priv;
-        const struct firmware *fw = NULL;
+       const struct firmware *fw = NULL;
        int ret;
 
        if (!state->initialised) {
@@ -509,9 +520,9 @@ static int sp887x_init(struct dvb_frontend* fe)
                }
 
                ret = sp887x_initial_setup(fe, fw);
+               release_firmware(fw);
                if (ret) {
                        printk("sp887x: writing firmware to device failed\n");
-                       release_firmware(fw);
                        return ret;
                }
                printk("sp887x: firmware upload complete\n");
@@ -526,10 +537,10 @@ static int sp887x_init(struct dvb_frontend* fe)
 
 static int sp887x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 {
-        fesettings->min_delay_ms = 350;
-        fesettings->step_size = 166666*2;
-        fesettings->max_drift = (166666*2)+1;
-        return 0;
+       fesettings->min_delay_ms = 350;
+       fesettings->step_size = 166666*2;
+       fesettings->max_drift = (166666*2)+1;
+       return 0;
 }
 
 static void sp887x_release(struct dvb_frontend* fe)
@@ -552,14 +563,13 @@ struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &sp887x_ops, sizeof(struct dvb_frontend_ops));
        state->initialised = 0;
 
        /* check if the demod is there */
        if (sp887x_readreg(state, 0x0200) < 0) goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &sp887x_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -579,13 +589,14 @@ static struct dvb_frontend_ops sp887x_ops = {
                .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
                        FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
                        FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-                       FE_CAN_RECOVER
+                       FE_CAN_RECOVER
        },
 
        .release = sp887x_release,
 
        .init = sp887x_init,
        .sleep = sp887x_sleep,
+       .i2c_gate_ctrl = sp887x_i2c_gate_ctrl,
 
        .set_frontend = sp887x_setup_frontend_parameters,
        .get_tune_settings = sp887x_get_tune_settings,