return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
 }
 
+static int stv090x_setup_compound(struct stv090x_state *state)
+{
+       struct stv090x_dev *temp_int;
+
+       temp_int = find_dev(state->i2c,
+                           state->config->address);
+
+       if (temp_int && state->demod_mode == STV090x_DUAL) {
+               state->internal = temp_int->internal;
+               state->internal->num_used++;
+               dprintk(FE_INFO, 1, "Found Internal Structure!");
+       } else {
+               state->internal = kmalloc(sizeof(*state->internal), GFP_KERNEL);
+               if (!state->internal)
+                       goto error;
+               temp_int = append_internal(state->internal);
+               if (!temp_int) {
+                       kfree(state->internal);
+                       goto error;
+               }
+               state->internal->num_used = 1;
+               state->internal->mclk = 0;
+               state->internal->dev_ver = 0;
+               state->internal->i2c_adap = state->i2c;
+               state->internal->i2c_addr = state->config->address;
+               dprintk(FE_INFO, 1, "Create New Internal Structure!");
+
+               mutex_init(&state->internal->demod_lock);
+               mutex_init(&state->internal->tuner_lock);
+
+               if (stv090x_setup(&state->frontend) < 0) {
+                       dprintk(FE_ERROR, 1, "Error setting up device");
+                       goto err_remove;
+               }
+       }
+
+       if (state->internal->dev_ver >= 0x30)
+               state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
+
+       /* workaround for stuck DiSEqC output */
+       if (state->config->diseqc_envelope_mode)
+               stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
+
+       state->config->set_gpio = stv090x_set_gpio;
+
+       dprintk(FE_ERROR, 1, "Probing %s demodulator(%d) Cut=0x%02x",
+               state->device == STV0900 ? "STV0900" : "STV0903",
+               state->config->demod,
+               state->internal->dev_ver);
+
+       return 0;
+
+error:
+       kfree(state);
+       return -ENOMEM;
+err_remove:
+       remove_dev(state->internal);
+       kfree(state->internal);
+       return -ENODEV;
+}
+
 static const struct dvb_frontend_ops stv090x_ops = {
        .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
        .info = {
        .read_snr                       = stv090x_read_cnr,
 };
 
+static struct dvb_frontend *stv090x_get_dvb_frontend(struct i2c_client *client)
+{
+       struct stv090x_state *state = i2c_get_clientdata(client);
 
-struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
-                                   struct i2c_adapter *i2c,
-                                   enum stv090x_demodulator demod)
+       dev_dbg(&client->dev, "\n");
+
+       return &state->frontend;
+}
+
+static int stv090x_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
+       int ret = 0;
+       struct stv090x_config *config = client->dev.platform_data;
+
        struct stv090x_state *state = NULL;
-       struct stv090x_dev *temp_int;
 
-       state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL);
-       if (state == NULL)
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (!state) {
+               ret = -ENOMEM;
                goto error;
+       }
 
        state->verbose                          = &verbose;
        state->config                           = config;
-       state->i2c                              = i2c;
+       state->i2c                              = client->adapter;
        state->frontend.ops                     = stv090x_ops;
        state->frontend.demodulator_priv        = state;
-       state->demod                            = demod;
-       state->demod_mode                       = config->demod_mode; /* Single or Dual mode */
+       state->demod                            = config->demod;
+                                               /* Single or Dual mode */
+       state->demod_mode                       = config->demod_mode;
        state->device                           = config->device;
-       state->rolloff                          = STV090x_RO_35; /* default */
+                                               /* default */
+       state->rolloff                          = STV090x_RO_35;
 
-       temp_int = find_dev(state->i2c,
-                               state->config->address);
+       ret = stv090x_setup_compound(state);
+       if (ret)
+               goto error;
 
-       if ((temp_int != NULL) && (state->demod_mode == STV090x_DUAL)) {
-               state->internal = temp_int->internal;
-               state->internal->num_used++;
-               dprintk(FE_INFO, 1, "Found Internal Structure!");
-       } else {
-               state->internal = kmalloc(sizeof(struct stv090x_internal),
-                                         GFP_KERNEL);
-               if (!state->internal)
-                       goto error;
-               temp_int = append_internal(state->internal);
-               if (!temp_int) {
-                       kfree(state->internal);
-                       goto error;
-               }
-               state->internal->num_used = 1;
-               state->internal->mclk = 0;
-               state->internal->dev_ver = 0;
-               state->internal->i2c_adap = state->i2c;
-               state->internal->i2c_addr = state->config->address;
-               dprintk(FE_INFO, 1, "Create New Internal Structure!");
+       i2c_set_clientdata(client, state);
 
-               mutex_init(&state->internal->demod_lock);
-               mutex_init(&state->internal->tuner_lock);
+       /* setup callbacks */
+       config->get_dvb_frontend = stv090x_get_dvb_frontend;
 
-               if (stv090x_setup(&state->frontend) < 0) {
-                       dprintk(FE_ERROR, 1, "Error setting up device");
-                       goto err_remove;
-               }
-       }
+       return 0;
 
-       if (state->internal->dev_ver >= 0x30)
-               state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
+error:
+       kfree(state);
+       return ret;
+}
 
-       /* workaround for stuck DiSEqC output */
-       if (config->diseqc_envelope_mode)
-               stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
+static int stv090x_remove(struct i2c_client *client)
+{
+       struct stv090x_state *state = i2c_get_clientdata(client);
+
+       stv090x_release(&state->frontend);
+       return 0;
+}
 
-       config->set_gpio = stv090x_set_gpio;
+struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
+                                   struct i2c_adapter *i2c,
+                                   enum stv090x_demodulator demod)
+{
+       int ret = 0;
+       struct stv090x_state *state = NULL;
 
-       dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
-              state->device == STV0900 ? "STV0900" : "STV0903",
-              demod,
-              state->internal->dev_ver);
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (!state)
+               goto error;
+
+       state->verbose                          = &verbose;
+       state->config                           = config;
+       state->i2c                              = i2c;
+       state->frontend.ops                     = stv090x_ops;
+       state->frontend.demodulator_priv        = state;
+       state->demod                            = demod;
+                                               /* Single or Dual mode */
+       state->demod_mode                       = config->demod_mode;
+       state->device                           = config->device;
+                                               /* default */
+       state->rolloff                          = STV090x_RO_35;
+
+       ret = stv090x_setup_compound(state);
+       if (ret)
+               goto error;
 
        return &state->frontend;
 
-err_remove:
-       remove_dev(state->internal);
-       kfree(state->internal);
 error:
        kfree(state);
        return NULL;
 }
 EXPORT_SYMBOL(stv090x_attach);
+
+static const struct i2c_device_id stv090x_id_table[] = {
+       {"stv090x", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, stv090x_id_table);
+
+static struct i2c_driver stv090x_driver = {
+       .driver = {
+               .name   = "stv090x",
+               .suppress_bind_attrs = true,
+       },
+       .probe          = stv090x_probe,
+       .remove         = stv090x_remove,
+       .id_table       = stv090x_id_table,
+};
+
+module_i2c_driver(stv090x_driver);
+
 MODULE_PARM_DESC(verbose, "Set Verbosity level");
 MODULE_AUTHOR("Manu Abraham");
 MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend");