diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/dvb/ttpci/budget-av.c | 216 |
1 files changed, 118 insertions, 98 deletions
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 7891f3f06f04..6e0f5d307c52 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c | |||
@@ -59,8 +59,12 @@ struct budget_av { | |||
59 | struct dvb_ca_en50221 ca; | 59 | struct dvb_ca_en50221 ca; |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static int enable_ci = 0; | 62 | /* GPIO CI Connections: |
63 | 63 | * 0 - Vcc/Reset (Reset is controlled by capacitor) | |
64 | * 1 - Attribute Memory | ||
65 | * 2 - Card Enable (Active Low) | ||
66 | * 3 - Card Detect | ||
67 | */ | ||
64 | 68 | ||
65 | /**************************************************************************** | 69 | /**************************************************************************** |
66 | * INITIALIZATION | 70 | * INITIALIZATION |
@@ -188,22 +192,35 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) | |||
188 | { | 192 | { |
189 | struct budget_av *budget_av = (struct budget_av *) ca->data; | 193 | struct budget_av *budget_av = (struct budget_av *) ca->data; |
190 | struct saa7146_dev *saa = budget_av->budget.dev; | 194 | struct saa7146_dev *saa = budget_av->budget.dev; |
191 | int max = 20; | 195 | int timeout = 50; // 5 seconds (4.4.6 Ready) |
192 | 196 | ||
193 | if (slot != 0) | 197 | if (slot != 0) |
194 | return -EINVAL; | 198 | return -EINVAL; |
195 | 199 | ||
196 | dprintk(1, "ciintf_slot_reset\n"); | 200 | dprintk(1, "ciintf_slot_reset\n"); |
197 | 201 | ||
198 | /* reset the card */ | 202 | saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */ |
199 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); | ||
200 | msleep(100); | ||
201 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); | ||
202 | 203 | ||
203 | while (--max > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d) | 204 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */ |
205 | msleep(2); | ||
206 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */ | ||
207 | msleep(20); /* 20 ms Vcc settling time */ | ||
208 | |||
209 | saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */ | ||
210 | |||
211 | /* This should have been based on pin 16 READY of the pcmcia port, | ||
212 | * but AFAICS it is not routed to the saa7146 */ | ||
213 | while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d) | ||
204 | msleep(100); | 214 | msleep(100); |
205 | 215 | ||
206 | ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB); | 216 | if (timeout <= 0) |
217 | { | ||
218 | printk(KERN_ERR "budget-av: cam reset failed (timeout).\n"); | ||
219 | saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */ | ||
220 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */ | ||
221 | return -ETIMEDOUT; | ||
222 | } | ||
223 | |||
207 | return 0; | 224 | return 0; |
208 | } | 225 | } |
209 | 226 | ||
@@ -240,7 +257,6 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open | |||
240 | { | 257 | { |
241 | struct budget_av *budget_av = (struct budget_av *) ca->data; | 258 | struct budget_av *budget_av = (struct budget_av *) ca->data; |
242 | struct saa7146_dev *saa = budget_av->budget.dev; | 259 | struct saa7146_dev *saa = budget_av->budget.dev; |
243 | int cam = 0; | ||
244 | 260 | ||
245 | if (slot != 0) | 261 | if (slot != 0) |
246 | return -EINVAL; | 262 | return -EINVAL; |
@@ -248,15 +264,21 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open | |||
248 | if (!budget_av->slot_status) { | 264 | if (!budget_av->slot_status) { |
249 | saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); | 265 | saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT); |
250 | udelay(1); | 266 | udelay(1); |
251 | cam = saa7146_read(saa, PSR) & MASK_06; | 267 | if (saa7146_read(saa, PSR) & MASK_06) |
252 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); | 268 | { |
253 | 269 | printk(KERN_INFO "budget-av: cam inserted\n"); | |
254 | if (cam) | ||
255 | budget_av->slot_status = 1; | 270 | budget_av->slot_status = 1; |
271 | } | ||
272 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); | ||
256 | } else if (!open) { | 273 | } else if (!open) { |
257 | saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); | 274 | saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); |
258 | if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT) | 275 | if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT) |
276 | { | ||
277 | printk(KERN_INFO "budget-av: cam ejected\n"); | ||
278 | saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */ | ||
279 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */ | ||
259 | budget_av->slot_status = 0; | 280 | budget_av->slot_status = 0; |
281 | } | ||
260 | } | 282 | } |
261 | 283 | ||
262 | if (budget_av->slot_status == 1) | 284 | if (budget_av->slot_status == 1) |
@@ -272,17 +294,11 @@ static int ciintf_init(struct budget_av *budget_av) | |||
272 | 294 | ||
273 | memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221)); | 295 | memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221)); |
274 | 296 | ||
275 | /* setup GPIOs */ | 297 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); |
276 | saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI); | 298 | saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO); |
277 | saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); | 299 | saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); |
278 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); | 300 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO); |
279 | 301 | ||
280 | /* Reset the card */ | ||
281 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); | ||
282 | msleep(50); | ||
283 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); | ||
284 | msleep(100); | ||
285 | |||
286 | /* Enable DEBI pins */ | 302 | /* Enable DEBI pins */ |
287 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); | 303 | saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); |
288 | 304 | ||
@@ -297,13 +313,14 @@ static int ciintf_init(struct budget_av *budget_av) | |||
297 | budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable; | 313 | budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable; |
298 | budget_av->ca.poll_slot_status = ciintf_poll_slot_status; | 314 | budget_av->ca.poll_slot_status = ciintf_poll_slot_status; |
299 | budget_av->ca.data = budget_av; | 315 | budget_av->ca.data = budget_av; |
316 | |||
300 | if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter, | 317 | if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter, |
301 | &budget_av->ca, 0, 1)) != 0) { | 318 | &budget_av->ca, 0, 1)) != 0) { |
302 | printk("budget_av: CI interface detected, but initialisation failed.\n"); | 319 | printk(KERN_ERR "budget-av: ci initialisation failed.\n"); |
303 | goto error; | 320 | goto error; |
304 | } | 321 | } |
305 | // success! | 322 | |
306 | printk("ciintf_init: CI interface initialised\n"); | 323 | printk(KERN_INFO "budget-av: ci interface initialised.\n"); |
307 | budget_av->budget.ci_present = 1; | 324 | budget_av->budget.ci_present = 1; |
308 | return 0; | 325 | return 0; |
309 | 326 | ||
@@ -361,8 +378,12 @@ static const u8 saa7113_tab[] = { | |||
361 | static int saa7113_init(struct budget_av *budget_av) | 378 | static int saa7113_init(struct budget_av *budget_av) |
362 | { | 379 | { |
363 | struct budget *budget = &budget_av->budget; | 380 | struct budget *budget = &budget_av->budget; |
381 | struct saa7146_dev *saa = budget->dev; | ||
364 | const u8 *data = saa7113_tab; | 382 | const u8 *data = saa7113_tab; |
365 | 383 | ||
384 | saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); | ||
385 | msleep(200); | ||
386 | |||
366 | if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) { | 387 | if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) { |
367 | dprintk(1, "saa7113 not found on KNC card\n"); | 388 | dprintk(1, "saa7113 not found on KNC card\n"); |
368 | return -ENODEV; | 389 | return -ENODEV; |
@@ -697,82 +718,90 @@ static u8 read_pwm(struct budget_av *budget_av) | |||
697 | return pwm; | 718 | return pwm; |
698 | } | 719 | } |
699 | 720 | ||
721 | #define SUBID_DVBS_KNC1 0x0010 | ||
722 | #define SUBID_DVBS_KNC1_PLUS 0x0011 | ||
723 | #define SUBID_DVBS_TYPHOON 0x4f56 | ||
724 | #define SUBID_DVBS_CINERGY1200 0x1154 | ||
725 | |||
726 | #define SUBID_DVBC_KNC1 0x0020 | ||
727 | #define SUBID_DVBC_KNC1_PLUS 0x0021 | ||
728 | #define SUBID_DVBC_CINERGY1200 0x1156 | ||
729 | |||
730 | #define SUBID_DVBT_KNC1_PLUS 0x0031 | ||
731 | #define SUBID_DVBT_KNC1 0x0030 | ||
732 | #define SUBID_DVBT_CINERGY1200 0x1157 | ||
700 | 733 | ||
701 | static void frontend_init(struct budget_av *budget_av) | 734 | static void frontend_init(struct budget_av *budget_av) |
702 | { | 735 | { |
703 | switch (budget_av->budget.dev->pci->subsystem_device) { | 736 | struct saa7146_dev * saa = budget_av->budget.dev; |
704 | case 0x0011: // KNC1 DVB-S Plus budget with AV IN (stv0299/Philips SU1278(tsa5059)) | 737 | struct dvb_frontend * fe = NULL; |
705 | saa7146_write(budget_av->budget.dev, GPIO_CTRL, 0x50000000); // Enable / PowerON Frontend | 738 | |
706 | case 0x4f56: // Typhoon/KNC1 DVB-S budget (stv0299/Philips SU1278(tsa5059)) | 739 | switch (saa->pci->subsystem_device) { |
707 | case 0x0010: // KNC1 DVB-S budget (stv0299/Philips SU1278(tsa5059)) | 740 | case SUBID_DVBS_KNC1_PLUS: |
708 | budget_av->budget.dvb_frontend = | 741 | case SUBID_DVBC_KNC1_PLUS: |
709 | stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap); | 742 | case SUBID_DVBT_KNC1_PLUS: |
710 | if (budget_av->budget.dvb_frontend != NULL) { | 743 | // Enable / PowerON Frontend |
744 | saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI); | ||
711 | break; | 745 | break; |
712 | } | 746 | } |
747 | |||
748 | switch (saa->pci->subsystem_device) { | ||
749 | |||
750 | case SUBID_DVBS_KNC1: | ||
751 | case SUBID_DVBS_KNC1_PLUS: | ||
752 | case SUBID_DVBS_TYPHOON: | ||
753 | fe = stv0299_attach(&typhoon_config, | ||
754 | &budget_av->budget.i2c_adap); | ||
713 | break; | 755 | break; |
714 | 756 | ||
715 | case 0x0021: // KNC1 DVB-C Plus budget with AV IN (tda10021/Philips CU1216(tua6034)) | 757 | case SUBID_DVBS_CINERGY1200: |
716 | saa7146_write(budget_av->budget.dev, GPIO_CTRL, 0x50000000); // Enable / PowerON Frontend | 758 | fe = stv0299_attach(&cinergy_1200s_config, |
717 | case 0x0020: // KNC1 DVB-C budget (tda10021/Philips CU1216(tua6034)) | 759 | &budget_av->budget.i2c_adap); |
718 | budget_av->budget.dvb_frontend = | ||
719 | tda10021_attach(&philips_cu1216_config, | ||
720 | &budget_av->budget.i2c_adap, read_pwm(budget_av)); | ||
721 | if (budget_av->budget.dvb_frontend != NULL) { | ||
722 | break; | ||
723 | } | ||
724 | break; | 760 | break; |
725 | 761 | ||
726 | case 0x0031: // KNC1 DVB-T Plus budget with AV IN (tda10046/Philips TU1216(tda6651tt)) | 762 | case SUBID_DVBC_KNC1: |
727 | saa7146_write(budget_av->budget.dev, GPIO_CTRL, 0x50000000); // Enable / PowerON Frontend | 763 | case SUBID_DVBC_KNC1_PLUS: |
728 | case 0x0030: // KNC1 DVB-T budget (tda10046/Philips TU1216(tda6651tt)) | 764 | fe = tda10021_attach(&philips_cu1216_config, |
729 | budget_av->budget.dvb_frontend = | 765 | &budget_av->budget.i2c_adap, |
730 | tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap); | 766 | read_pwm(budget_av)); |
731 | if (budget_av->budget.dvb_frontend != NULL) { | ||
732 | break; | ||
733 | } | ||
734 | break; | 767 | break; |
735 | 768 | ||
736 | case 0x1154: // TerraTec Cinergy 1200 DVB-S (stv0299/Philips SU1278(tsa5059)) | 769 | case SUBID_DVBT_KNC1: |
737 | budget_av->budget.dvb_frontend = | 770 | case SUBID_DVBT_KNC1_PLUS: |
738 | stv0299_attach(&cinergy_1200s_config, &budget_av->budget.i2c_adap); | 771 | fe = tda10046_attach(&philips_tu1216_config, |
739 | if (budget_av->budget.dvb_frontend != NULL) { | 772 | &budget_av->budget.i2c_adap); |
740 | break; | ||
741 | } | ||
742 | break; | 773 | break; |
743 | 774 | ||
744 | case 0x1156: // Terratec Cinergy 1200 DVB-C (tda10021/Philips CU1216(tua6034)) | 775 | case SUBID_DVBC_CINERGY1200: |
745 | budget_av->budget.dvb_frontend = | 776 | fe = tda10021_attach(&philips_cu1216_config, |
746 | tda10021_attach(&philips_cu1216_config, | 777 | &budget_av->budget.i2c_adap, |
747 | &budget_av->budget.i2c_adap, read_pwm(budget_av)); | 778 | read_pwm(budget_av)); |
748 | if (budget_av->budget.dvb_frontend) { | ||
749 | break; | ||
750 | } | ||
751 | break; | 779 | break; |
752 | 780 | ||
753 | case 0x1157: // Terratec Cinergy 1200 DVB-T (tda10046/Philips TU1216(tda6651tt)) | 781 | case SUBID_DVBT_CINERGY1200: |
754 | budget_av->budget.dvb_frontend = | 782 | fe = tda10046_attach(&philips_tu1216_config, |
755 | tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap); | 783 | &budget_av->budget.i2c_adap); |
756 | if (budget_av->budget.dvb_frontend) { | ||
757 | break; | ||
758 | } | ||
759 | break; | 784 | break; |
760 | } | 785 | } |
761 | 786 | ||
762 | if (budget_av->budget.dvb_frontend == NULL) { | 787 | if (fe == NULL) { |
763 | printk("budget_av: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", | 788 | printk(KERN_ERR "budget-av: A frontend driver was not found " |
764 | budget_av->budget.dev->pci->vendor, | 789 | "for device %04x/%04x subsystem %04x/%04x\n", |
765 | budget_av->budget.dev->pci->device, | 790 | saa->pci->vendor, |
766 | budget_av->budget.dev->pci->subsystem_vendor, | 791 | saa->pci->device, |
767 | budget_av->budget.dev->pci->subsystem_device); | 792 | saa->pci->subsystem_vendor, |
768 | } else { | 793 | saa->pci->subsystem_device); |
769 | if (dvb_register_frontend | 794 | return; |
770 | (&budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) { | 795 | } |
771 | printk("budget-av: Frontend registration failed!\n"); | 796 | |
772 | if (budget_av->budget.dvb_frontend->ops->release) | 797 | budget_av->budget.dvb_frontend = fe; |
773 | budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend); | 798 | |
774 | budget_av->budget.dvb_frontend = NULL; | 799 | if (dvb_register_frontend(&budget_av->budget.dvb_adapter, |
775 | } | 800 | budget_av->budget.dvb_frontend)) { |
801 | printk(KERN_ERR "budget-av: Frontend registration failed!\n"); | ||
802 | if (budget_av->budget.dvb_frontend->ops->release) | ||
803 | budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend); | ||
804 | budget_av->budget.dvb_frontend = NULL; | ||
776 | } | 805 | } |
777 | } | 806 | } |
778 | 807 | ||
@@ -829,6 +858,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
829 | 858 | ||
830 | memset(budget_av, 0, sizeof(struct budget_av)); | 859 | memset(budget_av, 0, sizeof(struct budget_av)); |
831 | 860 | ||
861 | budget_av->has_saa7113 = 0; | ||
832 | budget_av->budget.ci_present = 0; | 862 | budget_av->budget.ci_present = 0; |
833 | 863 | ||
834 | dev->ext_priv = budget_av; | 864 | dev->ext_priv = budget_av; |
@@ -843,10 +873,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
843 | saa7146_write(dev, DD1_INIT, 0x07000600); | 873 | saa7146_write(dev, DD1_INIT, 0x07000600); |
844 | saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26); | 874 | saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26); |
845 | 875 | ||
846 | saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI); | 876 | if (saa7113_init(budget_av) == 0) { |
847 | msleep(500); | ||
848 | |||
849 | if (0 == saa7113_init(budget_av)) { | ||
850 | budget_av->has_saa7113 = 1; | 877 | budget_av->has_saa7113 = 1; |
851 | 878 | ||
852 | if (0 != saa7146_vv_init(dev, &vv_data)) { | 879 | if (0 != saa7146_vv_init(dev, &vv_data)) { |
@@ -867,9 +894,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
867 | 894 | ||
868 | saa7113_setinput(budget_av, 0); | 895 | saa7113_setinput(budget_av, 0); |
869 | } else { | 896 | } else { |
870 | budget_av->has_saa7113 = 0; | 897 | ciintf_init(budget_av); |
871 | |||
872 | saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO); | ||
873 | } | 898 | } |
874 | 899 | ||
875 | /* fixme: find some sane values here... */ | 900 | /* fixme: find some sane values here... */ |
@@ -877,11 +902,11 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
877 | 902 | ||
878 | mac = budget_av->budget.dvb_adapter.proposed_mac; | 903 | mac = budget_av->budget.dvb_adapter.proposed_mac; |
879 | if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) { | 904 | if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) { |
880 | printk("KNC1-%d: Could not read MAC from KNC1 card\n", | 905 | printk(KERN_ERR "KNC1-%d: Could not read MAC from KNC1 card\n", |
881 | budget_av->budget.dvb_adapter.num); | 906 | budget_av->budget.dvb_adapter.num); |
882 | memset(mac, 0, 6); | 907 | memset(mac, 0, 6); |
883 | } else { | 908 | } else { |
884 | printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", | 909 | printk(KERN_INFO "KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", |
885 | budget_av->budget.dvb_adapter.num, | 910 | budget_av->budget.dvb_adapter.num, |
886 | mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); | 911 | mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); |
887 | } | 912 | } |
@@ -889,9 +914,6 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio | |||
889 | budget_av->budget.dvb_adapter.priv = budget_av; | 914 | budget_av->budget.dvb_adapter.priv = budget_av; |
890 | frontend_init(budget_av); | 915 | frontend_init(budget_av); |
891 | 916 | ||
892 | if (enable_ci) | ||
893 | ciintf_init(budget_av); | ||
894 | |||
895 | return 0; | 917 | return 0; |
896 | } | 918 | } |
897 | 919 | ||
@@ -1024,5 +1046,3 @@ MODULE_LICENSE("GPL"); | |||
1024 | MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); | 1046 | MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); |
1025 | MODULE_DESCRIPTION("driver for the SAA7146 based so-called " | 1047 | MODULE_DESCRIPTION("driver for the SAA7146 based so-called " |
1026 | "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)"); | 1048 | "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)"); |
1027 | module_param_named(enable_ci, enable_ci, int, 0644); | ||
1028 | MODULE_PARM_DESC(enable_ci, "Turn on/off CI module (default:off)."); | ||