root/drivers/media/pci/ddbridge/ddbridge-ci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wait_ci_ready
  2. read_attribute_mem
  3. write_attribute_mem
  4. read_cam_control
  5. write_cam_control
  6. slot_reset
  7. slot_shutdown
  8. slot_ts_enable
  9. poll_slot_status
  10. ci_attach
  11. write_creg
  12. read_attribute_mem_xo2
  13. write_attribute_mem_xo2
  14. read_cam_control_xo2
  15. write_cam_control_xo2
  16. slot_reset_xo2
  17. slot_shutdown_xo2
  18. slot_ts_enable_xo2
  19. poll_slot_status_xo2
  20. ci_xo2_attach
  21. ci_cxd2099_attach
  22. ddb_ci_attach
  23. ddb_ci_detach

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * ddbridge-ci.c: Digital Devices bridge CI (DuoFlex, CI Bridge) support
   4  *
   5  * Copyright (C) 2010-2017 Digital Devices GmbH
   6  *                         Marcus Metzler <mocm@metzlerbros.de>
   7  *                         Ralph Metzler <rjkm@metzlerbros.de>
   8  *
   9  * This program is free software; you can redistribute it and/or
  10  * modify it under the terms of the GNU General Public License
  11  * version 2 only, as published by the Free Software Foundation.
  12  *
  13  * This program is distributed in the hope that it will be useful,
  14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16  * GNU General Public License for more details.
  17  */
  18 
  19 #include "ddbridge.h"
  20 #include "ddbridge-regs.h"
  21 #include "ddbridge-ci.h"
  22 #include "ddbridge-io.h"
  23 #include "ddbridge-i2c.h"
  24 
  25 #include "cxd2099.h"
  26 
  27 /* Octopus CI internal CI interface */
  28 
  29 static int wait_ci_ready(struct ddb_ci *ci)
  30 {
  31         u32 count = 10;
  32 
  33         ndelay(500);
  34         do {
  35                 if (ddbreadl(ci->port->dev,
  36                              CI_CONTROL(ci->nr)) & CI_READY)
  37                         break;
  38                 usleep_range(1, 2);
  39                 if ((--count) == 0)
  40                         return -1;
  41         } while (1);
  42         return 0;
  43 }
  44 
  45 static int read_attribute_mem(struct dvb_ca_en50221 *ca,
  46                               int slot, int address)
  47 {
  48         struct ddb_ci *ci = ca->data;
  49         u32 val, off = (address >> 1) & (CI_BUFFER_SIZE - 1);
  50 
  51         if (address > CI_BUFFER_SIZE)
  52                 return -1;
  53         ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address,
  54                   CI_DO_READ_ATTRIBUTES(ci->nr));
  55         wait_ci_ready(ci);
  56         val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off);
  57         return val;
  58 }
  59 
  60 static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
  61                                int address, u8 value)
  62 {
  63         struct ddb_ci *ci = ca->data;
  64 
  65         ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
  66                   CI_DO_ATTRIBUTE_RW(ci->nr));
  67         wait_ci_ready(ci);
  68         return 0;
  69 }
  70 
  71 static int read_cam_control(struct dvb_ca_en50221 *ca,
  72                             int slot, u8 address)
  73 {
  74         u32 count = 100;
  75         struct ddb_ci *ci = ca->data;
  76         u32 res;
  77 
  78         ddbwritel(ci->port->dev, CI_READ_CMD | address,
  79                   CI_DO_IO_RW(ci->nr));
  80         ndelay(500);
  81         do {
  82                 res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr));
  83                 if (res & CI_READY)
  84                         break;
  85                 usleep_range(1, 2);
  86                 if ((--count) == 0)
  87                         return -1;
  88         } while (1);
  89         return 0xff & res;
  90 }
  91 
  92 static int write_cam_control(struct dvb_ca_en50221 *ca, int slot,
  93                              u8 address, u8 value)
  94 {
  95         struct ddb_ci *ci = ca->data;
  96 
  97         ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
  98                   CI_DO_IO_RW(ci->nr));
  99         wait_ci_ready(ci);
 100         return 0;
 101 }
 102 
 103 static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
 104 {
 105         struct ddb_ci *ci = ca->data;
 106 
 107         ddbwritel(ci->port->dev, CI_POWER_ON,
 108                   CI_CONTROL(ci->nr));
 109         msleep(100);
 110         ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM,
 111                   CI_CONTROL(ci->nr));
 112         ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
 113                   CI_CONTROL(ci->nr));
 114         usleep_range(20, 25);
 115         ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON,
 116                   CI_CONTROL(ci->nr));
 117         return 0;
 118 }
 119 
 120 static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
 121 {
 122         struct ddb_ci *ci = ca->data;
 123 
 124         ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr));
 125         msleep(300);
 126         return 0;
 127 }
 128 
 129 static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
 130 {
 131         struct ddb_ci *ci = ca->data;
 132         u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
 133 
 134         ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE,
 135                   CI_CONTROL(ci->nr));
 136         return 0;
 137 }
 138 
 139 static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
 140 {
 141         struct ddb_ci *ci = ca->data;
 142         u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
 143         int stat = 0;
 144 
 145         if (val & CI_CAM_DETECT)
 146                 stat |= DVB_CA_EN50221_POLL_CAM_PRESENT;
 147         if (val & CI_CAM_READY)
 148                 stat |= DVB_CA_EN50221_POLL_CAM_READY;
 149         return stat;
 150 }
 151 
 152 static struct dvb_ca_en50221 en_templ = {
 153         .read_attribute_mem  = read_attribute_mem,
 154         .write_attribute_mem = write_attribute_mem,
 155         .read_cam_control    = read_cam_control,
 156         .write_cam_control   = write_cam_control,
 157         .slot_reset          = slot_reset,
 158         .slot_shutdown       = slot_shutdown,
 159         .slot_ts_enable      = slot_ts_enable,
 160         .poll_slot_status    = poll_slot_status,
 161 };
 162 
 163 static void ci_attach(struct ddb_port *port)
 164 {
 165         struct ddb_ci *ci;
 166 
 167         ci = kzalloc(sizeof(*ci), GFP_KERNEL);
 168         if (!ci)
 169                 return;
 170         memcpy(&ci->en, &en_templ, sizeof(en_templ));
 171         ci->en.data = ci;
 172         port->en = &ci->en;
 173         port->en_freedata = 1;
 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_dbg(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         port->en_freedata = 1;
 307         ci->port = port;
 308         ci->nr = port->nr - 2;
 309         ci->port->creg = 0;
 310         write_creg(ci, 0x10, 0xff);
 311         write_creg(ci, 0x08, 0x08);
 312 }
 313 
 314 static const struct cxd2099_cfg cxd_cfgtmpl = {
 315         .bitrate =  72000,
 316         .polarity = 1,
 317         .clock_mode = 1,
 318         .max_i2c = 512,
 319 };
 320 
 321 static int ci_cxd2099_attach(struct ddb_port *port, u32 bitrate)
 322 {
 323         struct cxd2099_cfg cxd_cfg = cxd_cfgtmpl;
 324         struct i2c_client *client;
 325 
 326         cxd_cfg.bitrate = bitrate;
 327         cxd_cfg.en = &port->en;
 328 
 329         client = dvb_module_probe("cxd2099", NULL, &port->i2c->adap,
 330                                   0x40, &cxd_cfg);
 331         if (!client)
 332                 goto err;
 333 
 334         port->dvb[0].i2c_client[0] = client;
 335         port->en_freedata = 0;
 336         return 0;
 337 
 338 err:
 339         dev_err(port->dev->dev, "CXD2099AR attach failed\n");
 340         return -ENODEV;
 341 }
 342 
 343 int ddb_ci_attach(struct ddb_port *port, u32 bitrate)
 344 {
 345         int ret;
 346 
 347         switch (port->type) {
 348         case DDB_CI_EXTERNAL_SONY:
 349                 ret = ci_cxd2099_attach(port, bitrate);
 350                 if (ret)
 351                         return -ENODEV;
 352                 break;
 353         case DDB_CI_EXTERNAL_XO2:
 354         case DDB_CI_EXTERNAL_XO2_B:
 355                 ci_xo2_attach(port);
 356                 break;
 357         case DDB_CI_INTERNAL:
 358                 ci_attach(port);
 359                 break;
 360         default:
 361                 return -ENODEV;
 362         }
 363 
 364         if (!port->en)
 365                 return -ENODEV;
 366         dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1);
 367         return 0;
 368 }
 369 
 370 void ddb_ci_detach(struct ddb_port *port)
 371 {
 372         if (port->dvb[0].dev)
 373                 dvb_unregister_device(port->dvb[0].dev);
 374         if (port->en) {
 375                 dvb_ca_en50221_release(port->en);
 376 
 377                 dvb_module_release(port->dvb[0].i2c_client[0]);
 378                 port->dvb[0].i2c_client[0] = NULL;
 379 
 380                 /* free alloc'ed memory if needed */
 381                 if (port->en_freedata)
 382                         kfree(port->en->data);
 383 
 384                 port->en = NULL;
 385         }
 386 }

/* [<][>][^][v][top][bottom][index][help] */