1 /* 2 * ddbridge-ci.c: Digital Devices bridge CI (DuoFlex, CI Bridge) support 3 * 4 * Copyright (C) 2010-2017 Digital Devices GmbH 5 * Marcus Metzler <mocm@metzlerbros.de> 6 * Ralph Metzler <rjkm@metzlerbros.de> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 only, as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * To obtain the license, point your browser to 18 * http://www.gnu.org/copyleft/gpl.html 19 */ 20 21 #include "ddbridge.h" 22 #include "ddbridge-regs.h" 23 #include "ddbridge-io.h" 24 #include "ddbridge-i2c.h" 25 26 #include "cxd2099.h" 27 28 /* Octopus CI internal CI interface */ 29 30 static int wait_ci_ready(struct ddb_ci *ci) 31 { 32 u32 count = 10; 33 34 ndelay(500); 35 do { 36 if (ddbreadl(ci->port->dev, 37 CI_CONTROL(ci->nr)) & CI_READY) 38 break; 39 usleep_range(1, 2); 40 if ((--count) == 0) 41 return -1; 42 } while (1); 43 return 0; 44 } 45 46 static int read_attribute_mem(struct dvb_ca_en50221 *ca, 47 int slot, int address) 48 { 49 struct ddb_ci *ci = ca->data; 50 u32 val, off = (address >> 1) & (CI_BUFFER_SIZE - 1); 51 52 if (address > CI_BUFFER_SIZE) 53 return -1; 54 ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, 55 CI_DO_READ_ATTRIBUTES(ci->nr)); 56 wait_ci_ready(ci); 57 val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); 58 return val; 59 } 60 61 static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, 62 int address, u8 value) 63 { 64 struct ddb_ci *ci = ca->data; 65 66 ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, 67 CI_DO_ATTRIBUTE_RW(ci->nr)); 68 wait_ci_ready(ci); 69 return 0; 70 } 71 72 static int read_cam_control(struct dvb_ca_en50221 *ca, 73 int slot, u8 address) 74 { 75 u32 count = 100; 76 struct ddb_ci *ci = ca->data; 77 u32 res; 78 79 ddbwritel(ci->port->dev, CI_READ_CMD | address, 80 CI_DO_IO_RW(ci->nr)); 81 ndelay(500); 82 do { 83 res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); 84 if (res & CI_READY) 85 break; 86 usleep_range(1, 2); 87 if ((--count) == 0) 88 return -1; 89 } while (1); 90 return 0xff & res; 91 } 92 93 static int write_cam_control(struct dvb_ca_en50221 *ca, int slot, 94 u8 address, u8 value) 95 { 96 struct ddb_ci *ci = ca->data; 97 98 ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, 99 CI_DO_IO_RW(ci->nr)); 100 wait_ci_ready(ci); 101 return 0; 102 } 103 104 static int slot_reset(struct dvb_ca_en50221 *ca, int slot) 105 { 106 struct ddb_ci *ci = ca->data; 107 108 ddbwritel(ci->port->dev, CI_POWER_ON, 109 CI_CONTROL(ci->nr)); 110 msleep(100); 111 ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, 112 CI_CONTROL(ci->nr)); 113 ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM, 114 CI_CONTROL(ci->nr)); 115 usleep_range(20, 25); 116 ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, 117 CI_CONTROL(ci->nr)); 118 return 0; 119 } 120 121 static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) 122 { 123 struct ddb_ci *ci = ca->data; 124 125 ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr)); 126 msleep(300); 127 return 0; 128 } 129 130 static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) 131 { 132 struct ddb_ci *ci = ca->data; 133 u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); 134 135 ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE, 136 CI_CONTROL(ci->nr)); 137 return 0; 138 } 139 140 static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) 141 { 142 struct ddb_ci *ci = ca->data; 143 u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); 144 int stat = 0; 145 146 if (val & CI_CAM_DETECT) 147 stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; 148 if (val & CI_CAM_READY) 149 stat |= DVB_CA_EN50221_POLL_CAM_READY; 150 return stat; 151 } 152 153 static struct dvb_ca_en50221 en_templ = { 154 .read_attribute_mem = read_attribute_mem, 155 .write_attribute_mem = write_attribute_mem, 156 .read_cam_control = read_cam_control, 157 .write_cam_control = write_cam_control, 158 .slot_reset = slot_reset, 159 .slot_shutdown = slot_shutdown, 160 .slot_ts_enable = slot_ts_enable, 161 .poll_slot_status = poll_slot_status, 162 }; 163 164 static void ci_attach(struct ddb_port *port) 165 { 166 struct ddb_ci *ci = NULL; 167 168 ci = kzalloc(sizeof(*ci), GFP_KERNEL); 169 if (!ci) 170 return; 171 memcpy(&ci->en, &en_templ, sizeof(en_templ)); 172 ci->en.data = ci; 173 port->en = &ci->en; 174 ci->port = port; 175 ci->nr = port->nr - 2; 176 } 177 178 /* DuoFlex Dual CI support */ 179 180 static int write_creg(struct ddb_ci *ci, u8 data, u8 mask) 181 { 182 struct i2c_adapter *i2c = &ci->port->i2c->adap; 183 u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; 184 185 ci->port->creg = (ci->port->creg & ~mask) | data; 186 return i2c_write_reg(i2c, adr, 0x02, ci->port->creg); 187 } 188 189 static int read_attribute_mem_xo2(struct dvb_ca_en50221 *ca, 190 int slot, int address) 191 { 192 struct ddb_ci *ci = ca->data; 193 struct i2c_adapter *i2c = &ci->port->i2c->adap; 194 u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; 195 int res; 196 u8 val; 197 198 res = i2c_read_reg16(i2c, adr, 0x8000 | address, &val); 199 return res ? res : val; 200 } 201 202 static int write_attribute_mem_xo2(struct dvb_ca_en50221 *ca, int slot, 203 int address, u8 value) 204 { 205 struct ddb_ci *ci = ca->data; 206 struct i2c_adapter *i2c = &ci->port->i2c->adap; 207 u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; 208 209 return i2c_write_reg16(i2c, adr, 0x8000 | address, value); 210 } 211 212 static int read_cam_control_xo2(struct dvb_ca_en50221 *ca, 213 int slot, u8 address) 214 { 215 struct ddb_ci *ci = ca->data; 216 struct i2c_adapter *i2c = &ci->port->i2c->adap; 217 u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; 218 u8 val; 219 int res; 220 221 res = i2c_read_reg(i2c, adr, 0x20 | (address & 3), &val); 222 return res ? res : val; 223 } 224 225 static int write_cam_control_xo2(struct dvb_ca_en50221 *ca, int slot, 226 u8 address, u8 value) 227 { 228 struct ddb_ci *ci = ca->data; 229 struct i2c_adapter *i2c = &ci->port->i2c->adap; 230 u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; 231 232 return i2c_write_reg(i2c, adr, 0x20 | (address & 3), value); 233 } 234 235 static int slot_reset_xo2(struct dvb_ca_en50221 *ca, int slot) 236 { 237 struct ddb_ci *ci = ca->data; 238 239 dev_dbg(ci->port->dev->dev, "%s\n", __func__); 240 write_creg(ci, 0x01, 0x01); 241 write_creg(ci, 0x04, 0x04); 242 msleep(20); 243 write_creg(ci, 0x02, 0x02); 244 write_creg(ci, 0x00, 0x04); 245 write_creg(ci, 0x18, 0x18); 246 return 0; 247 } 248 249 static int slot_shutdown_xo2(struct dvb_ca_en50221 *ca, int slot) 250 { 251 struct ddb_ci *ci = ca->data; 252 253 dev_dbg(ci->port->dev->dev, "%s\n", __func__); 254 write_creg(ci, 0x10, 0xff); 255 write_creg(ci, 0x08, 0x08); 256 return 0; 257 } 258 259 static int slot_ts_enable_xo2(struct dvb_ca_en50221 *ca, int slot) 260 { 261 struct ddb_ci *ci = ca->data; 262 263 dev_info(ci->port->dev->dev, "%s\n", __func__); 264 write_creg(ci, 0x00, 0x10); 265 return 0; 266 } 267 268 static int poll_slot_status_xo2(struct dvb_ca_en50221 *ca, int slot, int open) 269 { 270 struct ddb_ci *ci = ca->data; 271 struct i2c_adapter *i2c = &ci->port->i2c->adap; 272 u8 adr = (ci->port->type == DDB_CI_EXTERNAL_XO2) ? 0x12 : 0x13; 273 u8 val = 0; 274 int stat = 0; 275 276 i2c_read_reg(i2c, adr, 0x01, &val); 277 278 if (val & 2) 279 stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; 280 if (val & 1) 281 stat |= DVB_CA_EN50221_POLL_CAM_READY; 282 return stat; 283 } 284 285 static struct dvb_ca_en50221 en_xo2_templ = { 286 .read_attribute_mem = read_attribute_mem_xo2, 287 .write_attribute_mem = write_attribute_mem_xo2, 288 .read_cam_control = read_cam_control_xo2, 289 .write_cam_control = write_cam_control_xo2, 290 .slot_reset = slot_reset_xo2, 291 .slot_shutdown = slot_shutdown_xo2, 292 .slot_ts_enable = slot_ts_enable_xo2, 293 .poll_slot_status = poll_slot_status_xo2, 294 }; 295 296 static void ci_xo2_attach(struct ddb_port *port) 297 { 298 struct ddb_ci *ci; 299 300 ci = kzalloc(sizeof(*ci), GFP_KERNEL); 301 if (!ci) 302 return; 303 memcpy(&ci->en, &en_xo2_templ, sizeof(en_xo2_templ)); 304 ci->en.data = ci; 305 port->en = &ci->en; 306 ci->port = port; 307 ci->nr = port->nr - 2; 308 ci->port->creg = 0; 309 write_creg(ci, 0x10, 0xff); 310 write_creg(ci, 0x08, 0x08); 311 } 312 313 static struct cxd2099_cfg cxd_cfg = { 314 .bitrate = 72000, 315 .adr = 0x40, 316 .polarity = 1, 317 .clock_mode = 1, 318 .max_i2c = 512, 319 }; 320 321 int ddb_ci_attach(struct ddb_port *port, u32 bitrate) 322 { 323 switch (port->type) { 324 case DDB_CI_EXTERNAL_SONY: 325 cxd_cfg.bitrate = bitrate; 326 port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); 327 if (!port->en) 328 return -ENODEV; 329 dvb_ca_en50221_init(port->dvb[0].adap, 330 port->en, 0, 1); 331 break; 332 333 case DDB_CI_EXTERNAL_XO2: 334 case DDB_CI_EXTERNAL_XO2_B: 335 ci_xo2_attach(port); 336 if (!port->en) 337 return -ENODEV; 338 dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); 339 break; 340 341 case DDB_CI_INTERNAL: 342 ci_attach(port); 343 if (!port->en) 344 return -ENODEV; 345 dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1); 346 break; 347 } 348 return 0; 349 } 350