1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "sp2_priv.h"
25
26static int sp2_read_i2c(struct sp2 *s, u8 reg, u8 *buf, int len)
27{
28 int ret;
29 struct i2c_client *client = s->client;
30 struct i2c_adapter *adap = client->adapter;
31 struct i2c_msg msg[] = {
32 {
33 .addr = client->addr,
34 .flags = 0,
35 .buf = ®,
36 .len = 1
37 }, {
38 .addr = client->addr,
39 .flags = I2C_M_RD,
40 .buf = buf,
41 .len = len
42 }
43 };
44
45 ret = i2c_transfer(adap, msg, 2);
46
47 if (ret != 2) {
48 dev_err(&client->dev, "i2c read error, reg = 0x%02x, status = %d\n",
49 reg, ret);
50 if (ret < 0)
51 return ret;
52 else
53 return -EIO;
54 }
55
56 dev_dbg(&s->client->dev, "addr=0x%04x, reg = 0x%02x, data = %02x\n",
57 client->addr, reg, buf[0]);
58
59 return 0;
60}
61
62static int sp2_write_i2c(struct sp2 *s, u8 reg, u8 *buf, int len)
63{
64 int ret;
65 u8 buffer[35];
66 struct i2c_client *client = s->client;
67 struct i2c_adapter *adap = client->adapter;
68 struct i2c_msg msg = {
69 .addr = client->addr,
70 .flags = 0,
71 .buf = &buffer[0],
72 .len = len + 1
73 };
74
75 if ((len + 1) > sizeof(buffer)) {
76 dev_err(&client->dev, "i2c wr reg=%02x: len=%d is too big!\n",
77 reg, len);
78 return -EINVAL;
79 }
80
81 buffer[0] = reg;
82 memcpy(&buffer[1], buf, len);
83
84 ret = i2c_transfer(adap, &msg, 1);
85
86 if (ret != 1) {
87 dev_err(&client->dev, "i2c write error, reg = 0x%02x, status = %d\n",
88 reg, ret);
89 if (ret < 0)
90 return ret;
91 else
92 return -EIO;
93 }
94
95 return 0;
96}
97
98static int sp2_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, u8 acs,
99 u8 read, int addr, u8 data)
100{
101 struct sp2 *s = en50221->data;
102 u8 store;
103 int mem, ret;
104 int (*ci_op_cam)(void*, u8, int, u8, int*) = s->ci_control;
105
106 dev_dbg(&s->client->dev, "slot=%d, acs=0x%02x, addr=0x%04x, data = 0x%02x",
107 slot, acs, addr, data);
108
109 if (slot != 0)
110 return -EINVAL;
111
112
113
114
115
116 if (s->module_access_type != acs) {
117 ret = sp2_read_i2c(s, 0x00, &store, 1);
118
119 if (ret)
120 return ret;
121
122 store &= ~(SP2_MOD_CTL_ACS1 | SP2_MOD_CTL_ACS0);
123 store |= acs;
124
125 ret = sp2_write_i2c(s, 0x00, &store, 1);
126 if (ret)
127 return ret;
128 }
129
130 s->module_access_type = acs;
131
132
133 if (ci_op_cam) {
134 ret = ci_op_cam(s->priv, read, addr, data, &mem);
135 } else {
136 dev_err(&s->client->dev, "callback not defined");
137 return -EINVAL;
138 }
139
140 if (ret)
141 return ret;
142
143 if (read) {
144 dev_dbg(&s->client->dev, "cam read, addr=0x%04x, data = 0x%04x",
145 addr, mem);
146 return mem;
147 } else {
148 return 0;
149 }
150}
151
152int sp2_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
153 int slot, int addr)
154{
155 return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS,
156 SP2_CI_RD, addr, 0);
157}
158
159int sp2_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
160 int slot, int addr, u8 data)
161{
162 return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS,
163 SP2_CI_WR, addr, data);
164}
165
166int sp2_ci_read_cam_control(struct dvb_ca_en50221 *en50221,
167 int slot, u8 addr)
168{
169 return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS,
170 SP2_CI_RD, addr, 0);
171}
172
173int sp2_ci_write_cam_control(struct dvb_ca_en50221 *en50221,
174 int slot, u8 addr, u8 data)
175{
176 return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS,
177 SP2_CI_WR, addr, data);
178}
179
180int sp2_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
181{
182 struct sp2 *s = en50221->data;
183 u8 buf;
184 int ret;
185
186 dev_dbg(&s->client->dev, "slot: %d\n", slot);
187
188 if (slot != 0)
189 return -EINVAL;
190
191
192 buf = SP2_MOD_CTL_RST;
193 ret = sp2_write_i2c(s, 0x00, &buf, 1);
194
195 if (ret)
196 return ret;
197
198 usleep_range(500, 600);
199
200
201 buf = 0x00;
202 ret = sp2_write_i2c(s, 0x00, &buf, 1);
203
204 if (ret)
205 return ret;
206
207 msleep(1000);
208
209 return 0;
210}
211
212int sp2_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
213{
214 struct sp2 *s = en50221->data;
215
216 dev_dbg(&s->client->dev, "slot:%d\n", slot);
217
218
219 return 0;
220}
221
222int sp2_ci_slot_ts_enable(struct dvb_ca_en50221 *en50221, int slot)
223{
224 struct sp2 *s = en50221->data;
225 u8 buf;
226
227 dev_dbg(&s->client->dev, "slot:%d\n", slot);
228
229 if (slot != 0)
230 return -EINVAL;
231
232 sp2_read_i2c(s, 0x00, &buf, 1);
233
234
235 buf |= (SP2_MOD_CTL_TSOEN | SP2_MOD_CTL_TSIEN);
236 return sp2_write_i2c(s, 0, &buf, 1);
237}
238
239int sp2_ci_poll_slot_status(struct dvb_ca_en50221 *en50221,
240 int slot, int open)
241{
242 struct sp2 *s = en50221->data;
243 u8 buf[2];
244 int ret;
245
246 dev_dbg(&s->client->dev, "slot:%d open:%d\n", slot, open);
247
248
249
250
251
252 if (time_after(jiffies, s->next_status_checked_time)) {
253 ret = sp2_read_i2c(s, 0x00, buf, 1);
254 s->next_status_checked_time = jiffies + msecs_to_jiffies(1000);
255
256 if (ret)
257 return 0;
258
259 if (buf[0] & SP2_MOD_CTL_DET)
260 s->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
261 DVB_CA_EN50221_POLL_CAM_READY;
262 else
263 s->status = 0;
264 }
265
266 return s->status;
267}
268
269static int sp2_init(struct sp2 *s)
270{
271 int ret = 0;
272 u8 buf;
273 u8 cimax_init[34] = {
274 0x00,
275 0x00,
276 0x00,
277 0x00,
278 0x00,
279 0x44,
280 0x00,
281 0x00,
282 0x00,
283 0x00,
284 0x00,
285 0x00,
286 0x00,
287 0x00,
288 0x44,
289 0x00,
290 0x00,
291 0x00,
292 0x00,
293 0x00,
294 0x00,
295 0x00,
296 0x00,
297 0x02,
298 0x01,
299 0x00,
300 0x00,
301 0x00,
302 0x05,
303 0x00,
304 0x04,
305 0x00,
306 0x22,
307 0x00,
308 };
309
310 dev_dbg(&s->client->dev, "\n");
311
312 s->ca.owner = THIS_MODULE;
313 s->ca.read_attribute_mem = sp2_ci_read_attribute_mem;
314 s->ca.write_attribute_mem = sp2_ci_write_attribute_mem;
315 s->ca.read_cam_control = sp2_ci_read_cam_control;
316 s->ca.write_cam_control = sp2_ci_write_cam_control;
317 s->ca.slot_reset = sp2_ci_slot_reset;
318 s->ca.slot_shutdown = sp2_ci_slot_shutdown;
319 s->ca.slot_ts_enable = sp2_ci_slot_ts_enable;
320 s->ca.poll_slot_status = sp2_ci_poll_slot_status;
321 s->ca.data = s;
322 s->module_access_type = 0;
323
324
325 ret = sp2_write_i2c(s, 0x00, &cimax_init[0], 34);
326 if (ret)
327 goto err;
328
329
330 buf = 1;
331 ret = sp2_write_i2c(s, 0x1f, &buf, 1);
332 if (ret)
333 goto err;
334
335
336 ret = sp2_write_i2c(s, 0x18, &buf, 1);
337 if (ret)
338 goto err;
339
340 ret = dvb_ca_en50221_init(s->dvb_adap, &s->ca, 0, 1);
341 if (ret)
342 goto err;
343
344 return 0;
345
346err:
347 dev_dbg(&s->client->dev, "init failed=%d\n", ret);
348 return ret;
349}
350
351static int sp2_exit(struct i2c_client *client)
352{
353 struct sp2 *s;
354
355 dev_dbg(&client->dev, "\n");
356
357 if (client == NULL)
358 return 0;
359
360 s = i2c_get_clientdata(client);
361 if (s == NULL)
362 return 0;
363
364 if (s->ca.data == NULL)
365 return 0;
366
367 dvb_ca_en50221_release(&s->ca);
368
369 return 0;
370}
371
372static int sp2_probe(struct i2c_client *client,
373 const struct i2c_device_id *id)
374{
375 struct sp2_config *cfg = client->dev.platform_data;
376 struct sp2 *s;
377 int ret;
378
379 dev_dbg(&client->dev, "\n");
380
381 s = kzalloc(sizeof(struct sp2), GFP_KERNEL);
382 if (!s) {
383 ret = -ENOMEM;
384 dev_err(&client->dev, "kzalloc() failed\n");
385 goto err;
386 }
387
388 s->client = client;
389 s->dvb_adap = cfg->dvb_adap;
390 s->priv = cfg->priv;
391 s->ci_control = cfg->ci_control;
392
393 i2c_set_clientdata(client, s);
394
395 ret = sp2_init(s);
396 if (ret)
397 goto err;
398
399 dev_info(&s->client->dev, "CIMaX SP2 successfully attached\n");
400 return 0;
401err:
402 dev_dbg(&client->dev, "init failed=%d\n", ret);
403 kfree(s);
404
405 return ret;
406}
407
408static int sp2_remove(struct i2c_client *client)
409{
410 struct si2157 *s = i2c_get_clientdata(client);
411
412 dev_dbg(&client->dev, "\n");
413
414 sp2_exit(client);
415 if (s != NULL)
416 kfree(s);
417
418 return 0;
419}
420
421static const struct i2c_device_id sp2_id[] = {
422 {"sp2", 0},
423 {}
424};
425MODULE_DEVICE_TABLE(i2c, sp2_id);
426
427static struct i2c_driver sp2_driver = {
428 .driver = {
429 .owner = THIS_MODULE,
430 .name = "sp2",
431 },
432 .probe = sp2_probe,
433 .remove = sp2_remove,
434 .id_table = sp2_id,
435};
436
437module_i2c_driver(sp2_driver);
438
439MODULE_DESCRIPTION("CIMaX SP2/HF CI driver");
440MODULE_AUTHOR("Olli Salonen <olli.salonen@iki.fi>");
441MODULE_LICENSE("GPL");
442