• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/media/video/cx23885/
1/*
2 * cimax2.c
3 *
4 * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card
5 *
6 * Copyright (C) 2009 NetUP Inc.
7 * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
8 * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 *
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26#include "cx23885.h"
27#include "dvb_ca_en50221.h"
28/**** Bit definitions for MC417_RWD and MC417_OEN registers  ***
29  bits 31-16
30+-----------+
31| Reserved  |
32+-----------+
33  bit 15  bit 14  bit 13 bit 12  bit 11  bit 10  bit 9   bit 8
34+-------+-------+-------+-------+-------+-------+-------+-------+
35|  WR#  |  RD#  |       |  ACK# |  ADHI |  ADLO |  CS1# |  CS0# |
36+-------+-------+-------+-------+-------+-------+-------+-------+
37 bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
38+-------+-------+-------+-------+-------+-------+-------+-------+
39|  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|
40+-------+-------+-------+-------+-------+-------+-------+-------+
41***/
42/* MC417 */
43#define NETUP_DATA		0x000000ff
44#define NETUP_WR		0x00008000
45#define NETUP_RD		0x00004000
46#define NETUP_ACK		0x00001000
47#define NETUP_ADHI		0x00000800
48#define NETUP_ADLO		0x00000400
49#define NETUP_CS1		0x00000200
50#define NETUP_CS0		0x00000100
51#define NETUP_EN_ALL		0x00001000
52#define NETUP_CTRL_OFF		(NETUP_CS1 | NETUP_CS0 | NETUP_WR | NETUP_RD)
53#define NETUP_CI_CTL		0x04
54#define NETUP_CI_RD		1
55
56#define NETUP_IRQ_DETAM 	0x1
57#define NETUP_IRQ_IRQAM		0x4
58
59static unsigned int ci_dbg;
60module_param(ci_dbg, int, 0644);
61MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");
62
63static unsigned int ci_irq_enable;
64module_param(ci_irq_enable, int, 0644);
65MODULE_PARM_DESC(ci_irq_enable, "Enable IRQ from CAM");
66
67#define ci_dbg_print(args...) \
68	do { \
69		if (ci_dbg) \
70			printk(KERN_DEBUG args); \
71	} while (0)
72
73#define ci_irq_flags() (ci_irq_enable ? NETUP_IRQ_IRQAM : 0)
74
75/* stores all private variables for communication with CI */
76struct netup_ci_state {
77	struct dvb_ca_en50221 ca;
78	struct mutex ca_mutex;
79	struct i2c_adapter *i2c_adap;
80	u8 ci_i2c_addr;
81	int status;
82	struct work_struct work;
83	void *priv;
84	u8 current_irq_mode;
85	int current_ci_flag;
86	unsigned long next_status_checked_time;
87};
88
89
90int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
91						u8 *buf, int len)
92{
93	int ret;
94	struct i2c_msg msg[] = {
95		{
96			.addr	= addr,
97			.flags	= 0,
98			.buf	= &reg,
99			.len	= 1
100		}, {
101			.addr	= addr,
102			.flags	= I2C_M_RD,
103			.buf	= buf,
104			.len	= len
105		}
106	};
107
108	ret = i2c_transfer(i2c_adap, msg, 2);
109
110	if (ret != 2) {
111		ci_dbg_print("%s: i2c read error, Reg = 0x%02x, Status = %d\n",
112						__func__, reg, ret);
113
114		return -1;
115	}
116
117	ci_dbg_print("%s: i2c read Addr=0x%04x, Reg = 0x%02x, data = %02x\n",
118						__func__, addr, reg, buf[0]);
119
120	return 0;
121}
122
123int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
124						u8 *buf, int len)
125{
126	int ret;
127	u8 buffer[len + 1];
128
129	struct i2c_msg msg = {
130		.addr	= addr,
131		.flags	= 0,
132		.buf	= &buffer[0],
133		.len	= len + 1
134	};
135
136	buffer[0] = reg;
137	memcpy(&buffer[1], buf, len);
138
139	ret = i2c_transfer(i2c_adap, &msg, 1);
140
141	if (ret != 1) {
142		ci_dbg_print("%s: i2c write error, Reg=[0x%02x], Status=%d\n",
143						__func__, reg, ret);
144		return -1;
145	}
146
147	return 0;
148}
149
150int netup_ci_get_mem(struct cx23885_dev *dev)
151{
152	int mem;
153	unsigned long timeout = jiffies + msecs_to_jiffies(1);
154
155	for (;;) {
156		mem = cx_read(MC417_RWD);
157		if ((mem & NETUP_ACK) == 0)
158			break;
159		if (time_after(jiffies, timeout))
160			break;
161		udelay(1);
162	}
163
164	cx_set(MC417_RWD, NETUP_CTRL_OFF);
165
166	return mem & 0xff;
167}
168
169int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
170				u8 flag, u8 read, int addr, u8 data)
171{
172	struct netup_ci_state *state = en50221->data;
173	struct cx23885_tsport *port = state->priv;
174	struct cx23885_dev *dev = port->dev;
175
176	u8 store;
177	int mem;
178	int ret;
179
180	if (0 != slot)
181		return -EINVAL;
182
183	if (state->current_ci_flag != flag) {
184		ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
185				0, &store, 1);
186		if (ret != 0)
187			return ret;
188
189		store &= ~0x0c;
190		store |= flag;
191
192		ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
193				0, &store, 1);
194		if (ret != 0)
195			return ret;
196	};
197	state->current_ci_flag = flag;
198
199	mutex_lock(&dev->gpio_lock);
200
201	/* write addr */
202	cx_write(MC417_OEN, NETUP_EN_ALL);
203	cx_write(MC417_RWD, NETUP_CTRL_OFF |
204				NETUP_ADLO | (0xff & addr));
205	cx_clear(MC417_RWD, NETUP_ADLO);
206	cx_write(MC417_RWD, NETUP_CTRL_OFF |
207				NETUP_ADHI | (0xff & (addr >> 8)));
208	cx_clear(MC417_RWD, NETUP_ADHI);
209
210	if (read) { /* data in */
211		cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA);
212	} else /* data out */
213		cx_write(MC417_RWD, NETUP_CTRL_OFF | data);
214
215	/* choose chip */
216	cx_clear(MC417_RWD,
217			(state->ci_i2c_addr == 0x40) ? NETUP_CS0 : NETUP_CS1);
218	/* read/write */
219	cx_clear(MC417_RWD, (read) ? NETUP_RD : NETUP_WR);
220	mem = netup_ci_get_mem(dev);
221
222	mutex_unlock(&dev->gpio_lock);
223
224	if (!read)
225		if (mem < 0)
226			return -EREMOTEIO;
227
228	ci_dbg_print("%s: %s: chipaddr=[0x%x] addr=[0x%02x], %s=%x\n", __func__,
229			(read) ? "read" : "write", state->ci_i2c_addr, addr,
230			(flag == NETUP_CI_CTL) ? "ctl" : "mem",
231			(read) ? mem : data);
232
233	if (read)
234		return mem;
235
236	return 0;
237}
238
239int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
240						int slot, int addr)
241{
242	return netup_ci_op_cam(en50221, slot, 0, NETUP_CI_RD, addr, 0);
243}
244
245int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
246						int slot, int addr, u8 data)
247{
248	return netup_ci_op_cam(en50221, slot, 0, 0, addr, data);
249}
250
251int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
252{
253	return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL,
254							NETUP_CI_RD, addr, 0);
255}
256
257int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
258							u8 addr, u8 data)
259{
260	return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL, 0, addr, data);
261}
262
263int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
264{
265	struct netup_ci_state *state = en50221->data;
266	u8 buf =  0x80;
267	int ret;
268
269	if (0 != slot)
270		return -EINVAL;
271
272	udelay(500);
273	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
274							0, &buf, 1);
275
276	if (ret != 0)
277		return ret;
278
279	udelay(500);
280
281	buf = 0x00;
282	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
283							0, &buf, 1);
284
285	msleep(1000);
286	dvb_ca_en50221_camready_irq(&state->ca, 0);
287
288	return 0;
289
290}
291
292int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
293{
294	/* not implemented */
295	return 0;
296}
297
298int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)
299{
300	struct netup_ci_state *state = en50221->data;
301	int ret;
302
303	if (irq_mode == state->current_irq_mode)
304		return 0;
305
306	ci_dbg_print("%s: chipaddr=[0x%x] setting ci IRQ to [0x%x] \n",
307			__func__, state->ci_i2c_addr, irq_mode);
308	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
309							0x1b, &irq_mode, 1);
310
311	if (ret != 0)
312		return ret;
313
314	state->current_irq_mode = irq_mode;
315
316	return 0;
317}
318
319int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
320{
321	struct netup_ci_state *state = en50221->data;
322	u8 buf;
323
324	if (0 != slot)
325		return -EINVAL;
326
327	netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
328			0, &buf, 1);
329	buf |= 0x60;
330
331	return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
332							0, &buf, 1);
333}
334
335/* work handler */
336static void netup_read_ci_status(struct work_struct *work)
337{
338	struct netup_ci_state *state =
339			container_of(work, struct netup_ci_state, work);
340	u8 buf[33];
341	int ret;
342
343	/* CAM module IRQ processing. fast operation */
344	dvb_ca_en50221_frda_irq(&state->ca, 0);
345
346	/* CAM module INSERT/REMOVE processing. slow operation because of i2c
347	 * transfers */
348	if (time_after(jiffies, state->next_status_checked_time)
349			|| !state->status) {
350		ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
351				0, &buf[0], 33);
352
353		state->next_status_checked_time = jiffies
354			+ msecs_to_jiffies(1000);
355
356		if (ret != 0)
357			return;
358
359		ci_dbg_print("%s: Slot Status Addr=[0x%04x], "
360				"Reg=[0x%02x], data=%02x, "
361				"TS config = %02x\n", __func__,
362				state->ci_i2c_addr, 0, buf[0],
363				buf[0]);
364
365
366		if (buf[0] & 1)
367			state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
368				DVB_CA_EN50221_POLL_CAM_READY;
369		else
370			state->status = 0;
371	};
372}
373
374/* CI irq handler */
375int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status)
376{
377	struct cx23885_tsport *port = NULL;
378	struct netup_ci_state *state = NULL;
379
380	if (pci_status & PCI_MSK_GPIO0)
381		port = &dev->ts1;
382	else if (pci_status & PCI_MSK_GPIO1)
383		port = &dev->ts2;
384	else /* who calls ? */
385		return 0;
386
387	state = port->port_priv;
388
389	schedule_work(&state->work);
390
391	return 1;
392}
393
394int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
395{
396	struct netup_ci_state *state = en50221->data;
397
398	if (0 != slot)
399		return -EINVAL;
400
401	netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | ci_irq_flags())
402			: NETUP_IRQ_DETAM);
403
404	return state->status;
405}
406
407int netup_ci_init(struct cx23885_tsport *port)
408{
409	struct netup_ci_state *state;
410	u8 cimax_init[34] = {
411		0x00, /* module A control*/
412		0x00, /* auto select mask high A */
413		0x00, /* auto select mask low A */
414		0x00, /* auto select pattern high A */
415		0x00, /* auto select pattern low A */
416		0x44, /* memory access time A */
417		0x00, /* invert input A */
418		0x00, /* RFU */
419		0x00, /* RFU */
420		0x00, /* module B control*/
421		0x00, /* auto select mask high B */
422		0x00, /* auto select mask low B */
423		0x00, /* auto select pattern high B */
424		0x00, /* auto select pattern low B */
425		0x44, /* memory access time B */
426		0x00, /* invert input B */
427		0x00, /* RFU */
428		0x00, /* RFU */
429		0x00, /* auto select mask high Ext */
430		0x00, /* auto select mask low Ext */
431		0x00, /* auto select pattern high Ext */
432		0x00, /* auto select pattern low Ext */
433		0x00, /* RFU */
434		0x02, /* destination - module A */
435		0x01, /* power on (use it like store place) */
436		0x00, /* RFU */
437		0x00, /* int status read only */
438		ci_irq_flags() | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */
439		0x05, /* EXTINT=active-high, INT=push-pull */
440		0x00, /* USCG1 */
441		0x04, /* ack active low */
442		0x00, /* LOCK = 0 */
443		0x33, /* serial mode, rising in, rising out, MSB first*/
444		0x31, /* syncronization */
445	};
446	int ret;
447
448	ci_dbg_print("%s\n", __func__);
449	state = kzalloc(sizeof(struct netup_ci_state), GFP_KERNEL);
450	if (!state) {
451		ci_dbg_print("%s: Unable create CI structure!\n", __func__);
452		ret = -ENOMEM;
453		goto err;
454	}
455
456	port->port_priv = state;
457
458	switch (port->nr) {
459	case 1:
460		state->ci_i2c_addr = 0x40;
461		break;
462	case 2:
463		state->ci_i2c_addr = 0x41;
464		break;
465	}
466
467	state->i2c_adap = &port->dev->i2c_bus[0].i2c_adap;
468	state->ca.owner = THIS_MODULE;
469	state->ca.read_attribute_mem = netup_ci_read_attribute_mem;
470	state->ca.write_attribute_mem = netup_ci_write_attribute_mem;
471	state->ca.read_cam_control = netup_ci_read_cam_ctl;
472	state->ca.write_cam_control = netup_ci_write_cam_ctl;
473	state->ca.slot_reset = netup_ci_slot_reset;
474	state->ca.slot_shutdown = netup_ci_slot_shutdown;
475	state->ca.slot_ts_enable = netup_ci_slot_ts_ctl;
476	state->ca.poll_slot_status = netup_poll_ci_slot_status;
477	state->ca.data = state;
478	state->priv = port;
479	state->current_irq_mode = ci_irq_flags() | NETUP_IRQ_DETAM;
480
481	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
482						0, &cimax_init[0], 34);
483	/* lock registers */
484	ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
485						0x1f, &cimax_init[0x18], 1);
486	/* power on slots */
487	ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
488						0x18, &cimax_init[0x18], 1);
489
490	if (0 != ret)
491		goto err;
492
493	ret = dvb_ca_en50221_init(&port->frontends.adapter,
494				   &state->ca,
495				   /* flags */ 0,
496				   /* n_slots */ 1);
497	if (0 != ret)
498		goto err;
499
500	INIT_WORK(&state->work, netup_read_ci_status);
501	schedule_work(&state->work);
502
503	ci_dbg_print("%s: CI initialized!\n", __func__);
504
505	return 0;
506err:
507	ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);
508	kfree(state);
509	return ret;
510}
511
512void netup_ci_exit(struct cx23885_tsport *port)
513{
514	struct netup_ci_state *state;
515
516	if (NULL == port)
517		return;
518
519	state = (struct netup_ci_state *)port->port_priv;
520	if (NULL == state)
521		return;
522
523	if (NULL == state->ca.data)
524		return;
525
526	dvb_ca_en50221_release(&state->ca);
527	kfree(state);
528}
529