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 #define A8293_FLAG_ODT 0x10 11 12 struct a8293_dev { 13 struct i2c_client *client; 14 u8 reg[2]; 15 int volt_slew_nanos_per_mv; 16 }; 17 18 /* 19 * When increasing voltage, do so in minimal steps over time, minimizing 20 * risk of vIN undervoltage. 21 */ 22 23 static int a8293_set_voltage_slew(struct a8293_dev *dev, 24 struct i2c_client *client, 25 enum fe_sec_voltage fe_sec_voltage, 26 int min_nanos_per_mv) 27 { 28 int ret; 29 u8 reg0, reg1; 30 int new_volt_idx; 31 const int idx_to_mv[] = { 32 0, 12709, 13042, 13375, 14042, 15042, 18042, 18709, 19042 33 }; 34 const u8 idx_to_reg[] = { 35 0x00, 0x20, 0x21, 0x22, 0x24, 0x27, 0x28, 0x2A, 0x2B 36 }; 37 int this_volt_idx; 38 u8 status; 39 int prev_volt_idx; 40 41 dev_dbg(&client->dev, "set_voltage_slew fe_sec_voltage=%d\n", 42 fe_sec_voltage); 43 44 /* Read status register to clear any stale faults. */ 45 ret = i2c_master_recv(client, &status, 1); 46 if (ret < 0) 47 goto err; 48 49 /* Determine previous voltage */ 50 switch (dev->reg[0] & 0x2F) { 51 case 0x00: 52 prev_volt_idx = 0; 53 break; 54 case 0x20: 55 prev_volt_idx = 1; 56 break; 57 case 0x21: 58 prev_volt_idx = 2; 59 break; 60 case 0x22: 61 prev_volt_idx = 3; 62 break; 63 case 0x24: 64 prev_volt_idx = 4; 65 break; 66 case 0x27: 67 prev_volt_idx = 5; 68 break; 69 case 0x28: 70 prev_volt_idx = 6; 71 break; 72 case 0x2A: 73 prev_volt_idx = 7; 74 break; 75 case 0x2B: 76 prev_volt_idx = 8; 77 break; 78 default: 79 prev_volt_idx = 0; 80 } 81 82 /* Determine new voltage */ 83 switch (fe_sec_voltage) { 84 case SEC_VOLTAGE_OFF: 85 new_volt_idx = 0; 86 break; 87 case SEC_VOLTAGE_13: 88 new_volt_idx = 2; 89 break; 90 case SEC_VOLTAGE_18: 91 new_volt_idx = 6; 92 break; 93 default: 94 ret = -EINVAL; 95 goto err; 96 } 97 98 /* Slew to new voltage if new voltage is greater than current voltage */ 99 this_volt_idx = prev_volt_idx; 100 if (this_volt_idx < new_volt_idx) { 101 while (this_volt_idx < new_volt_idx) { 102 int delta_mv = idx_to_mv[this_volt_idx+1] - idx_to_mv[this_volt_idx]; 103 int min_wait_time = delta_mv * min_nanos_per_mv; 104 105 reg0 = idx_to_reg[this_volt_idx+1]; 106 reg0 |= A8293_FLAG_ODT; 107 108 ret = i2c_master_send(client, ®0, 1); 109 if (ret < 0) 110 goto err; 111 dev->reg[0] = reg0; 112 this_volt_idx++; 113 usleep_range(min_wait_time, min_wait_time * 2); 114 } 115 } else { /* Else just set the voltage */ 116 reg0 = idx_to_reg[new_volt_idx]; 117 reg0 |= A8293_FLAG_ODT; 118 ret = i2c_master_send(client, ®0, 1); 119 if (ret < 0) 120 goto err; 121 dev->reg[0] = reg0; 122 } 123 124 /* TMODE=0, TGATE=1 */ 125 reg1 = 0x82; 126 if (reg1 != dev->reg[1]) { 127 ret = i2c_master_send(client, ®1, 1); 128 if (ret < 0) 129 goto err; 130 dev->reg[1] = reg1; 131 } 132 133 usleep_range(1500, 5000); 134 135 return 0; 136 err: 137 dev_dbg(&client->dev, "failed=%d\n", ret); 138 return ret; 139 } 140 141 142 static int a8293_set_voltage_noslew(struct dvb_frontend *fe, 143 enum fe_sec_voltage fe_sec_voltage) 144 { 145 struct a8293_dev *dev = fe->sec_priv; 146 struct i2c_client *client = dev->client; 147 int ret; 148 u8 reg0, reg1; 149 150 dev_dbg(&client->dev, "set_voltage_noslew fe_sec_voltage=%d\n", 151 fe_sec_voltage); 152 153 switch (fe_sec_voltage) { 154 case SEC_VOLTAGE_OFF: 155 /* ENB=0 */ 156 reg0 = 0x10; 157 break; 158 case SEC_VOLTAGE_13: 159 /* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/ 160 reg0 = 0x31; 161 break; 162 case SEC_VOLTAGE_18: 163 /* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/ 164 reg0 = 0x38; 165 break; 166 default: 167 ret = -EINVAL; 168 goto err; 169 } 170 if (reg0 != dev->reg[0]) { 171 ret = i2c_master_send(client, ®0, 1); 172 if (ret < 0) 173 goto err; 174 dev->reg[0] = reg0; 175 } 176 177 /* TMODE=0, TGATE=1 */ 178 reg1 = 0x82; 179 if (reg1 != dev->reg[1]) { 180 ret = i2c_master_send(client, ®1, 1); 181 if (ret < 0) 182 goto err; 183 dev->reg[1] = reg1; 184 } 185 186 usleep_range(1500, 50000); 187 return 0; 188 err: 189 dev_dbg(&client->dev, "failed=%d\n", ret); 190 return ret; 191 } 192 193 static int a8293_set_voltage(struct dvb_frontend *fe, 194 enum fe_sec_voltage fe_sec_voltage) 195 { 196 struct a8293_dev *dev = fe->sec_priv; 197 struct i2c_client *client = dev->client; 198 int volt_slew_nanos_per_mv = dev->volt_slew_nanos_per_mv; 199 200 dev_dbg(&client->dev, "set_voltage volt_slew_nanos_per_mv=%d\n", 201 volt_slew_nanos_per_mv); 202 203 /* Use slew version if slew rate is set to a sane value */ 204 if (volt_slew_nanos_per_mv > 0 && volt_slew_nanos_per_mv < 1600) 205 a8293_set_voltage_slew(dev, client, fe_sec_voltage, 206 volt_slew_nanos_per_mv); 207 else 208 a8293_set_voltage_noslew(fe, fe_sec_voltage); 209 210 return 0; 211 } 212 213 static int a8293_probe(struct i2c_client *client) 214 { 215 struct a8293_dev *dev; 216 struct a8293_platform_data *pdata = client->dev.platform_data; 217 struct dvb_frontend *fe = pdata->dvb_frontend; 218 int ret; 219 u8 buf[2]; 220 221 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 222 if (!dev) { 223 ret = -ENOMEM; 224 goto err; 225 } 226 227 dev->client = client; 228 dev->volt_slew_nanos_per_mv = pdata->volt_slew_nanos_per_mv; 229 230 /* check if the SEC is there */ 231 ret = i2c_master_recv(client, buf, 2); 232 if (ret < 0) 233 goto err_kfree; 234 235 /* override frontend ops */ 236 fe->ops.set_voltage = a8293_set_voltage; 237 fe->sec_priv = dev; 238 i2c_set_clientdata(client, dev); 239 240 dev_info(&client->dev, "Allegro A8293 SEC successfully attached\n"); 241 return 0; 242 err_kfree: 243 kfree(dev); 244 err: 245 dev_dbg(&client->dev, "failed=%d\n", ret); 246 return ret; 247 } 248 249 static void a8293_remove(struct i2c_client *client) 250 { 251 struct a8293_dev *dev = i2c_get_clientdata(client); 252 253 dev_dbg(&client->dev, "\n"); 254 255 kfree(dev); 256 } 257 258 static const struct i2c_device_id a8293_id_table[] = { 259 {"a8293", 0}, 260 {} 261 }; 262 MODULE_DEVICE_TABLE(i2c, a8293_id_table); 263 264 static struct i2c_driver a8293_driver = { 265 .driver = { 266 .name = "a8293", 267 .suppress_bind_attrs = true, 268 }, 269 .probe = a8293_probe, 270 .remove = a8293_remove, 271 .id_table = a8293_id_table, 272 }; 273 274 module_i2c_driver(a8293_driver); 275 276 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 277 MODULE_DESCRIPTION("Allegro A8293 SEC driver"); 278 MODULE_LICENSE("GPL"); 279