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