aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/dvb-usb/ttusb2.c
diff options
context:
space:
mode:
authorJose Alberto Reguero <jareguero@telefonica.net>2011-09-18 06:59:05 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-09-23 22:07:35 -0400
commit8c0bc03c80952e81db8cb11082c0c6375e9083ab (patch)
tree3e19d69b601652924b46f9d67d03996a3185f3f9 /drivers/media/dvb/dvb-usb/ttusb2.c
parent1cd7acc4ef5459dd92d0d04430d353de0a54b393 (diff)
[media] ttusb2: TT CT-3650 CI support
Signed-off-by: Jose Alberto Reguero <jareguero@telefonica.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/dvb-usb/ttusb2.c')
-rw-r--r--drivers/media/dvb/dvb-usb/ttusb2.c284
1 files changed, 283 insertions, 1 deletions
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
index 7b07cf655387..ea4eab8b3965 100644
--- a/drivers/media/dvb/dvb-usb/ttusb2.c
+++ b/drivers/media/dvb/dvb-usb/ttusb2.c
@@ -33,16 +33,40 @@
33#include "tda10048.h" 33#include "tda10048.h"
34#include "tda827x.h" 34#include "tda827x.h"
35#include "lnbp21.h" 35#include "lnbp21.h"
36/* CA */
37#include "dvb_ca_en50221.h"
36 38
37/* debug */ 39/* debug */
38static int dvb_usb_ttusb2_debug; 40static int dvb_usb_ttusb2_debug;
39#define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args) 41#define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args)
40module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644); 42module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
41MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS); 43MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
44static int dvb_usb_ttusb2_debug_ci;
45module_param_named(debug_ci,dvb_usb_ttusb2_debug_ci, int, 0644);
46MODULE_PARM_DESC(debug_ci, "set debugging ci." DVB_USB_DEBUG_STATUS);
42 47
43DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 48DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
44 49
50#define ci_dbg(format, arg...) \
51do { \
52 if (dvb_usb_ttusb2_debug_ci) \
53 printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
54 ": %s " format "\n" , __func__, ## arg); \
55} while (0)
56
57enum {
58 TT3650_CMD_CI_TEST = 0x40,
59 TT3650_CMD_CI_RD_CTRL,
60 TT3650_CMD_CI_WR_CTRL,
61 TT3650_CMD_CI_RD_ATTR,
62 TT3650_CMD_CI_WR_ATTR,
63 TT3650_CMD_CI_RESET,
64 TT3650_CMD_CI_SET_VIDEO_PORT
65};
66
45struct ttusb2_state { 67struct ttusb2_state {
68 struct dvb_ca_en50221 ca;
69 struct mutex ca_mutex;
46 u8 id; 70 u8 id;
47 u16 last_rc_key; 71 u16 last_rc_key;
48}; 72};
@@ -79,6 +103,255 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
79 return 0; 103 return 0;
80} 104}
81 105
106/* ci */
107static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
108{
109 int ret;
110 u8 rx[60];/* (64 -4) */
111 ret = ttusb2_msg(d, cmd, data, write_len, rx, read_len);
112 if (!ret)
113 memcpy(data, rx, read_len);
114 return ret;
115}
116
117static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
118{
119 struct dvb_usb_device *d = ca->data;
120 struct ttusb2_state *state = d->priv;
121 int ret;
122
123 mutex_lock(&state->ca_mutex);
124 ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
125 mutex_unlock(&state->ca_mutex);
126
127 return ret;
128}
129
130static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
131{
132 u8 buf[3];
133 int ret = 0;
134
135 if (slot)
136 return -EINVAL;
137
138 buf[0] = (address >> 8) & 0x0F;
139 buf[1] = address;
140
141
142 ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
143
144 ci_dbg("%04x -> %d 0x%02x", address, ret, buf[2]);
145
146 if (ret < 0)
147 return ret;
148
149 return buf[2];
150}
151
152static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
153{
154 u8 buf[3];
155
156 ci_dbg("%d 0x%04x 0x%02x", slot, address, value);
157
158 if (slot)
159 return -EINVAL;
160
161 buf[0] = (address >> 8) & 0x0F;
162 buf[1] = address;
163 buf[2] = value;
164
165 return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
166}
167
168static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
169{
170 u8 buf[2];
171 int ret;
172
173 if (slot)
174 return -EINVAL;
175
176 buf[0] = address & 3;
177
178 ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
179
180 ci_dbg("0x%02x -> %d 0x%02x", address, ret, buf[1]);
181
182 if (ret < 0)
183 return ret;
184
185 return buf[1];
186}
187
188static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
189{
190 u8 buf[2];
191
192 ci_dbg("%d 0x%02x 0x%02x", slot, address, value);
193
194 if (slot)
195 return -EINVAL;
196
197 buf[0] = address;
198 buf[1] = value;
199
200 return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
201}
202
203static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca, int slot, int enable)
204{
205 u8 buf[1];
206 int ret;
207
208 ci_dbg("%d %d", slot, enable);
209
210 if (slot)
211 return -EINVAL;
212
213 buf[0] = enable;
214
215 ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
216 if (ret < 0)
217 return ret;
218
219 if (enable != buf[0]) {
220 err("CI not %sabled.", enable ? "en" : "dis");
221 return -EIO;
222 }
223
224 return 0;
225}
226
227static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
228{
229 return tt3650_ci_set_video_port(ca, slot, 0);
230}
231
232static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
233{
234 return tt3650_ci_set_video_port(ca, slot, 1);
235}
236
237static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
238{
239 struct dvb_usb_device *d = ca->data;
240 struct ttusb2_state *state = d->priv;
241 u8 buf[1];
242 int ret;
243
244 ci_dbg("%d", slot);
245
246 if (slot)
247 return -EINVAL;
248
249 buf[0] = 0;
250
251 mutex_lock(&state->ca_mutex);
252
253 ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
254 if (ret)
255 goto failed;
256
257 msleep(500);
258
259 buf[0] = 1;
260
261 ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
262 if (ret)
263 goto failed;
264
265 msleep(500);
266
267 buf[0] = 0; /* FTA */
268
269 ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
270
271 msleep(1100);
272
273 failed:
274 mutex_unlock(&state->ca_mutex);
275
276 return ret;
277}
278
279static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
280{
281 u8 buf[1];
282 int ret;
283
284 if (slot)
285 return -EINVAL;
286
287 ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
288 if (ret)
289 return ret;
290
291 if (1 == buf[0]) {
292 return DVB_CA_EN50221_POLL_CAM_PRESENT |
293 DVB_CA_EN50221_POLL_CAM_READY;
294 }
295 return 0;
296}
297
298static void tt3650_ci_uninit(struct dvb_usb_device *d)
299{
300 struct ttusb2_state *state;
301
302 ci_dbg("");
303
304 if (NULL == d)
305 return;
306
307 state = d->priv;
308 if (NULL == state)
309 return;
310
311 if (NULL == state->ca.data)
312 return;
313
314 dvb_ca_en50221_release(&state->ca);
315
316 memset(&state->ca, 0, sizeof(state->ca));
317}
318
319static int tt3650_ci_init(struct dvb_usb_adapter *a)
320{
321 struct dvb_usb_device *d = a->dev;
322 struct ttusb2_state *state = d->priv;
323 int ret;
324
325 ci_dbg("");
326
327 mutex_init(&state->ca_mutex);
328
329 state->ca.owner = THIS_MODULE;
330 state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
331 state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
332 state->ca.read_cam_control = tt3650_ci_read_cam_control;
333 state->ca.write_cam_control = tt3650_ci_write_cam_control;
334 state->ca.slot_reset = tt3650_ci_slot_reset;
335 state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
336 state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
337 state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
338 state->ca.data = d;
339
340 ret = dvb_ca_en50221_init(&a->dvb_adap,
341 &state->ca,
342 /* flags */ 0,
343 /* n_slots */ 1);
344 if (ret) {
345 err("Cannot initialize CI: Error %d.", ret);
346 memset(&state->ca, 0, sizeof(state->ca));
347 return ret;
348 }
349
350 info("CI initialized.");
351
352 return 0;
353}
354
82static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) 355static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
83{ 356{
84 struct dvb_usb_device *d = i2c_get_adapdata(adap); 357 struct dvb_usb_device *d = i2c_get_adapdata(adap);
@@ -251,6 +524,7 @@ static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
251 deb_info("TDA10023 attach failed\n"); 524 deb_info("TDA10023 attach failed\n");
252 return -ENODEV; 525 return -ENODEV;
253 } 526 }
527 tt3650_ci_init(adap);
254 } else { 528 } else {
255 adap->fe_adap[1].fe = dvb_attach(tda10048_attach, 529 adap->fe_adap[1].fe = dvb_attach(tda10048_attach,
256 &tda10048_config, &adap->dev->i2c_adap); 530 &tda10048_config, &adap->dev->i2c_adap);
@@ -305,6 +579,14 @@ static struct dvb_usb_device_properties ttusb2_properties;
305static struct dvb_usb_device_properties ttusb2_properties_s2400; 579static struct dvb_usb_device_properties ttusb2_properties_s2400;
306static struct dvb_usb_device_properties ttusb2_properties_ct3650; 580static struct dvb_usb_device_properties ttusb2_properties_ct3650;
307 581
582static void ttusb2_usb_disconnect(struct usb_interface *intf)
583{
584 struct dvb_usb_device *d = usb_get_intfdata(intf);
585
586 tt3650_ci_uninit(d);
587 dvb_usb_device_exit(intf);
588}
589
308static int ttusb2_probe(struct usb_interface *intf, 590static int ttusb2_probe(struct usb_interface *intf,
309 const struct usb_device_id *id) 591 const struct usb_device_id *id)
310{ 592{
@@ -513,7 +795,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
513static struct usb_driver ttusb2_driver = { 795static struct usb_driver ttusb2_driver = {
514 .name = "dvb_usb_ttusb2", 796 .name = "dvb_usb_ttusb2",
515 .probe = ttusb2_probe, 797 .probe = ttusb2_probe,
516 .disconnect = dvb_usb_device_exit, 798 .disconnect = ttusb2_usb_disconnect,
517 .id_table = ttusb2_table, 799 .id_table = ttusb2_table,
518}; 800};
519 801