[media] rtl2832: convert driver to I2C binding
[deliverable/linux.git] / drivers / media / dvb-frontends / rtl2832.c
index 9026e1aee163e5081a594b137a19a5097c711c22..53b446afe03061fd4a96a7b6198374d7d3e86913 100644 (file)
@@ -1183,6 +1183,114 @@ static struct dvb_frontend_ops rtl2832_ops = {
        .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl,
 };
 
+static int rtl2832_probe(struct i2c_client *client,
+               const struct i2c_device_id *id)
+{
+       struct rtl2832_platform_data *pdata = client->dev.platform_data;
+       const struct rtl2832_config *config = pdata->config;
+       struct i2c_adapter *i2c = client->adapter;
+       struct rtl2832_priv *priv;
+       int ret;
+       u8 tmp;
+
+       dev_dbg(&client->dev, "\n");
+
+       /* Caller really need to provide pointer for frontend we create. */
+       if (pdata->dvb_frontend == NULL) {
+               dev_err(&client->dev, "frontend pointer not defined\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* allocate memory for the internal state */
+       priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL);
+       if (priv == NULL) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       /* setup the priv */
+       priv->client = client;
+       priv->i2c = i2c;
+       priv->tuner = config->tuner;
+       priv->sleeping = true;
+       memcpy(&priv->cfg, config, sizeof(struct rtl2832_config));
+       INIT_DELAYED_WORK(&priv->i2c_gate_work, rtl2832_i2c_gate_work);
+
+       /* create muxed i2c adapter for demod itself */
+       priv->i2c_adapter = i2c_add_mux_adapter(i2c, &i2c->dev, priv, 0, 0, 0,
+                       rtl2832_select, NULL);
+       if (priv->i2c_adapter == NULL) {
+               ret = -ENODEV;
+               goto err_kfree;
+       }
+
+       /* check if the demod is there */
+       ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp);
+       if (ret)
+               goto err_i2c_del_mux_adapter;
+
+       /* create muxed i2c adapter for demod tuner bus */
+       priv->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, &i2c->dev, priv,
+                       0, 1, 0, rtl2832_select, rtl2832_deselect);
+       if (priv->i2c_adapter_tuner == NULL) {
+               ret = -ENODEV;
+               goto err_i2c_del_mux_adapter;
+       }
+
+       /* create dvb_frontend */
+       memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops));
+       priv->fe.ops.release = NULL;
+       priv->fe.demodulator_priv = priv;
+       i2c_set_clientdata(client, priv);
+       *pdata->dvb_frontend = &priv->fe;
+
+       dev_info(&client->dev, "Realtek RTL2832 successfully attached\n");
+       return 0;
+err_i2c_del_mux_adapter:
+       i2c_del_mux_adapter(priv->i2c_adapter);
+err_kfree:
+       kfree(priv);
+err:
+       dev_dbg(&client->dev, "failed=%d\n", ret);
+       return ret;
+}
+
+static int rtl2832_remove(struct i2c_client *client)
+{
+       struct rtl2832_priv *priv = i2c_get_clientdata(client);
+
+       dev_dbg(&client->dev, "\n");
+
+       cancel_delayed_work_sync(&priv->i2c_gate_work);
+
+       i2c_del_mux_adapter(priv->i2c_adapter_tuner);
+
+       i2c_del_mux_adapter(priv->i2c_adapter);
+
+       kfree(priv);
+
+       return 0;
+}
+
+static const struct i2c_device_id rtl2832_id_table[] = {
+       {"rtl2832", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, rtl2832_id_table);
+
+static struct i2c_driver rtl2832_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "rtl2832",
+       },
+       .probe          = rtl2832_probe,
+       .remove         = rtl2832_remove,
+       .id_table       = rtl2832_id_table,
+};
+
+module_i2c_driver(rtl2832_driver);
+
 MODULE_AUTHOR("Thomas Mair <mair.thomas86@gmail.com>");
 MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver");
 MODULE_LICENSE("GPL");
This page took 0.028617 seconds and 5 git commands to generate.