aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c216
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
62static 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[] = {
361static int saa7113_init(struct budget_av *budget_av) 378static 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
701static void frontend_init(struct budget_av *budget_av) 734static 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");
1024MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); 1046MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
1025MODULE_DESCRIPTION("driver for the SAA7146 based so-called " 1047MODULE_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)");
1027module_param_named(enable_ci, enable_ci, int, 0644);
1028MODULE_PARM_DESC(enable_ci, "Turn on/off CI module (default:off).");