brintos

brintos / linux-shallow public Read only

0
0
Text · 20.0 KiB · 0dc3482 Raw
839 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * altera-ci.c4 *5 *  CI driver in conjunction with NetUp Dual DVB-T/C RF CI card6 *7 * Copyright (C) 2010,2011 NetUP Inc.8 * Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru>9 */10 11/*12 * currently cx23885 GPIO's used.13 * GPIO-0 ~INT in14 * GPIO-1 TMS out15 * GPIO-2 ~reset chips out16 * GPIO-3 to GPIO-10 data/addr for CA in/out17 * GPIO-11 ~CS out18 * GPIO-12 AD_RG out19 * GPIO-13 ~WR out20 * GPIO-14 ~RD out21 * GPIO-15 ~RDY in22 * GPIO-16 TCK out23 * GPIO-17 TDO in24 * GPIO-18 TDI out25 */26/*27 *  Bit definitions for MC417_RWD and MC417_OEN registers28 * bits 31-1629 * +-----------+30 * | Reserved  |31 * +-----------+32 *   bit 15  bit 14  bit 13 bit 12  bit 11  bit 10  bit 9   bit 833 * +-------+-------+-------+-------+-------+-------+-------+-------+34 * |  TDI  |  TDO  |  TCK  |  RDY# |  #RD  |  #WR  | AD_RG |  #CS  |35 * +-------+-------+-------+-------+-------+-------+-------+-------+36 *  bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 037 * +-------+-------+-------+-------+-------+-------+-------+-------+38 * |  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|39 * +-------+-------+-------+-------+-------+-------+-------+-------+40 */41 42#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt43 44#include <media/dvb_demux.h>45#include <media/dvb_frontend.h>46#include "altera-ci.h"47#include <media/dvb_ca_en50221.h>48 49/* FPGA regs */50#define NETUP_CI_INT_CTRL	0x0051#define NETUP_CI_BUSCTRL2	0x0152#define NETUP_CI_ADDR0		0x0453#define NETUP_CI_ADDR1		0x0554#define NETUP_CI_DATA		0x0655#define NETUP_CI_BUSCTRL	0x0756#define NETUP_CI_PID_ADDR0	0x0857#define NETUP_CI_PID_ADDR1	0x0958#define NETUP_CI_PID_DATA	0x0a59#define NETUP_CI_TSA_DIV	0x0c60#define NETUP_CI_TSB_DIV	0x0d61#define NETUP_CI_REVISION	0x0f62 63/* const for ci op */64#define NETUP_CI_FLG_CTL	165#define NETUP_CI_FLG_RD		166#define NETUP_CI_FLG_AD		167 68static unsigned int ci_dbg;69module_param(ci_dbg, int, 0644);70MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");71 72static unsigned int pid_dbg;73module_param(pid_dbg, int, 0644);74MODULE_PARM_DESC(pid_dbg, "Enable PID filtering debugging");75 76MODULE_DESCRIPTION("altera FPGA CI module");77MODULE_AUTHOR("Igor M. Liplianin  <liplianin@netup.ru>");78MODULE_LICENSE("GPL");79 80#define ci_dbg_print(fmt, args...) \81	do { \82		if (ci_dbg) \83			printk(KERN_DEBUG pr_fmt("%s: " fmt), \84			       __func__, ##args); \85	} while (0)86 87#define pid_dbg_print(fmt, args...) \88	do { \89		if (pid_dbg) \90			printk(KERN_DEBUG pr_fmt("%s: " fmt), \91			       __func__, ##args); \92	} while (0)93 94struct altera_ci_state;95struct netup_hw_pid_filter;96 97struct fpga_internal {98	void *dev;99	struct mutex fpga_mutex;/* two CI's on the same fpga */100	struct netup_hw_pid_filter *pid_filt[2];101	struct altera_ci_state *state[2];102	struct work_struct work;103	int (*fpga_rw) (void *dev, int flag, int data, int rw);104	int cis_used;105	int filts_used;106	int strt_wrk;107};108 109/* stores all private variables for communication with CI */110struct altera_ci_state {111	struct fpga_internal *internal;112	struct dvb_ca_en50221 ca;113	int status;114	int nr;115};116 117/* stores all private variables for hardware pid filtering */118struct netup_hw_pid_filter {119	struct fpga_internal *internal;120	struct dvb_demux *demux;121	/* save old functions */122	int (*start_feed)(struct dvb_demux_feed *feed);123	int (*stop_feed)(struct dvb_demux_feed *feed);124 125	int status;126	int nr;127};128 129/* internal params node */130struct fpga_inode {131	/* pointer for internal params, one for each pair of CI's */132	struct fpga_internal		*internal;133	struct fpga_inode		*next_inode;134};135 136/* first internal params */137static struct fpga_inode *fpga_first_inode;138 139/* find chip by dev */140static struct fpga_inode *find_inode(void *dev)141{142	struct fpga_inode *temp_chip = fpga_first_inode;143 144	if (temp_chip == NULL)145		return temp_chip;146 147	/*148	 Search for the last fpga CI chip or149	 find it by dev */150	while ((temp_chip != NULL) &&151				(temp_chip->internal->dev != dev))152		temp_chip = temp_chip->next_inode;153 154	return temp_chip;155}156/* check demux */157static struct fpga_internal *check_filter(struct fpga_internal *temp_int,158						void *demux_dev, int filt_nr)159{160	if (temp_int == NULL)161		return NULL;162 163	if ((temp_int->pid_filt[filt_nr]) == NULL)164		return NULL;165 166	if (temp_int->pid_filt[filt_nr]->demux == demux_dev)167		return temp_int;168 169	return NULL;170}171 172/* find chip by demux */173static struct fpga_inode *find_dinode(void *demux_dev)174{175	struct fpga_inode *temp_chip = fpga_first_inode;176	struct fpga_internal *temp_int;177 178	/*179	 * Search of the last fpga CI chip or180	 * find it by demux181	 */182	while (temp_chip != NULL) {183		if (temp_chip->internal != NULL) {184			temp_int = temp_chip->internal;185			if (check_filter(temp_int, demux_dev, 0))186				break;187			if (check_filter(temp_int, demux_dev, 1))188				break;189		}190 191		temp_chip = temp_chip->next_inode;192	}193 194	return temp_chip;195}196 197/* deallocating chip */198static void remove_inode(struct fpga_internal *internal)199{200	struct fpga_inode *prev_node = fpga_first_inode;201	struct fpga_inode *del_node = find_inode(internal->dev);202 203	if (del_node != NULL) {204		if (del_node == fpga_first_inode) {205			fpga_first_inode = del_node->next_inode;206		} else {207			while (prev_node->next_inode != del_node)208				prev_node = prev_node->next_inode;209 210			if (del_node->next_inode == NULL)211				prev_node->next_inode = NULL;212			else213				prev_node->next_inode =214					prev_node->next_inode->next_inode;215		}216 217		kfree(del_node);218	}219}220 221/* allocating new chip */222static struct fpga_inode *append_internal(struct fpga_internal *internal)223{224	struct fpga_inode *new_node = fpga_first_inode;225 226	if (new_node == NULL) {227		new_node = kmalloc(sizeof(struct fpga_inode), GFP_KERNEL);228		fpga_first_inode = new_node;229	} else {230		while (new_node->next_inode != NULL)231			new_node = new_node->next_inode;232 233		new_node->next_inode =234				kmalloc(sizeof(struct fpga_inode), GFP_KERNEL);235		if (new_node->next_inode != NULL)236			new_node = new_node->next_inode;237		else238			new_node = NULL;239	}240 241	if (new_node != NULL) {242		new_node->internal = internal;243		new_node->next_inode = NULL;244	}245 246	return new_node;247}248 249static int netup_fpga_op_rw(struct fpga_internal *inter, int addr,250							u8 val, u8 read)251{252	inter->fpga_rw(inter->dev, NETUP_CI_FLG_AD, addr, 0);253	return inter->fpga_rw(inter->dev, 0, val, read);254}255 256/* flag - mem/io, read - read/write */257static int altera_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,258				u8 flag, u8 read, int addr, u8 val)259{260 261	struct altera_ci_state *state = en50221->data;262	struct fpga_internal *inter = state->internal;263 264	u8 store;265	int mem = 0;266 267	if (0 != slot)268		return -EINVAL;269 270	mutex_lock(&inter->fpga_mutex);271 272	netup_fpga_op_rw(inter, NETUP_CI_ADDR0, ((addr << 1) & 0xfe), 0);273	netup_fpga_op_rw(inter, NETUP_CI_ADDR1, ((addr >> 7) & 0x7f), 0);274	store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);275 276	store &= 0x0f;277	store |= ((state->nr << 7) | (flag << 6));278 279	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, store, 0);280	mem = netup_fpga_op_rw(inter, NETUP_CI_DATA, val, read);281 282	mutex_unlock(&inter->fpga_mutex);283 284	ci_dbg_print("%s: %s: addr=[0x%02x], %s=%x\n", __func__,285			(read) ? "read" : "write", addr,286			(flag == NETUP_CI_FLG_CTL) ? "ctl" : "mem",287			(read) ? mem : val);288 289	return mem;290}291 292static int altera_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,293					int slot, int addr)294{295	return altera_ci_op_cam(en50221, slot, 0, NETUP_CI_FLG_RD, addr, 0);296}297 298static int altera_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,299					 int slot, int addr, u8 data)300{301	return altera_ci_op_cam(en50221, slot, 0, 0, addr, data);302}303 304static int altera_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221,305				  int slot, u8 addr)306{307	return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL,308						NETUP_CI_FLG_RD, addr, 0);309}310 311static int altera_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,312				   u8 addr, u8 data)313{314	return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL, 0, addr, data);315}316 317static int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)318{319	struct altera_ci_state *state = en50221->data;320	struct fpga_internal *inter = state->internal;321	/* reasonable timeout for CI reset is 10 seconds */322	unsigned long t_out = jiffies + msecs_to_jiffies(9999);323	int ret;324 325	ci_dbg_print("%s\n", __func__);326 327	if (0 != slot)328		return -EINVAL;329 330	mutex_lock(&inter->fpga_mutex);331 332	ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);333	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,334				(ret & 0xcf) | (1 << (5 - state->nr)), 0);335 336	mutex_unlock(&inter->fpga_mutex);337 338	for (;;) {339		msleep(50);340 341		mutex_lock(&inter->fpga_mutex);342 343		ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,344						0, NETUP_CI_FLG_RD);345		mutex_unlock(&inter->fpga_mutex);346 347		if ((ret & (1 << (5 - state->nr))) == 0)348			break;349		if (time_after(jiffies, t_out))350			break;351	}352 353 354	ci_dbg_print("%s: %d msecs\n", __func__,355		jiffies_to_msecs(jiffies + msecs_to_jiffies(9999) - t_out));356 357	return 0;358}359 360static int altera_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)361{362	/* not implemented */363	return 0;364}365 366static int altera_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)367{368	struct altera_ci_state *state = en50221->data;369	struct fpga_internal *inter = state->internal;370	int ret;371 372	ci_dbg_print("%s\n", __func__);373 374	if (0 != slot)375		return -EINVAL;376 377	mutex_lock(&inter->fpga_mutex);378 379	ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);380	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,381				(ret & 0x0f) | (1 << (3 - state->nr)), 0);382 383	mutex_unlock(&inter->fpga_mutex);384 385	return 0;386}387 388/* work handler */389static void netup_read_ci_status(struct work_struct *work)390{391	struct fpga_internal *inter =392			container_of(work, struct fpga_internal, work);393	int ret;394 395	ci_dbg_print("%s\n", __func__);396 397	mutex_lock(&inter->fpga_mutex);398	/* ack' irq */399	ret = netup_fpga_op_rw(inter, NETUP_CI_INT_CTRL, 0, NETUP_CI_FLG_RD);400	ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);401 402	mutex_unlock(&inter->fpga_mutex);403 404	if (inter->state[1] != NULL) {405		inter->state[1]->status =406				((ret & 1) == 0 ?407				DVB_CA_EN50221_POLL_CAM_PRESENT |408				DVB_CA_EN50221_POLL_CAM_READY : 0);409		ci_dbg_print("%s: setting CI[1] status = 0x%x\n",410				__func__, inter->state[1]->status);411	}412 413	if (inter->state[0] != NULL) {414		inter->state[0]->status =415				((ret & 2) == 0 ?416				DVB_CA_EN50221_POLL_CAM_PRESENT |417				DVB_CA_EN50221_POLL_CAM_READY : 0);418		ci_dbg_print("%s: setting CI[0] status = 0x%x\n",419				__func__, inter->state[0]->status);420	}421}422 423/* CI irq handler */424int altera_ci_irq(void *dev)425{426	struct fpga_inode *temp_int = NULL;427	struct fpga_internal *inter = NULL;428 429	ci_dbg_print("%s\n", __func__);430 431	if (dev != NULL) {432		temp_int = find_inode(dev);433		if (temp_int != NULL) {434			inter = temp_int->internal;435			schedule_work(&inter->work);436		}437	}438 439	return 1;440}441EXPORT_SYMBOL(altera_ci_irq);442 443static int altera_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,444				      int slot, int open)445{446	struct altera_ci_state *state = en50221->data;447 448	if (0 != slot)449		return -EINVAL;450 451	return state->status;452}453 454static void altera_hw_filt_release(void *main_dev, int filt_nr)455{456	struct fpga_inode *temp_int = find_inode(main_dev);457	struct netup_hw_pid_filter *pid_filt = NULL;458 459	ci_dbg_print("%s\n", __func__);460 461	if (temp_int != NULL) {462		pid_filt = temp_int->internal->pid_filt[filt_nr - 1];463		/* stored old feed controls */464		pid_filt->demux->start_feed = pid_filt->start_feed;465		pid_filt->demux->stop_feed = pid_filt->stop_feed;466 467		if (((--(temp_int->internal->filts_used)) <= 0) &&468			 ((temp_int->internal->cis_used) <= 0)) {469 470			ci_dbg_print("%s: Actually removing\n", __func__);471 472			remove_inode(temp_int->internal);473			kfree(pid_filt->internal);474		}475 476		kfree(pid_filt);477 478	}479 480}481 482void altera_ci_release(void *dev, int ci_nr)483{484	struct fpga_inode *temp_int = find_inode(dev);485	struct altera_ci_state *state = NULL;486 487	ci_dbg_print("%s\n", __func__);488 489	if (temp_int != NULL) {490		state = temp_int->internal->state[ci_nr - 1];491		altera_hw_filt_release(dev, ci_nr);492 493 494		if (((temp_int->internal->filts_used) <= 0) &&495				((--(temp_int->internal->cis_used)) <= 0)) {496 497			ci_dbg_print("%s: Actually removing\n", __func__);498 499			remove_inode(temp_int->internal);500			kfree(state->internal);501		}502 503		if (state != NULL) {504			if (state->ca.data != NULL)505				dvb_ca_en50221_release(&state->ca);506 507			kfree(state);508		}509	}510 511}512EXPORT_SYMBOL(altera_ci_release);513 514static void altera_pid_control(struct netup_hw_pid_filter *pid_filt,515		u16 pid, int onoff)516{517	struct fpga_internal *inter = pid_filt->internal;518	u8 store = 0;519 520	/* pid 0-0x1f always enabled, don't touch them */521	if ((pid == 0x2000) || (pid < 0x20))522		return;523 524	mutex_lock(&inter->fpga_mutex);525 526	netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR0, (pid >> 3) & 0xff, 0);527	netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR1,528			((pid >> 11) & 0x03) | (pid_filt->nr << 2), 0);529 530	store = netup_fpga_op_rw(inter, NETUP_CI_PID_DATA, 0, NETUP_CI_FLG_RD);531 532	if (onoff)/* 0 - on, 1 - off */533		store |= (1 << (pid & 7));534	else535		store &= ~(1 << (pid & 7));536 537	netup_fpga_op_rw(inter, NETUP_CI_PID_DATA, store, 0);538 539	mutex_unlock(&inter->fpga_mutex);540 541	pid_dbg_print("%s: (%d) set pid: %5d 0x%04x '%s'\n", __func__,542		pid_filt->nr, pid, pid, onoff ? "off" : "on");543}544 545static void altera_toggle_fullts_streaming(struct netup_hw_pid_filter *pid_filt,546					int filt_nr, int onoff)547{548	struct fpga_internal *inter = pid_filt->internal;549	u8 store = 0;550	int i;551 552	pid_dbg_print("%s: pid_filt->nr[%d]  now %s\n", __func__, pid_filt->nr,553			onoff ? "off" : "on");554 555	if (onoff)/* 0 - on, 1 - off */556		store = 0xff;/* ignore pid */557	else558		store = 0;/* enable pid */559 560	mutex_lock(&inter->fpga_mutex);561 562	for (i = 0; i < 1024; i++) {563		netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR0, i & 0xff, 0);564 565		netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR1,566				((i >> 8) & 0x03) | (pid_filt->nr << 2), 0);567		/* pid 0-0x1f always enabled */568		netup_fpga_op_rw(inter, NETUP_CI_PID_DATA,569				(i > 3 ? store : 0), 0);570	}571 572	mutex_unlock(&inter->fpga_mutex);573}574 575static int altera_pid_feed_control(void *demux_dev, int filt_nr,576		struct dvb_demux_feed *feed, int onoff)577{578	struct fpga_inode *temp_int = find_dinode(demux_dev);579	struct fpga_internal *inter = temp_int->internal;580	struct netup_hw_pid_filter *pid_filt = inter->pid_filt[filt_nr - 1];581 582	altera_pid_control(pid_filt, feed->pid, onoff ? 0 : 1);583	/* call old feed proc's */584	if (onoff)585		pid_filt->start_feed(feed);586	else587		pid_filt->stop_feed(feed);588 589	if (feed->pid == 0x2000)590		altera_toggle_fullts_streaming(pid_filt, filt_nr,591						onoff ? 0 : 1);592 593	return 0;594}595 596static int altera_ci_start_feed(struct dvb_demux_feed *feed, int num)597{598	altera_pid_feed_control(feed->demux, num, feed, 1);599 600	return 0;601}602 603static int altera_ci_stop_feed(struct dvb_demux_feed *feed, int num)604{605	altera_pid_feed_control(feed->demux, num, feed, 0);606 607	return 0;608}609 610static int altera_ci_start_feed_1(struct dvb_demux_feed *feed)611{612	return altera_ci_start_feed(feed, 1);613}614 615static int altera_ci_stop_feed_1(struct dvb_demux_feed *feed)616{617	return altera_ci_stop_feed(feed, 1);618}619 620static int altera_ci_start_feed_2(struct dvb_demux_feed *feed)621{622	return altera_ci_start_feed(feed, 2);623}624 625static int altera_ci_stop_feed_2(struct dvb_demux_feed *feed)626{627	return altera_ci_stop_feed(feed, 2);628}629 630static int altera_hw_filt_init(struct altera_ci_config *config, int hw_filt_nr)631{632	struct netup_hw_pid_filter *pid_filt = NULL;633	struct fpga_inode *temp_int = find_inode(config->dev);634	struct fpga_internal *inter = NULL;635	int ret = 0;636 637	pid_filt = kzalloc(sizeof(struct netup_hw_pid_filter), GFP_KERNEL);638 639	ci_dbg_print("%s\n", __func__);640 641	if (!pid_filt) {642		ret = -ENOMEM;643		goto err;644	}645 646	if (temp_int != NULL) {647		inter = temp_int->internal;648		(inter->filts_used)++;649		ci_dbg_print("%s: Find Internal Structure!\n", __func__);650	} else {651		inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);652		if (!inter) {653			ret = -ENOMEM;654			goto err;655		}656 657		temp_int = append_internal(inter);658		if (!temp_int) {659			ret = -ENOMEM;660			goto err;661		}662		inter->filts_used = 1;663		inter->dev = config->dev;664		inter->fpga_rw = config->fpga_rw;665		mutex_init(&inter->fpga_mutex);666		inter->strt_wrk = 1;667		ci_dbg_print("%s: Create New Internal Structure!\n", __func__);668	}669 670	ci_dbg_print("%s: setting hw pid filter = %p for ci = %d\n", __func__,671						pid_filt, hw_filt_nr - 1);672	inter->pid_filt[hw_filt_nr - 1] = pid_filt;673	pid_filt->demux = config->demux;674	pid_filt->internal = inter;675	pid_filt->nr = hw_filt_nr - 1;676	/* store old feed controls */677	pid_filt->start_feed = config->demux->start_feed;678	pid_filt->stop_feed = config->demux->stop_feed;679	/* replace with new feed controls */680	if (hw_filt_nr == 1) {681		pid_filt->demux->start_feed = altera_ci_start_feed_1;682		pid_filt->demux->stop_feed = altera_ci_stop_feed_1;683	} else if (hw_filt_nr == 2) {684		pid_filt->demux->start_feed = altera_ci_start_feed_2;685		pid_filt->demux->stop_feed = altera_ci_stop_feed_2;686	}687 688	altera_toggle_fullts_streaming(pid_filt, 0, 1);689 690	return 0;691err:692	ci_dbg_print("%s: Can't init hardware filter: Error %d\n",693		     __func__, ret);694 695	kfree(pid_filt);696	kfree(inter);697 698	return ret;699}700 701int altera_ci_init(struct altera_ci_config *config, int ci_nr)702{703	struct altera_ci_state *state;704	struct fpga_inode *temp_int = find_inode(config->dev);705	struct fpga_internal *inter = NULL;706	int ret = 0;707	u8 store = 0;708 709	state = kzalloc(sizeof(struct altera_ci_state), GFP_KERNEL);710 711	ci_dbg_print("%s\n", __func__);712 713	if (!state) {714		ret = -ENOMEM;715		goto err;716	}717 718	if (temp_int != NULL) {719		inter = temp_int->internal;720		(inter->cis_used)++;721		inter->fpga_rw = config->fpga_rw;722		ci_dbg_print("%s: Find Internal Structure!\n", __func__);723	} else {724		inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);725		if (!inter) {726			ret = -ENOMEM;727			goto err;728		}729 730		temp_int = append_internal(inter);731		if (!temp_int) {732			ret = -ENOMEM;733			goto err;734		}735		inter->cis_used = 1;736		inter->dev = config->dev;737		inter->fpga_rw = config->fpga_rw;738		mutex_init(&inter->fpga_mutex);739		inter->strt_wrk = 1;740		ci_dbg_print("%s: Create New Internal Structure!\n", __func__);741	}742 743	ci_dbg_print("%s: setting state = %p for ci = %d\n", __func__,744						state, ci_nr - 1);745	state->internal = inter;746	state->nr = ci_nr - 1;747 748	state->ca.owner = THIS_MODULE;749	state->ca.read_attribute_mem = altera_ci_read_attribute_mem;750	state->ca.write_attribute_mem = altera_ci_write_attribute_mem;751	state->ca.read_cam_control = altera_ci_read_cam_ctl;752	state->ca.write_cam_control = altera_ci_write_cam_ctl;753	state->ca.slot_reset = altera_ci_slot_reset;754	state->ca.slot_shutdown = altera_ci_slot_shutdown;755	state->ca.slot_ts_enable = altera_ci_slot_ts_ctl;756	state->ca.poll_slot_status = altera_poll_ci_slot_status;757	state->ca.data = state;758 759	ret = dvb_ca_en50221_init(config->adapter,760				   &state->ca,761				   /* flags */ 0,762				   /* n_slots */ 1);763	if (0 != ret)764		goto err;765 766	inter->state[ci_nr - 1] = state;767 768	altera_hw_filt_init(config, ci_nr);769 770	if (inter->strt_wrk) {771		INIT_WORK(&inter->work, netup_read_ci_status);772		inter->strt_wrk = 0;773	}774 775	ci_dbg_print("%s: CI initialized!\n", __func__);776 777	mutex_lock(&inter->fpga_mutex);778 779	/* Enable div */780	netup_fpga_op_rw(inter, NETUP_CI_TSA_DIV, 0x0, 0);781	netup_fpga_op_rw(inter, NETUP_CI_TSB_DIV, 0x0, 0);782 783	/* enable TS out */784	store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, 0, NETUP_CI_FLG_RD);785	store |= (3 << 4);786	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);787 788	ret = netup_fpga_op_rw(inter, NETUP_CI_REVISION, 0, NETUP_CI_FLG_RD);789	/* enable irq */790	netup_fpga_op_rw(inter, NETUP_CI_INT_CTRL, 0x44, 0);791 792	mutex_unlock(&inter->fpga_mutex);793 794	ci_dbg_print("%s: NetUP CI Revision = 0x%x\n", __func__, ret);795 796	schedule_work(&inter->work);797 798	return 0;799err:800	ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);801 802	kfree(state);803	kfree(inter);804 805	return ret;806}807EXPORT_SYMBOL(altera_ci_init);808 809int altera_ci_tuner_reset(void *dev, int ci_nr)810{811	struct fpga_inode *temp_int = find_inode(dev);812	struct fpga_internal *inter = NULL;813	u8 store;814 815	ci_dbg_print("%s\n", __func__);816 817	if (temp_int == NULL)818		return -1;819 820	if (temp_int->internal == NULL)821		return -1;822 823	inter = temp_int->internal;824 825	mutex_lock(&inter->fpga_mutex);826 827	store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, 0, NETUP_CI_FLG_RD);828	store &= ~(4 << (2 - ci_nr));829	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);830	msleep(100);831	store |= (4 << (2 - ci_nr));832	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);833 834	mutex_unlock(&inter->fpga_mutex);835 836	return 0;837}838EXPORT_SYMBOL(altera_ci_tuner_reset);839