budget-ci.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197
  1. /*
  2. * budget-ci.c: driver for the SAA7146 based Budget DVB cards
  3. *
  4. * Compiled from various sources by Michael Hunold <michael@mihu.de>
  5. *
  6. * msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM>
  7. * partially based on the Siemens DVB driver by Ralph+Marcus Metzler
  8. *
  9. * CI interface support (c) 2004 Andrew de Quincey <adq_dvb@lidskialf.net>
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License
  13. * as published by the Free Software Foundation; either version 2
  14. * of the License, or (at your option) any later version.
  15. *
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  26. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  27. *
  28. *
  29. * the project's page is at http://www.linuxtv.org/dvb/
  30. */
  31. #include "budget.h"
  32. #include <linux/module.h>
  33. #include <linux/errno.h>
  34. #include <linux/slab.h>
  35. #include <linux/interrupt.h>
  36. #include <linux/input.h>
  37. #include <linux/spinlock.h>
  38. #include "dvb_ca_en50221.h"
  39. #include "stv0299.h"
  40. #include "stv0297.h"
  41. #include "tda1004x.h"
  42. #define DEBIADDR_IR 0x1234
  43. #define DEBIADDR_CICONTROL 0x0000
  44. #define DEBIADDR_CIVERSION 0x4000
  45. #define DEBIADDR_IO 0x1000
  46. #define DEBIADDR_ATTR 0x3000
  47. #define CICONTROL_RESET 0x01
  48. #define CICONTROL_ENABLETS 0x02
  49. #define CICONTROL_CAMDETECT 0x08
  50. #define DEBICICTL 0x00420000
  51. #define DEBICICAM 0x02420000
  52. #define SLOTSTATUS_NONE 1
  53. #define SLOTSTATUS_PRESENT 2
  54. #define SLOTSTATUS_RESET 4
  55. #define SLOTSTATUS_READY 8
  56. #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
  57. struct budget_ci {
  58. struct budget budget;
  59. struct input_dev *input_dev;
  60. struct tasklet_struct msp430_irq_tasklet;
  61. struct tasklet_struct ciintf_irq_tasklet;
  62. int slot_status;
  63. struct dvb_ca_en50221 ca;
  64. char ir_dev_name[50];
  65. u8 tuner_pll_address; /* used for philips_tdm1316l configs */
  66. };
  67. /* from reading the following remotes:
  68. Zenith Universal 7 / TV Mode 807 / VCR Mode 837
  69. Hauppauge (from NOVA-CI-s box product)
  70. i've taken a "middle of the road" approach and note the differences
  71. */
  72. static u16 key_map[64] = {
  73. /* 0x0X */
  74. KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8,
  75. KEY_9,
  76. KEY_ENTER,
  77. KEY_RED,
  78. KEY_POWER, /* RADIO on Hauppauge */
  79. KEY_MUTE,
  80. 0,
  81. KEY_A, /* TV on Hauppauge */
  82. /* 0x1X */
  83. KEY_VOLUMEUP, KEY_VOLUMEDOWN,
  84. 0, 0,
  85. KEY_B,
  86. 0, 0, 0, 0, 0, 0, 0,
  87. KEY_UP, KEY_DOWN,
  88. KEY_OPTION, /* RESERVED on Hauppauge */
  89. KEY_BREAK,
  90. /* 0x2X */
  91. KEY_CHANNELUP, KEY_CHANNELDOWN,
  92. KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */
  93. 0, KEY_RESTART, KEY_OK,
  94. KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */
  95. 0,
  96. KEY_ENTER, /* VCR mode on Zenith */
  97. KEY_PAUSE,
  98. 0,
  99. KEY_RIGHT, KEY_LEFT,
  100. 0,
  101. KEY_MENU, /* FULL SCREEN on Hauppauge */
  102. 0,
  103. /* 0x3X */
  104. KEY_SLOW,
  105. KEY_PREVIOUS, /* VCR mode on Zenith */
  106. KEY_REWIND,
  107. 0,
  108. KEY_FASTFORWARD,
  109. KEY_PLAY, KEY_STOP,
  110. KEY_RECORD,
  111. KEY_TUNER, /* TV/VCR on Zenith */
  112. 0,
  113. KEY_C,
  114. 0,
  115. KEY_EXIT,
  116. KEY_POWER2,
  117. KEY_TUNER, /* VCR mode on Zenith */
  118. 0,
  119. };
  120. static void msp430_ir_debounce(unsigned long data)
  121. {
  122. struct input_dev *dev = (struct input_dev *) data;
  123. if (dev->rep[0] == 0 || dev->rep[0] == ~0) {
  124. input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
  125. return;
  126. }
  127. dev->rep[0] = 0;
  128. dev->timer.expires = jiffies + HZ * 350 / 1000;
  129. add_timer(&dev->timer);
  130. input_event(dev, EV_KEY, key_map[dev->repeat_key], 2); /* REPEAT */
  131. }
  132. static void msp430_ir_interrupt(unsigned long data)
  133. {
  134. struct budget_ci *budget_ci = (struct budget_ci *) data;
  135. struct input_dev *dev = budget_ci->input_dev;
  136. unsigned int code =
  137. ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
  138. if (code & 0x40) {
  139. code &= 0x3f;
  140. if (timer_pending(&dev->timer)) {
  141. if (code == dev->repeat_key) {
  142. ++dev->rep[0];
  143. return;
  144. }
  145. del_timer(&dev->timer);
  146. input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
  147. }
  148. if (!key_map[code]) {
  149. printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
  150. return;
  151. }
  152. /* initialize debounce and repeat */
  153. dev->repeat_key = code;
  154. /* Zenith remote _always_ sends 2 sequences */
  155. dev->rep[0] = ~0;
  156. /* 350 milliseconds */
  157. dev->timer.expires = jiffies + HZ * 350 / 1000;
  158. /* MAKE */
  159. input_event(dev, EV_KEY, key_map[code], !0);
  160. add_timer(&dev->timer);
  161. }
  162. }
  163. static int msp430_ir_init(struct budget_ci *budget_ci)
  164. {
  165. struct saa7146_dev *saa = budget_ci->budget.dev;
  166. struct input_dev *input_dev;
  167. int i;
  168. budget_ci->input_dev = input_dev = input_allocate_device();
  169. if (!input_dev)
  170. return -ENOMEM;
  171. sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
  172. input_dev->name = budget_ci->ir_dev_name;
  173. set_bit(EV_KEY, input_dev->evbit);
  174. for (i = 0; i < ARRAY_SIZE(key_map); i++)
  175. if (key_map[i])
  176. set_bit(key_map[i], input_dev->keybit);
  177. input_register_device(budget_ci->input_dev);
  178. input_dev->timer.function = msp430_ir_debounce;
  179. saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
  180. saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
  181. return 0;
  182. }
  183. static void msp430_ir_deinit(struct budget_ci *budget_ci)
  184. {
  185. struct saa7146_dev *saa = budget_ci->budget.dev;
  186. struct input_dev *dev = budget_ci->input_dev;
  187. saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
  188. saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
  189. if (del_timer(&dev->timer))
  190. input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
  191. input_unregister_device(dev);
  192. }
  193. static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
  194. {
  195. struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
  196. if (slot != 0)
  197. return -EINVAL;
  198. return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
  199. DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
  200. }
  201. static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
  202. {
  203. struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
  204. if (slot != 0)
  205. return -EINVAL;
  206. return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
  207. DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
  208. }
  209. static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
  210. {
  211. struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
  212. if (slot != 0)
  213. return -EINVAL;
  214. return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
  215. DEBIADDR_IO | (address & 3), 1, 1, 0);
  216. }
  217. static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
  218. {
  219. struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
  220. if (slot != 0)
  221. return -EINVAL;
  222. return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
  223. DEBIADDR_IO | (address & 3), 1, value, 1, 0);
  224. }
  225. static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
  226. {
  227. struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
  228. struct saa7146_dev *saa = budget_ci->budget.dev;
  229. if (slot != 0)
  230. return -EINVAL;
  231. // trigger on RISING edge during reset so we know when READY is re-asserted
  232. saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
  233. budget_ci->slot_status = SLOTSTATUS_RESET;
  234. ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
  235. msleep(1);
  236. ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
  237. CICONTROL_RESET, 1, 0);
  238. saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
  239. ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
  240. return 0;
  241. }
  242. static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
  243. {
  244. struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
  245. struct saa7146_dev *saa = budget_ci->budget.dev;
  246. if (slot != 0)
  247. return -EINVAL;
  248. saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
  249. ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
  250. return 0;
  251. }
  252. static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
  253. {
  254. struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
  255. struct saa7146_dev *saa = budget_ci->budget.dev;
  256. int tmp;
  257. if (slot != 0)
  258. return -EINVAL;
  259. saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
  260. tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
  261. ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
  262. tmp | CICONTROL_ENABLETS, 1, 0);
  263. ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
  264. return 0;
  265. }
  266. static void ciintf_interrupt(unsigned long data)
  267. {
  268. struct budget_ci *budget_ci = (struct budget_ci *) data;
  269. struct saa7146_dev *saa = budget_ci->budget.dev;
  270. unsigned int flags;
  271. // ensure we don't get spurious IRQs during initialisation
  272. if (!budget_ci->budget.ci_present)
  273. return;
  274. // read the CAM status
  275. flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
  276. if (flags & CICONTROL_CAMDETECT) {
  277. // GPIO should be set to trigger on falling edge if a CAM is present
  278. saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
  279. if (budget_ci->slot_status & SLOTSTATUS_NONE) {
  280. // CAM insertion IRQ
  281. budget_ci->slot_status = SLOTSTATUS_PRESENT;
  282. dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
  283. DVB_CA_EN50221_CAMCHANGE_INSERTED);
  284. } else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
  285. // CAM ready (reset completed)
  286. budget_ci->slot_status = SLOTSTATUS_READY;
  287. dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
  288. } else if (budget_ci->slot_status & SLOTSTATUS_READY) {
  289. // FR/DA IRQ
  290. dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
  291. }
  292. } else {
  293. // trigger on rising edge if a CAM is not present - when a CAM is inserted, we
  294. // only want to get the IRQ when it sets READY. If we trigger on the falling edge,
  295. // the CAM might not actually be ready yet.
  296. saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
  297. // generate a CAM removal IRQ if we haven't already
  298. if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
  299. // CAM removal IRQ
  300. budget_ci->slot_status = SLOTSTATUS_NONE;
  301. dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
  302. DVB_CA_EN50221_CAMCHANGE_REMOVED);
  303. }
  304. }
  305. }
  306. static int ciintf_init(struct budget_ci *budget_ci)
  307. {
  308. struct saa7146_dev *saa = budget_ci->budget.dev;
  309. int flags;
  310. int result;
  311. memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
  312. // enable DEBI pins
  313. saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
  314. // test if it is there
  315. if ((ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0) & 0xa0) != 0xa0) {
  316. result = -ENODEV;
  317. goto error;
  318. }
  319. // determine whether a CAM is present or not
  320. flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
  321. budget_ci->slot_status = SLOTSTATUS_NONE;
  322. if (flags & CICONTROL_CAMDETECT)
  323. budget_ci->slot_status = SLOTSTATUS_PRESENT;
  324. // register CI interface
  325. budget_ci->ca.owner = THIS_MODULE;
  326. budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
  327. budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
  328. budget_ci->ca.read_cam_control = ciintf_read_cam_control;
  329. budget_ci->ca.write_cam_control = ciintf_write_cam_control;
  330. budget_ci->ca.slot_reset = ciintf_slot_reset;
  331. budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
  332. budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
  333. budget_ci->ca.data = budget_ci;
  334. if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
  335. &budget_ci->ca,
  336. DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
  337. DVB_CA_EN50221_FLAG_IRQ_FR |
  338. DVB_CA_EN50221_FLAG_IRQ_DA, 1)) != 0) {
  339. printk("budget_ci: CI interface detected, but initialisation failed.\n");
  340. goto error;
  341. }
  342. // Setup CI slot IRQ
  343. tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
  344. if (budget_ci->slot_status != SLOTSTATUS_NONE) {
  345. saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
  346. } else {
  347. saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
  348. }
  349. saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03);
  350. ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
  351. CICONTROL_RESET, 1, 0);
  352. // success!
  353. printk("budget_ci: CI interface initialised\n");
  354. budget_ci->budget.ci_present = 1;
  355. // forge a fake CI IRQ so the CAM state is setup correctly
  356. flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
  357. if (budget_ci->slot_status != SLOTSTATUS_NONE)
  358. flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
  359. dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
  360. return 0;
  361. error:
  362. saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
  363. return result;
  364. }
  365. static void ciintf_deinit(struct budget_ci *budget_ci)
  366. {
  367. struct saa7146_dev *saa = budget_ci->budget.dev;
  368. // disable CI interrupts
  369. saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03);
  370. saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
  371. tasklet_kill(&budget_ci->ciintf_irq_tasklet);
  372. ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
  373. msleep(1);
  374. ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
  375. CICONTROL_RESET, 1, 0);
  376. // disable TS data stream to CI interface
  377. saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
  378. // release the CA device
  379. dvb_ca_en50221_release(&budget_ci->ca);
  380. // disable DEBI pins
  381. saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
  382. }
  383. static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
  384. {
  385. struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
  386. dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
  387. if (*isr & MASK_06)
  388. tasklet_schedule(&budget_ci->msp430_irq_tasklet);
  389. if (*isr & MASK_10)
  390. ttpci_budget_irq10_handler(dev, isr);
  391. if ((*isr & MASK_03) && (budget_ci->budget.ci_present))
  392. tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
  393. }
  394. static u8 alps_bsru6_inittab[] = {
  395. 0x01, 0x15,
  396. 0x02, 0x00,
  397. 0x03, 0x00,
  398. 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
  399. 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
  400. 0x06, 0x40, /* DAC not used, set to high impendance mode */
  401. 0x07, 0x00, /* DAC LSB */
  402. 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
  403. 0x09, 0x00, /* FIFO */
  404. 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
  405. 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
  406. 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
  407. 0x10, 0x3f, // AGC2 0x3d
  408. 0x11, 0x84,
  409. 0x12, 0xb9,
  410. 0x15, 0xc9, // lock detector threshold
  411. 0x16, 0x00,
  412. 0x17, 0x00,
  413. 0x18, 0x00,
  414. 0x19, 0x00,
  415. 0x1a, 0x00,
  416. 0x1f, 0x50,
  417. 0x20, 0x00,
  418. 0x21, 0x00,
  419. 0x22, 0x00,
  420. 0x23, 0x00,
  421. 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
  422. 0x29, 0x1e, // 1/2 threshold
  423. 0x2a, 0x14, // 2/3 threshold
  424. 0x2b, 0x0f, // 3/4 threshold
  425. 0x2c, 0x09, // 5/6 threshold
  426. 0x2d, 0x05, // 7/8 threshold
  427. 0x2e, 0x01,
  428. 0x31, 0x1f, // test all FECs
  429. 0x32, 0x19, // viterbi and synchro search
  430. 0x33, 0xfc, // rs control
  431. 0x34, 0x93, // error control
  432. 0x0f, 0x52,
  433. 0xff, 0xff
  434. };
  435. static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
  436. {
  437. u8 aclk = 0;
  438. u8 bclk = 0;
  439. if (srate < 1500000) {
  440. aclk = 0xb7;
  441. bclk = 0x47;
  442. } else if (srate < 3000000) {
  443. aclk = 0xb7;
  444. bclk = 0x4b;
  445. } else if (srate < 7000000) {
  446. aclk = 0xb7;
  447. bclk = 0x4f;
  448. } else if (srate < 14000000) {
  449. aclk = 0xb7;
  450. bclk = 0x53;
  451. } else if (srate < 30000000) {
  452. aclk = 0xb6;
  453. bclk = 0x53;
  454. } else if (srate < 45000000) {
  455. aclk = 0xb4;
  456. bclk = 0x51;
  457. }
  458. stv0299_writereg(fe, 0x13, aclk);
  459. stv0299_writereg(fe, 0x14, bclk);
  460. stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
  461. stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
  462. stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
  463. return 0;
  464. }
  465. static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
  466. {
  467. u8 buf[4];
  468. u32 div;
  469. struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
  470. if ((params->frequency < 950000) || (params->frequency > 2150000))
  471. return -EINVAL;
  472. div = (params->frequency + (125 - 1)) / 125; // round correctly
  473. buf[0] = (div >> 8) & 0x7f;
  474. buf[1] = div & 0xff;
  475. buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
  476. buf[3] = 0xC4;
  477. if (params->frequency > 1530000)
  478. buf[3] = 0xc0;
  479. if (i2c_transfer(i2c, &msg, 1) != 1)
  480. return -EIO;
  481. return 0;
  482. }
  483. static struct stv0299_config alps_bsru6_config = {
  484. .demod_address = 0x68,
  485. .inittab = alps_bsru6_inittab,
  486. .mclk = 88000000UL,
  487. .invert = 1,
  488. .skip_reinit = 0,
  489. .lock_output = STV0229_LOCKOUTPUT_1,
  490. .volt13_op0_op1 = STV0299_VOLT13_OP1,
  491. .min_delay_ms = 100,
  492. .set_symbol_rate = alps_bsru6_set_symbol_rate,
  493. .pll_set = alps_bsru6_pll_set,
  494. };
  495. static u8 philips_su1278_tt_inittab[] = {
  496. 0x01, 0x0f,
  497. 0x02, 0x30,
  498. 0x03, 0x00,
  499. 0x04, 0x5b,
  500. 0x05, 0x85,
  501. 0x06, 0x02,
  502. 0x07, 0x00,
  503. 0x08, 0x02,
  504. 0x09, 0x00,
  505. 0x0C, 0x01,
  506. 0x0D, 0x81,
  507. 0x0E, 0x44,
  508. 0x0f, 0x14,
  509. 0x10, 0x3c,
  510. 0x11, 0x84,
  511. 0x12, 0xda,
  512. 0x13, 0x97,
  513. 0x14, 0x95,
  514. 0x15, 0xc9,
  515. 0x16, 0x19,
  516. 0x17, 0x8c,
  517. 0x18, 0x59,
  518. 0x19, 0xf8,
  519. 0x1a, 0xfe,
  520. 0x1c, 0x7f,
  521. 0x1d, 0x00,
  522. 0x1e, 0x00,
  523. 0x1f, 0x50,
  524. 0x20, 0x00,
  525. 0x21, 0x00,
  526. 0x22, 0x00,
  527. 0x23, 0x00,
  528. 0x28, 0x00,
  529. 0x29, 0x28,
  530. 0x2a, 0x14,
  531. 0x2b, 0x0f,
  532. 0x2c, 0x09,
  533. 0x2d, 0x09,
  534. 0x31, 0x1f,
  535. 0x32, 0x19,
  536. 0x33, 0xfc,
  537. 0x34, 0x93,
  538. 0xff, 0xff
  539. };
  540. static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
  541. {
  542. stv0299_writereg(fe, 0x0e, 0x44);
  543. if (srate >= 10000000) {
  544. stv0299_writereg(fe, 0x13, 0x97);
  545. stv0299_writereg(fe, 0x14, 0x95);
  546. stv0299_writereg(fe, 0x15, 0xc9);
  547. stv0299_writereg(fe, 0x17, 0x8c);
  548. stv0299_writereg(fe, 0x1a, 0xfe);
  549. stv0299_writereg(fe, 0x1c, 0x7f);
  550. stv0299_writereg(fe, 0x2d, 0x09);
  551. } else {
  552. stv0299_writereg(fe, 0x13, 0x99);
  553. stv0299_writereg(fe, 0x14, 0x8d);
  554. stv0299_writereg(fe, 0x15, 0xce);
  555. stv0299_writereg(fe, 0x17, 0x43);
  556. stv0299_writereg(fe, 0x1a, 0x1d);
  557. stv0299_writereg(fe, 0x1c, 0x12);
  558. stv0299_writereg(fe, 0x2d, 0x05);
  559. }
  560. stv0299_writereg(fe, 0x0e, 0x23);
  561. stv0299_writereg(fe, 0x0f, 0x94);
  562. stv0299_writereg(fe, 0x10, 0x39);
  563. stv0299_writereg(fe, 0x15, 0xc9);
  564. stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
  565. stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
  566. stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
  567. return 0;
  568. }
  569. static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
  570. struct i2c_adapter *i2c,
  571. struct dvb_frontend_parameters *params)
  572. {
  573. u32 div;
  574. u8 buf[4];
  575. struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
  576. if ((params->frequency < 950000) || (params->frequency > 2150000))
  577. return -EINVAL;
  578. div = (params->frequency + (500 - 1)) / 500; // round correctly
  579. buf[0] = (div >> 8) & 0x7f;
  580. buf[1] = div & 0xff;
  581. buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
  582. buf[3] = 0x20;
  583. if (params->u.qpsk.symbol_rate < 4000000)
  584. buf[3] |= 1;
  585. if (params->frequency < 1250000)
  586. buf[3] |= 0;
  587. else if (params->frequency < 1550000)
  588. buf[3] |= 0x40;
  589. else if (params->frequency < 2050000)
  590. buf[3] |= 0x80;
  591. else if (params->frequency < 2150000)
  592. buf[3] |= 0xC0;
  593. if (i2c_transfer(i2c, &msg, 1) != 1)
  594. return -EIO;
  595. return 0;
  596. }
  597. static struct stv0299_config philips_su1278_tt_config = {
  598. .demod_address = 0x68,
  599. .inittab = philips_su1278_tt_inittab,
  600. .mclk = 64000000UL,
  601. .invert = 0,
  602. .skip_reinit = 1,
  603. .lock_output = STV0229_LOCKOUTPUT_1,
  604. .volt13_op0_op1 = STV0299_VOLT13_OP1,
  605. .min_delay_ms = 50,
  606. .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
  607. .pll_set = philips_su1278_tt_pll_set,
  608. };
  609. static int philips_tdm1316l_pll_init(struct dvb_frontend *fe)
  610. {
  611. struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
  612. static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
  613. static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
  614. struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
  615. sizeof(td1316_init) };
  616. // setup PLL configuration
  617. if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
  618. return -EIO;
  619. msleep(1);
  620. // disable the mc44BC374c (do not check for errors)
  621. tuner_msg.addr = 0x65;
  622. tuner_msg.buf = disable_mc44BC374c;
  623. tuner_msg.len = sizeof(disable_mc44BC374c);
  624. if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
  625. i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
  626. }
  627. return 0;
  628. }
  629. static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
  630. {
  631. struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
  632. u8 tuner_buf[4];
  633. struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };
  634. int tuner_frequency = 0;
  635. u8 band, cp, filter;
  636. // determine charge pump
  637. tuner_frequency = params->frequency + 36130000;
  638. if (tuner_frequency < 87000000)
  639. return -EINVAL;
  640. else if (tuner_frequency < 130000000)
  641. cp = 3;
  642. else if (tuner_frequency < 160000000)
  643. cp = 5;
  644. else if (tuner_frequency < 200000000)
  645. cp = 6;
  646. else if (tuner_frequency < 290000000)
  647. cp = 3;
  648. else if (tuner_frequency < 420000000)
  649. cp = 5;
  650. else if (tuner_frequency < 480000000)
  651. cp = 6;
  652. else if (tuner_frequency < 620000000)
  653. cp = 3;
  654. else if (tuner_frequency < 830000000)
  655. cp = 5;
  656. else if (tuner_frequency < 895000000)
  657. cp = 7;
  658. else
  659. return -EINVAL;
  660. // determine band
  661. if (params->frequency < 49000000)
  662. return -EINVAL;
  663. else if (params->frequency < 159000000)
  664. band = 1;
  665. else if (params->frequency < 444000000)
  666. band = 2;
  667. else if (params->frequency < 861000000)
  668. band = 4;
  669. else
  670. return -EINVAL;
  671. // setup PLL filter and TDA9889
  672. switch (params->u.ofdm.bandwidth) {
  673. case BANDWIDTH_6_MHZ:
  674. tda1004x_write_byte(fe, 0x0C, 0x14);
  675. filter = 0;
  676. break;
  677. case BANDWIDTH_7_MHZ:
  678. tda1004x_write_byte(fe, 0x0C, 0x80);
  679. filter = 0;
  680. break;
  681. case BANDWIDTH_8_MHZ:
  682. tda1004x_write_byte(fe, 0x0C, 0x14);
  683. filter = 1;
  684. break;
  685. default:
  686. return -EINVAL;
  687. }
  688. // calculate divisor
  689. // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
  690. tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
  691. // setup tuner buffer
  692. tuner_buf[0] = tuner_frequency >> 8;
  693. tuner_buf[1] = tuner_frequency & 0xff;
  694. tuner_buf[2] = 0xca;
  695. tuner_buf[3] = (cp << 5) | (filter << 3) | band;
  696. if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
  697. return -EIO;
  698. msleep(1);
  699. return 0;
  700. }
  701. static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
  702. const struct firmware **fw, char *name)
  703. {
  704. struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
  705. return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
  706. }
  707. static struct tda1004x_config philips_tdm1316l_config = {
  708. .demod_address = 0x8,
  709. .invert = 0,
  710. .invert_oclk = 0,
  711. .xtal_freq = TDA10046_XTAL_4M,
  712. .agc_config = TDA10046_AGC_DEFAULT,
  713. .if_freq = TDA10046_FREQ_3617,
  714. .pll_init = philips_tdm1316l_pll_init,
  715. .pll_set = philips_tdm1316l_pll_set,
  716. .pll_sleep = NULL,
  717. .request_firmware = philips_tdm1316l_request_firmware,
  718. };
  719. static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
  720. {
  721. struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
  722. u8 tuner_buf[5];
  723. struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
  724. .flags = 0,
  725. .buf = tuner_buf,
  726. .len = sizeof(tuner_buf) };
  727. int tuner_frequency = 0;
  728. u8 band, cp, filter;
  729. // determine charge pump
  730. tuner_frequency = params->frequency + 36125000;
  731. if (tuner_frequency < 87000000)
  732. return -EINVAL;
  733. else if (tuner_frequency < 130000000) {
  734. cp = 3;
  735. band = 1;
  736. } else if (tuner_frequency < 160000000) {
  737. cp = 5;
  738. band = 1;
  739. } else if (tuner_frequency < 200000000) {
  740. cp = 6;
  741. band = 1;
  742. } else if (tuner_frequency < 290000000) {
  743. cp = 3;
  744. band = 2;
  745. } else if (tuner_frequency < 420000000) {
  746. cp = 5;
  747. band = 2;
  748. } else if (tuner_frequency < 480000000) {
  749. cp = 6;
  750. band = 2;
  751. } else if (tuner_frequency < 620000000) {
  752. cp = 3;
  753. band = 4;
  754. } else if (tuner_frequency < 830000000) {
  755. cp = 5;
  756. band = 4;
  757. } else if (tuner_frequency < 895000000) {
  758. cp = 7;
  759. band = 4;
  760. } else
  761. return -EINVAL;
  762. // assume PLL filter should always be 8MHz for the moment.
  763. filter = 1;
  764. // calculate divisor
  765. tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
  766. // setup tuner buffer
  767. tuner_buf[0] = tuner_frequency >> 8;
  768. tuner_buf[1] = tuner_frequency & 0xff;
  769. tuner_buf[2] = 0xc8;
  770. tuner_buf[3] = (cp << 5) | (filter << 3) | band;
  771. tuner_buf[4] = 0x80;
  772. stv0297_enable_plli2c(fe);
  773. if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
  774. return -EIO;
  775. msleep(50);
  776. stv0297_enable_plli2c(fe);
  777. if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
  778. return -EIO;
  779. msleep(1);
  780. return 0;
  781. }
  782. static u8 dvbc_philips_tdm1316l_inittab[] = {
  783. 0x80, 0x01,
  784. 0x80, 0x00,
  785. 0x81, 0x01,
  786. 0x81, 0x00,
  787. 0x00, 0x09,
  788. 0x01, 0x69,
  789. 0x03, 0x00,
  790. 0x04, 0x00,
  791. 0x07, 0x00,
  792. 0x08, 0x00,
  793. 0x20, 0x00,
  794. 0x21, 0x40,
  795. 0x22, 0x00,
  796. 0x23, 0x00,
  797. 0x24, 0x40,
  798. 0x25, 0x88,
  799. 0x30, 0xff,
  800. 0x31, 0x00,
  801. 0x32, 0xff,
  802. 0x33, 0x00,
  803. 0x34, 0x50,
  804. 0x35, 0x7f,
  805. 0x36, 0x00,
  806. 0x37, 0x20,
  807. 0x38, 0x00,
  808. 0x40, 0x1c,
  809. 0x41, 0xff,
  810. 0x42, 0x29,
  811. 0x43, 0x20,
  812. 0x44, 0xff,
  813. 0x45, 0x00,
  814. 0x46, 0x00,
  815. 0x49, 0x04,
  816. 0x4a, 0x00,
  817. 0x4b, 0x7b,
  818. 0x52, 0x30,
  819. 0x55, 0xae,
  820. 0x56, 0x47,
  821. 0x57, 0xe1,
  822. 0x58, 0x3a,
  823. 0x5a, 0x1e,
  824. 0x5b, 0x34,
  825. 0x60, 0x00,
  826. 0x63, 0x00,
  827. 0x64, 0x00,
  828. 0x65, 0x00,
  829. 0x66, 0x00,
  830. 0x67, 0x00,
  831. 0x68, 0x00,
  832. 0x69, 0x00,
  833. 0x6a, 0x02,
  834. 0x6b, 0x00,
  835. 0x70, 0xff,
  836. 0x71, 0x00,
  837. 0x72, 0x00,
  838. 0x73, 0x00,
  839. 0x74, 0x0c,
  840. 0x80, 0x00,
  841. 0x81, 0x00,
  842. 0x82, 0x00,
  843. 0x83, 0x00,
  844. 0x84, 0x04,
  845. 0x85, 0x80,
  846. 0x86, 0x24,
  847. 0x87, 0x78,
  848. 0x88, 0x10,
  849. 0x89, 0x00,
  850. 0x90, 0x01,
  851. 0x91, 0x01,
  852. 0xa0, 0x04,
  853. 0xa1, 0x00,
  854. 0xa2, 0x00,
  855. 0xb0, 0x91,
  856. 0xb1, 0x0b,
  857. 0xc0, 0x53,
  858. 0xc1, 0x70,
  859. 0xc2, 0x12,
  860. 0xd0, 0x00,
  861. 0xd1, 0x00,
  862. 0xd2, 0x00,
  863. 0xd3, 0x00,
  864. 0xd4, 0x00,
  865. 0xd5, 0x00,
  866. 0xde, 0x00,
  867. 0xdf, 0x00,
  868. 0x61, 0x38,
  869. 0x62, 0x0a,
  870. 0x53, 0x13,
  871. 0x59, 0x08,
  872. 0xff, 0xff,
  873. };
  874. static struct stv0297_config dvbc_philips_tdm1316l_config = {
  875. .demod_address = 0x1c,
  876. .inittab = dvbc_philips_tdm1316l_inittab,
  877. .invert = 0,
  878. .pll_set = dvbc_philips_tdm1316l_pll_set,
  879. };
  880. static void frontend_init(struct budget_ci *budget_ci)
  881. {
  882. switch (budget_ci->budget.dev->pci->subsystem_device) {
  883. case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
  884. budget_ci->budget.dvb_frontend =
  885. stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap);
  886. if (budget_ci->budget.dvb_frontend) {
  887. break;
  888. }
  889. break;
  890. case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
  891. budget_ci->budget.dvb_frontend =
  892. stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
  893. if (budget_ci->budget.dvb_frontend) {
  894. break;
  895. }
  896. break;
  897. case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
  898. budget_ci->tuner_pll_address = 0x61;
  899. budget_ci->budget.dvb_frontend =
  900. stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
  901. if (budget_ci->budget.dvb_frontend) {
  902. break;
  903. }
  904. break;
  905. case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
  906. budget_ci->tuner_pll_address = 0x63;
  907. budget_ci->budget.dvb_frontend =
  908. tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
  909. if (budget_ci->budget.dvb_frontend) {
  910. break;
  911. }
  912. break;
  913. case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
  914. budget_ci->tuner_pll_address = 0x60;
  915. budget_ci->budget.dvb_frontend =
  916. tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
  917. if (budget_ci->budget.dvb_frontend) {
  918. break;
  919. }
  920. break;
  921. }
  922. if (budget_ci->budget.dvb_frontend == NULL) {
  923. printk("budget-ci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
  924. budget_ci->budget.dev->pci->vendor,
  925. budget_ci->budget.dev->pci->device,
  926. budget_ci->budget.dev->pci->subsystem_vendor,
  927. budget_ci->budget.dev->pci->subsystem_device);
  928. } else {
  929. if (dvb_register_frontend
  930. (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
  931. printk("budget-ci: Frontend registration failed!\n");
  932. if (budget_ci->budget.dvb_frontend->ops->release)
  933. budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend);
  934. budget_ci->budget.dvb_frontend = NULL;
  935. }
  936. }
  937. }
  938. static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
  939. {
  940. struct budget_ci *budget_ci;
  941. int err;
  942. if (!(budget_ci = kmalloc(sizeof(struct budget_ci), GFP_KERNEL)))
  943. return -ENOMEM;
  944. dprintk(2, "budget_ci: %p\n", budget_ci);
  945. budget_ci->budget.ci_present = 0;
  946. dev->ext_priv = budget_ci;
  947. if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) {
  948. kfree(budget_ci);
  949. return err;
  950. }
  951. tasklet_init(&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt,
  952. (unsigned long) budget_ci);
  953. msp430_ir_init(budget_ci);
  954. ciintf_init(budget_ci);
  955. budget_ci->budget.dvb_adapter.priv = budget_ci;
  956. frontend_init(budget_ci);
  957. return 0;
  958. }
  959. static int budget_ci_detach(struct saa7146_dev *dev)
  960. {
  961. struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
  962. struct saa7146_dev *saa = budget_ci->budget.dev;
  963. int err;
  964. if (budget_ci->budget.ci_present)
  965. ciintf_deinit(budget_ci);
  966. if (budget_ci->budget.dvb_frontend)
  967. dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
  968. err = ttpci_budget_deinit(&budget_ci->budget);
  969. tasklet_kill(&budget_ci->msp430_irq_tasklet);
  970. msp430_ir_deinit(budget_ci);
  971. // disable frontend and CI interface
  972. saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
  973. kfree(budget_ci);
  974. return err;
  975. }
  976. static struct saa7146_extension budget_extension;
  977. MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
  978. MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
  979. MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
  980. MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
  981. static struct pci_device_id pci_tbl[] = {
  982. MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
  983. MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
  984. MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
  985. MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
  986. MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
  987. {
  988. .vendor = 0,
  989. }
  990. };
  991. MODULE_DEVICE_TABLE(pci, pci_tbl);
  992. static struct saa7146_extension budget_extension = {
  993. .name = "budget_ci dvb\0",
  994. .flags = SAA7146_I2C_SHORT_DELAY,
  995. .module = THIS_MODULE,
  996. .pci_tbl = &pci_tbl[0],
  997. .attach = budget_ci_attach,
  998. .detach = budget_ci_detach,
  999. .irq_mask = MASK_03 | MASK_06 | MASK_10,
  1000. .irq_func = budget_ci_irq,
  1001. };
  1002. static int __init budget_ci_init(void)
  1003. {
  1004. return saa7146_register_extension(&budget_extension);
  1005. }
  1006. static void __exit budget_ci_exit(void)
  1007. {
  1008. saa7146_unregister_extension(&budget_extension);
  1009. }
  1010. module_init(budget_ci_init);
  1011. module_exit(budget_ci_exit);
  1012. MODULE_LICENSE("GPL");
  1013. MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
  1014. MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
  1015. "budget PCI DVB cards w/ CI-module produced by "
  1016. "Siemens, Technotrend, Hauppauge");