Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
firedtv-avc.c
Go to the documentation of this file.
1 /*
2  * FireDTV driver (formerly known as FireSAT)
3  *
4  * Copyright (C) 2004 Andreas Monitzer <[email protected]>
5  * Copyright (C) 2008 Ben Backx <[email protected]>
6  * Copyright (C) 2008 Henrik Kurelid <[email protected]>
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 <dvb_frontend.h>
28 
29 #include "firedtv.h"
30 
31 #define FCP_COMMAND_REGISTER 0xfffff0000b00ULL
32 
33 #define AVC_CTYPE_CONTROL 0x0
34 #define AVC_CTYPE_STATUS 0x1
35 #define AVC_CTYPE_NOTIFY 0x3
36 
37 #define AVC_RESPONSE_ACCEPTED 0x9
38 #define AVC_RESPONSE_STABLE 0xc
39 #define AVC_RESPONSE_CHANGED 0xd
40 #define AVC_RESPONSE_INTERIM 0xf
41 
42 #define AVC_SUBUNIT_TYPE_TUNER (0x05 << 3)
43 #define AVC_SUBUNIT_TYPE_UNIT (0x1f << 3)
44 
45 #define AVC_OPCODE_VENDOR 0x00
46 #define AVC_OPCODE_READ_DESCRIPTOR 0x09
47 #define AVC_OPCODE_DSIT 0xc8
48 #define AVC_OPCODE_DSD 0xcb
49 
50 #define DESCRIPTOR_TUNER_STATUS 0x80
51 #define DESCRIPTOR_SUBUNIT_IDENTIFIER 0x00
52 
53 #define SFE_VENDOR_DE_COMPANYID_0 0x00 /* OUI of Digital Everywhere */
54 #define SFE_VENDOR_DE_COMPANYID_1 0x12
55 #define SFE_VENDOR_DE_COMPANYID_2 0x87
56 
57 #define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a
58 #define SFE_VENDOR_OPCODE_LNB_CONTROL 0x52
59 #define SFE_VENDOR_OPCODE_TUNE_QPSK 0x58 /* for DVB-S */
60 
61 #define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION 0x00
62 #define SFE_VENDOR_OPCODE_HOST2CA 0x56
63 #define SFE_VENDOR_OPCODE_CA2HOST 0x57
64 #define SFE_VENDOR_OPCODE_CISTATUS 0x59
65 #define SFE_VENDOR_OPCODE_TUNE_QPSK2 0x60 /* for DVB-S2 */
66 
67 #define SFE_VENDOR_TAG_CA_RESET 0x00
68 #define SFE_VENDOR_TAG_CA_APPLICATION_INFO 0x01
69 #define SFE_VENDOR_TAG_CA_PMT 0x02
70 #define SFE_VENDOR_TAG_CA_DATE_TIME 0x04
71 #define SFE_VENDOR_TAG_CA_MMI 0x05
72 #define SFE_VENDOR_TAG_CA_ENTER_MENU 0x07
73 
74 #define EN50221_LIST_MANAGEMENT_ONLY 0x03
75 #define EN50221_TAG_APP_INFO 0x9f8021
76 #define EN50221_TAG_CA_INFO 0x9f8031
77 
82  u8 operand[509];
83 };
84 
89  u8 operand[509];
90 };
91 
92 #define LAST_OPERAND (509 - 1)
93 
94 static inline void clear_operands(struct avc_command_frame *c, int from, int to)
95 {
96  memset(&c->operand[from], 0, to - from + 1);
97 }
98 
99 static void pad_operands(struct avc_command_frame *c, int from)
100 {
101  int to = ALIGN(from, 4);
102 
103  if (from <= to && to <= LAST_OPERAND)
104  clear_operands(c, from, to);
105 }
106 
107 #define AVC_DEBUG_READ_DESCRIPTOR 0x0001
108 #define AVC_DEBUG_DSIT 0x0002
109 #define AVC_DEBUG_DSD 0x0004
110 #define AVC_DEBUG_REGISTER_REMOTE_CONTROL 0x0008
111 #define AVC_DEBUG_LNB_CONTROL 0x0010
112 #define AVC_DEBUG_TUNE_QPSK 0x0020
113 #define AVC_DEBUG_TUNE_QPSK2 0x0040
114 #define AVC_DEBUG_HOST2CA 0x0080
115 #define AVC_DEBUG_CA2HOST 0x0100
116 #define AVC_DEBUG_APPLICATION_PMT 0x4000
117 #define AVC_DEBUG_FCP_PAYLOADS 0x8000
118 
119 static int avc_debug;
120 module_param_named(debug, avc_debug, int, 0644);
121 MODULE_PARM_DESC(debug, "Verbose logging (none = 0"
122  ", FCP subactions"
123  ": READ DESCRIPTOR = " __stringify(AVC_DEBUG_READ_DESCRIPTOR)
124  ", DSIT = " __stringify(AVC_DEBUG_DSIT)
125  ", REGISTER_REMOTE_CONTROL = " __stringify(AVC_DEBUG_REGISTER_REMOTE_CONTROL)
126  ", LNB CONTROL = " __stringify(AVC_DEBUG_LNB_CONTROL)
127  ", TUNE QPSK = " __stringify(AVC_DEBUG_TUNE_QPSK)
128  ", TUNE QPSK2 = " __stringify(AVC_DEBUG_TUNE_QPSK2)
129  ", HOST2CA = " __stringify(AVC_DEBUG_HOST2CA)
130  ", CA2HOST = " __stringify(AVC_DEBUG_CA2HOST)
131  "; Application sent PMT = " __stringify(AVC_DEBUG_APPLICATION_PMT)
132  ", FCP payloads = " __stringify(AVC_DEBUG_FCP_PAYLOADS)
133  ", or a combination, or all = -1)");
134 
135 /*
136  * This is a workaround since there is no vendor specific command to retrieve
137  * ca_info using AVC. If this parameter is not used, ca_system_id will be
138  * filled with application_manufacturer from ca_app_info.
139  * Digital Everywhere have said that adding ca_info is on their TODO list.
140  */
141 static unsigned int num_fake_ca_system_ids;
142 static int fake_ca_system_ids[4] = { -1, -1, -1, -1 };
143 module_param_array(fake_ca_system_ids, int, &num_fake_ca_system_ids, 0644);
144 MODULE_PARM_DESC(fake_ca_system_ids, "If your CAM application manufacturer "
145  "does not have the same ca_system_id as your CAS, you can "
146  "override what ca_system_ids are presented to the "
147  "application by setting this field to an array of ids.");
148 
149 static const char *debug_fcp_ctype(unsigned int ctype)
150 {
151  static const char *ctypes[] = {
152  [0x0] = "CONTROL", [0x1] = "STATUS",
153  [0x2] = "SPECIFIC INQUIRY", [0x3] = "NOTIFY",
154  [0x4] = "GENERAL INQUIRY", [0x8] = "NOT IMPLEMENTED",
155  [0x9] = "ACCEPTED", [0xa] = "REJECTED",
156  [0xb] = "IN TRANSITION", [0xc] = "IMPLEMENTED/STABLE",
157  [0xd] = "CHANGED", [0xf] = "INTERIM",
158  };
159  const char *ret = ctype < ARRAY_SIZE(ctypes) ? ctypes[ctype] : NULL;
160 
161  return ret ? ret : "?";
162 }
163 
164 static const char *debug_fcp_opcode(unsigned int opcode,
165  const u8 *data, int length)
166 {
167  switch (opcode) {
168  case AVC_OPCODE_VENDOR:
169  break;
171  return avc_debug & AVC_DEBUG_READ_DESCRIPTOR ?
172  "ReadDescriptor" : NULL;
173  case AVC_OPCODE_DSIT:
174  return avc_debug & AVC_DEBUG_DSIT ?
175  "DirectSelectInfo.Type" : NULL;
176  case AVC_OPCODE_DSD:
177  return avc_debug & AVC_DEBUG_DSD ? "DirectSelectData" : NULL;
178  default:
179  return "Unknown";
180  }
181 
182  if (length < 7 ||
183  data[3] != SFE_VENDOR_DE_COMPANYID_0 ||
184  data[4] != SFE_VENDOR_DE_COMPANYID_1 ||
185  data[5] != SFE_VENDOR_DE_COMPANYID_2)
186  return "Vendor/Unknown";
187 
188  switch (data[6]) {
190  return avc_debug & AVC_DEBUG_REGISTER_REMOTE_CONTROL ?
191  "RegisterRC" : NULL;
193  return avc_debug & AVC_DEBUG_LNB_CONTROL ? "LNBControl" : NULL;
195  return avc_debug & AVC_DEBUG_TUNE_QPSK ? "TuneQPSK" : NULL;
197  return avc_debug & AVC_DEBUG_TUNE_QPSK2 ? "TuneQPSK2" : NULL;
199  return avc_debug & AVC_DEBUG_HOST2CA ? "Host2CA" : NULL;
201  return avc_debug & AVC_DEBUG_CA2HOST ? "CA2Host" : NULL;
202  }
203  return "Vendor/Unknown";
204 }
205 
206 static void debug_fcp(const u8 *data, int length)
207 {
208  unsigned int subunit_type, subunit_id, opcode;
209  const char *op, *prefix;
210 
211  prefix = data[0] > 7 ? "FCP <- " : "FCP -> ";
212  subunit_type = data[1] >> 3;
213  subunit_id = data[1] & 7;
214  opcode = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
215  op = debug_fcp_opcode(opcode, data, length);
216 
217  if (op) {
218  printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
219  prefix, subunit_type, subunit_id, length,
220  debug_fcp_ctype(data[0]), op);
221  if (avc_debug & AVC_DEBUG_FCP_PAYLOADS)
222  print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE,
223  16, 1, data, length, false);
224  }
225 }
226 
227 static void debug_pmt(char *msg, int length)
228 {
229  printk(KERN_INFO "APP PMT -> l=%d\n", length);
230  print_hex_dump(KERN_INFO, "APP PMT -> ", DUMP_PREFIX_NONE,
231  16, 1, msg, length, false);
232 }
233 
234 static int avc_write(struct firedtv *fdtv)
235 {
236  int err, retry;
237 
238  fdtv->avc_reply_received = false;
239 
240  for (retry = 0; retry < 6; retry++) {
241  if (unlikely(avc_debug))
242  debug_fcp(fdtv->avc_data, fdtv->avc_data_length);
243 
244  err = fdtv_write(fdtv, FCP_COMMAND_REGISTER,
245  fdtv->avc_data, fdtv->avc_data_length);
246  if (err) {
247  dev_err(fdtv->device, "FCP command write failed\n");
248 
249  return err;
250  }
251 
252  /*
253  * AV/C specs say that answers should be sent within 150 ms.
254  * Time out after 200 ms.
255  */
256  if (wait_event_timeout(fdtv->avc_wait,
257  fdtv->avc_reply_received,
258  msecs_to_jiffies(200)) != 0)
259  return 0;
260  }
261  dev_err(fdtv->device, "FCP response timed out\n");
262 
263  return -ETIMEDOUT;
264 }
265 
266 static bool is_register_rc(struct avc_response_frame *r)
267 {
268  return r->opcode == AVC_OPCODE_VENDOR &&
273 }
274 
275 int avc_recv(struct firedtv *fdtv, void *data, size_t length)
276 {
277  struct avc_response_frame *r = data;
278 
279  if (unlikely(avc_debug))
280  debug_fcp(data, length);
281 
282  if (length >= 8 && is_register_rc(r)) {
283  switch (r->response) {
285  fdtv_handle_rc(fdtv, r->operand[4] << 8 | r->operand[5]);
287  break;
289  if (is_register_rc((void *)fdtv->avc_data))
290  goto wake;
291  break;
292  default:
293  dev_info(fdtv->device,
294  "remote control result = %d\n", r->response);
295  }
296  return 0;
297  }
298 
299  if (fdtv->avc_reply_received) {
300  dev_err(fdtv->device, "out-of-order AVC response, ignored\n");
301  return -EIO;
302  }
303 
304  memcpy(fdtv->avc_data, data, length);
305  fdtv->avc_data_length = length;
306 wake:
307  fdtv->avc_reply_received = true;
308  wake_up(&fdtv->avc_wait);
309 
310  return 0;
311 }
312 
313 static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
314 {
315  int i, n, pos = 1;
316 
317  for (i = 0, n = 0; i < 16; i++) {
318  if (test_bit(i, &fdtv->channel_active)) {
319  operand[pos++] = 0x13; /* flowfunction relay */
320  operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
321  operand[pos++] = (fdtv->channel_pid[i] >> 8) & 0x1f;
322  operand[pos++] = fdtv->channel_pid[i] & 0xff;
323  operand[pos++] = 0x00; /* tableID */
324  operand[pos++] = 0x00; /* filter_length */
325  n++;
326  }
327  }
328  operand[0] = n;
329 
330  return pos;
331 }
332 
333 /*
334  * tuning command for setting the relative LNB frequency
335  * (not supported by the AVC standard)
336  */
337 static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
338  struct dtv_frontend_properties *p)
339 {
340  struct avc_command_frame *c = (void *)fdtv->avc_data;
341 
343 
347  if (fdtv->type == FIREDTV_DVB_S2)
349  else
351 
352  c->operand[4] = (p->frequency >> 24) & 0xff;
353  c->operand[5] = (p->frequency >> 16) & 0xff;
354  c->operand[6] = (p->frequency >> 8) & 0xff;
355  c->operand[7] = p->frequency & 0xff;
356 
357  c->operand[8] = ((p->symbol_rate / 1000) >> 8) & 0xff;
358  c->operand[9] = (p->symbol_rate / 1000) & 0xff;
359 
360  switch (p->fec_inner) {
361  case FEC_1_2: c->operand[10] = 0x1; break;
362  case FEC_2_3: c->operand[10] = 0x2; break;
363  case FEC_3_4: c->operand[10] = 0x3; break;
364  case FEC_5_6: c->operand[10] = 0x4; break;
365  case FEC_7_8: c->operand[10] = 0x5; break;
366  case FEC_4_5:
367  case FEC_8_9:
368  case FEC_AUTO:
369  default: c->operand[10] = 0x0;
370  }
371 
372  if (fdtv->voltage == 0xff)
373  c->operand[11] = 0xff;
374  else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */
375  c->operand[11] = 0;
376  else
377  c->operand[11] = 1;
378 
379  if (fdtv->tone == 0xff)
380  c->operand[12] = 0xff;
381  else if (fdtv->tone == SEC_TONE_ON) /* band */
382  c->operand[12] = 1;
383  else
384  c->operand[12] = 0;
385 
386  if (fdtv->type == FIREDTV_DVB_S2) {
387  if (fdtv->fe.dtv_property_cache.delivery_system == SYS_DVBS2) {
388  switch (fdtv->fe.dtv_property_cache.modulation) {
389  case QAM_16: c->operand[13] = 0x1; break;
390  case QPSK: c->operand[13] = 0x2; break;
391  case PSK_8: c->operand[13] = 0x3; break;
392  default: c->operand[13] = 0x2; break;
393  }
394  switch (fdtv->fe.dtv_property_cache.rolloff) {
395  case ROLLOFF_35: c->operand[14] = 0x2; break;
396  case ROLLOFF_20: c->operand[14] = 0x0; break;
397  case ROLLOFF_25: c->operand[14] = 0x1; break;
398  case ROLLOFF_AUTO:
399  default: c->operand[14] = 0x2; break;
400  /* case ROLLOFF_NONE: c->operand[14] = 0xff; break; */
401  }
402  switch (fdtv->fe.dtv_property_cache.pilot) {
403  case PILOT_AUTO: c->operand[15] = 0x0; break;
404  case PILOT_OFF: c->operand[15] = 0x0; break;
405  case PILOT_ON: c->operand[15] = 0x1; break;
406  }
407  } else {
408  c->operand[13] = 0x1; /* auto modulation */
409  c->operand[14] = 0xff; /* disable rolloff */
410  c->operand[15] = 0xff; /* disable pilot */
411  }
412  return 16;
413  } else {
414  return 13;
415  }
416 }
417 
418 static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
419  struct dtv_frontend_properties *p)
420 {
421  struct avc_command_frame *c = (void *)fdtv->avc_data;
422 
423  c->opcode = AVC_OPCODE_DSD;
424 
425  c->operand[0] = 0; /* source plug */
426  c->operand[1] = 0xd2; /* subfunction replace */
427  c->operand[2] = 0x20; /* system id = DVB */
428  c->operand[3] = 0x00; /* antenna number */
429  c->operand[4] = 0x11; /* system_specific_multiplex selection_length */
430 
431  /* multiplex_valid_flags, high byte */
432  c->operand[5] = 0 << 7 /* reserved */
433  | 0 << 6 /* Polarisation */
434  | 0 << 5 /* Orbital_Pos */
435  | 1 << 4 /* Frequency */
436  | 1 << 3 /* Symbol_Rate */
437  | 0 << 2 /* FEC_outer */
438  | (p->fec_inner != FEC_AUTO ? 1 << 1 : 0)
439  | (p->modulation != QAM_AUTO ? 1 << 0 : 0);
440 
441  /* multiplex_valid_flags, low byte */
442  c->operand[6] = 0 << 7 /* NetworkID */
443  | 0 << 0 /* reserved */ ;
444 
445  c->operand[7] = 0x00;
446  c->operand[8] = 0x00;
447  c->operand[9] = 0x00;
448  c->operand[10] = 0x00;
449 
450  c->operand[11] = (((p->frequency / 4000) >> 16) & 0xff) | (2 << 6);
451  c->operand[12] = ((p->frequency / 4000) >> 8) & 0xff;
452  c->operand[13] = (p->frequency / 4000) & 0xff;
453  c->operand[14] = ((p->symbol_rate / 1000) >> 12) & 0xff;
454  c->operand[15] = ((p->symbol_rate / 1000) >> 4) & 0xff;
455  c->operand[16] = ((p->symbol_rate / 1000) << 4) & 0xf0;
456  c->operand[17] = 0x00;
457 
458  switch (p->fec_inner) {
459  case FEC_1_2: c->operand[18] = 0x1; break;
460  case FEC_2_3: c->operand[18] = 0x2; break;
461  case FEC_3_4: c->operand[18] = 0x3; break;
462  case FEC_5_6: c->operand[18] = 0x4; break;
463  case FEC_7_8: c->operand[18] = 0x5; break;
464  case FEC_8_9: c->operand[18] = 0x6; break;
465  case FEC_4_5: c->operand[18] = 0x8; break;
466  case FEC_AUTO:
467  default: c->operand[18] = 0x0;
468  }
469 
470  switch (p->modulation) {
471  case QAM_16: c->operand[19] = 0x08; break;
472  case QAM_32: c->operand[19] = 0x10; break;
473  case QAM_64: c->operand[19] = 0x18; break;
474  case QAM_128: c->operand[19] = 0x20; break;
475  case QAM_256: c->operand[19] = 0x28; break;
476  case QAM_AUTO:
477  default: c->operand[19] = 0x00;
478  }
479 
480  c->operand[20] = 0x00;
481  c->operand[21] = 0x00;
482 
483  return 22 + add_pid_filter(fdtv, &c->operand[22]);
484 }
485 
486 static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
487  struct dtv_frontend_properties *p)
488 {
489  struct avc_command_frame *c = (void *)fdtv->avc_data;
490 
491  c->opcode = AVC_OPCODE_DSD;
492 
493  c->operand[0] = 0; /* source plug */
494  c->operand[1] = 0xd2; /* subfunction replace */
495  c->operand[2] = 0x20; /* system id = DVB */
496  c->operand[3] = 0x00; /* antenna number */
497  c->operand[4] = 0x0c; /* system_specific_multiplex selection_length */
498 
499  /* multiplex_valid_flags, high byte */
500  c->operand[5] =
501  0 << 7 /* reserved */
502  | 1 << 6 /* CenterFrequency */
503  | (p->bandwidth_hz != 0 ? 1 << 5 : 0)
504  | (p->modulation != QAM_AUTO ? 1 << 4 : 0)
505  | (p->hierarchy != HIERARCHY_AUTO ? 1 << 3 : 0)
506  | (p->code_rate_HP != FEC_AUTO ? 1 << 2 : 0)
507  | (p->code_rate_LP != FEC_AUTO ? 1 << 1 : 0)
508  | (p->guard_interval != GUARD_INTERVAL_AUTO ? 1 << 0 : 0);
509 
510  /* multiplex_valid_flags, low byte */
511  c->operand[6] =
512  0 << 7 /* NetworkID */
513  | (p->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
514  | 0 << 5 /* OtherFrequencyFlag */
515  | 0 << 0 /* reserved */ ;
516 
517  c->operand[7] = 0x0;
518  c->operand[8] = (p->frequency / 10) >> 24;
519  c->operand[9] = ((p->frequency / 10) >> 16) & 0xff;
520  c->operand[10] = ((p->frequency / 10) >> 8) & 0xff;
521  c->operand[11] = (p->frequency / 10) & 0xff;
522 
523  switch (p->bandwidth_hz) {
524  case 7000000: c->operand[12] = 0x20; break;
525  case 8000000:
526  case 6000000: /* not defined by AVC spec */
527  case 0:
528  default: c->operand[12] = 0x00;
529  }
530 
531  switch (p->modulation) {
532  case QAM_16: c->operand[13] = 1 << 6; break;
533  case QAM_64: c->operand[13] = 2 << 6; break;
534  case QPSK:
535  default: c->operand[13] = 0x00;
536  }
537 
538  switch (p->hierarchy) {
539  case HIERARCHY_1: c->operand[13] |= 1 << 3; break;
540  case HIERARCHY_2: c->operand[13] |= 2 << 3; break;
541  case HIERARCHY_4: c->operand[13] |= 3 << 3; break;
542  case HIERARCHY_AUTO:
543  case HIERARCHY_NONE:
544  default: break;
545  }
546 
547  switch (p->code_rate_HP) {
548  case FEC_2_3: c->operand[13] |= 1; break;
549  case FEC_3_4: c->operand[13] |= 2; break;
550  case FEC_5_6: c->operand[13] |= 3; break;
551  case FEC_7_8: c->operand[13] |= 4; break;
552  case FEC_1_2:
553  default: break;
554  }
555 
556  switch (p->code_rate_LP) {
557  case FEC_2_3: c->operand[14] = 1 << 5; break;
558  case FEC_3_4: c->operand[14] = 2 << 5; break;
559  case FEC_5_6: c->operand[14] = 3 << 5; break;
560  case FEC_7_8: c->operand[14] = 4 << 5; break;
561  case FEC_1_2:
562  default: c->operand[14] = 0x00; break;
563  }
564 
565  switch (p->guard_interval) {
566  case GUARD_INTERVAL_1_16: c->operand[14] |= 1 << 3; break;
567  case GUARD_INTERVAL_1_8: c->operand[14] |= 2 << 3; break;
568  case GUARD_INTERVAL_1_4: c->operand[14] |= 3 << 3; break;
569  case GUARD_INTERVAL_1_32:
570  case GUARD_INTERVAL_AUTO:
571  default: break;
572  }
573 
574  switch (p->transmission_mode) {
575  case TRANSMISSION_MODE_8K: c->operand[14] |= 1 << 1; break;
578  default: break;
579  }
580 
581  c->operand[15] = 0x00; /* network_ID[0] */
582  c->operand[16] = 0x00; /* network_ID[1] */
583 
584  return 17 + add_pid_filter(fdtv, &c->operand[17]);
585 }
586 
587 int avc_tuner_dsd(struct firedtv *fdtv,
588  struct dtv_frontend_properties *p)
589 {
590  struct avc_command_frame *c = (void *)fdtv->avc_data;
591  int pos, ret;
592 
593  mutex_lock(&fdtv->avc_mutex);
594 
597 
598  switch (fdtv->type) {
599  case FIREDTV_DVB_S:
600  case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, p); break;
601  case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, p); break;
602  case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, p); break;
603  default:
604  BUG();
605  }
606  pad_operands(c, pos);
607 
608  fdtv->avc_data_length = ALIGN(3 + pos, 4);
609  ret = avc_write(fdtv);
610 #if 0
611  /*
612  * FIXME:
613  * u8 *status was an out-parameter of avc_tuner_dsd, unused by caller.
614  * Check for AVC_RESPONSE_ACCEPTED here instead?
615  */
616  if (status)
617  *status = r->operand[2];
618 #endif
619  mutex_unlock(&fdtv->avc_mutex);
620 
621  if (ret == 0)
622  msleep(500);
623 
624  return ret;
625 }
626 
627 int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
628 {
629  struct avc_command_frame *c = (void *)fdtv->avc_data;
630  int ret, pos, k;
631 
632  if (pidc > 16 && pidc != 0xff)
633  return -EINVAL;
634 
635  mutex_lock(&fdtv->avc_mutex);
636 
639  c->opcode = AVC_OPCODE_DSD;
640 
641  c->operand[0] = 0; /* source plug */
642  c->operand[1] = 0xd2; /* subfunction replace */
643  c->operand[2] = 0x20; /* system id = DVB */
644  c->operand[3] = 0x00; /* antenna number */
645  c->operand[4] = 0x00; /* system_specific_multiplex selection_length */
646  c->operand[5] = pidc; /* Nr_of_dsd_sel_specs */
647 
648  pos = 6;
649  if (pidc != 0xff)
650  for (k = 0; k < pidc; k++) {
651  c->operand[pos++] = 0x13; /* flowfunction relay */
652  c->operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
653  c->operand[pos++] = (pid[k] >> 8) & 0x1f;
654  c->operand[pos++] = pid[k] & 0xff;
655  c->operand[pos++] = 0x00; /* tableID */
656  c->operand[pos++] = 0x00; /* filter_length */
657  }
658  pad_operands(c, pos);
659 
660  fdtv->avc_data_length = ALIGN(3 + pos, 4);
661  ret = avc_write(fdtv);
662 
663  /* FIXME: check response code? */
664 
665  mutex_unlock(&fdtv->avc_mutex);
666 
667  if (ret == 0)
668  msleep(50);
669 
670  return ret;
671 }
672 
673 int avc_tuner_get_ts(struct firedtv *fdtv)
674 {
675  struct avc_command_frame *c = (void *)fdtv->avc_data;
676  int ret, sl;
677 
678  mutex_lock(&fdtv->avc_mutex);
679 
682  c->opcode = AVC_OPCODE_DSIT;
683 
684  sl = fdtv->type == FIREDTV_DVB_T ? 0x0c : 0x11;
685 
686  c->operand[0] = 0; /* source plug */
687  c->operand[1] = 0xd2; /* subfunction replace */
688  c->operand[2] = 0xff; /* status */
689  c->operand[3] = 0x20; /* system id = DVB */
690  c->operand[4] = 0x00; /* antenna number */
691  c->operand[5] = 0x0; /* system_specific_search_flags */
692  c->operand[6] = sl; /* system_specific_multiplex selection_length */
693  /*
694  * operand[7]: valid_flags[0]
695  * operand[8]: valid_flags[1]
696  * operand[7 + sl]: nr_of_dsit_sel_specs (always 0)
697  */
698  clear_operands(c, 7, 24);
699 
700  fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
701  ret = avc_write(fdtv);
702 
703  /* FIXME: check response code? */
704 
705  mutex_unlock(&fdtv->avc_mutex);
706 
707  if (ret == 0)
708  msleep(250);
709 
710  return ret;
711 }
712 
713 int avc_identify_subunit(struct firedtv *fdtv)
714 {
715  struct avc_command_frame *c = (void *)fdtv->avc_data;
716  struct avc_response_frame *r = (void *)fdtv->avc_data;
717  int ret;
718 
719  mutex_lock(&fdtv->avc_mutex);
720 
724 
726  c->operand[1] = 0xff;
727  c->operand[2] = 0x00;
728  c->operand[3] = 0x00; /* length highbyte */
729  c->operand[4] = 0x08; /* length lowbyte */
730  c->operand[5] = 0x00; /* offset highbyte */
731  c->operand[6] = 0x0d; /* offset lowbyte */
732  clear_operands(c, 7, 8); /* padding */
733 
734  fdtv->avc_data_length = 12;
735  ret = avc_write(fdtv);
736  if (ret < 0)
737  goto out;
738 
739  if ((r->response != AVC_RESPONSE_STABLE &&
740  r->response != AVC_RESPONSE_ACCEPTED) ||
741  (r->operand[3] << 8) + r->operand[4] != 8) {
742  dev_err(fdtv->device, "cannot read subunit identifier\n");
743  ret = -EINVAL;
744  }
745 out:
746  mutex_unlock(&fdtv->avc_mutex);
747 
748  return ret;
749 }
750 
751 #define SIZEOF_ANTENNA_INPUT_INFO 22
752 
754 {
755  struct avc_command_frame *c = (void *)fdtv->avc_data;
756  struct avc_response_frame *r = (void *)fdtv->avc_data;
757  int length, ret;
758 
759  mutex_lock(&fdtv->avc_mutex);
760 
764 
766  c->operand[1] = 0xff; /* read_result_status */
767  /*
768  * operand[2]: reserved
769  * operand[3]: SIZEOF_ANTENNA_INPUT_INFO >> 8
770  * operand[4]: SIZEOF_ANTENNA_INPUT_INFO & 0xff
771  */
772  clear_operands(c, 2, 31);
773 
774  fdtv->avc_data_length = 12;
775  ret = avc_write(fdtv);
776  if (ret < 0)
777  goto out;
778 
779  if (r->response != AVC_RESPONSE_STABLE &&
780  r->response != AVC_RESPONSE_ACCEPTED) {
781  dev_err(fdtv->device, "cannot read tuner status\n");
782  ret = -EINVAL;
783  goto out;
784  }
785 
786  length = r->operand[9];
787  if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
788  dev_err(fdtv->device, "got invalid tuner status\n");
789  ret = -EINVAL;
790  goto out;
791  }
792 
793  stat->active_system = r->operand[10];
794  stat->searching = r->operand[11] >> 7 & 1;
795  stat->moving = r->operand[11] >> 6 & 1;
796  stat->no_rf = r->operand[11] >> 5 & 1;
797  stat->input = r->operand[12] >> 7 & 1;
798  stat->selected_antenna = r->operand[12] & 0x7f;
799  stat->ber = r->operand[13] << 24 |
800  r->operand[14] << 16 |
801  r->operand[15] << 8 |
802  r->operand[16];
803  stat->signal_strength = r->operand[17];
804  stat->raster_frequency = r->operand[18] >> 6 & 2;
805  stat->rf_frequency = (r->operand[18] & 0x3f) << 16 |
806  r->operand[19] << 8 |
807  r->operand[20];
808  stat->man_dep_info_length = r->operand[21];
809  stat->front_end_error = r->operand[22] >> 4 & 1;
810  stat->antenna_error = r->operand[22] >> 3 & 1;
811  stat->front_end_power_status = r->operand[22] >> 1 & 1;
812  stat->power_supply = r->operand[22] & 1;
813  stat->carrier_noise_ratio = r->operand[23] << 8 |
814  r->operand[24];
815  stat->power_supply_voltage = r->operand[27];
816  stat->antenna_voltage = r->operand[28];
817  stat->firewire_bus_voltage = r->operand[29];
818  stat->ca_mmi = r->operand[30] & 1;
819  stat->ca_pmt_reply = r->operand[31] >> 7 & 1;
820  stat->ca_date_time_request = r->operand[31] >> 6 & 1;
821  stat->ca_application_info = r->operand[31] >> 5 & 1;
822  stat->ca_module_present_status = r->operand[31] >> 4 & 1;
823  stat->ca_dvb_flag = r->operand[31] >> 3 & 1;
824  stat->ca_error_flag = r->operand[31] >> 2 & 1;
825  stat->ca_initialization_status = r->operand[31] >> 1 & 1;
826 out:
827  mutex_unlock(&fdtv->avc_mutex);
828 
829  return ret;
830 }
831 
832 int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
833  char conttone, char nrdiseq,
834  struct dvb_diseqc_master_cmd *diseqcmd)
835 {
836  struct avc_command_frame *c = (void *)fdtv->avc_data;
837  struct avc_response_frame *r = (void *)fdtv->avc_data;
838  int pos, j, k, ret;
839 
840  mutex_lock(&fdtv->avc_mutex);
841 
845 
850  c->operand[4] = voltage;
851  c->operand[5] = nrdiseq;
852 
853  pos = 6;
854  for (j = 0; j < nrdiseq; j++) {
855  c->operand[pos++] = diseqcmd[j].msg_len;
856 
857  for (k = 0; k < diseqcmd[j].msg_len; k++)
858  c->operand[pos++] = diseqcmd[j].msg[k];
859  }
860  c->operand[pos++] = burst;
861  c->operand[pos++] = conttone;
862  pad_operands(c, pos);
863 
864  fdtv->avc_data_length = ALIGN(3 + pos, 4);
865  ret = avc_write(fdtv);
866  if (ret < 0)
867  goto out;
868 
869  if (r->response != AVC_RESPONSE_ACCEPTED) {
870  dev_err(fdtv->device, "LNB control failed\n");
871  ret = -EINVAL;
872  }
873 out:
874  mutex_unlock(&fdtv->avc_mutex);
875 
876  return ret;
877 }
878 
880 {
881  struct avc_command_frame *c = (void *)fdtv->avc_data;
882  int ret;
883 
884  mutex_lock(&fdtv->avc_mutex);
885 
886  c->ctype = AVC_CTYPE_NOTIFY;
889 
894  c->operand[4] = 0; /* padding */
895 
896  fdtv->avc_data_length = 8;
897  ret = avc_write(fdtv);
898 
899  /* FIXME: check response code? */
900 
901  mutex_unlock(&fdtv->avc_mutex);
902 
903  return ret;
904 }
905 
907 {
908  struct firedtv *fdtv =
909  container_of(work, struct firedtv, remote_ctrl_work);
910 
911  /* Should it be rescheduled in failure cases? */
913 }
914 
915 #if 0 /* FIXME: unused */
916 int avc_tuner_host2ca(struct firedtv *fdtv)
917 {
918  struct avc_command_frame *c = (void *)fdtv->avc_data;
919  int ret;
920 
921  mutex_lock(&fdtv->avc_mutex);
922 
926 
931  c->operand[4] = 0; /* slot */
932  c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
933  clear_operands(c, 6, 8);
934 
935  fdtv->avc_data_length = 12;
936  ret = avc_write(fdtv);
937 
938  /* FIXME: check response code? */
939 
940  mutex_unlock(&fdtv->avc_mutex);
941 
942  return ret;
943 }
944 #endif
945 
946 static int get_ca_object_pos(struct avc_response_frame *r)
947 {
948  int length = 1;
949 
950  /* Check length of length field */
951  if (r->operand[7] & 0x80)
952  length = (r->operand[7] & 0x7f) + 1;
953  return length + 7;
954 }
955 
956 static int get_ca_object_length(struct avc_response_frame *r)
957 {
958 #if 0 /* FIXME: unused */
959  int size = 0;
960  int i;
961 
962  if (r->operand[7] & 0x80)
963  for (i = 0; i < (r->operand[7] & 0x7f); i++) {
964  size <<= 8;
965  size += r->operand[8 + i];
966  }
967 #endif
968  return r->operand[7];
969 }
970 
971 int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
972 {
973  struct avc_command_frame *c = (void *)fdtv->avc_data;
974  struct avc_response_frame *r = (void *)fdtv->avc_data;
975  int pos, ret;
976 
977  mutex_lock(&fdtv->avc_mutex);
978 
979  c->ctype = AVC_CTYPE_STATUS;
982 
987  c->operand[4] = 0; /* slot */
988  c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
989  clear_operands(c, 6, LAST_OPERAND);
990 
991  fdtv->avc_data_length = 12;
992  ret = avc_write(fdtv);
993  if (ret < 0)
994  goto out;
995 
996  /* FIXME: check response code and validate response data */
997 
998  pos = get_ca_object_pos(r);
999  app_info[0] = (EN50221_TAG_APP_INFO >> 16) & 0xff;
1000  app_info[1] = (EN50221_TAG_APP_INFO >> 8) & 0xff;
1001  app_info[2] = (EN50221_TAG_APP_INFO >> 0) & 0xff;
1002  app_info[3] = 6 + r->operand[pos + 4];
1003  app_info[4] = 0x01;
1004  memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
1005  *len = app_info[3] + 4;
1006 out:
1007  mutex_unlock(&fdtv->avc_mutex);
1008 
1009  return ret;
1010 }
1011 
1012 int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
1013 {
1014  struct avc_command_frame *c = (void *)fdtv->avc_data;
1015  struct avc_response_frame *r = (void *)fdtv->avc_data;
1016  int i, pos, ret;
1017 
1018  mutex_lock(&fdtv->avc_mutex);
1019 
1020  c->ctype = AVC_CTYPE_STATUS;
1021  c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1023 
1028  c->operand[4] = 0; /* slot */
1029  c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
1030  clear_operands(c, 6, LAST_OPERAND);
1031 
1032  fdtv->avc_data_length = 12;
1033  ret = avc_write(fdtv);
1034  if (ret < 0)
1035  goto out;
1036 
1037  /* FIXME: check response code and validate response data */
1038 
1039  pos = get_ca_object_pos(r);
1040  app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
1041  app_info[1] = (EN50221_TAG_CA_INFO >> 8) & 0xff;
1042  app_info[2] = (EN50221_TAG_CA_INFO >> 0) & 0xff;
1043  if (num_fake_ca_system_ids == 0) {
1044  app_info[3] = 2;
1045  app_info[4] = r->operand[pos + 0];
1046  app_info[5] = r->operand[pos + 1];
1047  } else {
1048  app_info[3] = num_fake_ca_system_ids * 2;
1049  for (i = 0; i < num_fake_ca_system_ids; i++) {
1050  app_info[4 + i * 2] =
1051  (fake_ca_system_ids[i] >> 8) & 0xff;
1052  app_info[5 + i * 2] = fake_ca_system_ids[i] & 0xff;
1053  }
1054  }
1055  *len = app_info[3] + 4;
1056 out:
1057  mutex_unlock(&fdtv->avc_mutex);
1058 
1059  return ret;
1060 }
1061 
1062 int avc_ca_reset(struct firedtv *fdtv)
1063 {
1064  struct avc_command_frame *c = (void *)fdtv->avc_data;
1065  int ret;
1066 
1067  mutex_lock(&fdtv->avc_mutex);
1068 
1069  c->ctype = AVC_CTYPE_CONTROL;
1070  c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1072 
1077  c->operand[4] = 0; /* slot */
1078  c->operand[5] = SFE_VENDOR_TAG_CA_RESET; /* ca tag */
1079  c->operand[6] = 0; /* more/last */
1080  c->operand[7] = 1; /* length */
1081  c->operand[8] = 0; /* force hardware reset */
1082 
1083  fdtv->avc_data_length = 12;
1084  ret = avc_write(fdtv);
1085 
1086  /* FIXME: check response code? */
1087 
1088  mutex_unlock(&fdtv->avc_mutex);
1089 
1090  return ret;
1091 }
1092 
1093 int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
1094 {
1095  struct avc_command_frame *c = (void *)fdtv->avc_data;
1096  struct avc_response_frame *r = (void *)fdtv->avc_data;
1097  int list_management;
1098  int program_info_length;
1099  int pmt_cmd_id;
1100  int read_pos;
1101  int write_pos;
1102  int es_info_length;
1103  int crc32_csum;
1104  int ret;
1105 
1106  if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT))
1107  debug_pmt(msg, length);
1108 
1109  mutex_lock(&fdtv->avc_mutex);
1110 
1111  c->ctype = AVC_CTYPE_CONTROL;
1112  c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1114 
1115  if (msg[0] != EN50221_LIST_MANAGEMENT_ONLY) {
1116  dev_info(fdtv->device, "forcing list_management to ONLY\n");
1118  }
1119  /* We take the cmd_id from the programme level only! */
1120  list_management = msg[0];
1121  program_info_length = ((msg[4] & 0x0f) << 8) + msg[5];
1122  if (program_info_length > 0)
1123  program_info_length--; /* Remove pmt_cmd_id */
1124  pmt_cmd_id = msg[6];
1125 
1130  c->operand[4] = 0; /* slot */
1131  c->operand[5] = SFE_VENDOR_TAG_CA_PMT; /* ca tag */
1132  c->operand[6] = 0; /* more/last */
1133  /* Use three bytes for length field in case length > 127 */
1134  c->operand[10] = list_management;
1135  c->operand[11] = 0x01; /* pmt_cmd=OK_descramble */
1136 
1137  /* TS program map table */
1138 
1139  c->operand[12] = 0x02; /* Table id=2 */
1140  c->operand[13] = 0x80; /* Section syntax + length */
1141 
1142  c->operand[15] = msg[1]; /* Program number */
1143  c->operand[16] = msg[2];
1144  c->operand[17] = msg[3]; /* Version number and current/next */
1145  c->operand[18] = 0x00; /* Section number=0 */
1146  c->operand[19] = 0x00; /* Last section number=0 */
1147  c->operand[20] = 0x1f; /* PCR_PID=1FFF */
1148  c->operand[21] = 0xff;
1149  c->operand[22] = (program_info_length >> 8); /* Program info length */
1150  c->operand[23] = (program_info_length & 0xff);
1151 
1152  /* CA descriptors at programme level */
1153  read_pos = 6;
1154  write_pos = 24;
1155  if (program_info_length > 0) {
1156  pmt_cmd_id = msg[read_pos++];
1157  if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
1158  dev_err(fdtv->device,
1159  "invalid pmt_cmd_id %d\n", pmt_cmd_id);
1160 
1161  memcpy(&c->operand[write_pos], &msg[read_pos],
1162  program_info_length);
1163  read_pos += program_info_length;
1164  write_pos += program_info_length;
1165  }
1166  while (read_pos < length) {
1167  c->operand[write_pos++] = msg[read_pos++];
1168  c->operand[write_pos++] = msg[read_pos++];
1169  c->operand[write_pos++] = msg[read_pos++];
1170  es_info_length =
1171  ((msg[read_pos] & 0x0f) << 8) + msg[read_pos + 1];
1172  read_pos += 2;
1173  if (es_info_length > 0)
1174  es_info_length--; /* Remove pmt_cmd_id */
1175  c->operand[write_pos++] = es_info_length >> 8;
1176  c->operand[write_pos++] = es_info_length & 0xff;
1177  if (es_info_length > 0) {
1178  pmt_cmd_id = msg[read_pos++];
1179  if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
1180  dev_err(fdtv->device, "invalid pmt_cmd_id %d "
1181  "at stream level\n", pmt_cmd_id);
1182 
1183  memcpy(&c->operand[write_pos], &msg[read_pos],
1184  es_info_length);
1185  read_pos += es_info_length;
1186  write_pos += es_info_length;
1187  }
1188  }
1189  write_pos += 4; /* CRC */
1190 
1191  c->operand[7] = 0x82;
1192  c->operand[8] = (write_pos - 10) >> 8;
1193  c->operand[9] = (write_pos - 10) & 0xff;
1194  c->operand[14] = write_pos - 15;
1195 
1196  crc32_csum = crc32_be(0, &c->operand[10], c->operand[12] - 1);
1197  c->operand[write_pos - 4] = (crc32_csum >> 24) & 0xff;
1198  c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
1199  c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff;
1200  c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff;
1201  pad_operands(c, write_pos);
1202 
1203  fdtv->avc_data_length = ALIGN(3 + write_pos, 4);
1204  ret = avc_write(fdtv);
1205  if (ret < 0)
1206  goto out;
1207 
1208  if (r->response != AVC_RESPONSE_ACCEPTED) {
1209  dev_err(fdtv->device,
1210  "CA PMT failed with response 0x%x\n", r->response);
1211  ret = -EACCES;
1212  }
1213 out:
1214  mutex_unlock(&fdtv->avc_mutex);
1215 
1216  return ret;
1217 }
1218 
1219 int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
1220 {
1221  struct avc_command_frame *c = (void *)fdtv->avc_data;
1222  struct avc_response_frame *r = (void *)fdtv->avc_data;
1223  int ret;
1224 
1225  mutex_lock(&fdtv->avc_mutex);
1226 
1227  c->ctype = AVC_CTYPE_STATUS;
1228  c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1230 
1235  c->operand[4] = 0; /* slot */
1236  c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
1237  clear_operands(c, 6, LAST_OPERAND);
1238 
1239  fdtv->avc_data_length = 12;
1240  ret = avc_write(fdtv);
1241  if (ret < 0)
1242  goto out;
1243 
1244  /* FIXME: check response code and validate response data */
1245 
1246  *interval = r->operand[get_ca_object_pos(r)];
1247 out:
1248  mutex_unlock(&fdtv->avc_mutex);
1249 
1250  return ret;
1251 }
1252 
1253 int avc_ca_enter_menu(struct firedtv *fdtv)
1254 {
1255  struct avc_command_frame *c = (void *)fdtv->avc_data;
1256  int ret;
1257 
1258  mutex_lock(&fdtv->avc_mutex);
1259 
1260  c->ctype = AVC_CTYPE_STATUS;
1261  c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1263 
1268  c->operand[4] = 0; /* slot */
1270  clear_operands(c, 6, 8);
1271 
1272  fdtv->avc_data_length = 12;
1273  ret = avc_write(fdtv);
1274 
1275  /* FIXME: check response code? */
1276 
1277  mutex_unlock(&fdtv->avc_mutex);
1278 
1279  return ret;
1280 }
1281 
1282 int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
1283 {
1284  struct avc_command_frame *c = (void *)fdtv->avc_data;
1285  struct avc_response_frame *r = (void *)fdtv->avc_data;
1286  int ret;
1287 
1288  mutex_lock(&fdtv->avc_mutex);
1289 
1290  c->ctype = AVC_CTYPE_STATUS;
1291  c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1293 
1298  c->operand[4] = 0; /* slot */
1300  clear_operands(c, 6, LAST_OPERAND);
1301 
1302  fdtv->avc_data_length = 12;
1303  ret = avc_write(fdtv);
1304  if (ret < 0)
1305  goto out;
1306 
1307  /* FIXME: check response code and validate response data */
1308 
1309  *len = get_ca_object_length(r);
1310  memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
1311 out:
1312  mutex_unlock(&fdtv->avc_mutex);
1313 
1314  return ret;
1315 }
1316 
1317 #define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL
1318 
1319 static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
1320 {
1321  int ret;
1322 
1323  ret = fdtv_read(fdtv, addr, data);
1324  if (ret < 0)
1325  dev_err(fdtv->device, "CMP: read I/O error\n");
1326 
1327  return ret;
1328 }
1329 
1330 static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
1331 {
1332  int ret;
1333 
1334  ret = fdtv_lock(fdtv, addr, data);
1335  if (ret < 0)
1336  dev_err(fdtv->device, "CMP: lock I/O error\n");
1337 
1338  return ret;
1339 }
1340 
1341 static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
1342 {
1343  return (be32_to_cpu(opcr) >> shift) & mask;
1344 }
1345 
1346 static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
1347 {
1348  *opcr &= ~cpu_to_be32(mask << shift);
1349  *opcr |= cpu_to_be32((value & mask) << shift);
1350 }
1351 
1352 #define get_opcr_online(v) get_opcr((v), 0x1, 31)
1353 #define get_opcr_p2p_connections(v) get_opcr((v), 0x3f, 24)
1354 #define get_opcr_channel(v) get_opcr((v), 0x3f, 16)
1355 
1356 #define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24)
1357 #define set_opcr_channel(p, v) set_opcr((p), (v), 0x3f, 16)
1358 #define set_opcr_data_rate(p, v) set_opcr((p), (v), 0x3, 14)
1359 #define set_opcr_overhead_id(p, v) set_opcr((p), (v), 0xf, 10)
1360 
1361 int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
1362 {
1363  __be32 old_opcr, opcr[2];
1364  u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
1365  int attempts = 0;
1366  int ret;
1367 
1368  ret = cmp_read(fdtv, opcr_address, opcr);
1369  if (ret < 0)
1370  return ret;
1371 
1372 repeat:
1373  if (!get_opcr_online(*opcr)) {
1374  dev_err(fdtv->device, "CMP: output offline\n");
1375  return -EBUSY;
1376  }
1377 
1378  old_opcr = *opcr;
1379 
1380  if (get_opcr_p2p_connections(*opcr)) {
1381  if (get_opcr_channel(*opcr) != channel) {
1382  dev_err(fdtv->device, "CMP: cannot change channel\n");
1383  return -EBUSY;
1384  }
1385  dev_info(fdtv->device, "CMP: overlaying connection\n");
1386 
1387  /* We don't allocate isochronous resources. */
1388  } else {
1389  set_opcr_channel(opcr, channel);
1390  set_opcr_data_rate(opcr, 2); /* S400 */
1391 
1392  /* FIXME: this is for the worst case - optimize */
1393  set_opcr_overhead_id(opcr, 0);
1394 
1395  /* FIXME: allocate isochronous channel and bandwidth at IRM */
1396  }
1397 
1399 
1400  opcr[1] = *opcr;
1401  opcr[0] = old_opcr;
1402 
1403  ret = cmp_lock(fdtv, opcr_address, opcr);
1404  if (ret < 0)
1405  return ret;
1406 
1407  if (old_opcr != *opcr) {
1408  /*
1409  * FIXME: if old_opcr.P2P_Connections > 0,
1410  * deallocate isochronous channel and bandwidth at IRM
1411  */
1412 
1413  if (++attempts < 6) /* arbitrary limit */
1414  goto repeat;
1415  return -EBUSY;
1416  }
1417 
1418  return 0;
1419 }
1420 
1421 void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
1422 {
1423  __be32 old_opcr, opcr[2];
1424  u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
1425  int attempts = 0;
1426 
1427  if (cmp_read(fdtv, opcr_address, opcr) < 0)
1428  return;
1429 
1430 repeat:
1431  if (!get_opcr_online(*opcr) || !get_opcr_p2p_connections(*opcr) ||
1432  get_opcr_channel(*opcr) != channel) {
1433  dev_err(fdtv->device, "CMP: no connection to break\n");
1434  return;
1435  }
1436 
1437  old_opcr = *opcr;
1439 
1440  opcr[1] = *opcr;
1441  opcr[0] = old_opcr;
1442 
1443  if (cmp_lock(fdtv, opcr_address, opcr) < 0)
1444  return;
1445 
1446  if (old_opcr != *opcr) {
1447  /*
1448  * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
1449  * owner, deallocate isochronous channel and bandwidth at IRM
1450  * if (...)
1451  * fdtv->backend->dealloc_resources(fdtv, channel, bw);
1452  */
1453 
1454  if (++attempts < 6) /* arbitrary limit */
1455  goto repeat;
1456  }
1457 }