Merge branch 'old.dcache' into work.dcache
[sfrench/cifs-2.6.git] / drivers / media / dvb-frontends / sp2.c
1 /*
2  * CIMaX SP2/SP2HF (Atmel T90FJR) CI driver
3  *
4  * Copyright (C) 2014 Olli Salonen <olli.salonen@iki.fi>
5  *
6  * Heavily based on CIMax2(R) SP2 driver in conjunction with NetUp Dual
7  * DVB-S2 CI card (cimax2) with following copyrights:
8  *
9  *  Copyright (C) 2009 NetUP Inc.
10  *  Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
11  *  Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
12  *
13  *    This program is free software; you can redistribute it and/or modify
14  *    it under the terms of the GNU General Public License as published by
15  *    the Free Software Foundation; either version 2 of the License, or
16  *    (at your option) any later version.
17  *
18  *    This program is distributed in the hope that it will be useful,
19  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *    GNU General Public License for more details.
22  */
23
24 #include "sp2_priv.h"
25
26 static 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 = &reg,
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
62 static 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
101 static 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          * change module access type between IO space and attribute memory
114          * when needed
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         /* implementation of ci_op_cam is device specific */
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
155 int 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
162 int 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
169 int 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
176 int 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
183 int 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         /* RST on */
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         /* RST off */
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
215 int 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         /* not implemented */
222         return 0;
223 }
224
225 int 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         /* disable bypass and enable TS */
238         buf |= (SP2_MOD_CTL_TSOEN | SP2_MOD_CTL_TSIEN);
239         return sp2_write_i2c(s, 0, &buf, 1);
240 }
241
242 int 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          * CAM module INSERT/REMOVE processing. Slow operation because of i2c
253          * transfers. Throttle read to one per sec.
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
272 static int sp2_init(struct sp2 *s)
273 {
274         int ret = 0;
275         u8 buf;
276         u8 cimax_init[34] = {
277                 0x00, /* module A control*/
278                 0x00, /* auto select mask high A */
279                 0x00, /* auto select mask low A */
280                 0x00, /* auto select pattern high A */
281                 0x00, /* auto select pattern low A */
282                 0x44, /* memory access time A, 600 ns */
283                 0x00, /* invert input A */
284                 0x00, /* RFU */
285                 0x00, /* RFU */
286                 0x00, /* module B control*/
287                 0x00, /* auto select mask high B */
288                 0x00, /* auto select mask low B */
289                 0x00, /* auto select pattern high B */
290                 0x00, /* auto select pattern low B */
291                 0x44, /* memory access time B, 600 ns */
292                 0x00, /* invert input B */
293                 0x00, /* RFU */
294                 0x00, /* RFU */
295                 0x00, /* auto select mask high Ext */
296                 0x00, /* auto select mask low Ext */
297                 0x00, /* auto select pattern high Ext */
298                 0x00, /* auto select pattern low Ext */
299                 0x00, /* RFU */
300                 0x02, /* destination - module A */
301                 0x01, /* power control reg, VCC power on */
302                 0x00, /* RFU */
303                 0x00, /* int status read only */
304                 0x00, /* Interrupt Mask Register */
305                 0x05, /* EXTINT=active-high, INT=push-pull */
306                 0x00, /* USCG1 */
307                 0x04, /* ack active low */
308                 0x00, /* LOCK = 0 */
309                 0x22, /* unknown */
310                 0x00, /* synchronization? */
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         /* initialize all regs */
328         ret = sp2_write_i2c(s, 0x00, &cimax_init[0], 34);
329         if (ret)
330                 goto err;
331
332         /* lock registers */
333         buf = 1;
334         ret = sp2_write_i2c(s, 0x1f, &buf, 1);
335         if (ret)
336                 goto err;
337
338         /* power on slots */
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
349 err:
350         dev_dbg(&s->client->dev, "init failed=%d\n", ret);
351         return ret;
352 }
353
354 static 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
375 static 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;
403 err:
404         dev_dbg(&client->dev, "init failed=%d\n", ret);
405         kfree(s);
406
407         return ret;
408 }
409
410 static 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
420 static const struct i2c_device_id sp2_id[] = {
421         {"sp2", 0},
422         {}
423 };
424 MODULE_DEVICE_TABLE(i2c, sp2_id);
425
426 static 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
435 module_i2c_driver(sp2_driver);
436
437 MODULE_DESCRIPTION("CIMaX SP2/HF CI driver");
438 MODULE_AUTHOR("Olli Salonen <olli.salonen@iki.fi>");
439 MODULE_LICENSE("GPL");