330216febd780652ae393d88b31fd9d1e05ebe27
[linux-3.10.git] / drivers / media / dvb / mantis / mantis_ca.c
1 /*
2         Mantis PCI bridge driver
3
4         Copyright (C) Manu Abraham (abraham.manu@gmail.com)
5
6         This program is free software; you can redistribute it and/or modify
7         it under the terms of the GNU General Public License as published by
8         the Free Software Foundation; either version 2 of the License, or
9         (at your option) any later version.
10
11         This program is distributed in the hope that it will be useful,
12         but WITHOUT ANY WARRANTY; without even the implied warranty of
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14         GNU General Public License for more details.
15
16         You should have received a copy of the GNU General Public License
17         along with this program; if not, write to the Free Software
18         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <linux/signal.h>
22 #include <linux/slab.h>
23 #include <linux/sched.h>
24 #include <linux/interrupt.h>
25
26 #include "dmxdev.h"
27 #include "dvbdev.h"
28 #include "dvb_demux.h"
29 #include "dvb_frontend.h"
30 #include "dvb_net.h"
31
32 #include "mantis_common.h"
33 #include "mantis_link.h"
34 #include "mantis_hif.h"
35 #include "mantis_reg.h"
36
37 #include "mantis_ca.h"
38
39 static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr)
40 {
41         struct mantis_ca *ca = en50221->data;
42         struct mantis_pci *mantis = ca->ca_priv;
43
44         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot);
45
46         if (slot != 0)
47                 return -EINVAL;
48
49         return mantis_hif_read_mem(ca, addr);
50 }
51
52 static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data)
53 {
54         struct mantis_ca *ca = en50221->data;
55         struct mantis_pci *mantis = ca->ca_priv;
56
57         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot);
58
59         if (slot != 0)
60                 return -EINVAL;
61
62         return mantis_hif_write_mem(ca, addr, data);
63 }
64
65 static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
66 {
67         struct mantis_ca *ca = en50221->data;
68         struct mantis_pci *mantis = ca->ca_priv;
69
70         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot);
71
72         if (slot != 0)
73                 return -EINVAL;
74
75         return mantis_hif_read_iom(ca, addr);
76 }
77
78 static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data)
79 {
80         struct mantis_ca *ca = en50221->data;
81         struct mantis_pci *mantis = ca->ca_priv;
82
83         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot);
84
85         if (slot != 0)
86                 return -EINVAL;
87
88         return mantis_hif_write_iom(ca, addr, data);
89 }
90
91 static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
92 {
93         struct mantis_ca *ca = en50221->data;
94         struct mantis_pci *mantis = ca->ca_priv;
95
96         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot);
97         udelay(500); /* Wait.. */
98         mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */
99         udelay(500);
100         mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */
101         msleep(1000);
102         dvb_ca_en50221_camready_irq(&ca->en50221, 0);
103
104         return 0;
105 }
106
107 static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
108 {
109         struct mantis_ca *ca = en50221->data;
110         struct mantis_pci *mantis = ca->ca_priv;
111
112         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot);
113
114         return 0;
115 }
116
117 static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot)
118 {
119         struct mantis_ca *ca = en50221->data;
120         struct mantis_pci *mantis = ca->ca_priv;
121
122         dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot);
123 /*      mantis_set_direction(mantis, 1); */ /* Enable TS through CAM */
124
125         return 0;
126 }
127
128 static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
129 {
130         struct mantis_ca *ca = en50221->data;
131         struct mantis_pci *mantis = ca->ca_priv;
132
133         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot);
134
135         if (ca->slot_state == MODULE_INSERTED) {
136                 dprintk(MANTIS_DEBUG, 1, "CA Module present and ready");
137                 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
138         } else {
139                 dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready");
140         }
141
142         return 0;
143 }
144
145 int mantis_ca_init(struct mantis_pci *mantis)
146 {
147         struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter;
148         struct mantis_ca *ca;
149         int ca_flags = 0, result;
150
151         dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA");
152         ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL);
153         if (!ca) {
154                 dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting ..");
155                 result = -ENOMEM;
156                 goto err;
157         }
158
159         ca->ca_priv             = mantis;
160         mantis->mantis_ca       = ca;
161         ca_flags                = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE;
162         /* register CA interface */
163         ca->en50221.owner               = THIS_MODULE;
164         ca->en50221.read_attribute_mem  = mantis_ca_read_attr_mem;
165         ca->en50221.write_attribute_mem = mantis_ca_write_attr_mem;
166         ca->en50221.read_cam_control    = mantis_ca_read_cam_ctl;
167         ca->en50221.write_cam_control   = mantis_ca_write_cam_ctl;
168         ca->en50221.slot_reset          = mantis_ca_slot_reset;
169         ca->en50221.slot_shutdown       = mantis_ca_slot_shutdown;
170         ca->en50221.slot_ts_enable      = mantis_ts_control;
171         ca->en50221.poll_slot_status    = mantis_slot_status;
172         ca->en50221.data                = ca;
173
174         mutex_init(&ca->ca_lock);
175
176         init_waitqueue_head(&ca->hif_data_wq);
177         init_waitqueue_head(&ca->hif_opdone_wq);
178         init_waitqueue_head(&ca->hif_write_wq);
179
180         dprintk(MANTIS_ERROR, 1, "Registering EN50221 device");
181         result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1);
182         if (result != 0) {
183                 dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result);
184                 goto err;
185         }
186         dprintk(MANTIS_ERROR, 1, "Registered EN50221 device");
187         mantis_evmgr_init(ca);
188         return 0;
189 err:
190         kfree(ca);
191         return result;
192 }
193 EXPORT_SYMBOL_GPL(mantis_ca_init);
194
195 void mantis_ca_exit(struct mantis_pci *mantis)
196 {
197         struct mantis_ca *ca = mantis->mantis_ca;
198
199         dprintk(MANTIS_DEBUG, 1, "Mantis CA exit");
200
201         mantis_evmgr_exit(ca);
202         dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device");
203         if (ca)
204                 dvb_ca_en50221_release(&ca->en50221);
205
206         kfree(ca);
207 }
208 EXPORT_SYMBOL_GPL(mantis_ca_exit);