aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/ttpci/budget-av.c
diff options
context:
space:
mode:
authorAndrew de Quincey <adq_dvb@lidskialf.net>2006-05-22 09:32:02 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-06-25 01:00:06 -0400
commit5c1208ba457a1668c81868060c08496a2d053be0 (patch)
tree293abaefbcb991b6f6d645447ff41aaea3428f11 /drivers/media/dvb/ttpci/budget-av.c
parent48c35756a762e2d569dfd9ab2f24d1b63ea657b9 (diff)
V4L/DVB (3984): Fix CI interface on KNC1 DVBT and DVBC cards
These cards need special handling for CI - reinitialising the frontend device when the CI module is reset. Additionally the tda10021 needs to be set into a different transport stream mode when a CI module is present. Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb/ttpci/budget-av.c')
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c194
1 files changed, 120 insertions, 74 deletions
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 68004187860f..3ff67523cce2 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -50,6 +50,12 @@
50 50
51#define DEBICICAM 0x02420000 51#define DEBICICAM 0x02420000
52 52
53#define SLOTSTATUS_NONE 1
54#define SLOTSTATUS_PRESENT 2
55#define SLOTSTATUS_RESET 4
56#define SLOTSTATUS_READY 8
57#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
58
53struct budget_av { 59struct budget_av {
54 struct budget budget; 60 struct budget budget;
55 struct video_device *vd; 61 struct video_device *vd;
@@ -58,8 +64,15 @@ struct budget_av {
58 struct tasklet_struct ciintf_irq_tasklet; 64 struct tasklet_struct ciintf_irq_tasklet;
59 int slot_status; 65 int slot_status;
60 struct dvb_ca_en50221 ca; 66 struct dvb_ca_en50221 ca;
67 u8 reinitialise_demod:1;
68 u8 tda10021_poclkp:1;
69 u8 tda10021_ts_enabled;
70 int (*tda10021_set_frontend)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
61}; 71};
62 72
73static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot);
74
75
63/* GPIO Connections: 76/* GPIO Connections:
64 * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*! 77 * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
65 * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory 78 * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
@@ -129,9 +142,10 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad
129 udelay(1); 142 udelay(1);
130 143
131 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1); 144 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
132 145 if (result == -ETIMEDOUT) {
133 if (result == -ETIMEDOUT) 146 ciintf_slot_shutdown(ca, slot);
134 budget_av->slot_status = 0; 147 printk(KERN_INFO "budget-av: cam ejected 1\n");
148 }
135 return result; 149 return result;
136} 150}
137 151
@@ -147,9 +161,10 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a
147 udelay(1); 161 udelay(1);
148 162
149 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1); 163 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
150 164 if (result == -ETIMEDOUT) {
151 if (result == -ETIMEDOUT) 165 ciintf_slot_shutdown(ca, slot);
152 budget_av->slot_status = 0; 166 printk(KERN_INFO "budget-av: cam ejected 2\n");
167 }
153 return result; 168 return result;
154} 169}
155 170
@@ -165,9 +180,11 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
165 udelay(1); 180 udelay(1);
166 181
167 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0); 182 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
168 183 if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) {
169 if (result == -ETIMEDOUT) 184 ciintf_slot_shutdown(ca, slot);
170 budget_av->slot_status = 0; 185 printk(KERN_INFO "budget-av: cam ejected 3\n");
186 return -ETIMEDOUT;
187 }
171 return result; 188 return result;
172} 189}
173 190
@@ -183,9 +200,10 @@ static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addr
183 udelay(1); 200 udelay(1);
184 201
185 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0); 202 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
186 203 if (result == -ETIMEDOUT) {
187 if (result == -ETIMEDOUT) 204 ciintf_slot_shutdown(ca, slot);
188 budget_av->slot_status = 0; 205 printk(KERN_INFO "budget-av: cam ejected 5\n");
206 }
189 return result; 207 return result;
190} 208}
191 209
@@ -193,12 +211,12 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
193{ 211{
194 struct budget_av *budget_av = (struct budget_av *) ca->data; 212 struct budget_av *budget_av = (struct budget_av *) ca->data;
195 struct saa7146_dev *saa = budget_av->budget.dev; 213 struct saa7146_dev *saa = budget_av->budget.dev;
196 int timeout = 50; // 5 seconds (4.4.6 Ready)
197 214
198 if (slot != 0) 215 if (slot != 0)
199 return -EINVAL; 216 return -EINVAL;
200 217
201 dprintk(1, "ciintf_slot_reset\n"); 218 dprintk(1, "ciintf_slot_reset\n");
219 budget_av->slot_status = SLOTSTATUS_RESET;
202 220
203 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */ 221 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
204 222
@@ -208,20 +226,17 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
208 msleep(20); /* 20 ms Vcc settling time */ 226 msleep(20); /* 20 ms Vcc settling time */
209 227
210 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */ 228 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
229 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
230 msleep(20);
211 231
212 /* This should have been based on pin 16 READY of the pcmcia port, 232 /* reinitialise the frontend if necessary */
213 * but AFAICS it is not routed to the saa7146 */ 233 if (budget_av->reinitialise_demod)
214 while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d) 234 dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
215 msleep(100);
216
217 /* reinitialise the frontend */
218 dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
219 235
220 if (timeout <= 0) 236 /* set tda10021 back to original clock configuration on reset */
221 { 237 if (budget_av->tda10021_poclkp) {
222 printk(KERN_ERR "budget-av: cam reset failed (timeout).\n"); 238 tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
223 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */ 239 budget_av->tda10021_ts_enabled = 0;
224 return -ETIMEDOUT;
225 } 240 }
226 241
227 return 0; 242 return 0;
@@ -238,7 +253,13 @@ static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
238 dprintk(1, "ciintf_slot_shutdown\n"); 253 dprintk(1, "ciintf_slot_shutdown\n");
239 254
240 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); 255 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
241 budget_av->slot_status = 0; 256 budget_av->slot_status = SLOTSTATUS_NONE;
257
258 /* set tda10021 back to original clock configuration when cam removed */
259 if (budget_av->tda10021_poclkp) {
260 tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
261 budget_av->tda10021_ts_enabled = 0;
262 }
242 return 0; 263 return 0;
243} 264}
244 265
@@ -253,6 +274,13 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
253 dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status); 274 dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
254 275
255 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA); 276 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
277
278 /* tda10021 seems to need a different TS clock config when data is routed to the CAM */
279 if (budget_av->tda10021_poclkp) {
280 tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
281 budget_av->tda10021_ts_enabled = 1;
282 }
283
256 return 0; 284 return 0;
257} 285}
258 286
@@ -260,50 +288,61 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
260{ 288{
261 struct budget_av *budget_av = (struct budget_av *) ca->data; 289 struct budget_av *budget_av = (struct budget_av *) ca->data;
262 struct saa7146_dev *saa = budget_av->budget.dev; 290 struct saa7146_dev *saa = budget_av->budget.dev;
263 int cam_present = 0; 291 int result;
264 292
265 if (slot != 0) 293 if (slot != 0)
266 return -EINVAL; 294 return -EINVAL;
267 295
268 if (!budget_av->slot_status) 296 /* test the card detect line - needs to be done carefully
269 { 297 * since it never goes high for some CAMs on this interface (e.g. topuptv) */
270 // first of all test the card detect line 298 if (budget_av->slot_status == SLOTSTATUS_NONE) {
271 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); 299 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
272 udelay(1); 300 udelay(1);
273 if (saa7146_read(saa, PSR) & MASK_06) 301 if (saa7146_read(saa, PSR) & MASK_06) {
274 { 302 if (budget_av->slot_status == SLOTSTATUS_NONE) {
275 cam_present = 1; 303 budget_av->slot_status = SLOTSTATUS_PRESENT;
304 printk(KERN_INFO "budget-av: cam inserted A\n");
305 }
276 } 306 }
277 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); 307 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
308 }
278 309
279 // that is unreliable however, so try and read from IO memory 310 /* We also try and read from IO memory to work round the above detection bug. If
280 if (!cam_present) 311 * there is no CAM, we will get a timeout. Only done if there is no cam
281 { 312 * present, since this test actually breaks some cams :(
282 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); 313 *
283 if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT) 314 * if the CI interface is not open, we also do the above test since we
284 { 315 * don't care if the cam has problems - we'll be resetting it on open() anyway */
285 cam_present = 1; 316 if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {
317 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
318 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
319 if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
320 budget_av->slot_status = SLOTSTATUS_PRESENT;
321 printk(KERN_INFO "budget-av: cam inserted B\n");
322 } else if (result < 0) {
323 if (budget_av->slot_status != SLOTSTATUS_NONE) {
324 ciintf_slot_shutdown(ca, slot);
325 printk(KERN_INFO "budget-av: cam ejected 5\n");
326 return 0;
286 } 327 }
287 } 328 }
329 }
288 330
289 // did we find something? 331 /* read from attribute memory in reset/ready state to know when the CAM is ready */
290 if (cam_present) { 332 if (budget_av->slot_status == SLOTSTATUS_RESET) {
291 printk(KERN_INFO "budget-av: cam inserted\n"); 333 result = ciintf_read_attribute_mem(ca, slot, 0);
292 budget_av->slot_status = 1; 334 if (result == 0x1d) {
293 } 335 budget_av->slot_status = SLOTSTATUS_READY;
294 } else if (!open) {
295 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
296 if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
297 {
298 printk(KERN_INFO "budget-av: cam ejected\n");
299 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
300 budget_av->slot_status = 0;
301 } 336 }
302 } 337 }
303 338
304 if (budget_av->slot_status == 1) 339 /* work out correct return code */
305 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; 340 if (budget_av->slot_status != SLOTSTATUS_NONE) {
306 341 if (budget_av->slot_status & SLOTSTATUS_READY) {
342 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
343 }
344 return DVB_CA_EN50221_POLL_CAM_PRESENT;
345 }
307 return 0; 346 return 0;
308} 347}
309 348
@@ -333,6 +372,8 @@ static int ciintf_init(struct budget_av *budget_av)
333 budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable; 372 budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
334 budget_av->ca.poll_slot_status = ciintf_poll_slot_status; 373 budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
335 budget_av->ca.data = budget_av; 374 budget_av->ca.data = budget_av;
375 budget_av->budget.ci_present = 1;
376 budget_av->slot_status = SLOTSTATUS_NONE;
336 377
337 if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter, 378 if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
338 &budget_av->ca, 0, 1)) != 0) { 379 &budget_av->ca, 0, 1)) != 0) {
@@ -341,7 +382,6 @@ static int ciintf_init(struct budget_av *budget_av)
341 } 382 }
342 383
343 printk(KERN_INFO "budget-av: ci interface initialised.\n"); 384 printk(KERN_INFO "budget-av: ci interface initialised.\n");
344 budget_av->budget.ci_present = 1;
345 return 0; 385 return 0;
346 386
347error: 387error:
@@ -976,7 +1016,7 @@ static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
976 1016
977static struct stv0299_config philips_sd1878_config = { 1017static struct stv0299_config philips_sd1878_config = {
978 .demod_address = 0x68, 1018 .demod_address = 0x68,
979 .inittab = philips_sd1878_inittab, 1019 .inittab = philips_sd1878_inittab,
980 .mclk = 88000000UL, 1020 .mclk = 88000000UL,
981 .invert = 0, 1021 .invert = 0,
982 .skip_reinit = 0, 1022 .skip_reinit = 0,
@@ -1018,6 +1058,23 @@ static u8 read_pwm(struct budget_av *budget_av)
1018#define SUBID_DVBT_KNC1 0x0030 1058#define SUBID_DVBT_KNC1 0x0030
1019#define SUBID_DVBT_CINERGY1200 0x1157 1059#define SUBID_DVBT_CINERGY1200 0x1157
1020 1060
1061
1062static int tda10021_set_frontend(struct dvb_frontend *fe,
1063 struct dvb_frontend_parameters *p)
1064{
1065 struct budget_av* budget_av = fe->dvb->priv;
1066 int result;
1067
1068 result = budget_av->tda10021_set_frontend(fe, p);
1069 if (budget_av->tda10021_ts_enabled) {
1070 tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
1071 } else {
1072 tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
1073 }
1074
1075 return result;
1076}
1077
1021static void frontend_init(struct budget_av *budget_av) 1078static void frontend_init(struct budget_av *budget_av)
1022{ 1079{
1023 struct saa7146_dev * saa = budget_av->budget.dev; 1080 struct saa7146_dev * saa = budget_av->budget.dev;
@@ -1083,34 +1140,23 @@ static void frontend_init(struct budget_av *budget_av)
1083 1140
1084 case SUBID_DVBC_KNC1: 1141 case SUBID_DVBC_KNC1:
1085 case SUBID_DVBC_KNC1_PLUS: 1142 case SUBID_DVBC_KNC1_PLUS:
1143 case SUBID_DVBC_CINERGY1200:
1144 budget_av->reinitialise_demod = 1;
1086 fe = tda10021_attach(&philips_cu1216_config, 1145 fe = tda10021_attach(&philips_cu1216_config,
1087 &budget_av->budget.i2c_adap, 1146 &budget_av->budget.i2c_adap,
1088 read_pwm(budget_av)); 1147 read_pwm(budget_av));
1089 if (fe) { 1148 if (fe) {
1149 budget_av->tda10021_poclkp = 1;
1150 budget_av->tda10021_set_frontend = fe->ops->set_frontend;
1151 fe->ops->set_frontend = tda10021_set_frontend;
1090 fe->ops->tuner_ops.set_params = philips_cu1216_tuner_set_params; 1152 fe->ops->tuner_ops.set_params = philips_cu1216_tuner_set_params;
1091 } 1153 }
1092 break; 1154 break;
1093 1155
1094 case SUBID_DVBT_KNC1: 1156 case SUBID_DVBT_KNC1:
1095 case SUBID_DVBT_KNC1_PLUS: 1157 case SUBID_DVBT_KNC1_PLUS:
1096 fe = tda10046_attach(&philips_tu1216_config,
1097 &budget_av->budget.i2c_adap);
1098 if (fe) {
1099 fe->ops->tuner_ops.init = philips_tu1216_tuner_init;
1100 fe->ops->tuner_ops.set_params = philips_tu1216_tuner_set_params;
1101 }
1102 break;
1103
1104 case SUBID_DVBC_CINERGY1200:
1105 fe = tda10021_attach(&philips_cu1216_config,
1106 &budget_av->budget.i2c_adap,
1107 read_pwm(budget_av));
1108 if (fe) {
1109 fe->ops->tuner_ops.set_params = philips_cu1216_tuner_set_params;
1110 }
1111 break;
1112
1113 case SUBID_DVBT_CINERGY1200: 1158 case SUBID_DVBT_CINERGY1200:
1159 budget_av->reinitialise_demod = 1;
1114 fe = tda10046_attach(&philips_tu1216_config, 1160 fe = tda10046_attach(&philips_tu1216_config,
1115 &budget_av->budget.i2c_adap); 1161 &budget_av->budget.i2c_adap);
1116 if (fe) { 1162 if (fe) {