blob: 8f3105420756cebb75753de208c703b5b1a902a9 [file] [log] [blame]
Stefan Richter15490792009-02-23 14:21:10 +01001/*
2 * FireDTV driver (formerly known as FireSAT)
3 *
4 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5 * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
6 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 */
13
14#include <linux/bug.h>
15#include <linux/crc32.h>
16#include <linux/delay.h>
17#include <linux/device.h>
18#include <linux/jiffies.h>
19#include <linux/kernel.h>
20#include <linux/moduleparam.h>
21#include <linux/mutex.h>
22#include <linux/string.h>
23#include <linux/stringify.h>
24#include <linux/wait.h>
25#include <linux/workqueue.h>
26
27#include "firedtv.h"
28
29#define FCP_COMMAND_REGISTER 0xfffff0000b00ULL
30
31#define AVC_CTYPE_CONTROL 0x0
32#define AVC_CTYPE_STATUS 0x1
33#define AVC_CTYPE_NOTIFY 0x3
34
35#define AVC_RESPONSE_ACCEPTED 0x9
36#define AVC_RESPONSE_STABLE 0xc
37#define AVC_RESPONSE_CHANGED 0xd
38#define AVC_RESPONSE_INTERIM 0xf
39
40#define AVC_SUBUNIT_TYPE_TUNER (0x05 << 3)
41#define AVC_SUBUNIT_TYPE_UNIT (0x1f << 3)
42
43#define AVC_OPCODE_VENDOR 0x00
44#define AVC_OPCODE_READ_DESCRIPTOR 0x09
45#define AVC_OPCODE_DSIT 0xc8
46#define AVC_OPCODE_DSD 0xcb
47
48#define DESCRIPTOR_TUNER_STATUS 0x80
49#define DESCRIPTOR_SUBUNIT_IDENTIFIER 0x00
50
51#define SFE_VENDOR_DE_COMPANYID_0 0x00 /* OUI of Digital Everywhere */
52#define SFE_VENDOR_DE_COMPANYID_1 0x12
53#define SFE_VENDOR_DE_COMPANYID_2 0x87
54
55#define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a
56#define SFE_VENDOR_OPCODE_LNB_CONTROL 0x52
57#define SFE_VENDOR_OPCODE_TUNE_QPSK 0x58 /* for DVB-S */
58
59#define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION 0x00
60#define SFE_VENDOR_OPCODE_HOST2CA 0x56
61#define SFE_VENDOR_OPCODE_CA2HOST 0x57
62#define SFE_VENDOR_OPCODE_CISTATUS 0x59
63#define SFE_VENDOR_OPCODE_TUNE_QPSK2 0x60 /* for DVB-S2 */
64
65#define SFE_VENDOR_TAG_CA_RESET 0x00
66#define SFE_VENDOR_TAG_CA_APPLICATION_INFO 0x01
67#define SFE_VENDOR_TAG_CA_PMT 0x02
68#define SFE_VENDOR_TAG_CA_DATE_TIME 0x04
69#define SFE_VENDOR_TAG_CA_MMI 0x05
70#define SFE_VENDOR_TAG_CA_ENTER_MENU 0x07
71
72#define EN50221_LIST_MANAGEMENT_ONLY 0x03
73#define EN50221_TAG_APP_INFO 0x9f8021
74#define EN50221_TAG_CA_INFO 0x9f8031
75
76struct avc_command_frame {
Stefan Richter15490792009-02-23 14:21:10 +010077 u8 ctype;
78 u8 subunit;
79 u8 opcode;
80 u8 operand[509];
81};
82
83struct avc_response_frame {
Stefan Richter15490792009-02-23 14:21:10 +010084 u8 response;
85 u8 subunit;
86 u8 opcode;
87 u8 operand[509];
88};
89
Henrik Kurelid15344772009-08-01 08:04:06 -030090#define AVC_DEBUG_READ_DESCRIPTOR 0x0001
91#define AVC_DEBUG_DSIT 0x0002
92#define AVC_DEBUG_DSD 0x0004
93#define AVC_DEBUG_REGISTER_REMOTE_CONTROL 0x0008
94#define AVC_DEBUG_LNB_CONTROL 0x0010
95#define AVC_DEBUG_TUNE_QPSK 0x0020
96#define AVC_DEBUG_TUNE_QPSK2 0x0040
97#define AVC_DEBUG_HOST2CA 0x0080
98#define AVC_DEBUG_CA2HOST 0x0100
99#define AVC_DEBUG_APPLICATION_PMT 0x4000
100#define AVC_DEBUG_FCP_PAYLOADS 0x8000
Stefan Richter15490792009-02-23 14:21:10 +0100101
102static int avc_debug;
103module_param_named(debug, avc_debug, int, 0644);
Stefan Richter96e242a52009-08-01 08:05:16 -0300104MODULE_PARM_DESC(debug, "Verbose logging (none = 0"
105 ", FCP subactions"
106 ": READ DESCRIPTOR = " __stringify(AVC_DEBUG_READ_DESCRIPTOR)
107 ", DSIT = " __stringify(AVC_DEBUG_DSIT)
108 ", REGISTER_REMOTE_CONTROL = " __stringify(AVC_DEBUG_REGISTER_REMOTE_CONTROL)
109 ", LNB CONTROL = " __stringify(AVC_DEBUG_LNB_CONTROL)
110 ", TUNE QPSK = " __stringify(AVC_DEBUG_TUNE_QPSK)
111 ", TUNE QPSK2 = " __stringify(AVC_DEBUG_TUNE_QPSK2)
112 ", HOST2CA = " __stringify(AVC_DEBUG_HOST2CA)
113 ", CA2HOST = " __stringify(AVC_DEBUG_CA2HOST)
114 "; Application sent PMT = " __stringify(AVC_DEBUG_APPLICATION_PMT)
115 ", FCP payloads = " __stringify(AVC_DEBUG_FCP_PAYLOADS)
116 ", or a combination, or all = -1)");
Stefan Richter15490792009-02-23 14:21:10 +0100117
118static const char *debug_fcp_ctype(unsigned int ctype)
119{
120 static const char *ctypes[] = {
121 [0x0] = "CONTROL", [0x1] = "STATUS",
122 [0x2] = "SPECIFIC INQUIRY", [0x3] = "NOTIFY",
123 [0x4] = "GENERAL INQUIRY", [0x8] = "NOT IMPLEMENTED",
124 [0x9] = "ACCEPTED", [0xa] = "REJECTED",
125 [0xb] = "IN TRANSITION", [0xc] = "IMPLEMENTED/STABLE",
126 [0xd] = "CHANGED", [0xf] = "INTERIM",
127 };
128 const char *ret = ctype < ARRAY_SIZE(ctypes) ? ctypes[ctype] : NULL;
129
130 return ret ? ret : "?";
131}
132
133static const char *debug_fcp_opcode(unsigned int opcode,
Stefan Richter40cf65d2009-03-05 19:13:43 +0100134 const u8 *data, int length)
Stefan Richter15490792009-02-23 14:21:10 +0100135{
136 switch (opcode) {
Stefan Richter96e242a52009-08-01 08:05:16 -0300137 case AVC_OPCODE_VENDOR:
138 break;
139 case AVC_OPCODE_READ_DESCRIPTOR:
140 return avc_debug & AVC_DEBUG_READ_DESCRIPTOR ?
141 "ReadDescriptor" : NULL;
142 case AVC_OPCODE_DSIT:
143 return avc_debug & AVC_DEBUG_DSIT ?
144 "DirectSelectInfo.Type" : NULL;
145 case AVC_OPCODE_DSD:
146 return avc_debug & AVC_DEBUG_DSD ? "DirectSelectData" : NULL;
147 default:
148 return "Unknown";
Stefan Richter15490792009-02-23 14:21:10 +0100149 }
150
151 if (length < 7 ||
152 data[3] != SFE_VENDOR_DE_COMPANYID_0 ||
153 data[4] != SFE_VENDOR_DE_COMPANYID_1 ||
154 data[5] != SFE_VENDOR_DE_COMPANYID_2)
Stefan Richter96e242a52009-08-01 08:05:16 -0300155 return "Vendor/Unknown";
Stefan Richter15490792009-02-23 14:21:10 +0100156
157 switch (data[6]) {
Stefan Richter96e242a52009-08-01 08:05:16 -0300158 case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL:
159 return avc_debug & AVC_DEBUG_REGISTER_REMOTE_CONTROL ?
160 "RegisterRC" : NULL;
161 case SFE_VENDOR_OPCODE_LNB_CONTROL:
162 return avc_debug & AVC_DEBUG_LNB_CONTROL ? "LNBControl" : NULL;
163 case SFE_VENDOR_OPCODE_TUNE_QPSK:
164 return avc_debug & AVC_DEBUG_TUNE_QPSK ? "TuneQPSK" : NULL;
165 case SFE_VENDOR_OPCODE_TUNE_QPSK2:
166 return avc_debug & AVC_DEBUG_TUNE_QPSK2 ? "TuneQPSK2" : NULL;
167 case SFE_VENDOR_OPCODE_HOST2CA:
168 return avc_debug & AVC_DEBUG_HOST2CA ? "Host2CA" : NULL;
169 case SFE_VENDOR_OPCODE_CA2HOST:
170 return avc_debug & AVC_DEBUG_CA2HOST ? "CA2Host" : NULL;
Stefan Richter15490792009-02-23 14:21:10 +0100171 }
Stefan Richter96e242a52009-08-01 08:05:16 -0300172 return "Vendor/Unknown";
Henrik Kurelid15344772009-08-01 08:04:06 -0300173}
174
Stefan Richter40cf65d2009-03-05 19:13:43 +0100175static void debug_fcp(const u8 *data, int length)
Stefan Richter15490792009-02-23 14:21:10 +0100176{
Stefan Richter96e242a52009-08-01 08:05:16 -0300177 unsigned int subunit_type, subunit_id, opcode;
178 const char *op, *prefix;
Stefan Richter15490792009-02-23 14:21:10 +0100179
Stefan Richter96e242a52009-08-01 08:05:16 -0300180 prefix = data[0] > 7 ? "FCP <- " : "FCP -> ";
Henrik Kurelid15344772009-08-01 08:04:06 -0300181 subunit_type = data[1] >> 3;
Stefan Richter96e242a52009-08-01 08:05:16 -0300182 subunit_id = data[1] & 7;
183 opcode = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
184 op = debug_fcp_opcode(opcode, data, length);
185
186 if (op) {
Stefan Richter14edcd52009-04-01 17:25:00 -0300187 printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
Stefan Richter15490792009-02-23 14:21:10 +0100188 prefix, subunit_type, subunit_id, length,
Stefan Richter96e242a52009-08-01 08:05:16 -0300189 debug_fcp_ctype(data[0]), op);
Henrik Kurelid15344772009-08-01 08:04:06 -0300190 if (avc_debug & AVC_DEBUG_FCP_PAYLOADS)
191 print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE,
192 16, 1, data, length, false);
Stefan Richter15490792009-02-23 14:21:10 +0100193 }
Henrik Kurelid15344772009-08-01 08:04:06 -0300194}
Stefan Richter15490792009-02-23 14:21:10 +0100195
Henrik Kurelid15344772009-08-01 08:04:06 -0300196static void debug_pmt(char *msg, int length)
197{
198 printk(KERN_INFO "APP PMT -> l=%d\n", length);
199 print_hex_dump(KERN_INFO, "APP PMT -> ", DUMP_PREFIX_NONE,
200 16, 1, msg, length, false);
Stefan Richter15490792009-02-23 14:21:10 +0100201}
202
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300203static int avc_write(struct firedtv *fdtv)
Stefan Richter15490792009-02-23 14:21:10 +0100204{
205 int err, retry;
206
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300207 fdtv->avc_reply_received = false;
Stefan Richter15490792009-02-23 14:21:10 +0100208
209 for (retry = 0; retry < 6; retry++) {
210 if (unlikely(avc_debug))
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300211 debug_fcp(fdtv->avc_data, fdtv->avc_data_length);
Stefan Richter15490792009-02-23 14:21:10 +0100212
213 err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER,
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300214 fdtv->avc_data, fdtv->avc_data_length);
Stefan Richter15490792009-02-23 14:21:10 +0100215 if (err) {
Stefan Richter15490792009-02-23 14:21:10 +0100216 dev_err(fdtv->device, "FCP command write failed\n");
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300217
Stefan Richter15490792009-02-23 14:21:10 +0100218 return err;
219 }
220
Stefan Richter15490792009-02-23 14:21:10 +0100221 /*
222 * AV/C specs say that answers should be sent within 150 ms.
223 * Time out after 200 ms.
224 */
225 if (wait_event_timeout(fdtv->avc_wait,
226 fdtv->avc_reply_received,
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300227 msecs_to_jiffies(200)) != 0)
Stefan Richter15490792009-02-23 14:21:10 +0100228 return 0;
Stefan Richter15490792009-02-23 14:21:10 +0100229 }
230 dev_err(fdtv->device, "FCP response timed out\n");
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300231
Stefan Richter15490792009-02-23 14:21:10 +0100232 return -ETIMEDOUT;
233}
234
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300235static bool is_register_rc(struct avc_response_frame *r)
Stefan Richter15490792009-02-23 14:21:10 +0100236{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300237 return r->opcode == AVC_OPCODE_VENDOR &&
238 r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
239 r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
240 r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
241 r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
Stefan Richter15490792009-02-23 14:21:10 +0100242}
243
244int avc_recv(struct firedtv *fdtv, void *data, size_t length)
245{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300246 struct avc_response_frame *r = data;
Stefan Richter15490792009-02-23 14:21:10 +0100247
248 if (unlikely(avc_debug))
249 debug_fcp(data, length);
250
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300251 if (length >= 8 && is_register_rc(r)) {
252 switch (r->response) {
253 case AVC_RESPONSE_CHANGED:
254 fdtv_handle_rc(fdtv, r->operand[4] << 8 | r->operand[5]);
Stefan Richter15490792009-02-23 14:21:10 +0100255 schedule_work(&fdtv->remote_ctrl_work);
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300256 break;
257 case AVC_RESPONSE_INTERIM:
258 if (is_register_rc((void *)fdtv->avc_data))
259 goto wake;
260 break;
261 default:
Stefan Richter15490792009-02-23 14:21:10 +0100262 dev_info(fdtv->device,
263 "remote control result = %d\n", r->response);
264 }
265 return 0;
266 }
267
268 if (fdtv->avc_reply_received) {
269 dev_err(fdtv->device, "out-of-order AVC response, ignored\n");
270 return -EIO;
271 }
272
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300273 memcpy(fdtv->avc_data, data, length);
274 fdtv->avc_data_length = length;
275wake:
Stefan Richter15490792009-02-23 14:21:10 +0100276 fdtv->avc_reply_received = true;
277 wake_up(&fdtv->avc_wait);
278
279 return 0;
280}
281
Henrik Kurelid166987c2009-08-01 08:02:38 -0300282static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
283{
284 int i, n, pos = 1;
285
286 for (i = 0, n = 0; i < 16; i++) {
287 if (test_bit(i, &fdtv->channel_active)) {
288 operand[pos++] = 0x13; /* flowfunction relay */
289 operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
290 operand[pos++] = (fdtv->channel_pid[i] >> 8) & 0x1f;
291 operand[pos++] = fdtv->channel_pid[i] & 0xff;
292 operand[pos++] = 0x00; /* tableID */
293 operand[pos++] = 0x00; /* filter_length */
294 n++;
295 }
296 }
297 operand[0] = n;
298
299 return pos;
300}
301
Stefan Richter15490792009-02-23 14:21:10 +0100302/*
303 * tuning command for setting the relative LNB frequency
304 * (not supported by the AVC standard)
305 */
306static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300307 struct dvb_frontend_parameters *params)
Stefan Richter15490792009-02-23 14:21:10 +0100308{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300309 struct avc_command_frame *c = (void *)fdtv->avc_data;
310
Stefan Richter15490792009-02-23 14:21:10 +0100311 c->opcode = AVC_OPCODE_VENDOR;
312
313 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
314 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
315 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
Beat Michel Liechti32a0f482009-03-26 22:36:52 +0100316 if (fdtv->type == FIREDTV_DVB_S2)
317 c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK2;
318 else
319 c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
Stefan Richter15490792009-02-23 14:21:10 +0100320
321 c->operand[4] = (params->frequency >> 24) & 0xff;
322 c->operand[5] = (params->frequency >> 16) & 0xff;
323 c->operand[6] = (params->frequency >> 8) & 0xff;
324 c->operand[7] = params->frequency & 0xff;
325
326 c->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff;
327 c->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff;
328
329 switch (params->u.qpsk.fec_inner) {
330 case FEC_1_2: c->operand[10] = 0x1; break;
331 case FEC_2_3: c->operand[10] = 0x2; break;
332 case FEC_3_4: c->operand[10] = 0x3; break;
333 case FEC_5_6: c->operand[10] = 0x4; break;
334 case FEC_7_8: c->operand[10] = 0x5; break;
335 case FEC_4_5:
336 case FEC_8_9:
337 case FEC_AUTO:
338 default: c->operand[10] = 0x0;
339 }
340
341 if (fdtv->voltage == 0xff)
342 c->operand[11] = 0xff;
343 else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */
344 c->operand[11] = 0;
345 else
346 c->operand[11] = 1;
347
348 if (fdtv->tone == 0xff)
349 c->operand[12] = 0xff;
350 else if (fdtv->tone == SEC_TONE_ON) /* band */
351 c->operand[12] = 1;
352 else
353 c->operand[12] = 0;
354
355 if (fdtv->type == FIREDTV_DVB_S2) {
356 c->operand[13] = 0x1;
357 c->operand[14] = 0xff;
358 c->operand[15] = 0xff;
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300359 fdtv->avc_data_length = 20;
Stefan Richter15490792009-02-23 14:21:10 +0100360 } else {
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300361 fdtv->avc_data_length = 16;
Stefan Richter15490792009-02-23 14:21:10 +0100362 }
363}
364
Henrik Kurelid166987c2009-08-01 08:02:38 -0300365static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300366 struct dvb_frontend_parameters *params)
Stefan Richter15490792009-02-23 14:21:10 +0100367{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300368 struct avc_command_frame *c = (void *)fdtv->avc_data;
369
Stefan Richter15490792009-02-23 14:21:10 +0100370 c->opcode = AVC_OPCODE_DSD;
371
372 c->operand[0] = 0; /* source plug */
373 c->operand[1] = 0xd2; /* subfunction replace */
374 c->operand[2] = 0x20; /* system id = DVB */
375 c->operand[3] = 0x00; /* antenna number */
376 c->operand[4] = 0x11; /* system_specific_multiplex selection_length */
377
378 /* multiplex_valid_flags, high byte */
379 c->operand[5] = 0 << 7 /* reserved */
380 | 0 << 6 /* Polarisation */
381 | 0 << 5 /* Orbital_Pos */
382 | 1 << 4 /* Frequency */
383 | 1 << 3 /* Symbol_Rate */
384 | 0 << 2 /* FEC_outer */
385 | (params->u.qam.fec_inner != FEC_AUTO ? 1 << 1 : 0)
386 | (params->u.qam.modulation != QAM_AUTO ? 1 << 0 : 0);
387
388 /* multiplex_valid_flags, low byte */
389 c->operand[6] = 0 << 7 /* NetworkID */
390 | 0 << 0 /* reserved */ ;
391
392 c->operand[7] = 0x00;
393 c->operand[8] = 0x00;
394 c->operand[9] = 0x00;
395 c->operand[10] = 0x00;
396
397 c->operand[11] = (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6);
398 c->operand[12] = ((params->frequency / 4000) >> 8) & 0xff;
399 c->operand[13] = (params->frequency / 4000) & 0xff;
400 c->operand[14] = ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff;
401 c->operand[15] = ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff;
402 c->operand[16] = ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0;
403 c->operand[17] = 0x00;
404
405 switch (params->u.qpsk.fec_inner) {
406 case FEC_1_2: c->operand[18] = 0x1; break;
407 case FEC_2_3: c->operand[18] = 0x2; break;
408 case FEC_3_4: c->operand[18] = 0x3; break;
409 case FEC_5_6: c->operand[18] = 0x4; break;
410 case FEC_7_8: c->operand[18] = 0x5; break;
411 case FEC_8_9: c->operand[18] = 0x6; break;
412 case FEC_4_5: c->operand[18] = 0x8; break;
413 case FEC_AUTO:
414 default: c->operand[18] = 0x0;
415 }
416
417 switch (params->u.qam.modulation) {
418 case QAM_16: c->operand[19] = 0x08; break;
419 case QAM_32: c->operand[19] = 0x10; break;
420 case QAM_64: c->operand[19] = 0x18; break;
421 case QAM_128: c->operand[19] = 0x20; break;
422 case QAM_256: c->operand[19] = 0x28; break;
423 case QAM_AUTO:
424 default: c->operand[19] = 0x00;
425 }
426
427 c->operand[20] = 0x00;
428 c->operand[21] = 0x00;
Stefan Richter15490792009-02-23 14:21:10 +0100429
Henrik Kurelid166987c2009-08-01 08:02:38 -0300430 /* Add PIDs to filter */
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300431 fdtv->avc_data_length =
432 ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4);
Stefan Richter15490792009-02-23 14:21:10 +0100433}
434
Henrik Kurelid166987c2009-08-01 08:02:38 -0300435static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300436 struct dvb_frontend_parameters *params)
Stefan Richter15490792009-02-23 14:21:10 +0100437{
438 struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300439 struct avc_command_frame *c = (void *)fdtv->avc_data;
Stefan Richter15490792009-02-23 14:21:10 +0100440
441 c->opcode = AVC_OPCODE_DSD;
442
443 c->operand[0] = 0; /* source plug */
444 c->operand[1] = 0xd2; /* subfunction replace */
445 c->operand[2] = 0x20; /* system id = DVB */
446 c->operand[3] = 0x00; /* antenna number */
447 c->operand[4] = 0x0c; /* system_specific_multiplex selection_length */
448
449 /* multiplex_valid_flags, high byte */
450 c->operand[5] =
451 0 << 7 /* reserved */
452 | 1 << 6 /* CenterFrequency */
453 | (ofdm->bandwidth != BANDWIDTH_AUTO ? 1 << 5 : 0)
454 | (ofdm->constellation != QAM_AUTO ? 1 << 4 : 0)
455 | (ofdm->hierarchy_information != HIERARCHY_AUTO ? 1 << 3 : 0)
456 | (ofdm->code_rate_HP != FEC_AUTO ? 1 << 2 : 0)
457 | (ofdm->code_rate_LP != FEC_AUTO ? 1 << 1 : 0)
458 | (ofdm->guard_interval != GUARD_INTERVAL_AUTO ? 1 << 0 : 0);
459
460 /* multiplex_valid_flags, low byte */
461 c->operand[6] =
462 0 << 7 /* NetworkID */
463 | (ofdm->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
464 | 0 << 5 /* OtherFrequencyFlag */
465 | 0 << 0 /* reserved */ ;
466
467 c->operand[7] = 0x0;
468 c->operand[8] = (params->frequency / 10) >> 24;
469 c->operand[9] = ((params->frequency / 10) >> 16) & 0xff;
470 c->operand[10] = ((params->frequency / 10) >> 8) & 0xff;
471 c->operand[11] = (params->frequency / 10) & 0xff;
472
473 switch (ofdm->bandwidth) {
474 case BANDWIDTH_7_MHZ: c->operand[12] = 0x20; break;
475 case BANDWIDTH_8_MHZ:
476 case BANDWIDTH_6_MHZ: /* not defined by AVC spec */
477 case BANDWIDTH_AUTO:
478 default: c->operand[12] = 0x00;
479 }
480
481 switch (ofdm->constellation) {
482 case QAM_16: c->operand[13] = 1 << 6; break;
483 case QAM_64: c->operand[13] = 2 << 6; break;
484 case QPSK:
485 default: c->operand[13] = 0x00;
486 }
487
488 switch (ofdm->hierarchy_information) {
489 case HIERARCHY_1: c->operand[13] |= 1 << 3; break;
490 case HIERARCHY_2: c->operand[13] |= 2 << 3; break;
491 case HIERARCHY_4: c->operand[13] |= 3 << 3; break;
492 case HIERARCHY_AUTO:
493 case HIERARCHY_NONE:
494 default: break;
495 }
496
497 switch (ofdm->code_rate_HP) {
498 case FEC_2_3: c->operand[13] |= 1; break;
499 case FEC_3_4: c->operand[13] |= 2; break;
500 case FEC_5_6: c->operand[13] |= 3; break;
501 case FEC_7_8: c->operand[13] |= 4; break;
502 case FEC_1_2:
503 default: break;
504 }
505
506 switch (ofdm->code_rate_LP) {
507 case FEC_2_3: c->operand[14] = 1 << 5; break;
508 case FEC_3_4: c->operand[14] = 2 << 5; break;
509 case FEC_5_6: c->operand[14] = 3 << 5; break;
510 case FEC_7_8: c->operand[14] = 4 << 5; break;
511 case FEC_1_2:
512 default: c->operand[14] = 0x00; break;
513 }
514
515 switch (ofdm->guard_interval) {
516 case GUARD_INTERVAL_1_16: c->operand[14] |= 1 << 3; break;
517 case GUARD_INTERVAL_1_8: c->operand[14] |= 2 << 3; break;
518 case GUARD_INTERVAL_1_4: c->operand[14] |= 3 << 3; break;
519 case GUARD_INTERVAL_1_32:
520 case GUARD_INTERVAL_AUTO:
521 default: break;
522 }
523
524 switch (ofdm->transmission_mode) {
525 case TRANSMISSION_MODE_8K: c->operand[14] |= 1 << 1; break;
526 case TRANSMISSION_MODE_2K:
527 case TRANSMISSION_MODE_AUTO:
528 default: break;
529 }
530
531 c->operand[15] = 0x00; /* network_ID[0] */
532 c->operand[16] = 0x00; /* network_ID[1] */
Stefan Richter15490792009-02-23 14:21:10 +0100533
Henrik Kurelid166987c2009-08-01 08:02:38 -0300534 /* Add PIDs to filter */
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300535 fdtv->avc_data_length =
536 ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4);
Stefan Richter15490792009-02-23 14:21:10 +0100537}
538
539int avc_tuner_dsd(struct firedtv *fdtv,
540 struct dvb_frontend_parameters *params)
541{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300542 struct avc_command_frame *c = (void *)fdtv->avc_data;
543 int ret;
544
545 if (mutex_lock_interruptible(&fdtv->avc_mutex))
546 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +0100547
548 memset(c, 0, sizeof(*c));
549
550 c->ctype = AVC_CTYPE_CONTROL;
551 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
552
553 switch (fdtv->type) {
554 case FIREDTV_DVB_S:
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300555 case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params); break;
556 case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params); break;
557 case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params); break;
Stefan Richter15490792009-02-23 14:21:10 +0100558 default:
559 BUG();
560 }
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300561 ret = avc_write(fdtv);
Stefan Richter15490792009-02-23 14:21:10 +0100562#if 0
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300563 /*
564 * FIXME:
565 * u8 *status was an out-parameter of avc_tuner_dsd, unused by caller.
566 * Check for AVC_RESPONSE_ACCEPTED here instead?
567 */
Stefan Richter15490792009-02-23 14:21:10 +0100568 if (status)
569 *status = r->operand[2];
570#endif
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300571 mutex_unlock(&fdtv->avc_mutex);
572
573 if (ret == 0)
574 msleep(500);
575
576 return ret;
Stefan Richter15490792009-02-23 14:21:10 +0100577}
578
579int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
580{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300581 struct avc_command_frame *c = (void *)fdtv->avc_data;
582 int ret, pos, k;
Stefan Richter15490792009-02-23 14:21:10 +0100583
584 if (pidc > 16 && pidc != 0xff)
585 return -EINVAL;
586
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300587 if (mutex_lock_interruptible(&fdtv->avc_mutex))
588 return -EINTR;
589
Stefan Richter15490792009-02-23 14:21:10 +0100590 memset(c, 0, sizeof(*c));
591
592 c->ctype = AVC_CTYPE_CONTROL;
593 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
594 c->opcode = AVC_OPCODE_DSD;
595
596 c->operand[0] = 0; /* source plug */
597 c->operand[1] = 0xd2; /* subfunction replace */
598 c->operand[2] = 0x20; /* system id = DVB */
599 c->operand[3] = 0x00; /* antenna number */
600 c->operand[4] = 0x00; /* system_specific_multiplex selection_length */
601 c->operand[5] = pidc; /* Nr_of_dsd_sel_specs */
602
603 pos = 6;
604 if (pidc != 0xff)
605 for (k = 0; k < pidc; k++) {
606 c->operand[pos++] = 0x13; /* flowfunction relay */
607 c->operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
608 c->operand[pos++] = (pid[k] >> 8) & 0x1f;
609 c->operand[pos++] = pid[k] & 0xff;
610 c->operand[pos++] = 0x00; /* tableID */
611 c->operand[pos++] = 0x00; /* filter_length */
612 }
613
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300614 fdtv->avc_data_length = ALIGN(3 + pos, 4);
615 ret = avc_write(fdtv);
Stefan Richter15490792009-02-23 14:21:10 +0100616
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300617 /* FIXME: check response code? */
Stefan Richter15490792009-02-23 14:21:10 +0100618
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300619 mutex_unlock(&fdtv->avc_mutex);
620
621 if (ret == 0)
622 msleep(50);
623
624 return ret;
Stefan Richter15490792009-02-23 14:21:10 +0100625}
626
627int avc_tuner_get_ts(struct firedtv *fdtv)
628{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300629 struct avc_command_frame *c = (void *)fdtv->avc_data;
630 int ret, sl;
631
632 if (mutex_lock_interruptible(&fdtv->avc_mutex))
633 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +0100634
635 memset(c, 0, sizeof(*c));
636
637 c->ctype = AVC_CTYPE_CONTROL;
638 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
639 c->opcode = AVC_OPCODE_DSIT;
640
641 sl = fdtv->type == FIREDTV_DVB_T ? 0x0c : 0x11;
642
643 c->operand[0] = 0; /* source plug */
644 c->operand[1] = 0xd2; /* subfunction replace */
645 c->operand[2] = 0xff; /* status */
646 c->operand[3] = 0x20; /* system id = DVB */
647 c->operand[4] = 0x00; /* antenna number */
648 c->operand[5] = 0x0; /* system_specific_search_flags */
649 c->operand[6] = sl; /* system_specific_multiplex selection_length */
650 c->operand[7] = 0x00; /* valid_flags [0] */
651 c->operand[8] = 0x00; /* valid_flags [1] */
652 c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */
653
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300654 fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
655 ret = avc_write(fdtv);
Stefan Richter15490792009-02-23 14:21:10 +0100656
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300657 /* FIXME: check response code? */
Stefan Richter15490792009-02-23 14:21:10 +0100658
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300659 mutex_unlock(&fdtv->avc_mutex);
660
661 if (ret == 0)
662 msleep(250);
663
664 return ret;
Stefan Richter15490792009-02-23 14:21:10 +0100665}
666
667int avc_identify_subunit(struct firedtv *fdtv)
668{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300669 struct avc_command_frame *c = (void *)fdtv->avc_data;
670 struct avc_response_frame *r = (void *)fdtv->avc_data;
671 int ret;
672
673 if (mutex_lock_interruptible(&fdtv->avc_mutex))
674 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +0100675
676 memset(c, 0, sizeof(*c));
677
678 c->ctype = AVC_CTYPE_CONTROL;
679 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
680 c->opcode = AVC_OPCODE_READ_DESCRIPTOR;
681
682 c->operand[0] = DESCRIPTOR_SUBUNIT_IDENTIFIER;
683 c->operand[1] = 0xff;
684 c->operand[2] = 0x00;
685 c->operand[3] = 0x00; /* length highbyte */
686 c->operand[4] = 0x08; /* length lowbyte */
687 c->operand[5] = 0x00; /* offset highbyte */
688 c->operand[6] = 0x0d; /* offset lowbyte */
689
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300690 fdtv->avc_data_length = 12;
691 ret = avc_write(fdtv);
692 if (ret < 0)
693 goto out;
Stefan Richter15490792009-02-23 14:21:10 +0100694
695 if ((r->response != AVC_RESPONSE_STABLE &&
696 r->response != AVC_RESPONSE_ACCEPTED) ||
697 (r->operand[3] << 8) + r->operand[4] != 8) {
698 dev_err(fdtv->device, "cannot read subunit identifier\n");
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300699 ret = -EINVAL;
Stefan Richter15490792009-02-23 14:21:10 +0100700 }
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300701out:
702 mutex_unlock(&fdtv->avc_mutex);
703
704 return ret;
Stefan Richter15490792009-02-23 14:21:10 +0100705}
706
707#define SIZEOF_ANTENNA_INPUT_INFO 22
708
709int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
710{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300711 struct avc_command_frame *c = (void *)fdtv->avc_data;
712 struct avc_response_frame *r = (void *)fdtv->avc_data;
713 int length, ret;
714
715 if (mutex_lock_interruptible(&fdtv->avc_mutex))
716 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +0100717
718 memset(c, 0, sizeof(*c));
719
720 c->ctype = AVC_CTYPE_CONTROL;
721 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
722 c->opcode = AVC_OPCODE_READ_DESCRIPTOR;
723
724 c->operand[0] = DESCRIPTOR_TUNER_STATUS;
725 c->operand[1] = 0xff; /* read_result_status */
726 c->operand[2] = 0x00; /* reserved */
727 c->operand[3] = 0; /* SIZEOF_ANTENNA_INPUT_INFO >> 8; */
728 c->operand[4] = 0; /* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */
729 c->operand[5] = 0x00;
730 c->operand[6] = 0x00;
731
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300732 fdtv->avc_data_length = 12;
733 ret = avc_write(fdtv);
734 if (ret < 0)
735 goto out;
Stefan Richter15490792009-02-23 14:21:10 +0100736
737 if (r->response != AVC_RESPONSE_STABLE &&
738 r->response != AVC_RESPONSE_ACCEPTED) {
739 dev_err(fdtv->device, "cannot read tuner status\n");
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300740 ret = -EINVAL;
741 goto out;
Stefan Richter15490792009-02-23 14:21:10 +0100742 }
743
744 length = r->operand[9];
745 if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
746 dev_err(fdtv->device, "got invalid tuner status\n");
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300747 ret = -EINVAL;
748 goto out;
Stefan Richter15490792009-02-23 14:21:10 +0100749 }
750
751 stat->active_system = r->operand[10];
752 stat->searching = r->operand[11] >> 7 & 1;
753 stat->moving = r->operand[11] >> 6 & 1;
754 stat->no_rf = r->operand[11] >> 5 & 1;
755 stat->input = r->operand[12] >> 7 & 1;
756 stat->selected_antenna = r->operand[12] & 0x7f;
757 stat->ber = r->operand[13] << 24 |
758 r->operand[14] << 16 |
759 r->operand[15] << 8 |
760 r->operand[16];
761 stat->signal_strength = r->operand[17];
762 stat->raster_frequency = r->operand[18] >> 6 & 2;
763 stat->rf_frequency = (r->operand[18] & 0x3f) << 16 |
764 r->operand[19] << 8 |
765 r->operand[20];
766 stat->man_dep_info_length = r->operand[21];
767 stat->front_end_error = r->operand[22] >> 4 & 1;
768 stat->antenna_error = r->operand[22] >> 3 & 1;
769 stat->front_end_power_status = r->operand[22] >> 1 & 1;
770 stat->power_supply = r->operand[22] & 1;
771 stat->carrier_noise_ratio = r->operand[23] << 8 |
772 r->operand[24];
773 stat->power_supply_voltage = r->operand[27];
774 stat->antenna_voltage = r->operand[28];
775 stat->firewire_bus_voltage = r->operand[29];
776 stat->ca_mmi = r->operand[30] & 1;
777 stat->ca_pmt_reply = r->operand[31] >> 7 & 1;
778 stat->ca_date_time_request = r->operand[31] >> 6 & 1;
779 stat->ca_application_info = r->operand[31] >> 5 & 1;
780 stat->ca_module_present_status = r->operand[31] >> 4 & 1;
781 stat->ca_dvb_flag = r->operand[31] >> 3 & 1;
782 stat->ca_error_flag = r->operand[31] >> 2 & 1;
783 stat->ca_initialization_status = r->operand[31] >> 1 & 1;
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300784out:
785 mutex_unlock(&fdtv->avc_mutex);
Stefan Richter15490792009-02-23 14:21:10 +0100786
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300787 return ret;
Stefan Richter15490792009-02-23 14:21:10 +0100788}
789
790int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
791 char conttone, char nrdiseq,
792 struct dvb_diseqc_master_cmd *diseqcmd)
793{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300794 struct avc_command_frame *c = (void *)fdtv->avc_data;
795 struct avc_response_frame *r = (void *)fdtv->avc_data;
796 int i, j, k, ret;
797
798 if (mutex_lock_interruptible(&fdtv->avc_mutex))
799 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +0100800
801 memset(c, 0, sizeof(*c));
802
803 c->ctype = AVC_CTYPE_CONTROL;
804 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
805 c->opcode = AVC_OPCODE_VENDOR;
806
807 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
808 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
809 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
810 c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
811
812 c->operand[4] = voltage;
813 c->operand[5] = nrdiseq;
814
815 i = 6;
816
817 for (j = 0; j < nrdiseq; j++) {
818 c->operand[i++] = diseqcmd[j].msg_len;
819
820 for (k = 0; k < diseqcmd[j].msg_len; k++)
821 c->operand[i++] = diseqcmd[j].msg[k];
822 }
823
824 c->operand[i++] = burst;
825 c->operand[i++] = conttone;
826
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300827 fdtv->avc_data_length = ALIGN(3 + i, 4);
828 ret = avc_write(fdtv);
829 if (ret < 0)
830 goto out;
Stefan Richter15490792009-02-23 14:21:10 +0100831
832 if (r->response != AVC_RESPONSE_ACCEPTED) {
833 dev_err(fdtv->device, "LNB control failed\n");
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300834 ret = -EINVAL;
Stefan Richter15490792009-02-23 14:21:10 +0100835 }
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300836out:
837 mutex_unlock(&fdtv->avc_mutex);
Stefan Richter15490792009-02-23 14:21:10 +0100838
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300839 return ret;
Stefan Richter15490792009-02-23 14:21:10 +0100840}
841
842int avc_register_remote_control(struct firedtv *fdtv)
843{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300844 struct avc_command_frame *c = (void *)fdtv->avc_data;
845 int ret;
846
847 if (mutex_lock_interruptible(&fdtv->avc_mutex))
848 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +0100849
850 memset(c, 0, sizeof(*c));
851
852 c->ctype = AVC_CTYPE_NOTIFY;
853 c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
854 c->opcode = AVC_OPCODE_VENDOR;
855
856 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
857 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
858 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
859 c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
860
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300861 fdtv->avc_data_length = 8;
862 ret = avc_write(fdtv);
Stefan Richter15490792009-02-23 14:21:10 +0100863
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300864 /* FIXME: check response code? */
865
866 mutex_unlock(&fdtv->avc_mutex);
867
868 return ret;
Stefan Richter15490792009-02-23 14:21:10 +0100869}
870
871void avc_remote_ctrl_work(struct work_struct *work)
872{
873 struct firedtv *fdtv =
874 container_of(work, struct firedtv, remote_ctrl_work);
875
876 /* Should it be rescheduled in failure cases? */
877 avc_register_remote_control(fdtv);
878}
879
880#if 0 /* FIXME: unused */
881int avc_tuner_host2ca(struct firedtv *fdtv)
882{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300883 struct avc_command_frame *c = (void *)fdtv->avc_data;
884 int ret;
885
886 if (mutex_lock_interruptible(&fdtv->avc_mutex))
887 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +0100888
889 memset(c, 0, sizeof(*c));
890
891 c->ctype = AVC_CTYPE_CONTROL;
892 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
893 c->opcode = AVC_OPCODE_VENDOR;
894
895 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
896 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
897 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
898 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
899 c->operand[4] = 0; /* slot */
900 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
901 c->operand[6] = 0; /* more/last */
902 c->operand[7] = 0; /* length */
903
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300904 fdtv->avc_data_length = 12;
905 ret = avc_write(fdtv);
Stefan Richter15490792009-02-23 14:21:10 +0100906
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300907 /* FIXME: check response code? */
Stefan Richter15490792009-02-23 14:21:10 +0100908
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300909 mutex_unlock(&fdtv->avc_mutex);
910
911 return ret;
Stefan Richter15490792009-02-23 14:21:10 +0100912}
913#endif
914
915static int get_ca_object_pos(struct avc_response_frame *r)
916{
917 int length = 1;
918
919 /* Check length of length field */
920 if (r->operand[7] & 0x80)
921 length = (r->operand[7] & 0x7f) + 1;
922 return length + 7;
923}
924
925static int get_ca_object_length(struct avc_response_frame *r)
926{
927#if 0 /* FIXME: unused */
928 int size = 0;
929 int i;
930
931 if (r->operand[7] & 0x80)
932 for (i = 0; i < (r->operand[7] & 0x7f); i++) {
933 size <<= 8;
934 size += r->operand[8 + i];
935 }
936#endif
937 return r->operand[7];
938}
939
940int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
941{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300942 struct avc_command_frame *c = (void *)fdtv->avc_data;
943 struct avc_response_frame *r = (void *)fdtv->avc_data;
944 int pos, ret;
945
946 if (mutex_lock_interruptible(&fdtv->avc_mutex))
947 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +0100948
949 memset(c, 0, sizeof(*c));
950
951 c->ctype = AVC_CTYPE_STATUS;
952 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
953 c->opcode = AVC_OPCODE_VENDOR;
954
955 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
956 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
957 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
958 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
959 c->operand[4] = 0; /* slot */
960 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
961
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300962 fdtv->avc_data_length = 12;
963 ret = avc_write(fdtv);
964 if (ret < 0)
965 goto out;
Stefan Richter15490792009-02-23 14:21:10 +0100966
967 /* FIXME: check response code and validate response data */
968
969 pos = get_ca_object_pos(r);
970 app_info[0] = (EN50221_TAG_APP_INFO >> 16) & 0xff;
971 app_info[1] = (EN50221_TAG_APP_INFO >> 8) & 0xff;
972 app_info[2] = (EN50221_TAG_APP_INFO >> 0) & 0xff;
973 app_info[3] = 6 + r->operand[pos + 4];
974 app_info[4] = 0x01;
975 memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
976 *len = app_info[3] + 4;
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300977out:
978 mutex_unlock(&fdtv->avc_mutex);
Stefan Richter15490792009-02-23 14:21:10 +0100979
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300980 return ret;
Stefan Richter15490792009-02-23 14:21:10 +0100981}
982
983int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
984{
Stefan Richter3fb80ef2009-11-18 16:02:01 -0300985 struct avc_command_frame *c = (void *)fdtv->avc_data;
986 struct avc_response_frame *r = (void *)fdtv->avc_data;
987 int pos, ret;
988
989 if (mutex_lock_interruptible(&fdtv->avc_mutex))
990 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +0100991
992 memset(c, 0, sizeof(*c));
993
994 c->ctype = AVC_CTYPE_STATUS;
995 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
996 c->opcode = AVC_OPCODE_VENDOR;
997
998 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
999 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1000 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1001 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
1002 c->operand[4] = 0; /* slot */
1003 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
1004
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001005 fdtv->avc_data_length = 12;
1006 ret = avc_write(fdtv);
1007 if (ret < 0)
1008 goto out;
Stefan Richter15490792009-02-23 14:21:10 +01001009
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001010 /* FIXME: check response code and validate response data */
Stefan Richter15490792009-02-23 14:21:10 +01001011
1012 pos = get_ca_object_pos(r);
1013 app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
1014 app_info[1] = (EN50221_TAG_CA_INFO >> 8) & 0xff;
1015 app_info[2] = (EN50221_TAG_CA_INFO >> 0) & 0xff;
1016 app_info[3] = 2;
1017 app_info[4] = r->operand[pos + 0];
1018 app_info[5] = r->operand[pos + 1];
1019 *len = app_info[3] + 4;
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001020out:
1021 mutex_unlock(&fdtv->avc_mutex);
Stefan Richter15490792009-02-23 14:21:10 +01001022
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001023 return ret;
Stefan Richter15490792009-02-23 14:21:10 +01001024}
1025
1026int avc_ca_reset(struct firedtv *fdtv)
1027{
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001028 struct avc_command_frame *c = (void *)fdtv->avc_data;
1029 int ret;
1030
1031 if (mutex_lock_interruptible(&fdtv->avc_mutex))
1032 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +01001033
1034 memset(c, 0, sizeof(*c));
1035
1036 c->ctype = AVC_CTYPE_CONTROL;
1037 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1038 c->opcode = AVC_OPCODE_VENDOR;
1039
1040 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1041 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1042 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1043 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
1044 c->operand[4] = 0; /* slot */
1045 c->operand[5] = SFE_VENDOR_TAG_CA_RESET; /* ca tag */
1046 c->operand[6] = 0; /* more/last */
1047 c->operand[7] = 1; /* length */
1048 c->operand[8] = 0; /* force hardware reset */
1049
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001050 fdtv->avc_data_length = 12;
1051 ret = avc_write(fdtv);
Stefan Richter15490792009-02-23 14:21:10 +01001052
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001053 /* FIXME: check response code? */
Stefan Richter15490792009-02-23 14:21:10 +01001054
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001055 mutex_unlock(&fdtv->avc_mutex);
1056
1057 return ret;
Stefan Richter15490792009-02-23 14:21:10 +01001058}
1059
1060int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
1061{
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001062 struct avc_command_frame *c = (void *)fdtv->avc_data;
1063 struct avc_response_frame *r = (void *)fdtv->avc_data;
Stefan Richter15490792009-02-23 14:21:10 +01001064 int list_management;
1065 int program_info_length;
1066 int pmt_cmd_id;
1067 int read_pos;
1068 int write_pos;
1069 int es_info_length;
1070 int crc32_csum;
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001071 int ret;
Stefan Richter15490792009-02-23 14:21:10 +01001072
Henrik Kurelid15344772009-08-01 08:04:06 -03001073 if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT))
1074 debug_pmt(msg, length);
1075
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001076 if (mutex_lock_interruptible(&fdtv->avc_mutex))
1077 return -EINTR;
1078
Stefan Richter15490792009-02-23 14:21:10 +01001079 memset(c, 0, sizeof(*c));
1080
1081 c->ctype = AVC_CTYPE_CONTROL;
1082 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1083 c->opcode = AVC_OPCODE_VENDOR;
1084
1085 if (msg[0] != EN50221_LIST_MANAGEMENT_ONLY) {
1086 dev_info(fdtv->device, "forcing list_management to ONLY\n");
1087 msg[0] = EN50221_LIST_MANAGEMENT_ONLY;
1088 }
1089 /* We take the cmd_id from the programme level only! */
1090 list_management = msg[0];
1091 program_info_length = ((msg[4] & 0x0f) << 8) + msg[5];
1092 if (program_info_length > 0)
1093 program_info_length--; /* Remove pmt_cmd_id */
1094 pmt_cmd_id = msg[6];
1095
1096 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1097 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1098 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1099 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
1100 c->operand[4] = 0; /* slot */
1101 c->operand[5] = SFE_VENDOR_TAG_CA_PMT; /* ca tag */
1102 c->operand[6] = 0; /* more/last */
Henrik Kurelidc94115f2009-10-03 05:37:58 -03001103 /* Use three bytes for length field in case length > 127 */
1104 c->operand[10] = list_management;
1105 c->operand[11] = 0x01; /* pmt_cmd=OK_descramble */
Stefan Richter15490792009-02-23 14:21:10 +01001106
1107 /* TS program map table */
1108
Henrik Kurelidc94115f2009-10-03 05:37:58 -03001109 c->operand[12] = 0x02; /* Table id=2 */
1110 c->operand[13] = 0x80; /* Section syntax + length */
1111 /* c->operand[14] = XXXprogram_info_length + 12; */
1112 c->operand[15] = msg[1]; /* Program number */
1113 c->operand[16] = msg[2];
1114 c->operand[17] = 0x01; /* Version number=0 + current/next=1 */
1115 c->operand[18] = 0x00; /* Section number=0 */
1116 c->operand[19] = 0x00; /* Last section number=0 */
1117 c->operand[20] = 0x1f; /* PCR_PID=1FFF */
1118 c->operand[21] = 0xff;
1119 c->operand[22] = (program_info_length >> 8); /* Program info length */
1120 c->operand[23] = (program_info_length & 0xff);
Stefan Richter15490792009-02-23 14:21:10 +01001121
1122 /* CA descriptors at programme level */
1123 read_pos = 6;
Henrik Kurelidc94115f2009-10-03 05:37:58 -03001124 write_pos = 24;
Stefan Richter15490792009-02-23 14:21:10 +01001125 if (program_info_length > 0) {
1126 pmt_cmd_id = msg[read_pos++];
1127 if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
1128 dev_err(fdtv->device,
1129 "invalid pmt_cmd_id %d\n", pmt_cmd_id);
1130
1131 memcpy(&c->operand[write_pos], &msg[read_pos],
1132 program_info_length);
1133 read_pos += program_info_length;
1134 write_pos += program_info_length;
1135 }
1136 while (read_pos < length) {
1137 c->operand[write_pos++] = msg[read_pos++];
1138 c->operand[write_pos++] = msg[read_pos++];
1139 c->operand[write_pos++] = msg[read_pos++];
1140 es_info_length =
1141 ((msg[read_pos] & 0x0f) << 8) + msg[read_pos + 1];
1142 read_pos += 2;
1143 if (es_info_length > 0)
1144 es_info_length--; /* Remove pmt_cmd_id */
1145 c->operand[write_pos++] = es_info_length >> 8;
1146 c->operand[write_pos++] = es_info_length & 0xff;
1147 if (es_info_length > 0) {
1148 pmt_cmd_id = msg[read_pos++];
1149 if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
1150 dev_err(fdtv->device, "invalid pmt_cmd_id %d "
1151 "at stream level\n", pmt_cmd_id);
1152
1153 memcpy(&c->operand[write_pos], &msg[read_pos],
1154 es_info_length);
1155 read_pos += es_info_length;
1156 write_pos += es_info_length;
1157 }
1158 }
1159
1160 /* CRC */
1161 c->operand[write_pos++] = 0x00;
1162 c->operand[write_pos++] = 0x00;
1163 c->operand[write_pos++] = 0x00;
1164 c->operand[write_pos++] = 0x00;
1165
Henrik Kurelidc94115f2009-10-03 05:37:58 -03001166 c->operand[7] = 0x82;
1167 c->operand[8] = (write_pos - 10) >> 8;
1168 c->operand[9] = (write_pos - 10) & 0xff;
1169 c->operand[14] = write_pos - 15;
Stefan Richter15490792009-02-23 14:21:10 +01001170
1171 crc32_csum = crc32_be(0, &c->operand[10], c->operand[12] - 1);
1172 c->operand[write_pos - 4] = (crc32_csum >> 24) & 0xff;
1173 c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
1174 c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff;
1175 c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff;
1176
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001177 fdtv->avc_data_length = ALIGN(3 + write_pos, 4);
1178 ret = avc_write(fdtv);
1179 if (ret < 0)
1180 goto out;
Stefan Richter15490792009-02-23 14:21:10 +01001181
1182 if (r->response != AVC_RESPONSE_ACCEPTED) {
1183 dev_err(fdtv->device,
1184 "CA PMT failed with response 0x%x\n", r->response);
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001185 ret = -EFAULT;
Stefan Richter15490792009-02-23 14:21:10 +01001186 }
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001187out:
1188 mutex_unlock(&fdtv->avc_mutex);
Stefan Richter15490792009-02-23 14:21:10 +01001189
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001190 return ret;
Stefan Richter15490792009-02-23 14:21:10 +01001191}
1192
1193int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
1194{
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001195 struct avc_command_frame *c = (void *)fdtv->avc_data;
1196 struct avc_response_frame *r = (void *)fdtv->avc_data;
1197 int ret;
1198
1199 if (mutex_lock_interruptible(&fdtv->avc_mutex))
1200 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +01001201
1202 memset(c, 0, sizeof(*c));
1203
1204 c->ctype = AVC_CTYPE_STATUS;
1205 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1206 c->opcode = AVC_OPCODE_VENDOR;
1207
1208 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1209 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1210 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1211 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
1212 c->operand[4] = 0; /* slot */
1213 c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
1214 c->operand[6] = 0; /* more/last */
1215 c->operand[7] = 0; /* length */
1216
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001217 fdtv->avc_data_length = 12;
1218 ret = avc_write(fdtv);
1219 if (ret < 0)
1220 goto out;
Stefan Richter15490792009-02-23 14:21:10 +01001221
1222 /* FIXME: check response code and validate response data */
1223
1224 *interval = r->operand[get_ca_object_pos(r)];
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001225out:
1226 mutex_unlock(&fdtv->avc_mutex);
Stefan Richter15490792009-02-23 14:21:10 +01001227
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001228 return ret;
Stefan Richter15490792009-02-23 14:21:10 +01001229}
1230
1231int avc_ca_enter_menu(struct firedtv *fdtv)
1232{
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001233 struct avc_command_frame *c = (void *)fdtv->avc_data;
1234 int ret;
1235
1236 if (mutex_lock_interruptible(&fdtv->avc_mutex))
1237 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +01001238
1239 memset(c, 0, sizeof(*c));
1240
1241 c->ctype = AVC_CTYPE_STATUS;
1242 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1243 c->opcode = AVC_OPCODE_VENDOR;
1244
1245 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1246 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1247 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1248 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
1249 c->operand[4] = 0; /* slot */
1250 c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
1251 c->operand[6] = 0; /* more/last */
1252 c->operand[7] = 0; /* length */
1253
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001254 fdtv->avc_data_length = 12;
1255 ret = avc_write(fdtv);
Stefan Richter15490792009-02-23 14:21:10 +01001256
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001257 /* FIXME: check response code? */
Stefan Richter15490792009-02-23 14:21:10 +01001258
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001259 mutex_unlock(&fdtv->avc_mutex);
1260
1261 return ret;
Stefan Richter15490792009-02-23 14:21:10 +01001262}
1263
1264int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
1265{
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001266 struct avc_command_frame *c = (void *)fdtv->avc_data;
1267 struct avc_response_frame *r = (void *)fdtv->avc_data;
1268 int ret;
1269
1270 if (mutex_lock_interruptible(&fdtv->avc_mutex))
1271 return -EINTR;
Stefan Richter15490792009-02-23 14:21:10 +01001272
1273 memset(c, 0, sizeof(*c));
1274
1275 c->ctype = AVC_CTYPE_STATUS;
1276 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1277 c->opcode = AVC_OPCODE_VENDOR;
1278
1279 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1280 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1281 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1282 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
1283 c->operand[4] = 0; /* slot */
1284 c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
1285 c->operand[6] = 0; /* more/last */
1286 c->operand[7] = 0; /* length */
1287
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001288 fdtv->avc_data_length = 12;
1289 ret = avc_write(fdtv);
1290 if (ret < 0)
1291 goto out;
Stefan Richter15490792009-02-23 14:21:10 +01001292
1293 /* FIXME: check response code and validate response data */
1294
1295 *len = get_ca_object_length(r);
1296 memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001297out:
1298 mutex_unlock(&fdtv->avc_mutex);
Stefan Richter15490792009-02-23 14:21:10 +01001299
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001300 return ret;
Stefan Richter15490792009-02-23 14:21:10 +01001301}
1302
1303#define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL
1304
Stefan Richter53756592009-11-18 16:01:34 -03001305static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
Stefan Richter15490792009-02-23 14:21:10 +01001306{
1307 int ret;
1308
1309 if (mutex_lock_interruptible(&fdtv->avc_mutex))
1310 return -EINTR;
1311
Stefan Richter53756592009-11-18 16:01:34 -03001312 ret = fdtv->backend->read(fdtv, addr, data);
Stefan Richter15490792009-02-23 14:21:10 +01001313 if (ret < 0)
1314 dev_err(fdtv->device, "CMP: read I/O error\n");
1315
1316 mutex_unlock(&fdtv->avc_mutex);
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001317
Stefan Richter15490792009-02-23 14:21:10 +01001318 return ret;
1319}
1320
Stefan Richter054286b2009-11-08 18:29:08 -03001321static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
Stefan Richter15490792009-02-23 14:21:10 +01001322{
1323 int ret;
1324
1325 if (mutex_lock_interruptible(&fdtv->avc_mutex))
1326 return -EINTR;
1327
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001328 /* data[] is stack-allocated and should not be DMA-mapped. */
1329 memcpy(fdtv->avc_data, data, 8);
1330
1331 ret = fdtv->backend->lock(fdtv, addr, fdtv->avc_data);
Stefan Richter15490792009-02-23 14:21:10 +01001332 if (ret < 0)
1333 dev_err(fdtv->device, "CMP: lock I/O error\n");
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001334 else
1335 memcpy(data, fdtv->avc_data, 8);
Stefan Richter15490792009-02-23 14:21:10 +01001336
1337 mutex_unlock(&fdtv->avc_mutex);
Stefan Richter3fb80ef2009-11-18 16:02:01 -03001338
Stefan Richter15490792009-02-23 14:21:10 +01001339 return ret;
1340}
1341
1342static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
1343{
1344 return (be32_to_cpu(opcr) >> shift) & mask;
1345}
1346
1347static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
1348{
1349 *opcr &= ~cpu_to_be32(mask << shift);
1350 *opcr |= cpu_to_be32((value & mask) << shift);
1351}
1352
1353#define get_opcr_online(v) get_opcr((v), 0x1, 31)
1354#define get_opcr_p2p_connections(v) get_opcr((v), 0x3f, 24)
1355#define get_opcr_channel(v) get_opcr((v), 0x3f, 16)
1356
1357#define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24)
1358#define set_opcr_channel(p, v) set_opcr((p), (v), 0x3f, 16)
1359#define set_opcr_data_rate(p, v) set_opcr((p), (v), 0x3, 14)
1360#define set_opcr_overhead_id(p, v) set_opcr((p), (v), 0xf, 10)
1361
1362int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
1363{
Stefan Richter054286b2009-11-08 18:29:08 -03001364 __be32 old_opcr, opcr[2];
Stefan Richter15490792009-02-23 14:21:10 +01001365 u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
1366 int attempts = 0;
1367 int ret;
1368
Stefan Richter53756592009-11-18 16:01:34 -03001369 ret = cmp_read(fdtv, opcr_address, opcr);
Stefan Richter15490792009-02-23 14:21:10 +01001370 if (ret < 0)
1371 return ret;
1372
1373repeat:
Stefan Richter054286b2009-11-08 18:29:08 -03001374 if (!get_opcr_online(*opcr)) {
Stefan Richter15490792009-02-23 14:21:10 +01001375 dev_err(fdtv->device, "CMP: output offline\n");
1376 return -EBUSY;
1377 }
1378
Stefan Richter054286b2009-11-08 18:29:08 -03001379 old_opcr = *opcr;
Stefan Richter15490792009-02-23 14:21:10 +01001380
Stefan Richter054286b2009-11-08 18:29:08 -03001381 if (get_opcr_p2p_connections(*opcr)) {
1382 if (get_opcr_channel(*opcr) != channel) {
Stefan Richter15490792009-02-23 14:21:10 +01001383 dev_err(fdtv->device, "CMP: cannot change channel\n");
1384 return -EBUSY;
1385 }
1386 dev_info(fdtv->device, "CMP: overlaying connection\n");
1387
1388 /* We don't allocate isochronous resources. */
1389 } else {
Stefan Richter054286b2009-11-08 18:29:08 -03001390 set_opcr_channel(opcr, channel);
1391 set_opcr_data_rate(opcr, 2); /* S400 */
Stefan Richter15490792009-02-23 14:21:10 +01001392
1393 /* FIXME: this is for the worst case - optimize */
Stefan Richter054286b2009-11-08 18:29:08 -03001394 set_opcr_overhead_id(opcr, 0);
Stefan Richter15490792009-02-23 14:21:10 +01001395
1396 /*
1397 * FIXME: allocate isochronous channel and bandwidth at IRM
1398 * fdtv->backend->alloc_resources(fdtv, channels_mask, bw);
1399 */
1400 }
1401
Stefan Richter054286b2009-11-08 18:29:08 -03001402 set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) + 1);
Stefan Richter15490792009-02-23 14:21:10 +01001403
Stefan Richter054286b2009-11-08 18:29:08 -03001404 opcr[1] = *opcr;
1405 opcr[0] = old_opcr;
1406
1407 ret = cmp_lock(fdtv, opcr_address, opcr);
Stefan Richter15490792009-02-23 14:21:10 +01001408 if (ret < 0)
1409 return ret;
1410
Stefan Richter054286b2009-11-08 18:29:08 -03001411 if (old_opcr != *opcr) {
Stefan Richter15490792009-02-23 14:21:10 +01001412 /*
1413 * FIXME: if old_opcr.P2P_Connections > 0,
1414 * deallocate isochronous channel and bandwidth at IRM
1415 * if (...)
1416 * fdtv->backend->dealloc_resources(fdtv, channel, bw);
1417 */
1418
1419 if (++attempts < 6) /* arbitrary limit */
1420 goto repeat;
1421 return -EBUSY;
1422 }
1423
1424 return 0;
1425}
1426
1427void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
1428{
Stefan Richter054286b2009-11-08 18:29:08 -03001429 __be32 old_opcr, opcr[2];
Stefan Richter15490792009-02-23 14:21:10 +01001430 u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
1431 int attempts = 0;
1432
Stefan Richter53756592009-11-18 16:01:34 -03001433 if (cmp_read(fdtv, opcr_address, opcr) < 0)
Stefan Richter15490792009-02-23 14:21:10 +01001434 return;
1435
1436repeat:
Stefan Richter054286b2009-11-08 18:29:08 -03001437 if (!get_opcr_online(*opcr) || !get_opcr_p2p_connections(*opcr) ||
1438 get_opcr_channel(*opcr) != channel) {
Stefan Richter15490792009-02-23 14:21:10 +01001439 dev_err(fdtv->device, "CMP: no connection to break\n");
1440 return;
1441 }
1442
Stefan Richter054286b2009-11-08 18:29:08 -03001443 old_opcr = *opcr;
1444 set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) - 1);
Stefan Richter15490792009-02-23 14:21:10 +01001445
Stefan Richter054286b2009-11-08 18:29:08 -03001446 opcr[1] = *opcr;
1447 opcr[0] = old_opcr;
1448
1449 if (cmp_lock(fdtv, opcr_address, opcr) < 0)
Stefan Richter15490792009-02-23 14:21:10 +01001450 return;
1451
Stefan Richter054286b2009-11-08 18:29:08 -03001452 if (old_opcr != *opcr) {
Stefan Richter15490792009-02-23 14:21:10 +01001453 /*
1454 * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
1455 * owner, deallocate isochronous channel and bandwidth at IRM
1456 * if (...)
1457 * fdtv->backend->dealloc_resources(fdtv, channel, bw);
1458 */
1459
1460 if (++attempts < 6) /* arbitrary limit */
1461 goto repeat;
1462 }
1463}