1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Allegro A8293 SEC driver
4 *
5 * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
6 */
7
8#include "a8293.h"
9
10struct a8293_dev {
11	struct i2c_client *client;
12	u8 reg[2];
13};
14
15static int a8293_set_voltage(struct dvb_frontend *fe,
16			     enum fe_sec_voltage fe_sec_voltage)
17{
18	struct a8293_dev *dev = fe->sec_priv;
19	struct i2c_client *client = dev->client;
20	int ret;
21	u8 reg0, reg1;
22
23	dev_dbg(&client->dev, "fe_sec_voltage=%d\n", fe_sec_voltage);
24
25	switch (fe_sec_voltage) {
26	case SEC_VOLTAGE_OFF:
27		/* ENB=0 */
28		reg0 = 0x10;
29		break;
30	case SEC_VOLTAGE_13:
31		/* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/
32		reg0 = 0x31;
33		break;
34	case SEC_VOLTAGE_18:
35		/* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/
36		reg0 = 0x38;
37		break;
38	default:
39		ret = -EINVAL;
40		goto err;
41	}
42	if (reg0 != dev->reg[0]) {
43		ret = i2c_master_send(client, &reg0, 1);
44		if (ret < 0)
45			goto err;
46		dev->reg[0] = reg0;
47	}
48
49	/* TMODE=0, TGATE=1 */
50	reg1 = 0x82;
51	if (reg1 != dev->reg[1]) {
52		ret = i2c_master_send(client, &reg1, 1);
53		if (ret < 0)
54			goto err;
55		dev->reg[1] = reg1;
56	}
57
58	usleep_range(1500, 50000);
59	return 0;
60err:
61	dev_dbg(&client->dev, "failed=%d\n", ret);
62	return ret;
63}
64
65static int a8293_probe(struct i2c_client *client,
66		       const struct i2c_device_id *id)
67{
68	struct a8293_dev *dev;
69	struct a8293_platform_data *pdata = client->dev.platform_data;
70	struct dvb_frontend *fe = pdata->dvb_frontend;
71	int ret;
72	u8 buf[2];
73
74	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
75	if (!dev) {
76		ret = -ENOMEM;
77		goto err;
78	}
79
80	dev->client = client;
81
82	/* check if the SEC is there */
83	ret = i2c_master_recv(client, buf, 2);
84	if (ret < 0)
85		goto err_kfree;
86
87	/* override frontend ops */
88	fe->ops.set_voltage = a8293_set_voltage;
89	fe->sec_priv = dev;
90	i2c_set_clientdata(client, dev);
91
92	dev_info(&client->dev, "Allegro A8293 SEC successfully attached\n");
93	return 0;
94err_kfree:
95	kfree(dev);
96err:
97	dev_dbg(&client->dev, "failed=%d\n", ret);
98	return ret;
99}
100
101static int a8293_remove(struct i2c_client *client)
102{
103	struct a8293_dev *dev = i2c_get_clientdata(client);
104
105	dev_dbg(&client->dev, "\n");
106
107	kfree(dev);
108	return 0;
109}
110
111static const struct i2c_device_id a8293_id_table[] = {
112	{"a8293", 0},
113	{}
114};
115MODULE_DEVICE_TABLE(i2c, a8293_id_table);
116
117static struct i2c_driver a8293_driver = {
118	.driver = {
119		.name	= "a8293",
120		.suppress_bind_attrs = true,
121	},
122	.probe		= a8293_probe,
123	.remove		= a8293_remove,
124	.id_table	= a8293_id_table,
125};
126
127module_i2c_driver(a8293_driver);
128
129MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
130MODULE_DESCRIPTION("Allegro A8293 SEC driver");
131MODULE_LICENSE("GPL");
132