diff options
Diffstat (limited to 'linux/drivers/media/dvb/ttpci-budget/budget-av.c')
-rw-r--r-- | linux/drivers/media/dvb/ttpci-budget/budget-av.c | 302 |
1 files changed, 160 insertions, 142 deletions
diff --git a/linux/drivers/media/dvb/ttpci-budget/budget-av.c b/linux/drivers/media/dvb/ttpci-budget/budget-av.c index 78c977900..66173a760 100644 --- a/linux/drivers/media/dvb/ttpci-budget/budget-av.c +++ b/linux/drivers/media/dvb/ttpci-budget/budget-av.c @@ -37,23 +37,10 @@ #define KBUILD_MODNAME budget_av #endif -static struct saa7146_extension budget_extension; - -MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1); -static -struct pci_device_id devices[] = { - MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56), - { - .vendor = 0, - } -}; - -struct budget_av_data -{ +struct budget_av { + struct budget budget; struct video_device vd; - int registered; - int cur_input; }; @@ -61,32 +48,36 @@ struct budget_av_data * INITIALIZATION ****************************************************************************/ -static inline void ddelay(int i) +static inline +void ddelay(int i) { current->state=TASK_INTERRUPTIBLE; schedule_timeout((HZ*i)/100); } -static inline u8 -i2c_readreg(struct dvb_i2c_bus *i2c, u8 id, u8 reg) + +static +u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg) { - u8 mm1[] = {0x00}; - u8 mm2[] = {0x00}; - struct i2c_msg msgs[2]; - - msgs[0].flags=0; - msgs[1].flags=I2C_M_RD; - msgs[0].addr=msgs[1].addr=id/2; - mm1[0]=reg; - msgs[0].len=1; msgs[1].len=1; - msgs[0].buf=mm1; msgs[1].buf=mm2; - i2c->xfer(i2c, msgs, 2); - - return mm2[0]; + u8 mm1[] = {0x00}; + u8 mm2[] = {0x00}; + struct i2c_msg msgs[2]; + + msgs[0].flags = 0; + msgs[1].flags = I2C_M_RD; + msgs[0].addr = msgs[1].addr=id/2; + mm1[0] = reg; + msgs[0].len = 1; msgs[1].len = 1; + msgs[0].buf = mm1; msgs[1].buf = mm2; + + i2c->xfer(i2c, msgs, 2); + + return mm2[0]; } -static inline int -i2c_writereg(struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) + +static +int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) { u8 msg[2]={ reg, val }; struct i2c_msg msgs; @@ -98,7 +89,9 @@ i2c_writereg(struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) return i2c->xfer (i2c, &msgs, 1); } -static const u8 saa7113_tab[] = { + +static const +u8 saa7113_tab[] = { 0x01, 0x08, 0x02, 0xc0, 0x03, 0x33, @@ -127,109 +120,128 @@ static const u8 saa7113_tab[] = { 0xff }; -static int -init_saa7113(struct budget_s *budget) + +static +int saa7113_init (struct budget_av *budget_av) { - const u8 *data=saa7113_tab; + struct budget *budget = &budget_av->budget; + const u8 *data = saa7113_tab; - if (i2c_writereg(budget->i2c_bus, 0x4a, 0x01, 0x08)!=1) { + if (i2c_writereg (budget->i2c_bus, 0x4a, 0x01, 0x08) != 1) { DEB_D(("saa7113: not found on KNC card\n")); - return -1; + return -ENODEV; } + INFO(("saa7113: detected and initializing\n")); - while (*data!=0xff) { + + while (*data != 0xff) { i2c_writereg(budget->i2c_bus, 0x4a, *data, *(data+1)); - data+=2; + data += 2; } - DEB_D(("saa7113: status=%02x\n", i2c_readreg(budget->i2c_bus, 0x4a, 0x1f))); + + DEB_D(("saa7113: status=%02x\n", + i2c_readreg(budget->i2c_bus, 0x4a, 0x1f))); + + return 0; +} + + +static +int saa7113_setinput (struct budget_av *budget_av, int input) +{ + struct budget *budget = &budget_av->budget; + + if (input == 1) { + i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc7); + i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x80); + } else if (input == 0) { + i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc0); + i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x00); + } else + return -EINVAL; + + budget_av->cur_input = input; return 0; } + static -int av_detach(struct saa7146_dev* dev) +int budget_av_detach (struct saa7146_dev *dev) { - struct budget_s *budget = (struct budget_s*)dev->ext_priv; - struct budget_av_data *data = budget->priv; + struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; + int err; DEB_EE(("dev: %p\n",dev)); + saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO); + ddelay(20); - if( 0 != data->registered ) { - saa7146_unregister_device(&data->vd,dev); - data->registered = 0; - } - if( NULL != budget->priv ) { - kfree(data); - budget->priv = NULL; - - } - - return budget_detach(dev); -} + saa7146_unregister_device (&budget_av->vd, dev); -void knc1_setinput(struct budget_s *budget, int i) -{ - if (i) { - i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc7); - i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x80); - } else { - i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc0); - i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x00); - } + err = ttpci_budget_deinit (&budget_av->budget); + + kfree (budget_av); + + return err; } + static -int av_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) +int budget_av_attach (struct saa7146_dev* dev, + struct saa7146_pci_extension_data *info) { - struct budget_s *budget = NULL; - struct budget_av_data *data = NULL; + struct budget_av *budget_av; struct budget_info *bi = info->ext_priv; - + int err; + DEB_EE(("dev: %p\n",dev)); - if (bi->type != BUDGET_KNC1) { - return -1; + + if (bi->type != BUDGET_KNC1) { + return -ENODEV; } - data = kmalloc(sizeof(struct budget_av_data), GFP_KERNEL); - if( NULL == data ) { + if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL))) return -ENOMEM; + + memset(budget_av, 0, sizeof(struct budget_av)); + + if ((err = ttpci_budget_init(&budget_av->budget, dev, info))) { + kfree(budget_av); + return err; } - memset(data,0,sizeof(*data)); - - if( 0 != budget_attach(dev,info)) { - kfree(data); - return -1; - } - budget = (struct budget_s*)dev->ext_priv; - budget->priv = data; - + + dev->ext_priv = budget_av; + /* knc1 initialization */ saa7146_write(dev, DD1_STREAM_B, 0x04000000); saa7146_write(dev, DD1_INIT, 0x07000600); - saa7146_write(dev, MC2, - MASK_09 | MASK_25 | MASK_10 | MASK_26); + saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26); //test_knc_ci(av7110); saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI); ddelay(50); - if( 0 != init_saa7113(budget)) { - av_detach(dev); - return -1; + + if ((err = saa7113_init (budget_av))) { + budget_av_detach(dev); + return err; } - + saa7146_vv_init(dev); - if( 0 != saa7146_register_device(&data->vd, dev, "knc1", VFL_TYPE_GRABBER)) { + if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", + VFL_TYPE_GRABBER))) + { ERR(("cannot register capture v4l2 device.\n")); - av_detach(dev); - return -1; + budget_av_detach(dev); + return err; } - data->registered = 1; - + /* beware: this modifies dev->vv ... */ - saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A); - knc1_setinput(budget, 0); + saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A, + SAA7146_HPS_SYNC_PORT_A); + + saa7113_setinput (budget_av, 0); /* what is this? since we don't support open()/close() notifications, we simply put this into the release handler... */ @@ -239,30 +251,31 @@ int av_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) /* fixme: find some sane values here... */ saa7146_write(dev, PCI_BT_V1, 0x1c00101f); - // FIXME: cope with error here! - budget_register(budget); - printk(KERN_INFO "budget-av: found budget card w/ video-in '%s'.\n",budget->card->name); - return 0; } + + #define KNC1_INPUTS 2 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = { - { 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, - { 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, }; -static struct saa7146_extension_ioctls ioctls[] = { + +static +struct saa7146_extension_ioctls ioctls[] = { { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, { 0, 0 } }; -static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) + +static +int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) { - struct budget_s *budget = (struct budget_s*)dev->ext_priv; - struct budget_av_data *data = budget->priv; + struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; /* struct saa7146_vv *vv = dev->vv_data; */ @@ -275,18 +288,14 @@ static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) if( i->index < 0 || i->index >= KNC1_INPUTS) { return -EINVAL; } - if( BUDGET_KNC1 == budget->card->type ) { - memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); - } else { - return -EINVAL; - } - + memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input)); return 0; } case VIDIOC_G_INPUT: { int *input = (int *)arg; - *input = data->cur_input; + + *input = budget_av->cur_input; DEB_EE(("VIDIOC_G_INPUT %d.\n",*input)); return 0; @@ -294,22 +303,8 @@ static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) case VIDIOC_S_INPUT: { int input = *(int *)arg; - - DEB_EE(("VIDIOC_S_INPUT %d.\n",input)); - - if (input < 0 || input > 1) { - return -EINVAL; - } - - if( BUDGET_KNC1 == budget->card->type ) { - knc1_setinput(budget, input); - } else { - return -EINVAL; - } - - data->cur_input = input; - - return 0; + DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); + return saa7113_setinput (budget_av, input); } default: /* @@ -320,11 +315,13 @@ static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) return 0; } -static struct saa7146_standard standard[] = { +static +struct saa7146_standard standard[] = { { "PAL", V4L2_STD_PAL, SAA7146_PAL_VALUES }, { "NTSC", V4L2_STD_NTSC, SAA7146_NTSC_VALUES }, }; + static struct saa7146_ext_vv vv_data = { .inputs = 2, @@ -336,21 +333,41 @@ struct saa7146_ext_vv vv_data = { .ioctl = av_ioctl, }; + + +static struct saa7146_extension budget_extension; + + +MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1); + +static +struct pci_device_id pci_tbl [] = { + MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56), + { + .vendor = 0, + } +}; + + + static struct saa7146_extension budget_extension = { .name = "budget dvb /w video in\0", - .pci_tbl = &devices[0], + .pci_tbl = pci_tbl, + .module = THIS_MODULE, + .attach = budget_av_attach, + .detach = budget_av_detach, + .ext_vv_data = &vv_data, - .attach = av_attach, - .detach = av_detach, - .irq_mask = MASK_07, - .irq_func = budget_irq, + + .irq_mask = MASK_10, + .irq_func = ttpci_budget_irq10_handler, }; static -int __init budget_init(void) +int __init budget_av_init(void) { DEB_EE((".\n")); @@ -362,16 +379,17 @@ int __init budget_init(void) static -void __exit budget_exit(void) +void __exit budget_av_exit(void) { DEB_EE((".\n")); saa7146_unregister_extension(&budget_extension); } -module_init(budget_init); -module_exit(budget_exit); +module_init(budget_av_init); +module_exit(budget_av_exit); -MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB cards by " - "Siemens, Technotrend, Hauppauge"); -MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others"); MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others"); +MODULE_DESCRIPTION("driver for the SAA7146 based so-called " + "budget PCI DVB w/ analog input (e.g. the KNC cards)"); + |