Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2c8386f authored by Antti Palosaari's avatar Antti Palosaari Committed by Mauro Carvalho Chehab
Browse files

[media] rtl2832: convert driver to I2C binding



Convert that driver to I2C driver model.
Legacy DVB binding is left also for later removal...

Tested-by: default avatarBenjamin Larsson <benjamin@southpole.se>
Signed-off-by: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent c97da154
Loading
Loading
Loading
Loading
+108 −0
Original line number Diff line number Diff line
@@ -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");
+10 −0
Original line number Diff line number Diff line
@@ -50,6 +50,16 @@ struct rtl2832_config {
	u8 tuner;
};

struct rtl2832_platform_data {
	const struct rtl2832_config *config;

	/*
	 * frontend
	 * returned by driver
	 */
	struct dvb_frontend **dvb_frontend;
};

#if IS_ENABLED(CONFIG_DVB_RTL2832)
struct dvb_frontend *rtl2832_attach(
	const struct rtl2832_config *cfg,
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/i2c-mux.h>

struct rtl2832_priv {
	struct i2c_client *client;
	struct i2c_adapter *i2c;
	struct i2c_adapter *i2c_adapter;
	struct i2c_adapter *i2c_adapter_tuner;