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 
10 struct a8293_dev {
11 	struct i2c_client *client;
12 	u8 reg[2];
13 };
14 
15 static 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;
60 err:
61 	dev_dbg(&client->dev, "failed=%d\n", ret);
62 	return ret;
63 }
64 
65 static 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;
94 err_kfree:
95 	kfree(dev);
96 err:
97 	dev_dbg(&client->dev, "failed=%d\n", ret);
98 	return ret;
99 }
100 
101 static void 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 }
109 
110 static const struct i2c_device_id a8293_id_table[] = {
111 	{"a8293", 0},
112 	{}
113 };
114 MODULE_DEVICE_TABLE(i2c, a8293_id_table);
115 
116 static struct i2c_driver a8293_driver = {
117 	.driver = {
118 		.name	= "a8293",
119 		.suppress_bind_attrs = true,
120 	},
121 	.probe		= a8293_probe,
122 	.remove		= a8293_remove,
123 	.id_table	= a8293_id_table,
124 };
125 
126 module_i2c_driver(a8293_driver);
127 
128 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
129 MODULE_DESCRIPTION("Allegro A8293 SEC driver");
130 MODULE_LICENSE("GPL");
131