diff options
-rw-r--r-- | drivers/media/dvb/dm1105/dm1105.c | 272 |
1 files changed, 236 insertions, 36 deletions
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 2d8b4044be36..b2b0c45f32a9 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
23 | #include <linux/i2c-algo-bit.h> | ||
23 | #include <linux/init.h> | 24 | #include <linux/init.h> |
24 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
@@ -49,11 +50,12 @@ | |||
49 | 50 | ||
50 | #define UNSET (-1U) | 51 | #define UNSET (-1U) |
51 | 52 | ||
52 | #define DM1105_BOARD_NOAUTO UNSET | 53 | #define DM1105_BOARD_NOAUTO UNSET |
53 | #define DM1105_BOARD_UNKNOWN 0 | 54 | #define DM1105_BOARD_UNKNOWN 0 |
54 | #define DM1105_BOARD_DVBWORLD_2002 1 | 55 | #define DM1105_BOARD_DVBWORLD_2002 1 |
55 | #define DM1105_BOARD_DVBWORLD_2004 2 | 56 | #define DM1105_BOARD_DVBWORLD_2004 2 |
56 | #define DM1105_BOARD_AXESS_DM05 3 | 57 | #define DM1105_BOARD_AXESS_DM05 3 |
58 | #define DM1105_BOARD_UNBRANDED_I2C_ON_GPIO 4 | ||
57 | 59 | ||
58 | /* ----------------------------------------------- */ | 60 | /* ----------------------------------------------- */ |
59 | /* | 61 | /* |
@@ -157,22 +159,38 @@ | |||
157 | #define DM1105_MAX 0x04 | 159 | #define DM1105_MAX 0x04 |
158 | 160 | ||
159 | #define DRIVER_NAME "dm1105" | 161 | #define DRIVER_NAME "dm1105" |
162 | #define DM1105_I2C_GPIO_NAME "dm1105-gpio" | ||
160 | 163 | ||
161 | #define DM1105_DMA_PACKETS 47 | 164 | #define DM1105_DMA_PACKETS 47 |
162 | #define DM1105_DMA_PACKET_LENGTH (128*4) | 165 | #define DM1105_DMA_PACKET_LENGTH (128*4) |
163 | #define DM1105_DMA_BYTES (128 * 4 * DM1105_DMA_PACKETS) | 166 | #define DM1105_DMA_BYTES (128 * 4 * DM1105_DMA_PACKETS) |
164 | 167 | ||
168 | /* */ | ||
169 | #define GPIO08 (1 << 8) | ||
170 | #define GPIO13 (1 << 13) | ||
171 | #define GPIO14 (1 << 14) | ||
172 | #define GPIO15 (1 << 15) | ||
173 | #define GPIO16 (1 << 16) | ||
174 | #define GPIO17 (1 << 17) | ||
175 | #define GPIO_ALL 0x03ffff | ||
176 | |||
165 | /* GPIO's for LNB power control */ | 177 | /* GPIO's for LNB power control */ |
166 | #define DM1105_LNB_MASK 0x00000000 | 178 | #define DM1105_LNB_MASK (GPIO_ALL & ~(GPIO14 | GPIO13)) |
167 | #define DM1105_LNB_OFF 0x00020000 | 179 | #define DM1105_LNB_OFF GPIO17 |
168 | #define DM1105_LNB_13V 0x00010100 | 180 | #define DM1105_LNB_13V (GPIO16 | GPIO08) |
169 | #define DM1105_LNB_18V 0x00000100 | 181 | #define DM1105_LNB_18V GPIO08 |
170 | 182 | ||
171 | /* GPIO's for LNB power control for Axess DM05 */ | 183 | /* GPIO's for LNB power control for Axess DM05 */ |
172 | #define DM05_LNB_MASK 0x00000000 | 184 | #define DM05_LNB_MASK (GPIO_ALL & ~(GPIO14 | GPIO13)) |
173 | #define DM05_LNB_OFF 0x00020000/* actually 13v */ | 185 | #define DM05_LNB_OFF GPIO17/* actually 13v */ |
174 | #define DM05_LNB_13V 0x00020000 | 186 | #define DM05_LNB_13V GPIO17 |
175 | #define DM05_LNB_18V 0x00030000 | 187 | #define DM05_LNB_18V (GPIO17 | GPIO16) |
188 | |||
189 | /* GPIO's for LNB power control for unbranded with I2C on GPIO */ | ||
190 | #define UNBR_LNB_MASK (GPIO17 | GPIO16) | ||
191 | #define UNBR_LNB_OFF 0 | ||
192 | #define UNBR_LNB_13V GPIO17 | ||
193 | #define UNBR_LNB_18V (GPIO17 | GPIO16) | ||
176 | 194 | ||
177 | static unsigned int card[] = {[0 ... 3] = UNSET }; | 195 | static unsigned int card[] = {[0 ... 3] = UNSET }; |
178 | module_param_array(card, int, NULL, 0444); | 196 | module_param_array(card, int, NULL, 0444); |
@@ -187,7 +205,11 @@ static unsigned int dm1105_devcount; | |||
187 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 205 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
188 | 206 | ||
189 | struct dm1105_board { | 207 | struct dm1105_board { |
190 | char *name; | 208 | char *name; |
209 | struct { | ||
210 | u32 mask, off, v13, v18; | ||
211 | } lnb; | ||
212 | u32 gpio_scl, gpio_sda; | ||
191 | }; | 213 | }; |
192 | 214 | ||
193 | struct dm1105_subid { | 215 | struct dm1105_subid { |
@@ -199,15 +221,50 @@ struct dm1105_subid { | |||
199 | static const struct dm1105_board dm1105_boards[] = { | 221 | static const struct dm1105_board dm1105_boards[] = { |
200 | [DM1105_BOARD_UNKNOWN] = { | 222 | [DM1105_BOARD_UNKNOWN] = { |
201 | .name = "UNKNOWN/GENERIC", | 223 | .name = "UNKNOWN/GENERIC", |
224 | .lnb = { | ||
225 | .mask = DM1105_LNB_MASK, | ||
226 | .off = DM1105_LNB_OFF, | ||
227 | .v13 = DM1105_LNB_13V, | ||
228 | .v18 = DM1105_LNB_18V, | ||
229 | }, | ||
202 | }, | 230 | }, |
203 | [DM1105_BOARD_DVBWORLD_2002] = { | 231 | [DM1105_BOARD_DVBWORLD_2002] = { |
204 | .name = "DVBWorld PCI 2002", | 232 | .name = "DVBWorld PCI 2002", |
233 | .lnb = { | ||
234 | .mask = DM1105_LNB_MASK, | ||
235 | .off = DM1105_LNB_OFF, | ||
236 | .v13 = DM1105_LNB_13V, | ||
237 | .v18 = DM1105_LNB_18V, | ||
238 | }, | ||
205 | }, | 239 | }, |
206 | [DM1105_BOARD_DVBWORLD_2004] = { | 240 | [DM1105_BOARD_DVBWORLD_2004] = { |
207 | .name = "DVBWorld PCI 2004", | 241 | .name = "DVBWorld PCI 2004", |
242 | .lnb = { | ||
243 | .mask = DM1105_LNB_MASK, | ||
244 | .off = DM1105_LNB_OFF, | ||
245 | .v13 = DM1105_LNB_13V, | ||
246 | .v18 = DM1105_LNB_18V, | ||
247 | }, | ||
208 | }, | 248 | }, |
209 | [DM1105_BOARD_AXESS_DM05] = { | 249 | [DM1105_BOARD_AXESS_DM05] = { |
210 | .name = "Axess/EasyTv DM05", | 250 | .name = "Axess/EasyTv DM05", |
251 | .lnb = { | ||
252 | .mask = DM05_LNB_MASK, | ||
253 | .off = DM05_LNB_OFF, | ||
254 | .v13 = DM05_LNB_13V, | ||
255 | .v18 = DM05_LNB_18V, | ||
256 | }, | ||
257 | }, | ||
258 | [DM1105_BOARD_UNBRANDED_I2C_ON_GPIO] = { | ||
259 | .name = "Unbranded DM1105 with i2c on GPIOs", | ||
260 | .lnb = { | ||
261 | .mask = UNBR_LNB_MASK, | ||
262 | .off = UNBR_LNB_OFF, | ||
263 | .v13 = UNBR_LNB_13V, | ||
264 | .v18 = UNBR_LNB_18V, | ||
265 | }, | ||
266 | .gpio_scl = GPIO14, | ||
267 | .gpio_sda = GPIO13, | ||
211 | }, | 268 | }, |
212 | }; | 269 | }; |
213 | 270 | ||
@@ -293,6 +350,8 @@ struct dm1105_dev { | |||
293 | 350 | ||
294 | /* i2c */ | 351 | /* i2c */ |
295 | struct i2c_adapter i2c_adap; | 352 | struct i2c_adapter i2c_adap; |
353 | struct i2c_adapter i2c_bb_adap; | ||
354 | struct i2c_algo_bit_data i2c_bit; | ||
296 | 355 | ||
297 | /* irq */ | 356 | /* irq */ |
298 | struct work_struct work; | 357 | struct work_struct work; |
@@ -328,6 +387,103 @@ struct dm1105_dev { | |||
328 | #define dm_setl(reg, bit) dm_andorl((reg), (bit), (bit)) | 387 | #define dm_setl(reg, bit) dm_andorl((reg), (bit), (bit)) |
329 | #define dm_clearl(reg, bit) dm_andorl((reg), (bit), 0) | 388 | #define dm_clearl(reg, bit) dm_andorl((reg), (bit), 0) |
330 | 389 | ||
390 | /* The chip has 18 GPIOs. In HOST mode GPIO's used as 15 bit address lines, | ||
391 | so we can use only 3 GPIO's from GPIO15 to GPIO17. | ||
392 | Here I don't check whether HOST is enebled as it is not implemented yet. | ||
393 | */ | ||
394 | static void dm1105_gpio_set(struct dm1105_dev *dev, u32 mask) | ||
395 | { | ||
396 | if (mask & 0xfffc0000) | ||
397 | printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); | ||
398 | |||
399 | if (mask & 0x0003ffff) | ||
400 | dm_setl(DM1105_GPIOVAL, mask & 0x0003ffff); | ||
401 | |||
402 | } | ||
403 | |||
404 | static void dm1105_gpio_clear(struct dm1105_dev *dev, u32 mask) | ||
405 | { | ||
406 | if (mask & 0xfffc0000) | ||
407 | printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); | ||
408 | |||
409 | if (mask & 0x0003ffff) | ||
410 | dm_clearl(DM1105_GPIOVAL, mask & 0x0003ffff); | ||
411 | |||
412 | } | ||
413 | |||
414 | static void dm1105_gpio_andor(struct dm1105_dev *dev, u32 mask, u32 val) | ||
415 | { | ||
416 | if (mask & 0xfffc0000) | ||
417 | printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); | ||
418 | |||
419 | if (mask & 0x0003ffff) | ||
420 | dm_andorl(DM1105_GPIOVAL, mask & 0x0003ffff, val); | ||
421 | |||
422 | } | ||
423 | |||
424 | static u32 dm1105_gpio_get(struct dm1105_dev *dev, u32 mask) | ||
425 | { | ||
426 | if (mask & 0xfffc0000) | ||
427 | printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); | ||
428 | |||
429 | if (mask & 0x0003ffff) | ||
430 | return dm_readl(DM1105_GPIOVAL) & mask & 0x0003ffff; | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static void dm1105_gpio_enable(struct dm1105_dev *dev, u32 mask, int asoutput) | ||
436 | { | ||
437 | if (mask & 0xfffc0000) | ||
438 | printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__); | ||
439 | |||
440 | if ((mask & 0x0003ffff) && asoutput) | ||
441 | dm_clearl(DM1105_GPIOCTR, mask & 0x0003ffff); | ||
442 | else if ((mask & 0x0003ffff) && !asoutput) | ||
443 | dm_setl(DM1105_GPIOCTR, mask & 0x0003ffff); | ||
444 | |||
445 | } | ||
446 | |||
447 | static void dm1105_setline(struct dm1105_dev *dev, u32 line, int state) | ||
448 | { | ||
449 | if (state) | ||
450 | dm1105_gpio_enable(dev, line, 0); | ||
451 | else { | ||
452 | dm1105_gpio_enable(dev, line, 1); | ||
453 | dm1105_gpio_clear(dev, line); | ||
454 | } | ||
455 | } | ||
456 | |||
457 | static void dm1105_setsda(void *data, int state) | ||
458 | { | ||
459 | struct dm1105_dev *dev = data; | ||
460 | |||
461 | dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_sda, state); | ||
462 | } | ||
463 | |||
464 | static void dm1105_setscl(void *data, int state) | ||
465 | { | ||
466 | struct dm1105_dev *dev = data; | ||
467 | |||
468 | dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_scl, state); | ||
469 | } | ||
470 | |||
471 | static int dm1105_getsda(void *data) | ||
472 | { | ||
473 | struct dm1105_dev *dev = data; | ||
474 | |||
475 | return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_sda) | ||
476 | ? 1 : 0; | ||
477 | } | ||
478 | |||
479 | static int dm1105_getscl(void *data) | ||
480 | { | ||
481 | struct dm1105_dev *dev = data; | ||
482 | |||
483 | return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_scl) | ||
484 | ? 1 : 0; | ||
485 | } | ||
486 | |||
331 | static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, | 487 | static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, |
332 | struct i2c_msg *msgs, int num) | 488 | struct i2c_msg *msgs, int num) |
333 | { | 489 | { |
@@ -436,31 +592,20 @@ static inline struct dm1105_dev *frontend_to_dm1105_dev(struct dvb_frontend *fe) | |||
436 | static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | 592 | static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) |
437 | { | 593 | { |
438 | struct dm1105_dev *dev = frontend_to_dm1105_dev(fe); | 594 | struct dm1105_dev *dev = frontend_to_dm1105_dev(fe); |
439 | u32 lnb_mask, lnb_13v, lnb_18v, lnb_off; | ||
440 | 595 | ||
441 | switch (dev->boardnr) { | 596 | dm1105_gpio_enable(dev, dm1105_boards[dev->boardnr].lnb.mask, 1); |
442 | case DM1105_BOARD_AXESS_DM05: | ||
443 | lnb_mask = DM05_LNB_MASK; | ||
444 | lnb_off = DM05_LNB_OFF; | ||
445 | lnb_13v = DM05_LNB_13V; | ||
446 | lnb_18v = DM05_LNB_18V; | ||
447 | break; | ||
448 | case DM1105_BOARD_DVBWORLD_2002: | ||
449 | case DM1105_BOARD_DVBWORLD_2004: | ||
450 | default: | ||
451 | lnb_mask = DM1105_LNB_MASK; | ||
452 | lnb_off = DM1105_LNB_OFF; | ||
453 | lnb_13v = DM1105_LNB_13V; | ||
454 | lnb_18v = DM1105_LNB_18V; | ||
455 | } | ||
456 | |||
457 | dm_writel(DM1105_GPIOCTR, lnb_mask); | ||
458 | if (voltage == SEC_VOLTAGE_18) | 597 | if (voltage == SEC_VOLTAGE_18) |
459 | dm_writel(DM1105_GPIOVAL, lnb_18v); | 598 | dm1105_gpio_andor(dev, |
599 | dm1105_boards[dev->boardnr].lnb.mask, | ||
600 | dm1105_boards[dev->boardnr].lnb.v18); | ||
460 | else if (voltage == SEC_VOLTAGE_13) | 601 | else if (voltage == SEC_VOLTAGE_13) |
461 | dm_writel(DM1105_GPIOVAL, lnb_13v); | 602 | dm1105_gpio_andor(dev, |
603 | dm1105_boards[dev->boardnr].lnb.mask, | ||
604 | dm1105_boards[dev->boardnr].lnb.v13); | ||
462 | else | 605 | else |
463 | dm_writel(DM1105_GPIOVAL, lnb_off); | 606 | dm1105_gpio_andor(dev, |
607 | dm1105_boards[dev->boardnr].lnb.mask, | ||
608 | dm1105_boards[dev->boardnr].lnb.off); | ||
464 | 609 | ||
465 | return 0; | 610 | return 0; |
466 | } | 611 | } |
@@ -708,6 +853,38 @@ static int __devinit frontend_init(struct dm1105_dev *dev) | |||
708 | int ret; | 853 | int ret; |
709 | 854 | ||
710 | switch (dev->boardnr) { | 855 | switch (dev->boardnr) { |
856 | case DM1105_BOARD_UNBRANDED_I2C_ON_GPIO: | ||
857 | dm1105_gpio_enable(dev, GPIO15, 1); | ||
858 | dm1105_gpio_clear(dev, GPIO15); | ||
859 | msleep(100); | ||
860 | dm1105_gpio_set(dev, GPIO15); | ||
861 | msleep(200); | ||
862 | dev->fe = dvb_attach( | ||
863 | stv0299_attach, &sharp_z0194a_config, | ||
864 | &dev->i2c_bb_adap); | ||
865 | if (dev->fe) { | ||
866 | dev->fe->ops.set_voltage = dm1105_set_voltage; | ||
867 | dvb_attach(dvb_pll_attach, dev->fe, 0x60, | ||
868 | &dev->i2c_bb_adap, DVB_PLL_OPERA1); | ||
869 | break; | ||
870 | } | ||
871 | |||
872 | dev->fe = dvb_attach( | ||
873 | stv0288_attach, &earda_config, | ||
874 | &dev->i2c_bb_adap); | ||
875 | if (dev->fe) { | ||
876 | dev->fe->ops.set_voltage = dm1105_set_voltage; | ||
877 | dvb_attach(stb6000_attach, dev->fe, 0x61, | ||
878 | &dev->i2c_bb_adap); | ||
879 | break; | ||
880 | } | ||
881 | |||
882 | dev->fe = dvb_attach( | ||
883 | si21xx_attach, &serit_config, | ||
884 | &dev->i2c_bb_adap); | ||
885 | if (dev->fe) | ||
886 | dev->fe->ops.set_voltage = dm1105_set_voltage; | ||
887 | break; | ||
711 | case DM1105_BOARD_DVBWORLD_2004: | 888 | case DM1105_BOARD_DVBWORLD_2004: |
712 | dev->fe = dvb_attach( | 889 | dev->fe = dvb_attach( |
713 | cx24116_attach, &serit_sp2633_config, | 890 | cx24116_attach, &serit_sp2633_config, |
@@ -870,11 +1047,32 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, | |||
870 | if (ret < 0) | 1047 | if (ret < 0) |
871 | goto err_dm1105_hw_exit; | 1048 | goto err_dm1105_hw_exit; |
872 | 1049 | ||
1050 | i2c_set_adapdata(&dev->i2c_bb_adap, dev); | ||
1051 | strcpy(dev->i2c_bb_adap.name, DM1105_I2C_GPIO_NAME); | ||
1052 | dev->i2c_bb_adap.owner = THIS_MODULE; | ||
1053 | dev->i2c_bb_adap.dev.parent = &pdev->dev; | ||
1054 | dev->i2c_bb_adap.algo_data = &dev->i2c_bit; | ||
1055 | dev->i2c_bit.data = dev; | ||
1056 | dev->i2c_bit.setsda = dm1105_setsda; | ||
1057 | dev->i2c_bit.setscl = dm1105_setscl; | ||
1058 | dev->i2c_bit.getsda = dm1105_getsda; | ||
1059 | dev->i2c_bit.getscl = dm1105_getscl; | ||
1060 | dev->i2c_bit.udelay = 10; | ||
1061 | dev->i2c_bit.timeout = 10; | ||
1062 | |||
1063 | /* Raise SCL and SDA */ | ||
1064 | dm1105_setsda(dev, 1); | ||
1065 | dm1105_setscl(dev, 1); | ||
1066 | |||
1067 | ret = i2c_bit_add_bus(&dev->i2c_bb_adap); | ||
1068 | if (ret < 0) | ||
1069 | goto err_i2c_del_adapter; | ||
1070 | |||
873 | /* dvb */ | 1071 | /* dvb */ |
874 | ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME, | 1072 | ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME, |
875 | THIS_MODULE, &pdev->dev, adapter_nr); | 1073 | THIS_MODULE, &pdev->dev, adapter_nr); |
876 | if (ret < 0) | 1074 | if (ret < 0) |
877 | goto err_i2c_del_adapter; | 1075 | goto err_i2c_del_adapters; |
878 | 1076 | ||
879 | dvb_adapter = &dev->dvb_adapter; | 1077 | dvb_adapter = &dev->dvb_adapter; |
880 | 1078 | ||
@@ -952,6 +1150,8 @@ err_dvb_dmx_release: | |||
952 | dvb_dmx_release(dvbdemux); | 1150 | dvb_dmx_release(dvbdemux); |
953 | err_dvb_unregister_adapter: | 1151 | err_dvb_unregister_adapter: |
954 | dvb_unregister_adapter(dvb_adapter); | 1152 | dvb_unregister_adapter(dvb_adapter); |
1153 | err_i2c_del_adapters: | ||
1154 | i2c_del_adapter(&dev->i2c_bb_adap); | ||
955 | err_i2c_del_adapter: | 1155 | err_i2c_del_adapter: |
956 | i2c_del_adapter(&dev->i2c_adap); | 1156 | i2c_del_adapter(&dev->i2c_adap); |
957 | err_dm1105_hw_exit: | 1157 | err_dm1105_hw_exit: |