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 dev_dbg(&s->client->dev, "addr=0x%04x, reg = 0x%02x, data = %*ph\n",
96 client->addr, reg, len, buf);
97
98 return 0;
99}
100
101static int sp2_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, u8 acs,
102 u8 read, int addr, u8 data)
103{
104 struct sp2 *s = en50221->data;
105 u8 store;
106 int mem, ret;
107 int (*ci_op_cam)(void*, u8, int, u8, int*) = s->ci_control;
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 dev_dbg(&s->client->dev, "%s: slot=%d, addr=0x%04x, %s, data=%x",
144 (read) ? "read" : "write", slot, addr,
145 (acs == SP2_CI_ATTR_ACS) ? "attr" : "io",
146 (read) ? mem : data);
147
148 if (read)
149 return mem;
150 else
151 return 0;
152
153}
154
155int sp2_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
156 int slot, int addr)
157{
158 return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS,
159 SP2_CI_RD, addr, 0);
160}
161
162int sp2_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
163 int slot, int addr, u8 data)
164{
165 return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS,
166 SP2_CI_WR, addr, data);
167}
168
169int sp2_ci_read_cam_control(struct dvb_ca_en50221 *en50221,
170 int slot, u8 addr)
171{
172 return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS,
173 SP2_CI_RD, addr, 0);
174}
175
176int sp2_ci_write_cam_control(struct dvb_ca_en50221 *en50221,
177 int slot, u8 addr, u8 data)
178{
179 return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS,
180 SP2_CI_WR, addr, data);
181}
182
183int sp2_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
184{
185 struct sp2 *s = en50221->data;
186 u8 buf;
187 int ret;
188
189 dev_dbg(&s->client->dev, "slot: %d\n", slot);
190
191 if (slot != 0)
192 return -EINVAL;
193
194
195 buf = SP2_MOD_CTL_RST;
196 ret = sp2_write_i2c(s, 0x00, &buf, 1);
197
198 if (ret)
199 return ret;
200
201 usleep_range(500, 600);
202
203
204 buf = 0x00;
205 ret = sp2_write_i2c(s, 0x00, &buf, 1);
206
207 if (ret)
208 return ret;
209
210 msleep(1000);
211
212 return 0;
213}
214
215int sp2_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
216{
217 struct sp2 *s = en50221->data;
218
219 dev_dbg(&s->client->dev, "slot:%d\n", slot);
220
221
222 return 0;
223}
224
225int sp2_ci_slot_ts_enable(struct dvb_ca_en50221 *en50221, int slot)
226{
227 struct sp2 *s = en50221->data;
228 u8 buf;
229
230 dev_dbg(&s->client->dev, "slot:%d\n", slot);
231
232 if (slot != 0)
233 return -EINVAL;
234
235 sp2_read_i2c(s, 0x00, &buf, 1);
236
237
238 buf |= (SP2_MOD_CTL_TSOEN | SP2_MOD_CTL_TSIEN);
239 return sp2_write_i2c(s, 0, &buf, 1);
240}
241
242int sp2_ci_poll_slot_status(struct dvb_ca_en50221 *en50221,
243 int slot, int open)
244{
245 struct sp2 *s = en50221->data;
246 u8 buf[2];
247 int ret;
248
249 dev_dbg(&s->client->dev, "slot:%d open:%d\n", slot, open);
250
251
252
253
254
255 if (time_after(jiffies, s->next_status_checked_time)) {
256 ret = sp2_read_i2c(s, 0x00, buf, 1);
257 s->next_status_checked_time = jiffies + msecs_to_jiffies(1000);
258
259 if (ret)
260 return 0;
261
262 if (buf[0] & SP2_MOD_CTL_DET)
263 s->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
264 DVB_CA_EN50221_POLL_CAM_READY;
265 else
266 s->status = 0;
267 }
268
269 return s->status;
270}
271
272static int sp2_init(struct sp2 *s)
273{
274 int ret = 0;
275 u8 buf;
276 u8 cimax_init[34] = {
277 0x00,
278 0x00,
279 0x00,
280 0x00,
281 0x00,
282 0x44,
283 0x00,
284 0x00,
285 0x00,
286 0x00,
287 0x00,
288 0x00,
289 0x00,
290 0x00,
291 0x44,
292 0x00,
293 0x00,
294 0x00,
295 0x00,
296 0x00,
297 0x00,
298 0x00,
299 0x00,
300 0x02,
301 0x01,
302 0x00,
303 0x00,
304 0x00,
305 0x05,
306 0x00,
307 0x04,
308 0x00,
309 0x22,
310 0x00,
311 };
312
313 dev_dbg(&s->client->dev, "\n");
314
315 s->ca.owner = THIS_MODULE;
316 s->ca.read_attribute_mem = sp2_ci_read_attribute_mem;
317 s->ca.write_attribute_mem = sp2_ci_write_attribute_mem;
318 s->ca.read_cam_control = sp2_ci_read_cam_control;
319 s->ca.write_cam_control = sp2_ci_write_cam_control;
320 s->ca.slot_reset = sp2_ci_slot_reset;
321 s->ca.slot_shutdown = sp2_ci_slot_shutdown;
322 s->ca.slot_ts_enable = sp2_ci_slot_ts_enable;
323 s->ca.poll_slot_status = sp2_ci_poll_slot_status;
324 s->ca.data = s;
325 s->module_access_type = 0;
326
327
328 ret = sp2_write_i2c(s, 0x00, &cimax_init[0], 34);
329 if (ret)
330 goto err;
331
332
333 buf = 1;
334 ret = sp2_write_i2c(s, 0x1f, &buf, 1);
335 if (ret)
336 goto err;
337
338
339 ret = sp2_write_i2c(s, 0x18, &buf, 1);
340 if (ret)
341 goto err;
342
343 ret = dvb_ca_en50221_init(s->dvb_adap, &s->ca, 0, 1);
344 if (ret)
345 goto err;
346
347 return 0;
348
349err:
350 dev_dbg(&s->client->dev, "init failed=%d\n", ret);
351 return ret;
352}
353
354static int sp2_exit(struct i2c_client *client)
355{
356 struct sp2 *s;
357
358 dev_dbg(&client->dev, "\n");
359
360 if (!client)
361 return 0;
362
363 s = i2c_get_clientdata(client);
364 if (!s)
365 return 0;
366
367 if (!s->ca.data)
368 return 0;
369
370 dvb_ca_en50221_release(&s->ca);
371
372 return 0;
373}
374
375static int sp2_probe(struct i2c_client *client,
376 const struct i2c_device_id *id)
377{
378 struct sp2_config *cfg = client->dev.platform_data;
379 struct sp2 *s;
380 int ret;
381
382 dev_dbg(&client->dev, "\n");
383
384 s = kzalloc(sizeof(*s), GFP_KERNEL);
385 if (!s) {
386 ret = -ENOMEM;
387 goto err;
388 }
389
390 s->client = client;
391 s->dvb_adap = cfg->dvb_adap;
392 s->priv = cfg->priv;
393 s->ci_control = cfg->ci_control;
394
395 i2c_set_clientdata(client, s);
396
397 ret = sp2_init(s);
398 if (ret)
399 goto err;
400
401 dev_info(&s->client->dev, "CIMaX SP2 successfully attached\n");
402 return 0;
403err:
404 dev_dbg(&client->dev, "init failed=%d\n", ret);
405 kfree(s);
406
407 return ret;
408}
409
410static int sp2_remove(struct i2c_client *client)
411{
412 struct sp2 *s = i2c_get_clientdata(client);
413
414 dev_dbg(&client->dev, "\n");
415 sp2_exit(client);
416 kfree(s);
417 return 0;
418}
419
420static const struct i2c_device_id sp2_id[] = {
421 {"sp2", 0},
422 {}
423};
424MODULE_DEVICE_TABLE(i2c, sp2_id);
425
426static struct i2c_driver sp2_driver = {
427 .driver = {
428 .name = "sp2",
429 },
430 .probe = sp2_probe,
431 .remove = sp2_remove,
432 .id_table = sp2_id,
433};
434
435module_i2c_driver(sp2_driver);
436
437MODULE_DESCRIPTION("CIMaX SP2/HF CI driver");
438MODULE_AUTHOR("Olli Salonen <olli.salonen@iki.fi>");
439MODULE_LICENSE("GPL");
440