aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorIgor M. Liplianin <liplianin@me.by>2011-05-05 15:35:01 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-05-25 06:51:26 -0400
commit0017505de0d2888f57a9f84e8eb3963b3cd28baf (patch)
tree2d6215b8508a260f86104c771458e3697307994b /drivers/media
parentbc125106f8afe15ffb0aae70d9b72bebec46e519 (diff)
[media] dm1105: GPIO handling added, I2C on GPIO added, LNB control through GPIO reworked
Here is patch for GPIO's handling. It allows to support I2C on GPIO's and per board LNB control through GPIO's. Also incuded some support for Hendrik Skarpeid card. For those, who needs to tweak the driver, I think it is clear how to change and test GPIO's for LNB and other GPIO related stuff now. [mchehab@redhat.com: I2C_CLASS_TV_DIGITAL is deprecated. removed to avoid breaking compilation] Signed-off-by: Igor M. Liplianin <liplianin@me.by> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/dvb/dm1105/dm1105.c272
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
177static unsigned int card[] = {[0 ... 3] = UNSET }; 195static unsigned int card[] = {[0 ... 3] = UNSET };
178module_param_array(card, int, NULL, 0444); 196module_param_array(card, int, NULL, 0444);
@@ -187,7 +205,11 @@ static unsigned int dm1105_devcount;
187DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 205DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
188 206
189struct dm1105_board { 207struct 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
193struct dm1105_subid { 215struct dm1105_subid {
@@ -199,15 +221,50 @@ struct dm1105_subid {
199static const struct dm1105_board dm1105_boards[] = { 221static 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 */
394static 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
404static 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
414static 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
424static 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
435static 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
447static 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
457static 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
464static 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
471static 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
479static 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
331static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, 487static 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)
436static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) 592static 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);
953err_dvb_unregister_adapter: 1151err_dvb_unregister_adapter:
954 dvb_unregister_adapter(dvb_adapter); 1152 dvb_unregister_adapter(dvb_adapter);
1153err_i2c_del_adapters:
1154 i2c_del_adapter(&dev->i2c_bb_adap);
955err_i2c_del_adapter: 1155err_i2c_del_adapter:
956 i2c_del_adapter(&dev->i2c_adap); 1156 i2c_del_adapter(&dev->i2c_adap);
957err_dm1105_hw_exit: 1157err_dm1105_hw_exit: