Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzi...
[pandora-kernel.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 #include <asm/io.h>
26
27 #include "dmxdev.h"
28 #include "dvbdev.h"
29 #include "dvb_demux.h"
30 #include "dvb_frontend.h"
31 #include "dvb_net.h"
32
33 #include "mantis_common.h"
34 #include "mantis_link.h"
35 #include "mantis_hif.h"
36 #include "mantis_reg.h"
37
38 #include "mantis_ca.h"
39
40 static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr)
41 {
42         struct mantis_ca *ca = en50221->data;
43         struct mantis_pci *mantis = ca->ca_priv;
44
45         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot);
46
47         if (slot != 0)
48                 return -EINVAL;
49
50         return mantis_hif_read_mem(ca, addr);
51 }
52
53 static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data)
54 {
55         struct mantis_ca *ca = en50221->data;
56         struct mantis_pci *mantis = ca->ca_priv;
57
58         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot);
59
60         if (slot != 0)
61                 return -EINVAL;
62
63         return mantis_hif_write_mem(ca, addr, data);
64 }
65
66 static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
67 {
68         struct mantis_ca *ca = en50221->data;
69         struct mantis_pci *mantis = ca->ca_priv;
70
71         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot);
72
73         if (slot != 0)
74                 return -EINVAL;
75
76         return mantis_hif_read_iom(ca, addr);
77 }
78
79 static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data)
80 {
81         struct mantis_ca *ca = en50221->data;
82         struct mantis_pci *mantis = ca->ca_priv;
83
84         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot);
85
86         if (slot != 0)
87                 return -EINVAL;
88
89         return mantis_hif_write_iom(ca, addr, data);
90 }
91
92 static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
93 {
94         struct mantis_ca *ca = en50221->data;
95         struct mantis_pci *mantis = ca->ca_priv;
96
97         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot);
98         udelay(500); /* Wait.. */
99         mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */
100         udelay(500);
101         mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */
102         msleep(1000);
103         dvb_ca_en50221_camready_irq(&ca->en50221, 0);
104
105         return 0;
106 }
107
108 static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
109 {
110         struct mantis_ca *ca = en50221->data;
111         struct mantis_pci *mantis = ca->ca_priv;
112
113         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot);
114
115         return 0;
116 }
117
118 static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot)
119 {
120         struct mantis_ca *ca = en50221->data;
121         struct mantis_pci *mantis = ca->ca_priv;
122
123         dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot);
124 /*      mantis_set_direction(mantis, 1); */ /* Enable TS through CAM */
125
126         return 0;
127 }
128
129 static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
130 {
131         struct mantis_ca *ca = en50221->data;
132         struct mantis_pci *mantis = ca->ca_priv;
133
134         dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot);
135
136         if (ca->slot_state == MODULE_INSERTED) {
137                 dprintk(MANTIS_DEBUG, 1, "CA Module present and ready");
138                 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
139         } else {
140                 dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready");
141         }
142
143         return 0;
144 }
145
146 int mantis_ca_init(struct mantis_pci *mantis)
147 {
148         struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter;
149         struct mantis_ca *ca;
150         int ca_flags = 0, result;
151
152         dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA");
153         ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL);
154         if (!ca) {
155                 dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting ..");
156                 result = -ENOMEM;
157                 goto err;
158         }
159
160         ca->ca_priv             = mantis;
161         mantis->mantis_ca       = ca;
162         ca_flags                = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE;
163         /* register CA interface */
164         ca->en50221.owner               = THIS_MODULE;
165         ca->en50221.read_attribute_mem  = mantis_ca_read_attr_mem;
166         ca->en50221.write_attribute_mem = mantis_ca_write_attr_mem;
167         ca->en50221.read_cam_control    = mantis_ca_read_cam_ctl;
168         ca->en50221.write_cam_control   = mantis_ca_write_cam_ctl;
169         ca->en50221.slot_reset          = mantis_ca_slot_reset;
170         ca->en50221.slot_shutdown       = mantis_ca_slot_shutdown;
171         ca->en50221.slot_ts_enable      = mantis_ts_control;
172         ca->en50221.poll_slot_status    = mantis_slot_status;
173         ca->en50221.data                = ca;
174
175         mutex_init(&ca->ca_lock);
176
177         init_waitqueue_head(&ca->hif_data_wq);
178         init_waitqueue_head(&ca->hif_opdone_wq);
179         init_waitqueue_head(&ca->hif_write_wq);
180
181         dprintk(MANTIS_ERROR, 1, "Registering EN50221 device");
182         result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1);
183         if (result != 0) {
184                 dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result);
185                 goto err;
186         }
187         dprintk(MANTIS_ERROR, 1, "Registered EN50221 device");
188         mantis_evmgr_init(ca);
189         return 0;
190 err:
191         kfree(ca);
192         return result;
193 }
194 EXPORT_SYMBOL_GPL(mantis_ca_init);
195
196 void mantis_ca_exit(struct mantis_pci *mantis)
197 {
198         struct mantis_ca *ca = mantis->mantis_ca;
199
200         dprintk(MANTIS_DEBUG, 1, "Mantis CA exit");
201
202         mantis_evmgr_exit(ca);
203         dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device");
204         if (ca)
205                 dvb_ca_en50221_release(&ca->en50221);
206
207         kfree(ca);
208 }
209 EXPORT_SYMBOL_GPL(mantis_ca_exit);