1 // SPDX-License-Identifier: GPL-2.0
3 * ddbridge-ci.c: Digital Devices bridge CI (DuoFlex, CI Bridge) support
5 * Copyright (C) 2010-2017 Digital Devices GmbH
6 * Marcus Metzler <mocm@metzlerbros.de>
7 * Ralph Metzler <rjkm@metzlerbros.de>
11 #include "ddbridge-regs.h"
12 #include "ddbridge-ci.h"
13 #include "ddbridge-io.h"
14 #include "ddbridge-i2c.h"
18 /* Octopus CI internal CI interface */
20 static int wait_ci_ready(struct ddb_ci
*ci
)
26 if (ddbreadl(ci
->port
->dev
,
27 CI_CONTROL(ci
->nr
)) & CI_READY
)
36 static int read_attribute_mem(struct dvb_ca_en50221
*ca
,
37 int slot
, int address
)
39 struct ddb_ci
*ci
= ca
->data
;
40 u32 val
, off
= (address
>> 1) & (CI_BUFFER_SIZE
- 1);
42 if (address
> CI_BUFFER_SIZE
)
44 ddbwritel(ci
->port
->dev
, CI_READ_CMD
| (1 << 16) | address
,
45 CI_DO_READ_ATTRIBUTES(ci
->nr
));
47 val
= 0xff & ddbreadl(ci
->port
->dev
, CI_BUFFER(ci
->nr
) + off
);
51 static int write_attribute_mem(struct dvb_ca_en50221
*ca
, int slot
,
52 int address
, u8 value
)
54 struct ddb_ci
*ci
= ca
->data
;
56 ddbwritel(ci
->port
->dev
, CI_WRITE_CMD
| (value
<< 16) | address
,
57 CI_DO_ATTRIBUTE_RW(ci
->nr
));
62 static int read_cam_control(struct dvb_ca_en50221
*ca
,
66 struct ddb_ci
*ci
= ca
->data
;
69 ddbwritel(ci
->port
->dev
, CI_READ_CMD
| address
,
73 res
= ddbreadl(ci
->port
->dev
, CI_READDATA(ci
->nr
));
83 static int write_cam_control(struct dvb_ca_en50221
*ca
, int slot
,
86 struct ddb_ci
*ci
= ca
->data
;
88 ddbwritel(ci
->port
->dev
, CI_WRITE_CMD
| (value
<< 16) | address
,
94 static int slot_reset(struct dvb_ca_en50221
*ca
, int slot
)
96 struct ddb_ci
*ci
= ca
->data
;
98 ddbwritel(ci
->port
->dev
, CI_POWER_ON
,
101 ddbwritel(ci
->port
->dev
, CI_POWER_ON
| CI_RESET_CAM
,
103 ddbwritel(ci
->port
->dev
, CI_ENABLE
| CI_POWER_ON
| CI_RESET_CAM
,
105 usleep_range(20, 25);
106 ddbwritel(ci
->port
->dev
, CI_ENABLE
| CI_POWER_ON
,
111 static int slot_shutdown(struct dvb_ca_en50221
*ca
, int slot
)
113 struct ddb_ci
*ci
= ca
->data
;
115 ddbwritel(ci
->port
->dev
, 0, CI_CONTROL(ci
->nr
));
120 static int slot_ts_enable(struct dvb_ca_en50221
*ca
, int slot
)
122 struct ddb_ci
*ci
= ca
->data
;
123 u32 val
= ddbreadl(ci
->port
->dev
, CI_CONTROL(ci
->nr
));
125 ddbwritel(ci
->port
->dev
, val
| CI_BYPASS_DISABLE
,
130 static int poll_slot_status(struct dvb_ca_en50221
*ca
, int slot
, int open
)
132 struct ddb_ci
*ci
= ca
->data
;
133 u32 val
= ddbreadl(ci
->port
->dev
, CI_CONTROL(ci
->nr
));
136 if (val
& CI_CAM_DETECT
)
137 stat
|= DVB_CA_EN50221_POLL_CAM_PRESENT
;
138 if (val
& CI_CAM_READY
)
139 stat
|= DVB_CA_EN50221_POLL_CAM_READY
;
143 static struct dvb_ca_en50221 en_templ
= {
144 .read_attribute_mem
= read_attribute_mem
,
145 .write_attribute_mem
= write_attribute_mem
,
146 .read_cam_control
= read_cam_control
,
147 .write_cam_control
= write_cam_control
,
148 .slot_reset
= slot_reset
,
149 .slot_shutdown
= slot_shutdown
,
150 .slot_ts_enable
= slot_ts_enable
,
151 .poll_slot_status
= poll_slot_status
,
154 static void ci_attach(struct ddb_port
*port
)
158 ci
= kzalloc(sizeof(*ci
), GFP_KERNEL
);
161 memcpy(&ci
->en
, &en_templ
, sizeof(en_templ
));
164 port
->en_freedata
= 1;
166 ci
->nr
= port
->nr
- 2;
169 /* DuoFlex Dual CI support */
171 static int write_creg(struct ddb_ci
*ci
, u8 data
, u8 mask
)
173 struct i2c_adapter
*i2c
= &ci
->port
->i2c
->adap
;
174 u8 adr
= (ci
->port
->type
== DDB_CI_EXTERNAL_XO2
) ? 0x12 : 0x13;
176 ci
->port
->creg
= (ci
->port
->creg
& ~mask
) | data
;
177 return i2c_write_reg(i2c
, adr
, 0x02, ci
->port
->creg
);
180 static int read_attribute_mem_xo2(struct dvb_ca_en50221
*ca
,
181 int slot
, int address
)
183 struct ddb_ci
*ci
= ca
->data
;
184 struct i2c_adapter
*i2c
= &ci
->port
->i2c
->adap
;
185 u8 adr
= (ci
->port
->type
== DDB_CI_EXTERNAL_XO2
) ? 0x12 : 0x13;
189 res
= i2c_read_reg16(i2c
, adr
, 0x8000 | address
, &val
);
190 return res
? res
: val
;
193 static int write_attribute_mem_xo2(struct dvb_ca_en50221
*ca
, int slot
,
194 int address
, u8 value
)
196 struct ddb_ci
*ci
= ca
->data
;
197 struct i2c_adapter
*i2c
= &ci
->port
->i2c
->adap
;
198 u8 adr
= (ci
->port
->type
== DDB_CI_EXTERNAL_XO2
) ? 0x12 : 0x13;
200 return i2c_write_reg16(i2c
, adr
, 0x8000 | address
, value
);
203 static int read_cam_control_xo2(struct dvb_ca_en50221
*ca
,
204 int slot
, u8 address
)
206 struct ddb_ci
*ci
= ca
->data
;
207 struct i2c_adapter
*i2c
= &ci
->port
->i2c
->adap
;
208 u8 adr
= (ci
->port
->type
== DDB_CI_EXTERNAL_XO2
) ? 0x12 : 0x13;
212 res
= i2c_read_reg(i2c
, adr
, 0x20 | (address
& 3), &val
);
213 return res
? res
: val
;
216 static int write_cam_control_xo2(struct dvb_ca_en50221
*ca
, int slot
,
217 u8 address
, u8 value
)
219 struct ddb_ci
*ci
= ca
->data
;
220 struct i2c_adapter
*i2c
= &ci
->port
->i2c
->adap
;
221 u8 adr
= (ci
->port
->type
== DDB_CI_EXTERNAL_XO2
) ? 0x12 : 0x13;
223 return i2c_write_reg(i2c
, adr
, 0x20 | (address
& 3), value
);
226 static int slot_reset_xo2(struct dvb_ca_en50221
*ca
, int slot
)
228 struct ddb_ci
*ci
= ca
->data
;
230 dev_dbg(ci
->port
->dev
->dev
, "%s\n", __func__
);
231 write_creg(ci
, 0x01, 0x01);
232 write_creg(ci
, 0x04, 0x04);
234 write_creg(ci
, 0x02, 0x02);
235 write_creg(ci
, 0x00, 0x04);
236 write_creg(ci
, 0x18, 0x18);
240 static int slot_shutdown_xo2(struct dvb_ca_en50221
*ca
, int slot
)
242 struct ddb_ci
*ci
= ca
->data
;
244 dev_dbg(ci
->port
->dev
->dev
, "%s\n", __func__
);
245 write_creg(ci
, 0x10, 0xff);
246 write_creg(ci
, 0x08, 0x08);
250 static int slot_ts_enable_xo2(struct dvb_ca_en50221
*ca
, int slot
)
252 struct ddb_ci
*ci
= ca
->data
;
254 dev_dbg(ci
->port
->dev
->dev
, "%s\n", __func__
);
255 write_creg(ci
, 0x00, 0x10);
259 static int poll_slot_status_xo2(struct dvb_ca_en50221
*ca
, int slot
, int open
)
261 struct ddb_ci
*ci
= ca
->data
;
262 struct i2c_adapter
*i2c
= &ci
->port
->i2c
->adap
;
263 u8 adr
= (ci
->port
->type
== DDB_CI_EXTERNAL_XO2
) ? 0x12 : 0x13;
267 i2c_read_reg(i2c
, adr
, 0x01, &val
);
270 stat
|= DVB_CA_EN50221_POLL_CAM_PRESENT
;
272 stat
|= DVB_CA_EN50221_POLL_CAM_READY
;
276 static struct dvb_ca_en50221 en_xo2_templ
= {
277 .read_attribute_mem
= read_attribute_mem_xo2
,
278 .write_attribute_mem
= write_attribute_mem_xo2
,
279 .read_cam_control
= read_cam_control_xo2
,
280 .write_cam_control
= write_cam_control_xo2
,
281 .slot_reset
= slot_reset_xo2
,
282 .slot_shutdown
= slot_shutdown_xo2
,
283 .slot_ts_enable
= slot_ts_enable_xo2
,
284 .poll_slot_status
= poll_slot_status_xo2
,
287 static void ci_xo2_attach(struct ddb_port
*port
)
291 ci
= kzalloc(sizeof(*ci
), GFP_KERNEL
);
294 memcpy(&ci
->en
, &en_xo2_templ
, sizeof(en_xo2_templ
));
297 port
->en_freedata
= 1;
299 ci
->nr
= port
->nr
- 2;
301 write_creg(ci
, 0x10, 0xff);
302 write_creg(ci
, 0x08, 0x08);
305 static const struct cxd2099_cfg cxd_cfgtmpl
= {
312 static int ci_cxd2099_attach(struct ddb_port
*port
, u32 bitrate
)
314 struct cxd2099_cfg cxd_cfg
= cxd_cfgtmpl
;
315 struct i2c_client
*client
;
317 cxd_cfg
.bitrate
= bitrate
;
318 cxd_cfg
.en
= &port
->en
;
320 client
= dvb_module_probe("cxd2099", NULL
, &port
->i2c
->adap
,
325 port
->dvb
[0].i2c_client
[0] = client
;
326 port
->en_freedata
= 0;
330 dev_err(port
->dev
->dev
, "CXD2099AR attach failed\n");
334 int ddb_ci_attach(struct ddb_port
*port
, u32 bitrate
)
338 switch (port
->type
) {
339 case DDB_CI_EXTERNAL_SONY
:
340 ret
= ci_cxd2099_attach(port
, bitrate
);
344 case DDB_CI_EXTERNAL_XO2
:
345 case DDB_CI_EXTERNAL_XO2_B
:
348 case DDB_CI_INTERNAL
:
357 dvb_ca_en50221_init(port
->dvb
[0].adap
, port
->en
, 0, 1);
361 void ddb_ci_detach(struct ddb_port
*port
)
363 if (port
->dvb
[0].dev
)
364 dvb_unregister_device(port
->dvb
[0].dev
);
366 dvb_ca_en50221_release(port
->en
);
368 dvb_module_release(port
->dvb
[0].i2c_client
[0]);
369 port
->dvb
[0].i2c_client
[0] = NULL
;
371 /* free alloc'ed memory if needed */
372 if (port
->en_freedata
)
373 kfree(port
->en
->data
);