From c95c4ad7e1adade38d71962379f194434b44c1bd Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 19 Jun 2009 13:13:55 +0200 Subject: libv4l: add various laptop models to the upside down devices table From: Hans de Goede libv4l: add various laptop models to the upside down devices table Priority: normal Signed-off-by: Hans de Goede --- .../libv4l/libv4lconvert/control/libv4lcontrol.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 4e600351b..eae1438e1 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -57,9 +57,24 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { /* Genius E-M 112 (also want whitebalance by default) */ { 0x093a, 0x2476, 0, NULL, NULL, V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED|V4LCONTROL_WANTS_WB, 1500 }, - /* Asus N50Vn laptop */ - { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vn ", + /* Laptops */ + { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vn ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "F7SR ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "W7S ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "X55SV ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "N20A ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Sr ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1S ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G2S ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + /* Second: devices which should use some software processing by default */ /* Pac207 based devices */ { 0x041e, 0x4028, 0, NULL, NULL, V4LCONTROL_WANTS_WB, 1500 }, -- cgit v1.2.3 From 78b537e32fbc1e45a9d5fe1086c4e6c303661e53 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 10 Aug 2009 07:49:08 +0200 Subject: v4l: simplify v4l2_i2c_new_subdev and friends From: Hans Verkuil Rewrite v4l2_i2c_new_subdev as a simplified version of v4l2_i2c_new_subdev_cfg and remove v4l2_i2c_new_probed_subdev and v4l2_i2c_new_probed_subdev_addr. This simplifies this API substantially. Priority: normal Signed-off-by: Hans Verkuil --- linux/Documentation/video4linux/v4l2-framework.txt | 16 +-- linux/drivers/media/video/au0828/au0828-cards.c | 4 +- linux/drivers/media/video/bt8xx/bttv-cards.c | 44 +++--- linux/drivers/media/video/cafe_ccic.c | 2 +- linux/drivers/media/video/cx18/cx18-i2c.c | 14 +- linux/drivers/media/video/cx231xx/cx231xx-cards.c | 4 +- linux/drivers/media/video/cx23885/cx23885-cards.c | 2 +- linux/drivers/media/video/cx23885/cx23885-video.c | 6 +- linux/drivers/media/video/cx88/cx88-cards.c | 14 +- linux/drivers/media/video/cx88/cx88-video.c | 6 +- linux/drivers/media/video/davinci/vpif_display.c | 4 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 34 ++--- linux/drivers/media/video/ivtv/ivtv-i2c.c | 18 +-- linux/drivers/media/video/mxb.c | 14 +- linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c | 10 +- linux/drivers/media/video/saa7134/saa7134-cards.c | 12 +- linux/drivers/media/video/saa7134/saa7134-core.c | 6 +- .../drivers/media/video/usbvision/usbvision-i2c.c | 12 +- linux/drivers/media/video/v4l2-common.c | 157 --------------------- linux/drivers/media/video/vino.c | 8 +- linux/drivers/media/video/w9968cf.c | 4 +- linux/drivers/media/video/zoran/zoran_card.c | 8 +- linux/include/media/v4l2-common.h | 24 ++-- 23 files changed, 128 insertions(+), 295 deletions(-) diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index ba4706afc..e395a9cdc 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -370,19 +370,20 @@ from the remove() callback ensures that this is always done correctly. The bridge driver also has some helper functions it can use: struct v4l2_subdev *sd = v4l2_i2c_new_subdev(v4l2_dev, adapter, - "module_foo", "chipid", 0x36); + "module_foo", "chipid", 0x36, NULL); This loads the given module (can be NULL if no module needs to be loaded) and calls i2c_new_device() with the given i2c_adapter and chip/address arguments. If all goes well, then it registers the subdev with the v4l2_device. -You can also use v4l2_i2c_new_probed_subdev() which is very similar to -v4l2_i2c_new_subdev(), except that it has an array of possible I2C addresses -that it should probe. Internally it calls i2c_new_probed_device(). +You can also use the last argument of v4l2_i2c_new_subdev() to pass an array +of possible I2C addresses that it should probe. These probe addresses are +only used if the previous argument is 0. A non-zero argument means that you +know the exact i2c address so in that case no probing will take place. Both functions return NULL if something went wrong. -Note that the chipid you pass to v4l2_i2c_new_(probed_)subdev() is usually +Note that the chipid you pass to v4l2_i2c_new_subdev() is usually the same as the module name. It allows you to specify a chip variant, e.g. "saa7114" or "saa7115". In general though the i2c driver autodetects this. The use of chipid is something that needs to be looked at more closely at a @@ -410,11 +411,6 @@ the irq and platform_data arguments after the subdev was setup. The older v4l2_i2c_new_(probed_)subdev functions will call s_config as well, but with irq set to 0 and platform_data set to NULL. -Note that in the next kernel release the functions v4l2_i2c_new_subdev, -v4l2_i2c_new_probed_subdev and v4l2_i2c_new_probed_subdev_addr will all be -replaced by a single v4l2_i2c_new_subdev that is identical to -v4l2_i2c_new_subdev_cfg but without the irq and platform_data arguments. - struct video_device ------------------- diff --git a/linux/drivers/media/video/au0828/au0828-cards.c b/linux/drivers/media/video/au0828/au0828-cards.c index 830c4a933..57dd9195d 100644 --- a/linux/drivers/media/video/au0828/au0828-cards.c +++ b/linux/drivers/media/video/au0828/au0828-cards.c @@ -212,7 +212,7 @@ void au0828_card_setup(struct au0828_dev *dev) be abstracted out if we ever need to support a different demod) */ sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "au8522", "au8522", 0x8e >> 1); + "au8522", "au8522", 0x8e >> 1, NULL); if (sd == NULL) printk(KERN_ERR "analog subdev registration failed\n"); } @@ -221,7 +221,7 @@ void au0828_card_setup(struct au0828_dev *dev) if (dev->board.tuner_type != TUNER_ABSENT) { /* Load the tuner module, which does the attach */ sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", "tuner", dev->board.tuner_addr); + "tuner", "tuner", dev->board.tuner_addr, NULL); if (sd == NULL) printk(KERN_ERR "tuner subdev registration fail\n"); diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index fdca5f67c..6b41aa5dc 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -3561,8 +3561,8 @@ void __devinit bttv_init_card2(struct bttv *btv) }; struct v4l2_subdev *sd; - sd = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "saa6588", "saa6588", addrs); + sd = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "saa6588", "saa6588", 0, addrs); btv->has_saa6588 = (sd != NULL); } @@ -3586,8 +3586,8 @@ void __devinit bttv_init_card2(struct bttv *btv) I2C_CLIENT_END }; - btv->sd_msp34xx = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "msp3400", "msp3400", addrs); + btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "msp3400", "msp3400", 0, addrs); if (btv->sd_msp34xx) return; goto no_audio; @@ -3600,16 +3600,16 @@ void __devinit bttv_init_card2(struct bttv *btv) I2C_CLIENT_END }; - if (v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tda7432", "tda7432", addrs)) + if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tda7432", "tda7432", 0, addrs)) return; goto no_audio; } case 3: { /* The user specified that we should probe for tvaudio */ - btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tvaudio", "tvaudio", tvaudio_addrs()); + btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tvaudio", "tvaudio", 0, tvaudio_addrs()); if (btv->sd_tvaudio) return; goto no_audio; @@ -3628,13 +3628,13 @@ void __devinit bttv_init_card2(struct bttv *btv) it really is a msp3400, so it will return NULL when the device found is really something else (e.g. a tea6300). */ if (!bttv_tvcards[btv->c.type].no_msp34xx) { - btv->sd_msp34xx = v4l2_i2c_new_probed_subdev_addr(&btv->c.v4l2_dev, + btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, &btv->c.i2c_adap, "msp3400", "msp3400", - I2C_ADDR_MSP3400 >> 1); + 0, I2C_ADDRS(I2C_ADDR_MSP3400 >> 1)); } else if (bttv_tvcards[btv->c.type].msp34xx_alt) { - btv->sd_msp34xx = v4l2_i2c_new_probed_subdev_addr(&btv->c.v4l2_dev, + btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, &btv->c.i2c_adap, "msp3400", "msp3400", - I2C_ADDR_MSP3400_ALT >> 1); + 0, I2C_ADDRS(I2C_ADDR_MSP3400_ALT >> 1)); } /* If we found a msp34xx, then we're done. */ @@ -3648,14 +3648,14 @@ void __devinit bttv_init_card2(struct bttv *btv) I2C_CLIENT_END }; - if (v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tda7432", "tda7432", addrs)) + if (v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tda7432", "tda7432", 0, addrs)) return; } /* Now see if we can find one of the tvaudio devices. */ - btv->sd_tvaudio = v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, - &btv->c.i2c_adap, "tvaudio", "tvaudio", tvaudio_addrs()); + btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev, + &btv->c.i2c_adap, "tvaudio", "tvaudio", 0, tvaudio_addrs()); if (btv->sd_tvaudio) return; @@ -3678,15 +3678,15 @@ void __devinit bttv_init_tuner(struct bttv *btv) /* Load tuner module before issuing tuner config call! */ if (bttv_tvcards[btv->c.type].has_radio) - v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + v4l2_i2c_new_subdev(&btv->c.v4l2_dev, &btv->c.i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_RADIO)); - v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + v4l2_i2c_new_subdev(&btv->c.v4l2_dev, &btv->c.i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev, + 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + v4l2_i2c_new_subdev(&btv->c.v4l2_dev, &btv->c.i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD)); + 0, v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD)); tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c index 2c78c35e8..7e86e9bfb 100644 --- a/linux/drivers/media/video/cafe_ccic.c +++ b/linux/drivers/media/video/cafe_ccic.c @@ -1956,7 +1956,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, cam->sensor_addr = 0x42; cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, &cam->i2c_adapter, - "ov7670", "ov7670", cam->sensor_addr); + "ov7670", "ov7670", cam->sensor_addr, NULL); if (cam->sensor == NULL) { ret = -ENODEV; goto out_smbus; diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c index c551fcd47..7d4272d33 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.c +++ b/linux/drivers/media/video/cx18/cx18-i2c.c @@ -144,16 +144,16 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) if (hw == CX18_HW_TUNER) { /* special tuner group handling */ - sd = v4l2_i2c_new_probed_subdev(&cx->v4l2_dev, - adap, mod, type, cx->card_i2c->radio); + sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, + adap, mod, type, 0, cx->card_i2c->radio); if (sd != NULL) sd->grp_id = hw; - sd = v4l2_i2c_new_probed_subdev(&cx->v4l2_dev, - adap, mod, type, cx->card_i2c->demod); + sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, + adap, mod, type, 0, cx->card_i2c->demod); if (sd != NULL) sd->grp_id = hw; - sd = v4l2_i2c_new_probed_subdev(&cx->v4l2_dev, - adap, mod, type, cx->card_i2c->tv); + sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, + adap, mod, type, 0, cx->card_i2c->tv); if (sd != NULL) sd->grp_id = hw; return sd != NULL ? 0 : -1; @@ -167,7 +167,7 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) return -1; /* It's an I2C device other than an analog tuner or IR chip */ - sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, mod, type, hw_addrs[idx]); + sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, mod, type, hw_addrs[idx], NULL); if (sd != NULL) sd->grp_id = hw; return sd != NULL ? 0 : -1; diff --git a/linux/drivers/media/video/cx231xx/cx231xx-cards.c b/linux/drivers/media/video/cx231xx/cx231xx-cards.c index f388262bd..84b37a906 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/linux/drivers/media/video/cx231xx/cx231xx-cards.c @@ -327,7 +327,7 @@ void cx231xx_card_setup(struct cx231xx *dev) if (dev->board.decoder == CX231XX_AVDECODER) { dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[0].i2c_adap, - "cx25840", "cx25840", 0x88 >> 1); + "cx25840", "cx25840", 0x88 >> 1, NULL); if (dev->sd_cx25840 == NULL) cx231xx_info("cx25840 subdev registration failure\n"); cx25840_call(dev, core, load_fw); @@ -337,7 +337,7 @@ void cx231xx_card_setup(struct cx231xx *dev) if (dev->board.tuner_type != TUNER_ABSENT) { dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[1].i2c_adap, - "tuner", "tuner", 0xc2 >> 1); + "tuner", "tuner", 0xc2 >> 1, NULL); if (dev->sd_tuner == NULL) cx231xx_info("tuner subdev registration failure\n"); diff --git a/linux/drivers/media/video/cx23885/cx23885-cards.c b/linux/drivers/media/video/cx23885/cx23885-cards.c index 2ffc83e60..8be8b819e 100644 --- a/linux/drivers/media/video/cx23885/cx23885-cards.c +++ b/linux/drivers/media/video/cx23885/cx23885-cards.c @@ -930,7 +930,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[2].i2c_adap, - "cx25840", "cx25840", 0x88 >> 1); + "cx25840", "cx25840", 0x88 >> 1, NULL); v4l2_subdev_call(dev->sd_cx25840, core, load_fw); break; } diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index fc7af991e..1f8161829 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -1777,11 +1777,11 @@ int cx23885_video_register(struct cx23885_dev *dev) if (dev->tuner_addr) sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[1].i2c_adap, - "tuner", "tuner", dev->tuner_addr); + "tuner", "tuner", dev->tuner_addr, NULL); else - sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[1].i2c_adap, - "tuner", "tuner", v4l2_i2c_tuner_addrs(ADDRS_TV)); + "tuner", "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_TV)); if (sd) { struct tuner_setup tun_setup; diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 67ccc59a7..c3cfdd463 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -3418,20 +3418,20 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) The radio_type is sometimes missing, or set to UNSET but later code configures a tea5767. */ - v4l2_i2c_new_probed_subdev(&core->v4l2_dev, &core->i2c_adap, + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_RADIO)); + 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO)); if (has_demod) - v4l2_i2c_new_probed_subdev(&core->v4l2_dev, + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (core->board.tuner_addr == ADDR_UNSET) { - v4l2_i2c_new_probed_subdev(&core->v4l2_dev, + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, "tuner", "tuner", - has_demod ? tv_addrs + 4 : tv_addrs); + 0, has_demod ? tv_addrs + 4 : tv_addrs); } else { v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "tuner", "tuner", core->board.tuner_addr); + "tuner", "tuner", core->board.tuner_addr, NULL); } } diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index d4bd9ba68..9ec7d2f57 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -2155,14 +2155,14 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, if (core->board.audio_chip == V4L2_IDENT_WM8775) v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "wm8775", "wm8775", 0x36 >> 1); + "wm8775", "wm8775", 0x36 >> 1, NULL); if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { /* This probes for a tda9874 as is used on some Pixelview Ultra boards. */ - v4l2_i2c_new_probed_subdev_addr(&core->v4l2_dev, + v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "tvaudio", "tvaudio", 0xb0 >> 1); + "tvaudio", "tvaudio", 0, I2C_ADDRS(0xb0 >> 1)); } switch (core->boardnr) { diff --git a/linux/drivers/media/video/davinci/vpif_display.c b/linux/drivers/media/video/davinci/vpif_display.c index 969d4b3aa..0f0ec8dc6 100644 --- a/linux/drivers/media/video/davinci/vpif_display.c +++ b/linux/drivers/media/video/davinci/vpif_display.c @@ -1566,10 +1566,10 @@ static __init int vpif_probe(struct platform_device *pdev) } for (i = 0; i < subdev_count; i++) { - vpif_obj.sd[i] = v4l2_i2c_new_probed_subdev(&vpif_obj.v4l2_dev, + vpif_obj.sd[i] = v4l2_i2c_new_subdev(&vpif_obj.v4l2_dev, i2c_adap, subdevdata[i].name, subdevdata[i].name, - &subdevdata[i].addr); + 0, I2C_ADDRS(subdevdata[i].addr)); if (!vpif_obj.sd[i]) { vpif_err("Error registering v4l2 subdevice\n"); goto probe_subdev_out; diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 9a09df296..02e251f8c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2428,61 +2428,61 @@ void em28xx_card_setup(struct em28xx *dev) /* request some modules */ if (dev->board.has_msp34xx) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "msp3400", "msp3400", msp3400_addrs); + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "msp3400", "msp3400", 0, msp3400_addrs); if (dev->board.decoder == EM28XX_SAA711X) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "saa7115", "saa7115_auto", saa711x_addrs); + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "saa7115", "saa7115_auto", 0, saa711x_addrs); if (dev->board.decoder == EM28XX_TVP5150) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvp5150", "tvp5150", tvp5150_addrs); + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "tvp5150", "tvp5150", 0, tvp5150_addrs); if (dev->em28xx_sensor == EM28XX_MT9V011) { struct v4l2_subdev *sd; - sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, - &dev->i2c_adap, "mt9v011", "mt9v011", mt9v011_addrs); + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_adap, "mt9v011", "mt9v011", 0, mt9v011_addrs); v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal); } #if 0 /* FIXME: use mt9m001 after their conversion to v4l dev/subdev */ if (dev->em28xx_sensor == EM28XX_MT9M001) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "mt9m001", "mt9m001", mt9v011_addrs); + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, + "mt9m001", "mt9m001", 0, mt9v011_addrs); #endif if (dev->board.adecoder == EM28XX_TVAUDIO) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tvaudio", "tvaudio", dev->board.tvaudio_addr); + "tvaudio", "tvaudio", dev->board.tvaudio_addr, NULL); if (dev->board.tuner_type != TUNER_ABSENT) { int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); if (dev->board.radio.type) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", "tuner", dev->board.radio_addr); + "tuner", "tuner", dev->board.radio_addr, NULL); if (has_demod) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (dev->tuner_addr == 0) { enum v4l2_i2c_tuner_type type = has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; struct v4l2_subdev *sd; - sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(type)); + 0, v4l2_i2c_tuner_addrs(type)); if (sd) dev->tuner_addr = v4l2_i2c_subdev_addr(sd); } else { v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, - "tuner", "tuner", dev->tuner_addr); + "tuner", "tuner", dev->tuner_addr, NULL); } } diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index b5c94d646..32d0b84d7 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -165,19 +165,19 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) return -1; if (hw == IVTV_HW_TUNER) { /* special tuner handling */ - sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev, + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, mod, type, - itv->card_i2c->radio); + 0, itv->card_i2c->radio); if (sd) sd->grp_id = 1 << idx; - sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev, + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, mod, type, - itv->card_i2c->demod); + 0, itv->card_i2c->demod); if (sd) sd->grp_id = 1 << idx; - sd = v4l2_i2c_new_probed_subdev(&itv->v4l2_dev, + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, mod, type, - itv->card_i2c->tv); + 0, itv->card_i2c->tv); if (sd) sd->grp_id = 1 << idx; return sd ? 0 : -1; @@ -185,11 +185,11 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) if (!hw_addrs[idx]) return -1; if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { - sd = v4l2_i2c_new_probed_subdev_addr(&itv->v4l2_dev, - adap, mod, type, hw_addrs[idx]); + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, + adap, mod, type, 0, I2C_ADDRS(hw_addrs[idx])); } else { sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, - adap, mod, type, hw_addrs[idx]); + adap, mod, type, hw_addrs[idx], NULL); } if (sd) sd->grp_id = 1 << idx; diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index 411efcd34..d727acaa5 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -190,19 +190,19 @@ static int mxb_probe(struct saa7146_dev *dev) } mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "saa7115", "saa7111", I2C_SAA7111A); + "saa7115", "saa7111", I2C_SAA7111A, NULL); mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tea6420", "tea6420", I2C_TEA6420_1); + "tea6420", "tea6420", I2C_TEA6420_1, NULL); mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tea6420", "tea6420", I2C_TEA6420_2); + "tea6420", "tea6420", I2C_TEA6420_2, NULL); mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tea6415c", "tea6415c", I2C_TEA6415C); + "tea6415c", "tea6415c", I2C_TEA6415C, NULL); mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tda9840", "tda9840", I2C_TDA9840); + "tda9840", "tda9840", I2C_TDA9840, NULL); mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "tuner", "tuner", I2C_TUNER); + "tuner", "tuner", I2C_TUNER, NULL); if (v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter, - "saa5246a", "saa5246a", I2C_SAA5246A)) { + "saa5246a", "saa5246a", I2C_SAA5246A, NULL)) { printk(KERN_INFO "mxb: found teletext decoder\n"); } diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 0bbd20f13..493232936 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -2080,8 +2080,8 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, return -EINVAL; } - /* Note how the 2nd and 3rd arguments are the same for both - * v4l2_i2c_new_subdev() and v4l2_i2c_new_probed_subdev(). Why? + /* Note how the 2nd and 3rd arguments are the same for + * v4l2_i2c_new_subdev(). Why? * Well the 2nd argument is the module name to load, while the 3rd * argument is documented in the framework as being the "chipid" - * and every other place where I can find examples of this, the @@ -2094,15 +2094,15 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, mid, i2caddr[0]); sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, fname, fname, - i2caddr[0]); + i2caddr[0], NULL); } else { pvr2_trace(PVR2_TRACE_INIT, "Module ID %u:" " Setting up with address probe list", mid); - sd = v4l2_i2c_new_probed_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, + sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap, fname, fname, - i2caddr); + 0, i2caddr); } if (!sd) { diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index c18b41ee6..22fdc40d1 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -7110,22 +7110,22 @@ int saa7134_board_init2(struct saa7134_dev *dev) if (dev->radio_type != UNSET) v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - dev->radio_addr); + dev->radio_addr, NULL); if (has_demod) - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); if (dev->tuner_addr == ADDR_UNSET) { enum v4l2_i2c_tuner_type type = has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, + v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - v4l2_i2c_tuner_addrs(type)); + 0, v4l2_i2c_tuner_addrs(type)); } else { v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "tuner", "tuner", - dev->tuner_addr); + dev->tuner_addr, NULL); } } diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index e466afd18..d0080370f 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1061,7 +1061,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, struct v4l2_subdev *sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "saa6752hs", "saa6752hs", - saa7134_boards[dev->board].empress_addr); + saa7134_boards[dev->board].empress_addr, NULL); if (sd) sd->grp_id = GRP_EMPRESS; @@ -1070,9 +1070,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (saa7134_boards[dev->board].rds_addr) { struct v4l2_subdev *sd; - sd = v4l2_i2c_new_probed_subdev_addr(&dev->v4l2_dev, + sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, "saa6588", "saa6588", - saa7134_boards[dev->board].rds_addr); + 0, I2C_ADDRS(saa7134_boards[dev->board].rds_addr)); if (sd) { printk(KERN_INFO "%s: found RDS decoder\n", dev->name); dev->has_rds = 1; diff --git a/linux/drivers/media/video/usbvision/usbvision-i2c.c b/linux/drivers/media/video/usbvision/usbvision-i2c.c index b74ada0c6..82c7d298d 100644 --- a/linux/drivers/media/video/usbvision/usbvision-i2c.c +++ b/linux/drivers/media/video/usbvision/usbvision-i2c.c @@ -250,9 +250,9 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) switch (usbvision_device_data[usbvision->DevModel].Codec) { case CODEC_SAA7113: case CODEC_SAA7111: - v4l2_i2c_new_probed_subdev(&usbvision->v4l2_dev, + v4l2_i2c_new_subdev(&usbvision->v4l2_dev, &usbvision->i2c_adap, "saa7115", - "saa7115_auto", saa711x_addrs); + "saa7115_auto", 0, saa711x_addrs); break; } if (usbvision_device_data[usbvision->DevModel].Tuner == 1) { @@ -260,16 +260,16 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) enum v4l2_i2c_tuner_type type; struct tuner_setup tun_setup; - sd = v4l2_i2c_new_probed_subdev(&usbvision->v4l2_dev, + sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev, &usbvision->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); /* depending on whether we found a demod or not, select the tuner type. */ type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - sd = v4l2_i2c_new_probed_subdev(&usbvision->v4l2_dev, + sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev, &usbvision->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(type)); + "tuner", 0, v4l2_i2c_tuner_addrs(type)); if (usbvision->tuner_type != -1) { tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 864ee0772..fe1dfc00b 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -818,163 +818,6 @@ static struct i2c_client *v4l2_i2c_legacy_find_client(struct i2c_adapter *adap, #endif -/* Load an i2c sub-device. */ -struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, - struct i2c_adapter *adapter, - const char *module_name, const char *client_type, u8 addr) -{ - struct v4l2_subdev *sd = NULL; - struct i2c_client *client; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - struct i2c_board_info info; -#endif - - BUG_ON(!v4l2_dev); - - if (module_name) - request_module(module_name); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - /* Setup the i2c board info with the device type and - the device address. */ - memset(&info, 0, sizeof(info)); - strlcpy(info.type, client_type, sizeof(info.type)); - info.addr = addr; - - /* Create the i2c client */ - client = i2c_new_device(adapter, &info); -#else - /* Legacy code: loading the module automatically - probes and creates the i2c_client on the adapter. - Try to find the client by walking the adapter's client list. */ - client = v4l2_i2c_legacy_find_client(adapter, addr); -#endif - /* Note: it is possible in the future that - c->driver is NULL if the driver is still being loaded. - We need better support from the kernel so that we - can easily wait for the load to finish. */ - if (client == NULL || client->driver == NULL) - goto error; - - /* Lock the module so we can safely get the v4l2_subdev pointer */ - if (!try_module_get(client->driver->driver.owner)) - goto error; - sd = i2c_get_clientdata(client); - - /* Register with the v4l2_device which increases the module's - use count as well. */ - if (v4l2_device_register_subdev(v4l2_dev, sd)) - sd = NULL; - /* Decrease the module use count to match the first try_module_get. */ - module_put(client->driver->driver.owner); - - if (sd) { - /* We return errors from v4l2_subdev_call only if we have the - callback as the .s_config is not mandatory */ - int err = v4l2_subdev_call(sd, core, s_config, 0, NULL); - - if (err && err != -ENOIOCTLCMD) { - v4l2_device_unregister_subdev(sd); - sd = NULL; - } - } - -error: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - /* If we have a client but no subdev, then something went wrong and - we must unregister the client. */ - if (client && sd == NULL) - i2c_unregister_device(client); -#endif - return sd; -} -EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev); - -/* Probe and load an i2c sub-device. */ -struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct v4l2_device *v4l2_dev, - struct i2c_adapter *adapter, - const char *module_name, const char *client_type, - const unsigned short *addrs) -{ - struct v4l2_subdev *sd = NULL; - struct i2c_client *client = NULL; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - struct i2c_board_info info; -#endif - - BUG_ON(!v4l2_dev); - - if (module_name) - request_module(module_name); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - /* Setup the i2c board info with the device type and - the device address. */ - memset(&info, 0, sizeof(info)); - strlcpy(info.type, client_type, sizeof(info.type)); - - /* Probe and create the i2c client */ - client = i2c_new_probed_device(adapter, &info, addrs); -#else - /* Legacy code: loading the module should automatically - probe and create the i2c_client on the adapter. - Try to find the client by walking the adapter's client list - for each of the possible addresses. */ - while (!client && *addrs != I2C_CLIENT_END) - client = v4l2_i2c_legacy_find_client(adapter, *addrs++); -#endif - /* Note: it is possible in the future that - c->driver is NULL if the driver is still being loaded. - We need better support from the kernel so that we - can easily wait for the load to finish. */ - if (client == NULL || client->driver == NULL) - goto error; - - /* Lock the module so we can safely get the v4l2_subdev pointer */ - if (!try_module_get(client->driver->driver.owner)) - goto error; - sd = i2c_get_clientdata(client); - - /* Register with the v4l2_device which increases the module's - use count as well. */ - if (v4l2_device_register_subdev(v4l2_dev, sd)) - sd = NULL; - /* Decrease the module use count to match the first try_module_get. */ - module_put(client->driver->driver.owner); - - if (sd) { - /* We return errors from v4l2_subdev_call only if we have the - callback as the .s_config is not mandatory */ - int err = v4l2_subdev_call(sd, core, s_config, 0, NULL); - - if (err && err != -ENOIOCTLCMD) { - v4l2_device_unregister_subdev(sd); - sd = NULL; - } - } - -error: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - /* If we have a client but no subdev, then something went wrong and - we must unregister the client. */ - if (client && sd == NULL) - i2c_unregister_device(client); -#endif - return sd; -} -EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev); - -struct v4l2_subdev *v4l2_i2c_new_probed_subdev_addr(struct v4l2_device *v4l2_dev, - struct i2c_adapter *adapter, - const char *module_name, const char *client_type, u8 addr) -{ - unsigned short addrs[2] = { addr, I2C_CLIENT_END }; - - return v4l2_i2c_new_probed_subdev(v4l2_dev, adapter, - module_name, client_type, addrs); -} -EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev_addr); - /* Load an i2c sub-device. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index af03ec2d5..8383e6f80 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -4337,11 +4337,11 @@ static int __init vino_module_init(void) vino_init_stage++; vino_drvdata->decoder = - v4l2_i2c_new_probed_subdev_addr(&vino_drvdata->v4l2_dev, - &vino_i2c_adapter, "saa7191", "saa7191", 0x45); + v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter, + "saa7191", "saa7191", 0, I2C_ADDRS(0x45)); vino_drvdata->camera = - v4l2_i2c_new_probed_subdev_addr(&vino_drvdata->v4l2_dev, - &vino_i2c_adapter, "indycam", "indycam", 0x2b); + v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter, + "indycam", "indycam", 0, I2C_ADDRS(0x2b)); dprintk("init complete!\n"); diff --git a/linux/drivers/media/video/w9968cf.c b/linux/drivers/media/video/w9968cf.c index 5324c092a..c52301762 100644 --- a/linux/drivers/media/video/w9968cf.c +++ b/linux/drivers/media/video/w9968cf.c @@ -3529,9 +3529,9 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) w9968cf_turn_on_led(cam); w9968cf_i2c_init(cam); - cam->sensor_sd = v4l2_i2c_new_probed_subdev(&cam->v4l2_dev, + cam->sensor_sd = v4l2_i2c_new_subdev(&cam->v4l2_dev, &cam->i2c_adapter, - "ovcamchip", "ovcamchip", addrs); + "ovcamchip", "ovcamchip", 0, addrs); usb_set_intfdata(intf, cam); mutex_unlock(&cam->dev_mutex); diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 217fec9e4..74509d627 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -1358,15 +1358,15 @@ static int __devinit zoran_probe(struct pci_dev *pdev, goto zr_free_irq; } - zr->decoder = v4l2_i2c_new_probed_subdev(&zr->v4l2_dev, + zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter, zr->card.mod_decoder, zr->card.i2c_decoder, - zr->card.addrs_decoder); + 0, zr->card.addrs_decoder); if (zr->card.mod_encoder) - zr->encoder = v4l2_i2c_new_probed_subdev(&zr->v4l2_dev, + zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, &zr->i2c_adapter, zr->card.mod_encoder, zr->card.i2c_encoder, - zr->card.addrs_encoder); + 0, zr->card.addrs_encoder); dprintk(2, KERN_INFO "%s: Initializing videocodec bus...\n", diff --git a/linux/include/media/v4l2-common.h b/linux/include/media/v4l2-common.h index 831c4c038..5a5d927af 100644 --- a/linux/include/media/v4l2-common.h +++ b/linux/include/media/v4l2-common.h @@ -144,29 +144,23 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver /* Load an i2c module and return an initialized v4l2_subdev struct. Only call request_module if module_name != NULL. The client_type argument is the name of the chip that's on the adapter. */ -struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, - struct i2c_adapter *adapter, - const char *module_name, const char *client_type, u8 addr); -/* Probe and load an i2c module and return an initialized v4l2_subdev struct. - Only call request_module if module_name != NULL. - The client_type argument is the name of the chip that's on the adapter. */ -struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct v4l2_device *v4l2_dev, +struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev, struct i2c_adapter *adapter, const char *module_name, const char *client_type, - const unsigned short *addrs); -/* Like v4l2_i2c_new_probed_subdev, except probe for a single address. */ -struct v4l2_subdev *v4l2_i2c_new_probed_subdev_addr(struct v4l2_device *v4l2_dev, - struct i2c_adapter *adapter, - const char *module_name, const char *client_type, u8 addr); + int irq, void *platform_data, + u8 addr, const unsigned short *probe_addrs); /* Load an i2c module and return an initialized v4l2_subdev struct. Only call request_module if module_name != NULL. The client_type argument is the name of the chip that's on the adapter. */ -struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev, +static inline struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, struct i2c_adapter *adapter, const char *module_name, const char *client_type, - int irq, void *platform_data, - u8 addr, const unsigned short *probe_addrs); + u8 addr, const unsigned short *probe_addrs) +{ + return v4l2_i2c_new_subdev_cfg(v4l2_dev, adapter, module_name, + client_type, 0, NULL, addr, probe_addrs); +} #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) struct i2c_board_info; -- cgit v1.2.3 From 06db2bf24db3684dec5bc4cb6883c196e8a8cbba Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Jun 2009 16:32:56 +0200 Subject: v4l: remove video_register_device_index From: Hans Verkuil video_register_device_index is never actually called, instead the stream index number is always calculated automatically. This patch removes this function and simplifies the internal get_index function since that can now always just return the first free index. Priority: normal Signed-off-by: Hans Verkuil --- linux/Documentation/video4linux/v4l2-framework.txt | 17 ++----- linux/drivers/media/video/v4l2-dev.c | 55 ++++++---------------- linux/include/media/v4l2-dev.h | 2 - 3 files changed, 20 insertions(+), 54 deletions(-) diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index e395a9cdc..cb6c7eb51 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -500,17 +500,11 @@ first free number. Whenever a device node is created some attributes are also created for you. If you look in /sys/class/video4linux you see the devices. Go into e.g. video0 and you will see 'name' and 'index' attributes. The 'name' attribute -is the 'name' field of the video_device struct. The 'index' attribute is -a device node index that can be assigned by the driver, or that is calculated -for you. - -If you call video_register_device(), then the index is just increased by -1 for each device node you register. The first video device node you register -always starts off with 0. +is the 'name' field of the video_device struct. -Alternatively you can call video_register_device_index() which is identical -to video_register_device(), but with an extra index argument. Here you can -pass a specific index value (between 0 and 31) that should be used. +The 'index' attribute is the index of the device node: for each call to +video_register_device() the index is just increased by 1. The first video +device node you register always starts with index 0. Users can setup udev rules that utilize the index attribute to make fancy device names (e.g. 'mpegX' for MPEG video capture device nodes). @@ -520,8 +514,7 @@ After the device was successfully registered, then you can use these fields: - vfl_type: the device type passed to video_register_device. - minor: the assigned device minor number. - num: the device kernel number (i.e. the X in videoX). -- index: the device index number (calculated or set explicitly using - video_register_device_index). +- index: the device index number. If the registration failed, then you need to call video_device_release() to free the allocated video_device struct, or free your own struct if the diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 9969abb28..9f04a8e6d 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -337,32 +337,28 @@ static const struct file_operations v4l2_fops = { }; /** - * get_index - assign stream number based on parent device + * get_index - assign stream index number based on parent device * @vdev: video_device to assign index number to, vdev->parent should be assigned - * @num: -1 if auto assign, requested number otherwise * * Note that when this is called the new device has not yet been registered - * in the video_device array. + * in the video_device array, but it was able to obtain a minor number. * - * Returns -ENFILE if num is already in use, a free index number if - * successful. + * This means that we can always obtain a free stream index number since + * the worst case scenario is that there are VIDEO_NUM_DEVICES - 1 slots in + * use of the video_device array. + * + * Returns a free index number. */ -static int get_index(struct video_device *vdev, int num) +static int get_index(struct video_device *vdev) { /* This can be static since this function is called with the global videodev_lock held. */ static DECLARE_BITMAP(used, VIDEO_NUM_DEVICES); int i; - if (num >= VIDEO_NUM_DEVICES) { - printk(KERN_ERR "videodev: %s num is too large\n", __func__); - return -EINVAL; - } - - /* Some drivers do not set the parent. In that case always return - num or 0. */ + /* Some drivers do not set the parent. In that case always return 0. */ if (vdev->parent == NULL) - return num >= 0 ? num : 0; + return 0; bitmap_zero(used, VIDEO_NUM_DEVICES); @@ -373,30 +369,15 @@ static int get_index(struct video_device *vdev, int num) } } - if (num >= 0) { - if (test_bit(num, used)) - return -ENFILE; - return num; - } - - i = find_first_zero_bit(used, VIDEO_NUM_DEVICES); - return i == VIDEO_NUM_DEVICES ? -ENFILE : i; + return find_first_zero_bit(used, VIDEO_NUM_DEVICES); } -int video_register_device(struct video_device *vdev, int type, int nr) -{ - return video_register_device_index(vdev, type, nr, -1); -} -EXPORT_SYMBOL(video_register_device); - /** - * video_register_device_index - register video4linux devices + * video_register_device - register video4linux devices * @vdev: video device structure we want to register * @type: type of device to register * @nr: which device number (0 == /dev/video0, 1 == /dev/video1, ... * -1 == first free) - * @index: stream number based on parent device; - * -1 if auto assign, requested number otherwise * * The registration code assigns minor numbers based on the type * requested. -ENFILE is returned in all the device slots for this @@ -415,8 +396,7 @@ EXPORT_SYMBOL(video_register_device); * * %VFL_TYPE_RADIO - A radio card */ -int video_register_device_index(struct video_device *vdev, int type, int nr, - int index) +int video_register_device(struct video_device *vdev, int type, int nr) { int i = 0; int ret; @@ -519,14 +499,9 @@ int video_register_device_index(struct video_device *vdev, int type, int nr, set_bit(nr, video_nums[type]); /* Should not happen since we thought this minor was free */ WARN_ON(video_device[vdev->minor] != NULL); - ret = vdev->index = get_index(vdev, index); + vdev->index = get_index(vdev); mutex_unlock(&videodev_lock); - if (ret < 0) { - printk(KERN_ERR "%s: get_index failed\n", __func__); - goto cleanup; - } - /* Part 3: Initialize the character device */ vdev->cdev = cdev_alloc(); if (vdev->cdev == NULL) { @@ -611,7 +586,7 @@ cleanup: vdev->minor = -1; return ret; } -EXPORT_SYMBOL(video_register_device_index); +EXPORT_SYMBOL(video_register_device); /** * video_unregister_device - unregister a video4linux device diff --git a/linux/include/media/v4l2-dev.h b/linux/include/media/v4l2-dev.h index 978e26506..1cae97561 100644 --- a/linux/include/media/v4l2-dev.h +++ b/linux/include/media/v4l2-dev.h @@ -104,8 +104,6 @@ struct video_device Also note that vdev->minor is set to -1 if the registration failed. */ int __must_check video_register_device(struct video_device *vdev, int type, int nr); -int __must_check video_register_device_index(struct video_device *vdev, - int type, int nr, int index); /* Unregister video devices. Will do nothing if vdev == NULL or vdev->minor < 0. */ -- cgit v1.2.3 From 67317e288ea475e9d7d9d9883c4b007aac4ec6a3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 6 Sep 2009 13:13:14 +0300 Subject: v4l2-dev: replace 'kernel number' by 'device node number'. From: Hans Verkuil The term 'kernel number' is very vague, so replace it with the somewhat more descriptive term 'device node number'. In one place the local variable 'nr' was used to create the device node number of the new device name. This has been replaced with the vdev->num field to more clearly mark this as being the device node number and not the minor number. Priority: normal Signed-off-by: Hans Verkuil --- linux/Documentation/video4linux/v4l2-framework.txt | 8 ++--- linux/drivers/media/video/v4l2-dev.c | 40 ++++++++++++---------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index cb6c7eb51..38b3716d8 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -486,14 +486,14 @@ VFL_TYPE_RADIO: radioX for radio tuners VFL_TYPE_VTX: vtxX for teletext devices (deprecated, don't use) The last argument gives you a certain amount of control over the device -kernel number used (i.e. the X in videoX). Normally you will pass -1 to +device node number used (i.e. the X in videoX). Normally you will pass -1 to let the v4l2 framework pick the first free number. But if a driver creates many devices, then it can be useful to have different video devices in separate ranges. For example, video capture devices start at 0, video output devices start at 16. -So you can use the last argument to specify a minimum kernel number and -the v4l2 framework will try to pick the first free number that is equal +So you can use the last argument to specify a minimum device node number +and the v4l2 framework will try to pick the first free number that is equal or higher to what you passed. If that fails, then it will just pick the first free number. @@ -513,7 +513,7 @@ After the device was successfully registered, then you can use these fields: - vfl_type: the device type passed to video_register_device. - minor: the assigned device minor number. -- num: the device kernel number (i.e. the X in videoX). +- num: the device node number (i.e. the X in videoX). - index: the device index number. If the registration failed, then you need to call video_device_release() diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 9f04a8e6d..77e650616 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -86,7 +86,7 @@ static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL); */ static struct video_device *video_device[VIDEO_NUM_DEVICES]; static DEFINE_MUTEX(videodev_lock); -static DECLARE_BITMAP(video_nums[VFL_TYPE_MAX], VIDEO_NUM_DEVICES); +static DECLARE_BITMAP(devnode_nums[VFL_TYPE_MAX], VIDEO_NUM_DEVICES); struct video_device *video_device_alloc(void) { @@ -151,8 +151,8 @@ static void v4l2_device_release(struct device *cd) the release() callback. */ vdev->cdev = NULL; - /* Mark minor as free */ - clear_bit(vdev->num, video_nums[vdev->vfl_type]); + /* Mark device node number as free */ + clear_bit(vdev->num, devnode_nums[vdev->vfl_type]); mutex_unlock(&videodev_lock); @@ -376,13 +376,14 @@ static int get_index(struct video_device *vdev) * video_register_device - register video4linux devices * @vdev: video device structure we want to register * @type: type of device to register - * @nr: which device number (0 == /dev/video0, 1 == /dev/video1, ... + * @nr: which device node number (0 == /dev/video0, 1 == /dev/video1, ... * -1 == first free) * - * The registration code assigns minor numbers based on the type - * requested. -ENFILE is returned in all the device slots for this - * category are full. If not then the minor field is set and the - * driver initialize function is called (if non %NULL). + * The registration code assigns minor numbers and device node numbers + * based on the requested type and registers the new device node with + * the kernel. + * An error is returned if no free minor or device node number could be + * found, or if the registration of the device node failed. * * Zero is returned on success. * @@ -439,7 +440,7 @@ int video_register_device(struct video_device *vdev, int type, int nr) if (vdev->v4l2_dev && vdev->v4l2_dev->dev) vdev->parent = vdev->v4l2_dev->dev; - /* Part 2: find a free minor, kernel number and device index. */ + /* Part 2: find a free minor, device node number and device index. */ #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES /* Keep the ranges for the first four types for historical * reasons. @@ -470,21 +471,22 @@ int video_register_device(struct video_device *vdev, int type, int nr) } #endif - /* Pick a minor number */ + /* Pick a device node number */ mutex_lock(&videodev_lock); - nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr); + nr = find_next_zero_bit(devnode_nums[type], minor_cnt, nr == -1 ? 0 : nr); if (nr == minor_cnt) - nr = find_first_zero_bit(video_nums[type], minor_cnt); + nr = find_first_zero_bit(devnode_nums[type], minor_cnt); if (nr == minor_cnt) { - printk(KERN_ERR "could not get a free kernel number\n"); + printk(KERN_ERR "could not get a free device node number\n"); mutex_unlock(&videodev_lock); return -ENFILE; } #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES - /* 1-on-1 mapping of kernel number to minor number */ + /* 1-on-1 mapping of device node number to minor number */ i = nr; #else - /* The kernel number and minor numbers are independent */ + /* The device node number and minor numbers are independent, so + we just find the first free minor number. */ for (i = 0; i < VIDEO_NUM_DEVICES; i++) if (video_device[i] == NULL) break; @@ -496,7 +498,7 @@ int video_register_device(struct video_device *vdev, int type, int nr) #endif vdev->minor = i + minor_offset; vdev->num = nr; - set_bit(nr, video_nums[type]); + set_bit(nr, devnode_nums[type]); /* Should not happen since we thought this minor was free */ WARN_ON(video_device[vdev->minor] != NULL); vdev->index = get_index(vdev); @@ -538,12 +540,12 @@ int video_register_device(struct video_device *vdev, int type, int nr) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) if (vdev->parent) vdev->dev.dev = vdev->parent; - sprintf(vdev->dev.class_id, "%s%d", name_base, nr); + sprintf(vdev->dev.class_id, "%s%d", name_base, vdev->num); ret = class_device_register(&vdev->dev); #else if (vdev->parent) vdev->dev.parent = vdev->parent; - dev_set_name(&vdev->dev, "%s%d", name_base, nr); + dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num); ret = device_register(&vdev->dev); #endif if (ret < 0) { @@ -580,7 +582,7 @@ cleanup: mutex_lock(&videodev_lock); if (vdev->cdev) cdev_del(vdev->cdev); - clear_bit(vdev->num, video_nums[type]); + clear_bit(vdev->num, devnode_nums[type]); mutex_unlock(&videodev_lock); /* Mark this video device as never having been registered. */ vdev->minor = -1; -- cgit v1.2.3 From b9d280f965f8d2bdf786d7338015ce1be777c666 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 19 Jun 2009 16:54:00 +0200 Subject: ivtv/cx18: replace 'kernel number' with 'device node number'. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx18/cx18-driver.c | 2 +- linux/drivers/media/video/cx18/cx18-streams.c | 2 +- linux/drivers/media/video/ivtv/ivtv-driver.c | 2 +- linux/drivers/media/video/ivtv/ivtv-streams.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index ae13a1546..ede519748 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -231,7 +231,7 @@ MODULE_PARM_DESC(enc_pcm_bufs, "Number of encoder PCM buffers\n" "\t\t\tDefault is computed from other enc_pcm_* parameters"); -MODULE_PARM_DESC(cx18_first_minor, "Set kernel number assigned to first card"); +MODULE_PARM_DESC(cx18_first_minor, "Set device node number assigned to first card"); MODULE_AUTHOR("Hans Verkuil"); MODULE_DESCRIPTION("CX23418 driver"); diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index c134927b3..816d70cc2 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -252,7 +252,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type) /* Register device. First try the desired minor, then any free one. */ ret = video_register_device(s->video_dev, vfl_type, num); if (ret < 0) { - CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n", + CX18_ERR("Couldn't register v4l2 device for %s (device node number %d)\n", s->name, num); video_device_release(s->video_dev); s->video_dev = NULL; diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index fbb8586c5..383d401b4 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -246,7 +246,7 @@ MODULE_PARM_DESC(newi2c, "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" "\t\t\tDefault is autodetect"); -MODULE_PARM_DESC(ivtv_first_minor, "Set kernel number assigned to first card"); +MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card"); MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); MODULE_DESCRIPTION("CX23415/CX23416 driver"); diff --git a/linux/drivers/media/video/ivtv/ivtv-streams.c b/linux/drivers/media/video/ivtv/ivtv-streams.c index 15da01710..234000352 100644 --- a/linux/drivers/media/video/ivtv/ivtv-streams.c +++ b/linux/drivers/media/video/ivtv/ivtv-streams.c @@ -262,7 +262,7 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) /* Register device. First try the desired minor, then any free one. */ if (video_register_device(s->vdev, vfl_type, num)) { - IVTV_ERR("Couldn't register v4l2 device for %s kernel number %d\n", + IVTV_ERR("Couldn't register v4l2 device for %s (device node number %d)\n", s->name, num); video_device_release(s->vdev); s->vdev = NULL; -- cgit v1.2.3 From acf23fa81cd74df218b6eeafdb66477a6884e60a Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 20 Jun 2009 15:51:48 +0300 Subject: Add ce5039(zl10039) tuner support. From: Igor M. Liplianin The code from Jan D. Louw with some minor changes. http://article.gmane.org/gmane.linux.drivers.dvb/38163 Tested with TeVii S630 DVB-S USB card by me (Igor) Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/frontends/Kconfig | 7 + linux/drivers/media/dvb/frontends/Makefile | 1 + linux/drivers/media/dvb/frontends/zl10039.c | 308 ++++++++++++++++++++++++++++ linux/drivers/media/dvb/frontends/zl10039.h | 40 ++++ 4 files changed, 356 insertions(+) create mode 100644 linux/drivers/media/dvb/frontends/zl10039.c create mode 100644 linux/drivers/media/dvb/frontends/zl10039.h diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index be967ac09..b794e860b 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -81,6 +81,13 @@ config DVB_ZL10036 help A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_ZL10039 + tristate "Zarlink ZL10039 silicon tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + config DVB_S5H1420 tristate "Samsung S5H1420 based" depends on DVB_CORE && I2C diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 832473c1e..3b49d37ab 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_DVB_SP887X) += sp887x.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_MT352) += mt352.o obj-$(CONFIG_DVB_ZL10036) += zl10036.o +obj-$(CONFIG_DVB_ZL10039) += zl10039.o obj-$(CONFIG_DVB_ZL10353) += zl10353.o obj-$(CONFIG_DVB_CX22702) += cx22702.o obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o diff --git a/linux/drivers/media/dvb/frontends/zl10039.c b/linux/drivers/media/dvb/frontends/zl10039.c new file mode 100644 index 000000000..11b29cb88 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/zl10039.c @@ -0,0 +1,308 @@ +/* + * Driver for Zarlink ZL10039 DVB-S tuner + * + * Copyright 2007 Jan D. Louw + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "zl10039.h" + +static int debug; + +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG args); \ + } while (0) + +enum zl10039_model_id { + ID_ZL10039 = 1 +}; + +struct zl10039_state { + struct i2c_adapter *i2c; + u8 i2c_addr; + u8 id; +}; + +enum zl10039_reg_addr { + PLL0 = 0, + PLL1, + PLL2, + PLL3, + RFFE, + BASE0, + BASE1, + BASE2, + LO0, + LO1, + LO2, + LO3, + LO4, + LO5, + LO6, + GENERAL +}; + +static int zl10039_read(const struct zl10039_state *state, + const enum zl10039_reg_addr reg, u8 *buf, + const size_t count) +{ + u8 regbuf[] = { reg }; + struct i2c_msg msg[] = { + {/* Write register address */ + .addr = state->i2c_addr, + .flags = 0, + .buf = regbuf, + .len = 1, + }, {/* Read count bytes */ + .addr = state->i2c_addr, + .flags = I2C_M_RD, + .buf = buf, + .len = count, + }, + }; + + dprintk("%s\n", __func__); + + if (i2c_transfer(state->i2c, msg, 2) != 2) { + dprintk("%s: i2c read error\n", __func__); + return -EREMOTEIO; + } + + return 0; /* Success */ +} + +static int zl10039_write(struct zl10039_state *state, + const enum zl10039_reg_addr reg, const u8 *src, + const size_t count) +{ + u8 buf[count + 1]; + struct i2c_msg msg = { + .addr = state->i2c_addr, + .flags = 0, + .buf = buf, + .len = count + 1, + }; + + dprintk("%s\n", __func__); + /* Write register address and data in one go */ + buf[0] = reg; + memcpy(&buf[1], src, count); + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + dprintk("%s: i2c write error\n", __func__); + return -EREMOTEIO; + } + + return 0; /* Success */ +} + +static inline int zl10039_readreg(struct zl10039_state *state, + const enum zl10039_reg_addr reg, u8 *val) +{ + return zl10039_read(state, reg, val, 1); +} + +static inline int zl10039_writereg(struct zl10039_state *state, + const enum zl10039_reg_addr reg, + const u8 val) +{ + return zl10039_write(state, reg, &val, 1); +} + +static int zl10039_init(struct dvb_frontend *fe) +{ + struct zl10039_state *state = fe->tuner_priv; + int ret; + + dprintk("%s\n", __func__); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + /* Reset logic */ + ret = zl10039_writereg(state, GENERAL, 0x40); + if (ret < 0) { + dprintk("Note: i2c write error normal when resetting the " + "tuner\n"); + } + /* Wake up */ + ret = zl10039_writereg(state, GENERAL, 0x01); + if (ret < 0) { + dprintk("Tuner power up failed\n"); + return ret; + } + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +} + +static int zl10039_sleep(struct dvb_frontend *fe) +{ + struct zl10039_state *state = fe->tuner_priv; + int ret; + + dprintk("%s\n", __func__); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + ret = zl10039_writereg(state, GENERAL, 0x80); + if (ret < 0) { + dprintk("Tuner sleep failed\n"); + return ret; + } + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; +} + +static int zl10039_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct zl10039_state *state = fe->tuner_priv; + u8 buf[6]; + u8 bf; + u32 fbw; + u32 div; + int ret; + + dprintk("%s\n", __func__); + dprintk("Set frequency = %d, symbol rate = %d\n", + params->frequency, params->u.qpsk.symbol_rate); + + /* Assumed 10.111 MHz crystal oscillator */ + /* Cancelled num/den 80 to prevent overflow */ + div = (params->frequency * 1000) / 126387; + fbw = (params->u.qpsk.symbol_rate * 27) / 32000; + /* Cancelled num/den 10 to prevent overflow */ + bf = ((fbw * 5088) / 1011100) - 1; + + /*PLL divider*/ + buf[0] = (div >> 8) & 0x7f; + buf[1] = (div >> 0) & 0xff; + /*Reference divider*/ + /* Select reference ratio of 80 */ + buf[2] = 0x1D; + /*PLL test modes*/ + buf[3] = 0x40; + /*RF Control register*/ + buf[4] = 0x6E; /* Bypass enable */ + /*Baseband filter cutoff */ + buf[5] = bf; + + /* Open i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + /* BR = 10, Enable filter adjustment */ + ret = zl10039_writereg(state, BASE1, 0x0A); + if (ret < 0) + goto error; + /* Write new config values */ + ret = zl10039_write(state, PLL0, buf, sizeof(buf)); + if (ret < 0) + goto error; + /* BR = 10, Disable filter adjustment */ + ret = zl10039_writereg(state, BASE1, 0x6A); + if (ret < 0) + goto error; + + /* Close i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + return 0; +error: + dprintk("Error setting tuner\n"); + return ret; +} + +static int zl10039_release(struct dvb_frontend *fe) +{ + struct zl10039_state *state = fe->tuner_priv; + + dprintk("%s\n", __func__); + kfree(state); + fe->tuner_priv = NULL; + return 0; +} + +static struct dvb_tuner_ops zl10039_ops = { + .release = zl10039_release, + .init = zl10039_init, + .sleep = zl10039_sleep, + .set_params = zl10039_set_params, +}; + +struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, + u8 i2c_addr, struct i2c_adapter *i2c) +{ + struct zl10039_state *state = NULL; + + dprintk("%s\n", __func__); + state = kmalloc(sizeof(struct zl10039_state), GFP_KERNEL); + if (state == NULL) + goto error; + + state->i2c = i2c; + state->i2c_addr = i2c_addr; + + /* Open i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + /* check if this is a valid tuner */ + if (zl10039_readreg(state, GENERAL, &state->id) < 0) { + /* Close i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + goto error; + } + /* Close i2c gate */ + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + state->id = state->id & 0x0f; + switch (state->id) { + case ID_ZL10039: + strcpy(fe->ops.tuner_ops.info.name, + "Zarlink ZL10039 DVB-S tuner"); + break; + default: + dprintk("Chip ID=%x does not match a known type\n", state->id); + break; + goto error; + } + + memcpy(&fe->ops.tuner_ops, &zl10039_ops, sizeof(struct dvb_tuner_ops)); + fe->tuner_priv = state; + dprintk("Tuner attached @ i2c address 0x%02x\n", i2c_addr); + return fe; +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(zl10039_attach); + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); +MODULE_DESCRIPTION("Zarlink ZL10039 DVB-S tuner driver"); +MODULE_AUTHOR("Jan D. Louw "); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/zl10039.h b/linux/drivers/media/dvb/frontends/zl10039.h new file mode 100644 index 000000000..5eee7ea16 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/zl10039.h @@ -0,0 +1,40 @@ +/* + Driver for Zarlink ZL10039 DVB-S tuner + + Copyright (C) 2007 Jan D. Louw + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef ZL10039_H +#define ZL10039_H + +#if defined(CONFIG_DVB_ZL10039) || (defined(CONFIG_DVB_ZL10039_MODULE) \ + && defined(MODULE)) +struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, + u8 i2c_addr, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, + u8 i2c_addr, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_ZL10039 */ + +#endif /* ZL10039_H */ -- cgit v1.2.3 From a06280dab2e0258fda0e80e548df8a0e9c0eddca Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sat, 20 Jun 2009 15:54:18 +0300 Subject: Add TeVii S630 USB DVB-S card support. From: Igor M. Liplianin The card includes Intel ce5039(Zarlink zl10039) tuner and Intel ce6313 (Zarlink zl10313) demod. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/dvb/dvb-usb/Kconfig | 6 +- linux/drivers/media/dvb/dvb-usb/dw2102.c | 184 ++++++++++++++++++++++++++++++- 2 files changed, 185 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 496c1a370..8b8bc04ee 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -253,7 +253,7 @@ config DVB_USB_AF9005_REMOTE Afatech AF9005 based receiver. config DVB_USB_DW2102 - tristate "DvbWorld DVB-S/S2 USB2.0 support" + tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support" depends on DVB_USB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE @@ -262,9 +262,11 @@ config DVB_USB_DW2102 select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_SI21XX if !DVB_FE_CUSTOMISE select DVB_TDA10021 if !DVB_FE_CUSTOMISE + select DVB_MT312 if !DVB_FE_CUSTOMISE + select DVB_ZL10039 if !DVB_FE_CUSTOMISE help Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers - and the TeVii S650. + and the TeVii S650, S630. config DVB_USB_CINERGY_T2 tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.c b/linux/drivers/media/dvb/dvb-usb/dw2102.c index 0fc9be43a..c8bdb2e78 100644 --- a/linux/drivers/media/dvb/dvb-usb/dw2102.c +++ b/linux/drivers/media/dvb/dvb-usb/dw2102.c @@ -1,6 +1,6 @@ /* DVB USB framework compliant Linux driver for the * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, -* TeVii S600, S650 Cards +* TeVii S600, S630, S650 Cards * Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by) * * This program is free software; you can redistribute it and/or modify it @@ -18,6 +18,8 @@ #include "eds1547.h" #include "cx24116.h" #include "tda1002x.h" +#include "mt312.h" +#include "zl10039.h" #ifndef USB_PID_DW2102 #define USB_PID_DW2102 0x2102 @@ -39,6 +41,10 @@ #define USB_PID_TEVII_S650 0xd650 #endif +#ifndef USB_PID_TEVII_S630 +#define USB_PID_TEVII_S630 0xd630 +#endif + #define DW210X_READ_MSG 0 #define DW210X_WRITE_MSG 1 @@ -436,6 +442,69 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], return num; } +static int s630_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], + int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int ret = 0; + + if (!d) + return -ENODEV; + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + switch (num) { + case 2: { /* read */ + u8 ibuf[msg[1].len], obuf[3]; + obuf[0] = msg[1].len; + obuf[1] = (msg[0].addr << 1); + obuf[2] = msg[0].buf[0]; + + ret = dw210x_op_rw(d->udev, 0x90, 0, 0, + obuf, 3, DW210X_WRITE_MSG); + msleep(5); + ret = dw210x_op_rw(d->udev, 0x91, 0, 0, + ibuf, msg[1].len, DW210X_READ_MSG); + memcpy(msg[1].buf, ibuf, msg[1].len); + break; + } + case 1: + switch (msg[0].addr) { + case 0x60: + case 0x0e: { + /* write to zl10313, zl10039 register, */ + u8 obuf[msg[0].len + 2]; + obuf[0] = msg[0].len + 1; + obuf[1] = (msg[0].addr << 1); + memcpy(obuf + 2, msg[0].buf, msg[0].len); + ret = dw210x_op_rw(d->udev, 0x80, 0, 0, + obuf, msg[0].len + 2, DW210X_WRITE_MSG); + break; + } + case (DW2102_RC_QUERY): { + u8 ibuf[4]; + ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, + ibuf, 4, DW210X_READ_MSG); + msg[0].buf[0] = ibuf[3]; + break; + } + case (DW2102_VOLTAGE_CTRL): { + u8 obuf[2]; + obuf[0] = 0x03; + obuf[1] = msg[0].buf[0]; + ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, + obuf, 2, DW210X_WRITE_MSG); + break; + } + } + + break; + } + + mutex_unlock(&d->i2c_mutex); + return num; +} + static u32 dw210x_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; @@ -481,6 +550,14 @@ static struct i2c_algorithm dw3101_i2c_algo = { #endif }; +static struct i2c_algorithm s630_i2c_algo = { + .master_xfer = s630_i2c_transfer, + .functionality = dw210x_i2c_func, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif +}; + static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) { int i; @@ -505,6 +582,37 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) return 0; }; +static int s630_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) +{ + int i, ret; + u8 buf[3], eeprom[256], eepromline[16]; + + for (i = 0; i < 256; i++) { + buf[0] = 1; + buf[1] = 0xa0; + buf[2] = i; + ret = dw210x_op_rw(d->udev, 0x90, 0, 0, + buf, 3, DW210X_WRITE_MSG); + ret = dw210x_op_rw(d->udev, 0x91, 0, 0, + buf, 1, DW210X_READ_MSG); + if (ret < 0) { + err("read eeprom failed."); + return -1; + } else { + eepromline[i % 16] = buf[0]; + eeprom[i] = buf[0]; + } + + if ((i % 16) == 15) { + deb_xfer("%02x: ", i - 15); + debug_dump(eepromline, 16, deb_xfer); + } + } + + memcpy(mac, eeprom + 16, 6); + return 0; +}; + static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { static u8 command_13v[1] = {0x00}; @@ -550,6 +658,10 @@ static struct tda10023_config dw3101_tda10023_config = { .invert = 1, }; +static struct mt312_config zl313_config = { + .demod_address = 0x0e, +}; + static int dw2104_frontend_attach(struct dvb_usb_adapter *d) { if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config, @@ -611,6 +723,18 @@ static int dw3101_frontend_attach(struct dvb_usb_adapter *d) return -EIO; } +static int s630_frontend_attach(struct dvb_usb_adapter *d) +{ + d->fe = dvb_attach(mt312_attach, &zl313_config, + &d->dev->i2c_adap); + if (d->fe != NULL) { + d->fe->ops.set_voltage = dw210x_set_voltage; + info("Attached zl10313!\n"); + return 0; + } + return -EIO; +} + static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) { dvb_attach(dvb_pll_attach, adap->fe, 0x60, @@ -634,6 +758,14 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) return 0; } +static int s630_zl10039_tuner_attach(struct dvb_usb_adapter *adap) +{ + dvb_attach(zl10039_attach, adap->fe, 0x60, + &adap->dev->i2c_adap); + + return 0; +} + static struct dvb_usb_rc_key dw210x_rc_keys[] = { { 0xf8, 0x0a, KEY_Q }, /*power*/ { 0xf8, 0x0c, KEY_M }, /*mute*/ @@ -778,7 +910,7 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) } *state = REMOTE_NO_KEY_PRESSED; - if (dw2102_i2c_transfer(&d->i2c_adap, &msg, 1) == 1) { + if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { for (i = 0; i < keymap_size ; i++) { if (keymap[i].data == msg.buf[0]) { *state = REMOTE_KEY_PRESSED; @@ -807,6 +939,7 @@ static struct usb_device_id dw2102_table[] = { {USB_DEVICE(0x9022, USB_PID_TEVII_S650)}, {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)}, {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)}, + {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, { } }; @@ -821,6 +954,7 @@ static int dw2102_load_firmware(struct usb_device *dev, u8 reset16[] = {0, 0, 0, 0, 0, 0, 0}; const struct firmware *fw; const char *filename = "dvb-usb-dw2101.fw"; + switch (dev->descriptor.idProduct) { case 0x2101: ret = request_firmware(&fw, filename, &dev->dev); @@ -1068,6 +1202,48 @@ static struct dvb_usb_device_properties dw3101_properties = { } }; +static struct dvb_usb_device_properties s630_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-s630.fw", + .no_reconnect = 1, + + .i2c_algo = &s630_i2c_algo, + .rc_key_map = tevii_rc_keys, + .rc_key_map_size = ARRAY_SIZE(tevii_rc_keys), + .rc_interval = 150, + .rc_query = dw2102_rc_query, + + .generic_bulk_ctrl_endpoint = 0x81, + .num_adapters = 1, + .download_firmware = dw2102_load_firmware, + .read_mac_address = s630_read_mac_address, + .adapter = { + { + .frontend_attach = s630_frontend_attach, + .streaming_ctrl = NULL, + .tuner_attach = s630_zl10039_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, + } + }, + .num_device_descs = 1, + .devices = { + {"TeVii S630 USB", + {&dw2102_table[6], NULL}, + {NULL}, + }, + } +}; + static int dw2102_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -1076,6 +1252,8 @@ static int dw2102_probe(struct usb_interface *intf, 0 == dvb_usb_device_init(intf, &dw2104_properties, THIS_MODULE, NULL, adapter_nr) || 0 == dvb_usb_device_init(intf, &dw3101_properties, + THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &s630_properties, THIS_MODULE, NULL, adapter_nr)) { return 0; } @@ -1109,6 +1287,6 @@ module_exit(dw2102_module_exit); MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," " DVB-C 3101 USB2.0," - " TeVii S600, S650 USB2.0 devices"); + " TeVii S600, S630, S650 USB2.0 devices"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From b45791b1525cf26b186d476f84229cb9ef563f99 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 21 Jun 2009 23:45:33 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/Makefile | 2 +- .../libv4lconvert/control/libv4lcontrol-priv.h | 4 ++++ .../libv4l/libv4lconvert/control/libv4lcontrol.c | 23 ++++++++++++++++++++-- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/v4l2-apps/libv4l/Makefile b/v4l2-apps/libv4l/Makefile index acec5c540..b0fdd6331 100644 --- a/v4l2-apps/libv4l/Makefile +++ b/v4l2-apps/libv4l/Makefile @@ -1,5 +1,5 @@ LIB_RELEASE=0 -V4L2_LIB_VERSION=$(LIB_RELEASE).5.99 +V4L2_LIB_VERSION=$(LIB_RELEASE).6.0-test all install: $(MAKE) -C libv4lconvert V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@ diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h index 6211ee22a..3394132e0 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h @@ -49,6 +49,10 @@ struct v4lcontrol_flags_info { const char *product; */ int flags; int default_gamma; +/* Some seldom used dmi strings (for notebooks with bogus info in the board + entries, but usefull info elsewhere). We keep this at the end as to not + polute the initalizers for the normal case. */ + const char *dmi_system_version; }; #endif diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index eae1438e1..f23b18026 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -58,7 +58,9 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { { 0x093a, 0x2476, 0, NULL, NULL, V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED|V4LCONTROL_WANTS_WB, 1500 }, /* Laptops */ - { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vn ", + { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vn ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N51Vg ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "F7SR ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, @@ -68,12 +70,18 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "N20A ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Ke ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Sr ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1Sn ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G2S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x5986, 0x0205, 0, "LENOVO", "Base Board Product Name", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED, 0, "Lenovo IdeaPad U330" }, /* Second: devices which should use some software processing by default */ /* Pac207 based devices */ @@ -111,6 +119,7 @@ static void v4lcontrol_init_flags(struct v4lcontrol_data *data) unsigned short product_id = 0; char dmi_board_vendor[512] = ""; char dmi_board_name[512]= ""; + char dmi_system_version[512]= ""; int i, minor; char c, *s, buf[32]; struct v4l2_input input; @@ -206,6 +215,14 @@ static void v4lcontrol_init_flags(struct v4lcontrol_data *data) fclose(f); } + f = fopen("/sys/devices/virtual/dmi/id/product_version", "r"); + if (f) { + s = fgets(dmi_system_version, sizeof(dmi_system_version), f); + if (s) + s[strlen(s) - 1] = 0; + fclose(f); + } + for (i = 0; i < ARRAY_SIZE(v4lcontrol_flags); i++) if (v4lcontrol_flags[i].vendor_id == vendor_id && v4lcontrol_flags[i].product_id == @@ -213,7 +230,9 @@ static void v4lcontrol_init_flags(struct v4lcontrol_data *data) (v4lcontrol_flags[i].dmi_board_vendor == NULL || !strcmp(v4lcontrol_flags[i].dmi_board_vendor, dmi_board_vendor)) && (v4lcontrol_flags[i].dmi_board_name == NULL || - !strcmp(v4lcontrol_flags[i].dmi_board_name, dmi_board_name))) { + !strcmp(v4lcontrol_flags[i].dmi_board_name, dmi_board_name)) && + (v4lcontrol_flags[i].dmi_system_version == NULL || + !strcmp(v4lcontrol_flags[i].dmi_system_version, dmi_system_version))) { data->flags |= v4lcontrol_flags[i].flags; data->flags_info = &v4lcontrol_flags[i]; break; -- cgit v1.2.3 From 408926f2c84bd8478d27ef988a2db4a7bb7e8f0d Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 22 Jun 2009 10:15:35 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index f23b18026..9b64f97cd 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -74,8 +74,11 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Sr ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + /* The G1S has been seen with 2 different board name strings */ { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1S ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1Sn ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G2S ", -- cgit v1.2.3 From e9e321113789949491c97d93eae4f5e9bacc86f1 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 24 Jun 2009 14:07:03 +0200 Subject: libv4l: whitebalance fix divide by 0 and avoid abrupt changes From: Hans de Goede libv4l: whitebalance fix divide by 0 and avoid abrupt changes Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 4 +- v4l2-apps/libv4l/Makefile | 2 +- .../processing/libv4lprocessing-priv.h | 6 + .../libv4lconvert/processing/libv4lprocessing.c | 5 +- .../libv4l/libv4lconvert/processing/whitebalance.c | 136 ++++++++++++++------- 5 files changed, 107 insertions(+), 46 deletions(-) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index e69a8c8f4..638d87eba 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -6,8 +6,8 @@ libv4l-0.6.0 an external helper as I've failed to contact Mark W. McClelland to get permission to relicense the code. If you know a working email address for Mark W. McClelland, please let me know. -* Fix a bug in the always report widths which are a multiple of 8 code added - in 0.5.97 +* Add various laptop models to the upside down devices table +* Many bug fixes (see the mercurial tree for details) libv4l-0.5.99 ------------- diff --git a/v4l2-apps/libv4l/Makefile b/v4l2-apps/libv4l/Makefile index b0fdd6331..8f72059e5 100644 --- a/v4l2-apps/libv4l/Makefile +++ b/v4l2-apps/libv4l/Makefile @@ -1,5 +1,5 @@ LIB_RELEASE=0 -V4L2_LIB_VERSION=$(LIB_RELEASE).6.0-test +V4L2_LIB_VERSION=$(LIB_RELEASE).6.0 all install: $(MAKE) -C libv4lconvert V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@ diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing-priv.h b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing-priv.h index b73c73b53..c314231cd 100644 --- a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing-priv.h +++ b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing-priv.h @@ -30,6 +30,7 @@ struct v4lprocessing_data { struct v4lcontrol_data *control; int fd; int do_process; + int controls_changed; /* True if any of the lookup tables does not contain linear 0-255 */ int lookup_table_active; @@ -41,6 +42,11 @@ struct v4lprocessing_data { unsigned char green[256]; unsigned char comp2[256]; /* Filter private data for filters which need it */ + /* whitebalance.c data */ + int green_avg; + int comp1_avg; + int comp2_avg; + /* gamma.c data */ int last_gamma; unsigned char gamma_table[256]; }; diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c index cbbcca73c..af0056e94 100644 --- a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c +++ b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c @@ -62,6 +62,8 @@ int v4lprocessing_pre_processing(struct v4lprocessing_data *data) data->do_process = 1; } + data->controls_changed |= v4lcontrol_controls_changed(data->control); + return data->do_process; } @@ -167,9 +169,10 @@ void v4lprocessing_processing(struct v4lprocessing_data *data, return; /* Non supported pix format */ } - if (v4lcontrol_controls_changed(data->control) || + if (data->controls_changed || data->lookup_table_update_counter == V4L2PROCESSING_UPDATE_RATE) { v4lprocessing_update_lookup_tables(data, buf, fmt); + data->controls_changed = 0; data->lookup_table_update_counter = 0; } else data->lookup_table_update_counter++; diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/whitebalance.c b/v4l2-apps/libv4l/libv4lconvert/processing/whitebalance.c index 64d20b3ff..5ee0cfaa8 100644 --- a/v4l2-apps/libv4l/libv4lconvert/processing/whitebalance.c +++ b/v4l2-apps/libv4l/libv4lconvert/processing/whitebalance.c @@ -27,10 +27,82 @@ #include "libv4lprocessing-priv.h" #include "../libv4lconvert-priv.h" /* for PIX_FMT defines */ -#define CLIP(color) (unsigned char)(((color)>0xff)?0xff:(((color)<0)?0:(color))) +#define CLIP256(color) (((color)>0xff)?0xff:(((color)<0)?0:(color))) +#define CLIP(color, min, max) (((color)>(max))?(max):(((color)<(min))?(min):(color))) static int whitebalance_active(struct v4lprocessing_data *data) { - return v4lcontrol_get_ctrl(data->control, V4LCONTROL_WHITEBALANCE); + int wb; + + wb = v4lcontrol_get_ctrl(data->control, V4LCONTROL_WHITEBALANCE); + if (!wb) { + /* Reset cached color averages */ + data->green_avg = 0; + } + + return wb; +} + +static int whitebalance_calculate_lookup_tables_generic( + struct v4lprocessing_data *data, int green_avg, int comp1_avg, int comp2_avg) +{ + int i, avg_avg; + const int max_step = 64; + + /* Clip averages (restricts maximum white balance correction) */ + green_avg = CLIP(green_avg, 512, 3072); + comp1_avg = CLIP(comp1_avg, 512, 3072); + comp2_avg = CLIP(comp2_avg, 512, 3072); + + /* First frame ? */ + if (data->green_avg == 0) { + data->green_avg = green_avg; + data->comp1_avg = comp1_avg; + data->comp2_avg = comp2_avg; + } else { + /* Slowly adjust the averages used for the correction, so that we + do not get a sudden change in colors */ + if (abs(data->green_avg - green_avg) > max_step) { + if (data->green_avg < green_avg) + data->green_avg += max_step; + else + data->green_avg -= max_step; + } + else + data->green_avg = green_avg; + + if (abs(data->comp1_avg - comp1_avg) > max_step) { + if (data->comp1_avg < comp1_avg) + data->comp1_avg += max_step; + else + data->comp1_avg -= max_step; + } + else + data->comp1_avg = comp1_avg; + + if (abs(data->comp2_avg - comp2_avg) > max_step) { + if (data->comp2_avg < comp2_avg) + data->comp2_avg += max_step; + else + data->comp2_avg -= max_step; + } + else + data->comp2_avg = comp2_avg; + } + + if (abs(data->green_avg - data->comp1_avg) < max_step && + abs(data->green_avg - data->comp2_avg) < max_step && + abs(data->comp1_avg - data->comp2_avg) < max_step) + return 0; + + avg_avg = (data->green_avg + data->comp1_avg + data->comp2_avg) / 3; + + for (i = 0; i < 256; i++) { + data->comp1[i] = CLIP256(data->comp1[i] * avg_avg / data->comp1_avg); + data->green[i] = CLIP256(data->green[i] * avg_avg / data->green_avg); + data->comp2[i] = CLIP256(data->comp2[i] * avg_avg / data->comp2_avg); + } + + return 1; } static int whitebalance_calculate_lookup_tables_bayer( @@ -38,7 +110,7 @@ static int whitebalance_calculate_lookup_tables_bayer( const struct v4l2_format *fmt, int starts_with_green) { int x, y, a1 = 0, a2 = 0, b1 = 0, b2 = 0; - int green_avg, comp1_avg, comp2_avg, avg_avg; + int green_avg, comp1_avg, comp2_avg; for (y = 0; y < fmt->fmt.pix.height; y += 2) { for (x = 0; x < fmt->fmt.pix.width; x += 2) { @@ -54,37 +126,29 @@ static int whitebalance_calculate_lookup_tables_bayer( } if (starts_with_green) { - green_avg = (a1 + b2) / 512; - comp1_avg = a2 / 256; - comp2_avg = b1 / 256; + green_avg = a1 / 2 + b2 / 2; + comp1_avg = a2; + comp2_avg = b1; } else { - green_avg = (a2 + b1) / 512; - comp1_avg = a1 / 256; - comp2_avg = b2 / 256; + green_avg = a2 / 2 + b1 / 2; + comp1_avg = a1; + comp2_avg = b2; } - x = fmt->fmt.pix.width * fmt->fmt.pix.height / 64; - if (abs(green_avg - comp1_avg) < x && - abs(green_avg - comp2_avg) < x && - abs(comp1_avg - comp2_avg) < x) - return 0; - - avg_avg = (green_avg + comp1_avg + comp2_avg) / 3; - - for (x = 0; x < 256; x++) { - data->comp1[x] = CLIP(data->comp1[x] * avg_avg / comp1_avg); - data->green[x] = CLIP(data->green[x] * avg_avg / green_avg); - data->comp2[x] = CLIP(data->comp2[x] * avg_avg / comp2_avg); - } + /* Norm avg to ~ 0 - 4095 */ + green_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 64; + comp1_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 64; + comp2_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 64; - return 1; + return whitebalance_calculate_lookup_tables_generic(data, green_avg, + comp1_avg, comp2_avg); } static int whitebalance_calculate_lookup_tables_rgb( struct v4lprocessing_data *data, unsigned char *buf, const struct v4l2_format *fmt) { - int x, y, green_avg = 0, comp1_avg = 0, comp2_avg = 0, avg_avg; + int x, y, green_avg = 0, comp1_avg = 0, comp2_avg = 0; for (y = 0; y < fmt->fmt.pix.height; y++) { for (x = 0; x < fmt->fmt.pix.width; x++) { @@ -95,25 +159,13 @@ static int whitebalance_calculate_lookup_tables_rgb( buf += fmt->fmt.pix.bytesperline - fmt->fmt.pix.width * 3; } - x = fmt->fmt.pix.width * fmt->fmt.pix.height * 4; - if (abs(green_avg - comp1_avg) < x && - abs(green_avg - comp2_avg) < x && - abs(comp1_avg - comp2_avg) < x) - return 0; - - /* scale to avoid integer overflows */ - green_avg /= 256; - comp1_avg /= 256; - comp2_avg /= 256; - avg_avg = (green_avg + comp1_avg + comp2_avg) / 3; + /* Norm avg to ~ 0 - 4095 */ + green_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 16; + comp1_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 16; + comp2_avg /= fmt->fmt.pix.width * fmt->fmt.pix.height / 16; - for (x = 0; x < 256; x++) { - data->comp1[x] = CLIP(data->comp1[x] * avg_avg / comp1_avg); - data->green[x] = CLIP(data->green[x] * avg_avg / green_avg); - data->comp2[x] = CLIP(data->comp2[x] * avg_avg / comp2_avg); - } - - return 1; + return whitebalance_calculate_lookup_tables_generic(data, green_avg, + comp1_avg, comp2_avg); } -- cgit v1.2.3 From 3a2464da9eecc69416435aa55658c89dc7e305d9 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 24 Jun 2009 14:11:00 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 9b64f97cd..eb7e11a68 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -83,6 +83,9 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G2S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + /* Asus notebook in disguise */ + { 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_BG46", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x5986, 0x0205, 0, "LENOVO", "Base Board Product Name", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED, 0, "Lenovo IdeaPad U330" }, -- cgit v1.2.3 From 0e5b9d79fea526431aebf58a3f58fa77381205ce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Aug 2009 14:40:54 -0300 Subject: versions: Fix compilation with kernel 2.6.16 From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l/versions.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/v4l/versions.txt b/v4l/versions.txt index 01b553d6c..9e23e500c 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -49,6 +49,7 @@ DVB_FIREDTV [2.6.20] #This driver requires HID_REQ_GET_REPORT USB_SI470X +RADIO_SI470X # use of struct delayed_work USB_GSPCA_FINEPIX # uses linux/hid.h and struct delayed_work -- cgit v1.2.3 From 8b3e3e1439154e2c003f09c7fdcc0253bf878b66 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 12 Aug 2009 16:21:44 -0700 Subject: adds webcam for Micron device MT9M111 0x143A to em28xx From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Steve Gotthardt [mchehab@redhat.com: fix merge conflict and a few CodingStyle issues] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 40 +++++++++++++++++++++++-- linux/drivers/media/video/em28xx/em28xx.h | 1 + 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index c936e7660..a38586176 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1802,6 +1802,25 @@ static inline void em28xx_set_model(struct em28xx *dev) EM28XX_I2C_FREQ_100_KHZ; } + +/* FIXME: Should be replaced by a proper mt9m111 driver */ +static int em28xx_initialize_mt9m111(struct em28xx *dev) +{ + int i; + unsigned char regs[][3] = { + { 0x0d, 0x00, 0x01, }, /* reset and use defaults */ + { 0x0d, 0x00, 0x00, }, + { 0x0a, 0x00, 0x21, }, + { 0x21, 0x04, 0x00, }, /* full readout speed, no row/col skipping */ + }; + + for (i = 0; i < ARRAY_SIZE(regs); i++) + i2c_master_send(&dev->i2c_client, ®s[i][0], 3); + + return 0; +} + + /* FIXME: Should be replaced by a proper mt9m001 driver */ static int em28xx_initialize_mt9m001(struct em28xx *dev) { @@ -1830,7 +1849,7 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev) /* HINT method: webcam I2C chips * - * This method work for webcams with Micron sensors + * This method works for webcams with Micron sensors */ static int em28xx_hint_sensor(struct em28xx *dev) { @@ -1876,6 +1895,23 @@ static int em28xx_hint_sensor(struct em28xx *dev) dev->vinctl = 0x00; break; + + case 0x143a: /* MT9M111 as found in the ECS G200 */ + dev->model = EM2750_BOARD_UNKNOWN; + em28xx_set_model(dev); + + sensor_name = "mt9m111"; + dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ; + dev->em28xx_sensor = EM28XX_MT9M111; + em28xx_initialize_mt9m111(dev); + dev->sensor_xres = 640; + dev->sensor_yres = 512; + + dev->vinmode = 0x0a; + dev->vinctl = 0x00; + + break; + #if 0 case 0x8411: case 0x8421: @@ -1896,7 +1932,7 @@ static int em28xx_hint_sensor(struct em28xx *dev) break; default: - printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version)); + printk("Unknown Micron Sensor 0x%04x\n", version); return -EINVAL; } diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index c76da6985..70a41b640 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -368,6 +368,7 @@ enum em28xx_sensor { EM28XX_NOSENSOR = 0, EM28XX_MT9V011, EM28XX_MT9M001, + EM28XX_MT9M111, }; enum em28xx_adecoder { -- cgit v1.2.3 From 6e05c460e54586ee98bad3744eef1e47d90176fa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Jun 2009 07:22:55 +0000 Subject: Siano: Fixed SDIO compilation bugs From: Udi Atar Fixed SDIO compilation bugs (for latest kernel). Also fixed a memory overrun issue in buffer management. Priority: normal Signed-off-by: Udi Atar Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/smssdio.c | 54 ++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/linux/drivers/media/dvb/siano/smssdio.c b/linux/drivers/media/dvb/siano/smssdio.c index dfaa49a53..d1d652e7f 100644 --- a/linux/drivers/media/dvb/siano/smssdio.c +++ b/linux/drivers/media/dvb/siano/smssdio.c @@ -46,6 +46,7 @@ #define SMSSDIO_DATA 0x00 #define SMSSDIO_INT 0x04 +#define SMSSDIO_BLOCK_SIZE 128 static const struct sdio_device_id smssdio_ids[] = { {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR), @@ -85,7 +86,8 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size) sdio_claim_host(smsdev->func); while (size >= smsdev->func->cur_blksize) { - ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1); + ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA, + buffer, smsdev->func->cur_blksize); if (ret) goto out; @@ -94,8 +96,8 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size) } if (size) { - ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA, - buffer, size); + ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA, + buffer, size); } out: @@ -125,23 +127,23 @@ static void smssdio_interrupt(struct sdio_func *func) */ isr = sdio_readb(func, SMSSDIO_INT, &ret); if (ret) { - dev_err(&smsdev->func->dev, - "Unable to read interrupt register!\n"); + sms_err("Unable to read interrupt register!\n"); return; } if (smsdev->split_cb == NULL) { cb = smscore_getbuffer(smsdev->coredev); if (!cb) { - dev_err(&smsdev->func->dev, - "Unable to allocate data buffer!\n"); + sms_err("Unable to allocate data buffer!\n"); return; } - ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1); + ret = sdio_memcpy_fromio(smsdev->func, + cb->p, + SMSSDIO_DATA, + SMSSDIO_BLOCK_SIZE); if (ret) { - dev_err(&smsdev->func->dev, - "Error %d reading initial block!\n", ret); + sms_err("Error %d reading initial block!\n", ret); return; } @@ -152,7 +154,10 @@ static void smssdio_interrupt(struct sdio_func *func) return; } - size = hdr->msgLength - smsdev->func->cur_blksize; + if (hdr->msgLength > smsdev->func->cur_blksize) + size = hdr->msgLength - smsdev->func->cur_blksize; + else + size = 0; } else { cb = smsdev->split_cb; hdr = cb->p; @@ -162,23 +167,24 @@ static void smssdio_interrupt(struct sdio_func *func) smsdev->split_cb = NULL; } - if (hdr->msgLength > smsdev->func->cur_blksize) { + if (size) { void *buffer; - size = ALIGN(size, 128); - buffer = cb->p + hdr->msgLength; + buffer = cb->p + (hdr->msgLength - size); + size = ALIGN(size, SMSSDIO_BLOCK_SIZE); - BUG_ON(smsdev->func->cur_blksize != 128); + BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE); /* * First attempt to transfer all of it in one go... */ - ret = sdio_read_blocks(smsdev->func, buffer, - SMSSDIO_DATA, size / 128); + ret = sdio_memcpy_fromio(smsdev->func, + buffer, + SMSSDIO_DATA, + size); if (ret && ret != -EINVAL) { smscore_putbuffer(smsdev->coredev, cb); - dev_err(&smsdev->func->dev, - "Error %d reading data from card!\n", ret); + sms_err("Error %d reading data from card!\n", ret); return; } @@ -191,12 +197,12 @@ static void smssdio_interrupt(struct sdio_func *func) */ if (ret == -EINVAL) { while (size) { - ret = sdio_read_blocks(smsdev->func, - buffer, SMSSDIO_DATA, 1); + ret = sdio_memcpy_fromio(smsdev->func, + buffer, SMSSDIO_DATA, + smsdev->func->cur_blksize); if (ret) { smscore_putbuffer(smsdev->coredev, cb); - dev_err(&smsdev->func->dev, - "Error %d reading " + sms_err("Error %d reading " "data from card!\n", ret); return; } @@ -269,7 +275,7 @@ static int smssdio_probe(struct sdio_func *func, if (ret) goto release; - ret = sdio_set_block_size(func, 128); + ret = sdio_set_block_size(func, SMSSDIO_BLOCK_SIZE); if (ret) goto disable; -- cgit v1.2.3 From 515fc60834c8e3e51c3fb97e362c74a3324d817e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 28 Jun 2009 13:37:50 +0200 Subject: uvcvideo: Restructure the driver to support multiple simultaneous streams. From: Laurent Pinchart As a first step towards multiple streaming interfaces support, reorganize the driver's data structures to cleanly separate video control and video streaming data. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_driver.c | 174 ++++++------ linux/drivers/media/video/uvc/uvc_isight.c | 7 +- linux/drivers/media/video/uvc/uvc_v4l2.c | 195 +++++++------- linux/drivers/media/video/uvc/uvc_video.c | 415 +++++++++++++++-------------- linux/drivers/media/video/uvc/uvcvideo.h | 86 +++--- 5 files changed, 456 insertions(+), 421 deletions(-) diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 1d09751a3..70d15a926 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -551,6 +551,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, } mutex_init(&streaming->mutex); + streaming->dev = dev; streaming->intf = usb_get_intf(intf); streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; @@ -751,7 +752,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, streaming->maxpsize = psize; } - list_add_tail(&streaming->list, &dev->streaming); + list_add_tail(&streaming->list, &dev->streams); return 0; error: @@ -1167,13 +1168,75 @@ next_descriptor: */ static void uvc_unregister_video(struct uvc_device *dev) { - if (dev->video.vdev) { - if (dev->video.vdev->minor == -1) - video_device_release(dev->video.vdev); + struct uvc_streaming *streaming; + + list_for_each_entry(streaming, &dev->streams, list) { + if (streaming->vdev == NULL) + continue; + + if (streaming->vdev->minor == -1) + video_device_release(streaming->vdev); else - video_unregister_device(dev->video.vdev); - dev->video.vdev = NULL; + video_unregister_device(streaming->vdev); + streaming->vdev = NULL; + } +} + +static int uvc_register_video(struct uvc_device *dev, + struct uvc_streaming *stream) +{ + struct video_device *vdev; + struct uvc_entity *term; + int ret; + + if (uvc_trace_param & UVC_TRACE_PROBE) { + uvc_printk(KERN_INFO, "Found a valid video chain ("); + list_for_each_entry(term, &dev->video.iterms, chain) { + printk("%d", term->id); + if (term->chain.next != &dev->video.iterms) + printk(","); + } + printk(" -> %d).\n", dev->video.oterm->id); + } + + /* Initialize the streaming interface with default streaming + * parameters. + */ + ret = uvc_video_init(stream); + if (ret < 0) { + uvc_printk(KERN_ERR, "Failed to initialize the device " + "(%d).\n", ret); + return ret; + } + + /* Register the device with V4L. */ + vdev = video_device_alloc(); + if (vdev == NULL) + return -1; + + /* We already hold a reference to dev->udev. The video device will be + * unregistered before the reference is released, so we don't need to + * get another one. + */ + vdev->parent = &dev->intf->dev; + vdev->minor = -1; + vdev->fops = &uvc_fops; + vdev->release = video_device_release; + strlcpy(vdev->name, dev->name, sizeof vdev->name); + + /* Set the driver data before calling video_register_device, otherwise + * uvc_v4l2_open might race us. + */ + stream->vdev = vdev; + video_set_drvdata(vdev, stream); + + if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) < 0) { + stream->vdev = NULL; + video_device_release(vdev); + return -1; } + + return 0; } /* @@ -1419,7 +1482,7 @@ static int uvc_scan_chain(struct uvc_video_device *video) } /* - * Register the video devices. + * Scan the device for video chains and register video devices. * * The driver currently supports a single video device per control interface * only. The terminal and units must match the following structure: @@ -1432,15 +1495,14 @@ static int uvc_scan_chain(struct uvc_video_device *video) * Extension Units connected to the main chain as single-unit branches are * also supported. */ -static int uvc_register_video(struct uvc_device *dev) +static int uvc_scan_device(struct uvc_device *dev) { - struct video_device *vdev; struct uvc_entity *term; - int found = 0, ret; + int found = 0; /* Check if the control interface matches the structure we expect. */ list_for_each_entry(term, &dev->entities, list) { - struct uvc_streaming *streaming; + struct uvc_streaming *stream; if (!UVC_ENTITY_IS_TERM(term) || !UVC_ENTITY_IS_OTERM(term)) continue; @@ -1454,17 +1516,14 @@ static int uvc_register_video(struct uvc_device *dev) if (uvc_scan_chain(&dev->video) < 0) continue; - list_for_each_entry(streaming, &dev->streaming, list) { - if (streaming->header.bTerminalLink == + list_for_each_entry(stream, &dev->streams, list) { + if (stream->header.bTerminalLink == dev->video.sterm->id) { - dev->video.streaming = streaming; + uvc_register_video(dev, stream); found = 1; break; } } - - if (found) - break; } if (!found) { @@ -1472,55 +1531,6 @@ static int uvc_register_video(struct uvc_device *dev) return -1; } - if (uvc_trace_param & UVC_TRACE_PROBE) { - uvc_printk(KERN_INFO, "Found a valid video chain ("); - list_for_each_entry(term, &dev->video.iterms, chain) { - printk("%d", term->id); - if (term->chain.next != &dev->video.iterms) - printk(","); - } - printk(" -> %d).\n", dev->video.oterm->id); - } - - /* Initialize the video buffers queue. */ - uvc_queue_init(&dev->video.queue, dev->video.streaming->type); - - /* Initialize the streaming interface with default streaming - * parameters. - */ - if ((ret = uvc_video_init(&dev->video)) < 0) { - uvc_printk(KERN_ERR, "Failed to initialize the device " - "(%d).\n", ret); - return ret; - } - - /* Register the device with V4L. */ - vdev = video_device_alloc(); - if (vdev == NULL) - return -1; - - /* We already hold a reference to dev->udev. The video device will be - * unregistered before the reference is released, so we don't need to - * get another one. - */ - vdev->parent = &dev->intf->dev; - vdev->minor = -1; - vdev->fops = &uvc_fops; - vdev->release = video_device_release; - strlcpy(vdev->name, dev->name, sizeof vdev->name); - - /* Set the driver data before calling video_register_device, otherwise - * uvc_v4l2_open might race us. - */ - dev->video.vdev = vdev; - video_set_drvdata(vdev, &dev->video); - - if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) < 0) { - dev->video.vdev = NULL; - video_device_release(vdev); - return -1; - } - return 0; } @@ -1559,7 +1569,7 @@ void uvc_delete(struct kref *kref) kfree(entity); } - list_for_each_safe(p, n, &dev->streaming) { + list_for_each_safe(p, n, &dev->streams) { struct uvc_streaming *streaming; streaming = list_entry(p, struct uvc_streaming, list); usb_driver_release_interface(&uvc_driver.driver, @@ -1593,7 +1603,7 @@ static int uvc_probe(struct usb_interface *intf, return -ENOMEM; INIT_LIST_HEAD(&dev->entities); - INIT_LIST_HEAD(&dev->streaming); + INIT_LIST_HEAD(&dev->streams); kref_init(&dev->kref); atomic_set(&dev->users, 0); @@ -1634,8 +1644,8 @@ static int uvc_probe(struct usb_interface *intf, if (uvc_ctrl_init_device(dev) < 0) goto error; - /* Register the video devices. */ - if (uvc_register_video(dev) < 0) + /* Scan the device for video chains and register video devices. */ + if (uvc_scan_device(dev) < 0) goto error; /* Save our data pointer in the interface data. */ @@ -1689,6 +1699,7 @@ static void uvc_disconnect(struct usb_interface *intf) static int uvc_suspend(struct usb_interface *intf, pm_message_t message) { struct uvc_device *dev = usb_get_intfdata(intf); + struct uvc_streaming *stream; uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n", intf->cur_altsetting->desc.bInterfaceNumber); @@ -1698,18 +1709,20 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) UVC_SC_VIDEOCONTROL) return uvc_status_suspend(dev); - if (dev->video.streaming->intf != intf) { - uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB " - "interface mismatch.\n"); - return -EINVAL; + list_for_each_entry(stream, &dev->streams, list) { + if (stream->intf == intf) + return uvc_video_suspend(stream); } - return uvc_video_suspend(&dev->video); + uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB interface " + "mismatch.\n"); + return -EINVAL; } static int __uvc_resume(struct usb_interface *intf, int reset) { struct uvc_device *dev = usb_get_intfdata(intf); + struct uvc_streaming *stream; uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n", intf->cur_altsetting->desc.bInterfaceNumber); @@ -1726,13 +1739,14 @@ static int __uvc_resume(struct usb_interface *intf, int reset) return uvc_status_resume(dev); } - if (dev->video.streaming->intf != intf) { - uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB " - "interface mismatch.\n"); - return -EINVAL; + list_for_each_entry(stream, &dev->streams, list) { + if (stream->intf == intf) + return uvc_video_resume(stream); } - return uvc_video_resume(&dev->video); + uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface " + "mismatch.\n"); + return -EINVAL; } static int uvc_resume(struct usb_interface *intf) diff --git a/linux/drivers/media/video/uvc/uvc_isight.c b/linux/drivers/media/video/uvc/uvc_isight.c index 436f46268..a9285b570 100644 --- a/linux/drivers/media/video/uvc/uvc_isight.c +++ b/linux/drivers/media/video/uvc/uvc_isight.c @@ -99,7 +99,7 @@ static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf, return 0; } -void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, +void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream, struct uvc_buffer *buf) { int ret, i; @@ -120,7 +120,7 @@ void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, * processes the data of the first payload of the new frame. */ do { - ret = isight_decode(&video->queue, buf, + ret = isight_decode(&stream->queue, buf, urb->transfer_buffer + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length); @@ -130,7 +130,8 @@ void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, if (buf->state == UVC_BUF_STATE_DONE || buf->state == UVC_BUF_STATE_ERROR) - buf = uvc_queue_next_buffer(&video->queue, buf); + buf = uvc_queue_next_buffer(&stream->queue, + buf); } while (ret == -EAGAIN); } } diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index 31a9ed4ff..3379e1320 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -103,7 +103,7 @@ static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval) return interval; } -static int uvc_v4l2_try_format(struct uvc_video_device *video, +static int uvc_v4l2_try_format(struct uvc_streaming *stream, struct v4l2_format *fmt, struct uvc_streaming_control *probe, struct uvc_format **uvc_format, struct uvc_frame **uvc_frame) { @@ -116,7 +116,7 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video, int ret = 0; __u8 *fcc; - if (fmt->type != video->streaming->type) + if (fmt->type != stream->type) return -EINVAL; fcc = (__u8 *)&fmt->fmt.pix.pixelformat; @@ -126,8 +126,8 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video, fmt->fmt.pix.width, fmt->fmt.pix.height); /* Check if the hardware supports the requested format. */ - for (i = 0; i < video->streaming->nformats; ++i) { - format = &video->streaming->format[i]; + for (i = 0; i < stream->nformats; ++i) { + format = &stream->format[i]; if (format->fcc == fmt->fmt.pix.pixelformat) break; } @@ -191,12 +191,13 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video, * developers test their webcams with the Linux driver as well as with * the Windows driver). */ - if (video->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) + if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) probe->dwMaxVideoFrameSize = - video->streaming->ctrl.dwMaxVideoFrameSize; + stream->ctrl.dwMaxVideoFrameSize; /* Probe the device. */ - if ((ret = uvc_probe_video(video, probe)) < 0) + ret = uvc_probe_video(stream, probe); + if (ret < 0) goto done; fmt->fmt.pix.width = frame->wWidth; @@ -216,13 +217,13 @@ done: return ret; } -static int uvc_v4l2_get_format(struct uvc_video_device *video, +static int uvc_v4l2_get_format(struct uvc_streaming *stream, struct v4l2_format *fmt) { - struct uvc_format *format = video->streaming->cur_format; - struct uvc_frame *frame = video->streaming->cur_frame; + struct uvc_format *format = stream->cur_format; + struct uvc_frame *frame = stream->cur_frame; - if (fmt->type != video->streaming->type) + if (fmt->type != stream->type) return -EINVAL; if (format == NULL || frame == NULL) @@ -233,14 +234,14 @@ static int uvc_v4l2_get_format(struct uvc_video_device *video, fmt->fmt.pix.height = frame->wHeight; fmt->fmt.pix.field = V4L2_FIELD_NONE; fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8; - fmt->fmt.pix.sizeimage = video->streaming->ctrl.dwMaxVideoFrameSize; + fmt->fmt.pix.sizeimage = stream->ctrl.dwMaxVideoFrameSize; fmt->fmt.pix.colorspace = format->colorspace; fmt->fmt.pix.priv = 0; return 0; } -static int uvc_v4l2_set_format(struct uvc_video_device *video, +static int uvc_v4l2_set_format(struct uvc_streaming *stream, struct v4l2_format *fmt) { struct uvc_streaming_control probe; @@ -248,39 +249,39 @@ static int uvc_v4l2_set_format(struct uvc_video_device *video, struct uvc_frame *frame; int ret; - if (fmt->type != video->streaming->type) + if (fmt->type != stream->type) return -EINVAL; - if (uvc_queue_allocated(&video->queue)) + if (uvc_queue_allocated(&stream->queue)) return -EBUSY; - ret = uvc_v4l2_try_format(video, fmt, &probe, &format, &frame); + ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame); if (ret < 0) return ret; - memcpy(&video->streaming->ctrl, &probe, sizeof probe); - video->streaming->cur_format = format; - video->streaming->cur_frame = frame; + memcpy(&stream->ctrl, &probe, sizeof probe); + stream->cur_format = format; + stream->cur_frame = frame; return 0; } -static int uvc_v4l2_get_streamparm(struct uvc_video_device *video, +static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, struct v4l2_streamparm *parm) { uint32_t numerator, denominator; - if (parm->type != video->streaming->type) + if (parm->type != stream->type) return -EINVAL; - numerator = video->streaming->ctrl.dwFrameInterval; + numerator = stream->ctrl.dwFrameInterval; denominator = 10000000; uvc_simplify_fraction(&numerator, &denominator, 8, 333); memset(parm, 0, sizeof *parm); - parm->type = video->streaming->type; + parm->type = stream->type; - if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; parm->parm.capture.capturemode = 0; parm->parm.capture.timeperframe.numerator = numerator; @@ -297,19 +298,19 @@ static int uvc_v4l2_get_streamparm(struct uvc_video_device *video, return 0; } -static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, +static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, struct v4l2_streamparm *parm) { - struct uvc_frame *frame = video->streaming->cur_frame; + struct uvc_frame *frame = stream->cur_frame; struct uvc_streaming_control probe; struct v4l2_fract timeperframe; uint32_t interval; int ret; - if (parm->type != video->streaming->type) + if (parm->type != stream->type) return -EINVAL; - if (uvc_queue_streaming(&video->queue)) + if (uvc_queue_streaming(&stream->queue)) return -EBUSY; if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -317,7 +318,7 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, else timeperframe = parm->parm.output.timeperframe; - memcpy(&probe, &video->streaming->ctrl, sizeof probe); + memcpy(&probe, &stream->ctrl, sizeof probe); interval = uvc_fraction_to_interval(timeperframe.numerator, timeperframe.denominator); @@ -326,10 +327,11 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); /* Probe the device with the new settings. */ - if ((ret = uvc_probe_video(video, &probe)) < 0) + ret = uvc_probe_video(stream, &probe); + if (ret < 0) return ret; - memcpy(&video->streaming->ctrl, &probe, sizeof probe); + memcpy(&stream->ctrl, &probe, sizeof probe); /* Return the actual frame period. */ timeperframe.numerator = probe.dwFrameInterval; @@ -382,8 +384,8 @@ static int uvc_acquire_privileges(struct uvc_fh *handle) /* Check if the device already has a privileged handle. */ mutex_lock(&uvc_driver.open_mutex); - if (atomic_inc_return(&handle->device->active) != 1) { - atomic_dec(&handle->device->active); + if (atomic_inc_return(&handle->stream->active) != 1) { + atomic_dec(&handle->stream->active); ret = -EBUSY; goto done; } @@ -398,7 +400,7 @@ done: static void uvc_dismiss_privileges(struct uvc_fh *handle) { if (handle->state == UVC_HANDLE_ACTIVE) - atomic_dec(&handle->device->active); + atomic_dec(&handle->stream->active); handle->state = UVC_HANDLE_PASSIVE; } @@ -414,21 +416,21 @@ static int uvc_has_privileges(struct uvc_fh *handle) static int uvc_v4l2_open(struct file *file) { - struct uvc_video_device *video; + struct uvc_streaming *stream; struct uvc_fh *handle; int ret = 0; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); mutex_lock(&uvc_driver.open_mutex); - video = video_drvdata(file); + stream = video_drvdata(file); - if (video->dev->state & UVC_DEV_DISCONNECTED) { + if (stream->dev->state & UVC_DEV_DISCONNECTED) { ret = -ENODEV; goto done; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) - ret = usb_autopm_get_interface(video->dev->intf); + ret = usb_autopm_get_interface(stream->dev->intf); if (ret < 0) goto done; #endif @@ -437,28 +439,30 @@ static int uvc_v4l2_open(struct file *file) handle = kzalloc(sizeof *handle, GFP_KERNEL); if (handle == NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) - usb_autopm_put_interface(video->dev->intf); + usb_autopm_put_interface(stream->dev->intf); #endif ret = -ENOMEM; goto done; } - if (atomic_inc_return(&video->dev->users) == 1) { - if ((ret = uvc_status_start(video->dev)) < 0) { + if (atomic_inc_return(&stream->dev->users) == 1) { + ret = uvc_status_start(stream->dev); + if (ret < 0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) - usb_autopm_put_interface(video->dev->intf); + usb_autopm_put_interface(stream->dev->intf); #endif - atomic_dec(&video->dev->users); + atomic_dec(&stream->dev->users); kfree(handle); goto done; } } - handle->device = video; + handle->video = &stream->dev->video; + handle->stream = stream; handle->state = UVC_HANDLE_PASSIVE; file->private_data = handle; - kref_get(&video->dev->kref); + kref_get(&stream->dev->kref); done: mutex_unlock(&uvc_driver.open_mutex); @@ -467,20 +471,20 @@ done: static int uvc_v4l2_release(struct file *file) { - struct uvc_video_device *video = video_drvdata(file); struct uvc_fh *handle = (struct uvc_fh *)file->private_data; + struct uvc_streaming *stream = handle->stream; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); /* Only free resources if this is a privileged handle. */ if (uvc_has_privileges(handle)) { - uvc_video_enable(video, 0); + uvc_video_enable(stream, 0); - mutex_lock(&video->queue.mutex); - if (uvc_free_buffers(&video->queue) < 0) + mutex_lock(&stream->queue.mutex); + if (uvc_free_buffers(&stream->queue) < 0) uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to " "free buffers.\n"); - mutex_unlock(&video->queue.mutex); + mutex_unlock(&stream->queue.mutex); } /* Release the file handle. */ @@ -488,21 +492,22 @@ static int uvc_v4l2_release(struct file *file) kfree(handle); file->private_data = NULL; - if (atomic_dec_return(&video->dev->users) == 0) - uvc_status_stop(video->dev); + if (atomic_dec_return(&stream->dev->users) == 0) + uvc_status_stop(stream->dev); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) - usb_autopm_put_interface(video->dev->intf); + usb_autopm_put_interface(stream->dev->intf); #endif - kref_put(&video->dev->kref, uvc_delete); + kref_put(&stream->dev->kref, uvc_delete); return 0; } static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); - struct uvc_video_device *video = video_get_drvdata(vdev); struct uvc_fh *handle = (struct uvc_fh *)file->private_data; + struct uvc_video_device *video = handle->video; + struct uvc_streaming *stream = handle->stream; long ret = 0; switch (cmd) { @@ -514,10 +519,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(cap, 0, sizeof *cap); strlcpy(cap->driver, "uvcvideo", sizeof cap->driver); strlcpy(cap->card, vdev->name, sizeof cap->card); - usb_make_path(video->dev->udev, + usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->version = DRIVER_VERSION_NUMBER; - if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; else @@ -711,15 +716,15 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) enum v4l2_buf_type type = fmt->type; __u32 index = fmt->index; - if (fmt->type != video->streaming->type || - fmt->index >= video->streaming->nformats) + if (fmt->type != stream->type || + fmt->index >= stream->nformats) return -EINVAL; memset(fmt, 0, sizeof(*fmt)); fmt->index = index; fmt->type = type; - format = &video->streaming->format[fmt->index]; + format = &stream->format[fmt->index]; fmt->flags = 0; if (format->flags & UVC_FMT_FLAG_COMPRESSED) fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; @@ -737,17 +742,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - return uvc_v4l2_try_format(video, arg, &probe, NULL, NULL); + return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL); } case VIDIOC_S_FMT: if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - return uvc_v4l2_set_format(video, arg); + return uvc_v4l2_set_format(stream, arg); case VIDIOC_G_FMT: - return uvc_v4l2_get_format(video, arg); + return uvc_v4l2_get_format(stream, arg); /* Frame size enumeration */ case VIDIOC_ENUM_FRAMESIZES: @@ -758,10 +763,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) int i; /* Look for the given pixel format */ - for (i = 0; i < video->streaming->nformats; i++) { - if (video->streaming->format[i].fcc == + for (i = 0; i < stream->nformats; i++) { + if (stream->format[i].fcc == fsize->pixel_format) { - format = &video->streaming->format[i]; + format = &stream->format[i]; break; } } @@ -787,10 +792,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) int i; /* Look for the given pixel format and frame size */ - for (i = 0; i < video->streaming->nformats; i++) { - if (video->streaming->format[i].fcc == + for (i = 0; i < stream->nformats; i++) { + if (stream->format[i].fcc == fival->pixel_format) { - format = &video->streaming->format[i]; + format = &stream->format[i]; break; } } @@ -840,21 +845,21 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* Get & Set streaming parameters */ case VIDIOC_G_PARM: - return uvc_v4l2_get_streamparm(video, arg); + return uvc_v4l2_get_streamparm(stream, arg); case VIDIOC_S_PARM: if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - return uvc_v4l2_set_streamparm(video, arg); + return uvc_v4l2_set_streamparm(stream, arg); /* Cropping and scaling */ case VIDIOC_CROPCAP: { struct v4l2_cropcap *ccap = arg; - struct uvc_frame *frame = video->streaming->cur_frame; + struct uvc_frame *frame = stream->cur_frame; - if (ccap->type != video->streaming->type) + if (ccap->type != stream->type) return -EINVAL; ccap->bounds.left = 0; @@ -878,16 +883,16 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct v4l2_requestbuffers *rb = arg; unsigned int bufsize = - video->streaming->ctrl.dwMaxVideoFrameSize; + stream->ctrl.dwMaxVideoFrameSize; - if (rb->type != video->streaming->type || + if (rb->type != stream->type || rb->memory != V4L2_MEMORY_MMAP) return -EINVAL; if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - ret = uvc_alloc_buffers(&video->queue, rb->count, bufsize); + ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize); if (ret < 0) return ret; @@ -900,39 +905,40 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct v4l2_buffer *buf = arg; - if (buf->type != video->streaming->type) + if (buf->type != stream->type) return -EINVAL; if (!uvc_has_privileges(handle)) return -EBUSY; - return uvc_query_buffer(&video->queue, buf); + return uvc_query_buffer(&stream->queue, buf); } case VIDIOC_QBUF: if (!uvc_has_privileges(handle)) return -EBUSY; - return uvc_queue_buffer(&video->queue, arg); + return uvc_queue_buffer(&stream->queue, arg); case VIDIOC_DQBUF: if (!uvc_has_privileges(handle)) return -EBUSY; - return uvc_dequeue_buffer(&video->queue, arg, + return uvc_dequeue_buffer(&stream->queue, arg, file->f_flags & O_NONBLOCK); case VIDIOC_STREAMON: { int *type = arg; - if (*type != video->streaming->type) + if (*type != stream->type) return -EINVAL; if (!uvc_has_privileges(handle)) return -EBUSY; - if ((ret = uvc_video_enable(video, 1)) < 0) + ret = uvc_video_enable(stream, 1); + if (ret < 0) return ret; break; } @@ -941,13 +947,13 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { int *type = arg; - if (*type != video->streaming->type) + if (*type != stream->type) return -EINVAL; if (!uvc_has_privileges(handle)) return -EBUSY; - return uvc_video_enable(video, 0); + return uvc_video_enable(stream, 0); } /* Analog video standards make no sense for digital cameras. */ @@ -1078,7 +1084,9 @@ static struct vm_operations_struct uvc_vm_ops = { static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) { - struct uvc_video_device *video = video_drvdata(file); + struct uvc_fh *handle = (struct uvc_fh *)file->private_data; + struct uvc_streaming *stream = handle->stream; + struct uvc_video_queue *queue = &stream->queue; struct uvc_buffer *uninitialized_var(buffer); struct page *page; unsigned long addr, start, size; @@ -1090,15 +1098,15 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) start = vma->vm_start; size = vma->vm_end - vma->vm_start; - mutex_lock(&video->queue.mutex); + mutex_lock(&queue->mutex); - for (i = 0; i < video->queue.count; ++i) { - buffer = &video->queue.buffer[i]; + for (i = 0; i < queue->count; ++i) { + buffer = &queue->buffer[i]; if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) break; } - if (i == video->queue.count || size != video->queue.buf_size) { + if (i == queue->count || size != queue->buf_size) { ret = -EINVAL; goto done; } @@ -1109,7 +1117,7 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) */ vma->vm_flags |= VM_IO; - addr = (unsigned long)video->queue.mem + buffer->buf.m.offset; + addr = (unsigned long)queue->mem + buffer->buf.m.offset; while (size > 0) { page = vmalloc_to_page((void *)addr); if ((ret = vm_insert_page(vma, start, page)) < 0) @@ -1125,17 +1133,18 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) uvc_vm_open(vma); done: - mutex_unlock(&video->queue.mutex); + mutex_unlock(&queue->mutex); return ret; } static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) { - struct uvc_video_device *video = video_drvdata(file); + struct uvc_fh *handle = (struct uvc_fh *)file->private_data; + struct uvc_streaming *stream = handle->stream; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); - return uvc_queue_poll(&video->queue, file, wait); + return uvc_queue_poll(&stream->queue, file, wait); } const struct v4l2_file_operations uvc_fops = { diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index f4f4e1bb3..38cb7a367 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -61,7 +61,7 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, return 0; } -static void uvc_fixup_video_ctrl(struct uvc_video_device *video, +static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl) { struct uvc_format *format; @@ -69,10 +69,10 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, unsigned int i; if (ctrl->bFormatIndex <= 0 || - ctrl->bFormatIndex > video->streaming->nformats) + ctrl->bFormatIndex > stream->nformats) return; - format = &video->streaming->format[ctrl->bFormatIndex - 1]; + format = &stream->format[ctrl->bFormatIndex - 1]; for (i = 0; i < format->nframes; ++i) { if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) { @@ -86,12 +86,12 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) || (ctrl->dwMaxVideoFrameSize == 0 && - video->dev->uvc_version < 0x0110)) + stream->dev->uvc_version < 0x0110)) ctrl->dwMaxVideoFrameSize = frame->dwMaxVideoFrameBufferSize; - if (video->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && - video->streaming->intf->num_altsetting > 1) { + if (stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && + stream->intf->num_altsetting > 1) { u32 interval; u32 bandwidth; @@ -108,7 +108,7 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp; bandwidth *= 10000000 / interval + 1; bandwidth /= 1000; - if (video->dev->udev->speed == USB_SPEED_HIGH) + if (stream->dev->udev->speed == USB_SPEED_HIGH) bandwidth /= 8; bandwidth += 12; @@ -116,14 +116,14 @@ static void uvc_fixup_video_ctrl(struct uvc_video_device *video, } } -static int uvc_get_video_ctrl(struct uvc_video_device *video, +static int uvc_get_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl, int probe, __u8 query) { __u8 *data; __u16 size; int ret; - size = video->dev->uvc_version >= 0x0110 ? 34 : 26; + size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; data = kmalloc(size, GFP_KERNEL); if (data == NULL) return -ENOMEM; @@ -131,7 +131,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, if ((video->dev->quirks & UVC_QUIRK_PROBE_DEF) && query == UVC_GET_DEF) return -EIO; - ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, + ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum, probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, size, UVC_CTRL_STREAMING_TIMEOUT); @@ -140,7 +140,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, * answer a GET_MIN or GET_MAX request with the wCompQuality * field only. */ - uvc_warn_once(video->dev, UVC_WARN_MINMAX, "UVC non " + uvc_warn_once(stream->dev, UVC_WARN_MINMAX, "UVC non " "compliance - GET_MIN/MAX(PROBE) incorrectly " "supported. Enabling workaround.\n"); memset(ctrl, 0, sizeof ctrl); @@ -152,7 +152,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, * video probe control. Warn once and return, the caller will * fall back to GET_CUR. */ - uvc_warn_once(video->dev, UVC_WARN_PROBE_DEF, "UVC non " + uvc_warn_once(stream->dev, UVC_WARN_PROBE_DEF, "UVC non " "compliance - GET_DEF(PROBE) not supported. " "Enabling workaround.\n"); ret = -EIO; @@ -184,7 +184,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, ctrl->bMinVersion = data[32]; ctrl->bMaxVersion = data[33]; } else { - ctrl->dwClockFrequency = video->dev->clock_frequency; + ctrl->dwClockFrequency = stream->dev->clock_frequency; ctrl->bmFramingInfo = 0; ctrl->bPreferedVersion = 0; ctrl->bMinVersion = 0; @@ -195,7 +195,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, * dwMaxPayloadTransferSize fields. Try to get the value from the * format and frame descriptors. */ - uvc_fixup_video_ctrl(video, ctrl); + uvc_fixup_video_ctrl(stream, ctrl); ret = 0; out: @@ -203,14 +203,14 @@ out: return ret; } -static int uvc_set_video_ctrl(struct uvc_video_device *video, +static int uvc_set_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl, int probe) { __u8 *data; __u16 size; int ret; - size = video->dev->uvc_version >= 0x0110 ? 34 : 26; + size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; data = kzalloc(size, GFP_KERNEL); if (data == NULL) return -ENOMEM; @@ -235,8 +235,7 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video, data[33] = ctrl->bMaxVersion; } - ret = __uvc_query_ctrl(video->dev, UVC_SET_CUR, 0, - video->streaming->intfnum, + ret = __uvc_query_ctrl(stream->dev, UVC_SET_CUR, 0, stream->intfnum, probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data, size, UVC_CTRL_STREAMING_TIMEOUT); if (ret != size) { @@ -250,7 +249,7 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video, return ret; } -int uvc_probe_video(struct uvc_video_device *video, +int uvc_probe_video(struct uvc_streaming *stream, struct uvc_streaming_control *probe) { struct uvc_streaming_control probe_min, probe_max; @@ -258,7 +257,7 @@ int uvc_probe_video(struct uvc_video_device *video, unsigned int i; int ret; - mutex_lock(&video->streaming->mutex); + mutex_lock(&stream->mutex); /* Perform probing. The device should adjust the requested values * according to its capabilities. However, some devices, namely the @@ -267,15 +266,16 @@ int uvc_probe_video(struct uvc_video_device *video, * that reason, if the needed bandwidth exceeds the maximum available * bandwidth, try to lower the quality. */ - if ((ret = uvc_set_video_ctrl(video, probe, 1)) < 0) + ret = uvc_set_video_ctrl(stream, probe, 1); + if (ret < 0) goto done; /* Get the minimum and maximum values for compression settings. */ - if (!(video->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) { - ret = uvc_get_video_ctrl(video, &probe_min, 1, UVC_GET_MIN); + if (!(stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) { + ret = uvc_get_video_ctrl(stream, &probe_min, 1, UVC_GET_MIN); if (ret < 0) goto done; - ret = uvc_get_video_ctrl(video, &probe_max, 1, UVC_GET_MAX); + ret = uvc_get_video_ctrl(stream, &probe_max, 1, UVC_GET_MAX); if (ret < 0) goto done; @@ -283,21 +283,21 @@ int uvc_probe_video(struct uvc_video_device *video, } for (i = 0; i < 2; ++i) { - ret = uvc_set_video_ctrl(video, probe, 1); + ret = uvc_set_video_ctrl(stream, probe, 1); if (ret < 0) goto done; - ret = uvc_get_video_ctrl(video, probe, 1, UVC_GET_CUR); + ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR); if (ret < 0) goto done; - if (video->streaming->intf->num_altsetting == 1) + if (stream->intf->num_altsetting == 1) break; bandwidth = probe->dwMaxPayloadTransferSize; - if (bandwidth <= video->streaming->maxpsize) + if (bandwidth <= stream->maxpsize) break; - if (video->dev->quirks & UVC_QUIRK_PROBE_MINMAX) { + if (stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX) { ret = -ENOSPC; goto done; } @@ -310,14 +310,14 @@ int uvc_probe_video(struct uvc_video_device *video, } done: - mutex_unlock(&video->streaming->mutex); + mutex_unlock(&stream->mutex); return ret; } -int uvc_commit_video(struct uvc_video_device *video, +int uvc_commit_video(struct uvc_streaming *stream, struct uvc_streaming_control *probe) { - return uvc_set_video_ctrl(video, probe, 0); + return uvc_set_video_ctrl(stream, probe, 0); } /* ------------------------------------------------------------------------ @@ -369,7 +369,7 @@ int uvc_commit_video(struct uvc_video_device *video, * to be called with a NULL buf parameter. uvc_video_decode_data and * uvc_video_decode_end will never be called with a NULL buffer. */ -static int uvc_video_decode_start(struct uvc_video_device *video, +static int uvc_video_decode_start(struct uvc_streaming *stream, struct uvc_buffer *buf, const __u8 *data, int len) { __u8 fid; @@ -395,25 +395,25 @@ static int uvc_video_decode_start(struct uvc_video_device *video, * NULL. */ if (buf == NULL) { - video->last_fid = fid; + stream->last_fid = fid; return -ENODATA; } /* Synchronize to the input stream by waiting for the FID bit to be * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE. - * video->last_fid is initialized to -1, so the first isochronous + * stream->last_fid is initialized to -1, so the first isochronous * frame will always be in sync. * - * If the device doesn't toggle the FID bit, invert video->last_fid + * If the device doesn't toggle the FID bit, invert stream->last_fid * when the EOF bit is set to force synchronisation on the next packet. */ if (buf->state != UVC_BUF_STATE_ACTIVE) { - if (fid == video->last_fid) { + if (fid == stream->last_fid) { uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of " "sync).\n"); - if ((video->dev->quirks & UVC_QUIRK_STREAM_NO_FID) && + if ((stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) && (data[1] & UVC_STREAM_EOF)) - video->last_fid ^= UVC_STREAM_FID; + stream->last_fid ^= UVC_STREAM_FID; return -ENODATA; } @@ -428,7 +428,7 @@ static int uvc_video_decode_start(struct uvc_video_device *video, * last payload can be lost anyway). We thus must check if the FID has * been toggled. * - * video->last_fid is initialized to -1, so the first isochronous + * stream->last_fid is initialized to -1, so the first isochronous * frame will never trigger an end of frame detection. * * Empty buffers (bytesused == 0) don't trigger end of frame detection @@ -436,22 +436,22 @@ static int uvc_video_decode_start(struct uvc_video_device *video, * avoids detecting end of frame conditions at FID toggling if the * previous payload had the EOF bit set. */ - if (fid != video->last_fid && buf->buf.bytesused != 0) { + if (fid != stream->last_fid && buf->buf.bytesused != 0) { uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " "toggled).\n"); buf->state = UVC_BUF_STATE_DONE; return -EAGAIN; } - video->last_fid = fid; + stream->last_fid = fid; return data[0]; } -static void uvc_video_decode_data(struct uvc_video_device *video, +static void uvc_video_decode_data(struct uvc_streaming *stream, struct uvc_buffer *buf, const __u8 *data, int len) { - struct uvc_video_queue *queue = &video->queue; + struct uvc_video_queue *queue = &stream->queue; unsigned int maxlen, nbytes; void *mem; @@ -472,7 +472,7 @@ static void uvc_video_decode_data(struct uvc_video_device *video, } } -static void uvc_video_decode_end(struct uvc_video_device *video, +static void uvc_video_decode_end(struct uvc_streaming *stream, struct uvc_buffer *buf, const __u8 *data, int len) { /* Mark the buffer as done if the EOF marker is set. */ @@ -481,8 +481,8 @@ static void uvc_video_decode_end(struct uvc_video_device *video, if (data[0] == len) uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); buf->state = UVC_BUF_STATE_DONE; - if (video->dev->quirks & UVC_QUIRK_STREAM_NO_FID) - video->last_fid ^= UVC_STREAM_FID; + if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) + stream->last_fid ^= UVC_STREAM_FID; } } @@ -497,26 +497,26 @@ static void uvc_video_decode_end(struct uvc_video_device *video, * uvc_video_encode_data is called for every URB and copies the data from the * video buffer to the transfer buffer. */ -static int uvc_video_encode_header(struct uvc_video_device *video, +static int uvc_video_encode_header(struct uvc_streaming *stream, struct uvc_buffer *buf, __u8 *data, int len) { data[0] = 2; /* Header length */ data[1] = UVC_STREAM_EOH | UVC_STREAM_EOF - | (video->last_fid & UVC_STREAM_FID); + | (stream->last_fid & UVC_STREAM_FID); return 2; } -static int uvc_video_encode_data(struct uvc_video_device *video, +static int uvc_video_encode_data(struct uvc_streaming *stream, struct uvc_buffer *buf, __u8 *data, int len) { - struct uvc_video_queue *queue = &video->queue; + struct uvc_video_queue *queue = &stream->queue; unsigned int nbytes; void *mem; /* Copy video data to the URB buffer. */ mem = queue->mem + buf->buf.m.offset + queue->buf_used; nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used); - nbytes = min(video->bulk.max_payload_size - video->bulk.payload_size, + nbytes = min(stream->bulk.max_payload_size - stream->bulk.payload_size, nbytes); memcpy(data, mem, nbytes); @@ -532,8 +532,8 @@ static int uvc_video_encode_data(struct uvc_video_device *video, /* * Completion handler for video URBs. */ -static void uvc_video_decode_isoc(struct urb *urb, - struct uvc_video_device *video, struct uvc_buffer *buf) +static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream, + struct uvc_buffer *buf) { u8 *mem; int ret, i; @@ -548,31 +548,32 @@ static void uvc_video_decode_isoc(struct urb *urb, /* Decode the payload header. */ mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset; do { - ret = uvc_video_decode_start(video, buf, mem, + ret = uvc_video_decode_start(stream, buf, mem, urb->iso_frame_desc[i].actual_length); if (ret == -EAGAIN) - buf = uvc_queue_next_buffer(&video->queue, buf); + buf = uvc_queue_next_buffer(&stream->queue, + buf); } while (ret == -EAGAIN); if (ret < 0) continue; /* Decode the payload data. */ - uvc_video_decode_data(video, buf, mem + ret, + uvc_video_decode_data(stream, buf, mem + ret, urb->iso_frame_desc[i].actual_length - ret); /* Process the header again. */ - uvc_video_decode_end(video, buf, mem, + uvc_video_decode_end(stream, buf, mem, urb->iso_frame_desc[i].actual_length); if (buf->state == UVC_BUF_STATE_DONE || buf->state == UVC_BUF_STATE_ERROR) - buf = uvc_queue_next_buffer(&video->queue, buf); + buf = uvc_queue_next_buffer(&stream->queue, buf); } } -static void uvc_video_decode_bulk(struct urb *urb, - struct uvc_video_device *video, struct uvc_buffer *buf) +static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream, + struct uvc_buffer *buf) { u8 *mem; int len, ret; @@ -582,24 +583,25 @@ static void uvc_video_decode_bulk(struct urb *urb, mem = urb->transfer_buffer; len = urb->actual_length; - video->bulk.payload_size += len; + stream->bulk.payload_size += len; /* If the URB is the first of its payload, decode and save the * header. */ - if (video->bulk.header_size == 0 && !video->bulk.skip_payload) { + if (stream->bulk.header_size == 0 && !stream->bulk.skip_payload) { do { - ret = uvc_video_decode_start(video, buf, mem, len); + ret = uvc_video_decode_start(stream, buf, mem, len); if (ret == -EAGAIN) - buf = uvc_queue_next_buffer(&video->queue, buf); + buf = uvc_queue_next_buffer(&stream->queue, + buf); } while (ret == -EAGAIN); /* If an error occured skip the rest of the payload. */ if (ret < 0 || buf == NULL) { - video->bulk.skip_payload = 1; + stream->bulk.skip_payload = 1; } else { - memcpy(video->bulk.header, mem, ret); - video->bulk.header_size = ret; + memcpy(stream->bulk.header, mem, ret); + stream->bulk.header_size = ret; mem += ret; len -= ret; @@ -612,33 +614,34 @@ static void uvc_video_decode_bulk(struct urb *urb, */ /* Process video data. */ - if (!video->bulk.skip_payload && buf != NULL) - uvc_video_decode_data(video, buf, mem, len); + if (!stream->bulk.skip_payload && buf != NULL) + uvc_video_decode_data(stream, buf, mem, len); /* Detect the payload end by a URB smaller than the maximum size (or * a payload size equal to the maximum) and process the header again. */ if (urb->actual_length < urb->transfer_buffer_length || - video->bulk.payload_size >= video->bulk.max_payload_size) { - if (!video->bulk.skip_payload && buf != NULL) { - uvc_video_decode_end(video, buf, video->bulk.header, - video->bulk.payload_size); + stream->bulk.payload_size >= stream->bulk.max_payload_size) { + if (!stream->bulk.skip_payload && buf != NULL) { + uvc_video_decode_end(stream, buf, stream->bulk.header, + stream->bulk.payload_size); if (buf->state == UVC_BUF_STATE_DONE || buf->state == UVC_BUF_STATE_ERROR) - buf = uvc_queue_next_buffer(&video->queue, buf); + buf = uvc_queue_next_buffer(&stream->queue, + buf); } - video->bulk.header_size = 0; - video->bulk.skip_payload = 0; - video->bulk.payload_size = 0; + stream->bulk.header_size = 0; + stream->bulk.skip_payload = 0; + stream->bulk.payload_size = 0; } } -static void uvc_video_encode_bulk(struct urb *urb, - struct uvc_video_device *video, struct uvc_buffer *buf) +static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream, + struct uvc_buffer *buf) { u8 *mem = urb->transfer_buffer; - int len = video->urb_size, ret; + int len = stream->urb_size, ret; if (buf == NULL) { urb->transfer_buffer_length = 0; @@ -646,34 +649,34 @@ static void uvc_video_encode_bulk(struct urb *urb, } /* If the URB is the first of its payload, add the header. */ - if (video->bulk.header_size == 0) { - ret = uvc_video_encode_header(video, buf, mem, len); - video->bulk.header_size = ret; - video->bulk.payload_size += ret; + if (stream->bulk.header_size == 0) { + ret = uvc_video_encode_header(stream, buf, mem, len); + stream->bulk.header_size = ret; + stream->bulk.payload_size += ret; mem += ret; len -= ret; } /* Process video data. */ - ret = uvc_video_encode_data(video, buf, mem, len); + ret = uvc_video_encode_data(stream, buf, mem, len); - video->bulk.payload_size += ret; + stream->bulk.payload_size += ret; len -= ret; - if (buf->buf.bytesused == video->queue.buf_used || - video->bulk.payload_size == video->bulk.max_payload_size) { - if (buf->buf.bytesused == video->queue.buf_used) { - video->queue.buf_used = 0; + if (buf->buf.bytesused == stream->queue.buf_used || + stream->bulk.payload_size == stream->bulk.max_payload_size) { + if (buf->buf.bytesused == stream->queue.buf_used) { + stream->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; - uvc_queue_next_buffer(&video->queue, buf); - video->last_fid ^= UVC_STREAM_FID; + uvc_queue_next_buffer(&stream->queue, buf); + stream->last_fid ^= UVC_STREAM_FID; } - video->bulk.header_size = 0; - video->bulk.payload_size = 0; + stream->bulk.header_size = 0; + stream->bulk.payload_size = 0; } - urb->transfer_buffer_length = video->urb_size - len; + urb->transfer_buffer_length = stream->urb_size - len; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) @@ -682,8 +685,8 @@ static void uvc_video_complete(struct urb *urb, struct pt_regs *regs) static void uvc_video_complete(struct urb *urb) #endif { - struct uvc_video_device *video = urb->context; - struct uvc_video_queue *queue = &video->queue; + struct uvc_streaming *stream = urb->context; + struct uvc_video_queue *queue = &stream->queue; struct uvc_buffer *buf = NULL; unsigned long flags; int ret; @@ -697,7 +700,7 @@ static void uvc_video_complete(struct urb *urb) "completion handler.\n", urb->status); case -ENOENT: /* usb_kill_urb() called. */ - if (video->frozen) + if (stream->frozen) return; case -ECONNRESET: /* usb_unlink_urb() called. */ @@ -712,7 +715,7 @@ static void uvc_video_complete(struct urb *urb) queue); spin_unlock_irqrestore(&queue->irqlock, flags); - video->decode(urb, video, buf); + stream->decode(urb, stream, buf); if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n", @@ -723,19 +726,19 @@ static void uvc_video_complete(struct urb *urb) /* * Free transfer buffers. */ -static void uvc_free_urb_buffers(struct uvc_video_device *video) +static void uvc_free_urb_buffers(struct uvc_streaming *stream) { unsigned int i; for (i = 0; i < UVC_URBS; ++i) { - if (video->urb_buffer[i]) { - usb_buffer_free(video->dev->udev, video->urb_size, - video->urb_buffer[i], video->urb_dma[i]); - video->urb_buffer[i] = NULL; + if (stream->urb_buffer[i]) { + usb_buffer_free(stream->dev->udev, stream->urb_size, + stream->urb_buffer[i], stream->urb_dma[i]); + stream->urb_buffer[i] = NULL; } } - video->urb_size = 0; + stream->urb_size = 0; } /* @@ -749,15 +752,15 @@ static void uvc_free_urb_buffers(struct uvc_video_device *video) * * Return the number of allocated packets on success or 0 when out of memory. */ -static int uvc_alloc_urb_buffers(struct uvc_video_device *video, +static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, unsigned int size, unsigned int psize, gfp_t gfp_flags) { unsigned int npackets; unsigned int i; /* Buffers are already allocated, bail out. */ - if (video->urb_size) - return video->urb_size / psize; + if (stream->urb_size) + return stream->urb_size / psize; /* Compute the number of packets. Bulk endpoints might transfer UVC * payloads accross multiple URBs. @@ -769,17 +772,17 @@ static int uvc_alloc_urb_buffers(struct uvc_video_device *video, /* Retry allocations until one succeed. */ for (; npackets > 1; npackets /= 2) { for (i = 0; i < UVC_URBS; ++i) { - video->urb_buffer[i] = usb_buffer_alloc( - video->dev->udev, psize * npackets, - gfp_flags | __GFP_NOWARN, &video->urb_dma[i]); - if (!video->urb_buffer[i]) { - uvc_free_urb_buffers(video); + stream->urb_buffer[i] = usb_buffer_alloc( + stream->dev->udev, psize * npackets, + gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]); + if (!stream->urb_buffer[i]) { + uvc_free_urb_buffers(stream); break; } } if (i == UVC_URBS) { - video->urb_size = psize * npackets; + stream->urb_size = psize * npackets; return npackets; } } @@ -790,29 +793,30 @@ static int uvc_alloc_urb_buffers(struct uvc_video_device *video, /* * Uninitialize isochronous/bulk URBs and free transfer buffers. */ -static void uvc_uninit_video(struct uvc_video_device *video, int free_buffers) +static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) { struct urb *urb; unsigned int i; for (i = 0; i < UVC_URBS; ++i) { - if ((urb = video->urb[i]) == NULL) + urb = stream->urb[i]; + if (urb == NULL) continue; usb_kill_urb(urb); usb_free_urb(urb); - video->urb[i] = NULL; + stream->urb[i] = NULL; } if (free_buffers) - uvc_free_urb_buffers(video); + uvc_free_urb_buffers(stream); } /* * Initialize isochronous URBs and allocate transfer buffers. The packet size * is given by the endpoint. */ -static int uvc_init_video_isoc(struct uvc_video_device *video, +static int uvc_init_video_isoc(struct uvc_streaming *stream, struct usb_host_endpoint *ep, gfp_t gfp_flags) { struct urb *urb; @@ -822,9 +826,9 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, psize = le16_to_cpu(ep->desc.wMaxPacketSize); psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - size = video->streaming->ctrl.dwMaxVideoFrameSize; + size = stream->ctrl.dwMaxVideoFrameSize; - npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags); + npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags); if (npackets == 0) return -ENOMEM; @@ -833,18 +837,18 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, for (i = 0; i < UVC_URBS; ++i) { urb = usb_alloc_urb(npackets, gfp_flags); if (urb == NULL) { - uvc_uninit_video(video, 1); + uvc_uninit_video(stream, 1); return -ENOMEM; } - urb->dev = video->dev->udev; - urb->context = video; - urb->pipe = usb_rcvisocpipe(video->dev->udev, + urb->dev = stream->dev->udev; + urb->context = stream; + urb->pipe = usb_rcvisocpipe(stream->dev->udev, ep->desc.bEndpointAddress); urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->interval = ep->desc.bInterval; - urb->transfer_buffer = video->urb_buffer[i]; - urb->transfer_dma = video->urb_dma[i]; + urb->transfer_buffer = stream->urb_buffer[i]; + urb->transfer_dma = stream->urb_dma[i]; urb->complete = uvc_video_complete; urb->number_of_packets = npackets; urb->transfer_buffer_length = size; @@ -854,7 +858,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, urb->iso_frame_desc[j].length = psize; } - video->urb[i] = urb; + stream->urb[i] = urb; } return 0; @@ -864,7 +868,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, * Initialize bulk URBs and allocate transfer buffers. The packet size is * given by the endpoint. */ -static int uvc_init_video_bulk(struct uvc_video_device *video, +static int uvc_init_video_bulk(struct uvc_streaming *stream, struct usb_host_endpoint *ep, gfp_t gfp_flags) { struct urb *urb; @@ -873,39 +877,39 @@ static int uvc_init_video_bulk(struct uvc_video_device *video, u32 size; psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff; - size = video->streaming->ctrl.dwMaxPayloadTransferSize; - video->bulk.max_payload_size = size; + size = stream->ctrl.dwMaxPayloadTransferSize; + stream->bulk.max_payload_size = size; - npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags); + npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags); if (npackets == 0) return -ENOMEM; size = npackets * psize; if (usb_endpoint_dir_in(&ep->desc)) - pipe = usb_rcvbulkpipe(video->dev->udev, + pipe = usb_rcvbulkpipe(stream->dev->udev, ep->desc.bEndpointAddress); else - pipe = usb_sndbulkpipe(video->dev->udev, + pipe = usb_sndbulkpipe(stream->dev->udev, ep->desc.bEndpointAddress); - if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) size = 0; for (i = 0; i < UVC_URBS; ++i) { urb = usb_alloc_urb(0, gfp_flags); if (urb == NULL) { - uvc_uninit_video(video, 1); + uvc_uninit_video(stream, 1); return -ENOMEM; } - usb_fill_bulk_urb(urb, video->dev->udev, pipe, - video->urb_buffer[i], size, uvc_video_complete, - video); + usb_fill_bulk_urb(urb, stream->dev->udev, pipe, + stream->urb_buffer[i], size, uvc_video_complete, + stream); urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; - urb->transfer_dma = video->urb_dma[i]; + urb->transfer_dma = stream->urb_dma[i]; - video->urb[i] = urb; + stream->urb[i] = urb; } return 0; @@ -914,35 +918,35 @@ static int uvc_init_video_bulk(struct uvc_video_device *video, /* * Initialize isochronous/bulk URBs and allocate transfer buffers. */ -static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags) +static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) { - struct usb_interface *intf = video->streaming->intf; + struct usb_interface *intf = stream->intf; struct usb_host_interface *alts; struct usb_host_endpoint *ep = NULL; - int intfnum = video->streaming->intfnum; + int intfnum = stream->intfnum; unsigned int bandwidth, psize, i; int ret; - video->last_fid = -1; - video->bulk.header_size = 0; - video->bulk.skip_payload = 0; - video->bulk.payload_size = 0; + stream->last_fid = -1; + stream->bulk.header_size = 0; + stream->bulk.skip_payload = 0; + stream->bulk.payload_size = 0; if (intf->num_altsetting > 1) { /* Isochronous endpoint, select the alternate setting. */ - bandwidth = video->streaming->ctrl.dwMaxPayloadTransferSize; + bandwidth = stream->ctrl.dwMaxPayloadTransferSize; if (bandwidth == 0) { uvc_printk(KERN_WARNING, "device %s requested null " "bandwidth, defaulting to lowest.\n", - video->vdev->name); + stream->dev->name); bandwidth = 1; } for (i = 0; i < intf->num_altsetting; ++i) { alts = &intf->altsetting[i]; ep = uvc_find_endpoint(alts, - video->streaming->header.bEndpointAddress); + stream->header.bEndpointAddress); if (ep == NULL) continue; @@ -956,18 +960,19 @@ static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags) if (i >= intf->num_altsetting) return -EIO; - if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0) + ret = usb_set_interface(stream->dev->udev, intfnum, i); + if (ret < 0) return ret; - ret = uvc_init_video_isoc(video, ep, gfp_flags); + ret = uvc_init_video_isoc(stream, ep, gfp_flags); } else { /* Bulk endpoint, proceed to URB initialization. */ ep = uvc_find_endpoint(&intf->altsetting[0], - video->streaming->header.bEndpointAddress); + stream->header.bEndpointAddress); if (ep == NULL) return -EIO; - ret = uvc_init_video_bulk(video, ep, gfp_flags); + ret = uvc_init_video_bulk(stream, ep, gfp_flags); } if (ret < 0) @@ -975,10 +980,11 @@ static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags) /* Submit the URBs. */ for (i = 0; i < UVC_URBS; ++i) { - if ((ret = usb_submit_urb(video->urb[i], gfp_flags)) < 0) { + ret = usb_submit_urb(stream->urb[i], gfp_flags); + if (ret < 0) { uvc_printk(KERN_ERR, "Failed to submit URB %u " "(%d).\n", i, ret); - uvc_uninit_video(video, 1); + uvc_uninit_video(stream, 1); return ret; } } @@ -997,14 +1003,14 @@ static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags) * video buffers in any way. We mark the device as frozen to make sure the URB * completion handler won't try to cancel the queue when we kill the URBs. */ -int uvc_video_suspend(struct uvc_video_device *video) +int uvc_video_suspend(struct uvc_streaming *stream) { - if (!uvc_queue_streaming(&video->queue)) + if (!uvc_queue_streaming(&stream->queue)) return 0; - video->frozen = 1; - uvc_uninit_video(video, 0); - usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); + stream->frozen = 1; + uvc_uninit_video(stream, 0); + usb_set_interface(stream->dev->udev, stream->intfnum, 0); return 0; } @@ -1016,22 +1022,24 @@ int uvc_video_suspend(struct uvc_video_device *video) * buffers, making sure userspace applications are notified of the problem * instead of waiting forever. */ -int uvc_video_resume(struct uvc_video_device *video) +int uvc_video_resume(struct uvc_streaming *stream) { int ret; - video->frozen = 0; + stream->frozen = 0; - if ((ret = uvc_commit_video(video, &video->streaming->ctrl)) < 0) { - uvc_queue_enable(&video->queue, 0); + ret = uvc_commit_video(stream, &stream->ctrl); + if (ret < 0) { + uvc_queue_enable(&stream->queue, 0); return ret; } - if (!uvc_queue_streaming(&video->queue)) + if (!uvc_queue_streaming(&stream->queue)) return 0; - if ((ret = uvc_init_video(video, GFP_NOIO)) < 0) - uvc_queue_enable(&video->queue, 0); + ret = uvc_init_video(stream, GFP_NOIO); + if (ret < 0) + uvc_queue_enable(&stream->queue, 0); return ret; } @@ -1050,48 +1058,53 @@ int uvc_video_resume(struct uvc_video_device *video) * * This function is called before registering the device with V4L. */ -int uvc_video_init(struct uvc_video_device *video) +int uvc_video_init(struct uvc_streaming *stream) { - struct uvc_streaming_control *probe = &video->streaming->ctrl; + struct uvc_streaming_control *probe = &stream->ctrl; struct uvc_format *format = NULL; struct uvc_frame *frame = NULL; unsigned int i; int ret; - if (video->streaming->nformats == 0) { + if (stream->nformats == 0) { uvc_printk(KERN_INFO, "No supported video formats found.\n"); return -EINVAL; } + atomic_set(&stream->active, 0); + + /* Initialize the video buffers queue. */ + uvc_queue_init(&stream->queue, stream->type); + /* Alternate setting 0 should be the default, yet the XBox Live Vision * Cam (and possibly other devices) crash or otherwise misbehave if * they don't receive a SET_INTERFACE request before any other video * control request. */ - usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); + usb_set_interface(stream->dev->udev, stream->intfnum, 0); /* Set the streaming probe control with default streaming parameters * retrieved from the device. Webcams that don't suport GET_DEF * requests on the probe control will just keep their current streaming * parameters. */ - if (uvc_get_video_ctrl(video, probe, 1, UVC_GET_DEF) == 0) - uvc_set_video_ctrl(video, probe, 1); + if (uvc_get_video_ctrl(stream, probe, 1, UVC_GET_DEF) == 0) + uvc_set_video_ctrl(stream, probe, 1); /* Initialize the streaming parameters with the probe control current * value. This makes sure SET_CUR requests on the streaming commit * control will always use values retrieved from a successful GET_CUR * request on the probe control, as required by the UVC specification. */ - ret = uvc_get_video_ctrl(video, probe, 1, UVC_GET_CUR); + ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR); if (ret < 0) return ret; /* Check if the default format descriptor exists. Use the first * available format otherwise. */ - for (i = video->streaming->nformats; i > 0; --i) { - format = &video->streaming->format[i-1]; + for (i = stream->nformats; i > 0; --i) { + format = &stream->format[i-1]; if (format->index == probe->bFormatIndex) break; } @@ -1116,21 +1129,20 @@ int uvc_video_init(struct uvc_video_device *video) probe->bFormatIndex = format->index; probe->bFrameIndex = frame->bFrameIndex; - video->streaming->cur_format = format; - video->streaming->cur_frame = frame; - atomic_set(&video->active, 0); + stream->cur_format = format; + stream->cur_frame = frame; /* Select the video decoding function */ - if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (video->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) - video->decode = uvc_video_decode_isight; - else if (video->streaming->intf->num_altsetting > 1) - video->decode = uvc_video_decode_isoc; + if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) + stream->decode = uvc_video_decode_isight; + else if (stream->intf->num_altsetting > 1) + stream->decode = uvc_video_decode_isoc; else - video->decode = uvc_video_decode_bulk; + stream->decode = uvc_video_decode_bulk; } else { - if (video->streaming->intf->num_altsetting == 1) - video->decode = uvc_video_encode_bulk; + if (stream->intf->num_altsetting == 1) + stream->decode = uvc_video_encode_bulk; else { uvc_printk(KERN_INFO, "Isochronous endpoints are not " "supported for video output devices.\n"); @@ -1144,31 +1156,32 @@ int uvc_video_init(struct uvc_video_device *video) /* * Enable or disable the video stream. */ -int uvc_video_enable(struct uvc_video_device *video, int enable) +int uvc_video_enable(struct uvc_streaming *stream, int enable) { int ret; if (!enable) { - uvc_uninit_video(video, 1); - usb_set_interface(video->dev->udev, - video->streaming->intfnum, 0); - uvc_queue_enable(&video->queue, 0); + uvc_uninit_video(stream, 1); + usb_set_interface(stream->dev->udev, stream->intfnum, 0); + uvc_queue_enable(&stream->queue, 0); return 0; } - if ((video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) || + if ((stream->cur_format->flags & UVC_FMT_FLAG_COMPRESSED) || uvc_no_drop_param) - video->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE; + stream->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE; else - video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; + stream->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; - if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) + ret = uvc_queue_enable(&stream->queue, 1); + if (ret < 0) return ret; /* Commit the streaming parameters. */ - if ((ret = uvc_commit_video(video, &video->streaming->ctrl)) < 0) + ret = uvc_commit_video(stream, &stream->ctrl); + if (ret < 0) return ret; - return uvc_init_video(video, GFP_KERNEL); + return uvc_init_video(stream, GFP_KERNEL); } diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index e700bdc20..c385b7bde 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -362,26 +362,6 @@ struct uvc_streaming_header { __u8 bTriggerUsage; }; -struct uvc_streaming { - struct list_head list; - - struct usb_interface *intf; - int intfnum; - __u16 maxpsize; - - struct uvc_streaming_header header; - enum v4l2_buf_type type; - - unsigned int nformats; - struct uvc_format *format; - - struct uvc_streaming_control ctrl; - struct uvc_format *cur_format; - struct uvc_frame *cur_frame; - - struct mutex mutex; -}; - enum uvc_buffer_state { UVC_BUF_STATE_IDLE = 0, UVC_BUF_STATE_QUEUED = 1, @@ -423,26 +403,31 @@ struct uvc_video_queue { struct list_head irqqueue; }; -struct uvc_video_device { +struct uvc_streaming { + struct list_head list; struct uvc_device *dev; struct video_device *vdev; atomic_t active; - unsigned int frozen : 1; - struct list_head iterms; /* Input terminals */ - struct uvc_entity *oterm; /* Output terminal */ - struct uvc_entity *sterm; /* USB streaming terminal */ - struct uvc_entity *processing; - struct uvc_entity *selector; - struct list_head extensions; - struct mutex ctrl_mutex; + struct usb_interface *intf; + int intfnum; + __u16 maxpsize; - struct uvc_video_queue queue; + struct uvc_streaming_header header; + enum v4l2_buf_type type; + + unsigned int nformats; + struct uvc_format *format; - /* Video streaming object, must always be non-NULL. */ - struct uvc_streaming *streaming; + struct uvc_streaming_control ctrl; + struct uvc_format *cur_format; + struct uvc_frame *cur_frame; + + struct mutex mutex; - void (*decode) (struct urb *urb, struct uvc_video_device *video, + unsigned int frozen : 1; + struct uvc_video_queue queue; + void (*decode) (struct urb *urb, struct uvc_streaming *video, struct uvc_buffer *buf); /* Context data used by the bulk completion handler. */ @@ -462,6 +447,18 @@ struct uvc_video_device { __u8 last_fid; }; +struct uvc_video_device { + struct uvc_device *dev; + + struct list_head iterms; /* Input terminals */ + struct uvc_entity *oterm; /* Output terminal */ + struct uvc_entity *sterm; /* USB streaming terminal */ + struct uvc_entity *processing; + struct uvc_entity *selector; + struct list_head extensions; + struct mutex ctrl_mutex; +}; + enum uvc_device_state { UVC_DEV_DISCONNECTED = 1, }; @@ -487,15 +484,15 @@ struct uvc_device { struct uvc_video_device video; + /* Video Streaming interfaces */ + struct list_head streams; + /* Status Interrupt Endpoint */ struct usb_host_endpoint *int_ep; struct urb *int_urb; __u8 *status; struct input_dev *input; char input_phys[64]; - - /* Video Streaming interfaces */ - struct list_head streaming; }; enum uvc_handle_state { @@ -504,7 +501,8 @@ enum uvc_handle_state { }; struct uvc_fh { - struct uvc_video_device *device; + struct uvc_video_device *video; + struct uvc_streaming *stream; enum uvc_handle_state state; }; @@ -601,13 +599,13 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue) extern const struct v4l2_file_operations uvc_fops; /* Video */ -extern int uvc_video_init(struct uvc_video_device *video); -extern int uvc_video_suspend(struct uvc_video_device *video); -extern int uvc_video_resume(struct uvc_video_device *video); -extern int uvc_video_enable(struct uvc_video_device *video, int enable); -extern int uvc_probe_video(struct uvc_video_device *video, +extern int uvc_video_init(struct uvc_streaming *stream); +extern int uvc_video_suspend(struct uvc_streaming *stream); +extern int uvc_video_resume(struct uvc_streaming *stream); +extern int uvc_video_enable(struct uvc_streaming *stream, int enable); +extern int uvc_probe_video(struct uvc_streaming *stream, struct uvc_streaming_control *probe); -extern int uvc_commit_video(struct uvc_video_device *video, +extern int uvc_commit_video(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl); extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, __u8 intfnum, __u8 cs, void *data, __u16 size); @@ -661,7 +659,7 @@ extern struct usb_host_endpoint *uvc_find_endpoint( struct usb_host_interface *alts, __u8 epaddr); /* Quirks support */ -void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, +void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream, struct uvc_buffer *buf); #endif /* __KERNEL__ */ -- cgit v1.2.3 From 6e2ae3dc6cc75b33e9950ffde1cbdbbdfd871262 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 29 Jun 2009 10:22:45 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index eb7e11a68..ccd859723 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -83,7 +83,9 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G2S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, - /* Asus notebook in disguise */ + /* These PACKARD BELL's are Asus notebook in disguise */ + { 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_BG45", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_BG46", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x5986, 0x0205, 0, "LENOVO", "Base Board Product Name", -- cgit v1.2.3 From c0be22d7a52d1be4f6948bdd43eaea9f0e284528 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 29 Jun 2009 11:29:59 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index ccd859723..e97fc3cd3 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -72,6 +72,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Ke ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Sa ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Sr ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* The G1S has been seen with 2 different board name strings */ -- cgit v1.2.3 From c5bf599bcaa4cba04f76ae9edce2d9766a9602fd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 Jul 2009 01:24:47 +0200 Subject: uvcvideo: Multiple streaming interfaces support From: Laurent Pinchart Restructure the UVC descriptors parsing code to handle multiple streaming interfaces. The driver now creates a uvc_video_chain instance for each chain detected in the UVC control interface descriptors, and tries to register one video device per streaming endpoint. Priority: normal Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_ctrl.c | 82 ++--- linux/drivers/media/video/uvc/uvc_driver.c | 466 ++++++++++++++++++----------- linux/drivers/media/video/uvc/uvc_v4l2.c | 80 ++--- linux/drivers/media/video/uvc/uvc_video.c | 2 +- linux/drivers/media/video/uvc/uvcvideo.h | 59 ++-- 5 files changed, 411 insertions(+), 278 deletions(-) diff --git a/linux/drivers/media/video/uvc/uvc_ctrl.c b/linux/drivers/media/video/uvc/uvc_ctrl.c index 81928f838..57b6fe937 100644 --- a/linux/drivers/media/video/uvc/uvc_ctrl.c +++ b/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -731,7 +731,7 @@ static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id, } } -struct uvc_control *uvc_find_control(struct uvc_video_device *video, +struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, __u32 v4l2_id, struct uvc_control_mapping **mapping) { struct uvc_control *ctrl = NULL; @@ -744,17 +744,17 @@ struct uvc_control *uvc_find_control(struct uvc_video_device *video, v4l2_id &= V4L2_CTRL_ID_MASK; /* Find the control. */ - __uvc_find_control(video->processing, v4l2_id, mapping, &ctrl, next); + __uvc_find_control(chain->processing, v4l2_id, mapping, &ctrl, next); if (ctrl && !next) return ctrl; - list_for_each_entry(entity, &video->iterms, chain) { + list_for_each_entry(entity, &chain->iterms, chain) { __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); if (ctrl && !next) return ctrl; } - list_for_each_entry(entity, &video->extensions, chain) { + list_for_each_entry(entity, &chain->extensions, chain) { __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); if (ctrl && !next) return ctrl; @@ -767,7 +767,7 @@ struct uvc_control *uvc_find_control(struct uvc_video_device *video, return ctrl; } -int uvc_query_v4l2_ctrl(struct uvc_video_device *video, +int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, struct v4l2_queryctrl *v4l2_ctrl) { struct uvc_control *ctrl; @@ -777,7 +777,7 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, __u8 *data; int ret; - ctrl = uvc_find_control(video, v4l2_ctrl->id, &mapping); + ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); if (ctrl == NULL) return -EINVAL; @@ -795,9 +795,9 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { - ret = uvc_query_ctrl(video->dev, UVC_GET_DEF, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, data, - ctrl->info->size); + ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, + chain->dev->intfnum, ctrl->info->selector, + data, ctrl->info->size); if (ret < 0) goto out; v4l2_ctrl->default_value = @@ -833,25 +833,25 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, } if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { - ret = uvc_query_ctrl(video->dev, UVC_GET_MIN, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, data, - ctrl->info->size); + ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, + chain->dev->intfnum, ctrl->info->selector, + data, ctrl->info->size); if (ret < 0) goto out; v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, data); } if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { - ret = uvc_query_ctrl(video->dev, UVC_GET_MAX, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, data, - ctrl->info->size); + ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, + chain->dev->intfnum, ctrl->info->selector, + data, ctrl->info->size); if (ret < 0) goto out; v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, data); } if (ctrl->info->flags & UVC_CONTROL_GET_RES) { - ret = uvc_query_ctrl(video->dev, UVC_GET_RES, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, data, - ctrl->info->size); + ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, + chain->dev->intfnum, ctrl->info->selector, + data, ctrl->info->size); if (ret < 0) goto out; v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, data); @@ -888,9 +888,9 @@ out: * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the * control lock. */ -int uvc_ctrl_begin(struct uvc_video_device *video) +int uvc_ctrl_begin(struct uvc_video_chain *chain) { - return mutex_lock_interruptible(&video->ctrl_mutex) ? -ERESTARTSYS : 0; + return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0; } static int uvc_ctrl_commit_entity(struct uvc_device *dev, @@ -940,34 +940,34 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev, return 0; } -int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback) +int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback) { struct uvc_entity *entity; int ret = 0; /* Find the control. */ - ret = uvc_ctrl_commit_entity(video->dev, video->processing, rollback); + ret = uvc_ctrl_commit_entity(chain->dev, chain->processing, rollback); if (ret < 0) goto done; - list_for_each_entry(entity, &video->iterms, chain) { - ret = uvc_ctrl_commit_entity(video->dev, entity, rollback); + list_for_each_entry(entity, &chain->iterms, chain) { + ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); if (ret < 0) goto done; } - list_for_each_entry(entity, &video->extensions, chain) { - ret = uvc_ctrl_commit_entity(video->dev, entity, rollback); + list_for_each_entry(entity, &chain->extensions, chain) { + ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); if (ret < 0) goto done; } done: - mutex_unlock(&video->ctrl_mutex); + mutex_unlock(&chain->ctrl_mutex); return ret; } -int uvc_ctrl_get(struct uvc_video_device *video, +int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl) { struct uvc_control *ctrl; @@ -976,13 +976,13 @@ int uvc_ctrl_get(struct uvc_video_device *video, unsigned int i; int ret; - ctrl = uvc_find_control(video, xctrl->id, &mapping); + ctrl = uvc_find_control(chain, xctrl->id, &mapping); if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) return -EINVAL; if (!ctrl->loaded) { - ret = uvc_query_ctrl(video->dev, UVC_GET_CUR, ctrl->entity->id, - video->dev->intfnum, ctrl->info->selector, + ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id, + chain->dev->intfnum, ctrl->info->selector, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), ctrl->info->size); if (ret < 0) @@ -1007,7 +1007,7 @@ int uvc_ctrl_get(struct uvc_video_device *video, return 0; } -int uvc_ctrl_set(struct uvc_video_device *video, +int uvc_ctrl_set(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl) { struct uvc_control *ctrl; @@ -1015,7 +1015,7 @@ int uvc_ctrl_set(struct uvc_video_device *video, s32 value = xctrl->value; int ret; - ctrl = uvc_find_control(video, xctrl->id, &mapping); + ctrl = uvc_find_control(chain, xctrl->id, &mapping); if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0) return -EINVAL; @@ -1030,8 +1030,8 @@ int uvc_ctrl_set(struct uvc_video_device *video, memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), 0, ctrl->info->size); } else { - ret = uvc_query_ctrl(video->dev, UVC_GET_CUR, - ctrl->entity->id, video->dev->intfnum, + ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, + ctrl->entity->id, chain->dev->intfnum, ctrl->info->selector, uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), ctrl->info->size); @@ -1060,7 +1060,7 @@ int uvc_ctrl_set(struct uvc_video_device *video, * Dynamic controls */ -int uvc_xu_ctrl_query(struct uvc_video_device *video, +int uvc_xu_ctrl_query(struct uvc_video_chain *chain, struct uvc_xu_control *xctrl, int set) { struct uvc_entity *entity; @@ -1070,7 +1070,7 @@ int uvc_xu_ctrl_query(struct uvc_video_device *video, int ret; /* Find the extension unit. */ - list_for_each_entry(entity, &video->extensions, chain) { + list_for_each_entry(entity, &chain->extensions, chain) { if (entity->id == xctrl->unit) break; } @@ -1109,7 +1109,7 @@ int uvc_xu_ctrl_query(struct uvc_video_device *video, (!set && !(ctrl->info->flags & UVC_CONTROL_GET_CUR))) return -EINVAL; - if (mutex_lock_interruptible(&video->ctrl_mutex)) + if (mutex_lock_interruptible(&chain->ctrl_mutex)) return -ERESTARTSYS; memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), @@ -1122,8 +1122,8 @@ int uvc_xu_ctrl_query(struct uvc_video_device *video, goto out; } - ret = uvc_query_ctrl(video->dev, set ? UVC_SET_CUR : UVC_GET_CUR, - xctrl->unit, video->dev->intfnum, xctrl->selector, + ret = uvc_query_ctrl(chain->dev, set ? UVC_SET_CUR : UVC_GET_CUR, + xctrl->unit, chain->dev->intfnum, xctrl->selector, data, xctrl->size); if (ret < 0) goto out; @@ -1139,7 +1139,7 @@ out: uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), xctrl->size); - mutex_unlock(&video->ctrl_mutex); + mutex_unlock(&chain->ctrl_mutex); return ret; } diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index 70d15a926..fa13b6765 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -276,8 +276,20 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev, return NULL; } +static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id) +{ + struct uvc_streaming *stream; + + list_for_each_entry(stream, &dev->streams, list) { + if (stream->header.bTerminalLink == id) + return stream; + } + + return NULL; +} + /* ------------------------------------------------------------------------ - * Descriptors handling + * Descriptors parsing */ static int uvc_parse_format(struct uvc_device *dev, @@ -1160,101 +1172,36 @@ next_descriptor: } /* ------------------------------------------------------------------------ - * USB probe and disconnect + * UVC device scan */ -/* - * Unregister the video devices. - */ -static void uvc_unregister_video(struct uvc_device *dev) -{ - struct uvc_streaming *streaming; - - list_for_each_entry(streaming, &dev->streams, list) { - if (streaming->vdev == NULL) - continue; - - if (streaming->vdev->minor == -1) - video_device_release(streaming->vdev); - else - video_unregister_device(streaming->vdev); - streaming->vdev = NULL; - } -} - -static int uvc_register_video(struct uvc_device *dev, - struct uvc_streaming *stream) -{ - struct video_device *vdev; - struct uvc_entity *term; - int ret; - - if (uvc_trace_param & UVC_TRACE_PROBE) { - uvc_printk(KERN_INFO, "Found a valid video chain ("); - list_for_each_entry(term, &dev->video.iterms, chain) { - printk("%d", term->id); - if (term->chain.next != &dev->video.iterms) - printk(","); - } - printk(" -> %d).\n", dev->video.oterm->id); - } - - /* Initialize the streaming interface with default streaming - * parameters. - */ - ret = uvc_video_init(stream); - if (ret < 0) { - uvc_printk(KERN_ERR, "Failed to initialize the device " - "(%d).\n", ret); - return ret; - } - - /* Register the device with V4L. */ - vdev = video_device_alloc(); - if (vdev == NULL) - return -1; - - /* We already hold a reference to dev->udev. The video device will be - * unregistered before the reference is released, so we don't need to - * get another one. - */ - vdev->parent = &dev->intf->dev; - vdev->minor = -1; - vdev->fops = &uvc_fops; - vdev->release = video_device_release; - strlcpy(vdev->name, dev->name, sizeof vdev->name); - - /* Set the driver data before calling video_register_device, otherwise - * uvc_v4l2_open might race us. - */ - stream->vdev = vdev; - video_set_drvdata(vdev, stream); - - if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) < 0) { - stream->vdev = NULL; - video_device_release(vdev); - return -1; - } - - return 0; -} - /* * Scan the UVC descriptors to locate a chain starting at an Output Terminal * and containing the following units: * - * - one Output Terminal (USB Streaming or Display) + * - one or more Output Terminals (USB Streaming or Display) * - zero or one Processing Unit - * - zero, one or mode single-input Selector Units + * - zero, one or more single-input Selector Units * - zero or one multiple-input Selector Units, provided all inputs are * connected to input terminals * - zero, one or mode single-input Extension Units * - one or more Input Terminals (Camera, External or USB Streaming) * - * A side forward scan is made on each detected entity to check for additional - * extension units. + * The terminal and units must match on of the following structures: + * + * ITT_*(0) -> +---------+ +---------+ +---------+ -> TT_STREAMING(0) + * ... | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} | ... + * ITT_*(n) -> +---------+ +---------+ +---------+ -> TT_STREAMING(n) + * + * +---------+ +---------+ -> OTT_*(0) + * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} | ... + * +---------+ +---------+ -> OTT_*(n) + * + * The Processing Unit and Extension Units can be in any order. Additional + * Extension Units connected to the main chain as single-unit branches are + * also supported. Single-input Selector Units are ignored. */ -static int uvc_scan_chain_entity(struct uvc_video_device *video, +static int uvc_scan_chain_entity(struct uvc_video_chain *chain, struct uvc_entity *entity) { switch (UVC_ENTITY_TYPE(entity)) { @@ -1268,20 +1215,20 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, return -1; } - list_add_tail(&entity->chain, &video->extensions); + list_add_tail(&entity->chain, &chain->extensions); break; case UVC_VC_PROCESSING_UNIT: if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- PU %d", entity->id); - if (video->processing != NULL) { + if (chain->processing != NULL) { uvc_trace(UVC_TRACE_DESCR, "Found multiple " "Processing Units in chain.\n"); return -1; } - video->processing = entity; + chain->processing = entity; break; case UVC_VC_SELECTOR_UNIT: @@ -1292,13 +1239,13 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, if (entity->selector.bNrInPins == 1) break; - if (video->selector != NULL) { + if (chain->selector != NULL) { uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector " "Units in chain.\n"); return -1; } - video->selector = entity; + chain->selector = entity; break; case UVC_ITT_VENDOR_SPECIFIC: @@ -1307,7 +1254,7 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- IT %d\n", entity->id); - list_add_tail(&entity->chain, &video->iterms); + list_add_tail(&entity->chain, &chain->iterms); break; case UVC_TT_STREAMING: @@ -1320,14 +1267,7 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, return -1; } - if (video->sterm != NULL) { - uvc_trace(UVC_TRACE_DESCR, "Found multiple streaming " - "entities in chain.\n"); - return -1; - } - - list_add_tail(&entity->chain, &video->iterms); - video->sterm = entity; + list_add_tail(&entity->chain, &chain->iterms); break; default: @@ -1339,7 +1279,7 @@ static int uvc_scan_chain_entity(struct uvc_video_device *video, return 0; } -static int uvc_scan_chain_forward(struct uvc_video_device *video, +static int uvc_scan_chain_forward(struct uvc_video_chain *chain, struct uvc_entity *entity, struct uvc_entity *prev) { struct uvc_entity *forward; @@ -1350,28 +1290,51 @@ static int uvc_scan_chain_forward(struct uvc_video_device *video, found = 0; while (1) { - forward = uvc_entity_by_reference(video->dev, entity->id, + forward = uvc_entity_by_reference(chain->dev, entity->id, forward); if (forward == NULL) break; - - if (UVC_ENTITY_TYPE(forward) != UVC_VC_EXTENSION_UNIT || - forward == prev) + if (forward == prev) continue; - if (forward->extension.bNrInPins != 1) { - uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has " - "more than 1 input pin.\n", entity->id); - return -1; - } + switch (UVC_ENTITY_TYPE(forward)) { + case UVC_VC_EXTENSION_UNIT: + if (forward->extension.bNrInPins != 1) { + uvc_trace(UVC_TRACE_DESCR, "Extension unit %d " + "has more than 1 input pin.\n", + entity->id); + return -EINVAL; + } + + list_add_tail(&forward->chain, &chain->extensions); + if (uvc_trace_param & UVC_TRACE_PROBE) { + if (!found) + printk(" (->"); + + printk(" XU %d", forward->id); + found = 1; + } + break; + + case UVC_OTT_VENDOR_SPECIFIC: + case UVC_OTT_DISPLAY: + case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: + case UVC_TT_STREAMING: + if (UVC_ENTITY_IS_ITERM(forward)) { + uvc_trace(UVC_TRACE_DESCR, "Unsupported input " + "terminal %u.\n", forward->id); + return -EINVAL; + } - list_add_tail(&forward->chain, &video->extensions); - if (uvc_trace_param & UVC_TRACE_PROBE) { - if (!found) - printk(" (-> XU"); + list_add_tail(&forward->chain, &chain->oterms); + if (uvc_trace_param & UVC_TRACE_PROBE) { + if (!found) + printk(" (->"); - printk(" %d", forward->id); - found = 1; + printk(" OT %d", forward->id); + found = 1; + } + break; } } if (found) @@ -1380,7 +1343,7 @@ static int uvc_scan_chain_forward(struct uvc_video_device *video, return 0; } -static int uvc_scan_chain_backward(struct uvc_video_device *video, +static int uvc_scan_chain_backward(struct uvc_video_chain *chain, struct uvc_entity *entity) { struct uvc_entity *term; @@ -1405,10 +1368,10 @@ static int uvc_scan_chain_backward(struct uvc_video_device *video, if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- IT"); - video->selector = entity; + chain->selector = entity; for (i = 0; i < entity->selector.bNrInPins; ++i) { id = entity->selector.baSourceID[i]; - term = uvc_entity_by_id(video->dev, id); + term = uvc_entity_by_id(chain->dev, id); if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) { uvc_trace(UVC_TRACE_DESCR, "Selector unit %d " "input %d isn't connected to an " @@ -1419,8 +1382,8 @@ static int uvc_scan_chain_backward(struct uvc_video_device *video, if (uvc_trace_param & UVC_TRACE_PROBE) printk(" %d", term->id); - list_add_tail(&term->chain, &video->iterms); - uvc_scan_chain_forward(video, term, entity); + list_add_tail(&term->chain, &chain->iterms); + uvc_scan_chain_forward(chain, term, entity); } if (uvc_trace_param & UVC_TRACE_PROBE) @@ -1433,100 +1396,129 @@ static int uvc_scan_chain_backward(struct uvc_video_device *video, return id; } -static int uvc_scan_chain(struct uvc_video_device *video) +static int uvc_scan_chain(struct uvc_video_chain *chain, + struct uvc_entity *oterm) { struct uvc_entity *entity, *prev; int id; - entity = video->oterm; + entity = oterm; + list_add_tail(&entity->chain, &chain->oterms); uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); - if (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) - video->sterm = entity; - id = entity->output.bSourceID; while (id != 0) { prev = entity; - entity = uvc_entity_by_id(video->dev, id); + entity = uvc_entity_by_id(chain->dev, id); if (entity == NULL) { uvc_trace(UVC_TRACE_DESCR, "Found reference to " "unknown entity %d.\n", id); - return -1; + return -EINVAL; + } + + if (entity->chain.next || entity->chain.prev) { + uvc_trace(UVC_TRACE_DESCR, "Found reference to " + "entity %d already in chain.\n", id); + return -EINVAL; } /* Process entity */ - if (uvc_scan_chain_entity(video, entity) < 0) - return -1; + if (uvc_scan_chain_entity(chain, entity) < 0) + return -EINVAL; /* Forward scan */ - if (uvc_scan_chain_forward(video, entity, prev) < 0) - return -1; + if (uvc_scan_chain_forward(chain, entity, prev) < 0) + return -EINVAL; /* Stop when a terminal is found. */ - if (!UVC_ENTITY_IS_UNIT(entity)) + if (UVC_ENTITY_IS_TERM(entity)) break; /* Backward scan */ - id = uvc_scan_chain_backward(video, entity); + id = uvc_scan_chain_backward(chain, entity); if (id < 0) return id; } - if (video->sterm == NULL) { - uvc_trace(UVC_TRACE_DESCR, "No streaming entity found in " - "chain.\n"); - return -1; + return 0; +} + +static unsigned int uvc_print_terms(struct list_head *terms, char *buffer) +{ + struct uvc_entity *term; + unsigned int nterms = 0; + char *p = buffer; + + list_for_each_entry(term, terms, chain) { + p += sprintf(p, "%u", term->id); + if (term->chain.next != terms) { + p += sprintf(p, ","); + if (++nterms >= 4) { + p += sprintf(p, "..."); + break; + } + } } - return 0; + return p - buffer; +} + +static const char *uvc_print_chain(struct uvc_video_chain *chain) +{ + static char buffer[43]; + char *p = buffer; + + p += uvc_print_terms(&chain->iterms, p); + p += sprintf(p, " -> "); + uvc_print_terms(&chain->oterms, p); + + return buffer; } /* * Scan the device for video chains and register video devices. * - * The driver currently supports a single video device per control interface - * only. The terminal and units must match the following structure: - * - * ITT_* -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> TT_STREAMING - * TT_STREAMING -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> OTT_* - * - * The Extension Units, if present, must have a single input pin. The - * Processing Unit and Extension Units can be in any order. Additional - * Extension Units connected to the main chain as single-unit branches are - * also supported. + * Chains are scanned starting at their output terminals and walked backwards. */ static int uvc_scan_device(struct uvc_device *dev) { + struct uvc_video_chain *chain; struct uvc_entity *term; - int found = 0; - /* Check if the control interface matches the structure we expect. */ list_for_each_entry(term, &dev->entities, list) { - struct uvc_streaming *stream; - - if (!UVC_ENTITY_IS_TERM(term) || !UVC_ENTITY_IS_OTERM(term)) + if (!UVC_ENTITY_IS_OTERM(term)) continue; - memset(&dev->video, 0, sizeof dev->video); - mutex_init(&dev->video.ctrl_mutex); - INIT_LIST_HEAD(&dev->video.iterms); - INIT_LIST_HEAD(&dev->video.extensions); - dev->video.oterm = term; - dev->video.dev = dev; - if (uvc_scan_chain(&dev->video) < 0) + /* If the terminal is already included in a chain, skip it. + * This can happen for chains that have multiple output + * terminals, where all output terminals beside the first one + * will be inserted in the chain in forward scans. + */ + if (term->chain.next || term->chain.prev) continue; - list_for_each_entry(stream, &dev->streams, list) { - if (stream->header.bTerminalLink == - dev->video.sterm->id) { - uvc_register_video(dev, stream); - found = 1; - break; - } + chain = kzalloc(sizeof(*chain), GFP_KERNEL); + if (chain == NULL) + return -ENOMEM; + + INIT_LIST_HEAD(&chain->iterms); + INIT_LIST_HEAD(&chain->oterms); + INIT_LIST_HEAD(&chain->extensions); + mutex_init(&chain->ctrl_mutex); + chain->dev = dev; + + if (uvc_scan_chain(chain, term) < 0) { + kfree(chain); + continue; } + + uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n", + uvc_print_chain(chain)); + + list_add_tail(&chain->list, &dev->chains); } - if (!found) { + if (list_empty(&dev->chains)) { uvc_printk(KERN_INFO, "No valid video chain found.\n"); return -1; } @@ -1534,6 +1526,133 @@ static int uvc_scan_device(struct uvc_device *dev) return 0; } +/* ------------------------------------------------------------------------ + * Video device registration and unregistration + */ + +/* + * Unregister the video devices. + */ +static void uvc_unregister_video(struct uvc_device *dev) +{ + struct uvc_streaming *stream; + + list_for_each_entry(stream, &dev->streams, list) { + if (stream->vdev == NULL) + continue; + + if (stream->vdev->minor == -1) + video_device_release(stream->vdev); + else + video_unregister_device(stream->vdev); + stream->vdev = NULL; + } +} + +static int uvc_register_video(struct uvc_device *dev, + struct uvc_streaming *stream) +{ + struct video_device *vdev; + int ret; + + /* Initialize the streaming interface with default streaming + * parameters. + */ + ret = uvc_video_init(stream); + if (ret < 0) { + uvc_printk(KERN_ERR, "Failed to initialize the device " + "(%d).\n", ret); + return ret; + } + + /* Register the device with V4L. */ + vdev = video_device_alloc(); + if (vdev == NULL) { + uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n", + ret); + return -ENOMEM; + } + + /* We already hold a reference to dev->udev. The video device will be + * unregistered before the reference is released, so we don't need to + * get another one. + */ + vdev->parent = &dev->intf->dev; + vdev->minor = -1; + vdev->fops = &uvc_fops; + vdev->release = video_device_release; + strlcpy(vdev->name, dev->name, sizeof vdev->name); + + /* Set the driver data before calling video_register_device, otherwise + * uvc_v4l2_open might race us. + */ + stream->vdev = vdev; + video_set_drvdata(vdev, stream); + + ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + if (ret < 0) { + uvc_printk(KERN_ERR, "Failed to register video device (%d).\n", + ret); + stream->vdev = NULL; + video_device_release(vdev); + return ret; + } + + return 0; +} + +/* + * Register all video devices in all chains. + */ +static int uvc_register_terms(struct uvc_device *dev, + struct uvc_video_chain *chain, struct list_head *terms) +{ + struct uvc_streaming *stream; + struct uvc_entity *term; + int ret; + + list_for_each_entry(term, terms, chain) { + if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING) + continue; + + stream = uvc_stream_by_id(dev, term->id); + if (stream == NULL) { + uvc_printk(KERN_INFO, "No streaming interface found " + "for terminal %u.", term->id); + continue; + } + + stream->chain = chain; + ret = uvc_register_video(dev, stream); + if (ret < 0) + return ret; + } + + return 0; +} + +static int uvc_register_chains(struct uvc_device *dev) +{ + struct uvc_video_chain *chain; + int ret; + + list_for_each_entry(chain, &dev->chains, list) { + ret = uvc_register_terms(dev, chain, &chain->iterms); + if (ret < 0) + return ret; + + ret = uvc_register_terms(dev, chain, &chain->oterms); + if (ret < 0) + return ret; + } + + return 0; +} + +/* ------------------------------------------------------------------------ + * USB probe, disconnect, suspend and resume + */ + /* * Delete the UVC device. * @@ -1555,7 +1674,7 @@ void uvc_delete(struct kref *kref) struct uvc_device *dev = container_of(kref, struct uvc_device, kref); struct list_head *p, *n; - /* Unregister the video device. */ + /* Unregister the video devices. */ uvc_unregister_video(dev); usb_put_intf(dev->intf); usb_put_dev(dev->udev); @@ -1563,6 +1682,12 @@ void uvc_delete(struct kref *kref) uvc_status_cleanup(dev); uvc_ctrl_cleanup_device(dev); + list_for_each_safe(p, n, &dev->chains) { + struct uvc_video_chain *chain; + chain = list_entry(p, struct uvc_video_chain, list); + kfree(chain); + } + list_for_each_safe(p, n, &dev->entities) { struct uvc_entity *entity; entity = list_entry(p, struct uvc_entity, list); @@ -1603,6 +1728,7 @@ static int uvc_probe(struct usb_interface *intf, return -ENOMEM; INIT_LIST_HEAD(&dev->entities); + INIT_LIST_HEAD(&dev->chains); INIT_LIST_HEAD(&dev->streams); kref_init(&dev->kref); atomic_set(&dev->users, 0); @@ -1644,10 +1770,14 @@ static int uvc_probe(struct usb_interface *intf, if (uvc_ctrl_init_device(dev) < 0) goto error; - /* Scan the device for video chains and register video devices. */ + /* Scan the device for video chains. */ if (uvc_scan_device(dev) < 0) goto error; + /* Register video devices. */ + if (uvc_register_chains(dev) < 0) + goto error; + /* Save our data pointer in the interface data. */ usb_set_intfdata(intf, dev); diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c index 3379e1320..b5a16acb6 100644 --- a/linux/drivers/media/video/uvc/uvc_v4l2.c +++ b/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -40,7 +40,7 @@ * table for the controls that can be mapped directly, and handle the others * manually. */ -static int uvc_v4l2_query_menu(struct uvc_video_device *video, +static int uvc_v4l2_query_menu(struct uvc_video_chain *chain, struct v4l2_querymenu *query_menu) { struct uvc_menu_info *menu_info; @@ -49,7 +49,7 @@ static int uvc_v4l2_query_menu(struct uvc_video_device *video, u32 index = query_menu->index; u32 id = query_menu->id; - ctrl = uvc_find_control(video, query_menu->id, &mapping); + ctrl = uvc_find_control(chain, query_menu->id, &mapping); if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) return -EINVAL; @@ -457,7 +457,7 @@ static int uvc_v4l2_open(struct file *file) } } - handle->video = &stream->dev->video; + handle->chain = stream->chain; handle->stream = stream; handle->state = UVC_HANDLE_PASSIVE; file->private_data = handle; @@ -506,7 +506,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); struct uvc_fh *handle = (struct uvc_fh *)file->private_data; - struct uvc_video_device *video = handle->video; + struct uvc_video_chain *chain = handle->chain; struct uvc_streaming *stream = handle->stream; long ret = 0; @@ -533,7 +533,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) /* Get, Set & Query control */ case VIDIOC_QUERYCTRL: - return uvc_query_v4l2_ctrl(video, arg); + return uvc_query_v4l2_ctrl(chain, arg); case VIDIOC_G_CTRL: { @@ -543,12 +543,12 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) memset(&xctrl, 0, sizeof xctrl); xctrl.id = ctrl->id; - ret = uvc_ctrl_begin(video); - if (ret < 0) + ret = uvc_ctrl_begin(chain); + if (ret < 0) return ret; - ret = uvc_ctrl_get(video, &xctrl); - uvc_ctrl_rollback(video); + ret = uvc_ctrl_get(chain, &xctrl); + uvc_ctrl_rollback(chain); if (ret >= 0) ctrl->value = xctrl.value; break; @@ -563,21 +563,21 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) xctrl.id = ctrl->id; xctrl.value = ctrl->value; - ret = uvc_ctrl_begin(video); - if (ret < 0) + uvc_ctrl_begin(chain); + if (ret < 0) return ret; - ret = uvc_ctrl_set(video, &xctrl); + ret = uvc_ctrl_set(chain, &xctrl); if (ret < 0) { - uvc_ctrl_rollback(video); + uvc_ctrl_rollback(chain); return ret; } - ret = uvc_ctrl_commit(video); + ret = uvc_ctrl_commit(chain); break; } case VIDIOC_QUERYMENU: - return uvc_v4l2_query_menu(video, arg); + return uvc_v4l2_query_menu(chain, arg); case VIDIOC_G_EXT_CTRLS: { @@ -585,20 +585,20 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_ext_control *ctrl = ctrls->controls; unsigned int i; - ret = uvc_ctrl_begin(video); - if (ret < 0) + ret = uvc_ctrl_begin(chain); + if (ret < 0) return ret; for (i = 0; i < ctrls->count; ++ctrl, ++i) { - ret = uvc_ctrl_get(video, ctrl); + ret = uvc_ctrl_get(chain, ctrl); if (ret < 0) { - uvc_ctrl_rollback(video); + uvc_ctrl_rollback(chain); ctrls->error_idx = i; return ret; } } ctrls->error_idx = 0; - ret = uvc_ctrl_rollback(video); + ret = uvc_ctrl_rollback(chain); break; } @@ -609,14 +609,14 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_ext_control *ctrl = ctrls->controls; unsigned int i; - ret = uvc_ctrl_begin(video); + ret = uvc_ctrl_begin(chain); if (ret < 0) return ret; for (i = 0; i < ctrls->count; ++ctrl, ++i) { - ret = uvc_ctrl_set(video, ctrl); + ret = uvc_ctrl_set(chain, ctrl); if (ret < 0) { - uvc_ctrl_rollback(video); + uvc_ctrl_rollback(chain); ctrls->error_idx = i; return ret; } @@ -625,31 +625,31 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ctrls->error_idx = 0; if (cmd == VIDIOC_S_EXT_CTRLS) - ret = uvc_ctrl_commit(video); + ret = uvc_ctrl_commit(chain); else - ret = uvc_ctrl_rollback(video); + ret = uvc_ctrl_rollback(chain); break; } /* Get, Set & Enum input */ case VIDIOC_ENUMINPUT: { - const struct uvc_entity *selector = video->selector; + const struct uvc_entity *selector = chain->selector; struct v4l2_input *input = arg; struct uvc_entity *iterm = NULL; u32 index = input->index; int pin = 0; if (selector == NULL || - (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { + (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { if (index != 0) return -EINVAL; - iterm = list_first_entry(&video->iterms, + iterm = list_first_entry(&chain->iterms, struct uvc_entity, chain); pin = iterm->id; } else if (pin < selector->selector.bNrInPins) { pin = selector->selector.baSourceID[index]; - list_for_each_entry(iterm, video->iterms.next, chain) { + list_for_each_entry(iterm, chain->iterms.next, chain) { if (iterm->id == pin) break; } @@ -670,14 +670,14 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { u8 input; - if (video->selector == NULL || - (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { + if (chain->selector == NULL || + (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { *(int *)arg = 0; break; } - ret = uvc_query_ctrl(video->dev, UVC_GET_CUR, - video->selector->id, video->dev->intfnum, + ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, + chain->selector->id, chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL, &input, 1); if (ret < 0) return ret; @@ -693,18 +693,18 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - if (video->selector == NULL || - (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { + if (chain->selector == NULL || + (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { if (input != 1) return -EINVAL; break; } - if (input == 0 || input > video->selector->selector.bNrInPins) + if (input == 0 || input > chain->selector->selector.bNrInPins) return -EINVAL; - return uvc_query_ctrl(video->dev, UVC_SET_CUR, - video->selector->id, video->dev->intfnum, + return uvc_query_ctrl(chain->dev, UVC_SET_CUR, + chain->selector->id, chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL, &input, 1); } @@ -1027,10 +1027,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) } case UVCIOC_CTRL_GET: - return uvc_xu_ctrl_query(video, arg, 0); + return uvc_xu_ctrl_query(chain, arg, 0); case UVCIOC_CTRL_SET: - return uvc_xu_ctrl_query(video, arg, 1); + return uvc_xu_ctrl_query(chain, arg, 1); default: if ((ret = v4l_compat_translate_ioctl(file, cmd, arg, diff --git a/linux/drivers/media/video/uvc/uvc_video.c b/linux/drivers/media/video/uvc/uvc_video.c index 38cb7a367..792a93a1c 100644 --- a/linux/drivers/media/video/uvc/uvc_video.c +++ b/linux/drivers/media/video/uvc/uvc_video.c @@ -128,7 +128,7 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream, if (data == NULL) return -ENOMEM; - if ((video->dev->quirks & UVC_QUIRK_PROBE_DEF) && query == UVC_GET_DEF) + if ((stream->dev->quirks & UVC_QUIRK_PROBE_DEF) && query == UVC_GET_DEF) return -EIO; ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum, diff --git a/linux/drivers/media/video/uvc/uvcvideo.h b/linux/drivers/media/video/uvc/uvcvideo.h index c385b7bde..30a17f24e 100644 --- a/linux/drivers/media/video/uvc/uvcvideo.h +++ b/linux/drivers/media/video/uvc/uvcvideo.h @@ -81,9 +81,11 @@ struct uvc_xu_control { #define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0) #define UVC_ENTITY_IS_TERM(entity) (((entity)->type & 0xff00) != 0) #define UVC_ENTITY_IS_ITERM(entity) \ - (((entity)->type & 0x8000) == UVC_TERM_INPUT) + (UVC_ENTITY_IS_TERM(entity) && \ + ((entity)->type & 0x8000) == UVC_TERM_INPUT) #define UVC_ENTITY_IS_OTERM(entity) \ - (((entity)->type & 0x8000) == UVC_TERM_OUTPUT) + (UVC_ENTITY_IS_TERM(entity) && \ + ((entity)->type & 0x8000) == UVC_TERM_OUTPUT) /* ------------------------------------------------------------------------ @@ -403,10 +405,24 @@ struct uvc_video_queue { struct list_head irqqueue; }; +struct uvc_video_chain { + struct uvc_device *dev; + struct list_head list; + + struct list_head iterms; /* Input terminals */ + struct list_head oterms; /* Output terminals */ + struct uvc_entity *processing; /* Processing unit */ + struct uvc_entity *selector; /* Selector unit */ + struct list_head extensions; /* Extension units */ + + struct mutex ctrl_mutex; +}; + struct uvc_streaming { struct list_head list; struct uvc_device *dev; struct video_device *vdev; + struct uvc_video_chain *chain; atomic_t active; struct usb_interface *intf; @@ -447,18 +463,6 @@ struct uvc_streaming { __u8 last_fid; }; -struct uvc_video_device { - struct uvc_device *dev; - - struct list_head iterms; /* Input terminals */ - struct uvc_entity *oterm; /* Output terminal */ - struct uvc_entity *sterm; /* USB streaming terminal */ - struct uvc_entity *processing; - struct uvc_entity *selector; - struct list_head extensions; - struct mutex ctrl_mutex; -}; - enum uvc_device_state { UVC_DEV_DISCONNECTED = 1, }; @@ -481,8 +485,7 @@ struct uvc_device { __u32 clock_frequency; struct list_head entities; - - struct uvc_video_device video; + struct list_head chains; /* Video Streaming interfaces */ struct list_head streams; @@ -501,7 +504,7 @@ enum uvc_handle_state { }; struct uvc_fh { - struct uvc_video_device *video; + struct uvc_video_chain *chain; struct uvc_streaming *stream; enum uvc_handle_state state; }; @@ -619,9 +622,9 @@ extern int uvc_status_suspend(struct uvc_device *dev); extern int uvc_status_resume(struct uvc_device *dev); /* Controls */ -extern struct uvc_control *uvc_find_control(struct uvc_video_device *video, +extern struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, __u32 v4l2_id, struct uvc_control_mapping **mapping); -extern int uvc_query_v4l2_ctrl(struct uvc_video_device *video, +extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, struct v4l2_queryctrl *v4l2_ctrl); extern int uvc_ctrl_add_info(struct uvc_control_info *info); @@ -631,23 +634,23 @@ extern void uvc_ctrl_cleanup_device(struct uvc_device *dev); extern int uvc_ctrl_resume_device(struct uvc_device *dev); extern void uvc_ctrl_init(void); -extern int uvc_ctrl_begin(struct uvc_video_device *video); -extern int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback); -static inline int uvc_ctrl_commit(struct uvc_video_device *video) +extern int uvc_ctrl_begin(struct uvc_video_chain *chain); +extern int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback); +static inline int uvc_ctrl_commit(struct uvc_video_chain *chain) { - return __uvc_ctrl_commit(video, 0); + return __uvc_ctrl_commit(chain, 0); } -static inline int uvc_ctrl_rollback(struct uvc_video_device *video) +static inline int uvc_ctrl_rollback(struct uvc_video_chain *chain) { - return __uvc_ctrl_commit(video, 1); + return __uvc_ctrl_commit(chain, 1); } -extern int uvc_ctrl_get(struct uvc_video_device *video, +extern int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl); -extern int uvc_ctrl_set(struct uvc_video_device *video, +extern int uvc_ctrl_set(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl); -extern int uvc_xu_ctrl_query(struct uvc_video_device *video, +extern int uvc_xu_ctrl_query(struct uvc_video_chain *chain, struct uvc_xu_control *ctrl, int set); /* Utility functions */ -- cgit v1.2.3 From db44a7d2b169cceeafa7a8b5fc5b8fe921d4088d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 12 Jul 2009 22:30:14 -0400 Subject: sms1xxx: restore GPIO functionality for all Hauppauge devices From: Michael Krufky Previous changesets broke Hauppauge devices and their GPIO configurations. This changeset restores the LED & LNA functionality. Priority: high Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/smsdvb.c | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c index f8856d9c8..67634899d 100644 --- a/linux/drivers/media/dvb/siano/smsdvb.c +++ b/linux/drivers/media/dvb/siano/smsdvb.c @@ -325,6 +325,16 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, 0 : -ETIME; } +static inline int led_feedback(struct smsdvb_client_t *client) +{ + if (client->fe_status & FE_HAS_LOCK) + return sms_board_led_feedback(client->coredev, + (client->sms_stat_dvb.ReceptionData.BER + == 0) ? SMS_LED_HI : SMS_LED_LO); + else + return sms_board_led_feedback(client->coredev, SMS_LED_OFF); +} + static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) { struct smsdvb_client_t *client; @@ -332,6 +342,8 @@ static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) *stat = client->fe_status; + led_feedback(client); + return 0; } @@ -342,6 +354,8 @@ static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) *ber = client->sms_stat_dvb.ReceptionData.BER; + led_feedback(client); + return 0; } @@ -359,6 +373,8 @@ static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) (client->sms_stat_dvb.ReceptionData.InBandPwr + 95) * 3 / 2; + led_feedback(client); + return 0; } @@ -369,6 +385,8 @@ static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) *snr = client->sms_stat_dvb.ReceptionData.SNR; + led_feedback(client); + return 0; } @@ -379,6 +397,8 @@ static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; + led_feedback(client); + return 0; } @@ -404,6 +424,8 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, u32 Data[3]; } Msg; + int ret; + client->fe_status = FE_HAS_SIGNAL; client->event_fe_state = -1; client->event_unc_state = -1; @@ -429,6 +451,23 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, case BANDWIDTH_AUTO: return -EOPNOTSUPP; default: return -EINVAL; } + /* Disable LNA, if any. An error is returned if no LNA is present */ + ret = sms_board_lna_control(client->coredev, 0); + if (ret == 0) { + fe_status_t status; + + /* tune with LNA off at first */ + ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), + &client->tune_done); + + smsdvb_read_status(fe, &status); + + if (status & FE_HAS_LOCK) + return ret; + + /* previous tune didnt lock - enable LNA and tune again */ + sms_board_lna_control(client->coredev, 1); + } return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), &client->tune_done); @@ -454,6 +493,8 @@ static int smsdvb_init(struct dvb_frontend *fe) struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); + sms_board_power(client->coredev, 1); + sms_board_dvb3_event(client, DVB3_EVENT_INIT); return 0; } @@ -463,6 +504,9 @@ static int smsdvb_sleep(struct dvb_frontend *fe) struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); + sms_board_led_feedback(client->coredev, SMS_LED_OFF); + sms_board_power(client->coredev, 0); + sms_board_dvb3_event(client, DVB3_EVENT_SLEEP); return 0; -- cgit v1.2.3 From 63f6769bcad76518a85506b5f19de1a48707d6fb Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 29 Jul 2009 10:01:54 +0200 Subject: gspca - main: Remove vidioc_s_std(). From: Marton Nemeth The vidioc_s_std() is not necessary when vdev->tvnorms == 0. Priority: normal Signed-off-by: Marton Nemeth Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/gspca.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index 2e5197073..670091e42 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -1504,12 +1504,6 @@ static int vidioc_s_parm(struct file *filp, void *priv, return 0; } -static int vidioc_s_std(struct file *filp, void *priv, - v4l2_std_id *parm) -{ - return 0; -} - #ifdef CONFIG_VIDEO_V4L1_COMPAT static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) @@ -1980,7 +1974,6 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = { .vidioc_s_jpegcomp = vidioc_s_jpegcomp, .vidioc_g_parm = vidioc_g_parm, .vidioc_s_parm = vidioc_s_parm, - .vidioc_s_std = vidioc_s_std, .vidioc_enum_framesizes = vidioc_enum_framesizes, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, -- cgit v1.2.3 From be7e7366b6e627b24db77147c07f9a3deb5f3933 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 1 Aug 2009 23:14:24 +0200 Subject: uvcvideo: Avoid flooding the kernel log with "unknown event type" messages From: Laurent Pinchart The iSight sends non-UVC status events through the interrupt endpoint. Those invalid events are reported to the kernel log, resulting in a log flood. Only log the events when the UVC_TRACE_STATUS flag is set. Priority: high Signed-off-by: Laurent Pinchart --- linux/drivers/media/video/uvc/uvc_status.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/uvc/uvc_status.c b/linux/drivers/media/video/uvc/uvc_status.c index b05df63b4..48614d39c 100644 --- a/linux/drivers/media/video/uvc/uvc_status.c +++ b/linux/drivers/media/video/uvc/uvc_status.c @@ -157,8 +157,8 @@ static void uvc_status_complete(struct urb *urb) break; default: - uvc_printk(KERN_INFO, "unknown event type %u.\n", - dev->status[0]); + uvc_trace(UVC_TRACE_STATUS, "Unknown status event " + "type %u.\n", dev->status[0]); break; } } -- cgit v1.2.3 From 0315e4babbc90dd9a89e82968fd924cae514d993 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 2 Aug 2009 11:56:47 +0200 Subject: gspca - vc032x: Bad h/v flip controls when inverted by default. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 44dea7949..6f9aab89c 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -3135,10 +3135,10 @@ static void sethvflip(struct gspca_dev *gspca_dev) hflip = sd->hflip; if (sd->flags & FL_HFLIP) - hflip != hflip; + hflip = !hflip; vflip = sd->vflip; if (sd->flags & FL_VFLIP) - vflip != vflip; + vflip = !vflip; switch (sd->sensor) { case SENSOR_MI1310_SOC: case SENSOR_MI1320_SOC: -- cgit v1.2.3 From 920d68bc15da48dcaf2144b777f7dcae138599ca Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 2 Aug 2009 11:37:34 -0400 Subject: sms1xxx: fix build warning: unused variable 'board' From: Michael Krufky Remove the following build warning: sms-cards.c: In function 'sms_board_event': sms-cards.c:120: warning: unused variable 'board' Thanks to Hans Verkuil for pointing this out. The problem code has been #if 0'd for now, this will likely be used again in the future, once the event interface is complete. Priority: high Signed-off-by: Michael Krufky Cc: Hans Verkuil --- linux/drivers/media/dvb/siano/sms-cards.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c index 76bd3cb82..62c1bf604 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -116,8 +116,10 @@ static inline void sms_gpio_assign_11xx_default_led_config( int sms_board_event(struct smscore_device_t *coredev, enum SMS_BOARD_EVENTS gevent) { +#if 0 int board_id = smscore_get_board_id(coredev); struct sms_board *board = sms_get_board(board_id); +#endif struct smscore_gpio_config MyGpioConfig; sms_gpio_assign_11xx_default_led_config(&MyGpioConfig); -- cgit v1.2.3 From 2e966abec56337af8c6314850d990720869b8786 Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Sun, 2 Aug 2009 20:44:37 +0200 Subject: dvb-usb: fix tuning with Cinergy T2 From: Eberhard Mattes cinergyInitialize param.flags. Priority: normal Signed-off-by: Eberhard Mattes Signed-off-by: Thierry MERLE --- linux/drivers/media/dvb/dvb-usb/cinergyT2-fe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/linux/drivers/media/dvb/dvb-usb/cinergyT2-fe.c index 649f25cca..9cd51ac12 100644 --- a/linux/drivers/media/dvb/dvb-usb/cinergyT2-fe.c +++ b/linux/drivers/media/dvb/dvb-usb/cinergyT2-fe.c @@ -275,6 +275,7 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe, param.tps = cpu_to_le16(compute_tps(fep)); param.freq = cpu_to_le32(fep->frequency / 1000); param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ; + param.flags = 0; err = dvb_usb_generic_rw(state->d, (char *)¶m, sizeof(param), -- cgit v1.2.3 From a692c68699d6ba2a72b200dac53a34a8f5d889a2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 3 Aug 2009 09:13:23 +0200 Subject: gspca - jeilinj: New subdriver for Jeilin chip. From: Theodore Kilgore Priority: normal Signed-off-by: Theodore Kilgore Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + linux/drivers/media/video/gspca/Kconfig | 9 + linux/drivers/media/video/gspca/Makefile | 2 + linux/drivers/media/video/gspca/jeilinj.c | 388 ++++++++++++++++++++++++++++++ 4 files changed, 400 insertions(+) create mode 100644 linux/drivers/media/video/gspca/jeilinj.c diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index b43702470..76203a221 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -239,6 +239,7 @@ pac7311 093a:2626 Labtec 2200 pac7311 093a:2629 Genious iSlim 300 pac7311 093a:262a Webcam 300k pac7311 093a:262c Philips SPC 230 NC +jeilinj 0979:0280 Sakar 57379 zc3xx 0ac8:0302 Z-star Vimicro zc0302 vc032x 0ac8:0321 Vimicro generic vc0321 vc032x 0ac8:0323 Vimicro Vc0323 diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index a14561956..c9166e543 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -47,6 +47,15 @@ config USB_GSPCA_FINEPIX To compile this driver as a module, choose M here: the module will be called gspca_finepix. +config USB_GSPCA_JEILINJ + tristate "Jeilin JPEG USB V4L2 driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based on this Jeilin chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_jeilinj. + config USB_GSPCA_MARS tristate "Mars USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/linux/drivers/media/video/gspca/Makefile b/linux/drivers/media/video/gspca/Makefile index f6d3b86e9..035616b5e 100644 --- a/linux/drivers/media/video/gspca/Makefile +++ b/linux/drivers/media/video/gspca/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_USB_GSPCA) += gspca_main.o obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o +obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o @@ -30,6 +31,7 @@ gspca_main-objs := gspca.o gspca_conex-objs := conex.o gspca_etoms-objs := etoms.o gspca_finepix-objs := finepix.o +gspca_jeilinj-objs := jeilinj.o gspca_mars-objs := mars.o gspca_mr97310a-objs := mr97310a.o gspca_ov519-objs := ov519.o diff --git a/linux/drivers/media/video/gspca/jeilinj.c b/linux/drivers/media/video/gspca/jeilinj.c new file mode 100644 index 000000000..dbfa3ed6e --- /dev/null +++ b/linux/drivers/media/video/gspca/jeilinj.c @@ -0,0 +1,388 @@ +/* + * Jeilinj subdriver + * + * Supports some Jeilin dual-mode cameras which use bulk transport and + * download raw JPEG data. + * + * Copyright (C) 2009 Theodore Kilgore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define MODULE_NAME "jeilinj" + +#include +#include "gspca.h" +#include "jpeg.h" + +MODULE_AUTHOR("Theodore Kilgore "); +MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver"); +MODULE_LICENSE("GPL"); + +/* Default timeouts, in ms */ +#define JEILINJ_CMD_TIMEOUT 500 +#define JEILINJ_DATA_TIMEOUT 1000 + +/* Maximum transfer size to use. */ +#define JEILINJ_MAX_TRANSFER 0x200 + +#define FRAME_HEADER_LEN 0x10 + +/* Structure to hold all of our device specific stuff */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + const struct v4l2_pix_format *cap_mode; + /* Driver stuff */ + struct work_struct work_struct; + struct workqueue_struct *work_thread; + u8 quality; /* image quality */ + u8 jpegqual; /* webcam quality */ + u8 *jpeg_hdr; +}; + + struct jlj_command { + unsigned char instruction[2]; + unsigned char ack_wanted; + }; + +/* AFAICT these cameras will only do 320x240. */ +static struct v4l2_pix_format jlj_mode[] = { + { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 0} +}; + +/* + * cam uses endpoint 0x03 to send commands, 0x84 for read commands, + * and 0x82 for bulk transfer. + */ + +/* All commands are two bytes only */ +static int jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command) +{ + int retval; + + memcpy(gspca_dev->usb_buf, command, 2); + retval = usb_bulk_msg(gspca_dev->dev, + usb_sndbulkpipe(gspca_dev->dev, 3), + gspca_dev->usb_buf, 2, NULL, 500); + if (retval < 0) + PDEBUG(D_ERR, "command write [%02x] error %d", + gspca_dev->usb_buf[0], retval); + return retval; +} + +/* Responses are one byte only */ +static int jlj_read1(struct gspca_dev *gspca_dev, unsigned char response) +{ + int retval; + + retval = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x84), + gspca_dev->usb_buf, 1, NULL, 500); + response = gspca_dev->usb_buf[0]; + if (retval < 0) + PDEBUG(D_ERR, "read command [%02x] error %d", + gspca_dev->usb_buf[0], retval); + return retval; +} + +static int jlj_start(struct gspca_dev *gspca_dev) +{ + int i; + int retval = -1; + u8 response = 0xff; + struct jlj_command start_commands[] = { + {{0x71, 0x81}, 0}, + {{0x70, 0x05}, 0}, + {{0x95, 0x70}, 1}, + {{0x71, 0x81}, 0}, + {{0x70, 0x04}, 0}, + {{0x95, 0x70}, 1}, + {{0x71, 0x00}, 0}, + {{0x70, 0x08}, 0}, + {{0x95, 0x70}, 1}, + {{0x94, 0x02}, 0}, + {{0xde, 0x24}, 0}, + {{0x94, 0x02}, 0}, + {{0xdd, 0xf0}, 0}, + {{0x94, 0x02}, 0}, + {{0xe3, 0x2c}, 0}, + {{0x94, 0x02}, 0}, + {{0xe4, 0x00}, 0}, + {{0x94, 0x02}, 0}, + {{0xe5, 0x00}, 0}, + {{0x94, 0x02}, 0}, + {{0xe6, 0x2c}, 0}, + {{0x94, 0x03}, 0}, + {{0xaa, 0x00}, 0}, + {{0x71, 0x1e}, 0}, + {{0x70, 0x06}, 0}, + {{0x71, 0x80}, 0}, + {{0x70, 0x07}, 0} + }; + for (i = 0; i < ARRAY_SIZE(start_commands); i++) { + retval = jlj_write2(gspca_dev, start_commands[i].instruction); + if (retval < 0) + return retval; + if (start_commands[i].ack_wanted) + retval = jlj_read1(gspca_dev, response); + if (retval < 0) + return retval; + } + PDEBUG(D_ERR, "jlj_start retval is %d", retval); + return retval; +} + +static int jlj_stop(struct gspca_dev *gspca_dev) +{ + int i; + int retval; + struct jlj_command stop_commands[] = { + {{0x71, 0x00}, 0}, + {{0x70, 0x09}, 0}, + {{0x71, 0x80}, 0}, + {{0x70, 0x05}, 0} + }; + for (i = 0; i < ARRAY_SIZE(stop_commands); i++) { + retval = jlj_write2(gspca_dev, stop_commands[i].instruction); + if (retval < 0) + return retval; + } + return retval; +} + +/* This function is called as a workqueue function and runs whenever the camera + * is streaming data. Because it is a workqueue function it is allowed to sleep + * so we can use synchronous USB calls. To avoid possible collisions with other + * threads attempting to use the camera's USB interface the gspca usb_lock is + * used when performing the one USB control operation inside the workqueue, + * which tells the camera to close the stream. In practice the only thing + * which needs to be protected against is the usb_set_interface call that + * gspca makes during stream_off. Otherwise the camera doesn't provide any + * controls that the user could try to change. + */ + +static void jlj_dostream(struct work_struct *work) +{ + struct sd *dev = container_of(work, struct sd, work_struct); + struct gspca_dev *gspca_dev = &dev->gspca_dev; + struct gspca_frame *frame; + int blocks_left; /* 0x200-sized blocks remaining in current frame. */ + int size_in_blocks; + int act_len; + int discarding = 0; /* true if we failed to get space for frame. */ + int packet_type; + int ret; + u8 *buffer; + + buffer = kmalloc(JEILINJ_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); + if (!buffer) { + PDEBUG(D_ERR, "Couldn't allocate USB buffer"); + goto quit_stream; + } + while (gspca_dev->present && gspca_dev->streaming) { + if (!gspca_dev->present) + goto quit_stream; + /* Start a new frame, and add the JPEG header, first thing */ + frame = gspca_get_i_frame(gspca_dev); + if (frame && !discarding) + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + dev->jpeg_hdr, JPEG_HDR_SZ); + else + discarding = 1; + /* + * Now request data block 0. Line 0 reports the size + * to download, in blocks of size 0x200, and also tells the + * "actual" data size, in bytes, which seems best to ignore. + */ + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x82), + buffer, JEILINJ_MAX_TRANSFER, &act_len, + JEILINJ_DATA_TIMEOUT); + PDEBUG(D_STREAM, + "Got %d bytes out of %d for Block 0", + act_len, JEILINJ_MAX_TRANSFER); + if (ret < 0 || act_len < FRAME_HEADER_LEN) + goto quit_stream; + size_in_blocks = buffer[0x0a]; + blocks_left = buffer[0x0a] - 1; + PDEBUG(D_STREAM, "blocks_left = 0x%x", blocks_left); + packet_type = INTER_PACKET; + if (frame && !discarding) + /* Toss line 0 of data block 0, keep the rest. */ + gspca_frame_add(gspca_dev, packet_type, + frame, buffer + FRAME_HEADER_LEN, + JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN); + else + discarding = 1; + while (blocks_left > 0) { + if (!gspca_dev->present) + goto quit_stream; + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x82), + buffer, JEILINJ_MAX_TRANSFER, &act_len, + JEILINJ_DATA_TIMEOUT); + if (ret < 0 || act_len < JEILINJ_MAX_TRANSFER) + goto quit_stream; + PDEBUG(D_STREAM, + "%d blocks remaining for frame", blocks_left); + blocks_left -= 1; + if (blocks_left == 0) + packet_type = LAST_PACKET; + else + packet_type = INTER_PACKET; + if (frame && !discarding) + gspca_frame_add(gspca_dev, packet_type, + frame, buffer, + JEILINJ_MAX_TRANSFER); + else + discarding = 1; + } + } +quit_stream: + mutex_lock(&gspca_dev->usb_lock); + if (gspca_dev->present) + jlj_stop(gspca_dev); + mutex_unlock(&gspca_dev->usb_lock); + kfree(buffer); +} + +/* This function is called at probe time just before sd_init */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct cam *cam = &gspca_dev->cam; + struct sd *dev = (struct sd *) gspca_dev; + + dev->quality = 85; + dev->jpegqual = 85; + PDEBUG(D_PROBE, + "JEILINJ camera detected" + " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + cam->cam_mode = jlj_mode; + cam->nmodes = 1; + cam->bulk = 1; + /* We don't use the buffer gspca allocates so make it small. */ + cam->bulk_size = 32; + INIT_WORK(&dev->work_struct, jlj_dostream); + return 0; +} + +/* called on streamoff with alt==0 and on disconnect */ +/* the usb_lock is held at entry - restore on exit */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + + /* wait for the work queue to terminate */ + mutex_unlock(&gspca_dev->usb_lock); + /* This waits for jlj_dostream to finish */ + destroy_workqueue(dev->work_thread); + dev->work_thread = NULL; + mutex_lock(&gspca_dev->usb_lock); + kfree(dev->jpeg_hdr); +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + return 0; +} + +/* Set up for getting frames. */ +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + int ret; + + /* create the JPEG header */ + dev->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); + jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width, + 0x21); /* JPEG 422 */ + jpeg_set_qual(dev->jpeg_hdr, dev->quality); + PDEBUG(D_STREAM, "Start streaming at 320x240"); + ret = jlj_start(gspca_dev); + if (ret < 0) { + PDEBUG(D_ERR, "Start streaming command failed"); + return ret; + } + /* Start the workqueue function to do the streaming */ + dev->work_thread = create_singlethread_workqueue(MODULE_NAME); + queue_work(dev->work_thread, &dev->work_struct); + + return 0; +} + +/* Table of supported USB devices */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x0979, 0x0280)}, + {} +}; + +MODULE_DEVICE_TABLE(usb, device_table); + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stop0 = sd_stop0, +}; + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, + &sd_desc, + sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + int ret; + + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + PDEBUG(D_PROBE, "registered"); + return 0; +} + +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); + PDEBUG(D_PROBE, "deregistered"); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); -- cgit v1.2.3 From f0b81434ee6e958e7ffc72aa28d580c3d08cb31c Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 3 Aug 2009 21:40:16 -0400 Subject: cx88: fix regression in tuning for Geniatech X8000 MT From: Devin Heitmueller The introduction of the zl10353 i2c gate control broke support for the Geniatech board (which is not behind an i2 gate). Add the needed parameter. Priority: high Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/cx88/cx88-dvb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 36f35f0b5..9c88b6c0f 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -502,6 +502,7 @@ static struct zl10353_config cx88_pinnacle_hybrid_pctv = { static struct zl10353_config cx88_geniatech_x8000_mt = { .demod_address = (0x1e >> 1), .no_tuner = 1, + .disable_i2c_gate_ctrl = 1, #if 0 .input_frequency = 0xe609, .parallel_ts = 1, -- cgit v1.2.3 From aa7df40721e36bcf9d4f1a60b9e58e69c08aac48 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 3 Aug 2009 21:52:59 -0400 Subject: cx88: Disable xc3028 power management for Geniatech x8000 From: Devin Heitmueller A user discovered that the Geniatech x8000 encountered a regression when the xc3028 power management was introduced. The xc3028 never recovers after setting the powerdown register, which is probably because the xc3028 reset GPIO is not properly configured. Since I do not have access to the hardware and thus cannot determine the correct GPIO configuration, just disable xc3028 power management on this board, which fixes the regression. Thanks to user "ritec" for reporting the issue and testing the fix. Priority: high Cc: rictec Signed-off-by: Devin Heitmueller --- linux/drivers/media/common/tuners/tuner-xc2028.c | 4 ++-- linux/drivers/media/common/tuners/tuner-xc2028.h | 1 + linux/drivers/media/video/cx88/cx88-cards.c | 8 ++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.c b/linux/drivers/media/common/tuners/tuner-xc2028.c index 3de5d6685..3cf380e6b 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.c +++ b/linux/drivers/media/common/tuners/tuner-xc2028.c @@ -1123,8 +1123,8 @@ static int xc2028_sleep(struct dvb_frontend *fe) struct xc2028_data *priv = fe->tuner_priv; int rc = 0; - /* Avoid firmware reload on slow devices */ - if (no_poweroff) + /* Avoid firmware reload on slow devices or if PM disabled */ + if (no_poweroff || priv->ctrl.disable_power_mgmt) return 0; tuner_dbg("Putting xc2028/3028 into poweroff mode.\n"); diff --git a/linux/drivers/media/common/tuners/tuner-xc2028.h b/linux/drivers/media/common/tuners/tuner-xc2028.h index 19de7928a..a90c35d50 100644 --- a/linux/drivers/media/common/tuners/tuner-xc2028.h +++ b/linux/drivers/media/common/tuners/tuner-xc2028.h @@ -38,6 +38,7 @@ struct xc2028_ctrl { unsigned int input1:1; unsigned int vhfbw7:1; unsigned int uhfbw8:1; + unsigned int disable_power_mgmt:1; unsigned int demod; enum firmware_type type:2; }; diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index bf0f26c03..67ccc59a7 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -3036,6 +3036,14 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: ctl->demod = XC3028_FE_OREN538; break; + case CX88_BOARD_GENIATECH_X8000_MT: + /* FIXME: For this board, the xc3028 never recovers after being + powered down (the reset GPIO probably is not set properly). + We don't have access to the hardware so we cannot determine + which GPIO is used for xc3028, so just disable power xc3028 + power management for now */ + ctl->disable_power_mgmt = 1; + break; case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: case CX88_BOARD_PROLINK_PV_8000GT: -- cgit v1.2.3 From 6355bbe94603dee693331f5ae62c8c1a109a8007 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 3 Aug 2009 22:56:51 -0400 Subject: em28xx: add support for Terratec Cinergy Hybrid T USB XS remote control From: Devin Heitmueller Add support for the remote control that comes with the Cinergy Hybrid T USB XS Thanks to Jelle de Jong for providing sample hardware to test with. Priority: normal Signed-off-by: Devin Heitmueller Cc: Jelle de Jong --- linux/drivers/media/common/ir-keymaps.c | 55 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-cards.c | 2 + linux/include/media/ir-common.h | 1 + 3 files changed, 58 insertions(+) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 56fa64b4c..67c67430d 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -2801,6 +2801,61 @@ IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { }; EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec); + +/* Terratec Cinergy Hybrid T USB XS + Devin Heitmueller + */ +IR_KEYTAB_TYPE ir_codes_terratec_cinergy_xs[IR_KEYTAB_SIZE] = { + [0x41] = KEY_HOME, + [0x01] = KEY_POWER, + [0x42] = KEY_MENU, + [0x02] = KEY_1, + [0x03] = KEY_2, + [0x04] = KEY_3, + [0x43] = KEY_SUBTITLE, + [0x05] = KEY_4, + [0x06] = KEY_5, + [0x07] = KEY_6, + [0x44] = KEY_TEXT, + [0x08] = KEY_7, + [0x09] = KEY_8, + [0x0a] = KEY_9, + [0x45] = KEY_DELETE, + [0x0b] = KEY_TUNER, + [0x0c] = KEY_0, + [0x0d] = KEY_MODE, + [0x46] = KEY_TV, + [0x47] = KEY_DVD, + [0x49] = KEY_VIDEO, + [0x4b] = KEY_AUX, + [0x10] = KEY_UP, + [0x11] = KEY_LEFT, + [0x12] = KEY_OK, + [0x13] = KEY_RIGHT, + [0x14] = KEY_DOWN, + [0x0f] = KEY_EPG, + [0x16] = KEY_INFO, + [0x4d] = KEY_BACKSPACE, + [0x1c] = KEY_VOLUMEUP, + [0x4c] = KEY_PLAY, + [0x1b] = KEY_CHANNELUP, + [0x1e] = KEY_VOLUMEDOWN, + [0x1d] = KEY_MUTE, + [0x1f] = KEY_CHANNELDOWN, + [0x17] = KEY_RED, + [0x18] = KEY_GREEN, + [0x19] = KEY_YELLOW, + [0x1a] = KEY_BLUE, + [0x58] = KEY_RECORD, + [0x48] = KEY_STOP, + [0x40] = KEY_PAUSE, + [0x54] = KEY_LAST, + [0x4e] = KEY_REWIND, + [0x4f] = KEY_FASTFORWARD, + [0x5c] = KEY_NEXT, +}; +EXPORT_SYMBOL_GPL(ir_codes_terratec_cinergy_xs); + /* EVGA inDtube Devin Heitmueller */ diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 795fd16a5..daa710b36 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -907,6 +907,8 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_TVP5150, .has_dvb = 1, .dvb_gpio = default_digital, + .ir_codes = ir_codes_terratec_cinergy_xs, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, diff --git a/linux/include/media/ir-common.h b/linux/include/media/ir-common.h index 9dcb632f6..922bad37d 100644 --- a/linux/include/media/ir-common.h +++ b/linux/include/media/ir-common.h @@ -163,6 +163,7 @@ extern IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_terratec_cinergy_xs[IR_KEYTAB_SIZE]; #endif -- cgit v1.2.3 From 33a9a00f41338f5ab7589a2611da979c87b884ce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Aug 2009 19:52:37 -0300 Subject: em28xx: fix V4L2 API compliance: don't expose audio inputs for devices without it From: Mauro Carvalho Chehab V4L2 API (chapter 1.5) states that: Drivers must implement all input ioctls when the device has one or more inputs, all output ioctls when the device has one or more outputs. When the device has any audio inputs or outputs the driver must set the V4L2_CAP_AUDIO flag in the struct v4l2_capability returned by the VIDIOC_QUERYCAP ioctl. So, devices without audio input should return -EINVAL. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index fcb99fb71..258cd38ce 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -976,6 +976,9 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; + if (!dev->audio_mode.has_audio) + return -EINVAL; + switch (a->index) { case EM28XX_AMUX_VIDEO: strcpy(a->name, "Television"); @@ -1022,6 +1025,9 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) return -EINVAL; #else + if (!dev->audio_mode.has_audio) + return -EINVAL; + if (a->index >= MAX_EM28XX_INPUT) return -EINVAL; if (0 == INPUT(a->index)->type) @@ -1444,9 +1450,11 @@ static int vidioc_querycap(struct file *file, void *priv, #endif V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + if (dev->audio_mode.has_audio) + cap->capabilities |= V4L2_CAP_AUDIO; + if (dev->tuner_type != TUNER_ABSENT) cap->capabilities |= V4L2_CAP_TUNER; -- cgit v1.2.3 From 3d106fc1f1a62d4ad61ba0ab78a9171508a97f16 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 9 Aug 2009 19:22:20 +0200 Subject: radio-si470x: separate common and usb code This patch is a preceding work to add the i2c interface of si470x. The si470x directory includes a common file and usb specific file and header file. The part unrelated with usb interface and i2c interface exists in radio-si470x-common.c file, and The usb specific part exists in radio-si470x-usb.c file. Signed-off-by: Joonyoung Shim Small changes, due to new include "linux/smp_lock.h". Acked-by: Tobias Lorenz --- linux/drivers/media/radio/Kconfig | 26 +- linux/drivers/media/radio/Makefile | 2 +- linux/drivers/media/radio/radio-si470x.c | 1870 -------------------- linux/drivers/media/radio/si470x/Kconfig | 24 + linux/drivers/media/radio/si470x/Makefile | 7 + .../media/radio/si470x/radio-si470x-common.c | 794 +++++++++ .../drivers/media/radio/si470x/radio-si470x-usb.c | 958 ++++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 202 +++ 8 files changed, 1989 insertions(+), 1892 deletions(-) delete mode 100644 linux/drivers/media/radio/radio-si470x.c create mode 100644 linux/drivers/media/radio/si470x/Kconfig create mode 100644 linux/drivers/media/radio/si470x/Makefile create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-common.c create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-usb.c create mode 100644 linux/drivers/media/radio/si470x/radio-si470x.h --- linux/drivers/media/radio/Kconfig | 26 +- linux/drivers/media/radio/Makefile | 2 +- linux/drivers/media/radio/radio-si470x.c | 1870 -------------------- linux/drivers/media/radio/si470x/Kconfig | 24 + linux/drivers/media/radio/si470x/Makefile | 7 + .../media/radio/si470x/radio-si470x-common.c | 794 +++++++++ .../drivers/media/radio/si470x/radio-si470x-usb.c | 958 ++++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 202 +++ 8 files changed, 1990 insertions(+), 1893 deletions(-) delete mode 100644 linux/drivers/media/radio/radio-si470x.c create mode 100644 linux/drivers/media/radio/si470x/Kconfig create mode 100644 linux/drivers/media/radio/si470x/Makefile create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-common.c create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-usb.c create mode 100644 linux/drivers/media/radio/si470x/radio-si470x.h diff --git a/linux/drivers/media/radio/Kconfig b/linux/drivers/media/radio/Kconfig index 3315cac87..41bbec6df 100644 --- a/linux/drivers/media/radio/Kconfig +++ b/linux/drivers/media/radio/Kconfig @@ -351,29 +351,11 @@ config USB_DSBR To compile this driver as a module, choose M here: the module will be called dsbr100. -config USB_SI470X - tristate "Silicon Labs Si470x FM Radio Receiver support" - depends on USB && VIDEO_V4L2 - ---help--- - This is a driver for USB devices with the Silicon Labs SI470x - chip. Currently these devices are known to work: - - 10c4:818a: Silicon Labs USB FM Radio Reference Design - - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) - - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700) - - Sound is provided by the ALSA USB Audio/MIDI driver. Therefore - if you don't want to use the device solely for RDS receiving, - it is recommended to also select SND_USB_AUDIO. - - Please have a look at the documentation, especially on how - to redirect the audio stream from the radio to your sound device: - Documentation/video4linux/si470x.txt - - Say Y here if you want to connect this type of radio to your - computer's USB port. +config RADIO_SI470X + bool "Silicon Labs Si470x FM Radio Receiver support" + depends on VIDEO_V4L2 - To compile this driver as a module, choose M here: the - module will be called radio-si470x. +source "drivers/media/radio/si470x/Kconfig" config USB_MR800 tristate "AverMedia MR 800 USB FM radio support" diff --git a/linux/drivers/media/radio/Makefile b/linux/drivers/media/radio/Makefile index 0f2b35b3e..18111e1fe 100644 --- a/linux/drivers/media/radio/Makefile +++ b/linux/drivers/media/radio/Makefile @@ -17,7 +17,7 @@ obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o obj-$(CONFIG_USB_DSBR) += dsbr100.o -obj-$(CONFIG_USB_SI470X) += radio-si470x.o +obj-$(CONFIG_RADIO_SI470X) += si470x/ obj-$(CONFIG_USB_MR800) += radio-mr800.o obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c deleted file mode 100644 index 5b4cab3d0..000000000 --- a/linux/drivers/media/radio/radio-si470x.c +++ /dev/null @@ -1,1870 +0,0 @@ -/* - * drivers/media/radio/radio-si470x.c - * - * Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers: - * - Silicon Labs USB FM Radio Reference Design - * - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) - * - KWorld USB FM Radio SnapMusic Mobile 700 (FM700) - * - Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) - * - * Copyright (c) 2009 Tobias Lorenz - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -/* - * History: - * 2008-01-12 Tobias Lorenz - * Version 1.0.0 - * - First working version - * 2008-01-13 Tobias Lorenz - * Version 1.0.1 - * - Improved error handling, every function now returns errno - * - Improved multi user access (start/mute/stop) - * - Channel doesn't get lost anymore after start/mute/stop - * - RDS support added (polling mode via interrupt EP 1) - * - marked default module parameters with *value* - * - switched from bit structs to bit masks - * - header file cleaned and integrated - * 2008-01-14 Tobias Lorenz - * Version 1.0.2 - * - hex values are now lower case - * - commented USB ID for ADS/Tech moved on todo list - * - blacklisted si470x in hid-quirks.c - * - rds buffer handling functions integrated into *_work, *_read - * - rds_command in si470x_poll exchanged against simple retval - * - check for firmware version 15 - * - code order and prototypes still remain the same - * - spacing and bottom of band codes remain the same - * 2008-01-16 Tobias Lorenz - * Version 1.0.3 - * - code reordered to avoid function prototypes - * - switch/case defaults are now more user-friendly - * - unified comment style - * - applied all checkpatch.pl v1.12 suggestions - * except the warning about the too long lines with bit comments - * - renamed FMRADIO to RADIO to cut line length (checkpatch.pl) - * 2008-01-22 Tobias Lorenz - * Version 1.0.4 - * - avoid poss. locking when doing copy_to_user which may sleep - * - RDS is automatically activated on read now - * - code cleaned of unnecessary rds_commands - * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified - * (thanks to Guillaume RAMOUSSE) - * 2008-01-27 Tobias Lorenz - * Version 1.0.5 - * - number of seek_retries changed to tune_timeout - * - fixed problem with incomplete tune operations by own buffers - * - optimization of variables and printf types - * - improved error logging - * 2008-01-31 Tobias Lorenz - * Oliver Neukum - * Version 1.0.6 - * - fixed coverity checker warnings in *_usb_driver_disconnect - * - probe()/open() race by correct ordering in probe() - * - DMA coherency rules by separate allocation of all buffers - * - use of endianness macros - * - abuse of spinlock, replaced by mutex - * - racy handling of timer in disconnect, - * replaced by delayed_work - * - racy interruptible_sleep_on(), - * replaced with wait_event_interruptible() - * - handle signals in read() - * 2008-02-08 Tobias Lorenz - * Oliver Neukum - * Version 1.0.7 - * - usb autosuspend support - * - unplugging fixed - * 2008-05-07 Tobias Lorenz - * Version 1.0.8 - * - hardware frequency seek support - * - afc indication - * - more safety checks, let si470x_get_freq return errno - * - vidioc behavior corrected according to v4l2 spec - * 2008-10-20 Alexey Klimov - * - add support for KWorld USB FM Radio FM700 - * - blacklisted KWorld radio in hid-core.c and hid-ids.h - * 2008-12-03 Mark Lord - * - add support for DealExtreme USB Radio - * 2009-01-31 Bob Ross - * - correction of stereo detection/setting - * - correction of signal strength indicator scaling - * 2009-01-31 Rick Bronson - * Tobias Lorenz - * - add LED status output - * - get HW/SW version from scratchpad - * 2009-06-16 Edouard Lafargue - * Version 1.0.10 - * - add support for interrupt mode for RDS endpoint, - * instead of polling. - * Improves RDS reception significantly - * - * ToDo: - * - add firmware download/update support - */ - - -/* driver definitions */ -#define DRIVER_AUTHOR "Tobias Lorenz " -#define DRIVER_NAME "radio-si470x" -#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 10) -#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" -#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" -#define DRIVER_VERSION "1.0.10" - - -/* kernel includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "compat.h" -#include -#include -#include -#include -#include -#include - - -/* USB Device ID List */ -static struct usb_device_id si470x_usb_driver_id_table[] = { - /* Silicon Labs USB FM Radio Reference Design */ - { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) }, - /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */ - { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, - /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */ - { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) }, - /* Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) */ - { USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) }, - /* Terminating entry */ - { } -}; -MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table); - - - -/************************************************************************** - * Module Parameters - **************************************************************************/ - -/* Radio Nr */ -static int radio_nr = -1; -module_param(radio_nr, int, 0444); -MODULE_PARM_DESC(radio_nr, "Radio Nr"); - -/* Spacing (kHz) */ -/* 0: 200 kHz (USA, Australia) */ -/* 1: 100 kHz (Europe, Japan) */ -/* 2: 50 kHz */ -static unsigned short space = 2; -module_param(space, ushort, 0444); -MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); - -/* Bottom of Band (MHz) */ -/* 0: 87.5 - 108 MHz (USA, Europe)*/ -/* 1: 76 - 108 MHz (Japan wide band) */ -/* 2: 76 - 90 MHz (Japan) */ -static unsigned short band = 1; -module_param(band, ushort, 0444); -MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); - -/* De-emphasis */ -/* 0: 75 us (USA) */ -/* 1: 50 us (Europe, Australia, Japan) */ -static unsigned short de = 1; -module_param(de, ushort, 0444); -MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*"); - -/* USB timeout */ -static unsigned int usb_timeout = 500; -module_param(usb_timeout, uint, 0644); -MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*"); - -/* Tune timeout */ -static unsigned int tune_timeout = 3000; -module_param(tune_timeout, uint, 0644); -MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*"); - -/* Seek timeout */ -static unsigned int seek_timeout = 5000; -module_param(seek_timeout, uint, 0644); -MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*"); - -/* RDS buffer blocks */ -static unsigned int rds_buf = 100; -module_param(rds_buf, uint, 0444); -MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*"); - -/* RDS maximum block errors */ -static unsigned short max_rds_errors = 1; -/* 0 means 0 errors requiring correction */ -/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */ -/* 2 means 3-5 errors requiring correction */ -/* 3 means 6+ errors or errors in checkword, correction not possible */ -module_param(max_rds_errors, ushort, 0644); -MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); - - -/************************************************************************** - * Register Definitions - **************************************************************************/ -#define RADIO_REGISTER_SIZE 2 /* 16 register bit width */ -#define RADIO_REGISTER_NUM 16 /* DEVICEID ... RDSD */ -#define RDS_REGISTER_NUM 6 /* STATUSRSSI ... RDSD */ - -#define DEVICEID 0 /* Device ID */ -#define DEVICEID_PN 0xf000 /* bits 15..12: Part Number */ -#define DEVICEID_MFGID 0x0fff /* bits 11..00: Manufacturer ID */ - -#define CHIPID 1 /* Chip ID */ -#define CHIPID_REV 0xfc00 /* bits 15..10: Chip Version */ -#define CHIPID_DEV 0x0200 /* bits 09..09: Device */ -#define CHIPID_FIRMWARE 0x01ff /* bits 08..00: Firmware Version */ - -#define POWERCFG 2 /* Power Configuration */ -#define POWERCFG_DSMUTE 0x8000 /* bits 15..15: Softmute Disable */ -#define POWERCFG_DMUTE 0x4000 /* bits 14..14: Mute Disable */ -#define POWERCFG_MONO 0x2000 /* bits 13..13: Mono Select */ -#define POWERCFG_RDSM 0x0800 /* bits 11..11: RDS Mode (Si4701 only) */ -#define POWERCFG_SKMODE 0x0400 /* bits 10..10: Seek Mode */ -#define POWERCFG_SEEKUP 0x0200 /* bits 09..09: Seek Direction */ -#define POWERCFG_SEEK 0x0100 /* bits 08..08: Seek */ -#define POWERCFG_DISABLE 0x0040 /* bits 06..06: Powerup Disable */ -#define POWERCFG_ENABLE 0x0001 /* bits 00..00: Powerup Enable */ - -#define CHANNEL 3 /* Channel */ -#define CHANNEL_TUNE 0x8000 /* bits 15..15: Tune */ -#define CHANNEL_CHAN 0x03ff /* bits 09..00: Channel Select */ - -#define SYSCONFIG1 4 /* System Configuration 1 */ -#define SYSCONFIG1_RDSIEN 0x8000 /* bits 15..15: RDS Interrupt Enable (Si4701 only) */ -#define SYSCONFIG1_STCIEN 0x4000 /* bits 14..14: Seek/Tune Complete Interrupt Enable */ -#define SYSCONFIG1_RDS 0x1000 /* bits 12..12: RDS Enable (Si4701 only) */ -#define SYSCONFIG1_DE 0x0800 /* bits 11..11: De-emphasis (0=75us 1=50us) */ -#define SYSCONFIG1_AGCD 0x0400 /* bits 10..10: AGC Disable */ -#define SYSCONFIG1_BLNDADJ 0x00c0 /* bits 07..06: Stereo/Mono Blend Level Adjustment */ -#define SYSCONFIG1_GPIO3 0x0030 /* bits 05..04: General Purpose I/O 3 */ -#define SYSCONFIG1_GPIO2 0x000c /* bits 03..02: General Purpose I/O 2 */ -#define SYSCONFIG1_GPIO1 0x0003 /* bits 01..00: General Purpose I/O 1 */ - -#define SYSCONFIG2 5 /* System Configuration 2 */ -#define SYSCONFIG2_SEEKTH 0xff00 /* bits 15..08: RSSI Seek Threshold */ -#define SYSCONFIG2_BAND 0x0080 /* bits 07..06: Band Select */ -#define SYSCONFIG2_SPACE 0x0030 /* bits 05..04: Channel Spacing */ -#define SYSCONFIG2_VOLUME 0x000f /* bits 03..00: Volume */ - -#define SYSCONFIG3 6 /* System Configuration 3 */ -#define SYSCONFIG3_SMUTER 0xc000 /* bits 15..14: Softmute Attack/Recover Rate */ -#define SYSCONFIG3_SMUTEA 0x3000 /* bits 13..12: Softmute Attenuation */ -#define SYSCONFIG3_SKSNR 0x00f0 /* bits 07..04: Seek SNR Threshold */ -#define SYSCONFIG3_SKCNT 0x000f /* bits 03..00: Seek FM Impulse Detection Threshold */ - -#define TEST1 7 /* Test 1 */ -#define TEST1_AHIZEN 0x4000 /* bits 14..14: Audio High-Z Enable */ - -#define TEST2 8 /* Test 2 */ -/* TEST2 only contains reserved bits */ - -#define BOOTCONFIG 9 /* Boot Configuration */ -/* BOOTCONFIG only contains reserved bits */ - -#define STATUSRSSI 10 /* Status RSSI */ -#define STATUSRSSI_RDSR 0x8000 /* bits 15..15: RDS Ready (Si4701 only) */ -#define STATUSRSSI_STC 0x4000 /* bits 14..14: Seek/Tune Complete */ -#define STATUSRSSI_SF 0x2000 /* bits 13..13: Seek Fail/Band Limit */ -#define STATUSRSSI_AFCRL 0x1000 /* bits 12..12: AFC Rail */ -#define STATUSRSSI_RDSS 0x0800 /* bits 11..11: RDS Synchronized (Si4701 only) */ -#define STATUSRSSI_BLERA 0x0600 /* bits 10..09: RDS Block A Errors (Si4701 only) */ -#define STATUSRSSI_ST 0x0100 /* bits 08..08: Stereo Indicator */ -#define STATUSRSSI_RSSI 0x00ff /* bits 07..00: RSSI (Received Signal Strength Indicator) */ - -#define READCHAN 11 /* Read Channel */ -#define READCHAN_BLERB 0xc000 /* bits 15..14: RDS Block D Errors (Si4701 only) */ -#define READCHAN_BLERC 0x3000 /* bits 13..12: RDS Block C Errors (Si4701 only) */ -#define READCHAN_BLERD 0x0c00 /* bits 11..10: RDS Block B Errors (Si4701 only) */ -#define READCHAN_READCHAN 0x03ff /* bits 09..00: Read Channel */ - -#define RDSA 12 /* RDSA */ -#define RDSA_RDSA 0xffff /* bits 15..00: RDS Block A Data (Si4701 only) */ - -#define RDSB 13 /* RDSB */ -#define RDSB_RDSB 0xffff /* bits 15..00: RDS Block B Data (Si4701 only) */ - -#define RDSC 14 /* RDSC */ -#define RDSC_RDSC 0xffff /* bits 15..00: RDS Block C Data (Si4701 only) */ - -#define RDSD 15 /* RDSD */ -#define RDSD_RDSD 0xffff /* bits 15..00: RDS Block D Data (Si4701 only) */ - - - -/************************************************************************** - * USB HID Reports - **************************************************************************/ - -/* Reports 1-16 give direct read/write access to the 16 Si470x registers */ -/* with the (REPORT_ID - 1) corresponding to the register address across USB */ -/* endpoint 0 using GET_REPORT and SET_REPORT */ -#define REGISTER_REPORT_SIZE (RADIO_REGISTER_SIZE + 1) -#define REGISTER_REPORT(reg) ((reg) + 1) - -/* Report 17 gives direct read/write access to the entire Si470x register */ -/* map across endpoint 0 using GET_REPORT and SET_REPORT */ -#define ENTIRE_REPORT_SIZE (RADIO_REGISTER_NUM * RADIO_REGISTER_SIZE + 1) -#define ENTIRE_REPORT 17 - -/* Report 18 is used to send the lowest 6 Si470x registers up the HID */ -/* interrupt endpoint 1 to Windows every 20 milliseconds for status */ -#define RDS_REPORT_SIZE (RDS_REGISTER_NUM * RADIO_REGISTER_SIZE + 1) -#define RDS_REPORT 18 - -/* Report 19: LED state */ -#define LED_REPORT_SIZE 3 -#define LED_REPORT 19 - -/* Report 19: stream */ -#define STREAM_REPORT_SIZE 3 -#define STREAM_REPORT 19 - -/* Report 20: scratch */ -#define SCRATCH_PAGE_SIZE 63 -#define SCRATCH_REPORT_SIZE (SCRATCH_PAGE_SIZE + 1) -#define SCRATCH_REPORT 20 - -/* Reports 19-22: flash upgrade of the C8051F321 */ -#define WRITE_REPORT_SIZE 4 -#define WRITE_REPORT 19 -#define FLASH_REPORT_SIZE 64 -#define FLASH_REPORT 20 -#define CRC_REPORT_SIZE 3 -#define CRC_REPORT 21 -#define RESPONSE_REPORT_SIZE 2 -#define RESPONSE_REPORT 22 - -/* Report 23: currently unused, but can accept 60 byte reports on the HID */ -/* interrupt out endpoint 2 every 1 millisecond */ -#define UNUSED_REPORT 23 - - - -/************************************************************************** - * Software/Hardware Versions - **************************************************************************/ -#define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6 -#define RADIO_SW_VERSION 7 -#define RADIO_SW_VERSION_CURRENT 15 -#define RADIO_HW_VERSION 1 - -#define SCRATCH_PAGE_SW_VERSION 1 -#define SCRATCH_PAGE_HW_VERSION 2 - - - -/************************************************************************** - * LED State Definitions - **************************************************************************/ -#define LED_COMMAND 0x35 - -#define NO_CHANGE_LED 0x00 -#define ALL_COLOR_LED 0x01 /* streaming state */ -#define BLINK_GREEN_LED 0x02 /* connect state */ -#define BLINK_RED_LED 0x04 -#define BLINK_ORANGE_LED 0x10 /* disconnect state */ -#define SOLID_GREEN_LED 0x20 /* tuning/seeking state */ -#define SOLID_RED_LED 0x40 /* bootload state */ -#define SOLID_ORANGE_LED 0x80 - - - -/************************************************************************** - * Stream State Definitions - **************************************************************************/ -#define STREAM_COMMAND 0x36 -#define STREAM_VIDPID 0x00 -#define STREAM_AUDIO 0xff - - - -/************************************************************************** - * Bootloader / Flash Commands - **************************************************************************/ - -/* unique id sent to bootloader and required to put into a bootload state */ -#define UNIQUE_BL_ID 0x34 - -/* mask for the flash data */ -#define FLASH_DATA_MASK 0x55 - -/* bootloader commands */ -#define GET_SW_VERSION_COMMAND 0x00 -#define SET_PAGE_COMMAND 0x01 -#define ERASE_PAGE_COMMAND 0x02 -#define WRITE_PAGE_COMMAND 0x03 -#define CRC_ON_PAGE_COMMAND 0x04 -#define READ_FLASH_BYTE_COMMAND 0x05 -#define RESET_DEVICE_COMMAND 0x06 -#define GET_HW_VERSION_COMMAND 0x07 -#define BLANK 0xff - -/* bootloader command responses */ -#define COMMAND_OK 0x01 -#define COMMAND_FAILED 0x02 -#define COMMAND_PENDING 0x03 - - - -/************************************************************************** - * General Driver Definitions - **************************************************************************/ - -/* - * si470x_device - private data - */ -struct si470x_device { - /* reference to USB and video device */ - struct usb_device *usbdev; - struct usb_interface *intf; - struct video_device *videodev; - - /* Interrupt endpoint handling */ - char *int_in_buffer; - struct usb_endpoint_descriptor *int_in_endpoint; - struct urb *int_in_urb; - int int_in_running; - - /* driver management */ - unsigned int users; - unsigned char disconnected; - struct mutex disconnect_lock; - - /* Silabs internal registers (0..15) */ - unsigned short registers[RADIO_REGISTER_NUM]; - - /* RDS receive buffer */ - wait_queue_head_t read_queue; - struct mutex lock; /* buffer locking */ - unsigned char *buffer; /* size is always multiple of three */ - unsigned int buf_size; - unsigned int rd_index; - unsigned int wr_index; - - /* scratch page */ - unsigned char software_version; - unsigned char hardware_version; -}; - - -/* - * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, - * 62.5 kHz otherwise. - * The tuner is able to have a channel spacing of 50, 100 or 200 kHz. - * tuner->capability is therefore set to V4L2_TUNER_CAP_LOW - * The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000 - */ -#define FREQ_MUL (1000000 / 62.5) - - - -/************************************************************************** - * General Driver Functions - REGISTER_REPORTs - **************************************************************************/ - -/* - * si470x_get_report - receive a HID report - */ -static int si470x_get_report(struct si470x_device *radio, void *buf, int size) -{ - unsigned char *report = (unsigned char *) buf; - int retval; - - retval = usb_control_msg(radio->usbdev, - usb_rcvctrlpipe(radio->usbdev, 0), - HID_REQ_GET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - report[0], 2, - buf, size, usb_timeout); - - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": si470x_get_report: usb_control_msg returned %d\n", - retval); - return retval; -} - - -/* - * si470x_set_report - send a HID report - */ -static int si470x_set_report(struct si470x_device *radio, void *buf, int size) -{ - unsigned char *report = (unsigned char *) buf; - int retval; - - retval = usb_control_msg(radio->usbdev, - usb_sndctrlpipe(radio->usbdev, 0), - HID_REQ_SET_REPORT, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, - report[0], 2, - buf, size, usb_timeout); - - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": si470x_set_report: usb_control_msg returned %d\n", - retval); - return retval; -} - - -/* - * si470x_get_register - read register - */ -static int si470x_get_register(struct si470x_device *radio, int regnr) -{ - unsigned char buf[REGISTER_REPORT_SIZE]; - int retval; - - buf[0] = REGISTER_REPORT(regnr); - - retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); - - if (retval >= 0) - radio->registers[regnr] = get_unaligned_be16(&buf[1]); - - return (retval < 0) ? -EINVAL : 0; -} - - -/* - * si470x_set_register - write register - */ -static int si470x_set_register(struct si470x_device *radio, int regnr) -{ - unsigned char buf[REGISTER_REPORT_SIZE]; - int retval; - - buf[0] = REGISTER_REPORT(regnr); - put_unaligned_be16(radio->registers[regnr], &buf[1]); - - retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); - - return (retval < 0) ? -EINVAL : 0; -} - - -/* - * si470x_set_chan - set the channel - */ -static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) -{ - int retval; - unsigned long timeout; - bool timed_out = 0; - - /* start tuning */ - radio->registers[CHANNEL] &= ~CHANNEL_CHAN; - radio->registers[CHANNEL] |= CHANNEL_TUNE | chan; - retval = si470x_set_register(radio, CHANNEL); - if (retval < 0) - goto done; - - /* wait till tune operation has completed */ - timeout = jiffies + msecs_to_jiffies(tune_timeout); - do { - retval = si470x_get_register(radio, STATUSRSSI); - if (retval < 0) - goto stop; - timed_out = time_after(jiffies, timeout); - } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && - (!timed_out)); - if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) - printk(KERN_WARNING DRIVER_NAME ": tune does not complete\n"); - if (timed_out) - printk(KERN_WARNING DRIVER_NAME - ": tune timed out after %u ms\n", tune_timeout); - -stop: - /* stop tuning */ - radio->registers[CHANNEL] &= ~CHANNEL_TUNE; - retval = si470x_set_register(radio, CHANNEL); - -done: - return retval; -} - - -/* - * si470x_get_freq - get the frequency - */ -static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq) -{ - unsigned int spacing, band_bottom; - unsigned short chan; - int retval; - - /* Spacing (kHz) */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { - /* 0: 200 kHz (USA, Australia) */ - case 0: - spacing = 0.200 * FREQ_MUL; break; - /* 1: 100 kHz (Europe, Japan) */ - case 1: - spacing = 0.100 * FREQ_MUL; break; - /* 2: 50 kHz */ - default: - spacing = 0.050 * FREQ_MUL; break; - }; - - /* Bottom of Band (MHz) */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { - /* 0: 87.5 - 108 MHz (USA, Europe) */ - case 0: - band_bottom = 87.5 * FREQ_MUL; break; - /* 1: 76 - 108 MHz (Japan wide band) */ - default: - band_bottom = 76 * FREQ_MUL; break; - /* 2: 76 - 90 MHz (Japan) */ - case 2: - band_bottom = 76 * FREQ_MUL; break; - }; - - /* read channel */ - retval = si470x_get_register(radio, READCHAN); - chan = radio->registers[READCHAN] & READCHAN_READCHAN; - - /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */ - *freq = chan * spacing + band_bottom; - - return retval; -} - - -/* - * si470x_set_freq - set the frequency - */ -static int si470x_set_freq(struct si470x_device *radio, unsigned int freq) -{ - unsigned int spacing, band_bottom; - unsigned short chan; - - /* Spacing (kHz) */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { - /* 0: 200 kHz (USA, Australia) */ - case 0: - spacing = 0.200 * FREQ_MUL; break; - /* 1: 100 kHz (Europe, Japan) */ - case 1: - spacing = 0.100 * FREQ_MUL; break; - /* 2: 50 kHz */ - default: - spacing = 0.050 * FREQ_MUL; break; - }; - - /* Bottom of Band (MHz) */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { - /* 0: 87.5 - 108 MHz (USA, Europe) */ - case 0: - band_bottom = 87.5 * FREQ_MUL; break; - /* 1: 76 - 108 MHz (Japan wide band) */ - default: - band_bottom = 76 * FREQ_MUL; break; - /* 2: 76 - 90 MHz (Japan) */ - case 2: - band_bottom = 76 * FREQ_MUL; break; - }; - - /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */ - chan = (freq - band_bottom) / spacing; - - return si470x_set_chan(radio, chan); -} - - -/* - * si470x_set_seek - set seek - */ -static int si470x_set_seek(struct si470x_device *radio, - unsigned int wrap_around, unsigned int seek_upward) -{ - int retval = 0; - unsigned long timeout; - bool timed_out = 0; - - /* start seeking */ - radio->registers[POWERCFG] |= POWERCFG_SEEK; - if (wrap_around == 1) - radio->registers[POWERCFG] &= ~POWERCFG_SKMODE; - else - radio->registers[POWERCFG] |= POWERCFG_SKMODE; - if (seek_upward == 1) - radio->registers[POWERCFG] |= POWERCFG_SEEKUP; - else - radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP; - retval = si470x_set_register(radio, POWERCFG); - if (retval < 0) - goto done; - - /* wait till seek operation has completed */ - timeout = jiffies + msecs_to_jiffies(seek_timeout); - do { - retval = si470x_get_register(radio, STATUSRSSI); - if (retval < 0) - goto stop; - timed_out = time_after(jiffies, timeout); - } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && - (!timed_out)); - if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) - printk(KERN_WARNING DRIVER_NAME ": seek does not complete\n"); - if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) - printk(KERN_WARNING DRIVER_NAME - ": seek failed / band limit reached\n"); - if (timed_out) - printk(KERN_WARNING DRIVER_NAME - ": seek timed out after %u ms\n", seek_timeout); - -stop: - /* stop seeking */ - radio->registers[POWERCFG] &= ~POWERCFG_SEEK; - retval = si470x_set_register(radio, POWERCFG); - -done: - /* try again, if timed out */ - if ((retval == 0) && timed_out) - retval = -EAGAIN; - - return retval; -} - - -/* - * si470x_start - switch on radio - */ -static int si470x_start(struct si470x_device *radio) -{ - int retval; - - /* powercfg */ - radio->registers[POWERCFG] = - POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM; - retval = si470x_set_register(radio, POWERCFG); - if (retval < 0) - goto done; - - /* sysconfig 1 */ - radio->registers[SYSCONFIG1] = SYSCONFIG1_DE; - retval = si470x_set_register(radio, SYSCONFIG1); - if (retval < 0) - goto done; - - /* sysconfig 2 */ - radio->registers[SYSCONFIG2] = - (0x3f << 8) | /* SEEKTH */ - ((band << 6) & SYSCONFIG2_BAND) | /* BAND */ - ((space << 4) & SYSCONFIG2_SPACE) | /* SPACE */ - 15; /* VOLUME (max) */ - retval = si470x_set_register(radio, SYSCONFIG2); - if (retval < 0) - goto done; - - /* reset last channel */ - retval = si470x_set_chan(radio, - radio->registers[CHANNEL] & CHANNEL_CHAN); - -done: - return retval; -} - - -/* - * si470x_stop - switch off radio - */ -static int si470x_stop(struct si470x_device *radio) -{ - int retval; - - /* sysconfig 1 */ - radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; - retval = si470x_set_register(radio, SYSCONFIG1); - if (retval < 0) - goto done; - - /* powercfg */ - radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; - /* POWERCFG_ENABLE has to automatically go low */ - radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE; - retval = si470x_set_register(radio, POWERCFG); - -done: - return retval; -} - - -/* - * si470x_rds_on - switch on rds reception - */ -static int si470x_rds_on(struct si470x_device *radio) -{ - int retval; - - /* sysconfig 1 */ - mutex_lock(&radio->lock); - radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS; - retval = si470x_set_register(radio, SYSCONFIG1); - if (retval < 0) - radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; - mutex_unlock(&radio->lock); - - return retval; -} - - - -/************************************************************************** - * General Driver Functions - ENTIRE_REPORT - **************************************************************************/ - -/* - * si470x_get_all_registers - read entire registers - */ -static int si470x_get_all_registers(struct si470x_device *radio) -{ - unsigned char buf[ENTIRE_REPORT_SIZE]; - int retval; - unsigned char regnr; - - buf[0] = ENTIRE_REPORT; - - retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); - - if (retval >= 0) - for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) - radio->registers[regnr] = get_unaligned_be16( - &buf[regnr * RADIO_REGISTER_SIZE + 1]); - - return (retval < 0) ? -EINVAL : 0; -} - - - -/************************************************************************** - * General Driver Functions - LED_REPORT - **************************************************************************/ - -/* - * si470x_set_led_state - sets the led state - */ -static int si470x_set_led_state(struct si470x_device *radio, - unsigned char led_state) -{ - unsigned char buf[LED_REPORT_SIZE]; - int retval; - - buf[0] = LED_REPORT; - buf[1] = LED_COMMAND; - buf[2] = led_state; - - retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); - - return (retval < 0) ? -EINVAL : 0; -} - - - -/************************************************************************** - * General Driver Functions - SCRATCH_REPORT - **************************************************************************/ - -/* - * si470x_get_scratch_versions - gets the scratch page and version infos - */ -static int si470x_get_scratch_page_versions(struct si470x_device *radio) -{ - unsigned char buf[SCRATCH_REPORT_SIZE]; - int retval; - - buf[0] = SCRATCH_REPORT; - - retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); - - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME ": si470x_get_scratch: " - "si470x_get_report returned %d\n", retval); - else { - radio->software_version = buf[1]; - radio->hardware_version = buf[2]; - } - - return (retval < 0) ? -EINVAL : 0; -} - - - -/************************************************************************** - * RDS Driver Functions - **************************************************************************/ - -/* - * si470x_int_in_callback - rds callback and processing function - * - * TODO: do we need to use mutex locks in some sections? - */ -static void si470x_int_in_callback(struct urb *urb) -{ - struct si470x_device *radio = urb->context; - unsigned char buf[RDS_REPORT_SIZE]; - int retval; - unsigned char regnr; - unsigned char blocknum; - unsigned short bler; /* rds block errors */ - unsigned short rds; - unsigned char tmpbuf[3]; - - if (urb->status) { - if (urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN) { - return; - } else { - printk(KERN_WARNING DRIVER_NAME - ": non-zero urb status (%d)\n", urb->status); - goto resubmit; /* Maybe we can recover. */ - } - } - - /* safety checks */ - if (radio->disconnected) - return; - if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) - goto resubmit; - - if (urb->actual_length > 0) { - /* Update RDS registers with URB data */ - buf[0] = RDS_REPORT; - for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) - radio->registers[STATUSRSSI + regnr] = - get_unaligned_be16(&radio->int_in_buffer[ - regnr * RADIO_REGISTER_SIZE + 1]); - /* get rds blocks */ - if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) { - /* No RDS group ready, better luck next time */ - goto resubmit; - } - if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSS) == 0) { - /* RDS decoder not synchronized */ - goto resubmit; - } - for (blocknum = 0; blocknum < 4; blocknum++) { - switch (blocknum) { - default: - bler = (radio->registers[STATUSRSSI] & - STATUSRSSI_BLERA) >> 9; - rds = radio->registers[RDSA]; - break; - case 1: - bler = (radio->registers[READCHAN] & - READCHAN_BLERB) >> 14; - rds = radio->registers[RDSB]; - break; - case 2: - bler = (radio->registers[READCHAN] & - READCHAN_BLERC) >> 12; - rds = radio->registers[RDSC]; - break; - case 3: - bler = (radio->registers[READCHAN] & - READCHAN_BLERD) >> 10; - rds = radio->registers[RDSD]; - break; - }; - - /* Fill the V4L2 RDS buffer */ - put_unaligned_le16(rds, &tmpbuf); - tmpbuf[2] = blocknum; /* offset name */ - tmpbuf[2] |= blocknum << 3; /* received offset */ - if (bler > max_rds_errors) - tmpbuf[2] |= 0x80; /* uncorrectable errors */ - else if (bler > 0) - tmpbuf[2] |= 0x40; /* corrected error(s) */ - - /* copy RDS block to internal buffer */ - memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3); - radio->wr_index += 3; - - /* wrap write pointer */ - if (radio->wr_index >= radio->buf_size) - radio->wr_index = 0; - - /* check for overflow */ - if (radio->wr_index == radio->rd_index) { - /* increment and wrap read pointer */ - radio->rd_index += 3; - if (radio->rd_index >= radio->buf_size) - radio->rd_index = 0; - } - } - if (radio->wr_index != radio->rd_index) - wake_up_interruptible(&radio->read_queue); - } - -resubmit: - /* Resubmit if we're still running. */ - if (radio->int_in_running && radio->usbdev) { - retval = usb_submit_urb(radio->int_in_urb, GFP_ATOMIC); - if (retval) { - printk(KERN_WARNING DRIVER_NAME - ": resubmitting urb failed (%d)", retval); - radio->int_in_running = 0; - } - } -} - - - -/************************************************************************** - * File Operations Interface - **************************************************************************/ - -/* - * si470x_fops_read - read RDS data - */ -static ssize_t si470x_fops_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - unsigned int block_count = 0; - - /* switch on rds reception */ - if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { - si470x_rds_on(radio); - } - - /* block if no new data available */ - while (radio->wr_index == radio->rd_index) { - if (file->f_flags & O_NONBLOCK) { - retval = -EWOULDBLOCK; - goto done; - } - if (wait_event_interruptible(radio->read_queue, - radio->wr_index != radio->rd_index) < 0) { - retval = -EINTR; - goto done; - } - } - - /* calculate block count from byte count */ - count /= 3; - - /* copy RDS block out of internal buffer and to user buffer */ - mutex_lock(&radio->lock); - while (block_count < count) { - if (radio->rd_index == radio->wr_index) - break; - - /* always transfer rds complete blocks */ - if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3)) - /* retval = -EFAULT; */ - break; - - /* increment and wrap read pointer */ - radio->rd_index += 3; - if (radio->rd_index >= radio->buf_size) - radio->rd_index = 0; - - /* increment counters */ - block_count++; - buf += 3; - retval += 3; - } - mutex_unlock(&radio->lock); - -done: - return retval; -} - - -/* - * si470x_fops_poll - poll RDS data - */ -static unsigned int si470x_fops_poll(struct file *file, - struct poll_table_struct *pts) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* switch on rds reception */ - if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { - si470x_rds_on(radio); - } - - poll_wait(file, &radio->read_queue, pts); - - if (radio->rd_index != radio->wr_index) - retval = POLLIN | POLLRDNORM; - - return retval; -} - - -/* - * si470x_fops_open - file open - */ -static int si470x_fops_open(struct file *file) -{ - struct si470x_device *radio = video_drvdata(file); - int retval; - - lock_kernel(); - radio->users++; - - retval = usb_autopm_get_interface(radio->intf); - if (retval < 0) { - radio->users--; - retval = -EIO; - goto done; - } - - if (radio->users == 1) { - /* start radio */ - retval = si470x_start(radio); - if (retval < 0) { - usb_autopm_put_interface(radio->intf); - goto done; - } - - /* initialize interrupt urb */ - usb_fill_int_urb(radio->int_in_urb, radio->usbdev, - usb_rcvintpipe(radio->usbdev, - radio->int_in_endpoint->bEndpointAddress), - radio->int_in_buffer, - le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize), - si470x_int_in_callback, - radio, - radio->int_in_endpoint->bInterval); - - radio->int_in_running = 1; - mb(); - - retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL); - if (retval) { - printk(KERN_INFO DRIVER_NAME - ": submitting int urb failed (%d)\n", retval); - radio->int_in_running = 0; - usb_autopm_put_interface(radio->intf); - } - } - -done: - unlock_kernel(); - return retval; -} - - -/* - * si470x_fops_release - file release - */ -static int si470x_fops_release(struct file *file) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety check */ - if (!radio) { - retval = -ENODEV; - goto done; - } - - mutex_lock(&radio->disconnect_lock); - radio->users--; - if (radio->users == 0) { - /* shutdown interrupt handler */ - if (radio->int_in_running) { - radio->int_in_running = 0; - if (radio->int_in_urb) - usb_kill_urb(radio->int_in_urb); - } - - if (radio->disconnected) { - video_unregister_device(radio->videodev); - kfree(radio->int_in_buffer); - kfree(radio->buffer); - kfree(radio); - goto unlock; - } - - /* cancel read processes */ - wake_up_interruptible(&radio->read_queue); - - /* stop radio */ - retval = si470x_stop(radio); - usb_autopm_put_interface(radio->intf); - } -unlock: - mutex_unlock(&radio->disconnect_lock); -done: - return retval; -} - - -/* - * si470x_fops - file operations interface - */ -static const struct v4l2_file_operations si470x_fops = { - .owner = THIS_MODULE, - .read = si470x_fops_read, - .poll = si470x_fops_poll, - .ioctl = video_ioctl2, - .open = si470x_fops_open, - .release = si470x_fops_release, -}; - - - -/************************************************************************** - * Video4Linux Interface - **************************************************************************/ - -/* - * si470x_vidioc_querycap - query device capabilities - */ -static int si470x_vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *capability) -{ - struct si470x_device *radio = video_drvdata(file); - - strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); - strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); - usb_make_path(radio->usbdev, capability->bus_info, sizeof(capability->bus_info)); - capability->version = DRIVER_KERNEL_VERSION; - capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | - V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; - - return 0; -} - - -/* - * si470x_vidioc_queryctrl - enumerate control items - */ -static int si470x_vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - int retval = -EINVAL; - - /* abort if qc->id is below V4L2_CID_BASE */ - if (qc->id < V4L2_CID_BASE) - goto done; - - /* search video control */ - switch (qc->id) { - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15); - case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); - } - - /* disable unsupported base controls */ - /* to satisfy kradio and such apps */ - if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) { - qc->flags = V4L2_CTRL_FLAG_DISABLED; - retval = 0; - } - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": query controls failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_g_ctrl - get the value of a control - */ -static int si470x_vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - ctrl->value = radio->registers[SYSCONFIG2] & - SYSCONFIG2_VOLUME; - break; - case V4L2_CID_AUDIO_MUTE: - ctrl->value = ((radio->registers[POWERCFG] & - POWERCFG_DMUTE) == 0) ? 1 : 0; - break; - default: - retval = -EINVAL; - } - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get control failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_s_ctrl - set the value of a control - */ -static int si470x_vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; - radio->registers[SYSCONFIG2] |= ctrl->value; - retval = si470x_set_register(radio, SYSCONFIG2); - break; - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value == 1) - radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; - else - radio->registers[POWERCFG] |= POWERCFG_DMUTE; - retval = si470x_set_register(radio, POWERCFG); - break; - default: - retval = -EINVAL; - } - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set control failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_g_audio - get audio attributes - */ -static int si470x_vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *audio) -{ - /* driver constants */ - audio->index = 0; - strcpy(audio->name, "Radio"); - audio->capability = V4L2_AUDCAP_STEREO; - audio->mode = 0; - - return 0; -} - - -/* - * si470x_vidioc_g_tuner - get tuner attributes - */ -static int si470x_vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *tuner) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - if (tuner->index != 0) { - retval = -EINVAL; - goto done; - } - - retval = si470x_get_register(radio, STATUSRSSI); - if (retval < 0) - goto done; - - /* driver constants */ - strcpy(tuner->name, "FM"); - tuner->type = V4L2_TUNER_RADIO; - tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_RDS; - - /* range limits */ - switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { - /* 0: 87.5 - 108 MHz (USA, Europe, default) */ - default: - tuner->rangelow = 87.5 * FREQ_MUL; - tuner->rangehigh = 108 * FREQ_MUL; - break; - /* 1: 76 - 108 MHz (Japan wide band) */ - case 1 : - tuner->rangelow = 76 * FREQ_MUL; - tuner->rangehigh = 108 * FREQ_MUL; - break; - /* 2: 76 - 90 MHz (Japan) */ - case 2 : - tuner->rangelow = 76 * FREQ_MUL; - tuner->rangehigh = 90 * FREQ_MUL; - break; - }; - - /* stereo indicator == stereo (instead of mono) */ - if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0) - tuner->rxsubchans = V4L2_TUNER_SUB_MONO; - else - tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - /* If there is a reliable method of detecting an RDS channel, - then this code should check for that before setting this - RDS subchannel. */ - tuner->rxsubchans |= V4L2_TUNER_SUB_RDS; - - /* mono/stereo selector */ - if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0) - tuner->audmode = V4L2_TUNER_MODE_STEREO; - else - tuner->audmode = V4L2_TUNER_MODE_MONO; - - /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */ - /* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */ - tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI); - /* the ideal factor is 0xffff/75 = 873,8 */ - tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10); - - /* automatic frequency control: -1: freq to low, 1 freq to high */ - /* AFCRL does only indicate that freq. differs, not if too low/high */ - tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0; - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get tuner failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_s_tuner - set tuner attributes - */ -static int si470x_vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *tuner) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = -EINVAL; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - if (tuner->index != 0) - goto done; - - /* mono/stereo selector */ - switch (tuner->audmode) { - case V4L2_TUNER_MODE_MONO: - radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */ - break; - case V4L2_TUNER_MODE_STEREO: - radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ - break; - default: - goto done; - } - - retval = si470x_set_register(radio, POWERCFG); - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set tuner failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_g_frequency - get tuner or modulator radio frequency - */ -static int si470x_vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - if (freq->tuner != 0) { - retval = -EINVAL; - goto done; - } - - freq->type = V4L2_TUNER_RADIO; - retval = si470x_get_freq(radio, &freq->frequency); - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get frequency failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_s_frequency - set tuner or modulator radio frequency - */ -static int si470x_vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *freq) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - if (freq->tuner != 0) { - retval = -EINVAL; - goto done; - } - - retval = si470x_set_freq(radio, freq->frequency); - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set frequency failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek - */ -static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, - struct v4l2_hw_freq_seek *seek) -{ - struct si470x_device *radio = video_drvdata(file); - int retval = 0; - - /* safety checks */ - if (radio->disconnected) { - retval = -EIO; - goto done; - } - if (seek->tuner != 0) { - retval = -EINVAL; - goto done; - } - - retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward); - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set hardware frequency seek failed with %d\n", - retval); - return retval; -} - - -/* - * si470x_ioctl_ops - video device ioctl operations - */ -static const struct v4l2_ioctl_ops si470x_ioctl_ops = { - .vidioc_querycap = si470x_vidioc_querycap, - .vidioc_queryctrl = si470x_vidioc_queryctrl, - .vidioc_g_ctrl = si470x_vidioc_g_ctrl, - .vidioc_s_ctrl = si470x_vidioc_s_ctrl, - .vidioc_g_audio = si470x_vidioc_g_audio, - .vidioc_g_tuner = si470x_vidioc_g_tuner, - .vidioc_s_tuner = si470x_vidioc_s_tuner, - .vidioc_g_frequency = si470x_vidioc_g_frequency, - .vidioc_s_frequency = si470x_vidioc_s_frequency, - .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek, -}; - - -/* - * si470x_viddev_template - video device interface - */ -static struct video_device si470x_viddev_template = { - .fops = &si470x_fops, - .name = DRIVER_NAME, - .release = video_device_release, - .ioctl_ops = &si470x_ioctl_ops, -}; - - - -/************************************************************************** - * USB Interface - **************************************************************************/ - -/* - * si470x_usb_driver_probe - probe for the device - */ -static int si470x_usb_driver_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct si470x_device *radio; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int i, int_end_size, retval = 0; - - /* private data allocation and initialization */ - radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); - if (!radio) { - retval = -ENOMEM; - goto err_initial; - } - radio->users = 0; - radio->disconnected = 0; - radio->usbdev = interface_to_usbdev(intf); - radio->intf = intf; - mutex_init(&radio->disconnect_lock); - mutex_init(&radio->lock); - - iface_desc = intf->cur_altsetting; - - /* Set up interrupt endpoint information. */ - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == - USB_DIR_IN) && ((endpoint->bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) - radio->int_in_endpoint = endpoint; - } - if (!radio->int_in_endpoint) { - printk(KERN_INFO DRIVER_NAME - ": could not find interrupt in endpoint\n"); - retval = -EIO; - goto err_radio; - } - - int_end_size = le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize); - - radio->int_in_buffer = kmalloc(int_end_size, GFP_KERNEL); - if (!radio->int_in_buffer) { - printk(KERN_INFO DRIVER_NAME - "could not allocate int_in_buffer"); - retval = -ENOMEM; - goto err_radio; - } - - radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!radio->int_in_urb) { - printk(KERN_INFO DRIVER_NAME "could not allocate int_in_urb"); - retval = -ENOMEM; - goto err_intbuffer; - } - - /* video device allocation and initialization */ - radio->videodev = video_device_alloc(); - if (!radio->videodev) { - retval = -ENOMEM; - goto err_intbuffer; - } - memcpy(radio->videodev, &si470x_viddev_template, - sizeof(si470x_viddev_template)); - video_set_drvdata(radio->videodev, radio); - - /* show some infos about the specific si470x device */ - if (si470x_get_all_registers(radio) < 0) { - retval = -EIO; - goto err_video; - } - printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", - radio->registers[DEVICEID], radio->registers[CHIPID]); - - /* get software and hardware versions */ - if (si470x_get_scratch_page_versions(radio) < 0) { - retval = -EIO; - goto err_video; - } - printk(KERN_INFO DRIVER_NAME - ": software version %d, hardware version %d\n", - radio->software_version, radio->hardware_version); - - /* check if device and firmware is current */ - if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) - < RADIO_SW_VERSION_CURRENT) { - printk(KERN_WARNING DRIVER_NAME - ": This driver is known to work with " - "firmware version %hu,\n", RADIO_SW_VERSION_CURRENT); - printk(KERN_WARNING DRIVER_NAME - ": but the device has firmware version %hu.\n", - radio->registers[CHIPID] & CHIPID_FIRMWARE); - printk(KERN_WARNING DRIVER_NAME - ": If you have some trouble using this driver,\n"); - printk(KERN_WARNING DRIVER_NAME - ": please report to V4L ML at " - "linux-media@vger.kernel.org\n"); - } - - /* set initial frequency */ - si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ - - /* set led to connect state */ - si470x_set_led_state(radio, BLINK_GREEN_LED); - - /* rds buffer allocation */ - radio->buf_size = rds_buf * 3; - radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); - if (!radio->buffer) { - retval = -EIO; - goto err_video; - } - - /* rds buffer configuration */ - radio->wr_index = 0; - radio->rd_index = 0; - init_waitqueue_head(&radio->read_queue); - - /* register video device */ - retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); - if (retval) { - printk(KERN_WARNING DRIVER_NAME - ": Could not register video device\n"); - goto err_all; - } - usb_set_intfdata(intf, radio); - - return 0; -err_all: - kfree(radio->buffer); -err_video: - video_device_release(radio->videodev); -err_intbuffer: - kfree(radio->int_in_buffer); -err_radio: - kfree(radio); -err_initial: - return retval; -} - - -/* - * si470x_usb_driver_suspend - suspend the device - */ -static int si470x_usb_driver_suspend(struct usb_interface *intf, - pm_message_t message) -{ - printk(KERN_INFO DRIVER_NAME ": suspending now...\n"); - - return 0; -} - - -/* - * si470x_usb_driver_resume - resume the device - */ -static int si470x_usb_driver_resume(struct usb_interface *intf) -{ - printk(KERN_INFO DRIVER_NAME ": resuming now...\n"); - - return 0; -} - - -/* - * si470x_usb_driver_disconnect - disconnect the device - */ -static void si470x_usb_driver_disconnect(struct usb_interface *intf) -{ - struct si470x_device *radio = usb_get_intfdata(intf); - - mutex_lock(&radio->disconnect_lock); - radio->disconnected = 1; - usb_set_intfdata(intf, NULL); - if (radio->users == 0) { - /* set led to disconnect state */ - si470x_set_led_state(radio, BLINK_ORANGE_LED); - - /* Free data structures. */ - usb_free_urb(radio->int_in_urb); - - kfree(radio->int_in_buffer); - video_unregister_device(radio->videodev); - kfree(radio->buffer); - kfree(radio); - } - mutex_unlock(&radio->disconnect_lock); -} - - -/* - * si470x_usb_driver - usb driver interface - */ -static struct usb_driver si470x_usb_driver = { - .name = DRIVER_NAME, - .probe = si470x_usb_driver_probe, - .disconnect = si470x_usb_driver_disconnect, - .suspend = si470x_usb_driver_suspend, - .resume = si470x_usb_driver_resume, - .id_table = si470x_usb_driver_id_table, - .supports_autosuspend = 1, -}; - - - -/************************************************************************** - * Module Interface - **************************************************************************/ - -/* - * si470x_module_init - module init - */ -static int __init si470x_module_init(void) -{ - printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); - return usb_register(&si470x_usb_driver); -} - - -/* - * si470x_module_exit - module exit - */ -static void __exit si470x_module_exit(void) -{ - usb_deregister(&si470x_usb_driver); -} - - -module_init(si470x_module_init); -module_exit(si470x_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); diff --git a/linux/drivers/media/radio/si470x/Kconfig b/linux/drivers/media/radio/si470x/Kconfig new file mode 100644 index 000000000..20d05c04f --- /dev/null +++ b/linux/drivers/media/radio/si470x/Kconfig @@ -0,0 +1,24 @@ +config USB_SI470X + tristate "Silicon Labs Si470x FM Radio Receiver support with USB" + depends on USB && RADIO_SI470X + ---help--- + This is a driver for USB devices with the Silicon Labs SI470x + chip. Currently these devices are known to work: + - 10c4:818a: Silicon Labs USB FM Radio Reference Design + - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) + - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700) + - 10c5:819a: Sanei Electric FM USB Radio (aka DealExtreme.com PCear) + + Sound is provided by the ALSA USB Audio/MIDI driver. Therefore + if you don't want to use the device solely for RDS receiving, + it is recommended to also select SND_USB_AUDIO. + + Please have a look at the documentation, especially on how + to redirect the audio stream from the radio to your sound device: + Documentation/video4linux/si470x.txt + + Say Y here if you want to connect this type of radio to your + computer's USB port. + + To compile this driver as a module, choose M here: the + module will be called radio-usb-si470x. diff --git a/linux/drivers/media/radio/si470x/Makefile b/linux/drivers/media/radio/si470x/Makefile new file mode 100644 index 000000000..3cb777fe3 --- /dev/null +++ b/linux/drivers/media/radio/si470x/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for radios with Silicon Labs Si470x FM Radio Receivers +# + +radio-usb-si470x-objs := radio-si470x-usb.o radio-si470x-common.o + +obj-$(CONFIG_USB_SI470X) += radio-usb-si470x.o diff --git a/linux/drivers/media/radio/si470x/radio-si470x-common.c b/linux/drivers/media/radio/si470x/radio-si470x-common.c new file mode 100644 index 000000000..b64559d56 --- /dev/null +++ b/linux/drivers/media/radio/si470x/radio-si470x-common.c @@ -0,0 +1,794 @@ +/* + * drivers/media/radio/si470x/radio-si470x-common.c + * + * Driver for radios with Silicon Labs Si470x FM Radio Receivers + * + * Copyright (c) 2009 Tobias Lorenz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * History: + * 2008-01-12 Tobias Lorenz + * Version 1.0.0 + * - First working version + * 2008-01-13 Tobias Lorenz + * Version 1.0.1 + * - Improved error handling, every function now returns errno + * - Improved multi user access (start/mute/stop) + * - Channel doesn't get lost anymore after start/mute/stop + * - RDS support added (polling mode via interrupt EP 1) + * - marked default module parameters with *value* + * - switched from bit structs to bit masks + * - header file cleaned and integrated + * 2008-01-14 Tobias Lorenz + * Version 1.0.2 + * - hex values are now lower case + * - commented USB ID for ADS/Tech moved on todo list + * - blacklisted si470x in hid-quirks.c + * - rds buffer handling functions integrated into *_work, *_read + * - rds_command in si470x_poll exchanged against simple retval + * - check for firmware version 15 + * - code order and prototypes still remain the same + * - spacing and bottom of band codes remain the same + * 2008-01-16 Tobias Lorenz + * Version 1.0.3 + * - code reordered to avoid function prototypes + * - switch/case defaults are now more user-friendly + * - unified comment style + * - applied all checkpatch.pl v1.12 suggestions + * except the warning about the too long lines with bit comments + * - renamed FMRADIO to RADIO to cut line length (checkpatch.pl) + * 2008-01-22 Tobias Lorenz + * Version 1.0.4 + * - avoid poss. locking when doing copy_to_user which may sleep + * - RDS is automatically activated on read now + * - code cleaned of unnecessary rds_commands + * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified + * (thanks to Guillaume RAMOUSSE) + * 2008-01-27 Tobias Lorenz + * Version 1.0.5 + * - number of seek_retries changed to tune_timeout + * - fixed problem with incomplete tune operations by own buffers + * - optimization of variables and printf types + * - improved error logging + * 2008-01-31 Tobias Lorenz + * Oliver Neukum + * Version 1.0.6 + * - fixed coverity checker warnings in *_usb_driver_disconnect + * - probe()/open() race by correct ordering in probe() + * - DMA coherency rules by separate allocation of all buffers + * - use of endianness macros + * - abuse of spinlock, replaced by mutex + * - racy handling of timer in disconnect, + * replaced by delayed_work + * - racy interruptible_sleep_on(), + * replaced with wait_event_interruptible() + * - handle signals in read() + * 2008-02-08 Tobias Lorenz + * Oliver Neukum + * Version 1.0.7 + * - usb autosuspend support + * - unplugging fixed + * 2008-05-07 Tobias Lorenz + * Version 1.0.8 + * - hardware frequency seek support + * - afc indication + * - more safety checks, let si470x_get_freq return errno + * - vidioc behavior corrected according to v4l2 spec + * 2008-10-20 Alexey Klimov + * - add support for KWorld USB FM Radio FM700 + * - blacklisted KWorld radio in hid-core.c and hid-ids.h + * 2008-12-03 Mark Lord + * - add support for DealExtreme USB Radio + * 2009-01-31 Bob Ross + * - correction of stereo detection/setting + * - correction of signal strength indicator scaling + * 2009-01-31 Rick Bronson + * Tobias Lorenz + * - add LED status output + * - get HW/SW version from scratchpad + * 2009-06-16 Edouard Lafargue + * Version 1.0.10 + * - add support for interrupt mode for RDS endpoint, + * instead of polling. + * Improves RDS reception significantly + */ + + +/* kernel includes */ +#include "radio-si470x.h" + + + +/************************************************************************** + * Module Parameters + **************************************************************************/ + +/* Spacing (kHz) */ +/* 0: 200 kHz (USA, Australia) */ +/* 1: 100 kHz (Europe, Japan) */ +/* 2: 50 kHz */ +static unsigned short space = 2; +module_param(space, ushort, 0444); +MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); + +/* Bottom of Band (MHz) */ +/* 0: 87.5 - 108 MHz (USA, Europe)*/ +/* 1: 76 - 108 MHz (Japan wide band) */ +/* 2: 76 - 90 MHz (Japan) */ +static unsigned short band = 1; +module_param(band, ushort, 0444); +MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); + +/* De-emphasis */ +/* 0: 75 us (USA) */ +/* 1: 50 us (Europe, Australia, Japan) */ +static unsigned short de = 1; +module_param(de, ushort, 0444); +MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*"); + +/* Tune timeout */ +static unsigned int tune_timeout = 3000; +module_param(tune_timeout, uint, 0644); +MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*"); + +/* Seek timeout */ +static unsigned int seek_timeout = 5000; +module_param(seek_timeout, uint, 0644); +MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*"); + + + +/************************************************************************** + * Generic Functions + **************************************************************************/ + +/* + * si470x_set_chan - set the channel + */ +static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) +{ + int retval; + unsigned long timeout; + bool timed_out = 0; + + /* start tuning */ + radio->registers[CHANNEL] &= ~CHANNEL_CHAN; + radio->registers[CHANNEL] |= CHANNEL_TUNE | chan; + retval = si470x_set_register(radio, CHANNEL); + if (retval < 0) + goto done; + + /* wait till tune operation has completed */ + timeout = jiffies + msecs_to_jiffies(tune_timeout); + do { + retval = si470x_get_register(radio, STATUSRSSI); + if (retval < 0) + goto stop; + timed_out = time_after(jiffies, timeout); + } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && + (!timed_out)); + if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) + printk(KERN_WARNING DRIVER_NAME ": tune does not complete\n"); + if (timed_out) + printk(KERN_WARNING DRIVER_NAME + ": tune timed out after %u ms\n", tune_timeout); + +stop: + /* stop tuning */ + radio->registers[CHANNEL] &= ~CHANNEL_TUNE; + retval = si470x_set_register(radio, CHANNEL); + +done: + return retval; +} + + +/* + * si470x_get_freq - get the frequency + */ +static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq) +{ + unsigned int spacing, band_bottom; + unsigned short chan; + int retval; + + /* Spacing (kHz) */ + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { + /* 0: 200 kHz (USA, Australia) */ + case 0: + spacing = 0.200 * FREQ_MUL; break; + /* 1: 100 kHz (Europe, Japan) */ + case 1: + spacing = 0.100 * FREQ_MUL; break; + /* 2: 50 kHz */ + default: + spacing = 0.050 * FREQ_MUL; break; + }; + + /* Bottom of Band (MHz) */ + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { + /* 0: 87.5 - 108 MHz (USA, Europe) */ + case 0: + band_bottom = 87.5 * FREQ_MUL; break; + /* 1: 76 - 108 MHz (Japan wide band) */ + default: + band_bottom = 76 * FREQ_MUL; break; + /* 2: 76 - 90 MHz (Japan) */ + case 2: + band_bottom = 76 * FREQ_MUL; break; + }; + + /* read channel */ + retval = si470x_get_register(radio, READCHAN); + chan = radio->registers[READCHAN] & READCHAN_READCHAN; + + /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */ + *freq = chan * spacing + band_bottom; + + return retval; +} + + +/* + * si470x_set_freq - set the frequency + */ +int si470x_set_freq(struct si470x_device *radio, unsigned int freq) +{ + unsigned int spacing, band_bottom; + unsigned short chan; + + /* Spacing (kHz) */ + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { + /* 0: 200 kHz (USA, Australia) */ + case 0: + spacing = 0.200 * FREQ_MUL; break; + /* 1: 100 kHz (Europe, Japan) */ + case 1: + spacing = 0.100 * FREQ_MUL; break; + /* 2: 50 kHz */ + default: + spacing = 0.050 * FREQ_MUL; break; + }; + + /* Bottom of Band (MHz) */ + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { + /* 0: 87.5 - 108 MHz (USA, Europe) */ + case 0: + band_bottom = 87.5 * FREQ_MUL; break; + /* 1: 76 - 108 MHz (Japan wide band) */ + default: + band_bottom = 76 * FREQ_MUL; break; + /* 2: 76 - 90 MHz (Japan) */ + case 2: + band_bottom = 76 * FREQ_MUL; break; + }; + + /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */ + chan = (freq - band_bottom) / spacing; + + return si470x_set_chan(radio, chan); +} + + +/* + * si470x_set_seek - set seek + */ +static int si470x_set_seek(struct si470x_device *radio, + unsigned int wrap_around, unsigned int seek_upward) +{ + int retval = 0; + unsigned long timeout; + bool timed_out = 0; + + /* start seeking */ + radio->registers[POWERCFG] |= POWERCFG_SEEK; + if (wrap_around == 1) + radio->registers[POWERCFG] &= ~POWERCFG_SKMODE; + else + radio->registers[POWERCFG] |= POWERCFG_SKMODE; + if (seek_upward == 1) + radio->registers[POWERCFG] |= POWERCFG_SEEKUP; + else + radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP; + retval = si470x_set_register(radio, POWERCFG); + if (retval < 0) + goto done; + + /* wait till seek operation has completed */ + timeout = jiffies + msecs_to_jiffies(seek_timeout); + do { + retval = si470x_get_register(radio, STATUSRSSI); + if (retval < 0) + goto stop; + timed_out = time_after(jiffies, timeout); + } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && + (!timed_out)); + if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) + printk(KERN_WARNING DRIVER_NAME ": seek does not complete\n"); + if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) + printk(KERN_WARNING DRIVER_NAME + ": seek failed / band limit reached\n"); + if (timed_out) + printk(KERN_WARNING DRIVER_NAME + ": seek timed out after %u ms\n", seek_timeout); + +stop: + /* stop seeking */ + radio->registers[POWERCFG] &= ~POWERCFG_SEEK; + retval = si470x_set_register(radio, POWERCFG); + +done: + /* try again, if timed out */ + if ((retval == 0) && timed_out) + retval = -EAGAIN; + + return retval; +} + + +/* + * si470x_start - switch on radio + */ +int si470x_start(struct si470x_device *radio) +{ + int retval; + + /* powercfg */ + radio->registers[POWERCFG] = + POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM; + retval = si470x_set_register(radio, POWERCFG); + if (retval < 0) + goto done; + + /* sysconfig 1 */ + radio->registers[SYSCONFIG1] = SYSCONFIG1_DE; + retval = si470x_set_register(radio, SYSCONFIG1); + if (retval < 0) + goto done; + + /* sysconfig 2 */ + radio->registers[SYSCONFIG2] = + (0x3f << 8) | /* SEEKTH */ + ((band << 6) & SYSCONFIG2_BAND) | /* BAND */ + ((space << 4) & SYSCONFIG2_SPACE) | /* SPACE */ + 15; /* VOLUME (max) */ + retval = si470x_set_register(radio, SYSCONFIG2); + if (retval < 0) + goto done; + + /* reset last channel */ + retval = si470x_set_chan(radio, + radio->registers[CHANNEL] & CHANNEL_CHAN); + +done: + return retval; +} + + +/* + * si470x_stop - switch off radio + */ +int si470x_stop(struct si470x_device *radio) +{ + int retval; + + /* sysconfig 1 */ + radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; + retval = si470x_set_register(radio, SYSCONFIG1); + if (retval < 0) + goto done; + + /* powercfg */ + radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; + /* POWERCFG_ENABLE has to automatically go low */ + radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE; + retval = si470x_set_register(radio, POWERCFG); + +done: + return retval; +} + + +/* + * si470x_rds_on - switch on rds reception + */ +int si470x_rds_on(struct si470x_device *radio) +{ + int retval; + + /* sysconfig 1 */ + mutex_lock(&radio->lock); + radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS; + retval = si470x_set_register(radio, SYSCONFIG1); + if (retval < 0) + radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; + mutex_unlock(&radio->lock); + + return retval; +} + + + +/************************************************************************** + * Video4Linux Interface + **************************************************************************/ + +/* + * si470x_vidioc_queryctrl - enumerate control items + */ +static int si470x_vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int retval = -EINVAL; + + /* abort if qc->id is below V4L2_CID_BASE */ + if (qc->id < V4L2_CID_BASE) + goto done; + + /* search video control */ + switch (qc->id) { + case V4L2_CID_AUDIO_VOLUME: + return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15); + case V4L2_CID_AUDIO_MUTE: + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + } + + /* disable unsupported base controls */ + /* to satisfy kradio and such apps */ + if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) { + qc->flags = V4L2_CTRL_FLAG_DISABLED; + retval = 0; + } + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": query controls failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_g_ctrl - get the value of a control + */ +static int si470x_vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = radio->registers[SYSCONFIG2] & + SYSCONFIG2_VOLUME; + break; + case V4L2_CID_AUDIO_MUTE: + ctrl->value = ((radio->registers[POWERCFG] & + POWERCFG_DMUTE) == 0) ? 1 : 0; + break; + default: + retval = -EINVAL; + } + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": get control failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_s_ctrl - set the value of a control + */ +static int si470x_vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: + radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; + radio->registers[SYSCONFIG2] |= ctrl->value; + retval = si470x_set_register(radio, SYSCONFIG2); + break; + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value == 1) + radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; + else + radio->registers[POWERCFG] |= POWERCFG_DMUTE; + retval = si470x_set_register(radio, POWERCFG); + break; + default: + retval = -EINVAL; + } + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": set control failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_g_audio - get audio attributes + */ +static int si470x_vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *audio) +{ + /* driver constants */ + audio->index = 0; + strcpy(audio->name, "Radio"); + audio->capability = V4L2_AUDCAP_STEREO; + audio->mode = 0; + + return 0; +} + + +/* + * si470x_vidioc_g_tuner - get tuner attributes + */ +static int si470x_vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *tuner) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + if (tuner->index != 0) { + retval = -EINVAL; + goto done; + } + + retval = si470x_get_register(radio, STATUSRSSI); + if (retval < 0) + goto done; + + /* driver constants */ + strcpy(tuner->name, "FM"); + tuner->type = V4L2_TUNER_RADIO; + tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_RDS; + + /* range limits */ + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { + /* 0: 87.5 - 108 MHz (USA, Europe, default) */ + default: + tuner->rangelow = 87.5 * FREQ_MUL; + tuner->rangehigh = 108 * FREQ_MUL; + break; + /* 1: 76 - 108 MHz (Japan wide band) */ + case 1: + tuner->rangelow = 76 * FREQ_MUL; + tuner->rangehigh = 108 * FREQ_MUL; + break; + /* 2: 76 - 90 MHz (Japan) */ + case 2: + tuner->rangelow = 76 * FREQ_MUL; + tuner->rangehigh = 90 * FREQ_MUL; + break; + }; + + /* stereo indicator == stereo (instead of mono) */ + if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0) + tuner->rxsubchans = V4L2_TUNER_SUB_MONO; + else + tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + /* If there is a reliable method of detecting an RDS channel, + then this code should check for that before setting this + RDS subchannel. */ + tuner->rxsubchans |= V4L2_TUNER_SUB_RDS; + + /* mono/stereo selector */ + if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0) + tuner->audmode = V4L2_TUNER_MODE_STEREO; + else + tuner->audmode = V4L2_TUNER_MODE_MONO; + + /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */ + /* measured in units of db쨉V in 1 db increments (max at ~75 db쨉V) */ + tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI); + /* the ideal factor is 0xffff/75 = 873,8 */ + tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10); + + /* automatic frequency control: -1: freq to low, 1 freq to high */ + /* AFCRL does only indicate that freq. differs, not if too low/high */ + tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0; + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": get tuner failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_s_tuner - set tuner attributes + */ +static int si470x_vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *tuner) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = -EINVAL; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + if (tuner->index != 0) + goto done; + + /* mono/stereo selector */ + switch (tuner->audmode) { + case V4L2_TUNER_MODE_MONO: + radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */ + break; + case V4L2_TUNER_MODE_STEREO: + radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ + break; + default: + goto done; + } + + retval = si470x_set_register(radio, POWERCFG); + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": set tuner failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_g_frequency - get tuner or modulator radio frequency + */ +static int si470x_vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + if (freq->tuner != 0) { + retval = -EINVAL; + goto done; + } + + freq->type = V4L2_TUNER_RADIO; + retval = si470x_get_freq(radio, &freq->frequency); + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": get frequency failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_s_frequency - set tuner or modulator radio frequency + */ +static int si470x_vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *freq) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + if (freq->tuner != 0) { + retval = -EINVAL; + goto done; + } + + retval = si470x_set_freq(radio, freq->frequency); + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": set frequency failed with %d\n", retval); + return retval; +} + + +/* + * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek + */ +static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, + struct v4l2_hw_freq_seek *seek) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety checks */ + if (radio->disconnected) { + retval = -EIO; + goto done; + } + if (seek->tuner != 0) { + retval = -EINVAL; + goto done; + } + + retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward); + +done: + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": set hardware frequency seek failed with %d\n", + retval); + return retval; +} + + +/* + * si470x_ioctl_ops - video device ioctl operations + */ +static const struct v4l2_ioctl_ops si470x_ioctl_ops = { + .vidioc_querycap = si470x_vidioc_querycap, + .vidioc_queryctrl = si470x_vidioc_queryctrl, + .vidioc_g_ctrl = si470x_vidioc_g_ctrl, + .vidioc_s_ctrl = si470x_vidioc_s_ctrl, + .vidioc_g_audio = si470x_vidioc_g_audio, + .vidioc_g_tuner = si470x_vidioc_g_tuner, + .vidioc_s_tuner = si470x_vidioc_s_tuner, + .vidioc_g_frequency = si470x_vidioc_g_frequency, + .vidioc_s_frequency = si470x_vidioc_s_frequency, + .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek, +}; + + +/* + * si470x_viddev_template - video device interface + */ +struct video_device si470x_viddev_template = { + .fops = &si470x_fops, + .name = DRIVER_NAME, + .release = video_device_release, + .ioctl_ops = &si470x_ioctl_ops, +}; diff --git a/linux/drivers/media/radio/si470x/radio-si470x-usb.c b/linux/drivers/media/radio/si470x/radio-si470x-usb.c new file mode 100644 index 000000000..f3d805f70 --- /dev/null +++ b/linux/drivers/media/radio/si470x/radio-si470x-usb.c @@ -0,0 +1,958 @@ +/* + * drivers/media/radio/si470x/radio-si470x-usb.c + * + * USB driver for radios with Silicon Labs Si470x FM Radio Receivers + * + * Copyright (c) 2009 Tobias Lorenz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * ToDo: + * - add firmware download/update support + */ + + +/* driver definitions */ +#define DRIVER_AUTHOR "Tobias Lorenz " +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 10) +#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" +#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" +#define DRIVER_VERSION "1.0.10" + +/* kernel includes */ +#include +#include + +#include "radio-si470x.h" + + +/* USB Device ID List */ +static struct usb_device_id si470x_usb_driver_id_table[] = { + /* Silicon Labs USB FM Radio Reference Design */ + { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) }, + /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, + /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) }, + /* Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) }, + /* Terminating entry */ + { } +}; +MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table); + + + +/************************************************************************** + * Module Parameters + **************************************************************************/ + +/* Radio Nr */ +static int radio_nr = -1; +module_param(radio_nr, int, 0444); +MODULE_PARM_DESC(radio_nr, "Radio Nr"); + +/* USB timeout */ +static unsigned int usb_timeout = 500; +module_param(usb_timeout, uint, 0644); +MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*"); + +/* RDS buffer blocks */ +static unsigned int rds_buf = 100; +module_param(rds_buf, uint, 0444); +MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*"); + +/* RDS maximum block errors */ +static unsigned short max_rds_errors = 1; +/* 0 means 0 errors requiring correction */ +/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */ +/* 2 means 3-5 errors requiring correction */ +/* 3 means 6+ errors or errors in checkword, correction not possible */ +module_param(max_rds_errors, ushort, 0644); +MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); + + + +/************************************************************************** + * USB HID Reports + **************************************************************************/ + +/* Reports 1-16 give direct read/write access to the 16 Si470x registers */ +/* with the (REPORT_ID - 1) corresponding to the register address across USB */ +/* endpoint 0 using GET_REPORT and SET_REPORT */ +#define REGISTER_REPORT_SIZE (RADIO_REGISTER_SIZE + 1) +#define REGISTER_REPORT(reg) ((reg) + 1) + +/* Report 17 gives direct read/write access to the entire Si470x register */ +/* map across endpoint 0 using GET_REPORT and SET_REPORT */ +#define ENTIRE_REPORT_SIZE (RADIO_REGISTER_NUM * RADIO_REGISTER_SIZE + 1) +#define ENTIRE_REPORT 17 + +/* Report 18 is used to send the lowest 6 Si470x registers up the HID */ +/* interrupt endpoint 1 to Windows every 20 milliseconds for status */ +#define RDS_REPORT_SIZE (RDS_REGISTER_NUM * RADIO_REGISTER_SIZE + 1) +#define RDS_REPORT 18 + +/* Report 19: LED state */ +#define LED_REPORT_SIZE 3 +#define LED_REPORT 19 + +/* Report 19: stream */ +#define STREAM_REPORT_SIZE 3 +#define STREAM_REPORT 19 + +/* Report 20: scratch */ +#define SCRATCH_PAGE_SIZE 63 +#define SCRATCH_REPORT_SIZE (SCRATCH_PAGE_SIZE + 1) +#define SCRATCH_REPORT 20 + +/* Reports 19-22: flash upgrade of the C8051F321 */ +#define WRITE_REPORT_SIZE 4 +#define WRITE_REPORT 19 +#define FLASH_REPORT_SIZE 64 +#define FLASH_REPORT 20 +#define CRC_REPORT_SIZE 3 +#define CRC_REPORT 21 +#define RESPONSE_REPORT_SIZE 2 +#define RESPONSE_REPORT 22 + +/* Report 23: currently unused, but can accept 60 byte reports on the HID */ +/* interrupt out endpoint 2 every 1 millisecond */ +#define UNUSED_REPORT 23 + + + +/************************************************************************** + * Software/Hardware Versions + **************************************************************************/ +#define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6 +#define RADIO_SW_VERSION 7 +#define RADIO_SW_VERSION_CURRENT 15 +#define RADIO_HW_VERSION 1 + +#define SCRATCH_PAGE_SW_VERSION 1 +#define SCRATCH_PAGE_HW_VERSION 2 + + + +/************************************************************************** + * LED State Definitions + **************************************************************************/ +#define LED_COMMAND 0x35 + +#define NO_CHANGE_LED 0x00 +#define ALL_COLOR_LED 0x01 /* streaming state */ +#define BLINK_GREEN_LED 0x02 /* connect state */ +#define BLINK_RED_LED 0x04 +#define BLINK_ORANGE_LED 0x10 /* disconnect state */ +#define SOLID_GREEN_LED 0x20 /* tuning/seeking state */ +#define SOLID_RED_LED 0x40 /* bootload state */ +#define SOLID_ORANGE_LED 0x80 + + + +/************************************************************************** + * Stream State Definitions + **************************************************************************/ +#define STREAM_COMMAND 0x36 +#define STREAM_VIDPID 0x00 +#define STREAM_AUDIO 0xff + + + +/************************************************************************** + * Bootloader / Flash Commands + **************************************************************************/ + +/* unique id sent to bootloader and required to put into a bootload state */ +#define UNIQUE_BL_ID 0x34 + +/* mask for the flash data */ +#define FLASH_DATA_MASK 0x55 + +/* bootloader commands */ +#define GET_SW_VERSION_COMMAND 0x00 +#define SET_PAGE_COMMAND 0x01 +#define ERASE_PAGE_COMMAND 0x02 +#define WRITE_PAGE_COMMAND 0x03 +#define CRC_ON_PAGE_COMMAND 0x04 +#define READ_FLASH_BYTE_COMMAND 0x05 +#define RESET_DEVICE_COMMAND 0x06 +#define GET_HW_VERSION_COMMAND 0x07 +#define BLANK 0xff + +/* bootloader command responses */ +#define COMMAND_OK 0x01 +#define COMMAND_FAILED 0x02 +#define COMMAND_PENDING 0x03 + + + +/************************************************************************** + * General Driver Functions - REGISTER_REPORTs + **************************************************************************/ + +/* + * si470x_get_report - receive a HID report + */ +static int si470x_get_report(struct si470x_device *radio, void *buf, int size) +{ + unsigned char *report = (unsigned char *) buf; + int retval; + + retval = usb_control_msg(radio->usbdev, + usb_rcvctrlpipe(radio->usbdev, 0), + HID_REQ_GET_REPORT, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, + report[0], 2, + buf, size, usb_timeout); + + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": si470x_get_report: usb_control_msg returned %d\n", + retval); + return retval; +} + + +/* + * si470x_set_report - send a HID report + */ +static int si470x_set_report(struct si470x_device *radio, void *buf, int size) +{ + unsigned char *report = (unsigned char *) buf; + int retval; + + retval = usb_control_msg(radio->usbdev, + usb_sndctrlpipe(radio->usbdev, 0), + HID_REQ_SET_REPORT, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, + report[0], 2, + buf, size, usb_timeout); + + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": si470x_set_report: usb_control_msg returned %d\n", + retval); + return retval; +} + + +/* + * si470x_get_register - read register + */ +int si470x_get_register(struct si470x_device *radio, int regnr) +{ + unsigned char buf[REGISTER_REPORT_SIZE]; + int retval; + + buf[0] = REGISTER_REPORT(regnr); + + retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); + + if (retval >= 0) + radio->registers[regnr] = get_unaligned_be16(&buf[1]); + + return (retval < 0) ? -EINVAL : 0; +} + + +/* + * si470x_set_register - write register + */ +int si470x_set_register(struct si470x_device *radio, int regnr) +{ + unsigned char buf[REGISTER_REPORT_SIZE]; + int retval; + + buf[0] = REGISTER_REPORT(regnr); + put_unaligned_be16(radio->registers[regnr], &buf[1]); + + retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); + + return (retval < 0) ? -EINVAL : 0; +} + + + +/************************************************************************** + * General Driver Functions - ENTIRE_REPORT + **************************************************************************/ + +/* + * si470x_get_all_registers - read entire registers + */ +static int si470x_get_all_registers(struct si470x_device *radio) +{ + unsigned char buf[ENTIRE_REPORT_SIZE]; + int retval; + unsigned char regnr; + + buf[0] = ENTIRE_REPORT; + + retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); + + if (retval >= 0) + for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) + radio->registers[regnr] = get_unaligned_be16( + &buf[regnr * RADIO_REGISTER_SIZE + 1]); + + return (retval < 0) ? -EINVAL : 0; +} + + + +/************************************************************************** + * General Driver Functions - LED_REPORT + **************************************************************************/ + +/* + * si470x_set_led_state - sets the led state + */ +static int si470x_set_led_state(struct si470x_device *radio, + unsigned char led_state) +{ + unsigned char buf[LED_REPORT_SIZE]; + int retval; + + buf[0] = LED_REPORT; + buf[1] = LED_COMMAND; + buf[2] = led_state; + + retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); + + return (retval < 0) ? -EINVAL : 0; +} + + + +/************************************************************************** + * General Driver Functions - SCRATCH_REPORT + **************************************************************************/ + +/* + * si470x_get_scratch_versions - gets the scratch page and version infos + */ +static int si470x_get_scratch_page_versions(struct si470x_device *radio) +{ + unsigned char buf[SCRATCH_REPORT_SIZE]; + int retval; + + buf[0] = SCRATCH_REPORT; + + retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); + + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME ": si470x_get_scratch: " + "si470x_get_report returned %d\n", retval); + else { + radio->software_version = buf[1]; + radio->hardware_version = buf[2]; + } + + return (retval < 0) ? -EINVAL : 0; +} + + + +/************************************************************************** + * RDS Driver Functions + **************************************************************************/ + +/* + * si470x_int_in_callback - rds callback and processing function + * + * TODO: do we need to use mutex locks in some sections? + */ +static void si470x_int_in_callback(struct urb *urb) +{ + struct si470x_device *radio = urb->context; + unsigned char buf[RDS_REPORT_SIZE]; + int retval; + unsigned char regnr; + unsigned char blocknum; + unsigned short bler; /* rds block errors */ + unsigned short rds; + unsigned char tmpbuf[3]; + + if (urb->status) { + if (urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN) { + return; + } else { + printk(KERN_WARNING DRIVER_NAME + ": non-zero urb status (%d)\n", urb->status); + goto resubmit; /* Maybe we can recover. */ + } + } + + /* safety checks */ + if (radio->disconnected) + return; + if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) + goto resubmit; + + if (urb->actual_length > 0) { + /* Update RDS registers with URB data */ + buf[0] = RDS_REPORT; + for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) + radio->registers[STATUSRSSI + regnr] = + get_unaligned_be16(&radio->int_in_buffer[ + regnr * RADIO_REGISTER_SIZE + 1]); + /* get rds blocks */ + if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) { + /* No RDS group ready, better luck next time */ + goto resubmit; + } + if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSS) == 0) { + /* RDS decoder not synchronized */ + goto resubmit; + } + for (blocknum = 0; blocknum < 4; blocknum++) { + switch (blocknum) { + default: + bler = (radio->registers[STATUSRSSI] & + STATUSRSSI_BLERA) >> 9; + rds = radio->registers[RDSA]; + break; + case 1: + bler = (radio->registers[READCHAN] & + READCHAN_BLERB) >> 14; + rds = radio->registers[RDSB]; + break; + case 2: + bler = (radio->registers[READCHAN] & + READCHAN_BLERC) >> 12; + rds = radio->registers[RDSC]; + break; + case 3: + bler = (radio->registers[READCHAN] & + READCHAN_BLERD) >> 10; + rds = radio->registers[RDSD]; + break; + }; + + /* Fill the V4L2 RDS buffer */ + put_unaligned_le16(rds, &tmpbuf); + tmpbuf[2] = blocknum; /* offset name */ + tmpbuf[2] |= blocknum << 3; /* received offset */ + if (bler > max_rds_errors) + tmpbuf[2] |= 0x80; /* uncorrectable errors */ + else if (bler > 0) + tmpbuf[2] |= 0x40; /* corrected error(s) */ + + /* copy RDS block to internal buffer */ + memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3); + radio->wr_index += 3; + + /* wrap write pointer */ + if (radio->wr_index >= radio->buf_size) + radio->wr_index = 0; + + /* check for overflow */ + if (radio->wr_index == radio->rd_index) { + /* increment and wrap read pointer */ + radio->rd_index += 3; + if (radio->rd_index >= radio->buf_size) + radio->rd_index = 0; + } + } + if (radio->wr_index != radio->rd_index) + wake_up_interruptible(&radio->read_queue); + } + +resubmit: + /* Resubmit if we're still running. */ + if (radio->int_in_running && radio->usbdev) { + retval = usb_submit_urb(radio->int_in_urb, GFP_ATOMIC); + if (retval) { + printk(KERN_WARNING DRIVER_NAME + ": resubmitting urb failed (%d)", retval); + radio->int_in_running = 0; + } + } +} + + + +/************************************************************************** + * File Operations Interface + **************************************************************************/ + +/* + * si470x_fops_read - read RDS data + */ +static ssize_t si470x_fops_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + unsigned int block_count = 0; + + /* switch on rds reception */ + if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) + si470x_rds_on(radio); + + /* block if no new data available */ + while (radio->wr_index == radio->rd_index) { + if (file->f_flags & O_NONBLOCK) { + retval = -EWOULDBLOCK; + goto done; + } + if (wait_event_interruptible(radio->read_queue, + radio->wr_index != radio->rd_index) < 0) { + retval = -EINTR; + goto done; + } + } + + /* calculate block count from byte count */ + count /= 3; + + /* copy RDS block out of internal buffer and to user buffer */ + mutex_lock(&radio->lock); + while (block_count < count) { + if (radio->rd_index == radio->wr_index) + break; + + /* always transfer rds complete blocks */ + if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3)) + /* retval = -EFAULT; */ + break; + + /* increment and wrap read pointer */ + radio->rd_index += 3; + if (radio->rd_index >= radio->buf_size) + radio->rd_index = 0; + + /* increment counters */ + block_count++; + buf += 3; + retval += 3; + } + mutex_unlock(&radio->lock); + +done: + return retval; +} + + +/* + * si470x_fops_poll - poll RDS data + */ +static unsigned int si470x_fops_poll(struct file *file, + struct poll_table_struct *pts) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* switch on rds reception */ + if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) + si470x_rds_on(radio); + + poll_wait(file, &radio->read_queue, pts); + + if (radio->rd_index != radio->wr_index) + retval = POLLIN | POLLRDNORM; + + return retval; +} + + +/* + * si470x_fops_open - file open + */ +static int si470x_fops_open(struct file *file) +{ + struct si470x_device *radio = video_drvdata(file); + int retval; + + lock_kernel(); + radio->users++; + + retval = usb_autopm_get_interface(radio->intf); + if (retval < 0) { + radio->users--; + retval = -EIO; + goto done; + } + + if (radio->users == 1) { + /* start radio */ + retval = si470x_start(radio); + if (retval < 0) { + usb_autopm_put_interface(radio->intf); + goto done; + } + + /* initialize interrupt urb */ + usb_fill_int_urb(radio->int_in_urb, radio->usbdev, + usb_rcvintpipe(radio->usbdev, + radio->int_in_endpoint->bEndpointAddress), + radio->int_in_buffer, + le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize), + si470x_int_in_callback, + radio, + radio->int_in_endpoint->bInterval); + + radio->int_in_running = 1; + mb(); + + retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL); + if (retval) { + printk(KERN_INFO DRIVER_NAME + ": submitting int urb failed (%d)\n", retval); + radio->int_in_running = 0; + usb_autopm_put_interface(radio->intf); + } + } + +done: + unlock_kernel(); + return retval; +} + + +/* + * si470x_fops_release - file release + */ +static int si470x_fops_release(struct file *file) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety check */ + if (!radio) { + retval = -ENODEV; + goto done; + } + + mutex_lock(&radio->disconnect_lock); + radio->users--; + if (radio->users == 0) { + /* shutdown interrupt handler */ + if (radio->int_in_running) { + radio->int_in_running = 0; + if (radio->int_in_urb) + usb_kill_urb(radio->int_in_urb); + } + + if (radio->disconnected) { + video_unregister_device(radio->videodev); + kfree(radio->int_in_buffer); + kfree(radio->buffer); + kfree(radio); + goto unlock; + } + + /* cancel read processes */ + wake_up_interruptible(&radio->read_queue); + + /* stop radio */ + retval = si470x_stop(radio); + usb_autopm_put_interface(radio->intf); + } +unlock: + mutex_unlock(&radio->disconnect_lock); +done: + return retval; +} + + +/* + * si470x_fops - file operations interface + */ +const struct v4l2_file_operations si470x_fops = { + .owner = THIS_MODULE, + .read = si470x_fops_read, + .poll = si470x_fops_poll, + .ioctl = video_ioctl2, + .open = si470x_fops_open, + .release = si470x_fops_release, +}; + + + +/************************************************************************** + * Video4Linux Interface + **************************************************************************/ + +/* + * si470x_vidioc_querycap - query device capabilities + */ +int si470x_vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *capability) +{ + struct si470x_device *radio = video_drvdata(file); + + strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); + strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); + usb_make_path(radio->usbdev, capability->bus_info, + sizeof(capability->bus_info)); + capability->version = DRIVER_KERNEL_VERSION; + capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | + V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; + + return 0; +} + + + +/************************************************************************** + * USB Interface + **************************************************************************/ + +/* + * si470x_usb_driver_probe - probe for the device + */ +static int si470x_usb_driver_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct si470x_device *radio; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int i, int_end_size, retval = 0; + + /* private data allocation and initialization */ + radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); + if (!radio) { + retval = -ENOMEM; + goto err_initial; + } + radio->users = 0; + radio->disconnected = 0; + radio->usbdev = interface_to_usbdev(intf); + radio->intf = intf; + mutex_init(&radio->disconnect_lock); + mutex_init(&radio->lock); + + iface_desc = intf->cur_altsetting; + + /* Set up interrupt endpoint information. */ + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == + USB_DIR_IN) && ((endpoint->bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) + radio->int_in_endpoint = endpoint; + } + if (!radio->int_in_endpoint) { + printk(KERN_INFO DRIVER_NAME + ": could not find interrupt in endpoint\n"); + retval = -EIO; + goto err_radio; + } + + int_end_size = le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize); + + radio->int_in_buffer = kmalloc(int_end_size, GFP_KERNEL); + if (!radio->int_in_buffer) { + printk(KERN_INFO DRIVER_NAME + "could not allocate int_in_buffer"); + retval = -ENOMEM; + goto err_radio; + } + + radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!radio->int_in_urb) { + printk(KERN_INFO DRIVER_NAME "could not allocate int_in_urb"); + retval = -ENOMEM; + goto err_intbuffer; + } + + /* video device allocation and initialization */ + radio->videodev = video_device_alloc(); + if (!radio->videodev) { + retval = -ENOMEM; + goto err_intbuffer; + } + memcpy(radio->videodev, &si470x_viddev_template, + sizeof(si470x_viddev_template)); + video_set_drvdata(radio->videodev, radio); + + /* show some infos about the specific si470x device */ + if (si470x_get_all_registers(radio) < 0) { + retval = -EIO; + goto err_video; + } + printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", + radio->registers[DEVICEID], radio->registers[CHIPID]); + + /* get software and hardware versions */ + if (si470x_get_scratch_page_versions(radio) < 0) { + retval = -EIO; + goto err_video; + } + printk(KERN_INFO DRIVER_NAME + ": software version %d, hardware version %d\n", + radio->software_version, radio->hardware_version); + + /* check if device and firmware is current */ + if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) + < RADIO_SW_VERSION_CURRENT) { + printk(KERN_WARNING DRIVER_NAME + ": This driver is known to work with " + "firmware version %hu,\n", RADIO_SW_VERSION_CURRENT); + printk(KERN_WARNING DRIVER_NAME + ": but the device has firmware version %hu.\n", + radio->registers[CHIPID] & CHIPID_FIRMWARE); + printk(KERN_WARNING DRIVER_NAME + ": If you have some trouble using this driver,\n"); + printk(KERN_WARNING DRIVER_NAME + ": please report to V4L ML at " + "linux-media@vger.kernel.org\n"); + } + + /* set initial frequency */ + si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ + + /* set led to connect state */ + si470x_set_led_state(radio, BLINK_GREEN_LED); + + /* rds buffer allocation */ + radio->buf_size = rds_buf * 3; + radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); + if (!radio->buffer) { + retval = -EIO; + goto err_video; + } + + /* rds buffer configuration */ + radio->wr_index = 0; + radio->rd_index = 0; + init_waitqueue_head(&radio->read_queue); + + /* register video device */ + retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, + radio_nr); + if (retval) { + printk(KERN_WARNING DRIVER_NAME + ": Could not register video device\n"); + goto err_all; + } + usb_set_intfdata(intf, radio); + + return 0; +err_all: + kfree(radio->buffer); +err_video: + video_device_release(radio->videodev); +err_intbuffer: + kfree(radio->int_in_buffer); +err_radio: + kfree(radio); +err_initial: + return retval; +} + + +/* + * si470x_usb_driver_suspend - suspend the device + */ +static int si470x_usb_driver_suspend(struct usb_interface *intf, + pm_message_t message) +{ + printk(KERN_INFO DRIVER_NAME ": suspending now...\n"); + + return 0; +} + + +/* + * si470x_usb_driver_resume - resume the device + */ +static int si470x_usb_driver_resume(struct usb_interface *intf) +{ + printk(KERN_INFO DRIVER_NAME ": resuming now...\n"); + + return 0; +} + + +/* + * si470x_usb_driver_disconnect - disconnect the device + */ +static void si470x_usb_driver_disconnect(struct usb_interface *intf) +{ + struct si470x_device *radio = usb_get_intfdata(intf); + + mutex_lock(&radio->disconnect_lock); + radio->disconnected = 1; + usb_set_intfdata(intf, NULL); + if (radio->users == 0) { + /* set led to disconnect state */ + si470x_set_led_state(radio, BLINK_ORANGE_LED); + + /* Free data structures. */ + usb_free_urb(radio->int_in_urb); + + kfree(radio->int_in_buffer); + video_unregister_device(radio->videodev); + kfree(radio->buffer); + kfree(radio); + } + mutex_unlock(&radio->disconnect_lock); +} + + +/* + * si470x_usb_driver - usb driver interface + */ +static struct usb_driver si470x_usb_driver = { + .name = DRIVER_NAME, + .probe = si470x_usb_driver_probe, + .disconnect = si470x_usb_driver_disconnect, + .suspend = si470x_usb_driver_suspend, + .resume = si470x_usb_driver_resume, + .id_table = si470x_usb_driver_id_table, + .supports_autosuspend = 1, +}; + + + +/************************************************************************** + * Module Interface + **************************************************************************/ + +/* + * si470x_module_init - module init + */ +static int __init si470x_module_init(void) +{ + printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); + return usb_register(&si470x_usb_driver); +} + + +/* + * si470x_module_exit - module exit + */ +static void __exit si470x_module_exit(void) +{ + usb_deregister(&si470x_usb_driver); +} + + +module_init(si470x_module_init); +module_exit(si470x_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); diff --git a/linux/drivers/media/radio/si470x/radio-si470x.h b/linux/drivers/media/radio/si470x/radio-si470x.h new file mode 100644 index 000000000..88d3ebbe2 --- /dev/null +++ b/linux/drivers/media/radio/si470x/radio-si470x.h @@ -0,0 +1,202 @@ +/* + * drivers/media/radio/si470x/radio-si470x.h + * + * Driver for radios with Silicon Labs Si470x FM Radio Receivers + * + * Copyright (c) 2009 Tobias Lorenz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* driver definitions */ +#define DRIVER_NAME "radio-si470x" + + +/* kernel includes */ +#include +#include +#include +#include +#include +#include +#include +#include "compat.h" +#include +#include +#include +#include +#include +#include + + +/************************************************************************** + * Register Definitions + **************************************************************************/ +#define RADIO_REGISTER_SIZE 2 /* 16 register bit width */ +#define RADIO_REGISTER_NUM 16 /* DEVICEID ... RDSD */ +#define RDS_REGISTER_NUM 6 /* STATUSRSSI ... RDSD */ + +#define DEVICEID 0 /* Device ID */ +#define DEVICEID_PN 0xf000 /* bits 15..12: Part Number */ +#define DEVICEID_MFGID 0x0fff /* bits 11..00: Manufacturer ID */ + +#define CHIPID 1 /* Chip ID */ +#define CHIPID_REV 0xfc00 /* bits 15..10: Chip Version */ +#define CHIPID_DEV 0x0200 /* bits 09..09: Device */ +#define CHIPID_FIRMWARE 0x01ff /* bits 08..00: Firmware Version */ + +#define POWERCFG 2 /* Power Configuration */ +#define POWERCFG_DSMUTE 0x8000 /* bits 15..15: Softmute Disable */ +#define POWERCFG_DMUTE 0x4000 /* bits 14..14: Mute Disable */ +#define POWERCFG_MONO 0x2000 /* bits 13..13: Mono Select */ +#define POWERCFG_RDSM 0x0800 /* bits 11..11: RDS Mode (Si4701 only) */ +#define POWERCFG_SKMODE 0x0400 /* bits 10..10: Seek Mode */ +#define POWERCFG_SEEKUP 0x0200 /* bits 09..09: Seek Direction */ +#define POWERCFG_SEEK 0x0100 /* bits 08..08: Seek */ +#define POWERCFG_DISABLE 0x0040 /* bits 06..06: Powerup Disable */ +#define POWERCFG_ENABLE 0x0001 /* bits 00..00: Powerup Enable */ + +#define CHANNEL 3 /* Channel */ +#define CHANNEL_TUNE 0x8000 /* bits 15..15: Tune */ +#define CHANNEL_CHAN 0x03ff /* bits 09..00: Channel Select */ + +#define SYSCONFIG1 4 /* System Configuration 1 */ +#define SYSCONFIG1_RDSIEN 0x8000 /* bits 15..15: RDS Interrupt Enable (Si4701 only) */ +#define SYSCONFIG1_STCIEN 0x4000 /* bits 14..14: Seek/Tune Complete Interrupt Enable */ +#define SYSCONFIG1_RDS 0x1000 /* bits 12..12: RDS Enable (Si4701 only) */ +#define SYSCONFIG1_DE 0x0800 /* bits 11..11: De-emphasis (0=75us 1=50us) */ +#define SYSCONFIG1_AGCD 0x0400 /* bits 10..10: AGC Disable */ +#define SYSCONFIG1_BLNDADJ 0x00c0 /* bits 07..06: Stereo/Mono Blend Level Adjustment */ +#define SYSCONFIG1_GPIO3 0x0030 /* bits 05..04: General Purpose I/O 3 */ +#define SYSCONFIG1_GPIO2 0x000c /* bits 03..02: General Purpose I/O 2 */ +#define SYSCONFIG1_GPIO1 0x0003 /* bits 01..00: General Purpose I/O 1 */ + +#define SYSCONFIG2 5 /* System Configuration 2 */ +#define SYSCONFIG2_SEEKTH 0xff00 /* bits 15..08: RSSI Seek Threshold */ +#define SYSCONFIG2_BAND 0x0080 /* bits 07..06: Band Select */ +#define SYSCONFIG2_SPACE 0x0030 /* bits 05..04: Channel Spacing */ +#define SYSCONFIG2_VOLUME 0x000f /* bits 03..00: Volume */ + +#define SYSCONFIG3 6 /* System Configuration 3 */ +#define SYSCONFIG3_SMUTER 0xc000 /* bits 15..14: Softmute Attack/Recover Rate */ +#define SYSCONFIG3_SMUTEA 0x3000 /* bits 13..12: Softmute Attenuation */ +#define SYSCONFIG3_SKSNR 0x00f0 /* bits 07..04: Seek SNR Threshold */ +#define SYSCONFIG3_SKCNT 0x000f /* bits 03..00: Seek FM Impulse Detection Threshold */ + +#define TEST1 7 /* Test 1 */ +#define TEST1_AHIZEN 0x4000 /* bits 14..14: Audio High-Z Enable */ + +#define TEST2 8 /* Test 2 */ +/* TEST2 only contains reserved bits */ + +#define BOOTCONFIG 9 /* Boot Configuration */ +/* BOOTCONFIG only contains reserved bits */ + +#define STATUSRSSI 10 /* Status RSSI */ +#define STATUSRSSI_RDSR 0x8000 /* bits 15..15: RDS Ready (Si4701 only) */ +#define STATUSRSSI_STC 0x4000 /* bits 14..14: Seek/Tune Complete */ +#define STATUSRSSI_SF 0x2000 /* bits 13..13: Seek Fail/Band Limit */ +#define STATUSRSSI_AFCRL 0x1000 /* bits 12..12: AFC Rail */ +#define STATUSRSSI_RDSS 0x0800 /* bits 11..11: RDS Synchronized (Si4701 only) */ +#define STATUSRSSI_BLERA 0x0600 /* bits 10..09: RDS Block A Errors (Si4701 only) */ +#define STATUSRSSI_ST 0x0100 /* bits 08..08: Stereo Indicator */ +#define STATUSRSSI_RSSI 0x00ff /* bits 07..00: RSSI (Received Signal Strength Indicator) */ + +#define READCHAN 11 /* Read Channel */ +#define READCHAN_BLERB 0xc000 /* bits 15..14: RDS Block D Errors (Si4701 only) */ +#define READCHAN_BLERC 0x3000 /* bits 13..12: RDS Block C Errors (Si4701 only) */ +#define READCHAN_BLERD 0x0c00 /* bits 11..10: RDS Block B Errors (Si4701 only) */ +#define READCHAN_READCHAN 0x03ff /* bits 09..00: Read Channel */ + +#define RDSA 12 /* RDSA */ +#define RDSA_RDSA 0xffff /* bits 15..00: RDS Block A Data (Si4701 only) */ + +#define RDSB 13 /* RDSB */ +#define RDSB_RDSB 0xffff /* bits 15..00: RDS Block B Data (Si4701 only) */ + +#define RDSC 14 /* RDSC */ +#define RDSC_RDSC 0xffff /* bits 15..00: RDS Block C Data (Si4701 only) */ + +#define RDSD 15 /* RDSD */ +#define RDSD_RDSD 0xffff /* bits 15..00: RDS Block D Data (Si4701 only) */ + + +/************************************************************************** + * General Driver Definitions + **************************************************************************/ + +/* + * si470x_device - private data + */ +struct si470x_device { + struct video_device *videodev; + + /* reference to USB and video device */ + struct usb_device *usbdev; + struct usb_interface *intf; + + /* Interrupt endpoint handling */ + char *int_in_buffer; + struct usb_endpoint_descriptor *int_in_endpoint; + struct urb *int_in_urb; + int int_in_running; + + /* scratch page */ + unsigned char software_version; + unsigned char hardware_version; + + /* driver management */ + unsigned char disconnected; + struct mutex disconnect_lock; + unsigned int users; + + /* Silabs internal registers (0..15) */ + unsigned short registers[RADIO_REGISTER_NUM]; + + /* RDS receive buffer */ + wait_queue_head_t read_queue; + struct mutex lock; /* buffer locking */ + unsigned char *buffer; /* size is always multiple of three */ + unsigned int buf_size; + unsigned int rd_index; + unsigned int wr_index; +}; + + +/* + * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, + * 62.5 kHz otherwise. + * The tuner is able to have a channel spacing of 50, 100 or 200 kHz. + * tuner->capability is therefore set to V4L2_TUNER_CAP_LOW + * The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000 + */ +#define FREQ_MUL (1000000 / 62.5) + + + +/************************************************************************** + * Common Functions + **************************************************************************/ +extern const struct v4l2_file_operations si470x_fops; +extern struct video_device si470x_viddev_template; +int si470x_get_register(struct si470x_device *radio, int regnr); +int si470x_set_register(struct si470x_device *radio, int regnr); +int si470x_set_freq(struct si470x_device *radio, unsigned int freq); +int si470x_start(struct si470x_device *radio); +int si470x_stop(struct si470x_device *radio); +int si470x_rds_on(struct si470x_device *radio); +int si470x_vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *capability); -- cgit v1.2.3 From 951be4abc87f0caf46aba5d23981a83c323deda2 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 9 Aug 2009 19:22:41 +0200 Subject: radio-si470x: change to dev_* macro from printk This patch is for using dev_* macro instead of printk. Signed-off-by: Joonyoung Shim Acked-by: Tobias Lorenz --- .../media/radio/si470x/radio-si470x-common.c | 50 +++++++++--------- .../drivers/media/radio/si470x/radio-si470x-usb.c | 58 +++++++++----------- 2 files changed, 52 insertions(+), 56 deletions(-) --- .../media/radio/si470x/radio-si470x-common.c | 50 +++++++++---------- .../drivers/media/radio/si470x/radio-si470x-usb.c | 58 ++++++++++------------ 2 files changed, 52 insertions(+), 56 deletions(-) diff --git a/linux/drivers/media/radio/si470x/radio-si470x-common.c b/linux/drivers/media/radio/si470x/radio-si470x-common.c index b64559d56..fd9fc4aa8 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-common.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-common.c @@ -184,10 +184,10 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && (!timed_out)); if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) - printk(KERN_WARNING DRIVER_NAME ": tune does not complete\n"); + dev_warn(&radio->videodev->dev, "tune does not complete\n"); if (timed_out) - printk(KERN_WARNING DRIVER_NAME - ": tune timed out after %u ms\n", tune_timeout); + dev_warn(&radio->videodev->dev, + "tune timed out after %u ms\n", tune_timeout); stop: /* stop tuning */ @@ -320,13 +320,13 @@ static int si470x_set_seek(struct si470x_device *radio, } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && (!timed_out)); if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) - printk(KERN_WARNING DRIVER_NAME ": seek does not complete\n"); + dev_warn(&radio->videodev->dev, "seek does not complete\n"); if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) - printk(KERN_WARNING DRIVER_NAME - ": seek failed / band limit reached\n"); + dev_warn(&radio->videodev->dev, + "seek failed / band limit reached\n"); if (timed_out) - printk(KERN_WARNING DRIVER_NAME - ": seek timed out after %u ms\n", seek_timeout); + dev_warn(&radio->videodev->dev, + "seek timed out after %u ms\n", seek_timeout); stop: /* stop seeking */ @@ -435,6 +435,7 @@ int si470x_rds_on(struct si470x_device *radio) static int si470x_vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { + struct si470x_device *radio = video_drvdata(file); int retval = -EINVAL; /* abort if qc->id is below V4L2_CID_BASE */ @@ -458,8 +459,8 @@ static int si470x_vidioc_queryctrl(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": query controls failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "query controls failed with %d\n", retval); return retval; } @@ -494,8 +495,8 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get control failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "get control failed with %d\n", retval); return retval; } @@ -534,8 +535,8 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set control failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "set control failed with %d\n", retval); return retval; } @@ -632,8 +633,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get tuner failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "get tuner failed with %d\n", retval); return retval; } @@ -671,8 +672,8 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set tuner failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "set tuner failed with %d\n", retval); return retval; } @@ -701,8 +702,8 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get frequency failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "get frequency failed with %d\n", retval); return retval; } @@ -730,8 +731,8 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set frequency failed with %d\n", retval); + dev_warn(&radio->videodev->dev, + "set frequency failed with %d\n", retval); return retval; } @@ -759,9 +760,8 @@ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, done: if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set hardware frequency seek failed with %d\n", - retval); + dev_warn(&radio->videodev->dev, + "set hardware frequency seek failed with %d\n", retval); return retval; } diff --git a/linux/drivers/media/radio/si470x/radio-si470x-usb.c b/linux/drivers/media/radio/si470x/radio-si470x-usb.c index f3d805f70..650816140 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-usb.c @@ -223,8 +223,8 @@ static int si470x_get_report(struct si470x_device *radio, void *buf, int size) buf, size, usb_timeout); if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": si470x_get_report: usb_control_msg returned %d\n", + dev_warn(&radio->intf->dev, + "si470x_get_report: usb_control_msg returned %d\n", retval); return retval; } @@ -246,8 +246,8 @@ static int si470x_set_report(struct si470x_device *radio, void *buf, int size) buf, size, usb_timeout); if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": si470x_set_report: usb_control_msg returned %d\n", + dev_warn(&radio->intf->dev, + "si470x_set_report: usb_control_msg returned %d\n", retval); return retval; } @@ -358,7 +358,7 @@ static int si470x_get_scratch_page_versions(struct si470x_device *radio) retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); if (retval < 0) - printk(KERN_WARNING DRIVER_NAME ": si470x_get_scratch: " + dev_warn(&radio->intf->dev, "si470x_get_scratch: " "si470x_get_report returned %d\n", retval); else { radio->software_version = buf[1]; @@ -396,8 +396,8 @@ static void si470x_int_in_callback(struct urb *urb) urb->status == -ESHUTDOWN) { return; } else { - printk(KERN_WARNING DRIVER_NAME - ": non-zero urb status (%d)\n", urb->status); + dev_warn(&radio->intf->dev, + "non-zero urb status (%d)\n", urb->status); goto resubmit; /* Maybe we can recover. */ } } @@ -482,8 +482,8 @@ resubmit: if (radio->int_in_running && radio->usbdev) { retval = usb_submit_urb(radio->int_in_urb, GFP_ATOMIC); if (retval) { - printk(KERN_WARNING DRIVER_NAME - ": resubmitting urb failed (%d)", retval); + dev_warn(&radio->intf->dev, + "resubmitting urb failed (%d)", retval); radio->int_in_running = 0; } } @@ -616,8 +616,8 @@ static int si470x_fops_open(struct file *file) retval = usb_submit_urb(radio->int_in_urb, GFP_KERNEL); if (retval) { - printk(KERN_INFO DRIVER_NAME - ": submitting int urb failed (%d)\n", retval); + dev_info(&radio->intf->dev, + "submitting int urb failed (%d)\n", retval); radio->int_in_running = 0; usb_autopm_put_interface(radio->intf); } @@ -753,8 +753,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, radio->int_in_endpoint = endpoint; } if (!radio->int_in_endpoint) { - printk(KERN_INFO DRIVER_NAME - ": could not find interrupt in endpoint\n"); + dev_info(&intf->dev, "could not find interrupt in endpoint\n"); retval = -EIO; goto err_radio; } @@ -763,15 +762,14 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, radio->int_in_buffer = kmalloc(int_end_size, GFP_KERNEL); if (!radio->int_in_buffer) { - printk(KERN_INFO DRIVER_NAME - "could not allocate int_in_buffer"); + dev_info(&intf->dev, "could not allocate int_in_buffer"); retval = -ENOMEM; goto err_radio; } radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); if (!radio->int_in_urb) { - printk(KERN_INFO DRIVER_NAME "could not allocate int_in_urb"); + dev_info(&intf->dev, "could not allocate int_in_urb"); retval = -ENOMEM; goto err_intbuffer; } @@ -791,7 +789,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, retval = -EIO; goto err_video; } - printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", + dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", radio->registers[DEVICEID], radio->registers[CHIPID]); /* get software and hardware versions */ @@ -799,23 +797,22 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, retval = -EIO; goto err_video; } - printk(KERN_INFO DRIVER_NAME - ": software version %d, hardware version %d\n", + dev_info(&intf->dev, "software version %d, hardware version %d\n", radio->software_version, radio->hardware_version); /* check if device and firmware is current */ if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_SW_VERSION_CURRENT) { - printk(KERN_WARNING DRIVER_NAME - ": This driver is known to work with " + dev_warn(&intf->dev, + "This driver is known to work with " "firmware version %hu,\n", RADIO_SW_VERSION_CURRENT); - printk(KERN_WARNING DRIVER_NAME - ": but the device has firmware version %hu.\n", + dev_warn(&intf->dev, + "but the device has firmware version %hu.\n", radio->registers[CHIPID] & CHIPID_FIRMWARE); - printk(KERN_WARNING DRIVER_NAME - ": If you have some trouble using this driver,\n"); - printk(KERN_WARNING DRIVER_NAME - ": please report to V4L ML at " + dev_warn(&intf->dev, + "If you have some trouble using this driver,\n"); + dev_warn(&intf->dev, + "please report to V4L ML at " "linux-media@vger.kernel.org\n"); } @@ -842,8 +839,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); if (retval) { - printk(KERN_WARNING DRIVER_NAME - ": Could not register video device\n"); + dev_warn(&intf->dev, "Could not register video device\n"); goto err_all; } usb_set_intfdata(intf, radio); @@ -868,7 +864,7 @@ err_initial: static int si470x_usb_driver_suspend(struct usb_interface *intf, pm_message_t message) { - printk(KERN_INFO DRIVER_NAME ": suspending now...\n"); + dev_info(&intf->dev, "suspending now...\n"); return 0; } @@ -879,7 +875,7 @@ static int si470x_usb_driver_suspend(struct usb_interface *intf, */ static int si470x_usb_driver_resume(struct usb_interface *intf) { - printk(KERN_INFO DRIVER_NAME ": resuming now...\n"); + dev_info(&intf->dev, "resuming now...\n"); return 0; } -- cgit v1.2.3 From edce5773436aeaa6d195d1db0cc80f4c10a7acf1 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 9 Aug 2009 19:23:02 +0200 Subject: radio-si470x: add disconnect check function The si470x_disconnect_check is function to check disconnect state of radio in common file. The function is implemented in each interface file. Signed-off-by: Joonyoung Shim Acked-by: Tobias Lorenz --- .../media/radio/si470x/radio-si470x-common.c | 40 +++++++++---------- .../drivers/media/radio/si470x/radio-si470x-usb.c | 17 ++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 1 + 3 files changed, 37 insertions(+), 21 deletions(-) --- .../media/radio/si470x/radio-si470x-common.c | 40 ++++++++++------------ .../drivers/media/radio/si470x/radio-si470x-usb.c | 17 +++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 1 + 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/linux/drivers/media/radio/si470x/radio-si470x-common.c b/linux/drivers/media/radio/si470x/radio-si470x-common.c index fd9fc4aa8..9f9a417ca 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-common.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-common.c @@ -475,10 +475,9 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: @@ -511,10 +510,9 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: @@ -567,10 +565,10 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } + if (tuner->index != 0) { retval = -EINVAL; goto done; @@ -649,10 +647,10 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv, int retval = -EINVAL; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } + if (tuner->index != 0) goto done; @@ -688,10 +686,10 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } + if (freq->tuner != 0) { retval = -EINVAL; goto done; @@ -718,10 +716,10 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } + if (freq->tuner != 0) { retval = -EINVAL; goto done; @@ -747,10 +745,10 @@ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, int retval = 0; /* safety checks */ - if (radio->disconnected) { - retval = -EIO; + retval = si470x_disconnect_check(radio); + if (retval) goto done; - } + if (seek->tuner != 0) { retval = -EINVAL; goto done; diff --git a/linux/drivers/media/radio/si470x/radio-si470x-usb.c b/linux/drivers/media/radio/si470x/radio-si470x-usb.c index 650816140..2f5cf6c72 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-usb.c @@ -370,6 +370,23 @@ static int si470x_get_scratch_page_versions(struct si470x_device *radio) +/************************************************************************** + * General Driver Functions - DISCONNECT_CHECK + **************************************************************************/ + +/* + * si470x_disconnect_check - check whether radio disconnects + */ +int si470x_disconnect_check(struct si470x_device *radio) +{ + if (radio->disconnected) + return -EIO; + else + return 0; +} + + + /************************************************************************** * RDS Driver Functions **************************************************************************/ diff --git a/linux/drivers/media/radio/si470x/radio-si470x.h b/linux/drivers/media/radio/si470x/radio-si470x.h index 88d3ebbe2..eb36b6451 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x.h +++ b/linux/drivers/media/radio/si470x/radio-si470x.h @@ -194,6 +194,7 @@ extern const struct v4l2_file_operations si470x_fops; extern struct video_device si470x_viddev_template; int si470x_get_register(struct si470x_device *radio, int regnr); int si470x_set_register(struct si470x_device *radio, int regnr); +int si470x_disconnect_check(struct si470x_device *radio); int si470x_set_freq(struct si470x_device *radio, unsigned int freq); int si470x_start(struct si470x_device *radio); int si470x_stop(struct si470x_device *radio); -- cgit v1.2.3 From b17608ffc4ff53dbf7bab4bbcdb1d3ad808e9ff0 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 9 Aug 2009 19:23:35 +0200 Subject: radio-si470x: add i2c driver for si470x This patch supports i2c interface of si470x. The i2c specific part exists in radio-si470x-i2c.c file and the common part uses radio-si470x-common.c file. The '#if defined' is inserted inevitably because of parts used only si470x usb in the common file. The current driver version doesn't support the RDS. Signed-off-by: Joonyoung Shim Acked-by: Tobias Lorenz --- linux/drivers/media/radio/si470x/Kconfig | 13 + linux/drivers/media/radio/si470x/Makefile | 2 + .../media/radio/si470x/radio-si470x-common.c | 6 + .../drivers/media/radio/si470x/radio-si470x-i2c.c | 254 ++++++++++++++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 6 + 5 files changed, 281 insertions(+), 0 deletions(-) create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-i2c.c --- linux/drivers/media/radio/si470x/Kconfig | 13 ++ linux/drivers/media/radio/si470x/Makefile | 2 + .../media/radio/si470x/radio-si470x-common.c | 6 + .../drivers/media/radio/si470x/radio-si470x-i2c.c | 254 +++++++++++++++++++++ linux/drivers/media/radio/si470x/radio-si470x.h | 6 + 5 files changed, 281 insertions(+) create mode 100644 linux/drivers/media/radio/si470x/radio-si470x-i2c.c diff --git a/linux/drivers/media/radio/si470x/Kconfig b/linux/drivers/media/radio/si470x/Kconfig index 20d05c04f..a466654ee 100644 --- a/linux/drivers/media/radio/si470x/Kconfig +++ b/linux/drivers/media/radio/si470x/Kconfig @@ -22,3 +22,16 @@ config USB_SI470X To compile this driver as a module, choose M here: the module will be called radio-usb-si470x. + +config I2C_SI470X + tristate "Silicon Labs Si470x FM Radio Receiver support with I2C" + depends on I2C && RADIO_SI470X && !USB_SI470X + ---help--- + This is a driver for I2C devices with the Silicon Labs SI470x + chip. + + Say Y here if you want to connect this type of radio to your + computer's I2C port. + + To compile this driver as a module, choose M here: the + module will be called radio-i2c-si470x. diff --git a/linux/drivers/media/radio/si470x/Makefile b/linux/drivers/media/radio/si470x/Makefile index 3cb777fe3..06964816c 100644 --- a/linux/drivers/media/radio/si470x/Makefile +++ b/linux/drivers/media/radio/si470x/Makefile @@ -3,5 +3,7 @@ # radio-usb-si470x-objs := radio-si470x-usb.o radio-si470x-common.o +radio-i2c-si470x-objs := radio-si470x-i2c.o radio-si470x-common.o obj-$(CONFIG_USB_SI470X) += radio-usb-si470x.o +obj-$(CONFIG_I2C_SI470X) += radio-i2c-si470x.o diff --git a/linux/drivers/media/radio/si470x/radio-si470x-common.c b/linux/drivers/media/radio/si470x/radio-si470x-common.c index 9f9a417ca..f33315f2c 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-common.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-common.c @@ -581,8 +581,12 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, /* driver constants */ strcpy(tuner->name, "FM"); tuner->type = V4L2_TUNER_RADIO; +#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS; +#else + tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; +#endif /* range limits */ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { @@ -608,10 +612,12 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, tuner->rxsubchans = V4L2_TUNER_SUB_MONO; else tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; +#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) /* If there is a reliable method of detecting an RDS channel, then this code should check for that before setting this RDS subchannel. */ tuner->rxsubchans |= V4L2_TUNER_SUB_RDS; +#endif /* mono/stereo selector */ if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0) diff --git a/linux/drivers/media/radio/si470x/radio-si470x-i2c.c b/linux/drivers/media/radio/si470x/radio-si470x-i2c.c new file mode 100644 index 000000000..218102184 --- /dev/null +++ b/linux/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -0,0 +1,254 @@ +/* + * drivers/media/radio/si470x/radio-si470x-i2c.c + * + * I2C driver for radios with Silicon Labs Si470x FM Radio Receivers + * + * Copyright (C) 2009 Samsung Electronics Co.Ltd + * Author: Joonyoung Shim + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * + * TODO: + * - RDS support + * + */ + +#include +#include +#include +#include + +#include "radio-si470x.h" + +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0) +#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" +#define DRIVER_VERSION "1.0.0" + +/* starting with the upper byte of register 0x0a */ +#define READ_REG_NUM RADIO_REGISTER_NUM +#define READ_INDEX(i) ((i + RADIO_REGISTER_NUM - 0x0a) % READ_REG_NUM) + +static int si470x_get_all_registers(struct si470x_device *radio) +{ + int i; + u16 buf[READ_REG_NUM]; + struct i2c_msg msgs[1] = { + { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, + (void *)buf }, + }; + + if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) + return -EIO; + + for (i = 0; i < READ_REG_NUM; i++) + radio->registers[i] = __be16_to_cpu(buf[READ_INDEX(i)]); + + return 0; +} + +int si470x_get_register(struct si470x_device *radio, int regnr) +{ + u16 buf[READ_REG_NUM]; + struct i2c_msg msgs[1] = { + { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, + (void *)buf }, + }; + + if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) + return -EIO; + + radio->registers[regnr] = __be16_to_cpu(buf[READ_INDEX(regnr)]); + + return 0; +} + +/* starting with the upper byte of register 0x02h */ +#define WRITE_REG_NUM 8 +#define WRITE_INDEX(i) (i + 0x02) + +int si470x_set_register(struct si470x_device *radio, int regnr) +{ + int i; + u16 buf[WRITE_REG_NUM]; + struct i2c_msg msgs[1] = { + { radio->client->addr, 0, sizeof(u16) * WRITE_REG_NUM, + (void *)buf }, + }; + + for (i = 0; i < WRITE_REG_NUM; i++) + buf[i] = __cpu_to_be16(radio->registers[WRITE_INDEX(i)]); + + if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) + return -EIO; + + return 0; +} + +int si470x_disconnect_check(struct si470x_device *radio) +{ + return 0; +} + +static int si470x_fops_open(struct file *file) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + mutex_lock(&radio->lock); + radio->users++; + + if (radio->users == 1) + /* start radio */ + retval = si470x_start(radio); + mutex_unlock(&radio->lock); + + return retval; +} + +static int si470x_fops_release(struct file *file) +{ + struct si470x_device *radio = video_drvdata(file); + int retval = 0; + + /* safety check */ + if (!radio) + return -ENODEV; + + mutex_lock(&radio->lock); + radio->users--; + if (radio->users == 0) + /* stop radio */ + retval = si470x_stop(radio); + mutex_unlock(&radio->lock); + + return retval; +} + +const struct v4l2_file_operations si470x_fops = { + .owner = THIS_MODULE, + .ioctl = video_ioctl2, + .open = si470x_fops_open, + .release = si470x_fops_release, +}; + +int si470x_vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *capability) +{ + strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); + strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); + capability->version = DRIVER_KERNEL_VERSION; + capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | + V4L2_CAP_TUNER | V4L2_CAP_RADIO; + + return 0; +} + +static int __devinit si470x_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct si470x_device *radio; + int retval = 0; + + /* private data allocation and initialization */ + radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); + if (!radio) { + retval = -ENOMEM; + goto err_initial; + } + radio->client = client; + radio->users = 0; + mutex_init(&radio->lock); + + /* video device allocation and initialization */ + radio->videodev = video_device_alloc(); + if (!radio->videodev) { + retval = -ENOMEM; + goto err_radio; + } + memcpy(radio->videodev, &si470x_viddev_template, + sizeof(si470x_viddev_template)); + video_set_drvdata(radio->videodev, radio); + + /* power up : need 110ms */ + radio->registers[POWERCFG] = POWERCFG_ENABLE; + if (si470x_set_register(radio, POWERCFG) < 0) { + retval = -EIO; + goto err_all; + } + msleep(110); + + /* show some infos about the specific si470x device */ + if (si470x_get_all_registers(radio) < 0) { + retval = -EIO; + goto err_radio; + } + dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", + radio->registers[DEVICEID], radio->registers[CHIPID]); + + /* set initial frequency */ + si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ + + /* register video device */ + retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, -1); + if (retval) { + dev_warn(&client->dev, "Could not register video device\n"); + goto err_all; + } + + i2c_set_clientdata(client, radio); + + return 0; +err_all: + video_device_release(radio->videodev); +err_radio: + kfree(radio); +err_initial: + return retval; +} + +static __devexit int si470x_i2c_remove(struct i2c_client *client) +{ + struct si470x_device *radio = i2c_get_clientdata(client); + + video_unregister_device(radio->videodev); + kfree(radio); + i2c_set_clientdata(client, NULL); + + return 0; +} + +static const struct i2c_device_id si470x_i2c_id[] = { + { "si470x", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, si470x_i2c_id); + +static struct i2c_driver si470x_i2c_driver = { + .driver = { + .name = "si470x", + .owner = THIS_MODULE, + }, + .probe = si470x_i2c_probe, + .remove = __devexit_p(si470x_i2c_remove), + .id_table = si470x_i2c_id, +}; + +static int __init si470x_i2c_init(void) +{ + return i2c_add_driver(&si470x_i2c_driver); +} +module_init(si470x_i2c_init); + +static void __exit si470x_i2c_exit(void) +{ + i2c_del_driver(&si470x_i2c_driver); +} +module_exit(si470x_i2c_exit); + +MODULE_DESCRIPTION("i2c radio driver for si470x fm radio receivers"); +MODULE_AUTHOR("Joonyoung Shim "); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/radio/si470x/radio-si470x.h b/linux/drivers/media/radio/si470x/radio-si470x.h index eb36b6451..791c367be 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x.h +++ b/linux/drivers/media/radio/si470x/radio-si470x.h @@ -144,6 +144,11 @@ struct si470x_device { struct video_device *videodev; +#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) + struct i2c_client *client; +#endif + +#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) /* reference to USB and video device */ struct usb_device *usbdev; struct usb_interface *intf; @@ -161,6 +166,7 @@ struct si470x_device { /* driver management */ unsigned char disconnected; struct mutex disconnect_lock; +#endif unsigned int users; /* Silabs internal registers (0..15) */ -- cgit v1.2.3 From 4a8acba072fef7a5126e7193667e6b0746555606 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 9 Aug 2009 19:39:23 -0300 Subject: em28xx: Implement g/s_register via address match From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 77ec51dad..c7d723a03 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1342,8 +1342,9 @@ static int vidioc_g_register(struct file *file, void *priv, v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: - /* Not supported yet */ - return -EINVAL; + /* TODO: is this correct? */ + v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); + return 0; default: if (!v4l2_chip_match_host(®->match)) return -EINVAL; @@ -1394,8 +1395,9 @@ static int vidioc_s_register(struct file *file, void *priv, v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); return 0; case V4L2_CHIP_MATCH_I2C_ADDR: - /* Not supported yet */ - return -EINVAL; + /* TODO: is this correct? */ + v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); + return 0; default: if (!v4l2_chip_match_host(®->match)) return -EINVAL; -- cgit v1.2.3 From c3f9323429d06d88d8986100746bebe48c6b7097 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 9 Aug 2009 19:58:14 -0300 Subject: v4l2-dbg: Add register maps for mt9v011 From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-dbg-micron.h | 46 ++++++++++++++++++++++++++++++++++++++++ v4l2-apps/util/v4l2-dbg.cpp | 19 ++++++++++++----- 2 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 v4l2-apps/util/v4l2-dbg-micron.h diff --git a/v4l2-apps/util/v4l2-dbg-micron.h b/v4l2-apps/util/v4l2-dbg-micron.h new file mode 100644 index 000000000..8466322bf --- /dev/null +++ b/v4l2-apps/util/v4l2-dbg-micron.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2009 Mauro Carvalho Chehab + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "v4l2-dbg.h" + +#define MT9V011_IDENT "mt9v011" + +/* Register name prefix */ +#define MT9V011_PREFIX "MT9V011_" + +static struct board_regs mt9v011_regs[] = { + {0x00, MT9V011_PREFIX "CHIP_VERSION"}, + {0x01, MT9V011_PREFIX "ROWSTART"}, + {0x02, MT9V011_PREFIX "COLSTART"}, + {0x03, MT9V011_PREFIX "HEIGHT"}, + {0x04, MT9V011_PREFIX "WIDTH"}, + {0x05, MT9V011_PREFIX "HBLANK"}, + {0x06, MT9V011_PREFIX "VBLANK"}, + {0x07, MT9V011_PREFIX "OUT_CTRL"}, + {0x09, MT9V011_PREFIX "SHUTTER_WIDTH"}, + {0x0a, MT9V011_PREFIX "CLK_SPEED"}, + {0x0b, MT9V011_PREFIX "RESTART"}, + {0x0c, MT9V011_PREFIX "SHUTTER_DELAY"}, + {0x0d, MT9V011_PREFIX "RESET"}, + {0x1e, MT9V011_PREFIX "DIGITAL_ZOOM"}, + {0x20, MT9V011_PREFIX "READ_MODE"}, + {0x2b, MT9V011_PREFIX "GREEN_1_GAIN"}, + {0x2c, MT9V011_PREFIX "BLUE_GAIN"}, + {0x2d, MT9V011_PREFIX "RED_GAIN"}, + {0x2e, MT9V011_PREFIX "GREEN_2_GAIN"}, + {0x35, MT9V011_PREFIX "GLOBAL_GAIN"}, + {0xf1, MT9V011_PREFIX "CHIP_ENABLE"}, +}; diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index 424b0fffe..1a481c04c 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -47,6 +47,7 @@ #include "v4l2-dbg-em28xx.h" #include "v4l2-dbg-ac97.h" #include "v4l2-dbg-tvp5150.h" +#include "v4l2-dbg-micron.h" #define ARRAY_SIZE(arr) ((int)(sizeof(arr) / sizeof((arr)[0]))) @@ -61,7 +62,7 @@ struct board_list { static const struct board_list boards[] = { #define AC97_BOARD 0 - { /* From ac97-dbg.h */ + { /* From v4l2-dbg-ac97.h */ AC97_IDENT, sizeof(AC97_PREFIX) - 1, ac97_regs, @@ -69,7 +70,7 @@ static const struct board_list boards[] = { NULL, 0, }, - { /* From bttv-dbg.h */ + { /* From v4l2-dbg-bttv.h */ BTTV_IDENT, sizeof(BTTV_PREFIX) - 1, bt8xx_regs, @@ -77,7 +78,7 @@ static const struct board_list boards[] = { bt8xx_regs_other, ARRAY_SIZE(bt8xx_regs_other), }, - { /* From saa7134-dbg.h */ + { /* From v4l2-dbg-saa7134.h */ SAA7134_IDENT, sizeof(SAA7134_PREFIX) - 1, saa7134_regs, @@ -85,7 +86,7 @@ static const struct board_list boards[] = { NULL, 0, }, - { /* From em28xx-dbg.h */ + { /* From v4l2-dbg-em28xx.h */ EM28XX_IDENT, sizeof(EM28XX_PREFIX) - 1, em28xx_regs, @@ -93,7 +94,7 @@ static const struct board_list boards[] = { em28xx_alt_regs, ARRAY_SIZE(em28xx_alt_regs), }, - { /* From tvp5150-dbg.h */ + { /* From v4l2-dbg-tvp5150.h */ TVP5150_IDENT, sizeof(TVP5150_PREFIX) - 1, tvp5150_regs, @@ -101,6 +102,14 @@ static const struct board_list boards[] = { NULL, 0, }, + { /* From v4l2-dbg-micron.h */ + MT9V011_IDENT, + sizeof(MT9V011_PREFIX) - 1, + mt9v011_regs, + ARRAY_SIZE(mt9v011_regs), + NULL, + 0, + }, }; struct chipid { -- cgit v1.2.3 From 67924cd04f67ef0bf649ab43a317717fbbeb69af Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 10 Aug 2009 02:57:57 -0300 Subject: em28xx: Move the non-board dependent part to be outside em28xx_pre_card_setup() From: Mauro Carvalho Chehab em28xx_pre_card_setup() is meant to contain board-specific initialization. Also, as autodetection sometimes occur only after having i2c bus enabled, this function may need to be called later. Moving those setups to happen outside the function avoids calling it twice without need and without duplicating output lines at dmesg. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 111 +++++++++++------------- 1 file changed, 53 insertions(+), 58 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 9a09df296..ee46460f0 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1895,63 +1895,6 @@ static int em28xx_hint_sensor(struct em28xx *dev) */ void em28xx_pre_card_setup(struct em28xx *dev) { - int rc; - - em28xx_set_model(dev); - - em28xx_info("Identified as %s (card=%d)\n", - dev->board.name, dev->model); - - /* Set the default GPO/GPIO for legacy devices */ - dev->reg_gpo_num = EM2880_R04_GPO; - dev->reg_gpio_num = EM28XX_R08_GPIO; - - dev->wait_after_write = 5; - - /* Based on the Chip ID, set the device configuration */ - rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); - if (rc > 0) { - dev->chip_id = rc; - - switch (dev->chip_id) { - case CHIP_ID_EM2710: - em28xx_info("chip ID is em2710\n"); - break; - case CHIP_ID_EM2750: - em28xx_info("chip ID is em2750\n"); - break; - case CHIP_ID_EM2820: - em28xx_info("chip ID is em2820 (or em2710)\n"); - break; - case CHIP_ID_EM2840: - em28xx_info("chip ID is em2840\n"); - break; - case CHIP_ID_EM2860: - em28xx_info("chip ID is em2860\n"); - break; - case CHIP_ID_EM2870: - em28xx_info("chip ID is em2870\n"); - dev->wait_after_write = 0; - break; - case CHIP_ID_EM2874: - em28xx_info("chip ID is em2874\n"); - dev->reg_gpio_num = EM2874_R80_GPIO; - dev->wait_after_write = 0; - break; - case CHIP_ID_EM2883: - em28xx_info("chip ID is em2882/em2883\n"); - dev->wait_after_write = 0; - break; - default: - em28xx_info("em28xx chip ID = %d\n", dev->chip_id); - } - } - - /* Prepopulate cached GPO register content */ - rc = em28xx_read_reg(dev, dev->reg_gpo_num); - if (rc >= 0) - dev->reg_gpo = rc; - /* Set the initial XCLK and I2C clock values based on the board definition */ em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f); @@ -2564,7 +2507,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, int minor) { struct em28xx *dev = *devhandle; - int retval = -ENOMEM; + int retval; int errCode; dev->udev = udev; @@ -2581,6 +2524,58 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->em28xx_read_reg_req = em28xx_read_reg_req; dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800; + em28xx_set_model(dev); + + /* Set the default GPO/GPIO for legacy devices */ + dev->reg_gpo_num = EM2880_R04_GPO; + dev->reg_gpio_num = EM28XX_R08_GPIO; + + dev->wait_after_write = 5; + + /* Based on the Chip ID, set the device configuration */ + retval = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); + if (retval > 0) { + dev->chip_id = retval; + + switch (dev->chip_id) { + case CHIP_ID_EM2710: + em28xx_info("chip ID is em2710\n"); + break; + case CHIP_ID_EM2750: + em28xx_info("chip ID is em2750\n"); + break; + case CHIP_ID_EM2820: + em28xx_info("chip ID is em2820 (or em2710)\n"); + break; + case CHIP_ID_EM2840: + em28xx_info("chip ID is em2840\n"); + break; + case CHIP_ID_EM2860: + em28xx_info("chip ID is em2860\n"); + break; + case CHIP_ID_EM2870: + em28xx_info("chip ID is em2870\n"); + dev->wait_after_write = 0; + break; + case CHIP_ID_EM2874: + em28xx_info("chip ID is em2874\n"); + dev->reg_gpio_num = EM2874_R80_GPIO; + dev->wait_after_write = 0; + break; + case CHIP_ID_EM2883: + em28xx_info("chip ID is em2882/em2883\n"); + dev->wait_after_write = 0; + break; + default: + em28xx_info("em28xx chip ID = %d\n", dev->chip_id); + } + } + + /* Prepopulate cached GPO register content */ + retval = em28xx_read_reg(dev, dev->reg_gpo_num); + if (retval >= 0) + dev->reg_gpo = retval; + em28xx_pre_card_setup(dev); if (!dev->board.is_em2800) { -- cgit v1.2.3 From 3c6dcb306a9773419a04a1f47bfa00ed856b5517 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 10 Aug 2009 10:29:27 -0300 Subject: em28xx: Fix artifacts with Silvercrest webcam From: Mauro Carvalho Chehab Silvercrest mt9v011 sensor produces a 640x480 image. However, previously, the code were getting only half of the lines and merging two consecutive frames to "produce" a 640x480 image. With the addition of progressive mode, now em28xx is working with a full image. However, when the number of lines is bigger than 240, the beginning of some odd lines are filled with blank. After lots of testing, and physically checking the device for a Xtal, it was noticed experimentally that mt9v011 is using em28xx XCLK as its clock. Due to that, changing XCLK value changes the maximum speed of the stream. At the tests, it were possible to produce up to 32 fps, using a 30 MHz XCLK. However, at that rate, the artifacts happen even at 320x240. Lower values of XCLK produces artifacts only at 640x480. At some values of xclk (for example XCLKK = 6 MHz, 640x480), it is possible to see an invalid sucession of artifacts with this pattern: .xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx .xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ....xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (where the dots represent the blanked pixels) So, it seems that a waveform in the format of a ramp is interferring at the image. The cause of this interference is currently unknown. Some possibilities are: - electrical interference (maybe this device is broken?); - some issue at mt9v011 programming; - some bug at em28xx chip. So, for now, let's be conservative and use a value of XCLK that we know for sure that it won't cause artifacts. As I'm waiting for more of such devices with different em28xx chipset revisions, I'll have the opportunity to double check the issue with other pieces of hardware. Later patches can vary XCLK depending on the vertical resolutions, if a proper fix is not discovered. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 50 +++++++++++++++++-------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index ee46460f0..4b7526fa2 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -231,7 +231,7 @@ static struct em28xx_reg_seq silvercrest_reg_seq[] = { struct em28xx_board em28xx_boards[] = { [EM2750_BOARD_UNKNOWN] = { .name = "EM2710/EM2750/EM2751 webcam grabber", - .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, + .xclk = EM28XX_XCLK_FREQUENCY_20MHZ, .tuner_type = TUNER_ABSENT, .is_webcam = 1, .no_audio = 1, @@ -1838,6 +1838,7 @@ static int em28xx_hint_sensor(struct em28xx *dev) __be16 version_be; u16 version; + /* Micron sensor detection */ dev->i2c_client.addr = 0xba >> 1; cmd = 0; i2c_master_send(&dev->i2c_client, &cmd, 1); @@ -1846,16 +1847,27 @@ static int em28xx_hint_sensor(struct em28xx *dev) return -EINVAL; version = be16_to_cpu(version_be); - switch (version) { case 0x8232: /* mt9v011 640x480 1.3 Mpix sensor */ case 0x8243: /* mt9v011 rev B 640x480 1.3 Mpix sensor */ dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; + em28xx_set_model(dev); + sensor_name = "mt9v011"; dev->em28xx_sensor = EM28XX_MT9V011; dev->sensor_xres = 640; dev->sensor_yres = 480; - dev->sensor_xtal = 12150000; + /* + * FIXME: mt9v011 uses I2S speed as xtal clk - at least with + * the Silvercrest cam I have here for testing - for higher + * resolutions, a high clock cause horizontal artifacts, so we + * need to use a lower xclk frequency. + * Yet, it would be possible to adjust xclk depending on the + * desired resolution, since this affects directly the + * frame rate. + */ + dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ; + dev->sensor_xtal = 4300000; /* probably means GRGB 16 bit bayer */ dev->vinmode = 0x0d; @@ -1868,6 +1880,8 @@ static int em28xx_hint_sensor(struct em28xx *dev) #endif case 0x8431: dev->model = EM2750_BOARD_UNKNOWN; + em28xx_set_model(dev); + sensor_name = "mt9m001"; dev->em28xx_sensor = EM28XX_MT9M001; em28xx_initialize_mt9m001(dev); @@ -1884,6 +1898,9 @@ static int em28xx_hint_sensor(struct em28xx *dev) return -EINVAL; } + /* Setup webcam defaults */ + em28xx_pre_card_setup(dev); + em28xx_errdev("Sensor is %s, using model %s entry.\n", sensor_name, em28xx_boards[dev->model].name); @@ -2277,7 +2294,20 @@ void em28xx_register_i2c_ir(struct em28xx *dev) void em28xx_card_setup(struct em28xx *dev) { - em28xx_set_model(dev); + /* + * If the device can be a webcam, seek for a sensor. + * If sensor is not found, then it isn't a webcam. + */ + if (dev->board.is_webcam) { + if (em28xx_hint_sensor(dev) < 0) + dev->board.is_webcam = 0; + else + dev->progressive = 1; + } else + em28xx_set_model(dev); + + em28xx_info("Identified as %s (card=%d)\n", + dev->board.name, dev->model); dev->tuner_type = em28xx_boards[dev->model].tuner_type; if (em28xx_boards[dev->model].tuner_addr) @@ -2610,18 +2640,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->vinmode = 0x10; dev->vinctl = 0x11; - /* - * If the device can be a webcam, seek for a sensor. - * If sensor is not found, then it isn't a webcam. - */ - if (dev->board.is_webcam) - if (em28xx_hint_sensor(dev) < 0) - dev->board.is_webcam = 0; - - /* It makes no sense to use de-interlacing mode on webcams */ - if (dev->board.is_webcam) - dev->progressive = 1; - /* Do board specific init and eeprom reading */ em28xx_card_setup(dev); -- cgit v1.2.3 From a4fd422232350c268306a54f169e5b1fe3655f8f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 10 Aug 2009 10:53:00 -0300 Subject: em28xx: fix: avoid having a bad colored image with webcams From: Mauro Carvalho Chehab Register 0x13 seems to be a sort of image control, maybe gamma. Lower values produce better images, while higher values increases the contrast and shifts colors to green. 0xff produces a black image. If this register is left alone, a random value can be found at the register, producing weird results. This register doesn't seem to affect tv streams. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 10da3ad82..46cb13182 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -632,6 +632,9 @@ int em28xx_capture_start(struct em28xx *dev, int start) return rc; } + if (dev->board.is_webcam) + rc = em28xx_write_reg(dev, 0x13, 0x0c); + /* enable video capture */ rc = em28xx_write_reg(dev, 0x48, 0x00); -- cgit v1.2.3 From 61fe68b877246eb29fc7cccb96a73ffa3c7267fe Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Mon, 10 Aug 2009 23:44:14 +0200 Subject: I2C cleanups and version checks The structure and comments of the I2C part have been adopted to fit to the USB part. Some additional cleanups and precisements have been made to the version detection and checking functionality to clearly separate HW/SW/FW version. Signed-off-by: Tobias Lorenz --- .../drivers/media/radio/si470x/radio-si470x-i2c.c | 245 ++++++++++++++++----- .../drivers/media/radio/si470x/radio-si470x-usb.c | 43 ++-- linux/drivers/media/radio/si470x/radio-si470x.h | 45 ++-- 3 files changed, 257 insertions(+), 76 deletions(-) diff --git a/linux/drivers/media/radio/si470x/radio-si470x-i2c.c b/linux/drivers/media/radio/si470x/radio-si470x-i2c.c index 218102184..2d53b6a94 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -3,53 +3,88 @@ * * I2C driver for radios with Silicon Labs Si470x FM Radio Receivers * - * Copyright (C) 2009 Samsung Electronics Co.Ltd + * Copyright (c) 2009 Samsung Electronics Co.Ltd * Author: Joonyoung Shim * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * TODO: + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * ToDo: * - RDS support - * */ -#include -#include + +/* driver definitions */ +#define DRIVER_AUTHOR "Joonyoung Shim "; +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0) +#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" +#define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers" +#define DRIVER_VERSION "1.0.0" + +/* kernel includes */ #include #include #include "radio-si470x.h" -#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0) -#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" -#define DRIVER_VERSION "1.0.0" -/* starting with the upper byte of register 0x0a */ +/* I2C Device ID List */ +static const struct i2c_device_id si470x_i2c_id[] = { + /* Generic Entry */ + { "si470x", 0 }, + /* Terminating entry */ + { } +}; +MODULE_DEVICE_TABLE(i2c, si470x_i2c_id); + + + +/************************************************************************** + * Module Parameters + **************************************************************************/ + +/* Radio Nr */ +static int radio_nr = -1; +module_param(radio_nr, int, 0444); +MODULE_PARM_DESC(radio_nr, "Radio Nr"); + + + +/************************************************************************** + * I2C Definitions + **************************************************************************/ + +/* Write starts with the upper byte of register 0x02 */ +#define WRITE_REG_NUM 8 +#define WRITE_INDEX(i) (i + 0x02) + +/* Read starts with the upper byte of register 0x0a */ #define READ_REG_NUM RADIO_REGISTER_NUM #define READ_INDEX(i) ((i + RADIO_REGISTER_NUM - 0x0a) % READ_REG_NUM) -static int si470x_get_all_registers(struct si470x_device *radio) -{ - int i; - u16 buf[READ_REG_NUM]; - struct i2c_msg msgs[1] = { - { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, - (void *)buf }, - }; - - if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) - return -EIO; - for (i = 0; i < READ_REG_NUM; i++) - radio->registers[i] = __be16_to_cpu(buf[READ_INDEX(i)]); - return 0; -} +/************************************************************************** + * General Driver Functions - REGISTERs + **************************************************************************/ +/* + * si470x_get_register - read register + */ int si470x_get_register(struct si470x_device *radio, int regnr) { u16 buf[READ_REG_NUM]; @@ -66,10 +101,10 @@ int si470x_get_register(struct si470x_device *radio, int regnr) return 0; } -/* starting with the upper byte of register 0x02h */ -#define WRITE_REG_NUM 8 -#define WRITE_INDEX(i) (i + 0x02) +/* + * si470x_set_register - write register + */ int si470x_set_register(struct si470x_device *radio, int regnr) { int i; @@ -88,11 +123,56 @@ int si470x_set_register(struct si470x_device *radio, int regnr) return 0; } + + +/************************************************************************** + * General Driver Functions - ENTIRE REGISTERS + **************************************************************************/ + +/* + * si470x_get_all_registers - read entire registers + */ +static int si470x_get_all_registers(struct si470x_device *radio) +{ + int i; + u16 buf[READ_REG_NUM]; + struct i2c_msg msgs[1] = { + { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM, + (void *)buf }, + }; + + if (i2c_transfer(radio->client->adapter, msgs, 1) != 1) + return -EIO; + + for (i = 0; i < READ_REG_NUM; i++) + radio->registers[i] = __be16_to_cpu(buf[READ_INDEX(i)]); + + return 0; +} + + + +/************************************************************************** + * General Driver Functions - DISCONNECT_CHECK + **************************************************************************/ + +/* + * si470x_disconnect_check - check whether radio disconnects + */ int si470x_disconnect_check(struct si470x_device *radio) { return 0; } + + +/************************************************************************** + * File Operations Interface + **************************************************************************/ + +/* + * si470x_fops_open - file open + */ static int si470x_fops_open(struct file *file) { struct si470x_device *radio = video_drvdata(file); @@ -104,11 +184,16 @@ static int si470x_fops_open(struct file *file) if (radio->users == 1) /* start radio */ retval = si470x_start(radio); + mutex_unlock(&radio->lock); return retval; } + +/* + * si470x_fops_release - file release + */ static int si470x_fops_release(struct file *file) { struct si470x_device *radio = video_drvdata(file); @@ -123,11 +208,16 @@ static int si470x_fops_release(struct file *file) if (radio->users == 0) /* stop radio */ retval = si470x_stop(radio); + mutex_unlock(&radio->lock); return retval; } + +/* + * si470x_fops - file operations interface + */ const struct v4l2_file_operations si470x_fops = { .owner = THIS_MODULE, .ioctl = video_ioctl2, @@ -135,6 +225,15 @@ const struct v4l2_file_operations si470x_fops = { .release = si470x_fops_release, }; + + +/************************************************************************** + * Video4Linux Interface + **************************************************************************/ + +/* + * si470x_vidioc_querycap - query device capabilities + */ int si470x_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *capability) { @@ -147,11 +246,21 @@ int si470x_vidioc_querycap(struct file *file, void *priv, return 0; } + + +/************************************************************************** + * I2C Interface + **************************************************************************/ + +/* + * si470x_i2c_probe - probe for the device + */ static int __devinit si470x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct si470x_device *radio; int retval = 0; + unsigned char version_warning = 0; /* private data allocation and initialization */ radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); @@ -159,8 +268,8 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, retval = -ENOMEM; goto err_initial; } - radio->client = client; radio->users = 0; + radio->client = client; mutex_init(&radio->lock); /* video device allocation and initialization */ @@ -181,28 +290,47 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, } msleep(110); - /* show some infos about the specific si470x device */ + /* get device and chip versions */ if (si470x_get_all_registers(radio) < 0) { retval = -EIO; - goto err_radio; + goto err_video; } dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", radio->registers[DEVICEID], radio->registers[CHIPID]); + if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_FW_VERSION) { + dev_warn(&client->dev, + "This driver is known to work with " + "firmware version %hu,\n", RADIO_FW_VERSION); + dev_warn(&client->dev, + "but the device has firmware version %hu.\n", + radio->registers[CHIPID] & CHIPID_FIRMWARE); + version_warning = 1; + } + + /* give out version warning */ + if (version_warning == 1) { + dev_warn(&client->dev, + "If you have some trouble using this driver,\n"); + dev_warn(&client->dev, + "please report to V4L ML at " + "linux-media@vger.kernel.org\n"); + } /* set initial frequency */ si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ /* register video device */ - retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, -1); + retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, + radio_nr); if (retval) { dev_warn(&client->dev, "Could not register video device\n"); goto err_all; } - i2c_set_clientdata(client, radio); return 0; err_all: +err_video: video_device_release(radio->videodev); err_radio: kfree(radio); @@ -210,6 +338,10 @@ err_initial: return retval; } + +/* + * si470x_i2c_remove - remove the device + */ static __devexit int si470x_i2c_remove(struct i2c_client *client) { struct si470x_device *radio = i2c_get_clientdata(client); @@ -221,34 +353,49 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) return 0; } -static const struct i2c_device_id si470x_i2c_id[] = { - { "si470x", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, si470x_i2c_id); +/* + * si470x_i2c_driver - i2c driver interface + */ static struct i2c_driver si470x_i2c_driver = { .driver = { - .name = "si470x", - .owner = THIS_MODULE, + .name = "si470x", + .owner = THIS_MODULE, }, - .probe = si470x_i2c_probe, - .remove = __devexit_p(si470x_i2c_remove), - .id_table = si470x_i2c_id, + .probe = si470x_i2c_probe, + .remove = __devexit_p(si470x_i2c_remove), + .id_table = si470x_i2c_id, }; + + +/************************************************************************** + * Module Interface + **************************************************************************/ + +/* + * si470x_i2c_init - module init + */ static int __init si470x_i2c_init(void) { + printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); return i2c_add_driver(&si470x_i2c_driver); } -module_init(si470x_i2c_init); + +/* + * si470x_i2c_exit - module exit + */ static void __exit si470x_i2c_exit(void) { i2c_del_driver(&si470x_i2c_driver); } + + +module_init(si470x_i2c_init); module_exit(si470x_i2c_exit); -MODULE_DESCRIPTION("i2c radio driver for si470x fm radio receivers"); -MODULE_AUTHOR("Joonyoung Shim "); MODULE_LICENSE("GPL"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); diff --git a/linux/drivers/media/radio/si470x/radio-si470x-usb.c b/linux/drivers/media/radio/si470x/radio-si470x-usb.c index 2f5cf6c72..f2d0e1ddb 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/linux/drivers/media/radio/si470x/radio-si470x-usb.c @@ -138,16 +138,12 @@ MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); /************************************************************************** - * Software/Hardware Versions + * Software/Hardware Versions from Scratch Page **************************************************************************/ #define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6 #define RADIO_SW_VERSION 7 -#define RADIO_SW_VERSION_CURRENT 15 #define RADIO_HW_VERSION 1 -#define SCRATCH_PAGE_SW_VERSION 1 -#define SCRATCH_PAGE_HW_VERSION 2 - /************************************************************************** @@ -745,6 +741,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int i, int_end_size, retval = 0; + unsigned char version_warning = 0; /* private data allocation and initialization */ radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); @@ -801,13 +798,22 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, sizeof(si470x_viddev_template)); video_set_drvdata(radio->videodev, radio); - /* show some infos about the specific si470x device */ + /* get device and chip versions */ if (si470x_get_all_registers(radio) < 0) { retval = -EIO; goto err_video; } dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", radio->registers[DEVICEID], radio->registers[CHIPID]); + if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_FW_VERSION) { + dev_warn(&intf->dev, + "This driver is known to work with " + "firmware version %hu,\n", RADIO_FW_VERSION); + dev_warn(&intf->dev, + "but the device has firmware version %hu.\n", + radio->registers[CHIPID] & CHIPID_FIRMWARE); + version_warning = 1; + } /* get software and hardware versions */ if (si470x_get_scratch_page_versions(radio) < 0) { @@ -816,16 +822,27 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, } dev_info(&intf->dev, "software version %d, hardware version %d\n", radio->software_version, radio->hardware_version); - - /* check if device and firmware is current */ - if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) - < RADIO_SW_VERSION_CURRENT) { + if (radio->software_version < RADIO_SW_VERSION) { dev_warn(&intf->dev, "This driver is known to work with " - "firmware version %hu,\n", RADIO_SW_VERSION_CURRENT); + "software version %hu,\n", RADIO_SW_VERSION); dev_warn(&intf->dev, - "but the device has firmware version %hu.\n", - radio->registers[CHIPID] & CHIPID_FIRMWARE); + "but the device has software version %hu.\n", + radio->software_version); + version_warning = 1; + } + if (radio->hardware_version < RADIO_HW_VERSION) { + dev_warn(&intf->dev, + "This driver is known to work with " + "hardware version %hu,\n", RADIO_HW_VERSION); + dev_warn(&intf->dev, + "but the device has hardware version %hu.\n", + radio->hardware_version); + version_warning = 1; + } + + /* give out version warning */ + if (version_warning == 1) { dev_warn(&intf->dev, "If you have some trouble using this driver,\n"); dev_warn(&intf->dev, diff --git a/linux/drivers/media/radio/si470x/radio-si470x.h b/linux/drivers/media/radio/si470x/radio-si470x.h index 791c367be..f931789c2 100644 --- a/linux/drivers/media/radio/si470x/radio-si470x.h +++ b/linux/drivers/media/radio/si470x/radio-si470x.h @@ -42,6 +42,7 @@ #include + /************************************************************************** * Register Definitions **************************************************************************/ @@ -134,6 +135,7 @@ #define RDSD_RDSD 0xffff /* bits 15..00: RDS Block D Data (Si4701 only) */ + /************************************************************************** * General Driver Definitions **************************************************************************/ @@ -144,9 +146,19 @@ struct si470x_device { struct video_device *videodev; -#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) - struct i2c_client *client; -#endif + /* driver management */ + unsigned int users; + + /* Silabs internal registers (0..15) */ + unsigned short registers[RADIO_REGISTER_NUM]; + + /* RDS receive buffer */ + wait_queue_head_t read_queue; + struct mutex lock; /* buffer locking */ + unsigned char *buffer; /* size is always multiple of three */ + unsigned int buf_size; + unsigned int rd_index; + unsigned int wr_index; #if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) /* reference to USB and video device */ @@ -167,21 +179,26 @@ struct si470x_device { unsigned char disconnected; struct mutex disconnect_lock; #endif - unsigned int users; - - /* Silabs internal registers (0..15) */ - unsigned short registers[RADIO_REGISTER_NUM]; - /* RDS receive buffer */ - wait_queue_head_t read_queue; - struct mutex lock; /* buffer locking */ - unsigned char *buffer; /* size is always multiple of three */ - unsigned int buf_size; - unsigned int rd_index; - unsigned int wr_index; +#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) + struct i2c_client *client; +#endif }; + +/************************************************************************** + * Firmware Versions + **************************************************************************/ + +#define RADIO_FW_VERSION 15 + + + +/************************************************************************** + * Frequency Multiplicator + **************************************************************************/ + /* * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, * 62.5 kHz otherwise. -- cgit v1.2.3 From f2315820af3c8b9a218c05c0fd44b6f0741c4a35 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Aug 2009 20:07:42 -0300 Subject: Fix incorrect type of tuner for the BeholdTV H6 card From: Beholder Intl. Ltd. Dmitry Belimov Define correct tuner in config. Radio now works fine Priority: normal Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 2 +- linux/drivers/media/video/saa7134/saa7134-dvb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index c18b41ee6..40aa654d2 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4900,7 +4900,7 @@ struct saa7134_board saa7134_boards[] = { /* Igor Kuznetsov */ .name = "Beholder BeholdTV H6", .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .tuner_type = TUNER_PHILIPS_FMD1216MEX_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index a5263c391..afd9b7e5c 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -1461,7 +1461,7 @@ static int dvb_init(struct saa7134_dev *dev) if (fe0->dvb.frontend) { dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x61, - TUNER_PHILIPS_FMD1216ME_MK3); + TUNER_PHILIPS_FMD1216MEX_MK3); } break; case SAA7134_BOARD_AVERMEDIA_A700_PRO: -- cgit v1.2.3 From 0ffdf3c011bae5197f3e30f633d32645be8df021 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Aug 2009 20:11:43 -0300 Subject: saa7134: fix the radio on Avermedia GO 007 FM From: hermann pitton We have support for radio on saa7133/35/31e cards with tda8290/8275(a) and 5.5MHz ceramic filter on the bridge chips since a while. It was previously not tested, if this card supports it too, but the old "ghost" radio with wrong filters doesn't work anymore. Thanks go to Pham Thanh Nam and Laszlo Kustan for reporting it working on that input. Priority: normal Signed-off-by: hermann pitton Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 40aa654d2..3ab7732e6 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -1633,7 +1633,7 @@ struct saa7134_board saa7134_boards[] = { }}, .radio = { .name = name_radio, - .amux = LINE1, + .amux = TV, .gpio = 0x00300001, }, .mute = { -- cgit v1.2.3 From 84b33bda3d8447bc0f28a9eae22039ec4a0bb3bf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Aug 2009 20:33:42 -0300 Subject: em28xx: fix: some webcams don't have audio inputs From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 3 +++ linux/drivers/media/video/em28xx/em28xx-core.c | 2 +- linux/drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 795fd16a5..2f4777f76 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -234,6 +234,7 @@ struct em28xx_board em28xx_boards[] = { .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, .tuner_type = TUNER_ABSENT, .is_webcam = 1, + .no_audio = 1, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, @@ -261,6 +262,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Unknown EM2750/28xx video grabber", .tuner_type = TUNER_ABSENT, .is_webcam = 1, /* To enable sensor probe */ + .no_audio = 1, }, [EM2750_BOARD_DLCW_130] = { /* Beijing Huaqi Information Digital Technology Co., Ltd */ @@ -481,6 +483,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Silvercrest Webcam 1.3mpix", .tuner_type = TUNER_ABSENT, .is_webcam = 1, + .no_audio = 1, .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = 0, diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index f24af40df..a1de593ec 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -494,7 +494,7 @@ int em28xx_audio_setup(struct em28xx *dev) /* If device doesn't support Usb Audio Class, use vendor class */ if (!dev->has_audio_class) - dev->has_alsa_audio = 1; + dev->has_alsa_audio = ~dev->board.no_audio; dev->audio_mode.has_audio = 1; diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index df7fe9af7..3c4cd00b2 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -397,6 +397,7 @@ struct em28xx_board { unsigned int has_dvb:1; unsigned int has_snapshot_button:1; unsigned int is_webcam:1; + unsigned int no_audio:1; unsigned int valid:1; unsigned char xclk, i2c_speed; -- cgit v1.2.3 From ba28fa4eca1b69daa57024d9c0c9fe880ac0b2c9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Aug 2009 22:00:24 -0300 Subject: drivers/media/video/gspca: introduce missing kfree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Julia Lawall Error handling code following a kmalloc should free the allocated data. Priority: normal Signed-off-by: Julia Lawall Acked-by: Erik Andrén Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 7127321ac..6b89f33a4 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -178,8 +178,10 @@ sensor_found: sens_priv->settings = kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL); - if (!sens_priv->settings) + if (!sens_priv->settings) { + kfree(sens_priv); return -ENOMEM; + } sd->gspca_dev.cam.cam_mode = s5k83a_modes; sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes); -- cgit v1.2.3 From fbcd7beea764d905edd7aec98388395e0d112a9d Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Wed, 5 Aug 2009 16:46:38 +0200 Subject: [patch] Added Support for STK7700D (DVB) From: Pete Hildebrandt This patch adds support for the STK7700D USB-DVB-Device. lsusb identifies it as: idVendor 0x1164 YUAN High-Tech Development Co., Ltd idProduct 0x1efc iProduct 2 STK7700D The device is build into a Samsung R55-T5500 notebook. Priority: normal Signed-off-by: Pete Hildebrandt Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 8 ++++++-- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index 8ec98f6e0..81cda8061 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1501,6 +1501,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_H) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T3) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T5) }, + { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1826,7 +1827,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 8, + .num_device_descs = 9, .devices = { { "Terratec Cinergy HT USB XE", { &dib0700_usb_id_table[27], NULL }, @@ -1860,7 +1861,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[51], NULL }, { NULL }, }, - + { "YUAN High-Tech STK7700D", + { &dib0700_usb_id_table[54], NULL }, + { NULL }, + }, }, .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dib0700_rc_keys, diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 9593b7289..6eccce1a7 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -252,6 +252,7 @@ #define USB_PID_YUAN_STK7700PH 0x1f08 #define USB_PID_YUAN_PD378S 0x2edc #define USB_PID_YUAN_MC770 0x0871 +#define USB_PID_YUAN_STK7700D 0x1efc #define USB_PID_DW2102 0x2102 #define USB_PID_XTENSIONS_XD_380 0x0381 #define USB_PID_TELESTAR_STARSTICK_2 0x8000 -- cgit v1.2.3 From 2f25ba7a8bf7364ee4bd4aee7b283b0ea273b160 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 5 Aug 2009 12:58:47 -0300 Subject: media/zr364xx: fix build errors From: Randy Dunlap Fix build errors in zr364xx by adding selects: zr364xx.c:(.text+0x195ed7): undefined reference to `videobuf_streamon' zr364xx.c:(.text+0x196030): undefined reference to `videobuf_dqbuf' zr364xx.c:(.text+0x1960c4): undefined reference to `videobuf_qbuf' zr364xx.c:(.text+0x196123): undefined reference to `videobuf_querybuf' zr364xx.c:(.text+0x196182): undefined reference to `videobuf_reqbufs' zr364xx.c:(.text+0x196224): undefined reference to `videobuf_queue_is_busy' zr364xx.c:(.text+0x196390): undefined reference to `videobuf_vmalloc_free' zr364xx.c:(.text+0x196571): undefined reference to `videobuf_iolock' zr364xx.c:(.text+0x196678): undefined reference to `videobuf_mmap_mapper' zr364xx.c:(.text+0x196760): undefined reference to `videobuf_poll_stream' zr364xx.c:(.text+0x19689a): undefined reference to `videobuf_read_one' zr364xx.c:(.text+0x1969ec): undefined reference to `videobuf_mmap_free' zr364xx.c:(.text+0x197862): undefined reference to `videobuf_queue_vmalloc_init' zr364xx.c:(.text+0x197a28): undefined reference to `videobuf_streamoff' zr364xx.c:(.text+0x198203): undefined reference to `videobuf_to_vmalloc' zr364xx.c:(.text+0x198603): undefined reference to `videobuf_streamoff' drivers/built-in.o: In function `free_buffer': zr364xx.c:(.text+0x19930c): undefined reference to `videobuf_vmalloc_free' drivers/built-in.o: In function `zr364xx_open': zr364xx.c:(.text+0x19a7de): undefined reference to `videobuf_queue_vmalloc_init' drivers/built-in.o: In function `read_pipe_completion': zr364xx.c:(.text+0x19b17f): undefined reference to `videobuf_to_vmalloc' Priority: normal Signed-off-by: Randy Dunlap Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index 8460013a0..e8a6e4de4 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -991,6 +991,8 @@ source "drivers/media/video/pwc/Kconfig" config USB_ZR364XX tristate "USB ZR364XX Camera support" depends on VIDEO_V4L2 + select VIDEOBUF_GEN + select VIDEOBUF_VMALLOC ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. -- cgit v1.2.3 From d3f91b69f01b8f1c132d1037137ef9b6fba4a142 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 5 Aug 2009 13:07:10 -0300 Subject: cxusb, d680 dmbth use unified lgs8gxx code instead of lgs8gl5 From: David T.L. Wong Use unified lgs8gxx frontend instead of reverse engineered lgs8gl5 frontend. After this patch, lgs8gl5 frontend could be mark as deprecated. Future development should base on unified lgs8gxx frontend. Priority: normal Signed-off-by: David T.L. Wong Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/cxusb.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/cxusb.c b/linux/drivers/media/dvb/dvb-usb/cxusb.c index f467cad8a..05da84c90 100644 --- a/linux/drivers/media/dvb/dvb-usb/cxusb.c +++ b/linux/drivers/media/dvb/dvb-usb/cxusb.c @@ -38,7 +38,7 @@ #include "mxl5005s.h" #include "dib7000p.h" #include "dib0070.h" -#include "lgs8gl5.h" +#include "lgs8gxx.h" /* debug */ static int dvb_usb_cxusb_debug; @@ -1097,8 +1097,18 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap) return -EIO; } -static struct lgs8gl5_config lgs8gl5_cfg = { +static struct lgs8gxx_config d680_lgs8gl5_cfg = { + .prod = LGS8GXX_PROD_LGS8GL5, .demod_address = 0x19, + .serial_ts = 0, + .ts_clk_pol = 0, + .ts_clk_gated = 1, + .if_clk_freq = 30400, /* 30.4 MHz */ + .if_freq = 5725, /* 5.725 MHz */ + .if_neg_center = 0, + .ext_adc = 0, + .adc_signed = 0, + .if_neg_edge = 0, }; static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap) @@ -1138,7 +1148,7 @@ static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap) msleep(100); /* Attach frontend */ - adap->fe = dvb_attach(lgs8gl5_attach, &lgs8gl5_cfg, &d->i2c_adap); + adap->fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap); if (adap->fe == NULL) return -EIO; -- cgit v1.2.3 From 431b7b75e8f6cc9c89cfca9f7e307731c3b07d0d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 6 Aug 2009 01:06:31 +0200 Subject: soc-camera: fix recursive locking in .buf_queue() From: Guennadi Liakhovetski The .buf_queue() V4L2 driver method is called under spinlock_irqsave(q->irqlock,...), don't take the lock again inside the function. Reported-by: Antonio Ospite Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/mx1_camera.c | 6 +----- drivers/media/video/mx3_camera.c | 19 ++++++++++--------- drivers/media/video/pxa_camera.c | 6 +----- drivers/media/video/sh_mobile_ceu_camera.c | 5 +---- 4 files changed, 13 insertions(+), 23 deletions(-) --- linux/drivers/media/video/mx1_camera.c | 6 +----- linux/drivers/media/video/mx3_camera.c | 19 ++++++++++--------- linux/drivers/media/video/pxa_camera.c | 6 +----- linux/drivers/media/video/sh_mobile_ceu_camera.c | 5 +---- 4 files changed, 13 insertions(+), 23 deletions(-) diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 2d075205b..736c31d23 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -234,6 +234,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) return ret; } +/* Called under spinlock_irqsave(&pcdev->lock, ...) */ static void mx1_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { @@ -241,13 +242,10 @@ static void mx1_videobuf_queue(struct videobuf_queue *vq, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx1_camera_dev *pcdev = ici->priv; struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); - unsigned long flags; dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); - spin_lock_irqsave(&pcdev->lock, flags); - list_add_tail(&vb->queue, &pcdev->capture); vb->state = VIDEOBUF_ACTIVE; @@ -264,8 +262,6 @@ static void mx1_videobuf_queue(struct videobuf_queue *vq, __raw_writel(temp, pcdev->base + CSICR1); } } - - spin_unlock_irqrestore(&pcdev->lock, flags); } static void mx1_videobuf_release(struct videobuf_queue *vq, diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index e605c076e..9770cb793 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -332,7 +332,10 @@ static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc) } } -/* Called with .vb_lock held */ +/* + * Called with .vb_lock mutex held and + * under spinlock_irqsave(&mx3_cam->lock, ...) + */ static void mx3_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { @@ -346,7 +349,8 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, struct idmac_video_param *video = &ichan->params.video; const struct soc_camera_data_format *data_fmt = icd->current_fmt; dma_cookie_t cookie; - unsigned long flags; + + BUG_ON(!irqs_disabled()); /* This is the configuration of one sg-element */ video->out_pixel_fmt = fourcc_to_ipu_pix(data_fmt->fourcc); @@ -359,8 +363,6 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, memset((void *)vb->baddr, 0xaa, vb->bsize); #endif - spin_lock_irqsave(&mx3_cam->lock, flags); - list_add_tail(&vb->queue, &mx3_cam->capture); if (!mx3_cam->active) { @@ -370,24 +372,23 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, vb->state = VIDEOBUF_QUEUED; } - spin_unlock_irqrestore(&mx3_cam->lock, flags); + spin_unlock_irq(&mx3_cam->lock); cookie = txd->tx_submit(txd); dev_dbg(&icd->dev, "Submitted cookie %d DMA 0x%08x\n", cookie, sg_dma_address(&buf->sg)); + + spin_lock_irq(&mx3_cam->lock); + if (cookie >= 0) return; /* Submit error */ vb->state = VIDEOBUF_PREPARED; - spin_lock_irqsave(&mx3_cam->lock, flags); - list_del_init(&vb->queue); if (mx3_cam->active == buf) mx3_cam->active = NULL; - - spin_unlock_irqrestore(&mx3_cam->lock, flags); } /* Called with .vb_lock held */ diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 3f1b63e4e..92fb8b191 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -624,6 +624,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev) dev_dbg(pcdev->soc_host.dev, "%s\n", __func__); } +/* Called under spinlock_irqsave(&pcdev->lock, ...) */ static void pxa_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { @@ -631,13 +632,10 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); - unsigned long flags; dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d active=%p\n", __func__, vb, vb->baddr, vb->bsize, pcdev->active); - spin_lock_irqsave(&pcdev->lock, flags); - list_add_tail(&vb->queue, &pcdev->capture); vb->state = VIDEOBUF_ACTIVE; @@ -645,8 +643,6 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, if (!pcdev->active) pxa_camera_start_capture(pcdev); - - spin_unlock_irqrestore(&pcdev->lock, flags); } static void pxa_videobuf_release(struct videobuf_queue *vq, diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 7ea2a0edf..1bae28a98 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -283,27 +283,24 @@ out: return ret; } +/* Called under spinlock_irqsave(&pcdev->lock, ...) */ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - unsigned long flags; dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, vb, vb->baddr, vb->bsize); vb->state = VIDEOBUF_QUEUED; - spin_lock_irqsave(&pcdev->lock, flags); list_add_tail(&vb->queue, &pcdev->capture); if (!pcdev->active) { pcdev->active = vb; sh_mobile_ceu_capture(pcdev); } - - spin_unlock_irqrestore(&pcdev->lock, flags); } static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq, -- cgit v1.2.3 From 672911c86336621bf8d82bb070c84d7082e53a05 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 6 Aug 2009 12:52:11 -0300 Subject: em28xx: fix empire auto-detect From: Douglas Schilling Landgraf Fixed eeprom hash table Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 2f4777f76..5b33e2dd1 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1729,7 +1729,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = { {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, - {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, + {0x166a0441, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028}, }; -- cgit v1.2.3 From 11a870a6ffe158aa929d11a5adac7cfc3d7a0f4e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 6 Aug 2009 20:32:01 -0300 Subject: v4l2-ctl: Add support for VIDIOC_[G|S]_PARM From: Mauro Carvalho Chehab Those ioctls are used to control streaming frame rate. Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-ctl.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp index b2246c557..e872a2916 100644 --- a/v4l2-apps/util/v4l2-ctl.cpp +++ b/v4l2-apps/util/v4l2-ctl.cpp @@ -77,6 +77,8 @@ enum Option { OptSetTuner = 't', OptGetVideoFormat = 'V', OptSetVideoFormat = 'v', + OptGetParm = 'P', + OptSetParm = 'p', OptGetSlicedVbiOutFormat = 128, OptGetOverlayFormat, @@ -222,6 +224,8 @@ static struct option long_options[] = { {"list-formats", no_argument, 0, OptListFormats}, {"get-standard", no_argument, 0, OptGetStandard}, {"set-standard", required_argument, 0, OptSetStandard}, + {"get-parm", no_argument, 0, OptGetParm}, + {"set-parm", required_argument, 0, OptSetParm}, {"info", no_argument, 0, OptGetDriverInfo}, {"list-ctrls", no_argument, 0, OptListCtrls}, {"list-ctrls-menus", no_argument, 0, OptListCtrlsMenus}, @@ -306,6 +310,8 @@ static void usage(void) " ntsc-X (X = M/J/K) or just 'ntsc' (V4L2_STD_NTSC)\n" " secam-X (X = B/G/H/D/K/L/Lc) or just 'secam' (V4L2_STD_SECAM)\n" " --list-standards display supported video standards [VIDIOC_ENUMSTD]\n" + " -P, --get-parm display video parameters [VIDIOC_G_PARMS]\n" + " -p, --set-parm set video rate in fps [VIDIOC_G_PARMS]\n" " -T, --get-tuner query the tuner settings [VIDIOC_G_TUNER]\n" " -t, --set-tuner=\n" " set the audio mode of the tuner [VIDIOC_S_TUNER]\n" @@ -1419,11 +1425,13 @@ int main(int argc, char **argv) struct v4l2_rect vcrop_out_overlay; /* crop rect */ struct v4l2_framebuffer fbuf; /* fbuf */ struct v4l2_jpegcompression jpegcomp; /* jpeg compression */ + struct v4l2_streamparm parm; /* get/set parm */ int input; /* set_input/get_input */ int output; /* set_output/get_output */ int txsubchans; /* set_modulator */ v4l2_std_id std; /* get_std/set_std */ double freq = 0; /* get/set frequency */ + double fps = 0; /* set framerate speed, in fps */ struct v4l2_frequency vf; /* get_freq/set_freq */ struct v4l2_standard vs; /* list_std */ int overlay; /* overlay */ @@ -1690,6 +1698,9 @@ int main(int argc, char **argv) std = strtol(optarg, 0L, 0) | (1ULL << 63); } break; + case OptSetParm: + fps = strtod(optarg, NULL); + break; case OptGetCtrl: subs = optarg; while (*subs != '\0') { @@ -1915,6 +1926,7 @@ int main(int argc, char **argv) options[OptGetAudioInput] = 1; options[OptGetAudioOutput] = 1; options[OptGetStandard] = 1; + options[OptGetParm] = 1; options[OptGetFreq] = 1; options[OptGetTuner] = 1; options[OptGetModulator] = 1; @@ -1976,6 +1988,23 @@ int main(int argc, char **argv) printf("Standard set to %08llx\n", (unsigned long long)std); } + + if (options[OptSetParm]) { + memset (&parm, 0, sizeof(parm)); + parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + parm.parm.capture.timeperframe.numerator = 1000; + parm.parm.capture.timeperframe.denominator = (__u32)(fps * parm.parm.capture.timeperframe.numerator); + + if (doioctl(fd, VIDIOC_S_PARM, &parm, "VIDIOC_S_PARM") == 0) { + struct v4l2_fract *tf = &parm.parm.capture.timeperframe; + if (!tf->denominator || !tf->numerator) + printf ("Invalid frame rate\n"); + else + printf("Frame rate set to: %.3f fps\n", + 1.0*tf->denominator/tf->numerator); + } + } + if (options[OptSetInput]) { if (doioctl(fd, VIDIOC_S_INPUT, &input, "VIDIOC_S_INPUT") == 0) { printf("Video input set to %d", input); @@ -2451,6 +2480,23 @@ set_vid_fmt_error: } } + if (options[OptGetParm]) { + memset (&parm, 0, sizeof(parm)); + parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (doioctl(fd, VIDIOC_G_PARM, &parm, "VIDIOC_G_PARM") == 0) { + struct v4l2_fract *tf = &parm.parm.capture.timeperframe; + if (parm.parm.capture.capability & V4L2_MODE_HIGHQUALITY) + printf("Has High quality imaging mode\n"); + if (parm.parm.capture.capability && V4L2_CAP_TIMEPERFRAME) + printf("Has V4L2_CAP_TIMEPERFRAME\n"); + if (!tf->denominator || !tf->numerator) + printf ("Invalid frame rate\n"); + else + printf("Frame rate is %.3f fps\n", + (1.0 * tf->denominator) / tf->numerator); + } + } + if (options[OptGetCtrl] && !get_ctrls.empty()) { struct v4l2_ext_controls ctrls = { 0 }; -- cgit v1.2.3 From 65a908e5b37515512c5cf89fa74a533c77e5ec62 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 6 Aug 2009 21:03:35 -0300 Subject: mt9v011: Add support for controlling frame rates From: Mauro Carvalho Chehab Implement g_parm/s_parm ioctls. Those are used to check the current frame rate (in fps) and to set it to a value. In practice, there are only 15 possible different speeds, due to chip limits. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 89 ++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index c9706b889..a76d02d40 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -166,7 +166,7 @@ static void set_balance(struct v4l2_subdev *sd) mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); } -static void calc_fps(struct v4l2_subdev *sd) +static void calc_fps(struct v4l2_subdev *sd, u32 *numerator, u32 *denominator) { struct mt9v011 *core = to_mt9v011(sd); unsigned height, width, hblank, vblank, speed; @@ -189,6 +189,51 @@ static void calc_fps(struct v4l2_subdev *sd) v4l2_dbg(1, debug, sd, "Programmed to %u.%03u fps (%d pixel clcks)\n", tmp / 1000, tmp % 1000, t_time); + + if (numerator && denominator) { + *numerator = 1000; + *denominator = (u32)frames_per_ms; + } +} + +static u16 calc_speed(struct v4l2_subdev *sd, u32 numerator, u32 denominator) +{ + struct mt9v011 *core = to_mt9v011(sd); + unsigned height, width, hblank, vblank; + unsigned row_time, line_time; + u64 t_time, speed; + + /* Avoid bogus calculus */ + if (!numerator || !denominator) + return 0; + + height = mt9v011_read(sd, R03_MT9V011_HEIGHT); + width = mt9v011_read(sd, R04_MT9V011_WIDTH); + hblank = mt9v011_read(sd, R05_MT9V011_HBLANK); + vblank = mt9v011_read(sd, R06_MT9V011_VBLANK); + + row_time = width + 113 + hblank; + line_time = height + vblank + 1; + + t_time = core->xtal * ((u64)numerator); + /* round to the closest value */ + t_time += denominator / 2; + do_div(t_time, denominator); + + speed = t_time; + do_div(speed, row_time * line_time); + + /* Avoid having a negative value for speed */ + if (speed < 2) + speed = 0; + else + speed -= 2; + + /* Avoid speed overflow */ + if (speed > 15) + return 15; + + return (u16)speed; } static void set_res(struct v4l2_subdev *sd) @@ -217,7 +262,7 @@ static void set_res(struct v4l2_subdev *sd) mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); - calc_fps(sd); + calc_fps(sd, NULL, NULL); }; static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) @@ -332,6 +377,44 @@ static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) return 0; } +static int mt9v011_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +{ + struct v4l2_captureparm *cp = &parms->parm.capture; + + if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + memset(cp, 0, sizeof(struct v4l2_captureparm)); + cp->capability = V4L2_CAP_TIMEPERFRAME; + calc_fps(sd, + &cp->timeperframe.numerator, + &cp->timeperframe.denominator); + + return 0; +} + +static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +{ + struct v4l2_captureparm *cp = &parms->parm.capture; + struct v4l2_fract *tpf = &cp->timeperframe; + u16 speed; + + if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (cp->extendedmode != 0) + return -EINVAL; + + speed = calc_speed(sd, tpf->numerator, tpf->denominator); + + mt9v011_write(sd, R0A_MT9V011_CLK_SPEED, speed); + v4l2_dbg(1, debug, sd, "Setting speed to %d\n", speed); + + /* Recalculate and update fps info */ + calc_fps(sd, &tpf->numerator, &tpf->denominator); + + return 0; +} + static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) { struct v4l2_pix_format *pix = &fmt->fmt.pix; @@ -429,6 +512,8 @@ static const struct v4l2_subdev_video_ops mt9v011_video_ops = { .enum_fmt = mt9v011_enum_fmt, .try_fmt = mt9v011_try_fmt, .s_fmt = mt9v011_s_fmt, + .g_parm = mt9v011_g_parm, + .s_parm = mt9v011_s_parm, }; static const struct v4l2_subdev_ops mt9v011_ops = { -- cgit v1.2.3 From 4eec1f6fb9e9c0c57fac129490eadead77179246 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 6 Aug 2009 21:53:59 -0300 Subject: em28xx: Allow changing fps on webcams From: Mauro Carvalho Chehab em28xx doesn't have temporal scaling. However, on webcams, sensors are capable of changing the output rate. So, VIDIOC_[G|S]_PARM ioctls should be passed to the sensor for it to properly set frame rate. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-video.c | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 258cd38ce..f2d9564e9 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -899,6 +899,41 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) return 0; } +static int vidioc_g_parm(struct file *file, void *priv, + struct v4l2_streamparm *p) +{ + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + int rc = 0; + + if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + if (dev->board.is_webcam) + rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0, + video, g_parm, p); + else + v4l2_video_std_frame_period(dev->norm, + &p->parm.capture.timeperframe); + + return rc; +} + +static int vidioc_s_parm(struct file *file, void *priv, + struct v4l2_streamparm *p) +{ + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + + if (!dev->board.is_webcam) + return -EINVAL; + + if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p); +} + static const char *iname[] = { [EM28XX_VMUX_COMPOSITE1] = "Composite1", [EM28XX_VMUX_COMPOSITE2] = "Composite2", @@ -2011,6 +2046,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, .vidioc_s_std = vidioc_s_std, + .vidioc_g_parm = vidioc_g_parm, + .vidioc_s_parm = vidioc_s_parm, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, -- cgit v1.2.3 From 124a5014e044c9b27016719a40c1dcf0b77210bd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Aug 2009 01:09:54 -0300 Subject: m9v011: add vflip/hflip controls to control mirror/upside down From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/mt9v011.c | 53 +++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/mt9v011.c b/linux/drivers/media/video/mt9v011.c index a76d02d40..70d359d84 100644 --- a/linux/drivers/media/video/mt9v011.c +++ b/linux/drivers/media/video/mt9v011.c @@ -62,13 +62,34 @@ static struct v4l2_queryctrl mt9v011_qctrl[] = { .step = 1, .default_value = 0, .flags = 0, - }, + }, { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Mirror", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Vflip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, { + } }; struct mt9v011 { struct v4l2_subdev sd; unsigned width, height; unsigned xtal; + unsigned hflip:1; + unsigned vflip:1; u16 global_gain, red_bal, blue_bal; }; @@ -141,7 +162,6 @@ static const struct i2c_reg_value mt9v011_init_default[] = { { R0A_MT9V011_CLK_SPEED, 0x0000 }, { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, - { R20_MT9V011_READ_MODE, 0x1000 }, { R07_MT9V011_OUT_CTRL, 0x0002 }, /* chip enable */ }; @@ -265,6 +285,20 @@ static void set_res(struct v4l2_subdev *sd) calc_fps(sd, NULL, NULL); }; +static void set_read_mode(struct v4l2_subdev *sd) +{ + struct mt9v011 *core = to_mt9v011(sd); + unsigned mode = 0x1000; + + if (core->hflip) + mode |= 0x4000; + + if (core->vflip) + mode |= 0x8000; + + mt9v011_write(sd, R20_MT9V011_READ_MODE, mode); +} + static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) { int i; @@ -275,6 +309,7 @@ static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) set_balance(sd); set_res(sd); + set_read_mode(sd); return 0; }; @@ -295,6 +330,12 @@ static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_BLUE_BALANCE: ctrl->value = core->blue_bal; return 0; + case V4L2_CID_HFLIP: + ctrl->value = core->hflip ? 1 : 0; + return 0; + case V4L2_CID_VFLIP: + ctrl->value = core->vflip ? 1 : 0; + return 0; } return -EINVAL; } @@ -343,6 +384,14 @@ static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_BLUE_BALANCE: core->blue_bal = ctrl->value; break; + case V4L2_CID_HFLIP: + core->hflip = ctrl->value; + set_read_mode(sd); + return 0; + case V4L2_CID_VFLIP: + core->vflip = ctrl->value; + set_read_mode(sd); + return 0; default: return -EINVAL; } -- cgit v1.2.3 From cc7fbc37dcf48dbb639f032d01717600ccc540ea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Aug 2009 12:08:02 -0300 Subject: em28xx: fix: some em2710 chips use a different vendor ID From: Mauro Carvalho Chehab Thanks to hermann pitton for pointing this new variation. Priority: normal Tested-by: hermann pitton Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.em28xx | 2 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index 084a7b624..66e5f8295 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -1,5 +1,5 @@ 0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800] - 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883] + 1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883] 2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036] 3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208] 4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201] diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 2f4777f76..6e68d534e 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1613,6 +1613,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2750_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2800), .driver_info = EM2800_BOARD_UNKNOWN }, + { USB_DEVICE(0xeb1a, 0x2710), + .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2820), .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2821), -- cgit v1.2.3 From 3304f06c0482f2180d240ec11da525578d33868a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Aug 2009 12:13:31 -0300 Subject: em28xx: properly reports some em2710 chips From: Mauro Carvalho Chehab As reported by hermann pitton , some devices has a different chip id for em2710 (likely the older ones): em28xx: New device @ 480 Mbps (eb1a:2710, interface 0, class 0) em28xx #0: Identified as EM2710/EM2750/EM2751 webcam grabber (card=22) em28xx #0: em28xx chip ID = 17 Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 5 ++++- linux/drivers/media/video/em28xx/em28xx-reg.h | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 6e68d534e..9dddd53c7 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1914,11 +1914,14 @@ void em28xx_pre_card_setup(struct em28xx *dev) dev->chip_id = rc; switch (dev->chip_id) { + case CHIP_ID_EM2710: + em28xx_info("chip ID is em2710\n"); + break; case CHIP_ID_EM2750: em28xx_info("chip ID is em2750\n"); break; case CHIP_ID_EM2820: - em28xx_info("chip ID is em2710 or em2820\n"); + em28xx_info("chip ID is em2820 (or em2710)\n"); break; case CHIP_ID_EM2840: em28xx_info("chip ID is em2840\n"); diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index a2676d63c..6bf84bd78 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -176,7 +176,8 @@ /* FIXME: Need to be populated with the other chip ID's */ enum em28xx_chip_id { - CHIP_ID_EM2820 = 18, /* Also used by em2710 */ + CHIP_ID_EM2710 = 17, + CHIP_ID_EM2820 = 18, /* Also used by some em2710 */ CHIP_ID_EM2840 = 20, CHIP_ID_EM2750 = 33, CHIP_ID_EM2860 = 34, -- cgit v1.2.3 From eb07db27a2dcfe8263e54069db82b60c4219e670 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Aug 2009 16:48:52 +0200 Subject: v4l2-ctl: fix help message From: hermann pitton For -p (--set-parm) v4l2-ctl also prints G_PARMS too. -P, --get-parm display video parameters [VIDIOC_G_PARMS] -p, --set-parm set video rate in fps [VIDIOC_G_PARMS] Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-ctl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp index e872a2916..898c88cb7 100644 --- a/v4l2-apps/util/v4l2-ctl.cpp +++ b/v4l2-apps/util/v4l2-ctl.cpp @@ -311,7 +311,7 @@ static void usage(void) " secam-X (X = B/G/H/D/K/L/Lc) or just 'secam' (V4L2_STD_SECAM)\n" " --list-standards display supported video standards [VIDIOC_ENUMSTD]\n" " -P, --get-parm display video parameters [VIDIOC_G_PARMS]\n" - " -p, --set-parm set video rate in fps [VIDIOC_G_PARMS]\n" + " -p, --set-parm set video rate in fps [VIDIOC_S_PARMS]\n" " -T, --get-tuner query the tuner settings [VIDIOC_G_TUNER]\n" " -t, --set-tuner=\n" " set the audio mode of the tuner [VIDIOC_S_TUNER]\n" -- cgit v1.2.3 From 32405a38daa6df56e36a1569031515af7a72f192 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Aug 2009 18:43:00 -0300 Subject: em28xx-cards: remove a code that doesn't seem to affect the webcam From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 9dddd53c7..27725c0ed 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2408,10 +2408,6 @@ void em28xx_card_setup(struct em28xx *dev) em28xx_gpio_set(dev, dev->board.tuner_gpio); em28xx_set_mode(dev, EM28XX_ANALOG_MODE); break; - case EM2820_BOARD_SILVERCREST_WEBCAM: - /* FIXME: need to document the registers bellow */ - em28xx_write_reg(dev, 0x0d, 0x42); - em28xx_write_reg(dev, 0x13, 0x08); } if (dev->board.has_snapshot_button) -- cgit v1.2.3 From 3f5d03feb375c275dac631a9d5819d4d2bc25c46 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 8 Aug 2009 03:14:55 -0300 Subject: em28xx: fix: don't do image interlacing on webcams From: Mauro Carvalho Chehab Due to historical reasons, em28xx driver gets two consecutive frames and fold them into an unique framing, doing interlacing. While this works fine for TV images, this produces two bad effects with webcams: 1) webcam images are progressive. Merging two consecutive images produce interlacing artifacts on the image; 2) since the driver needs to get two frames, it reduces the maximum frame rate by two. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 4 +++ linux/drivers/media/video/em28xx/em28xx-core.c | 5 +++- linux/drivers/media/video/em28xx/em28xx-video.c | 40 +++++++++++++++++++------ linux/drivers/media/video/em28xx/em28xx.h | 3 ++ 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 27725c0ed..594461739 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2623,6 +2623,10 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, if (em28xx_hint_sensor(dev) < 0) dev->board.is_webcam = 0; + /* It makes no sense to use de-interlacing mode on webcams */ + if (dev->board.is_webcam) + dev->progressive = 1; + /* Do board specific init and eeprom reading */ em28xx_card_setup(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index a1de593ec..10da3ad82 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -720,7 +720,10 @@ int em28xx_resolution_set(struct em28xx *dev) { int width, height; width = norm_maxw(dev); - height = norm_maxh(dev) >> 1; + height = norm_maxh(dev); + + if (!dev->progressive) + height >>= norm_maxh(dev); em28xx_set_outfmt(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index f2d9564e9..77ec51dad 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -212,15 +212,24 @@ static void em28xx_copy_video(struct em28xx *dev, startread = p; remain = len; - /* Interlaces frame */ - if (buf->top_field) + if (dev->progressive) fieldstart = outp; - else - fieldstart = outp + bytesperline; + else { + /* Interlaces two half frames */ + if (buf->top_field) + fieldstart = outp; + else + fieldstart = outp + bytesperline; + } linesdone = dma_q->pos / bytesperline; currlinedone = dma_q->pos % bytesperline; - offset = linesdone * bytesperline * 2 + currlinedone; + + if (dev->progressive) + offset = linesdone * bytesperline + currlinedone; + else + offset = linesdone * bytesperline * 2 + currlinedone; + startwrite = fieldstart + offset; lencopy = bytesperline - currlinedone; lencopy = lencopy > remain ? remain : lencopy; @@ -398,7 +407,7 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], len, (p[2] & 1) ? "odd" : "even"); - if (!(p[2] & 1)) { + if (dev->progressive || !(p[2] & 1)) { if (buf != NULL) buffer_filled(dev, dma_q, buf); get_next_buf(dma_q, &buf); @@ -742,7 +751,10 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ - f->fmt.pix.field = dev->interlaced ? + if (dev->progressive) + f->fmt.pix.field = V4L2_FIELD_NONE; + else + f->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; mutex_unlock(&dev->lock); @@ -806,7 +818,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.field = V4L2_FIELD_INTERLACED; + if (dev->progressive) + f->fmt.pix.field = V4L2_FIELD_NONE; + else + f->fmt.pix.field = dev->interlaced ? + V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; return 0; } @@ -1765,6 +1781,7 @@ static int em28xx_v4l2_open(struct file *filp) struct em28xx *dev; enum v4l2_buf_type fh_type; struct em28xx_fh *fh; + enum v4l2_field field; dev = em28xx_get_device(minor, &fh_type, &radio); @@ -1821,8 +1838,13 @@ static int em28xx_v4l2_open(struct file *filp) dev->users++; + if (dev->progressive) + field = V4L2_FIELD_NONE; + else + field = V4L2_FIELD_INTERLACED; + videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, - NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, + NULL, &dev->slock, fh->type, field, sizeof(struct em28xx_buffer), fh); mutex_unlock(&dev->lock); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 3c4cd00b2..c76da6985 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -494,6 +494,9 @@ struct em28xx { int sensor_xres, sensor_yres; int sensor_xtal; + /* Allows progressive (e. g. non-interlaced) mode */ + int progressive; + /* Vinmode/Vinctl used at the driver */ int vinmode, vinctl; -- cgit v1.2.3 From 731b07aacdb288bdc2e0d55090224470c064cac0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 8 Aug 2009 03:28:41 -0300 Subject: em28xx: Adjust Silvercrest xtal frequency From: Mauro Carvalho Chehab We don't know the xtal frequency of Silvercrest, but we need to have some value in order to allow controlling the frame rate frequency. The value is probably still wrong, since the manufacturer announces this device as being capable of 30fps, but the maximum we can get is 13.5 fps. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 594461739..9a09df296 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1855,7 +1855,7 @@ static int em28xx_hint_sensor(struct em28xx *dev) dev->em28xx_sensor = EM28XX_MT9V011; dev->sensor_xres = 640; dev->sensor_yres = 480; - dev->sensor_xtal = 6300000; + dev->sensor_xtal = 12150000; /* probably means GRGB 16 bit bayer */ dev->vinmode = 0x0d; -- cgit v1.2.3 From 73dd04edca69ade43ea5604f1842feed69d35def Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 7 Aug 2009 10:32:20 +0200 Subject: pvrusb2: fix compile warning From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil CC: Mike Isely --- linux/drivers/media/video/pvrusb2/pvrusb2-audio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c index 42875ec21..d8c9e6632 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -66,9 +66,10 @@ void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) u32 input; pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo"); + sp = (sid < ARRAY_SIZE(routing_schemes)) ? + routing_schemes[sid] : NULL; - if ((sid < ARRAY_SIZE(routing_schemes)) && - ((sp = routing_schemes[sid]) != NULL) && + if ((sp != NULL) && (hdw->input_val >= 0) && (hdw->input_val < sp->cnt)) { input = sp->def[hdw->input_val]; -- cgit v1.2.3 From a1eb3529b0c857e8de54c34b526aca3e07f5b34a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 7 Aug 2009 10:50:02 +0200 Subject: cx24113: fix mips compiler warning From: Hans Verkuil do_div requires an u64 as the first argument, not a s64. Priority: normal Signed-off-by: Hans Verkuil CC: Patrick Boettcher --- linux/drivers/media/dvb/frontends/cx24113.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/frontends/cx24113.c b/linux/drivers/media/dvb/frontends/cx24113.c index e4fd533a4..075b2b57c 100644 --- a/linux/drivers/media/dvb/frontends/cx24113.c +++ b/linux/drivers/media/dvb/frontends/cx24113.c @@ -303,6 +303,7 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f) { s32 N; s64 F; + u64 dividend; u8 R, r; u8 vcodiv; u8 factor; @@ -346,7 +347,10 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f) F = freq_hz; F *= (u64) (R * vcodiv * 262144); dprintk("1 N: %d, F: %lld, R: %d\n", N, (long long)F, R); - do_div(F, state->config->xtal_khz*1000 * factor * 2); + /* do_div needs an u64 as first argument */ + dividend = F; + do_div(dividend, state->config->xtal_khz * 1000 * factor * 2); + F = dividend; dprintk("2 N: %d, F: %lld, R: %d\n", N, (long long)F, R); F -= (N + 32) * 262144; -- cgit v1.2.3 From 84ca12cecb8b0b28efb9403b9ea6da6a9589caec Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 7 Aug 2009 12:10:52 +0200 Subject: hdpvr: add missing initialization of current_norm From: Hans Verkuil Drivers should either set current_norm or supply a g_std callback. The hdpvr driver does neither. Since it initializes to a 60 Hz format I've initialized the current_norm to NTSC | PAL_M | PAL_60 which is the 60 Hz subset of tvnorms. Priority: normal Signed-off-by: Hans Verkuil CC: Janne Grunau --- linux/drivers/media/video/hdpvr/hdpvr-video.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/drivers/media/video/hdpvr/hdpvr-video.c b/linux/drivers/media/video/hdpvr/hdpvr-video.c index 5937de23c..2eb9dc2eb 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-video.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c @@ -1222,6 +1222,8 @@ static const struct video_device hdpvr_video_template = { V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_PAL_I | V4L2_STD_PAL_D | V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_60, + .current_norm = V4L2_STD_NTSC | V4L2_STD_PAL_M | + V4L2_STD_PAL_60, }; int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, -- cgit v1.2.3 From f4002f575cdc4c826c424b19d21b8979de737d64 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 7 Aug 2009 12:28:16 +0200 Subject: v4l2-ioctl: fix G_STD and G_PARM default handlers From: Hans Verkuil The v4l core supplies default handlers for G_STD and G_PARM. However, both default handlers are buggy. This patch fixes the following: 1) If no g_std is supplied and current_norm == 0, then this driver does not support TV video standards (e.g. a radio or webcam driver). Return -EINVAL. This ensures that there is no bogus VIDIOC_G_STD support for such drivers. 2) The default VIDIOC_G_PARM handler used current_norm instead of first checking if the driver supported g_std and calling that to get the norm. It also didn't check if current_norm was 0, since in that case the driver does not support TV standards (or no standard was set at all) and the default handler should return -EINVAL. Note that I am very unhappy with these default handlers: I think they basically behave like some very strange and unexpected side-effect. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-ioctl.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 80c94dc5a..d746d9555 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -1088,8 +1088,10 @@ static long __video_do_ioctl(struct file *file, /* Calls the specific handler */ if (ops->vidioc_g_std) ret = ops->vidioc_g_std(file, fh, id); - else + else if (vfd->current_norm) *id = vfd->current_norm; + else + ret = -EINVAL; if (!ret) dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id); @@ -1560,12 +1562,19 @@ static long __video_do_ioctl(struct file *file, break; ret = ops->vidioc_g_parm(file, fh, p); } else { + v4l2_std_id std = vfd->current_norm; + if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - v4l2_video_std_frame_period(vfd->current_norm, - &p->parm.capture.timeperframe); ret = 0; + if (ops->vidioc_g_std) + ret = ops->vidioc_g_std(file, fh, &std); + else if (std == 0) + ret = -EINVAL; + if (ret == 0) + v4l2_video_std_frame_period(std, + &p->parm.capture.timeperframe); } dbgarg(cmd, "type=%d\n", p->type); -- cgit v1.2.3 From 9bd841d241b9c9c46b86a860a279d3c576b5ca90 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 7 Aug 2009 12:39:31 +0200 Subject: v4l2-ctl: fix get/set-parm bugs and add get/set-output-parm support From: Hans Verkuil Fixed several get/set-parm bugs, cleaned it up a bit and reformatted the output to conform to the output of the other get options. Implemented get/set-output-parm to complete the VIDIOC_G/S_PARM support. Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/util/v4l2-ctl.cpp | 98 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 19 deletions(-) diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp index 898c88cb7..60ebc5474 100644 --- a/v4l2-apps/util/v4l2-ctl.cpp +++ b/v4l2-apps/util/v4l2-ctl.cpp @@ -136,6 +136,8 @@ enum Option { OptGetModulator, OptSetModulator, OptListDevices, + OptGetOutputParm, + OptSetOutputParm, OptLast = 256 }; @@ -226,6 +228,8 @@ static struct option long_options[] = { {"set-standard", required_argument, 0, OptSetStandard}, {"get-parm", no_argument, 0, OptGetParm}, {"set-parm", required_argument, 0, OptSetParm}, + {"get-output-parm", no_argument, 0, OptGetOutputParm}, + {"set-output-parm", required_argument, 0, OptSetOutputParm}, {"info", no_argument, 0, OptGetDriverInfo}, {"list-ctrls", no_argument, 0, OptListCtrls}, {"list-ctrls-menus", no_argument, 0, OptListCtrlsMenus}, @@ -310,8 +314,9 @@ static void usage(void) " ntsc-X (X = M/J/K) or just 'ntsc' (V4L2_STD_NTSC)\n" " secam-X (X = B/G/H/D/K/L/Lc) or just 'secam' (V4L2_STD_SECAM)\n" " --list-standards display supported video standards [VIDIOC_ENUMSTD]\n" - " -P, --get-parm display video parameters [VIDIOC_G_PARMS]\n" - " -p, --set-parm set video rate in fps [VIDIOC_S_PARMS]\n" + " -P, --get-parm display video parameters [VIDIOC_G_PARM]\n" + " -p, --set-parm=\n" + " set video framerate in [VIDIOC_S_PARM]\n" " -T, --get-tuner query the tuner settings [VIDIOC_G_TUNER]\n" " -t, --set-tuner=\n" " set the audio mode of the tuner [VIDIOC_S_TUNER]\n" @@ -424,6 +429,9 @@ static void usage(void) " bilingual: Modulate as bilingual\n" " mono-sap: Modulate as mono with Second Audio Program\n" " stereo-sap: Modulate as stereo with Second Audio Program\n" + " --get-output-parm display output video parameters [VIDIOC_G_PARM]\n" + " --set-output-parm=\n" + " set output video framerate in [VIDIOC_S_PARM]\n" "\n"); printf("Expert options:\n" " --streamoff turn the stream off [VIDIOC_STREAMOFF]\n" @@ -830,7 +838,7 @@ static void printcropcap(const struct v4l2_cropcap &cropcap) printf("\tPixel Aspect: %u/%u\n", cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator); } -static void printfmt(struct v4l2_format vfmt) +static void printfmt(const struct v4l2_format &vfmt) { const flag_def vbi_def[] = { { V4L2_VBI_UNSYNC, "unsynchronized" }, @@ -1431,7 +1439,8 @@ int main(int argc, char **argv) int txsubchans; /* set_modulator */ v4l2_std_id std; /* get_std/set_std */ double freq = 0; /* get/set frequency */ - double fps = 0; /* set framerate speed, in fps */ + double fps = 0; /* set framerate speed, in fps */ + double output_fps = 0; /* set framerate speed, in fps */ struct v4l2_frequency vf; /* get_freq/set_freq */ struct v4l2_standard vs; /* list_std */ int overlay; /* overlay */ @@ -1701,6 +1710,9 @@ int main(int argc, char **argv) case OptSetParm: fps = strtod(optarg, NULL); break; + case OptSetOutputParm: + output_fps = strtod(optarg, NULL); + break; case OptGetCtrl: subs = optarg; while (*subs != '\0') { @@ -1927,6 +1939,7 @@ int main(int argc, char **argv) options[OptGetAudioOutput] = 1; options[OptGetStandard] = 1; options[OptGetParm] = 1; + options[OptGetOutputParm] = 1; options[OptGetFreq] = 1; options[OptGetTuner] = 1; options[OptGetModulator] = 1; @@ -1990,18 +2003,38 @@ int main(int argc, char **argv) if (options[OptSetParm]) { - memset (&parm, 0, sizeof(parm)); + memset(&parm, 0, sizeof(parm)); parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; parm.parm.capture.timeperframe.numerator = 1000; - parm.parm.capture.timeperframe.denominator = (__u32)(fps * parm.parm.capture.timeperframe.numerator); + parm.parm.capture.timeperframe.denominator = + fps * parm.parm.capture.timeperframe.numerator; if (doioctl(fd, VIDIOC_S_PARM, &parm, "VIDIOC_S_PARM") == 0) { struct v4l2_fract *tf = &parm.parm.capture.timeperframe; + if (!tf->denominator || !tf->numerator) - printf ("Invalid frame rate\n"); + printf("Invalid frame rate\n"); else - printf("Frame rate set to: %.3f fps\n", - 1.0*tf->denominator/tf->numerator); + printf("Frame rate set to %.3f fps\n", + 1.0 * tf->denominator / tf->numerator); + } + } + + if (options[OptSetOutputParm]) { + memset(&parm, 0, sizeof(parm)); + parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + parm.parm.output.timeperframe.numerator = 1000; + parm.parm.output.timeperframe.denominator = + fps * parm.parm.output.timeperframe.numerator; + + if (doioctl(fd, VIDIOC_S_PARM, &parm, "VIDIOC_S_PARM") == 0) { + struct v4l2_fract *tf = &parm.parm.output.timeperframe; + + if (!tf->denominator || !tf->numerator) + printf("Invalid frame rate\n"); + else + printf("Frame rate set to %.3f fps\n", + 1.0 * tf->denominator / tf->numerator); } } @@ -2481,19 +2514,46 @@ set_vid_fmt_error: } if (options[OptGetParm]) { - memset (&parm, 0, sizeof(parm)); + memset(&parm, 0, sizeof(parm)); parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (doioctl(fd, VIDIOC_G_PARM, &parm, "VIDIOC_G_PARM") == 0) { - struct v4l2_fract *tf = &parm.parm.capture.timeperframe; - if (parm.parm.capture.capability & V4L2_MODE_HIGHQUALITY) - printf("Has High quality imaging mode\n"); - if (parm.parm.capture.capability && V4L2_CAP_TIMEPERFRAME) - printf("Has V4L2_CAP_TIMEPERFRAME\n"); - if (!tf->denominator || !tf->numerator) - printf ("Invalid frame rate\n"); + const struct v4l2_fract &tf = parm.parm.capture.timeperframe; + + printf("Streaming Parameters %s:\n", buftype2s(parm.type).c_str()); + if (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) + printf("\tCapabilities : timeperframe\n"); + if (parm.parm.capture.capturemode & V4L2_MODE_HIGHQUALITY) + printf("\tCapture mode : high quality\n"); + if (!tf.denominator || !tf.numerator) + printf("\tFrames per second: invalid (%d/%d)\n", + tf.denominator, tf.numerator); + else + printf("\tFrames per second: %.3f (%d/%d)\n", + (1.0 * tf.denominator) / tf.numerator, + tf.denominator, tf.numerator); + printf("\tRead buffers : %d\n", parm.parm.output.writebuffers); + } + } + + if (options[OptGetOutputParm]) { + memset(&parm, 0, sizeof(parm)); + parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + if (doioctl(fd, VIDIOC_G_PARM, &parm, "VIDIOC_G_PARM") == 0) { + const struct v4l2_fract &tf = parm.parm.output.timeperframe; + + printf("Streaming Parameters %s:\n", buftype2s(parm.type).c_str()); + if (parm.parm.output.capability & V4L2_CAP_TIMEPERFRAME) + printf("\tCapabilities : timeperframe\n"); + if (parm.parm.output.outputmode & V4L2_MODE_HIGHQUALITY) + printf("\tOutput mode : high quality\n"); + if (!tf.denominator || !tf.numerator) + printf("\tFrames per second: invalid (%d/%d)\n", + tf.denominator, tf.numerator); else - printf("Frame rate is %.3f fps\n", - (1.0 * tf->denominator) / tf->numerator); + printf("\tFrames per second: %.3f (%d/%d)\n", + (1.0 * tf.denominator) / tf.numerator, + tf.denominator, tf.numerator); + printf("\tWrite buffers : %d\n", parm.parm.output.writebuffers); } } -- cgit v1.2.3 From 2ba96e655011fe3e04a32e5498ef82485b930c6f Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 7 Aug 2009 08:25:06 -0400 Subject: em28xx: fix regression in Empire DualTV digital tuning From: Devin Heitmueller Restore support for digital tuning caused by regression during introduction of disable_i2c_gate parameter to zl10353 driver. Thanks to user "Xwang" for reporting the problem and testing the fix Priority: high Cc: Xwang Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-dvb.c b/linux/drivers/media/video/em28xx/em28xx-dvb.c index e32267383..3d522d547 100644 --- a/linux/drivers/media/video/em28xx/em28xx-dvb.c +++ b/linux/drivers/media/video/em28xx/em28xx-dvb.c @@ -479,7 +479,6 @@ static int dvb_init(struct em28xx *dev) } break; case EM2880_BOARD_KWORLD_DVB_310U: - case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_with_xc3028, &dev->i2c_adap); @@ -489,6 +488,7 @@ static int dvb_init(struct em28xx *dev) } break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: + case EM2880_BOARD_EMPIRE_DUAL_TV: dvb->frontend = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap); -- cgit v1.2.3 From d029b650929bd8c6cda3c88135a3b754ca6ae0bb Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sat, 8 Aug 2009 12:58:52 -0300 Subject: strlcpy() will always null terminate the string. From: Roel Kluin Priority: normal Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c | 2 +- linux/drivers/media/video/pwc/pwc-v4l.c | 2 +- linux/drivers/media/video/zoran/zoran_card.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c index 326f76089..cead089bb 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c @@ -19,7 +19,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d) return -EINVAL; } - strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); + strlcpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); d->i2c_adap.class = I2C_CLASS_TV_DIGITAL, d->i2c_adap.algo = d->props.i2c_algo; d->i2c_adap.algo_data = NULL; diff --git a/linux/drivers/media/video/pwc/pwc-v4l.c b/linux/drivers/media/video/pwc/pwc-v4l.c index 2876ce084..bdb4ced57 100644 --- a/linux/drivers/media/video/pwc/pwc-v4l.c +++ b/linux/drivers/media/video/pwc/pwc-v4l.c @@ -1033,7 +1033,7 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (std->index != 0) return -EINVAL; std->id = V4L2_STD_UNKNOWN; - strncpy(std->name, "webcam", sizeof(std->name)); + strlcpy(std->name, "webcam", sizeof(std->name)); return 0; } diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 217fec9e4..375f158fd 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -1169,7 +1169,7 @@ zoran_setup_videocodec (struct zoran *zr, m->type = 0; m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER; - strncpy(m->name, ZR_DEVNAME(zr), sizeof(m->name)); + strlcpy(m->name, ZR_DEVNAME(zr), sizeof(m->name)); m->data = zr; switch (type) -- cgit v1.2.3 From b876feaf9b088d50b7519f8d6bbf15be977cd325 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 10 Aug 2009 22:17:25 -0300 Subject: stk-webcam: read buffer overflow From: Roel Kluin It tested the value of stk_sizes[i].m before checking whether i was in range. Priority: normal Signed-off-by: Roel Kluin Cc: Hans Verkuil Cc: Trent Piepho Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/stk-webcam.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 849867ab2..aaeee8319 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -1051,8 +1051,8 @@ static int stk_setup_format(struct stk_camera *dev) depth = 1; else depth = 2; - while (stk_sizes[i].m != dev->vsettings.mode - && i < ARRAY_SIZE(stk_sizes)) + while (i < ARRAY_SIZE(stk_sizes) && + stk_sizes[i].m != dev->vsettings.mode) i++; if (i == ARRAY_SIZE(stk_sizes)) { STK_ERROR("Something is broken in %s\n", __func__); -- cgit v1.2.3 From b8961acc4142f124a11a2b33594790dc49dd194a Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 10 Aug 2009 20:59:16 -0400 Subject: dvb: siano uses/depends on INPUT From: Randy Dunlap siano uses input_*() functions so it should depend on INPUT to prevent build errors: ERROR: "input_event" [drivers/media/dvb/siano/sms1xxx.ko] undefined! ERROR: "input_register_device" [drivers/media/dvb/siano/sms1xxx.ko] undefined! ERROR: "input_free_device" [drivers/media/dvb/siano/sms1xxx.ko] undefined! ERROR: "input_unregister_device" [drivers/media/dvb/siano/sms1xxx.ko] undefined! ERROR: "input_allocate_device" [drivers/media/dvb/siano/sms1xxx.ko] undefined! Priority: normal Signed-off-by: Randy Dunlap Cc: Michael Krufky Cc: Uri Shkolnik Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/dvb/siano/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/siano/Kconfig b/linux/drivers/media/dvb/siano/Kconfig index dd863f261..88847d1dc 100644 --- a/linux/drivers/media/dvb/siano/Kconfig +++ b/linux/drivers/media/dvb/siano/Kconfig @@ -4,7 +4,7 @@ config DVB_SIANO_SMS1XXX tristate "Siano SMS1XXX USB dongle support" - depends on DVB_CORE && USB + depends on DVB_CORE && USB && INPUT ---help--- Choose Y here if you have a USB dongle with a SMS1XXX chipset. -- cgit v1.2.3 From b889b807125e28911afda8c7740b18658aeb96fe Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 10 Aug 2009 21:07:54 -0400 Subject: Read buffer overflow From: Roel Kluin parport[n] is checked before n < MAX_CAMS Priority: normal Signed-off-by: Roel Kluin Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/bw-qcam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/bw-qcam.c b/linux/drivers/media/video/bw-qcam.c index 3702baad6..8f6bb845e 100644 --- a/linux/drivers/media/video/bw-qcam.c +++ b/linux/drivers/media/video/bw-qcam.c @@ -993,7 +993,7 @@ static int accept_bwqcam(struct parport *port) if (parport[0] && strncmp(parport[0], "auto", 4) != 0) { /* user gave parport parameters */ - for(n=0; parport[n] && n Date: Mon, 10 Aug 2009 21:15:54 -0400 Subject: cx88: add support for WinFast DTV2000H rev. J From: Vlastimil Labsky I updated and simplyfied patch from Zbynek Hrabovsky for recent kernel. It enables autodetection of card, sound in analog TV , sound in FM radio and switching between antenna and cable RF input. Radio tuner still doesn't work, I don't even know how it works. Some guys wrote me that FM radio works with TV tuner used instead of radio part (symlink video0 -> radio0). Priority: normal Signed-off-by: Vlastimil Labsky Cc: Gerd Knorr Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf --- linux/Documentation/video4linux/CARDLIST.cx88 | 1 + linux/drivers/media/video/cx88/cx88-cards.c | 49 +++++++++++++++++++++++++++ linux/drivers/media/video/cx88/cx88-dvb.c | 1 + linux/drivers/media/video/cx88/cx88-input.c | 1 + linux/drivers/media/video/cx88/cx88.h | 1 + 5 files changed, 53 insertions(+) diff --git a/linux/Documentation/video4linux/CARDLIST.cx88 b/linux/Documentation/video4linux/CARDLIST.cx88 index 0736518b2..3385f8b09 100644 --- a/linux/Documentation/video4linux/CARDLIST.cx88 +++ b/linux/Documentation/video4linux/CARDLIST.cx88 @@ -80,3 +80,4 @@ 79 -> Terratec Cinergy HT PCI MKII [153b:1177] 80 -> Hauppauge WinTV-IR Only [0070:9290] 81 -> Leadtek WinFast DTV1800 Hybrid [107d:6654] + 82 -> WinFast DTV2000 H rev. J [107d:6f2b] diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 67ccc59a7..19d57e698 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -1316,6 +1316,51 @@ static const struct cx88_board cx88_boards[] = { }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_WINFAST_DTV2000H_J] = { + .name = "WinFast DTV2000 H rev. J", + .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00017300, + .gpio1 = 0x00008207, + .gpio2 = 0x00000000, + .gpio3 = 0x02000000, + },{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00018300, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00018301, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00018301, + .gpio1 = 0x0000f207, + .gpio2 = 0x00017304, + .gpio3 = 0x02000000, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x00015702, + .gpio1 = 0x0000f207, + .gpio2 = 0x00015702, + .gpio3 = 0x02000000, + }, + .mpeg = CX88_MPEG_DVB, + }, [CX88_BOARD_GENIATECH_DVBS] = { .name = "Geniatech DVB-S", .tuner_type = TUNER_ABSENT, @@ -2314,6 +2359,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x107d, .subdevice = 0x665e, .card = CX88_BOARD_WINFAST_DTV2000H, + },{ + .subvendor = 0x107d, + .subdevice = 0x6f2b, + .card = CX88_BOARD_WINFAST_DTV2000H_J, },{ .subvendor = 0x18ac, .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */ diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 9c88b6c0f..ab84c085f 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -703,6 +703,7 @@ static int dvb_register(struct cx8802_dev *dev) } break; case CX88_BOARD_WINFAST_DTV2000H: + case CX88_BOARD_WINFAST_DTV2000H_J: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: case CX88_BOARD_HAUPPAUGE_HVR1300: diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index 7c5e94916..8d0042ab2 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -238,6 +238,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: + case CX88_BOARD_WINFAST_DTV2000H_J: case CX88_BOARD_WINFAST_DTV1800H: ir_codes = ir_codes_winfast; ir->gpio_addr = MO_GP0_IO; diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 59fc01a53..014004acd 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -238,6 +238,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79 #define CX88_BOARD_HAUPPAUGE_IRONLY 80 #define CX88_BOARD_WINFAST_DTV1800H 81 +#define CX88_BOARD_WINFAST_DTV2000H_J 82 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 84b86128572d1cef2f921fda840e365d8f01bdee Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 10 Aug 2009 21:51:01 -0400 Subject: Use kzalloc for frontend states to have struct dvb_frontend properly From: Matthias Schwarzott This patch changes most frontend drivers to allocate their state structure via kzalloc and not kmalloc. This is done to properly initialize the embedded "struct dvb_frontend frontend" field, that they all have. The visible effect of this struct being uninitalized is, that the member "id" that is used to set the name of kernel thread is totally random. Some board drivers (for example cx88-dvb) set this "id" via videobuf_dvb_alloc_frontend but most do not. So I at least get random id values for saa7134, flexcop and ttpci based cards. It looks like this in dmesg: DVB: registering adapter 1 frontend -10551321 (ST STV0299 DVB-S) The related kernel thread then also gets a strange name like "kdvb-ad-1-fe--1". Priority: normal Signed-off-by: Matthias Schwarzott CC: Michael Krufky CC: Steven Toth CC: Timothy Lee CC: Igor M. Liplianin Acked-by: Andreas Oberritter Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/dvb/frontends/at76c651.c | 2 +- linux/drivers/media/dvb/frontends/cx22700.c | 2 +- linux/drivers/media/dvb/frontends/cx22702.c | 2 +- linux/drivers/media/dvb/frontends/cx24110.c | 2 +- linux/drivers/media/dvb/frontends/dvb_dummy_fe.c | 6 +++--- linux/drivers/media/dvb/frontends/l64781.c | 2 +- linux/drivers/media/dvb/frontends/lgs8gl5.c | 2 +- linux/drivers/media/dvb/frontends/mt312.c | 2 +- linux/drivers/media/dvb/frontends/nxt6000.c | 2 +- linux/drivers/media/dvb/frontends/or51132.c | 2 +- linux/drivers/media/dvb/frontends/or51211.c | 2 +- linux/drivers/media/dvb/frontends/s5h1409.c | 2 +- linux/drivers/media/dvb/frontends/s5h1411.c | 2 +- linux/drivers/media/dvb/frontends/si21xx.c | 2 +- linux/drivers/media/dvb/frontends/sp8870.c | 2 +- linux/drivers/media/dvb/frontends/sp887x.c | 2 +- linux/drivers/media/dvb/frontends/stv0288.c | 2 +- linux/drivers/media/dvb/frontends/stv0297.c | 2 +- linux/drivers/media/dvb/frontends/stv0299.c | 2 +- linux/drivers/media/dvb/frontends/tda10021.c | 2 +- linux/drivers/media/dvb/frontends/tda10048.c | 2 +- linux/drivers/media/dvb/frontends/tda1004x.c | 4 ++-- linux/drivers/media/dvb/frontends/tda10086.c | 2 +- linux/drivers/media/dvb/frontends/tda8083.c | 2 +- linux/drivers/media/dvb/frontends/tda80xx.c | 2 +- linux/drivers/media/dvb/frontends/ves1820.c | 2 +- linux/drivers/media/dvb/frontends/ves1x93.c | 2 +- 27 files changed, 30 insertions(+), 30 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/at76c651.c b/linux/drivers/media/dvb/frontends/at76c651.c index 33486d54c..510e08f5a 100644 --- a/linux/drivers/media/dvb/frontends/at76c651.c +++ b/linux/drivers/media/dvb/frontends/at76c651.c @@ -369,7 +369,7 @@ struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, struct at76c651_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL); + state = kzalloc(sizeof(struct at76c651_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/cx22700.c b/linux/drivers/media/dvb/frontends/cx22700.c index ace5cb171..fbd838eca 100644 --- a/linux/drivers/media/dvb/frontends/cx22700.c +++ b/linux/drivers/media/dvb/frontends/cx22700.c @@ -380,7 +380,7 @@ struct dvb_frontend* cx22700_attach(const struct cx22700_config* config, struct cx22700_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct cx22700_state), GFP_KERNEL); + state = kzalloc(sizeof(struct cx22700_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/cx22702.c b/linux/drivers/media/dvb/frontends/cx22702.c index 5d1abe34b..00b5c7e91 100644 --- a/linux/drivers/media/dvb/frontends/cx22702.c +++ b/linux/drivers/media/dvb/frontends/cx22702.c @@ -580,7 +580,7 @@ struct dvb_frontend *cx22702_attach(const struct cx22702_config *config, struct cx22702_state *state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct cx22702_state), GFP_KERNEL); + state = kzalloc(sizeof(struct cx22702_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/cx24110.c b/linux/drivers/media/dvb/frontends/cx24110.c index 87ae29db0..ffbcfabd8 100644 --- a/linux/drivers/media/dvb/frontends/cx24110.c +++ b/linux/drivers/media/dvb/frontends/cx24110.c @@ -598,7 +598,7 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, int ret; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct cx24110_state), GFP_KERNEL); + state = kzalloc(sizeof(struct cx24110_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c b/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c index db8a937cc..a7fc7e53a 100644 --- a/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c +++ b/linux/drivers/media/dvb/frontends/dvb_dummy_fe.c @@ -117,7 +117,7 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void) struct dvb_dummy_fe_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); if (state == NULL) goto error; /* create dvb_frontend */ @@ -137,7 +137,7 @@ struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void) struct dvb_dummy_fe_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); if (state == NULL) goto error; /* create dvb_frontend */ @@ -157,7 +157,7 @@ struct dvb_frontend *dvb_dummy_fe_qam_attach(void) struct dvb_dummy_fe_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); + state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); if (state == NULL) goto error; /* create dvb_frontend */ diff --git a/linux/drivers/media/dvb/frontends/l64781.c b/linux/drivers/media/dvb/frontends/l64781.c index e1e70e9e0..3051b64aa 100644 --- a/linux/drivers/media/dvb/frontends/l64781.c +++ b/linux/drivers/media/dvb/frontends/l64781.c @@ -501,7 +501,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config, { .addr = config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct l64781_state), GFP_KERNEL); + state = kzalloc(sizeof(struct l64781_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/lgs8gl5.c b/linux/drivers/media/dvb/frontends/lgs8gl5.c index 380ae1868..8780905bc 100644 --- a/linux/drivers/media/dvb/frontends/lgs8gl5.c +++ b/linux/drivers/media/dvb/frontends/lgs8gl5.c @@ -411,7 +411,7 @@ lgs8gl5_attach(const struct lgs8gl5_config *config, struct i2c_adapter *i2c) dprintk("%s\n", __func__); /* Allocate memory for the internal state */ - state = kmalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL); + state = kzalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/mt312.c b/linux/drivers/media/dvb/frontends/mt312.c index f348f8bea..4d14f084d 100644 --- a/linux/drivers/media/dvb/frontends/mt312.c +++ b/linux/drivers/media/dvb/frontends/mt312.c @@ -784,7 +784,7 @@ struct dvb_frontend *mt312_attach(const struct mt312_config *config, struct mt312_state *state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL); + state = kzalloc(sizeof(struct mt312_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/nxt6000.c b/linux/drivers/media/dvb/frontends/nxt6000.c index 0eef22dbf..a763ec756 100644 --- a/linux/drivers/media/dvb/frontends/nxt6000.c +++ b/linux/drivers/media/dvb/frontends/nxt6000.c @@ -545,7 +545,7 @@ struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, struct nxt6000_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct nxt6000_state), GFP_KERNEL); + state = kzalloc(sizeof(struct nxt6000_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/or51132.c b/linux/drivers/media/dvb/frontends/or51132.c index 8133ea3cd..38e67accb 100644 --- a/linux/drivers/media/dvb/frontends/or51132.c +++ b/linux/drivers/media/dvb/frontends/or51132.c @@ -562,7 +562,7 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config, struct or51132_state* state = NULL; /* Allocate memory for the internal state */ - state = kmalloc(sizeof(struct or51132_state), GFP_KERNEL); + state = kzalloc(sizeof(struct or51132_state), GFP_KERNEL); if (state == NULL) return NULL; diff --git a/linux/drivers/media/dvb/frontends/or51211.c b/linux/drivers/media/dvb/frontends/or51211.c index 16cf2fdd5..c709ce677 100644 --- a/linux/drivers/media/dvb/frontends/or51211.c +++ b/linux/drivers/media/dvb/frontends/or51211.c @@ -527,7 +527,7 @@ struct dvb_frontend* or51211_attach(const struct or51211_config* config, struct or51211_state* state = NULL; /* Allocate memory for the internal state */ - state = kmalloc(sizeof(struct or51211_state), GFP_KERNEL); + state = kzalloc(sizeof(struct or51211_state), GFP_KERNEL); if (state == NULL) return NULL; diff --git a/linux/drivers/media/dvb/frontends/s5h1409.c b/linux/drivers/media/dvb/frontends/s5h1409.c index 3e08d985d..fb3011518 100644 --- a/linux/drivers/media/dvb/frontends/s5h1409.c +++ b/linux/drivers/media/dvb/frontends/s5h1409.c @@ -796,7 +796,7 @@ struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config, u16 reg; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL); + state = kzalloc(sizeof(struct s5h1409_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/s5h1411.c b/linux/drivers/media/dvb/frontends/s5h1411.c index 66e2dd6d6..d8adf1e32 100644 --- a/linux/drivers/media/dvb/frontends/s5h1411.c +++ b/linux/drivers/media/dvb/frontends/s5h1411.c @@ -844,7 +844,7 @@ struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config, u16 reg; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct s5h1411_state), GFP_KERNEL); + state = kzalloc(sizeof(struct s5h1411_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/si21xx.c b/linux/drivers/media/dvb/frontends/si21xx.c index 216a532ab..ee0a0a2dd 100644 --- a/linux/drivers/media/dvb/frontends/si21xx.c +++ b/linux/drivers/media/dvb/frontends/si21xx.c @@ -1003,7 +1003,7 @@ struct dvb_frontend *si21xx_attach(const struct si21xx_config *config, dprintk("%s\n", __func__); /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct si21xx_state), GFP_KERNEL); + state = kzalloc(sizeof(struct si21xx_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/sp8870.c b/linux/drivers/media/dvb/frontends/sp8870.c index 1c9a9b405..b85eb60a8 100644 --- a/linux/drivers/media/dvb/frontends/sp8870.c +++ b/linux/drivers/media/dvb/frontends/sp8870.c @@ -557,7 +557,7 @@ struct dvb_frontend* sp8870_attach(const struct sp8870_config* config, struct sp8870_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct sp8870_state), GFP_KERNEL); + state = kzalloc(sizeof(struct sp8870_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/sp887x.c b/linux/drivers/media/dvb/frontends/sp887x.c index 559509ab4..4a7c3d842 100644 --- a/linux/drivers/media/dvb/frontends/sp887x.c +++ b/linux/drivers/media/dvb/frontends/sp887x.c @@ -557,7 +557,7 @@ struct dvb_frontend* sp887x_attach(const struct sp887x_config* config, struct sp887x_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct sp887x_state), GFP_KERNEL); + state = kzalloc(sizeof(struct sp887x_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/stv0288.c b/linux/drivers/media/dvb/frontends/stv0288.c index ff1194de3..2930a5d67 100644 --- a/linux/drivers/media/dvb/frontends/stv0288.c +++ b/linux/drivers/media/dvb/frontends/stv0288.c @@ -570,7 +570,7 @@ struct dvb_frontend *stv0288_attach(const struct stv0288_config *config, int id; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct stv0288_state), GFP_KERNEL); + state = kzalloc(sizeof(struct stv0288_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/stv0297.c b/linux/drivers/media/dvb/frontends/stv0297.c index 1c5a0ae82..2e709a7a5 100644 --- a/linux/drivers/media/dvb/frontends/stv0297.c +++ b/linux/drivers/media/dvb/frontends/stv0297.c @@ -663,7 +663,7 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config, struct stv0297_state *state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct stv0297_state), GFP_KERNEL); + state = kzalloc(sizeof(struct stv0297_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/stv0299.c b/linux/drivers/media/dvb/frontends/stv0299.c index 6c1cb1973..968874469 100644 --- a/linux/drivers/media/dvb/frontends/stv0299.c +++ b/linux/drivers/media/dvb/frontends/stv0299.c @@ -667,7 +667,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, int id; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct stv0299_state), GFP_KERNEL); + state = kzalloc(sizeof(struct stv0299_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/tda10021.c b/linux/drivers/media/dvb/frontends/tda10021.c index c6f90f33a..242636e59 100644 --- a/linux/drivers/media/dvb/frontends/tda10021.c +++ b/linux/drivers/media/dvb/frontends/tda10021.c @@ -413,7 +413,7 @@ struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, u8 id; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda10021_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda10021_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/tda10048.c b/linux/drivers/media/dvb/frontends/tda10048.c index edf5a19a3..fd8c4cf00 100644 --- a/linux/drivers/media/dvb/frontends/tda10048.c +++ b/linux/drivers/media/dvb/frontends/tda10048.c @@ -1100,7 +1100,7 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config, dprintk(1, "%s()\n", __func__); /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda10048_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/tda1004x.c b/linux/drivers/media/dvb/frontends/tda1004x.c index 4981cef8b..f2a8abe0a 100644 --- a/linux/drivers/media/dvb/frontends/tda1004x.c +++ b/linux/drivers/media/dvb/frontends/tda1004x.c @@ -1269,7 +1269,7 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, int id; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); if (!state) { printk(KERN_ERR "Can't alocate memory for tda10045 state\n"); return NULL; @@ -1339,7 +1339,7 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, int id; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL); if (!state) { printk(KERN_ERR "Can't alocate memory for tda10046 state\n"); return NULL; diff --git a/linux/drivers/media/dvb/frontends/tda10086.c b/linux/drivers/media/dvb/frontends/tda10086.c index c749f96c2..502ce67cf 100644 --- a/linux/drivers/media/dvb/frontends/tda10086.c +++ b/linux/drivers/media/dvb/frontends/tda10086.c @@ -746,7 +746,7 @@ struct dvb_frontend* tda10086_attach(const struct tda10086_config* config, dprintk ("%s\n", __func__); /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda10086_state), GFP_KERNEL); if (!state) return NULL; diff --git a/linux/drivers/media/dvb/frontends/tda8083.c b/linux/drivers/media/dvb/frontends/tda8083.c index 5b843b2e6..9369f7442 100644 --- a/linux/drivers/media/dvb/frontends/tda8083.c +++ b/linux/drivers/media/dvb/frontends/tda8083.c @@ -417,7 +417,7 @@ struct dvb_frontend* tda8083_attach(const struct tda8083_config* config, struct tda8083_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda8083_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda8083_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/tda80xx.c b/linux/drivers/media/dvb/frontends/tda80xx.c index 83fc57a22..e04fd984f 100644 --- a/linux/drivers/media/dvb/frontends/tda80xx.c +++ b/linux/drivers/media/dvb/frontends/tda80xx.c @@ -646,7 +646,7 @@ struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config, int ret; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda80xx_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c index a184597f1..6e78e4865 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.c +++ b/linux/drivers/media/dvb/frontends/ves1820.c @@ -374,7 +374,7 @@ struct dvb_frontend* ves1820_attach(const struct ves1820_config* config, struct ves1820_state* state = NULL; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct ves1820_state), GFP_KERNEL); + state = kzalloc(sizeof(struct ves1820_state), GFP_KERNEL); if (state == NULL) goto error; diff --git a/linux/drivers/media/dvb/frontends/ves1x93.c b/linux/drivers/media/dvb/frontends/ves1x93.c index bd558960b..8d7854c2f 100644 --- a/linux/drivers/media/dvb/frontends/ves1x93.c +++ b/linux/drivers/media/dvb/frontends/ves1x93.c @@ -456,7 +456,7 @@ struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, u8 identity; /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL); + state = kzalloc(sizeof(struct ves1x93_state), GFP_KERNEL); if (state == NULL) goto error; /* setup the state */ -- cgit v1.2.3 From 1537b0475bd1f694226d14373ed31298f2d0e8ef Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 10 Aug 2009 21:59:33 -0400 Subject: siano: read buffer overflow From: Roel Kluin With mode DEVICE_MODE_RAW_TUNER a read occurs past the end of smscore_fw_lkup[]. Subsequently an attempt is made to load the firmware from the resulting filename. Priority: normal Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/dvb/siano/smscoreapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c index 54f59f24e..c0306af09 100644 --- a/linux/drivers/media/dvb/siano/smscoreapi.c +++ b/linux/drivers/media/dvb/siano/smscoreapi.c @@ -816,7 +816,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) sms_debug("set device mode to %d", mode); if (coredev->device_flags & SMS_DEVICE_FAMILY2) { - if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER) { + if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) { sms_err("invalid mode specified %d", mode); return -EINVAL; } -- cgit v1.2.3 From 796c449e9807bc070a33bcbbab2f4cae6cfc6d14 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 9 Aug 2009 12:14:26 +0200 Subject: fix device match logic From: Laurent Pinchart I forgot to change USB_DEVICE_ID_MATCH_VENDOR to USB_DEVICE_ID_MATCH_DEVICE in the last commit, defeating its whole purpose. Fix this. kernel-sync: Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/uvc/uvc_driver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c index fa13b6765..09b2e4ad5 100644 --- a/linux/drivers/media/video/uvc/uvc_driver.c +++ b/linux/drivers/media/video/uvc/uvc_driver.c @@ -1996,7 +1996,7 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_STREAM_NO_FID }, /* ViMicro Vega */ - { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x0ac8, .idProduct = 0x332d, @@ -2005,7 +2005,7 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, /* ViMicro - Minoru3D */ - { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x0ac8, .idProduct = 0x3410, @@ -2014,7 +2014,7 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_FIX_BANDWIDTH }, /* ViMicro Venus - Minoru3D */ - { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x0ac8, .idProduct = 0x3420, -- cgit v1.2.3 From 69f4f9ea01bb7203787bb5ba9cf384944660dd3f Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Tue, 11 Aug 2009 13:10:25 +0200 Subject: zr364: wrong indexes From: Roel Kluin The order of indexes is reversed Priority: high Signed-off-by: Roel Kluin Signed-off-by: Antoine Jacquet --- linux/drivers/media/video/zr364xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/zr364xx.c b/linux/drivers/media/video/zr364xx.c index c298ce625..ee5534230 100644 --- a/linux/drivers/media/video/zr364xx.c +++ b/linux/drivers/media/video/zr364xx.c @@ -1367,7 +1367,7 @@ static int zr364xx_release(struct file *file) for (i = 0; i < 2; i++) { err = send_control_msg(udev, 1, init[cam->method][i].value, - 0, init[i][cam->method].bytes, + 0, init[cam->method][i].bytes, init[cam->method][i].size); if (err < 0) { dev_err(&udev->dev, "error during release sequence\n"); -- cgit v1.2.3 From ba4502fc619943b78f8231e8889f9799bf12de61 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Aug 2009 15:10:20 +0200 Subject: radio-typhoon: remove obsolete RADIO_TYPHOON_PROC_FS config option From: Hans Verkuil Thanks to Robert P.J. Day for finding this. Priority: normal Signed-off-by: Hans Verkuil Thanks-to: Robert P.J. Day --- linux/drivers/media/radio/Kconfig | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/linux/drivers/media/radio/Kconfig b/linux/drivers/media/radio/Kconfig index 41bbec6df..0e39edf75 100644 --- a/linux/drivers/media/radio/Kconfig +++ b/linux/drivers/media/radio/Kconfig @@ -288,16 +288,6 @@ config RADIO_TYPHOON To compile this driver as a module, choose M here: the module will be called radio-typhoon. -config RADIO_TYPHOON_PROC_FS - bool "Support for /proc/radio-typhoon" - depends on PROC_FS && RADIO_TYPHOON - help - Say Y here if you want the typhoon radio card driver to write - status information (frequency, volume, muted, mute frequency, - base address) to /proc/radio-typhoon. The file can be viewed with - your favorite pager (i.e. use "more /proc/radio-typhoon" or "less - /proc/radio-typhoon" or simply "cat /proc/radio-typhoon"). - config RADIO_TYPHOON_PORT hex "Typhoon I/O port (0x316 or 0x336)" depends on RADIO_TYPHOON=y -- cgit v1.2.3 From 1b6c4f0e847da28690a2d746d09e80e25eb22fbc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Aug 2009 16:30:25 -0300 Subject: Update KConfig File to enable SDIO and USB interfaces From: Udi Atar Update KConfig file to enbale selection of SDIO and USB interfaces, and add dependancy on relevant modules. Priority: normal Signed-off-by: Udi Atar [mchehab@redhat.com: fix merge conflicts and remove default: m] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/Kconfig | 41 +++++++++++++++++++++------------- linux/drivers/media/dvb/siano/Makefile | 9 ++++---- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/linux/drivers/media/dvb/siano/Kconfig b/linux/drivers/media/dvb/siano/Kconfig index 88847d1dc..cd2285f6d 100644 --- a/linux/drivers/media/dvb/siano/Kconfig +++ b/linux/drivers/media/dvb/siano/Kconfig @@ -2,25 +2,34 @@ # Siano Mobile Silicon Digital TV device configuration # -config DVB_SIANO_SMS1XXX - tristate "Siano SMS1XXX USB dongle support" - depends on DVB_CORE && USB && INPUT +config SMS_SIANO_MDTV + tristate "Siano SMS1xxx based MDTV receiver" + depends on DVB_CORE && INPUT ---help--- - Choose Y here if you have a USB dongle with a SMS1XXX chipset. + Choose Y or M here if you have MDTV receiver with a Siano chipset. - To compile this driver as a module, choose M here: the - module will be called sms1xxx. + To compile this driver as a module, choose M here + (The module will be called smsmdtv). -config DVB_SIANO_SMS1XXX_SMS_IDS - bool "Enable support for Siano Mobile Silicon default USB IDs" - depends on DVB_SIANO_SMS1XXX - default y - ---help--- - Choose Y here if you have a USB dongle with a SMS1XXX chipset - that uses Siano Mobile Silicon's default usb vid:pid. + Further documentation on this driver can be found on the WWW + at http://www.siano-ms.com/ + +if SMS_SIANO_MDTV +menu "Siano module components" - Choose N here if you would prefer to use Siano's external driver. +# Hardware interfaces support - Further documentation on this driver can be found on the WWW at - . +config SMS_USB_DRV + tristate "USB interface support" + depends on DVB_CORE && USB + ---help--- + Choose if you would like to have Siano's support for USB interface + +config SMS_SDIO_DRV + tristate "SDIO interface support" + depends on DVB_CORE && MMC + default m + ---help--- + Choose if you would like to have Siano's support for SDIO interface +endif # SMS_SIANO_MDTV diff --git a/linux/drivers/media/dvb/siano/Makefile b/linux/drivers/media/dvb/siano/Makefile index c6644d909..c54140b5a 100644 --- a/linux/drivers/media/dvb/siano/Makefile +++ b/linux/drivers/media/dvb/siano/Makefile @@ -1,8 +1,9 @@ -sms1xxx-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o -obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o -obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o -obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsdvb.o +smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o + +obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o +obj-$(CONFIG_SMS_USB_DRV) += smsusb.o +obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core -- cgit v1.2.3 From 74b375ad36003080f781c9f2bdad6b837f4bc052 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Fri, 14 Aug 2009 03:42:21 +0300 Subject: Add support for Compro VideoMate S350 DVB-S PCI card. From: Igor M. Liplianin Add Compro VideoMate S350 DVB-S driver. The card uses zl10313, zl10039, saa7130 integrated circuits. Signed-off-by: Igor M. Liplianin --- linux/drivers/media/common/ir-keymaps.c | 48 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/Kconfig | 1 + linux/drivers/media/video/saa7134/saa7134-cards.c | 31 ++++++++++++++- linux/drivers/media/video/saa7134/saa7134-dvb.c | 15 +++++++ linux/drivers/media/video/saa7134/saa7134-input.c | 5 +++ linux/drivers/media/video/saa7134/saa7134.h | 1 + linux/include/media/ir-common.h | 1 + 7 files changed, 101 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 67c67430d..0b1566d34 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -2878,3 +2878,51 @@ IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE] = { [0x13] = KEY_CAMERA, }; EXPORT_SYMBOL_GPL(ir_codes_evga_indtube); + +IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = { + [0x00] = KEY_TV, + [0x01] = KEY_DVD, + [0x04] = KEY_RECORD, + [0x05] = KEY_VIDEO, /* TV/Video */ + [0x07] = KEY_STOP, + [0x08] = KEY_PLAYPAUSE, + [0x0a] = KEY_REWIND, + [0x0f] = KEY_FASTFORWARD, + [0x10] = KEY_CHANNELUP, + [0x12] = KEY_VOLUMEUP, + [0x13] = KEY_CHANNELDOWN, + [0x14] = KEY_MUTE, + [0x15] = KEY_VOLUMEDOWN, + [0x16] = KEY_1, + [0x17] = KEY_2, + [0x18] = KEY_3, + [0x19] = KEY_4, + [0x1a] = KEY_5, + [0x1b] = KEY_6, + [0x1c] = KEY_7, + [0x1d] = KEY_8, + [0x1e] = KEY_9, + [0x1f] = KEY_0, + [0x21] = KEY_SLEEP, + [0x24] = KEY_ZOOM, + [0x25] = KEY_LAST, /* Recall */ + [0x26] = KEY_SUBTITLE, /* CC */ + [0x27] = KEY_LANGUAGE, /* MTS */ + [0x29] = KEY_CHANNEL, /* SURF */ + [0x2b] = KEY_A, + [0x2c] = KEY_B, + [0x2f] = KEY_SHUFFLE, /* Snapshot */ + [0x23] = KEY_RADIO, + [0x02] = KEY_PREVIOUSSONG, + [0x06] = KEY_NEXTSONG, + [0x03] = KEY_EPG, + [0x09] = KEY_SETUP, + [0x22] = KEY_BACKSPACE, + [0x0c] = KEY_UP, + [0x0e] = KEY_DOWN, + [0x0b] = KEY_LEFT, + [0x0d] = KEY_RIGHT, + [0x11] = KEY_ENTER, + [0x20] = KEY_TEXT, +}; +EXPORT_SYMBOL_GPL(ir_codes_videomate_s350); diff --git a/linux/drivers/media/video/saa7134/Kconfig b/linux/drivers/media/video/saa7134/Kconfig index 5bcce092e..22bfd62c9 100644 --- a/linux/drivers/media/video/saa7134/Kconfig +++ b/linux/drivers/media/video/saa7134/Kconfig @@ -47,6 +47,7 @@ config VIDEO_SAA7134_DVB select DVB_TDA10048 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE + select DVB_ZL10039 if !DVB_FE_CUSTOMISE ---help--- This adds support for DVB cards based on the Philips saa7134 chip. diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 3ab7732e6..64933b5da 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -5155,6 +5155,25 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x00, }, }, + [SAA7134_BOARD_VIDEOMATE_S350] = { + /* Jan D. Louw > 2, 0x80040100, 0x80040100); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); break; + case SAA7134_BOARD_VIDEOMATE_S350: + dev->has_remote = SAA7134_REMOTE_GPIO; + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00008000, 0x00008000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000); + break; } return 0; } diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index afd9b7e5c..18223dafe 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -56,6 +56,7 @@ #include "zl10353.h" #include "zl10036.h" +#include "zl10039.h" #include "mt312.h" MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); @@ -968,6 +969,10 @@ static struct zl10036_config avertv_a700_tuner = { .tuner_address = 0x60, }; +static struct mt312_config zl10313_compro_s350_config = { + .demod_address = 0x0e, +}; + static struct lgdt3305_config hcw_lgdt3305_config = { .i2c_addr = 0x0e, .mpeg_mode = LGDT3305_MPEG_SERIAL, @@ -1476,6 +1481,16 @@ static int dvb_init(struct saa7134_dev *dev) __func__); } } + break; + case SAA7134_BOARD_VIDEOMATE_S350: + fe0->dvb.frontend = dvb_attach(mt312_attach, + &zl10313_compro_s350_config, &dev->i2c_adap); + if (fe0->dvb.frontend) + if (dvb_attach(zl10039_attach, fe0->dvb.frontend, + 0x60, &dev->i2c_adap) == NULL) + wprintk("%s: No zl10039 found!\n", + __func__); + break; default: wprintk("Huh? unknown DVB card?\n"); diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index b54bfd645..c6547f423 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -646,6 +646,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keycode = 0x7f; polling = 40; /* ms */ break; + case SAA7134_BOARD_VIDEOMATE_S350: + ir_codes = ir_codes_videomate_s350; + mask_keycode = 0x003f00; + mask_keydown = 0x040000; + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 6b0742ad7..c0757f8a1 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -293,6 +293,7 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_607RDS_MK5 166 #define SAA7134_BOARD_BEHOLD_609RDS_MK3 167 #define SAA7134_BOARD_BEHOLD_609RDS_MK5 168 +#define SAA7134_BOARD_VIDEOMATE_S350 169 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 diff --git a/linux/include/media/ir-common.h b/linux/include/media/ir-common.h index 922bad37d..8a607db49 100644 --- a/linux/include/media/ir-common.h +++ b/linux/include/media/ir-common.h @@ -164,6 +164,7 @@ extern IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_terratec_cinergy_xs[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE]; #endif -- cgit v1.2.3 From e67c964a2ec0b30fed9da5588068d39cbcc8e163 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 14 Aug 2009 01:45:57 -0300 Subject: gspca/Kconfig: Fix bad identation for USB_GSPCA_SN9C20X_EVDEV From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index 34f46f2bc..a14561956 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -113,10 +113,10 @@ config USB_GSPCA_SN9C20X module will be called gspca_sn9c20x. config USB_GSPCA_SN9C20X_EVDEV - bool "Enable evdev support" - depends on USB_GSPCA_SN9C20X - ---help--- - Say Y here in order to enable evdev support for sn9c20x webcam button. + bool "Enable evdev support" + depends on USB_GSPCA_SN9C20X + ---help--- + Say Y here in order to enable evdev support for sn9c20x webcam button. config USB_GSPCA_SONIXB tristate "SONIX Bayer USB Camera Driver" -- cgit v1.2.3 From 797d74746b7e94cbcd14b03b00bc7c467834ce07 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 14 Aug 2009 01:48:42 -0300 Subject: siano/Kconfig: add missing endmenu From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/siano/Kconfig b/linux/drivers/media/dvb/siano/Kconfig index cd2285f6d..ff297ceaf 100644 --- a/linux/drivers/media/dvb/siano/Kconfig +++ b/linux/drivers/media/dvb/siano/Kconfig @@ -31,5 +31,5 @@ config SMS_SDIO_DRV default m ---help--- Choose if you would like to have Siano's support for SDIO interface - +endmenu endif # SMS_SIANO_MDTV -- cgit v1.2.3 From 663970b7c101bbe35646a5003e25e40087bea009 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 16 Aug 2009 21:09:23 -0300 Subject: Document libv4l at V4L2 API specs From: Mauro Carvalho Chehab Since applications aren't prepared to handle all V4L2 available formats, an effort is done to have a library capable of understanding especially the proprietary formats. This patch documents this library, and adds v4l2grab.c as an example on how to use it. Parts of the text are based at the libv4l README file (c) by Hans de Goede. Thanks to Hans de Goede for his good work with libv4l. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- .hgignore | 2 + v4l2-apps/test/v4l2grab.c | 2 +- v4l2-spec/Makefile | 16 +++++ v4l2-spec/libv4l.sgml | 168 ++++++++++++++++++++++++++++++++++++++++++++++ v4l2-spec/v4l2.sgml | 38 ++++++++++- 5 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 v4l2-spec/libv4l.sgml diff --git a/.hgignore b/.hgignore index e09075e29..bc408c495 100644 --- a/.hgignore +++ b/.hgignore @@ -66,6 +66,8 @@ v4l2-spec/capture.c.sgml$ v4l2-spec/entities.sgml$ v4l2-spec/.*\.stamp$ v4l2-spec/indices.sgml$ +v4l2-spec/libv4l-fmt.sgml$ +v4l2-spec/v4l2grab.c.sgml$ v4l2-spec/v4l2-single$ v4l2-spec/v4l2$ v4l2-spec/v4l2.pdf$ diff --git a/v4l2-apps/test/v4l2grab.c b/v4l2-apps/test/v4l2grab.c index 153a0dd30..de921874b 100644 --- a/v4l2-apps/test/v4l2grab.c +++ b/v4l2-apps/test/v4l2grab.c @@ -1,5 +1,5 @@ /* V4L2 video picture grabber - Copyright (C) 2006 Mauro Carvalho Chehab + Copyright (C) 2009 Mauro Carvalho Chehab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/v4l2-spec/Makefile b/v4l2-spec/Makefile index 8f40e8614..616445137 100644 --- a/v4l2-spec/Makefile +++ b/v4l2-spec/Makefile @@ -5,6 +5,7 @@ SHELL=/bin/bash SGMLS = \ biblio.sgml \ capture.c.sgml \ + v4l2grab.c.sgml \ common.sgml \ compat.sgml \ controls.sgml \ @@ -20,6 +21,7 @@ SGMLS = \ dev-sliced-vbi.sgml \ dev-teletext.sgml \ driver.sgml \ + libv4l.sgml \ entities.sgml \ fdl-appendix.sgml \ func-close.sgml \ @@ -323,6 +325,12 @@ DOCUMENTED = \ -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\) /\1<\/link> /g" \ -e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" +libv4l-fmt.sgml: + cat ../v4l2-apps/libv4l/libv4lconvert/*.c| \ + perl -ne 'if (m/(V4L2_PIX_FMT_[^\s\;\\)\,:]+)/) { printf "$$1,\n"; };' \ + |sort|uniq| \ + sed -e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" > $@ + capture.c.sgml: ../v4l2-apps/test/capture-example.c Makefile echo "" > $@ expand --tabs=8 < $< | \ @@ -330,6 +338,13 @@ capture.c.sgml: ../v4l2-apps/test/capture-example.c Makefile sed 's/i\.e\./&ie;/' >> $@ echo "" >> $@ +v4l2grab.c.sgml: ../v4l2-apps/test/v4l2grab.c Makefile + echo "" > $@ + expand --tabs=8 < $< | \ + sed $(ESCAPE) $(DOCUMENTED) | \ + sed 's/i\.e\./&ie;/' >> $@ + echo "" >> $@ + videodev2.h.sgml: ../linux/include/linux/videodev2.h Makefile echo "" > $@ expand --tabs=8 < $< | \ @@ -488,6 +503,7 @@ distclean clean: rm -f *.stamp rm -f videodev2.h.sgml rm -f capture.c.sgml + rm -f v4l2grab.c.sgml rm -f capture rm -f indices.sgml entities.sgml rm -rf v4l2 v4l2-single v4l2.pdf diff --git a/v4l2-spec/libv4l.sgml b/v4l2-spec/libv4l.sgml new file mode 100644 index 000000000..ec1f8b6fe --- /dev/null +++ b/v4l2-spec/libv4l.sgml @@ -0,0 +1,168 @@ +Libv4l Userspace Library +
+ Introduction + + libv4l is a collection of libraries which adds a thin abstraction +layer on top of video4linux2 devices. The purpose of this (thin) layer +is to make it easy for application writers to support a wide variety of +devices without having to write separate code for different devices in the +same class. +An example of using libv4l is provided by +v4l2grab. + + + libv4l consists of 3 different libraries: +
+ libv4lconvert + + libv4lconvert is a library that converts several +different pixelformats found in V4L2 drivers into a few common RGB and +YUY formats. + It currently accepts the following V4L2 driver formats: +V4L2_PIX_FMT_BGR24, +V4L2_PIX_FMT_HM12, +V4L2_PIX_FMT_JPEG, +V4L2_PIX_FMT_MJPEG, +V4L2_PIX_FMT_MR97310A, +V4L2_PIX_FMT_OV511, +V4L2_PIX_FMT_OV518, +V4L2_PIX_FMT_PAC207, +V4L2_PIX_FMT_PJPG, +V4L2_PIX_FMT_RGB24, +V4L2_PIX_FMT_SBGGR8, +V4L2_PIX_FMT_SGBRG8, +V4L2_PIX_FMT_SGRBG8, +V4L2_PIX_FMT_SN9C10X, +V4L2_PIX_FMT_SN9C20X_I420, +V4L2_PIX_FMT_SPCA501, +V4L2_PIX_FMT_SPCA505, +V4L2_PIX_FMT_SPCA508, +V4L2_PIX_FMT_SPCA561, +V4L2_PIX_FMT_SQ905C, +V4L2_PIX_FMT_SRGGB8, +V4L2_PIX_FMT_UYVY, +V4L2_PIX_FMT_YUV420, +V4L2_PIX_FMT_YUYV, +V4L2_PIX_FMT_YVU420, +and V4L2_PIX_FMT_YVYU. + + Later on libv4lconvert was expanded to also be able to do +various video processing functions to improve webcam video quality. +The video processing is split in to 2 parts: libv4lconvert/control and +libv4lconvert/processing. + + The control part is used to offer video controls which can +be used to control the video processing functions made available by + libv4lconvert/processing. These controls are stored application wide +(until reboot) by using a persistent shared memory object. + + libv4lconvert/processing offers the actual video +processing functionality. +
+
+ libv4l1 + This library offers functions that can be used to quickly +make v4l1 applications work with v4l2 devices. These functions work exactly +like the normal open/close/etc, except that libv4l1 does full emulation of +the v4l1 api on top of v4l2 drivers, in case of v4l1 drivers it +will just pass calls through. + Since those functions are emulations of the old V4L1 API, +it shouldn't be used for new applications. +
+
+ libv4l2 + This library should be used for all modern V4L2 +applications. + It provides handles to call V4L2 open/ioctl/close/poll +methods. Instead of just providing the raw output of the device, it enhances +the calls in the sense that it will use libv4lconvert to provide more video +formats and to enhance the image quality. + In most cases, libv4l2 just passes the calls directly +through to the v4l2 driver, intercepting the calls to +VIDIOC_TRY_FMT, +VIDIOC_G_FMT +VIDIOC_S_FMT +VIDIOC_ENUM_FRAMESIZES +and +VIDIOC_ENUM_FRAMEINTERVALS +in order to emulate the formats +V4L2_PIX_FMT_BGR24, +V4L2_PIX_FMT_RGB24, +V4L2_PIX_FMT_YUV420, +and V4L2_PIX_FMT_YVU420, +if they aren't available in the driver. +VIDIOC_ENUM_FMT +keeps enumerating the hardware supported formats, plus the emulated formats +offered by libv4l at the end. + +
+ Libv4l device control functions + The common file operation methods are provided by +libv4l. + Those functions operate just like glibc +open/close/dup/ioctl/read/mmap/munmap: + + int v4l2_open(const char *file, int oflag, +...) - +operates like the standard open() function. + + int v4l2_close(int fd) - +operates like the standard close() function. + + int v4l2_dup(int fd) - +operates like the standard dup() function, duplicating a file handler. + + int v4l2_ioctl (int fd, unsigned long int request, ...) - +operates like the standard ioctl() function. + + int v4l2_read (int fd, void* buffer, size_t n) - +operates like the standard read() function. + + void v4l2_mmap(void *start, size_t length, int prot, int flags, int fd, int64_t offset); - +operates like the standard mmap() function. + + int v4l2_munmap(void *_start, size_t length); - +operates like the standard munmap() function. + + + Those functions provide additional control: + + int v4l2_fd_open(int fd, int v4l2_flags) - +opens an already opened fd for further use through v4l2lib and possibly +modify libv4l2's default behavior through the v4l2_flags argument. +Currently, v4l2_flags can be V4L2_DISABLE_CONVERSION, +to disable format conversion. + + int v4l2_set_control(int fd, int cid, int value) - +This function takes a value of 0 - 65535, and then scales that range to +the actual range of the given v4l control id, and then if the cid exists +and is not locked sets the cid to the scaled value. + + int v4l2_get_control(int fd, int cid) - +This function returns a value of 0 - 65535, scaled to from the actual range +of the given v4l control id. when the cid does not exist, could not be +accessed for some reason, or some error occured 0 is returned. + + +
+
+
+ + v4l1compat.so wrapper library + + This library intercepts calls to +open/close/ioctl/mmap/mmunmap operations and redirects them to the libv4l +counterparts, by using LD_PRELOAD=/usr/lib/v4l1compat.so. It also +emulates V4L1 calls via V4L2 API. + It allows usage of binary legacy applications that +still don't use libv4l. +
+ +
+ diff --git a/v4l2-spec/v4l2.sgml b/v4l2-spec/v4l2.sgml index bae7eb441..8e7610685 100644 --- a/v4l2-spec/v4l2.sgml +++ b/v4l2-spec/v4l2.sgml @@ -25,7 +25,7 @@ Video for Linux Two API Specification - Revision 0.26 + Revision 0.27 @@ -92,6 +92,18 @@ MPEG stream embedded, sliced VBI data format in this specification. + + Mauro + Carvalho Chehab + Documented libv4l, designed and added v4l2grab example + + +
+ mchehab@redhat.com +
+
+
+ 1999 2000 @@ -105,12 +117,13 @@ MPEG stream embedded, sliced VBI data format in this specification. 2008 2009 Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin -Rubli, Andy Walls +Rubli, Andy Walls, Mauro Carvalho Chehab This document is copyrighted © 1999-2009 by Bill -Dirks, Michael H. Schimek, Hans Verkuil, Martin Rubli, and Andy Walls. +Dirks, Michael H. Schimek, Hans Verkuil, Martin Rubli, Andy Walls and +Mauro Carvalho Chehab. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, @@ -130,6 +143,13 @@ structs, ioctls) must be noted in more detail in the history chapter (compat.sgml), along with the possible impact on existing drivers and applications. --> + + 0.27 + 2009-08-15 + mcc + Added libv4l documentation and v4l2grab example. + + 0.26 2009-06-15 @@ -471,6 +491,10 @@ available here: + &sub-libv4l; + + &sub-compat; @@ -485,6 +509,14 @@ available here: + Video Grabber example using libv4l + This program demonstrates how to grab V4L2 images in ppm format by +using libv4l handlers. The advantage is that this grabber can potentially work +with any V4L2 driver. + &sub-v4l2grab-c; + + &sub-fdl-appendix; &sub-indices; -- cgit v1.2.3 From 9e69ff729e59aa0acf91cb2a2aa546e874f53a51 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 2 Jul 2009 14:50:35 +0000 Subject: cx88: High resolution timer for Remote Controls From: Andrzej Hajda Patch solves problem of missed keystrokes on some remote controls, as reported on http://bugzilla.kernel.org/show_bug.cgi?id=9637 . Signed-off-by: Andrzej Hajda Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.saa7134 | 1 + linux/drivers/media/video/cx88/cx88-input.c | 37 +++++++++++------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134 index c913e5614..dc0576afe 100644 --- a/linux/Documentation/video4linux/CARDLIST.saa7134 +++ b/linux/Documentation/video4linux/CARDLIST.saa7134 @@ -167,3 +167,4 @@ 166 -> Beholder BeholdTV 607 RDS [5ace:6073] 167 -> Beholder BeholdTV 609 RDS [5ace:6092] 168 -> Beholder BeholdTV 609 RDS [5ace:6093] +169 -> Compro VideoMate S350/S300 [185b:c900] diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index 8d0042ab2..a585245df 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -23,10 +23,10 @@ */ #include -#include #include #include #include +#include #include "compat.h" #include "cx88.h" @@ -49,7 +49,7 @@ struct cx88_IR { /* poll external decoder */ int polling; - struct delayed_work work; + struct hrtimer timer; u32 gpio_addr; u32 last_gpio; u32 mask_keycode; @@ -145,31 +145,28 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) } } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void cx88_ir_work(void *data) -#else -static void cx88_ir_work(struct work_struct *work) -#endif +enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct cx88_IR *ir = data; -#else - struct cx88_IR *ir = container_of(work, struct cx88_IR, work.work); -#endif + unsigned long missed; + struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer); cx88_ir_handle_key(ir); - schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); + missed = hrtimer_forward_now(&ir->timer, + ktime_set(0, ir->polling * 1000000)); + if (missed > 1) + ir_dprintk("Missed ticks %ld\n", missed - 1); + + return HRTIMER_RESTART; } void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) { if (ir->polling) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_DELAYED_WORK(&ir->work, cx88_ir_work, ir); -#else - INIT_DELAYED_WORK(&ir->work, cx88_ir_work); -#endif - schedule_delayed_work(&ir->work, 0); + hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ir->timer.function = cx88_ir_work; + hrtimer_start(&ir->timer, + ktime_set(0, ir->polling * 1000000), + HRTIMER_MODE_REL); } if (ir->sampling) { core->pci_irqmask |= PCI_INT_IR_SMPINT; @@ -186,7 +183,7 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) } if (ir->polling) - cancel_delayed_work_sync(&ir->work); + hrtimer_cancel(&ir->timer); } /* ---------------------------------------------------------------------- */ -- cgit v1.2.3 From 2cc1e944209c3eccf7ff91ce2a7f5294dde68dd5 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 3 Jul 2009 10:59:47 +0200 Subject: libv4l: add support for RGB565 format From: Mauro Carvalho Chehab Currently, em28xx driver outputs webcams only at RGB565 format. However, several webcam applications don't support this format. In order to properly work with those applications, a RGB565 handler should be added at libv4l. Tested with Silvercrest 1.3 mpix with v4l2grab (V4L2, with native libv4l support) and two LD_PRELOAD applications: camorama (V4L1 API) and skype (using compat32). Priority: normal Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Hans de Goede --- .../libv4l/libv4lconvert/libv4lconvert-priv.h | 9 ++ v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 18 ++++ v4l2-apps/libv4l/libv4lconvert/rgbyuv.c | 104 ++++++++++++++++++++- 3 files changed, 130 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h index 2cf8f6ba4..d8a09c24a 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h @@ -184,6 +184,15 @@ void v4lconvert_swap_rgb(const unsigned char *src, unsigned char *dst, void v4lconvert_swap_uv(const unsigned char *src, unsigned char *dst, const struct v4l2_format *src_fmt); +void v4lconvert_rgb565_to_rgb24(const unsigned char *src, unsigned char *dest, + int width, int height); + +void v4lconvert_rgb565_to_bgr24(const unsigned char *src, unsigned char *dest, + int width, int height); + +void v4lconvert_rgb565_to_yuv420(const unsigned char *src, unsigned char *dest, + const struct v4l2_format *src_fmt, int yvu); + void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst, int width, int height, int yvu); diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c index 1389c58bc..4422ce084 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -46,6 +46,7 @@ static const struct v4lconvert_pixfmt supported_src_pixfmts[] = { { V4L2_PIX_FMT_YUYV, 0 }, { V4L2_PIX_FMT_YVYU, 0 }, { V4L2_PIX_FMT_UYVY, 0 }, + { V4L2_PIX_FMT_RGB565, 0 }, { V4L2_PIX_FMT_SN9C20X_I420, V4LCONVERT_NEEDS_CONVERSION }, { V4L2_PIX_FMT_SBGGR8, V4LCONVERT_NEEDS_CONVERSION }, { V4L2_PIX_FMT_SGBRG8, V4LCONVERT_NEEDS_CONVERSION }, @@ -787,6 +788,23 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data, } break; + case V4L2_PIX_FMT_RGB565: + switch (dest_pix_fmt) { + case V4L2_PIX_FMT_RGB24: + v4lconvert_rgb565_to_rgb24(src, dest, width, height); + break; + case V4L2_PIX_FMT_BGR24: + v4lconvert_rgb565_to_bgr24(src, dest, width, height); + break; + case V4L2_PIX_FMT_YUV420: + v4lconvert_rgb565_to_yuv420(src, dest, fmt, 0); + break; + case V4L2_PIX_FMT_YVU420: + v4lconvert_rgb565_to_yuv420(src, dest, fmt, 1); + break; + } + break; + case V4L2_PIX_FMT_RGB24: switch (dest_pix_fmt) { case V4L2_PIX_FMT_BGR24: diff --git a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c index 31cbc3c68..66fd3ee60 100644 --- a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c +++ b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c @@ -1,9 +1,11 @@ /* # RGB <-> YUV conversion routines - # (C) 2008 Hans de Goede +# RGB565 conversion routines +# (C) 2009 Mauro Carvalho Chehab + # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or @@ -472,3 +474,103 @@ void v4lconvert_swap_uv(const unsigned char *src, unsigned char *dest, src += src_fmt->fmt.pix.bytesperline / 2; } } + +void v4lconvert_rgb565_to_rgb24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + while (--height >= 0) { + for (j = 0; j < width; j++) { + unsigned short tmp = *(unsigned short *)src; + + /* Original format: rrrrrggg gggbbbbb */ + *dest++ = 0xf8 & (tmp >> 8); + *dest++ = 0xfc & (tmp >> 3); + *dest++ = 0xf8 & (tmp << 3); + + src += 2; + } + } +} + +void v4lconvert_rgb565_to_bgr24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + while (--height >= 0) { + for (j = 0; j < width; j++) { + unsigned short tmp = *(unsigned short *)src; + + /* Original format: rrrrrggg gggbbbbb */ + *dest++ = 0xf8 & (tmp << 3); + *dest++ = 0xfc & (tmp >> 3); + *dest++ = 0xf8 & (tmp >> 8); + + src += 2; + } + } +} + +void v4lconvert_rgb565_to_yuv420(const unsigned char *src, unsigned char *dest, + const struct v4l2_format *src_fmt, int yvu) +{ + int x, y; + unsigned short tmp; + unsigned char *udest, *vdest; + unsigned r[4], g[4], b[4]; + int avg_src[3]; + + /* Y */ + for (y = 0; y < src_fmt->fmt.pix.height; y++) { + for (x = 0; x < src_fmt->fmt.pix.width; x++) { + tmp = *(unsigned short *)src; + r[0] = 0xf8 & (tmp << 3); + g[0] = 0xfc & (tmp >> 3); + b[0] = 0xf8 & (tmp >> 8); + RGB2Y(r[0], g[0], b[0], *dest++); + src += 2; + } + src += src_fmt->fmt.pix.bytesperline - 2 * src_fmt->fmt.pix.width; + } + src -= src_fmt->fmt.pix.height * src_fmt->fmt.pix.bytesperline; + + /* U + V */ + if (yvu) { + vdest = dest; + udest = dest + src_fmt->fmt.pix.width * src_fmt->fmt.pix.height / 4; + } else { + udest = dest; + vdest = dest + src_fmt->fmt.pix.width * src_fmt->fmt.pix.height / 4; + } + + for (y = 0; y < src_fmt->fmt.pix.height / 2; y++) { + for (x = 0; x < src_fmt->fmt.pix.width / 2; x++) { + tmp = *(unsigned short *)src; + r[0] = 0xf8 & (tmp << 3); + g[0] = 0xfc & (tmp >> 3); + b[0] = 0xf8 & (tmp >> 8); + + tmp = *(((unsigned short *)src) + 1); + r[1] = 0xf8 & (tmp << 3); + g[1] = 0xfc & (tmp >> 3); + b[1] = 0xf8 & (tmp >> 8); + + tmp = *(((unsigned short *)src) + src_fmt->fmt.pix.bytesperline); + r[2] = 0xf8 & (tmp << 3); + g[2] = 0xfc & (tmp >> 3); + b[2] = 0xf8 & (tmp >> 8); + + tmp = *(((unsigned short *)src) + src_fmt->fmt.pix.bytesperline + 1); + r[3] = 0xf8 & (tmp << 3); + g[3] = 0xfc & (tmp >> 3); + b[3] = 0xf8 & (tmp >> 8); + + avg_src[0] = (r[0] + r[1] + r[2] + r[3]) /4; + avg_src[1] = (g[0] + g[1] + g[2] + g[3]) /4; + avg_src[2] = (b[0] + b[1] + b[2] + b[3]) /4; + RGB2UV(avg_src[0], avg_src[1], avg_src[2], *udest++, *vdest++); + src += 4; + } + src += 2 * src_fmt->fmt.pix.bytesperline - 2 * src_fmt->fmt.pix.width; + } +} -- cgit v1.2.3 From 2773722d57fb06561b98c93bfd44f63f640cb77a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 09:38:44 -0300 Subject: Kconfig files: Fix improper use of whitespaces From: Mauro Carvalho Chehab On VIDEO_M52790 and USB_GSPCA_SN9C20X, instead of tab, it were using 7 whitespaces at the beginning, probably due to some cut-and-paste trouble. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/Kconfig | 6 +++--- linux/drivers/media/video/gspca/Kconfig | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/Kconfig b/linux/drivers/media/video/Kconfig index e8a6e4de4..14a1b6160 100644 --- a/linux/drivers/media/video/Kconfig +++ b/linux/drivers/media/video/Kconfig @@ -203,9 +203,9 @@ config VIDEO_CS53L32A module will be called cs53l32a. config VIDEO_M52790 - tristate "Mitsubishi M52790 A/V switch" - depends on VIDEO_V4L2 && I2C - ---help--- + tristate "Mitsubishi M52790 A/V switch" + depends on VIDEO_V4L2 && I2C + ---help--- Support for the Mitsubishi M52790 A/V switch. To compile this driver as a module, choose M here: the diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index c9166e543..6ae1522ec 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -112,9 +112,9 @@ config USB_GSPCA_PAC7311 module will be called gspca_pac7311. config USB_GSPCA_SN9C20X - tristate "SN9C20X USB Camera Driver" - depends on VIDEO_V4L2 && USB_GSPCA - help + tristate "SN9C20X USB Camera Driver" + depends on VIDEO_V4L2 && USB_GSPCA + help Say Y here if you want support for cameras based on the sn9c20x chips (SN9C201 and SN9C202). -- cgit v1.2.3 From a5c6c097f7fa84eb79be22e98a6cd65267c52aa9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 09:39:54 -0300 Subject: em28xx: MT9M111 patch introduced some broken whitespaces From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- linux/drivers/media/video/em28xx/em28xx.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index a38586176..b8778577d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1896,7 +1896,7 @@ static int em28xx_hint_sensor(struct em28xx *dev) break; - case 0x143a: /* MT9M111 as found in the ECS G200 */ + case 0x143a: /* MT9M111 as found in the ECS G200 */ dev->model = EM2750_BOARD_UNKNOWN; em28xx_set_model(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 70a41b640..8203c6e1d 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -368,7 +368,7 @@ enum em28xx_sensor { EM28XX_NOSENSOR = 0, EM28XX_MT9V011, EM28XX_MT9M001, - EM28XX_MT9M111, + EM28XX_MT9M111, }; enum em28xx_adecoder { -- cgit v1.2.3 From faf00e29cab3d09eeb930702f997a11e42b6d7f2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:13:40 -0300 Subject: saa7134: Fix bad whitespacing From: Mauro Carvalho Chehab The patch that aded ASUSTeK P7131 Analog were using 7 spaces instead of tab, probably due to some bad cut-and-paste. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 6 +++--- linux/drivers/media/video/saa7134/saa7134-input.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 64933b5da..32f8bdb91 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -3702,8 +3702,8 @@ struct saa7134_board saa7134_boards[] = { .amux = TV, .gpio = 0x0200000, }, - }, - [SAA7134_BOARD_ASUSTeK_P7131_ANALOG] = { + }, + [SAA7134_BOARD_ASUSTeK_P7131_ANALOG] = { .name = "ASUSTeK P7131 Analog", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, @@ -6623,7 +6623,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_FLYDVBT_LR301: case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: - case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: + case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: case SAA7134_BOARD_FLYDVBTDUO: case SAA7134_BOARD_PROTEUS_2309: case SAA7134_BOARD_AVERMEDIA_A16AR: diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index c6547f423..585f78af3 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -605,7 +605,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: - case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: + case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: ir_codes = ir_codes_asus_pc39; mask_keydown = 0x0040000; rc5_gpio = 1; -- cgit v1.2.3 From fcf0d8c091324e9b5c0607af50b692fed42f9ec5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:14:45 -0300 Subject: fix bad whitespaces at cx88_geniatech_x8000_mt From: Mauro Carvalho Chehab It were using 7 spaces instead of tab for indent. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-dvb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index ab84c085f..d3d4c67ec 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -500,14 +500,14 @@ static struct zl10353_config cx88_pinnacle_hybrid_pctv = { }; static struct zl10353_config cx88_geniatech_x8000_mt = { - .demod_address = (0x1e >> 1), - .no_tuner = 1, - .disable_i2c_gate_ctrl = 1, + .demod_address = (0x1e >> 1), + .no_tuner = 1, + .disable_i2c_gate_ctrl = 1, #if 0 - .input_frequency = 0xe609, - .parallel_ts = 1, - .r56_agc_targets = 0x2b, - .r5c_clk_mpegts_output = 0x75, + .input_frequency = 0xe609, + .parallel_ts = 1, + .r56_agc_targets = 0x2b, + .r5c_clk_mpegts_output = 0x75, #endif }; -- cgit v1.2.3 From 2260966cdc908fdac4676bcb68dcb7fd2baea022 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:15:48 -0300 Subject: cx231xx/cx231xx-conf-reg.h: fix bad whitespaces From: Mauro Carvalho Chehab It were using 7 spaces instead of tab for indent. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h b/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h index a6f398a17..31a8759f6 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h +++ b/linux/drivers/media/video/cx231xx/cx231xx-conf-reg.h @@ -60,10 +60,10 @@ #define PWR_RESETOUT_EN 0x100 /* bit8 */ enum AV_MODE{ - POLARIS_AVMODE_DEFAULT = 0, - POLARIS_AVMODE_DIGITAL = 0x10, - POLARIS_AVMODE_ANALOGT_TV = 0x20, - POLARIS_AVMODE_ENXTERNAL_AV = 0x30, + POLARIS_AVMODE_DEFAULT = 0, + POLARIS_AVMODE_DIGITAL = 0x10, + POLARIS_AVMODE_ANALOGT_TV = 0x20, + POLARIS_AVMODE_ENXTERNAL_AV = 0x30, }; -- cgit v1.2.3 From 630128e6e1b7574d909def0cfdb204555e28b43b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:18:29 -0300 Subject: stv06xx: fix bad whitespaces From: Mauro Carvalho Chehab It were using 7 spaces instead of tab for indent. CC: Erik Andren Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/stv06xx/stv06xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c index 0da8e0de0..7af511b5e 100644 --- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -130,8 +130,8 @@ int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len) STV06XX_URB_MSG_TIMEOUT); if (err < 0) return err; - } - return stv06xx_write_sensor_finish(sd); + } + return stv06xx_write_sensor_finish(sd); } int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len) -- cgit v1.2.3 From 31da1cf039c5d397bbe955fd1e9903d19e7ff9e2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:20:06 -0300 Subject: hdpvr-control: fix bad whitespaces From: Mauro Carvalho Chehab It were using 7 spaces instead of tab for indent. CC: Janne Grunau Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/hdpvr/hdpvr-control.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/linux/drivers/media/video/hdpvr/hdpvr-control.c b/linux/drivers/media/video/hdpvr/hdpvr-control.c index 06791749d..5a6b78b8d 100644 --- a/linux/drivers/media/video/hdpvr/hdpvr-control.c +++ b/linux/drivers/media/video/hdpvr/hdpvr-control.c @@ -178,24 +178,24 @@ error: int hdpvr_set_options(struct hdpvr_device *dev) { - hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std); + hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std); - hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, + hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, dev->options.video_input+1); - hdpvr_set_audio(dev, dev->options.audio_input+1, + hdpvr_set_audio(dev, dev->options.audio_input+1, dev->options.audio_codec); - hdpvr_set_bitrate(dev); - hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, + hdpvr_set_bitrate(dev); + hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE, dev->options.bitrate_mode); - hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode); + hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode); - hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness); - hdpvr_config_call(dev, CTRL_CONTRAST, dev->options.contrast); - hdpvr_config_call(dev, CTRL_HUE, dev->options.hue); - hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation); - hdpvr_config_call(dev, CTRL_SHARPNESS, dev->options.sharpness); + hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness); + hdpvr_config_call(dev, CTRL_CONTRAST, dev->options.contrast); + hdpvr_config_call(dev, CTRL_HUE, dev->options.hue); + hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation); + hdpvr_config_call(dev, CTRL_SHARPNESS, dev->options.sharpness); - return 0; + return 0; } -- cgit v1.2.3 From 990c9e823d0db2e126fae7a2ead592ebd1ea2e6f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 10:28:17 -0300 Subject: cx88: Apply version 2 of high resolution timer for RC From: Mauro Carvalho Chehab Patch solves problem of missed keystrokes on some remote controls, as reported on http://bugzilla.kernel.org/show_bug.cgi?id=9637 . Changes of version 2: * Driver no longer builds on kernels < 2.6.22, so add an entry to v4l/versions.txt * Add a missing static. Build-tested on 2.6.22. Priority: normal Signed-off-by: Andrzej Hajda Signed-off-by: Jean Delvare [mchehab@redhat.com: this patch will be merged with version 1 for upstream submission] Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-input.c | 4 ++-- v4l/versions.txt | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index a585245df..6a3687a88 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -23,10 +23,10 @@ */ #include +#include #include #include #include -#include #include "compat.h" #include "cx88.h" @@ -145,7 +145,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) } } -enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) +static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) { unsigned long missed; struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer); diff --git a/v4l/versions.txt b/v4l/versions.txt index 9e23e500c..4ce31f852 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -45,6 +45,8 @@ DVB_DRX397XD DVB_DM1105 # This driver needs print_hex_dump DVB_FIREDTV +# This driver needs hrtimer API +VIDEO_CX88 [2.6.20] #This driver requires HID_REQ_GET_REPORT -- cgit v1.2.3 From d72c129e9f3b79a248c91178052e75c429cfbc53 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Jul 2009 08:58:25 +0000 Subject: Compatibility layer for hrtimer API From: Jean Delvare Kernels 2.6.22 to 2.6.24 (inclusive) need some compatibility quirks for the hrtimer API. For older kernels, some required functions were not exported so there's nothing we can do. This means that drivers using the hrtimer infrastructure will no longer work for kernels older than 2.6.22. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- v4l/compat.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/v4l/compat.h b/v4l/compat.h index 11dc57109..e73f03087 100644 --- a/v4l/compat.h +++ b/v4l/compat.h @@ -480,4 +480,23 @@ static inline unsigned long v4l_compat_fls(unsigned long x) } #endif +/* + * Compatibility code for hrtimer API + * This will make hrtimer usable for kernels 2.6.22 and later. + * For earlier kernels, not all required functions are exported + * so there's nothing we can do. + */ + +#ifdef _LINUX_HRTIMER_H +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) && \ + LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) +/* Forward a hrtimer so it expires after the hrtimer's current now */ +static inline unsigned long hrtimer_forward_now(struct hrtimer *timer, + ktime_t interval) +{ + return hrtimer_forward(timer, timer->base->get_time(), interval); +} +#endif +#endif /* _LINUX_HRTIMER_H */ + #endif /* _COMPAT_H */ -- cgit v1.2.3 From 4fe97c1de01452a0fa3ad92fde2c3f9e382d9334 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 6 Jul 2009 10:14:11 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 3 ++- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index 638d87eba..acf74c527 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -6,7 +6,8 @@ libv4l-0.6.0 an external helper as I've failed to contact Mark W. McClelland to get permission to relicense the code. If you know a working email address for Mark W. McClelland, please let me know. -* Add various laptop models to the upside down devices table +* Add tons of laptop models to the upside down devices table +* Support for rgb565 source format by Mauro Carvalho Chehab * Many bug fixes (see the mercurial tree for details) libv4l-0.5.99 diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index e97fc3cd3..141fe3c5b 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -66,10 +66,17 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "W7S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "X55SR ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "X55SV ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + /* Note no whitespace padding for board vendor, this is not a typo */ + { 0x064e, 0xa111, 0, "ASUSTeK Computer Inc.", "F5RL ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "N20A ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x090c, 0xe370, 0, "ASUSTeK Computer Inc. ", "U6S ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Ke ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Sa ", -- cgit v1.2.3 From 069c3e6bcf839eaaaddf6f1b5f2ce0307e7c388b Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 8 Jul 2009 17:08:32 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 141fe3c5b..5802449dd 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -70,6 +70,10 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "X55SV ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K40IJ ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "N10J ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* Note no whitespace padding for board vendor, this is not a typo */ { 0x064e, 0xa111, 0, "ASUSTeK Computer Inc.", "F5RL ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, -- cgit v1.2.3 From 4d1b85f28a9bdc2a6b5c8193caae3698b5010dd3 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 9 Jul 2009 11:14:31 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 5802449dd..7da1fb143 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -70,6 +70,11 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "X55SV ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + /* These 2 PACKARD BELL's are Asus notebook in disguise */ + { 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_BG45", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_BG46", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K40IJ ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "N10J ", @@ -77,6 +82,9 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { /* Note no whitespace padding for board vendor, this is not a typo */ { 0x064e, 0xa111, 0, "ASUSTeK Computer Inc.", "F5RL ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + /* Another Asus laptop in disguise */ + { 0x064e, 0xa111, 0, "PEGATRON CORPORATION ", "F5SR ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "N20A ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x090c, 0xe370, 0, "ASUSTeK Computer Inc. ", "U6S ", @@ -96,11 +104,6 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G2S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, - /* These PACKARD BELL's are Asus notebook in disguise */ - { 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_BG45", - V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, - { 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_BG46", - V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x5986, 0x0205, 0, "LENOVO", "Base Board Product Name", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED, 0, "Lenovo IdeaPad U330" }, -- cgit v1.2.3 From 63e4f194ca8471bdaf2c9442dece27410fb07cc9 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 9 Jul 2009 14:12:00 +0200 Subject: libv4l: Improved pac207 decompression code From: Hans de Goede Improved pac207 decompression code to also support higher compression modes of the pac207, which enables us to use higher framerates. Many many thanks to Bertrik Sikken for figuring the decompression out! Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 3 ++ .../libv4l/libv4lconvert/libv4lconvert-priv.h | 3 +- v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 7 ++- v4l2-apps/libv4l/libv4lconvert/pac207.c | 57 ++++++++++++++-------- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index acf74c527..a8ea42d1c 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -9,6 +9,9 @@ libv4l-0.6.0 * Add tons of laptop models to the upside down devices table * Support for rgb565 source format by Mauro Carvalho Chehab * Many bug fixes (see the mercurial tree for details) +* Improved pac207 decompression code to also support higher compression + modes of the pac207, which enables us to use higher framerates. + Many many thanks to Bertrik Sikken for figuring the decompression out! libv4l-0.5.99 ------------- diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h index d8a09c24a..4e3456bee 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h @@ -211,7 +211,8 @@ void v4lconvert_decode_spca561(const unsigned char *src, unsigned char *dst, void v4lconvert_decode_sn9c10x(const unsigned char *src, unsigned char *dst, int width, int height); -void v4lconvert_decode_pac207(const unsigned char *src, unsigned char *dst, +int v4lconvert_decode_pac207(struct v4lconvert_data *data, + const unsigned char *inp, int src_size, unsigned char *outp, int width, int height); void v4lconvert_decode_mr97310a(const unsigned char *src, unsigned char *dst, diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c index 4422ce084..6ff676abb 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -745,7 +745,12 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data, tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; break; case V4L2_PIX_FMT_PAC207: - v4lconvert_decode_pac207(src, tmpbuf, width, height); + if (v4lconvert_decode_pac207(data, src, src_size, tmpbuf, + width, height)) { + /* Corrupt frame, better get another one */ + errno = EAGAIN; + return -1; + } tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; break; case V4L2_PIX_FMT_MR97310A: diff --git a/v4l2-apps/libv4l/libv4lconvert/pac207.c b/v4l2-apps/libv4l/libv4lconvert/pac207.c index 97ef4ebc0..a81d5d511 100644 --- a/v4l2-apps/libv4l/libv4lconvert/pac207.c +++ b/v4l2-apps/libv4l/libv4lconvert/pac207.c @@ -52,35 +52,35 @@ static void init_pixart_decoder(void) len = 2; } else if ((i & 0xC0) == 0x40) { /* code 01 */ - val = -5; + val = -1; len = 2; } else if ((i & 0xC0) == 0x80) { /* code 10 */ - val = +5; + val = +1; len = 2; } else if ((i & 0xF0) == 0xC0) { /* code 1100 */ - val = -10; + val = -2; len = 4; } else if ((i & 0xF0) == 0xD0) { /* code 1101 */ - val = +10; + val = +2; len = 4; } else if ((i & 0xF8) == 0xE0) { /* code 11100 */ - val = -15; + val = -3; len = 5; } else if ((i & 0xF8) == 0xE8) { /* code 11101 */ - val = +15; + val = +3; len = 5; } else if ((i & 0xFC) == 0xF0) { /* code 111100 */ - val = -20; + val = -4; len = 6; } else if ((i & 0xFC) == 0xF4) { /* code 111101 */ - val = +20; + val = +4; len = 6; } else if ((i & 0xF8) == 0xF8) { /* code 11111xxxxxx */ @@ -109,7 +109,8 @@ static inline unsigned short getShort(const unsigned char *pt) } static int -pac_decompress_row(const unsigned char *inp, unsigned char *outp, int width) +pac_decompress_row(const unsigned char *inp, unsigned char *outp, int width, + int step_size, int abs_bits) { int col; int val; @@ -135,11 +136,11 @@ pac_decompress_row(const unsigned char *inp, unsigned char *outp, int width) if (table[code].is_abs) { /* absolute value: get 6 more bits */ code = getByte(inp, bitpos); - bitpos += 6; - *outp++ = code & 0xFC; + bitpos += abs_bits; + *outp++ = code & ~(0xff >> abs_bits); } else { /* relative to left pixel */ - val = outp[-2] + table[code].val; + val = outp[-2] + table[code].val * step_size; *outp++ = CLIP(val); } } @@ -148,18 +149,24 @@ pac_decompress_row(const unsigned char *inp, unsigned char *outp, int width) return 2 * ((bitpos + 15) / 16); } -void v4lconvert_decode_pac207(const unsigned char *inp, unsigned char *outp, +int v4lconvert_decode_pac207(struct v4lconvert_data *data, + const unsigned char *inp, int src_size, unsigned char *outp, int width, int height) { /* we should received a whole frame with header and EOL marker in myframe->data and return a GBRG pattern in frame->tmpbuffer remove the header then copy line by line EOL is set with 0x0f 0xf0 marker or 0x1e 0xe1 for compressed line*/ + const unsigned char *end = inp + src_size; unsigned short word; int row; /* iterate over all rows */ for (row = 0; row < height; row++) { + if ((inp + 2) > end) { + V4LCONVERT_ERR("incomplete pac207 frame\n"); + return -1; + } word = getShort(inp); switch (word) { case 0x0FF0: @@ -167,21 +174,31 @@ or 0x1e 0xe1 for compressed line*/ inp += (2 + width); break; case 0x1EE1: - inp += pac_decompress_row(inp, outp, width); + inp += pac_decompress_row(inp, outp, width, 5, 6); + break; + + case 0x2DD2: + inp += pac_decompress_row(inp, outp, width, 9, 5); break; - case 0x2DD2: /* prefix for "stronger" compressed lines, currently the - kernel driver programs the cam so that we should not - get any of these */ + case 0x3CC3: + inp += pac_decompress_row(inp, outp, width, 17, 4); + break; + + case 0x4BB4: + /* skip or copy line? */ + memcpy(outp, outp - 2 * width, width); + inp += 2; + break; default: /* corrupt frame */ - /* FIXME add error reporting */ - return; + V4LCONVERT_ERR("unknown pac207 row header: 0x%04x\n", (int)word); + return -1; } outp += width; } - return; + return 0; } -- cgit v1.2.3 From 91ee1547f250403bb4aac507b11bf893df0d961b Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 10 Jul 2009 15:12:08 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 7da1fb143..20a995241 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -58,6 +58,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { { 0x093a, 0x2476, 0, NULL, NULL, V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED|V4LCONTROL_WANTS_WB, 1500 }, /* Laptops */ + { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vc ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vn ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N51Vg ", @@ -104,6 +106,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G2S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0xa311, 0, "ASUSTeK Computer Inc. ", "A3F ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x5986, 0x0205, 0, "LENOVO", "Base Board Product Name", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED, 0, "Lenovo IdeaPad U330" }, -- cgit v1.2.3 From 128548bcb727ec7fa79a3a281712dc2a3f8e80e8 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 10 Jul 2009 15:13:05 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 4 ++++ v4l2-apps/libv4l/Makefile | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index a8ea42d1c..ffbad3e5e 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -1,3 +1,7 @@ +libv4l-0.6.1 +------------ +* Add more laptop models to the upside down devices table + libv4l-0.6.0 ------------ * Recognize disabled controls and replace with fake equivalents where diff --git a/v4l2-apps/libv4l/Makefile b/v4l2-apps/libv4l/Makefile index 8f72059e5..18dd17bdc 100644 --- a/v4l2-apps/libv4l/Makefile +++ b/v4l2-apps/libv4l/Makefile @@ -1,5 +1,5 @@ LIB_RELEASE=0 -V4L2_LIB_VERSION=$(LIB_RELEASE).6.0 +V4L2_LIB_VERSION=$(LIB_RELEASE).6.1 all install: $(MAKE) -C libv4lconvert V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@ -- cgit v1.2.3 From 10522e9e037af9fa283317ec0270ce0b8f05cb71 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 10 Jul 2009 19:20:57 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 20a995241..76e42ece9 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -79,6 +79,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K40IJ ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K50IJ ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "N10J ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* Note no whitespace padding for board vendor, this is not a typo */ -- cgit v1.2.3 From 68dc7281f696cd47941ab39f96e7e783bed14f1f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 12 Jul 2009 14:51:10 +0000 Subject: Add support for Humax/Coex DVB-T USB Stick 2.0 High Speed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Nam Phạm Thành This patch adds support for Humax/Coex DVB-T USB Stick 2.0 High Speed which is a very popular tuner sold in Vietnam. Tested with at least 3 tuners. CC: Patrick Boettcher Signed-off-by: Pham Thanh Nam Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/dibusb-mc.c | 10 ++++++++-- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c b/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c index 059cec955..a05b9f875 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c @@ -42,6 +42,8 @@ static struct usb_device_id dibusb_dib3000mc_table [] = { /* 11 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_WARM) }, /* 12 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_COLD) }, /* 13 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_WARM) }, +/* 14 */ { USB_DEVICE(USB_VID_HUMAX_COEX, USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD) }, +/* 15 */ { USB_DEVICE(USB_VID_HUMAX_COEX, USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table); @@ -66,7 +68,7 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, + .count = 8, .endpoint = 0x06, .u = { .bulk = { @@ -88,7 +90,7 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { .generic_bulk_ctrl_endpoint = 0x01, - .num_device_descs = 7, + .num_device_descs = 8, .devices = { { "DiBcom USB2.0 DVB-T reference design (MOD3000P)", { &dibusb_dib3000mc_table[0], NULL }, @@ -119,6 +121,10 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { { &dibusb_dib3000mc_table[12], NULL }, { &dibusb_dib3000mc_table[13], NULL }, }, + { "Humax/Coex DVB-T USB Stick 2.0 High Speed", + { &dibusb_dib3000mc_table[14], NULL }, + { &dibusb_dib3000mc_table[15], NULL }, + }, { NULL }, } }; diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 6eccce1a7..bf7320167 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -58,6 +58,7 @@ #define USB_VID_GIGABYTE 0x1044 #define USB_VID_YUAN 0x1164 #define USB_VID_XTENSIONS 0x1ae7 +#define USB_VID_HUMAX_COEX 0x10b9 /* Product IDs */ #define USB_PID_ADSTECH_USB2_COLD 0xa333 @@ -260,5 +261,7 @@ #define USB_PID_SONY_PLAYTV 0x0003 #define USB_PID_ELGATO_EYETV_DTT 0x0021 #define USB_PID_ELGATO_EYETV_DTT_Dlx 0x0020 +#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD 0x5000 +#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM 0x5001 #endif -- cgit v1.2.3 From 121108730f279bc32049ca5f4326b46641817626 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Tue, 14 Jul 2009 13:00:32 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 76e42ece9..9c9e77736 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -81,6 +81,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K50IJ ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K70AB ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "N10J ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* Note no whitespace padding for board vendor, this is not a typo */ -- cgit v1.2.3 From 9aba1d9db273279181ade3771f20a185f048348c Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 16 Jul 2009 17:03:40 +0200 Subject: libv4l: Make library subdir name configurable From: Gregor Jasny While studying the Debian library package name, I noticed that private So /usr/lib/libv4l should become /usr/lib/libv4l0. As this would break existing scripts, I suggest to start versioning with the next soname bump. The line in the makefiles will then read: ifeq ($(LIBSUBDIR),) LIBSUBDIR = libv4l$(LIB_RELEASE) endif Unfortunately, the private subdirs in Debian must be named after the library package, which would be libv4l-0. Therefore I need to configure the LIBSUBDIR at compile time. Priority: normal Signed-off-by: Gregor Jasny Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 1 + v4l2-apps/libv4l/libv4l1/Makefile | 8 ++++++-- v4l2-apps/libv4l/libv4l2/Makefile | 8 ++++++-- v4l2-apps/libv4l/libv4lconvert/Makefile | 10 +++++++--- v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 4 ++-- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index ffbad3e5e..9f170bdfd 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -1,6 +1,7 @@ libv4l-0.6.1 ------------ * Add more laptop models to the upside down devices table +* Makefile changes to make life easier for the Debian package (Gregor Jasny) libv4l-0.6.0 ------------ diff --git a/v4l2-apps/libv4l/libv4l1/Makefile b/v4l2-apps/libv4l/libv4l1/Makefile index e6d306055..3403f3710 100644 --- a/v4l2-apps/libv4l/libv4l1/Makefile +++ b/v4l2-apps/libv4l/libv4l1/Makefile @@ -33,6 +33,10 @@ ifeq ($(LIBDIR),) LIBDIR = $(PREFIX)/lib endif +ifeq ($(LIBSUBDIR),) +LIBSUBDIR = libv4l +endif + all: $(TARGETS) -include $(V4L1_OBJS:.o=.d) @@ -60,12 +64,12 @@ ifeq ($(LINKTYPE),static) mkdir -p $(DESTDIR)$(LIBDIR) install -m 644 $(V4L1_LIB) $(DESTDIR)$(LIBDIR) else - mkdir -p $(DESTDIR)$(LIBDIR)/libv4l + mkdir -p $(DESTDIR)$(LIBDIR)/$(LIBSUBDIR) install -m 755 $(V4L1_LIB).$(LIB_RELEASE) $(DESTDIR)$(LIBDIR) cd $(DESTDIR)$(LIBDIR) && \ ln -f -s $(V4L1_LIB).$(LIB_RELEASE) $(V4L1_LIB) install -m 755 $(V4L1COMPAT).$(LIB_RELEASE) \ - $(DESTDIR)$(LIBDIR)/libv4l/$(V4L1COMPAT) + $(DESTDIR)$(LIBDIR)/$(LIBSUBDIR)/$(V4L1COMPAT) endif mkdir -p $(DESTDIR)$(LIBDIR)/pkgconfig install -m 644 libv4l1.pc $(DESTDIR)$(LIBDIR)/pkgconfig diff --git a/v4l2-apps/libv4l/libv4l2/Makefile b/v4l2-apps/libv4l/libv4l2/Makefile index 06c010f3c..c13d7315d 100644 --- a/v4l2-apps/libv4l/libv4l2/Makefile +++ b/v4l2-apps/libv4l/libv4l2/Makefile @@ -33,6 +33,10 @@ ifeq ($(LIBDIR),) LIBDIR = $(PREFIX)/lib endif +ifeq ($(LIBSUBDIR),) +LIBSUBDIR = libv4l +endif + all: $(TARGETS) -include $(V4L2_OBJS:.o=.d) @@ -60,12 +64,12 @@ ifeq ($(LINKTYPE),static) mkdir -p $(DESTDIR)$(LIBDIR) install -m 644 $(V4L2_LIB) $(DESTDIR)$(LIBDIR) else - mkdir -p $(DESTDIR)$(LIBDIR)/libv4l + mkdir -p $(DESTDIR)$(LIBDIR)/$(LIBSUBDIR) install -m 755 $(V4L2_LIB).$(LIB_RELEASE) $(DESTDIR)$(LIBDIR) cd $(DESTDIR)$(LIBDIR) && \ ln -f -s $(V4L2_LIB).$(LIB_RELEASE) $(V4L2_LIB) install -m 755 $(V4L2CONVERT).$(LIB_RELEASE) \ - $(DESTDIR)$(LIBDIR)/libv4l/$(V4L2CONVERT) + $(DESTDIR)$(LIBDIR)/$(LIBSUBDIR)/$(V4L2CONVERT) endif mkdir -p $(DESTDIR)$(LIBDIR)/pkgconfig install -m 644 libv4l2.pc $(DESTDIR)$(LIBDIR)/pkgconfig diff --git a/v4l2-apps/libv4l/libv4lconvert/Makefile b/v4l2-apps/libv4l/libv4lconvert/Makefile index 036649e86..c3b894957 100644 --- a/v4l2-apps/libv4l/libv4lconvert/Makefile +++ b/v4l2-apps/libv4l/libv4lconvert/Makefile @@ -33,7 +33,11 @@ ifeq ($(LIBDIR),) LIBDIR = $(PREFIX)/lib endif -override CPPFLAGS += -DLIBDIR=\"$(LIBDIR)\" +ifeq ($(LIBSUBDIR),) +LIBSUBDIR = libv4l +endif + +override CPPFLAGS += -DLIBDIR=\"$(LIBDIR)\" -DLIBSUBDIR=\"$(LIBSUBDIR)\" all: $(TARGETS) @@ -55,7 +59,7 @@ libv4lconvert.pc: install: all mkdir -p $(DESTDIR)$(PREFIX)/include install -p -m 644 $(INCLUDES) $(DESTDIR)$(PREFIX)/include - mkdir -p $(DESTDIR)$(LIBDIR)/libv4l + mkdir -p $(DESTDIR)$(LIBDIR)/$(LIBSUBDIR) ifeq ($(LINKTYPE),static) install -m 644 $(CONVERT_LIB) $(DESTDIR)$(LIBDIR) else @@ -63,7 +67,7 @@ else cd $(DESTDIR)$(LIBDIR) && \ ln -f -s $(CONVERT_LIB).$(LIB_RELEASE) $(CONVERT_LIB) endif - install -m 755 *-decomp $(DESTDIR)$(LIBDIR)/libv4l + install -m 755 *-decomp $(DESTDIR)$(LIBDIR)/$(LIBSUBDIR) mkdir -p $(DESTDIR)$(LIBDIR)/pkgconfig install -m 644 libv4lconvert.pc $(DESTDIR)$(LIBDIR)/pkgconfig diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c index 6ff676abb..32849e8ca 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -672,7 +672,7 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data, v4lconvert_sn9c20x_to_yuv420(src, d, width, height, yvu); break; case V4L2_PIX_FMT_OV511: - if (v4lconvert_helper_decompress(data, LIBDIR "/libv4l/ov511-decomp", + if (v4lconvert_helper_decompress(data, LIBDIR "/" LIBSUBDIR "/ov511-decomp", src, src_size, d, d_size, width, height, yvu)) { /* Corrupt frame, better get another one */ errno = EAGAIN; @@ -680,7 +680,7 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data, } break; case V4L2_PIX_FMT_OV518: - if (v4lconvert_helper_decompress(data, LIBDIR "/libv4l/ov518-decomp", + if (v4lconvert_helper_decompress(data, LIBDIR "/" LIBSUBDIR "/ov518-decomp", src, src_size, d, d_size, width, height, yvu)) { /* Corrupt frame, better get another one */ errno = EAGAIN; -- cgit v1.2.3 From 6bd143668c399af17edddaaff09227d2217e6dd6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 20 Jul 2009 14:20:47 +0000 Subject: make digital side of pcHDTV HD-3000 functional again From: Jarod Wilson The dvb side of the pcHDTV HD-3000 doesn't work since at least 2.6.29. The crux of the problem is this: the HD-3000's device ID matches the modalias for the cx8800 driver, but not the cx8802 driver, which is required to set up the digital side of the card. You can load up cx8802 just fine, but cx88-dvb falls on its face, because the call to cx8802_register_driver() attempts to traverse the cx8802_devlist, which is completely empty. The list is only populated by the cx8802_probe() function, which never gets called for the HD-3000, as its device ID isn't matched by the cx8802 driver, so you wind up getting an -ENODEV return from cx8802_register_driver() back to cx88-dvb, and as a result, no digital side of the card for you. Long story short, by simply adding a vendor/device/subvendor/subdevice block to cx88-mpeg.c, cx8802_probe() will run, the cx88-2_devlist will get populated, cx8802_register_driver() won't fail, and cx88-dvb can actually load up all the way on this card. Channel scanning is of course currently failing for me still (works fine on several other cards I have handy), but that's another problem for another day... There might be a Better Way to do this, and I'm open to suggestions and willing to try them out, but this Works For Me. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-mpeg.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index e1bcd556b..c77981a8e 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -897,6 +897,11 @@ static struct pci_device_id cx8802_pci_tbl[] = { .device = 0x8802, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, + },{ /* pcHDTV HD-3000 */ + .vendor = 0x14f1, + .device = 0x8800, + .subvendor = 0x7063, + .subdevice = 0x3000, },{ /* --- end of list --- */ } -- cgit v1.2.3 From 232a32e4823887e382af8b96a5f21e7ab3891e21 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 21 Jul 2009 16:47:46 +0000 Subject: Use dst_type field instead of type_flags From: Julia Lawall It seems from other code that it is the dst_type field rather than the type_flags field that contains values of the form DST_TYPE_IS... The type_flags field contains values of the form DST_TYPE_HAS... The semantic match that finds this problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @@ struct dst_state E; @@ ( *E.type_flags == \( DST_TYPE_IS_SAT\|DST_TYPE_IS_TERR\|DST_TYPE_IS_CABLE\|DST_TYPE_IS_ATSC \) | *E.type_flags != \( DST_TYPE_IS_SAT\|DST_TYPE_IS_TERR\|DST_TYPE_IS_CABLE\|DST_TYPE_IS_ATSC \) ) // CC: Manu Abraham Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/bt8xx/dst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/bt8xx/dst.c b/linux/drivers/media/dvb/bt8xx/dst.c index fec1d77fa..91353a6fa 100644 --- a/linux/drivers/media/dvb/bt8xx/dst.c +++ b/linux/drivers/media/dvb/bt8xx/dst.c @@ -1059,7 +1059,7 @@ static int dst_get_tuner_info(struct dst_state *state) dprintk(verbose, DST_ERROR, 1, "DST type has TS=188"); } if (state->board_info[0] == 0xbc) { - if (state->type_flags != DST_TYPE_IS_ATSC) + if (state->dst_type != DST_TYPE_IS_ATSC) state->type_flags |= DST_TYPE_HAS_TS188; else state->type_flags |= DST_TYPE_HAS_NEWTUNE_2; -- cgit v1.2.3 From 27ec6ede22cb9fd152a2701c4f24b7f54ffb5b2f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 22 Jul 2009 03:02:29 +0000 Subject: ARRAY_SIZE changes From: Mauro Carvalho Chehab These changes were a direct result of using a semantic patch More information can be found at http://www.emn.fr/x-info/coccinelle/ Priority: normal [mchehab@redhat.com: fix a merge conflict] Signed-off-by: Stoyan Gaydarov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/conex.c | 2 +- linux/drivers/media/video/gspca/etoms.c | 4 ++-- linux/drivers/media/video/gspca/spca501.c | 2 +- linux/drivers/media/video/gspca/spca506.c | 2 +- linux/drivers/media/video/gspca/sunplus.c | 4 ++-- linux/drivers/media/video/gspca/zc3xx.c | 2 +- linux/drivers/media/video/tveeprom.c | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/video/gspca/conex.c b/linux/drivers/media/video/gspca/conex.c index 8d48ea174..eca003566 100644 --- a/linux/drivers/media/video/gspca/conex.c +++ b/linux/drivers/media/video/gspca/conex.c @@ -820,7 +820,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->cam_mode = vga_mode; - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + cam->nmodes = ARRAY_SIZE(vga_mode); sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; diff --git a/linux/drivers/media/video/gspca/etoms.c b/linux/drivers/media/video/gspca/etoms.c index 84f3a5eb8..42b36b8b7 100644 --- a/linux/drivers/media/video/gspca/etoms.c +++ b/linux/drivers/media/video/gspca/etoms.c @@ -635,10 +635,10 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor = id->driver_info; if (sd->sensor == SENSOR_PAS106) { cam->cam_mode = sif_mode; - cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; + cam->nmodes = ARRAY_SIZE(sif_mode); } else { cam->cam_mode = vga_mode; - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + cam->nmodes = ARRAY_SIZE(vga_mode); gspca_dev->ctrl_dis = (1 << COLOR_IDX); } sd->brightness = BRIGHTNESS_DEF; diff --git a/linux/drivers/media/video/gspca/spca501.c b/linux/drivers/media/video/gspca/spca501.c index 61dfc714f..9c4a2e6db 100644 --- a/linux/drivers/media/video/gspca/spca501.c +++ b/linux/drivers/media/video/gspca/spca501.c @@ -1948,7 +1948,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->cam_mode = vga_mode; - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + cam->nmodes = ARRAY_SIZE(vga_mode); sd->subtype = id->driver_info; sd->brightness = sd_ctrls[MY_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[MY_CONTRAST].qctrl.default_value; diff --git a/linux/drivers/media/video/gspca/spca506.c b/linux/drivers/media/video/gspca/spca506.c index 3a0c893f9..a199298a6 100644 --- a/linux/drivers/media/video/gspca/spca506.c +++ b/linux/drivers/media/video/gspca/spca506.c @@ -286,7 +286,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->cam_mode = vga_mode; - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + cam->nmodes = ARRAY_SIZE(vga_mode); sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index 270b86f24..33bac051d 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -872,7 +872,7 @@ static int sd_config(struct gspca_dev *gspca_dev, /* case BRIDGE_SPCA504: */ /* case BRIDGE_SPCA536: */ cam->cam_mode = vga_mode; - cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + cam->nmodes =ARRAY_SIZE(vga_mode); break; case BRIDGE_SPCA533: cam->cam_mode = custom_mode; @@ -883,7 +883,7 @@ static int sd_config(struct gspca_dev *gspca_dev, break; case BRIDGE_SPCA504C: cam->cam_mode = vga_mode2; - cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0]; + cam->nmodes = ARRAY_SIZE(vga_mode2); break; } sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c index 2a9480138..02b6e185f 100644 --- a/linux/drivers/media/video/gspca/zc3xx.c +++ b/linux/drivers/media/video/gspca/zc3xx.c @@ -7607,7 +7607,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, static const struct sd_desc sd_desc = { .name = MODULE_NAME, .ctrls = sd_ctrls, - .nctrls = sizeof sd_ctrls / sizeof sd_ctrls[0], + .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, .init = sd_init, .start = sd_start, diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c index 5e3c9f4e2..085b869f5 100644 --- a/linux/drivers/media/video/tveeprom.c +++ b/linux/drivers/media/video/tveeprom.c @@ -647,14 +647,14 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, tvee->has_radio = 1; } - if (tuner1 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) { + if (tuner1 < ARRAY_SIZE(hauppauge_tuner)) { tvee->tuner_type = hauppauge_tuner[tuner1].id; t_name1 = hauppauge_tuner[tuner1].name; } else { t_name1 = "unknown"; } - if (tuner2 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) { + if (tuner2 < ARRAY_SIZE(hauppauge_tuner)) { tvee->tuner2_type = hauppauge_tuner[tuner2].id; t_name2 = hauppauge_tuner[tuner2].name; } else { -- cgit v1.2.3 From 56c2830bdf4029ac6336993016266d843f99fe35 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 11:58:08 -0300 Subject: revert changeset 12476:a03f8edcaba7 From: Mauro Carvalho Chehab As asked by Jarod Wilson, this patch doesn't work properly. Reverting it. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-mpeg.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index c77981a8e..e1bcd556b 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -897,11 +897,6 @@ static struct pci_device_id cx8802_pci_tbl[] = { .device = 0x8802, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - },{ /* pcHDTV HD-3000 */ - .vendor = 0x14f1, - .device = 0x8800, - .subvendor = 0x7063, - .subdevice = 0x3000, },{ /* --- end of list --- */ } -- cgit v1.2.3 From 6d6da3a7c53bcd97db93c50943018e880d31412e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 24 Jul 2009 16:45:41 +0000 Subject: V4L/DVB: af9015: add new USB ID for KWorld PlusTV Dual DVB-T Stick (DVB-T 399U) From: Mart Raudsepp Add new USB ID (1b80:e400) for KWorld PlusTV Dual DVB-T Stick (DVB-T 399U). The model number on the devices sticker label is "KW-DVB-T 399UR". Signed-off-by: Mart Raudsepp Acked-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/af9015.c | 4 +++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 7798aabaa..21815367f 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -1267,6 +1267,7 @@ static struct usb_device_id af9015_usb_table[] = { {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)}, {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)}, +/* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1347,7 +1348,8 @@ static struct dvb_usb_device_properties af9015_properties[] = { { .name = "KWorld PlusTV Dual DVB-T Stick " \ "(DVB-T 399U)", - .cold_ids = {&af9015_usb_table[4], NULL}, + .cold_ids = {&af9015_usb_table[4], + &af9015_usb_table[25], NULL}, .warm_ids = {NULL}, }, { diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index bf7320167..3324a73d5 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -104,6 +104,7 @@ #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 #define USB_PID_INTEL_CE9500 0x9500 #define USB_PID_KWORLD_399U 0xe399 +#define USB_PID_KWORLD_399U_2 0xe400 #define USB_PID_KWORLD_395U 0xe396 #define USB_PID_KWORLD_395U_2 0xe39b #define USB_PID_KWORLD_395U_3 0xe395 -- cgit v1.2.3 From bf0b5acb84e3e997e8ecadbb7871cfbacabe2e9d Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sat, 25 Jul 2009 19:56:33 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 9c9e77736..b2b96b5b7 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -77,6 +77,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_BG46", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb036, 0, "ASUSTeK Computer Inc. ", "U6S ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K40IJ ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K50IJ ", @@ -99,8 +101,12 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Sa ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Sg ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Sr ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F5N ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* The G1S has been seen with 2 different board name strings */ { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, -- cgit v1.2.3 From d02c07fa32efb03f3c5f29781e4a1adbadef1e51 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 26 Jul 2009 10:41:04 +0200 Subject: libv4l: allow use of System / Product DMI strings in upside down cam list From: Hans de Goede libv4l: allow use of System / Product DMI strings in upside down cam list Priority: normal Signed-off-by: Hans de Goede --- .../libv4lconvert/control/libv4lcontrol-priv.h | 5 ++ .../libv4l/libv4lconvert/control/libv4lcontrol.c | 77 +++++++++++++--------- 2 files changed, 52 insertions(+), 30 deletions(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h index 3394132e0..834dee2ab 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h @@ -52,6 +52,11 @@ struct v4lcontrol_flags_info { /* Some seldom used dmi strings (for notebooks with bogus info in the board entries, but usefull info elsewhere). We keep this at the end as to not polute the initalizers for the normal case. */ + /* System (product) vendor / name */ + const char *dmi_system_vendor; + const char *dmi_system_name; + /* Board and System versions */ + const char *dmi_board_version; const char *dmi_system_version; }; diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index b2b96b5b7..3b0dd2307 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -119,7 +119,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { { 0x174f, 0xa311, 0, "ASUSTeK Computer Inc. ", "A3F ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x5986, 0x0205, 0, "LENOVO", "Base Board Product Name", - V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED, 0, "Lenovo IdeaPad U330" }, + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED, 0, NULL, NULL, NULL, + "Lenovo IdeaPad U330" }, /* Second: devices which should use some software processing by default */ /* Pac207 based devices */ @@ -148,6 +149,25 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { static const struct v4l2_queryctrl fake_controls[]; +static int v4lcontrol_get_dmi_string(const char *string, char *buf, int size) +{ + FILE *f; + char *s, sysfs_name[512]; + + snprintf(sysfs_name, sizeof(sysfs_name), + "/sys/devices/virtual/dmi/id/%s", string); + f = fopen(sysfs_name, "r"); + if (!f) { + buf[0] = 0; + return; + } + + s = fgets(buf, size, f); + if (s) + s[strlen(s) - 1] = 0; + fclose(f); +} + static void v4lcontrol_init_flags(struct v4lcontrol_data *data) { struct stat st; @@ -155,9 +175,8 @@ static void v4lcontrol_init_flags(struct v4lcontrol_data *data) char sysfs_name[512]; unsigned short vendor_id = 0; unsigned short product_id = 0; - char dmi_board_vendor[512] = ""; - char dmi_board_name[512]= ""; - char dmi_system_version[512]= ""; + char dmi_system_vendor[512], dmi_system_name[512], dmi_system_version[512]; + char dmi_board_vendor[512], dmi_board_name[512], dmi_board_version[512]; int i, minor; char c, *s, buf[32]; struct v4l2_input input; @@ -236,41 +255,39 @@ static void v4lcontrol_init_flags(struct v4lcontrol_data *data) return; /* Should never happen */ } - /* Get DMI board vendor and name */ - f = fopen("/sys/devices/virtual/dmi/id/board_vendor", "r"); - if (f) { - s = fgets(dmi_board_vendor, sizeof(dmi_board_vendor), f); - if (s) - s[strlen(s) - 1] = 0; - fclose(f); - } - - f = fopen("/sys/devices/virtual/dmi/id/board_name", "r"); - if (f) { - s = fgets(dmi_board_name, sizeof(dmi_board_name), f); - if (s) - s[strlen(s) - 1] = 0; - fclose(f); - } - - f = fopen("/sys/devices/virtual/dmi/id/product_version", "r"); - if (f) { - s = fgets(dmi_system_version, sizeof(dmi_system_version), f); - if (s) - s[strlen(s) - 1] = 0; - fclose(f); - } + /* Get DMI board and system strings */ + v4lcontrol_get_dmi_string("sys_vendor", dmi_system_vendor, + sizeof(dmi_system_vendor)); + v4lcontrol_get_dmi_string("product_name", dmi_system_name, + sizeof(dmi_system_name)); + v4lcontrol_get_dmi_string("product_version", dmi_system_version, + sizeof(dmi_system_version)); + + v4lcontrol_get_dmi_string("board_vendor", dmi_board_vendor, + sizeof(dmi_board_vendor)); + v4lcontrol_get_dmi_string("board_name", dmi_board_name, + sizeof(dmi_board_name)); + v4lcontrol_get_dmi_string("board_version", dmi_board_version, + sizeof(dmi_board_version)); for (i = 0; i < ARRAY_SIZE(v4lcontrol_flags); i++) if (v4lcontrol_flags[i].vendor_id == vendor_id && v4lcontrol_flags[i].product_id == (product_id & ~v4lcontrol_flags[i].product_mask) && + + (v4lcontrol_flags[i].dmi_system_vendor == NULL || + !strcmp(v4lcontrol_flags[i].dmi_system_vendor, dmi_system_vendor)) && + (v4lcontrol_flags[i].dmi_system_name == NULL || + !strcmp(v4lcontrol_flags[i].dmi_system_name, dmi_system_name)) && + (v4lcontrol_flags[i].dmi_system_version == NULL || + !strcmp(v4lcontrol_flags[i].dmi_system_version, dmi_system_version)) && + (v4lcontrol_flags[i].dmi_board_vendor == NULL || !strcmp(v4lcontrol_flags[i].dmi_board_vendor, dmi_board_vendor)) && (v4lcontrol_flags[i].dmi_board_name == NULL || !strcmp(v4lcontrol_flags[i].dmi_board_name, dmi_board_name)) && - (v4lcontrol_flags[i].dmi_system_version == NULL || - !strcmp(v4lcontrol_flags[i].dmi_system_version, dmi_system_version))) { + (v4lcontrol_flags[i].dmi_board_version == NULL || + !strcmp(v4lcontrol_flags[i].dmi_board_version, dmi_board_version))) { data->flags |= v4lcontrol_flags[i].flags; data->flags_info = &v4lcontrol_flags[i]; break; -- cgit v1.2.3 From 8a002c4721144c30733d736f6447ebd9238a8e21 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 27 Jul 2009 14:20:59 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 3b0dd2307..2a9038116 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -87,6 +87,9 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "N10J ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + /* Note no whitespace padding, this is not a typo */ + { 0x04f2, 0xb071, 0, "ASUSTeK Computer INC.", "N5051Tp", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* Note no whitespace padding for board vendor, this is not a typo */ { 0x064e, 0xa111, 0, "ASUSTeK Computer Inc.", "F5RL ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, -- cgit v1.2.3 From 89f9a2b48dabb22e84ddf4ca07284499aa5fc152 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 29 Jul 2009 13:02:50 +0200 Subject: gspca_pac207: remove a number of unneeded (repeated) register writes From: Hans de Goede gspca_pac207: remove a number of unneeded (repeated) register writes Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/pac207.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c index 95a97ab68..f20d21b1c 100644 --- a/linux/drivers/media/video/gspca/pac207.c +++ b/linux/drivers/media/video/gspca/pac207.c @@ -169,13 +169,9 @@ static const __u8 pac207_sensor_init[][8] = { {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0}, {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30}, {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00}, - {0x00, 0x00, 0x32, 0x00, 0x96, 0x00, 0xa2, 0x02}, {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00}, }; - /* 48 reg_72 Rate Control end BalSize_4a =0x36 */ -static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 }; - static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index, const u8 *buffer, u16 length) { @@ -274,7 +270,6 @@ static int sd_init(struct gspca_dev *gspca_dev) * Bit_1=LED, * Bit_2=Compression test mode enable */ pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */ - pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */ return 0; } @@ -289,9 +284,7 @@ static int sd_start(struct gspca_dev *gspca_dev) pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8); pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8); pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8); - pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8); - pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8); - pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4); + pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[3], 8); /* Compression Balance */ if (gspca_dev->width == 176) -- cgit v1.2.3 From 2f1c03be87cb8cd9f645aaf4c5c7206f3141ddad Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 29 Jul 2009 13:03:17 +0200 Subject: gspca_pac207: enable higher framerates / lower exposure settings From: Hans de Goede Now that we've figured out the higher compression settings (supported in libv4l-0.6.0 and later, so after this patch the driver should be used with libv4l-0.6.0 or higher only!), we can enable higher framerates. Which means lower exposure times, which is important for the use of the pac207 in full daylight. This patch also tweakes the brightness default and the per color gain balances to use the values which are adviced by Pixart in the pac207 application note. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/pac207.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c index f20d21b1c..96659433d 100644 --- a/linux/drivers/media/video/gspca/pac207.c +++ b/linux/drivers/media/video/gspca/pac207.c @@ -35,25 +35,17 @@ MODULE_LICENSE("GPL"); #define PAC207_BRIGHTNESS_MIN 0 #define PAC207_BRIGHTNESS_MAX 255 -#define PAC207_BRIGHTNESS_DEFAULT 4 /* power on default: 4 */ - -/* An exposure value of 4 also works (3 does not) but then we need to lower - the compression balance setting when in 352x288 mode, otherwise the usb - bandwidth is not enough and packets get dropped resulting in corrupt - frames. The problem with this is that when the compression balance gets - lowered below 0x80, the pac207 starts using a different compression - algorithm for some lines, these lines get prefixed with a 0x2dd2 prefix - and currently we do not know how to decompress these lines, so for now - we use a minimum exposure value of 5 */ -#define PAC207_EXPOSURE_MIN 5 +#define PAC207_BRIGHTNESS_DEFAULT 46 + +#define PAC207_EXPOSURE_MIN 3 #define PAC207_EXPOSURE_MAX 26 -#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 ?? */ -#define PAC207_EXPOSURE_KNEE 11 /* 4 = 30 fps, 11 = 8, 15 = 6 */ +#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 */ +#define PAC207_EXPOSURE_KNEE 8 /* 4 = 30 fps, 11 = 8, 15 = 6 */ #define PAC207_GAIN_MIN 0 #define PAC207_GAIN_MAX 31 #define PAC207_GAIN_DEFAULT 9 /* power on default: 9 */ -#define PAC207_GAIN_KNEE 20 +#define PAC207_GAIN_KNEE 31 #define PAC207_AUTOGAIN_DEADZONE 30 @@ -166,8 +158,8 @@ static const struct v4l2_pix_format sif_mode[] = { }; static const __u8 pac207_sensor_init[][8] = { - {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0}, - {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30}, + {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84}, + {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30}, {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00}, {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00}, }; @@ -290,7 +282,7 @@ static int sd_start(struct gspca_dev *gspca_dev) if (gspca_dev->width == 176) pac207_write_reg(gspca_dev, 0x4a, 0xff); else - pac207_write_reg(gspca_dev, 0x4a, 0x88); + pac207_write_reg(gspca_dev, 0x4a, 0x30); pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */ pac207_write_reg(gspca_dev, 0x08, sd->brightness); @@ -339,7 +331,7 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) if (sd->autogain_ignore_frames > 0) sd->autogain_ignore_frames--; else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, - 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE, + 100, PAC207_AUTOGAIN_DEADZONE, PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE)) sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; } -- cgit v1.2.3 From 6d42d3dbff0a3351611853581210b9fda6301510 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 31 Jul 2009 16:40:43 +0000 Subject: Fix lowband tuning with tda8261 From: Julian Scheel Attached is a patch which fixes tuning to low frequency channels with stb0899+tda8261 cards like the KNC TV-Station DVB-S2. The cause of the issue was a broken if construct, which should have been an if/else if, so that the setting for the lowest matching frequency is applied. Without this patch for example tuning to "arte" on Astra 19.2, 10744MHz SR22000 failed most times and when it failed the communication between driver and tda8261 was completely broken. This problem disappears with the attached patch. Signed-off-by: Julian Scheel Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/tda8261.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/tda8261.c b/linux/drivers/media/dvb/frontends/tda8261.c index b6d177799..320c3c36d 100644 --- a/linux/drivers/media/dvb/frontends/tda8261.c +++ b/linux/drivers/media/dvb/frontends/tda8261.c @@ -136,9 +136,9 @@ static int tda8261_set_state(struct dvb_frontend *fe, if (frequency < 1450000) buf[3] = 0x00; - if (frequency < 2000000) + else if (frequency < 2000000) buf[3] = 0x40; - if (frequency < 2150000) + else if (frequency < 2150000) buf[3] = 0x80; /* Set params */ -- cgit v1.2.3 From 2cf40a2b22144d35374eec8c26aab124bc129818 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 1 Aug 2009 11:02:38 +0000 Subject: firedtv: add PID filtering for SW zigzag retune From: Henrik Kurelid The AVC protocol uses the same command for tuning and PID filtering and since dvb-core uses a software zigzagging to do automatic retuning this could cause all PID filters to be cleared. PID filter information is now included in all DSD commands to the card. Background: There is a problem in the firedtv driver that causes recordings to stop if the SW zigzag algorithm in dvb-core kicks in with a retune after the application has set up the PID filters. Since tuning and setting PID filters uses the same AVC command (DSD) and only the replace subfunction is supported by the card, it is not possible to do a retune without setting the PID filters. This means that the PID filtering has to be sent in each tune. This problem applies to C and T cards since S and S2 cards tune using a vendor specific command. The patch corrects the problem by sending the PID list in each tune. I have tested it on my T card with a good result. How to trigger problem: Zap to a channel and output AV to a file, e.g. "tzap -c channels.conf SVT1 -r -o SVT1.ts". After a short while, pull the antenna cable from the card. The lock on the channel will disappear and the TS file will stop increasing in size. Wait a couple of seconds. Replug the cable again. You will get a lock on the channel again, but the TS file will never increase in size agains sinze no PIDS are filtered. Tested with kaffeine with DVB-T and DVB-C: Fixes retuning after antenna was plugged out and back in with DVB-T. Does not fix this with DVB-C, but also doesn't regress on DVB-C. Signed-off-by: Henrik Kurelid Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/firewire/firedtv-avc.c | 40 +++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/dvb/firewire/firedtv-avc.c b/linux/drivers/media/dvb/firewire/firedtv-avc.c index 620fa2c65..a2041df5f 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-avc.c +++ b/linux/drivers/media/dvb/firewire/firedtv-avc.c @@ -259,6 +259,26 @@ int avc_recv(struct firedtv *fdtv, void *data, size_t length) return 0; } +static int add_pid_filter(struct firedtv *fdtv, u8 *operand) +{ + int i, n, pos = 1; + + for (i = 0, n = 0; i < 16; i++) { + if (test_bit(i, &fdtv->channel_active)) { + operand[pos++] = 0x13; /* flowfunction relay */ + operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */ + operand[pos++] = (fdtv->channel_pid[i] >> 8) & 0x1f; + operand[pos++] = fdtv->channel_pid[i] & 0xff; + operand[pos++] = 0x00; /* tableID */ + operand[pos++] = 0x00; /* filter_length */ + n++; + } + } + operand[0] = n; + + return pos; +} + /* * tuning command for setting the relative LNB frequency * (not supported by the AVC standard) @@ -321,7 +341,8 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv, } } -static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params, +static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv, + struct dvb_frontend_parameters *params, struct avc_command_frame *c) { c->opcode = AVC_OPCODE_DSD; @@ -383,13 +404,13 @@ static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params, c->operand[20] = 0x00; c->operand[21] = 0x00; - /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ - c->operand[22] = 0x00; - c->length = 28; + /* Add PIDs to filter */ + c->length = ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4); } -static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params, +static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv, + struct dvb_frontend_parameters *params, struct avc_command_frame *c) { struct dvb_ofdm_parameters *ofdm = ¶ms->u.ofdm; @@ -486,10 +507,9 @@ static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params, c->operand[15] = 0x00; /* network_ID[0] */ c->operand[16] = 0x00; /* network_ID[1] */ - /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ - c->operand[17] = 0x00; - c->length = 24; + /* Add PIDs to filter */ + c->length = ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4); } int avc_tuner_dsd(struct firedtv *fdtv, @@ -507,8 +527,8 @@ int avc_tuner_dsd(struct firedtv *fdtv, switch (fdtv->type) { case FIREDTV_DVB_S: case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break; - case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(params, c); break; - case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(params, c); break; + case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params, c); break; + case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params, c); break; default: BUG(); } -- cgit v1.2.3 From 3a5d86fcd1ef7eb3617d26046cdffea4245ca987 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 1 Aug 2009 19:48:41 +0000 Subject: Use DIV_ROUND_CLOSEST From: Julia Lawall The kernel.h macro DIV_ROUND_CLOSEST performs the computation (x + d/2)/d but is perhaps more readable. The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @haskernel@ @@ @depends on haskernel@ expression x,__divisor; @@ - (((x) + ((__divisor) / 2)) / (__divisor)) + DIV_ROUND_CLOSEST(x,__divisor) // Signed-off-by: Julia Lawall Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/dib7000p.c | 2 +- linux/drivers/media/dvb/frontends/stb6100.c | 4 +++- linux/drivers/media/dvb/frontends/tda10021.c | 2 +- linux/drivers/media/dvb/frontends/ves1820.c | 2 +- linux/drivers/media/dvb/pluto2/pluto2.c | 2 +- linux/drivers/media/video/tuner-core.c | 4 ++-- linux/drivers/media/video/v4l1-compat.c | 5 ++--- 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/dib7000p.c b/linux/drivers/media/dvb/frontends/dib7000p.c index ebb7594e3..d56de75db 100644 --- a/linux/drivers/media/dvb/frontends/dib7000p.c +++ b/linux/drivers/media/dvb/frontends/dib7000p.c @@ -909,7 +909,7 @@ static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 255, 255, 255, 255, 255, 255}; u32 xtal = state->cfg.bw->xtal_hz / 1000; - int f_rel = ( (rf_khz + xtal/2) / xtal) * xtal - rf_khz; + int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz; int k; int coef_re[8],coef_im[8]; int bw_khz = bw; diff --git a/linux/drivers/media/dvb/frontends/stb6100.c b/linux/drivers/media/dvb/frontends/stb6100.c index 2b1af36b8..540967545 100644 --- a/linux/drivers/media/dvb/frontends/stb6100.c +++ b/linux/drivers/media/dvb/frontends/stb6100.c @@ -374,7 +374,9 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) /* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1))) */ nint = fvco / (state->reference << psd2); /* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9 */ - nfrac = (((fvco - (nint * state->reference << psd2)) << (9 - psd2)) + state->reference / 2) / state->reference; + nfrac = DIV_ROUND_CLOSEST((fvco - (nint * state->reference << psd2)) + << (9 - psd2), + state->reference); dprintk(verbose, FE_DEBUG, 1, "frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u", frequency, srate, (unsigned int)g, (unsigned int)odiv, diff --git a/linux/drivers/media/dvb/frontends/tda10021.c b/linux/drivers/media/dvb/frontends/tda10021.c index 242636e59..d90cd60ce 100644 --- a/linux/drivers/media/dvb/frontends/tda10021.c +++ b/linux/drivers/media/dvb/frontends/tda10021.c @@ -176,7 +176,7 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate tmp = ((symbolrate << 4) % FIN) << 8; ratio = (ratio << 8) + tmp / FIN; tmp = (tmp % FIN) << 8; - ratio = (ratio << 8) + (tmp + FIN/2) / FIN; + ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, FIN); BDR = ratio; BDRI = (((XIN << 5) / symbolrate) + 1) / 2; diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c index 6e78e4865..550a07a8a 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.c +++ b/linux/drivers/media/dvb/frontends/ves1820.c @@ -165,7 +165,7 @@ static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate) tmp = ((symbolrate << 4) % fin) << 8; ratio = (ratio << 8) + tmp / fin; tmp = (tmp % fin) << 8; - ratio = (ratio << 8) + (tmp + fin / 2) / fin; + ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, fin); BDR = ratio; BDRI = (((state->config->xin << 5) / symbolrate) + 1) / 2; diff --git a/linux/drivers/media/dvb/pluto2/pluto2.c b/linux/drivers/media/dvb/pluto2/pluto2.c index 647f6290e..8b6b2c094 100644 --- a/linux/drivers/media/dvb/pluto2/pluto2.c +++ b/linux/drivers/media/dvb/pluto2/pluto2.c @@ -447,7 +447,7 @@ static inline u32 divide(u32 numerator, u32 denominator) if (denominator == 0) return ~0; - return (numerator + denominator / 2) / denominator; + return DIV_ROUND_CLOSEST(numerator, denominator); } /* LG Innotek TDTE-E001P (Infineon TUA6034) */ diff --git a/linux/drivers/media/video/tuner-core.c b/linux/drivers/media/video/tuner-core.c index 85b133df4..a4f6c19b7 100644 --- a/linux/drivers/media/video/tuner-core.c +++ b/linux/drivers/media/video/tuner-core.c @@ -842,8 +842,8 @@ static int tuner_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) fe_tuner_ops->get_frequency(&t->fe, &abs_freq); f->frequency = (V4L2_TUNER_RADIO == t->mode) ? - (abs_freq * 2 + 125/2) / 125 : - (abs_freq + 62500/2) / 62500; + DIV_ROUND_CLOSEST(abs_freq * 2, 125) : + DIV_ROUND_CLOSEST(abs_freq, 62500); return 0; } f->frequency = (V4L2_TUNER_RADIO == t->mode) ? diff --git a/linux/drivers/media/video/v4l1-compat.c b/linux/drivers/media/video/v4l1-compat.c index ee3991f2f..2225243ad 100644 --- a/linux/drivers/media/video/v4l1-compat.c +++ b/linux/drivers/media/video/v4l1-compat.c @@ -77,9 +77,8 @@ get_v4l_control(struct file *file, dprintk("VIDIOC_G_CTRL: %d\n", err); return 0; } - return ((ctrl2.value - qctrl2.minimum) * 65535 - + (qctrl2.maximum - qctrl2.minimum) / 2) - / (qctrl2.maximum - qctrl2.minimum); + return DIV_ROUND_CLOSEST((ctrl2.value-qctrl2.minimum) * 65535, + qctrl2.maximum - qctrl2.minimum); } return 0; } -- cgit v1.2.3 From 6c611aa512f9f31e8880be5aa826b26e31d79cf9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 12:31:58 -0300 Subject: compat.h: implement DIV_ROUND_CLOSEST From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l/compat.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/v4l/compat.h b/v4l/compat.h index e73f03087..51e4408d4 100644 --- a/v4l/compat.h +++ b/v4l/compat.h @@ -72,6 +72,15 @@ #define vmalloc_32_user(a) vmalloc_32(a) #endif +#ifndef DIV_ROUND_CLOSEST +#define DIV_ROUND_CLOSEST(x, divisor)( \ +{ \ + typeof(divisor) __divisor = divisor; \ + (((x) + ((__divisor) / 2)) / (__divisor)); \ +} \ +) +#endif + #ifdef NEED_BOOL_TYPE /* bool type and enum-based definition of true and false was added in 2.6.19 */ typedef int bool; -- cgit v1.2.3 From 6a6c67ec6ada8fcc26c4fdbfbee70531fa737bcf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 2 Aug 2009 19:01:19 +0000 Subject: zl10353: correct implementation of FE_READ_UNCORRECTED_BLOCKS From: Aleksandr V. Piskunov Makes zl10353 a bit more DVB API compliant: FE_READ_UNCORRECTED_BLOCKS - keep a counter of UNC blocks FE_GET_FRONTEND - return last set frequency instead of zero Signed-off-by: Aleksandr V. Piskunov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/zl10353.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index a69e9602c..37a050efd 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.c +++ b/linux/drivers/media/dvb/frontends/zl10353.c @@ -39,6 +39,8 @@ struct zl10353_state { struct zl10353_config config; enum fe_bandwidth bandwidth; + u32 ucblocks; + u32 frequency; }; static int debug; @@ -204,6 +206,8 @@ static int zl10353_set_parameters(struct dvb_frontend *fe, u16 tps = 0; struct dvb_ofdm_parameters *op = ¶m->u.ofdm; + state->frequency = param->frequency; + zl10353_single_write(fe, RESET, 0x80); udelay(200); zl10353_single_write(fe, 0xEA, 0x01); @@ -469,7 +473,7 @@ static int zl10353_get_parameters(struct dvb_frontend *fe, break; } - param->frequency = 0; + param->frequency = state->frequency; op->bandwidth = state->bandwidth; param->inversion = INVERSION_AUTO; @@ -549,9 +553,13 @@ static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr) static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { struct zl10353_state *state = fe->demodulator_priv; + u32 ubl = 0; + + ubl = zl10353_read_register(state, RS_UBC_1) << 8 | + zl10353_read_register(state, RS_UBC_0); - *ucblocks = zl10353_read_register(state, RS_UBC_1) << 8 | - zl10353_read_register(state, RS_UBC_0); + state->ucblocks += ubl; + *ucblocks = state->ucblocks; return 0; } -- cgit v1.2.3 From 002b57013de6ad9e597eb9912dd16658b548d9f4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 30 Jul 2009 01:18:28 +0300 Subject: cx88: fix TBS 8920 card support From: Igor M. Liplianin It does matter to set explicitly gpio0 value in cx88_board structure for TBS 8920 card. Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx88/cx88-cards.c | 7 ++++++- linux/drivers/media/video/cx88/cx88-dvb.c | 9 ++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index 19d57e698..31256666c 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -1986,7 +1986,8 @@ static const struct cx88_board cx88_boards[] = { .radio_addr = ADDR_UNSET, .input = {{ .type = CX88_VMUX_DVB, - .vmux = 1, + .vmux = 0, + .gpio0 = 0x8080, } }, .mpeg = CX88_MPEG_DVB, }, @@ -3244,7 +3245,11 @@ static void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_PROF_6200: case CX88_BOARD_PROF_7300: case CX88_BOARD_SATTRADE_ST4200: + cx_write(MO_GP0_IO, 0x8000); + msleep(100); cx_write(MO_SRST_IO, 0); + msleep(10); + cx_write(MO_GP0_IO, 0x8080); msleep(100); cx_write(MO_SRST_IO, 1); msleep(100); diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index d3d4c67ec..28042ad5a 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -425,17 +425,16 @@ static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, struct cx8802_dev *dev= fe->dvb->priv; struct cx88_core *core = dev->core; + cx_set(MO_GP0_IO, 0x6040); switch (voltage) { case SEC_VOLTAGE_13: - printk("LNB Voltage SEC_VOLTAGE_13\n"); - cx_write(MO_GP0_IO, 0x00006040); + cx_clear(MO_GP0_IO, 0x20); break; case SEC_VOLTAGE_18: - printk("LNB Voltage SEC_VOLTAGE_18\n"); - cx_write(MO_GP0_IO, 0x00006060); + cx_set(MO_GP0_IO, 0x20); break; case SEC_VOLTAGE_OFF: - printk("LNB Voltage SEC_VOLTAGE_off\n"); + cx_clear(MO_GP0_IO, 0x20); break; } -- cgit v1.2.3 From 981223e70ff82e9b3868c6eb8964536149ad3f24 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 10 Aug 2009 07:48:16 +0000 Subject: Fix control AC-3 of the 6752HS From: Dmitri Belimov Fix error for AC-3 control of the 6752HS MPEG-2 coder. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa6752hs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/saa7134/saa6752hs.c b/linux/drivers/media/video/saa7134/saa6752hs.c index 860f271dd..32ecebe8c 100644 --- a/linux/drivers/media/video/saa7134/saa6752hs.c +++ b/linux/drivers/media/video/saa7134/saa6752hs.c @@ -475,7 +475,7 @@ static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) return -ERANGE; - new = old; + params->au_encoding = new; break; case V4L2_CID_MPEG_AUDIO_L2_BITRATE: old = params->au_l2_bitrate; -- cgit v1.2.3 From ed2baf21f311d3b8c28315ea54a05cd3c60ce47a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 11 Aug 2009 00:47:29 +0000 Subject: Add RDS config for BeholdTV cards From: Dmitri Belimov Add config of RDS part for the BeholdTV tuners. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 32f8bdb91..82b60b9ff 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -4120,6 +4120,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ @@ -4184,6 +4185,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ @@ -4214,6 +4216,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x00008000, .inputs = {{ @@ -4389,6 +4392,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, @@ -4417,6 +4421,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, @@ -4445,6 +4450,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, @@ -4473,6 +4479,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .tda9887_conf = TDA9887_PRESENT, .inputs = {{ .name = name_tv, @@ -4579,6 +4586,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .rds_addr = 0x10, .empress_addr = 0x20, .tda9887_conf = TDA9887_PRESENT, .inputs = { { -- cgit v1.2.3 From 24cb4c279c0d10fdc6b5649936b8bb0dbfd56433 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 14 Aug 2009 05:22:52 +0000 Subject: pwc - fix few use-after-free and memory leaks From: Dmitry Torokhov I just happen to peek inside the PWC driver and did not like what I saw there. Please consider applying the patch below. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pwc/pwc-if.c | 78 +++++++++++++++------------------- linux/drivers/media/video/pwc/pwc.h | 1 + 2 files changed, 36 insertions(+), 43 deletions(-) diff --git a/linux/drivers/media/video/pwc/pwc-if.c b/linux/drivers/media/video/pwc/pwc-if.c index f695c6624..788de22df 100644 --- a/linux/drivers/media/video/pwc/pwc-if.c +++ b/linux/drivers/media/video/pwc/pwc-if.c @@ -1065,7 +1065,8 @@ static int pwc_create_sysfs_files(struct video_device *vdev) goto err; if (pdev->features & FEATURE_MOTOR_PANTILT) { rc = device_create_file(&vdev->dev, &dev_attr_pan_tilt); - if (rc) goto err_button; + if (rc) + goto err_button; } return 0; @@ -1080,6 +1081,7 @@ err: static void pwc_remove_sysfs_files(struct video_device *vdev) { struct pwc_device *pdev = video_get_drvdata(vdev); + if (pdev->features & FEATURE_MOTOR_PANTILT) device_remove_file(&vdev->dev, &dev_attr_pan_tilt); device_remove_file(&vdev->dev, &dev_attr_button); @@ -1237,13 +1239,11 @@ static void pwc_cleanup(struct pwc_device *pdev) video_unregister_device(pdev->vdev); #ifdef CONFIG_USB_PWC_INPUT_EVDEV - if (pdev->button_dev) { + if (pdev->button_dev) input_unregister_device(pdev->button_dev); - input_free_device(pdev->button_dev); - kfree(pdev->button_dev->phys); - pdev->button_dev = NULL; - } #endif + + kfree(pdev); } /* Note that all cleanup is done in the reverse order as in _open */ @@ -1289,8 +1289,6 @@ static int pwc_video_close(struct file *file) PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); } else { pwc_cleanup(pdev); - /* Free memory (don't set pdev to 0 just yet) */ - kfree(pdev); /* search device_hint[] table if we occupy a slot, by any chance */ for (hint = 0; hint < MAX_DEV_HINTS; hint++) if (device_hint[hint].pdev == pdev) @@ -1507,13 +1505,10 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id struct usb_device *udev = interface_to_usbdev(intf); struct pwc_device *pdev = NULL; int vendor_id, product_id, type_id; - int i, hint, rc; + int hint, rc; int features = 0; int video_nr = -1; /* default: use next available device */ char serial_number[30], *name; -#ifdef CONFIG_USB_PWC_INPUT_EVDEV - char *phys = NULL; -#endif vendor_id = le16_to_cpu(udev->descriptor.idVendor); product_id = le16_to_cpu(udev->descriptor.idProduct); @@ -1765,8 +1760,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->vframes = default_fps; strcpy(pdev->serial, serial_number); pdev->features = features; - if (vendor_id == 0x046D && product_id == 0x08B5) - { + if (vendor_id == 0x046D && product_id == 0x08B5) { /* Logitech QuickCam Orbit The ranges have been determined experimentally; they may differ from cam to cam. Also, the exact ranges left-right and up-down are different for my cam @@ -1788,8 +1782,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->vdev = video_device_alloc(); if (!pdev->vdev) { PWC_ERROR("Err, cannot allocate video_device struture. Failing probe."); - kfree(pdev); - return -ENOMEM; + rc = -ENOMEM; + goto err_free_mem; } memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template)); pdev->vdev->parent = &intf->dev; @@ -1814,25 +1808,23 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id } pdev->vdev->release = video_device_release; - i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); - if (i < 0) { - PWC_ERROR("Failed to register as video device (%d).\n", i); - rc = i; - goto err; - } - else { - PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num); + rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); + if (rc < 0) { + PWC_ERROR("Failed to register as video device (%d).\n", rc); + goto err_video_release; } + PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num); + /* occupy slot */ if (hint < MAX_DEV_HINTS) device_hint[hint].pdev = pdev; PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev); - usb_set_intfdata (intf, pdev); + usb_set_intfdata(intf, pdev); rc = pwc_create_sysfs_files(pdev->vdev); if (rc) - goto err_unreg; + goto err_video_unreg; /* Set the leds off */ pwc_set_leds(pdev, 0, 0); @@ -1843,16 +1835,16 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id pdev->button_dev = input_allocate_device(); if (!pdev->button_dev) { PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); - return -ENOMEM; + rc = -ENOMEM; + pwc_remove_sysfs_files(pdev->vdev); + goto err_video_unreg; } + usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys)); + strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys)); + pdev->button_dev->name = "PWC snapshot button"; - phys = kasprintf(GFP_KERNEL,"usb-%s-%s", pdev->udev->bus->bus_name, pdev->udev->devpath); - if (!phys) { - input_free_device(pdev->button_dev); - return -ENOMEM; - } - pdev->button_dev->phys = phys; + pdev->button_dev->phys = pdev->button_phys; usb_to_input_id(pdev->udev, &pdev->button_dev->id); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) pdev->button_dev->dev.parent = &pdev->udev->dev; @@ -1865,25 +1857,27 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id rc = input_register_device(pdev->button_dev); if (rc) { input_free_device(pdev->button_dev); - kfree(pdev->button_dev->phys); pdev->button_dev = NULL; - return rc; + pwc_remove_sysfs_files(pdev->vdev); + goto err_video_unreg; } #endif return 0; -err_unreg: +err_video_unreg: if (hint < MAX_DEV_HINTS) device_hint[hint].pdev = NULL; video_unregister_device(pdev->vdev); -err: - video_device_release(pdev->vdev); /* Drip... drip... drip... */ - kfree(pdev); /* Oops, no memory leaks please */ + pdev->vdev = NULL; /* So we don't try to release it below */ +err_video_release: + video_device_release(pdev->vdev); +err_free_mem: + kfree(pdev); return rc; } -/* The user janked out the cable... */ +/* The user yanked out the cable... */ static void usb_pwc_disconnect(struct usb_interface *intf) { struct pwc_device *pdev; @@ -1914,7 +1908,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf) /* Alert waiting processes */ wake_up_interruptible(&pdev->frameq); /* Wait until device is closed */ - if(pdev->vopen) { + if (pdev->vopen) { mutex_lock(&pdev->modlock); pdev->unplugged = 1; mutex_unlock(&pdev->modlock); @@ -1923,8 +1917,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf) /* Device is closed, so we can safely unregister it */ PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); pwc_cleanup(pdev); - /* Free memory (don't set pdev to 0 just yet) */ - kfree(pdev); disconnect_out: /* search device_hint[] table if we occupy a slot, by any chance */ diff --git a/linux/drivers/media/video/pwc/pwc.h b/linux/drivers/media/video/pwc/pwc.h index 12c869d71..94c8e5a69 100644 --- a/linux/drivers/media/video/pwc/pwc.h +++ b/linux/drivers/media/video/pwc/pwc.h @@ -254,6 +254,7 @@ struct pwc_device int snapshot_button_status; /* set to 1 when the user push the button, reset to 0 when this value is read */ #ifdef CONFIG_USB_PWC_INPUT_EVDEV struct input_dev *button_dev; /* webcam snapshot button input */ + char button_phys[64]; #endif /*** Misc. data ***/ -- cgit v1.2.3 From 9835197004d3cc8362791e5a4db613d8e2b25b46 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Aug 2009 19:24:54 +0000 Subject: Report only 32kHz for ALSA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Oldřich Jedlička There are several reasons: - SAA7133/35 uses DDEP (DemDec Easy Programming mode), which works in 32kHz only - SAA7134 for TV mode uses DemDec mode (32kHz) - Radio works in 32kHz only - When recording 48kHz from Line1/Line2, switching of capture source to TV means switching to 32kHz without any frequency translation Signed-off-by: Oldřich Jedlička Acked-by: hermann pitton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-alsa.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/saa7134/saa7134-alsa.c b/linux/drivers/media/video/saa7134/saa7134-alsa.c index c09ec3e6f..504186ae6 100644 --- a/linux/drivers/media/video/saa7134/saa7134-alsa.c +++ b/linux/drivers/media/video/saa7134/saa7134-alsa.c @@ -440,6 +440,16 @@ snd_card_saa7134_capture_pointer(struct snd_pcm_substream * substream) /* * ALSA hardware capabilities definition + * + * Report only 32kHz for ALSA: + * + * - SAA7133/35 uses DDEP (DemDec Easy Programming mode), which works in 32kHz + * only + * - SAA7134 for TV mode uses DemDec mode (32kHz) + * - Radio works in 32kHz only + * - When recording 48kHz from Line1/Line2, switching of capture source to TV + * means + * switching to 32kHz without any frequency translation */ static struct snd_pcm_hardware snd_card_saa7134_capture = @@ -453,9 +463,9 @@ static struct snd_pcm_hardware snd_card_saa7134_capture = SNDRV_PCM_FMTBIT_U8 | \ SNDRV_PCM_FMTBIT_U16_LE | \ SNDRV_PCM_FMTBIT_U16_BE, - .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + .rates = SNDRV_PCM_RATE_32000, .rate_min = 32000, - .rate_max = 48000, + .rate_max = 32000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (256*1024), -- cgit v1.2.3 From 5ba9b1fa2dc6d6832ae773956d09922c9a7f3780 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 19 Aug 2009 19:41:59 +0000 Subject: remove unnecessary power management primitive in stk-webcam From: Oliver Neukum This patch removes an unneeded power management primitive. Power management is automatically enabled as probe ends. Signed-off-by: Oliver Neukum Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/stk-webcam.c | 1 - 1 file changed, 1 deletion(-) diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index aaeee8319..3034a31a5 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -1401,7 +1401,6 @@ static int stk_camera_probe(struct usb_interface *interface, } stk_create_sysfs_files(&dev->vdev); - usb_autopm_enable(dev->interface); return 0; -- cgit v1.2.3 From ef36e0392e76322283553a75b4f0e656c8151598 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Aug 2009 01:30:58 +0000 Subject: saa7134-input: don't probe for the Pinnacle remotes anymore From: hermann pitton With the recent improvements we don't need to probe anymore, if we know the i2c address of the receiver. The address of the receiver for the remote with the gray buttons is not confirmed anywhere, but it is very unlikely to see it on something else. We want to have that information anyway. BTW, those remaining still probing, please join. Signed-off-by: hermann pitton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-input.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 585f78af3..146ac816a 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -787,6 +787,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) #else init_data.get_key = get_key_pinnacle_color; init_data.ir_codes = ir_codes_pinnacle_color; + info.addr = 0x47; #endif } else { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) @@ -795,6 +796,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) #else init_data.get_key = get_key_pinnacle_grey; init_data.ir_codes = ir_codes_pinnacle_grey; + info.addr = 0x47; #endif } break; -- cgit v1.2.3 From 196154cdc667f000c62192f98d92bc7a90f6e981 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 21 Aug 2009 20:31:57 -0300 Subject: versions.txt: Don't compile smsdio on kernels lower than 2.6.24 From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l/versions.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l/versions.txt b/v4l/versions.txt index 4ce31f852..41c009263 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -29,6 +29,8 @@ SOC_CAMERA_MT9M001 [2.6.24] # Some freezer routines USB_GSPCA_SN9C20X_EVDEV +# Requires linux/mmc/sdio_func.h +SMS_SDIO_DRV [2.6.23] # Needs field intf_assoc in struct usb_host_config -- cgit v1.2.3 From 5d99eef4034c0c6059afabdccea5620e96e935e5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 21 Aug 2009 21:48:04 -0300 Subject: versions.txt: jeilinj needs 2.6.20 or upper From: Mauro Carvalho Chehab /home/v4l/master/v4l/jeilinj.c:282:43: error: macro "INIT_WORK" requires 3 arguments, but only 2 given /home/v4l/master/v4l/jeilinj.c: In function 'sd_config': /home/v4l/master/v4l/jeilinj.c:282: error: 'INIT_WORK' undeclared (first use in this function) /home/v4l/master/v4l/jeilinj.c:282: error: (Each undeclared identifier is reported only once /home/v4l/master/v4l/jeilinj.c:282: error: for each function it appears in.) Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l/versions.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/v4l/versions.txt b/v4l/versions.txt index 41c009263..413ede9e8 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -56,6 +56,7 @@ USB_SI470X RADIO_SI470X # use of struct delayed_work USB_GSPCA_FINEPIX +USB_GSPCA_JEILINJ # uses linux/hid.h and struct delayed_work USB_SI470X # due to INIT_WORK changes -- cgit v1.2.3 From 55978f5ebca02a1b6f03e130bdcd5b6957004025 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 21 Aug 2009 02:49:26 +0000 Subject: em28xx: Don't call em28xx_ir_init when disable_ir is true From: Shine Liu We should call em28xx_ir_init(dev) only when disable_ir is true. Signed-off-by: Shine Liu Reviewed-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index b8778577d..36bcaad4c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2498,7 +2498,9 @@ void em28xx_card_setup(struct em28xx *dev) } em28xx_tuner_setup(dev); - em28xx_ir_init(dev); + + if(!disable_ir) + em28xx_ir_init(dev); } -- cgit v1.2.3 From 0cba7f108664f9efc0e34a388c51cb943c72d68b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 21 Aug 2009 16:41:21 +0000 Subject: compat: Fix build for older kernels using DIV_ROUND_CLOSEST From: Andy Walls DIV_ROUND_CLOSEST() is not available on older kernels. Include compat.h in a few files to fix building v4l-dvb from mercurial on older kernels. Reported-by: Lou Otway Reported-by: Avo Aasma Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/stb6100.c | 1 + linux/drivers/media/dvb/frontends/tda10021.c | 1 + linux/drivers/media/dvb/frontends/ves1820.c | 1 + 3 files changed, 3 insertions(+) diff --git a/linux/drivers/media/dvb/frontends/stb6100.c b/linux/drivers/media/dvb/frontends/stb6100.c index 540967545..2de9e0c01 100644 --- a/linux/drivers/media/dvb/frontends/stb6100.c +++ b/linux/drivers/media/dvb/frontends/stb6100.c @@ -24,6 +24,7 @@ #include #include +#include "compat.h" #include "dvb_frontend.h" #include "stb6100.h" diff --git a/linux/drivers/media/dvb/frontends/tda10021.c b/linux/drivers/media/dvb/frontends/tda10021.c index d90cd60ce..f410fd5e2 100644 --- a/linux/drivers/media/dvb/frontends/tda10021.c +++ b/linux/drivers/media/dvb/frontends/tda10021.c @@ -29,6 +29,7 @@ #include #include +#include "compat.h" #include "dvb_frontend.h" #include "tda1002x.h" diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c index 550a07a8a..afd7f09ac 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.c +++ b/linux/drivers/media/dvb/frontends/ves1820.c @@ -27,6 +27,7 @@ #include #include +#include "compat.h" #include "dvb_frontend.h" #include "ves1820.h" -- cgit v1.2.3 From acfae2a2f2799047a9856f48803ed9d13d7f0e66 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 22 Aug 2009 23:17:30 -0300 Subject: v4l2-sysfs-path: print the subdevs associated with that device From: Mauro Carvalho Chehab The sysfs interface stores links to the other devices associated with a V4L link. Improves this util to display those associated subdevices. This small tool can be used inside other V4L applications to properly associate audio, input, sound and dvb devices with a /dev/video? file. device = /dev/video0 bus info = usb-0000:00:1d.7-8 sysfs path = /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-8 Subdevs: usb_endpoint:usbdev1.8_ep00 i2c-adapter:i2c-4 input:input8 sound:pcmC1D0c sound:dsp1 sound:audio1 sound:controlC1 sound:mixer1 dvb:dvb0.frontend0 dvb:dvb0.demux0 dvb:dvb0.dvr0 dvb:dvb0.net0 Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-sysfs-path.c | 51 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/util/v4l2-sysfs-path.c b/v4l2-apps/util/v4l2-sysfs-path.c index e3f3e63e8..90157fa11 100644 --- a/v4l2-apps/util/v4l2-sysfs-path.c +++ b/v4l2-apps/util/v4l2-sysfs-path.c @@ -23,6 +23,7 @@ #include #include #include +#include #define USB_ID "usb-" #define PCI_ID "PCI:" @@ -135,6 +136,52 @@ err: return NULL; } +/* + Examples of subdevs: + sound:audio1 + sound:controlC1 + sound:dsp1 + sound:mixer1 + sound:pcmC1D0c + dvb:dvb0.demux0 + dvb:dvb0.dvr0 + dvb:dvb0.frontend0 + dvb:dvb0.net0 + i2c-adapter:i2c-4 + input:input8 +*/ + +void get_subdevs(char *path) +{ + DIR *dir; + struct dirent *entry; + struct stat st; + char *p, name[1024]; + + dir = opendir(path); + if (!dir) + return; + + strcpy(name, path); + strcat(name, "/"); + p = name + strlen(name); + + printf("Subdevs: "); + entry = readdir(dir); + while (entry) { + strcpy(p, entry->d_name); + if ((lstat(name, &st) == 0) && + !S_ISDIR(st.st_mode)) { + char *s = strchr(entry->d_name, ':'); + if (s) + printf("%s ", entry->d_name); + } + entry = readdir(dir); + } + closedir(dir); + printf("\n"); +} + void get_sysfs(char *fname) { struct v4l2_driver drv; @@ -148,9 +195,11 @@ void get_sysfs(char *fname) printf("bus info = %s\n", drv.cap.bus_info); path = obtain_bus_sysfs_path((char *)drv.cap.bus_info); if (path) { - printf("sysfs path = %s\n\n", path); + printf("sysfs path = %s\n", path); + get_subdevs(path); free(path); } + printf("\n"); v4l2_close(&drv); } -- cgit v1.2.3 From bc086d6c321888e2a8df7c9495d09c46a393cb1a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 23 Aug 2009 00:22:30 -0300 Subject: firmware-tool: fix compilation From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/xc3028-firmware/firmware-tool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v4l2-apps/util/xc3028-firmware/firmware-tool.c b/v4l2-apps/util/xc3028-firmware/firmware-tool.c index de1262ceb..43b78df7e 100644 --- a/v4l2-apps/util/xc3028-firmware/firmware-tool.c +++ b/v4l2-apps/util/xc3028-firmware/firmware-tool.c @@ -33,8 +33,8 @@ #include #include -#include "../../../linux/drivers/media/video/tuner-xc2028-types.h" -#include "../../../linux/include/linux/videodev2.h" +#include "../../../linux/drivers/media/common/tuners/tuner-xc2028-types.h" +#include "linux/videodev2.h" #include "extract_head.h" #include "standards.h" -- cgit v1.2.3 From 2d5790ba1659b7cea2c72ac05747f29852fa272d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 23 Aug 2009 12:45:08 -0300 Subject: v4l2-sysfs-path: print device minor/major of the associated devices From: Mauro Carvalho Chehab Instead of just printing the associated devices, go further and display the device major/minors and the associated event interface. The output will look like: device = /dev/video0 bus info = usb-0000:00:1d.7-8 sysfs path = /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-8 Associated devices: usb_endpoint:usbdev1.8_ep00 (dev 252,20) i2c-adapter:i2c-4 input:input9:event6 (dev 13,70) sound:pcmC1D0c (dev 116,9) sound:dsp1 (dev 14,19) sound:audio1 (dev 14,20) sound:controlC1 (dev 116,10) sound:mixer1 (dev 14,16) dvb:dvb0.frontend0 (dev 212,0) dvb:dvb0.demux0 (dev 212,1) dvb:dvb0.dvr0 (dev 212,2) dvb:dvb0.net0 (dev 212,3) Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-sysfs-path.c | 90 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 6 deletions(-) diff --git a/v4l2-apps/util/v4l2-sysfs-path.c b/v4l2-apps/util/v4l2-sysfs-path.c index 90157fa11..2a6ab0cfc 100644 --- a/v4l2-apps/util/v4l2-sysfs-path.c +++ b/v4l2-apps/util/v4l2-sysfs-path.c @@ -136,6 +136,75 @@ err: return NULL; } +char *seek_name(char *path, char *match) +{ + DIR *dir; + struct dirent *entry; + struct stat st; + char *p; + static char name[1024]; + int major, minor; + + dir = opendir(path); + if (!dir) + return NULL; + + strcpy(name, path); + strcat(name, "/"); + p = name + strlen(name); + + entry = readdir(dir); + while (entry) { + if (!strncmp(entry->d_name, match, strlen(match))) { + + strcpy(name, entry->d_name); + closedir(dir); + return name; + } + entry = readdir(dir); + } + closedir(dir); + return NULL; +} + +int get_dev(char *class, int *major, int *minor, char *extra) +{ + char path[1024]; + char *name; + FILE *fp; + + name = strchr(class,':'); + if (!name) + return -1; + *name = 0; + name++; + + *extra = 0; + + if (!strcmp(class, "input")) { + char *event; + + sprintf(path, "/sys/class/%s/%s/", class, name); + event = seek_name(path, "event"); + if (!event) + return -1; + + strcpy(extra, event); + + sprintf(path, "/sys/class/%s/%s/%s/dev", class, name, event); + + } else + sprintf(path, "/sys/class/%s/%s/dev", class, name); + + fp = fopen(path, "r"); + if (!fp) + return -1; + + fscanf(fp, "%d:%d", major, minor); + + return 0; +} + /* Examples of subdevs: sound:audio1 @@ -156,7 +225,8 @@ void get_subdevs(char *path) DIR *dir; struct dirent *entry; struct stat st; - char *p, name[1024]; + char *p, name[1024], extra[20]; + int major, minor; dir = opendir(path); if (!dir) @@ -166,20 +236,28 @@ void get_subdevs(char *path) strcat(name, "/"); p = name + strlen(name); - printf("Subdevs: "); + printf("Associated devices:\n"); entry = readdir(dir); while (entry) { strcpy(p, entry->d_name); - if ((lstat(name, &st) == 0) && + if ((lstat(name, &st) == 0) && !S_ISDIR(st.st_mode)) { char *s = strchr(entry->d_name, ':'); - if (s) - printf("%s ", entry->d_name); + if (s) { + printf("\t%s", entry->d_name); + if (!get_dev(entry->d_name, &major, &minor, extra)) + if (*extra) + printf(":%s (dev %d,%d)", + extra, major, minor); + else + printf(" (dev %d,%d)", + major, minor); + printf("\n"); + } } entry = readdir(dir); } closedir(dir); - printf("\n"); } void get_sysfs(char *fname) -- cgit v1.2.3 From 6e1e0a7781dec40d41a9f8de5f694dacbac70cc6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 23 Aug 2009 13:55:25 -0300 Subject: compat.h: Fix compilation breakage with vanilla 2.6.16 to 2.6.19 From: Mauro Carvalho Chehab /marune/build/v4l-dvb-master/v4l/bttv-driver.c:4635: warning: implicit declaration of function 'PCI_VDEVICE' /marune/build/v4l-dvb-master/v4l/bttv-driver.c:4635: error: 'BROOKTREE' undeclared here (not in a function) /marune/build/v4l-dvb-master/v4l/bttv-driver.c:4635: error: initializer element is not constant /marune/build/v4l-dvb-master/v4l/bttv-driver.c:4635: error: (near initialization for 'bttv_pci_tbl[0].vendor') /marune/build/v4l-dvb-master/v4l/bttv-driver.c:4636: error: initializer element is not constant /marune/build/v4l-dvb-master/v4l/bttv-driver.c:4636: error: (near initialization for 'bttv_pci_tbl[1].vendor') /marune/build/v4l-dvb-master/v4l/bttv-driver.c:4637: error: initializer element is not constant /marune/build/v4l-dvb-master/v4l/bttv-driver.c:4637: error: (near initialization for 'bttv_pci_tbl[2].vendor') /marune/build/v4l-dvb-master/v4l/bttv-driver.c:4638: error: initializer element is not constant /marune/build/v4l-dvb-master/v4l/bttv-driver.c:4638: error: (near initialization for 'bttv_pci_tbl[3].vendor') Signed-off-by: Mauro Carvalho Chehab --- v4l/compat.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/v4l/compat.h b/v4l/compat.h index 51e4408d4..465b3ae8b 100644 --- a/v4l/compat.h +++ b/v4l/compat.h @@ -508,4 +508,10 @@ static inline unsigned long hrtimer_forward_now(struct hrtimer *timer, #endif #endif /* _LINUX_HRTIMER_H */ +#ifndef PCI_VDEVICE +#define PCI_VDEVICE(vendor, device) \ + PCI_VENDOR_ID_##vendor, (device), \ + PCI_ANY_ID, PCI_ANY_ID, 0, 0 +#endif + #endif /* _COMPAT_H */ -- cgit v1.2.3 From c8ad89b126394193632a77bc2502ea045cb383cf Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 25 Aug 2009 11:14:54 +0200 Subject: gspca - sonixj: Do the ov7660 sensor work again. From: Jean-Francois Moine - bad sensor power - bad edge gain/threshold - set back the auto gain - light frequency filter inverted Priority: high Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 98fb39c99..6a668deb1 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -741,7 +741,7 @@ static const u8 ov7660_sensor_init[][8] = { /* COM 1 BAVE GEAVE AECHH */ {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */ {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */ -#if 1 +#if 0 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10}, #else {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, @@ -795,7 +795,7 @@ static const u8 ov7660_sensor_init[][8] = { {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */ {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */ {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */ - {0xb1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10}, /****** (some exchanges in the win trace) ******/ {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */ /* bits[3..0]reserved */ @@ -1165,11 +1165,13 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x01, 0x42); break; case SENSOR_OV7660: +#if 0 reg_w1(gspca_dev, 0x01, 0x61); reg_w1(gspca_dev, 0x17, 0x20); reg_w1(gspca_dev, 0x01, 0x60); reg_w1(gspca_dev, 0x01, 0x40); break; +#endif case SENSOR_SP80708: reg_w1(gspca_dev, 0x01, 0x63); reg_w1(gspca_dev, 0x17, 0x20); @@ -1654,6 +1656,8 @@ static void setvflip(struct sd *sd) static void setinfrared(struct sd *sd) { + if (sd->gspca_dev.ctrl_dis & (1 << INFRARED_IDX)) + return; /*fixme: different sequence for StarCam Clip and StarCam 370i */ #if 1 /* Clip */ @@ -1675,14 +1679,14 @@ static void setfreq(struct gspca_dev *gspca_dev) if (sd->sensor == SENSOR_OV7660) { u8 com8; -#if 1 - com8 = 0xf8; /* no auto gain/wb/expo */ +#if 0 + com8 = 0xd8; /* no auto gain/wb/expo */ #else - com8 = 0xff; + com8 = 0xdf; /* auto gain/wb/expo */ #endif switch (sd->freq) { case 0: /* Banding filter disabled */ - i2c_w1(gspca_dev, 0x13, com8 & 0xdf); + i2c_w1(gspca_dev, 0x13, com8 | 0x20); break; case 1: /* 50 hz */ i2c_w1(gspca_dev, 0x13, com8); @@ -1839,12 +1843,14 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x99, 0x60); break; case SENSOR_OV7660: +#if 0 reg_w1(gspca_dev, 0x9a, 0x05); if (sd->bridge == BRIDGE_SN9C105) reg_w1(gspca_dev, 0x99, 0xff); else reg_w1(gspca_dev, 0x99, 0x5b); break; +#endif case SENSOR_SP80708: reg_w1(gspca_dev, 0x9a, 0x05); reg_w1(gspca_dev, 0x99, 0x59); @@ -2373,7 +2379,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)}, /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)}, -/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */ +/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6802, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)}, /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */ -- cgit v1.2.3 From 9d0dc1f40d5d02887f421e23e1c6e0c93bf69f00 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:04:30 +0200 Subject: ARM: convert pcm990 to soc-camera as platform-device From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski kernel-sync: --- arch/arm/mach-pxa/pcm990-baseboard.c | 54 +++++++++++++++++++++++++++------ 1 files changed, 44 insertions(+), 10 deletions(-) --- linux/arch/arm/mach-pxa/pcm990-baseboard.c | 54 ++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/linux/arch/arm/mach-pxa/pcm990-baseboard.c b/linux/arch/arm/mach-pxa/pcm990-baseboard.c index 01791d74e..713f24c94 100644 --- a/linux/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/linux/arch/arm/mach-pxa/pcm990-baseboard.c @@ -427,25 +427,56 @@ static void pcm990_camera_free_bus(struct soc_camera_link *link) gpio_bus_switch = -EINVAL; } -static struct soc_camera_link iclink = { - .bus_id = 0, /* Must match with the camera ID above */ - .query_bus_param = pcm990_camera_query_bus_param, - .set_bus_param = pcm990_camera_set_bus_param, - .free_bus = pcm990_camera_free_bus, -}; - /* Board I2C devices. */ static struct i2c_board_info __initdata pcm990_i2c_devices[] = { { /* Must initialize before the camera(s) */ I2C_BOARD_INFO("pca9536", 0x41), .platform_data = &pca9536_data, - }, { + }, +}; + +static struct i2c_board_info pcm990_camera_i2c[] = { + { I2C_BOARD_INFO("mt9v022", 0x48), - .platform_data = &iclink, /* With extender */ }, { I2C_BOARD_INFO("mt9m001", 0x5d), - .platform_data = &iclink, /* With extender */ + }, +}; + +static struct soc_camera_link iclink[] = { + { + .bus_id = 0, /* Must match with the camera ID */ + .board_info = &pcm990_camera_i2c[0], + .i2c_adapter_id = 0, + .query_bus_param = pcm990_camera_query_bus_param, + .set_bus_param = pcm990_camera_set_bus_param, + .free_bus = pcm990_camera_free_bus, + .module_name = "mt9v022", + }, { + .bus_id = 0, /* Must match with the camera ID */ + .board_info = &pcm990_camera_i2c[1], + .i2c_adapter_id = 0, + .query_bus_param = pcm990_camera_query_bus_param, + .set_bus_param = pcm990_camera_set_bus_param, + .free_bus = pcm990_camera_free_bus, + .module_name = "mt9m001", + }, +}; + +static struct platform_device pcm990_camera[] = { + { + .name = "soc-camera-pdrv", + .id = 0, + .dev = { + .platform_data = &iclink[0], + }, + }, { + .name = "soc-camera-pdrv", + .id = 1, + .dev = { + .platform_data = &iclink[1], + }, }, }; #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */ @@ -501,6 +532,9 @@ void __init pcm990_baseboard_init(void) pxa_set_camera_info(&pcm990_pxacamera_platform_data); i2c_register_board_info(0, ARRAY_AND_SIZE(pcm990_i2c_devices)); + + platform_device_register(&pcm990_camera[0]); + platform_device_register(&pcm990_camera[1]); #endif printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n"); -- cgit v1.2.3 From aea41520a95b61491620e5702c8322a8fcfbf12e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:06:21 +0200 Subject: soc-camera: prepare soc_camera_platform.c and its users for conversion From: Guennadi Liakhovetski soc_camera_platform.c is only used by y SuperH ap325rxa board. This patch converts soc_camera_platform.c and its users for the soc-camera platform- device conversion and also extends soc-camera core to handle non-I2C cameras. Signed-off-by: Guennadi Liakhovetski Cc: Paul Mundt Acked-by: Paul Mundt Priority: low --- arch/sh/boards/board-ap325rxa.c | 43 ++++++++++++++++++------ drivers/media/video/soc_camera.c | 61 ++++++++++++++++++++++++++-------- include/media/soc_camera.h | 6 +++ include/media/soc_camera_platform.h | 2 + 4 files changed, 86 insertions(+), 26 deletions(-) --- linux/arch/sh/boards/board-ap325rxa.c | 43 ++++++++++++++++------ linux/drivers/media/video/soc_camera.c | 61 +++++++++++++++++++++++-------- linux/include/media/soc_camera.h | 6 +++ linux/include/media/soc_camera_platform.h | 2 + 4 files changed, 86 insertions(+), 26 deletions(-) diff --git a/linux/arch/sh/boards/board-ap325rxa.c b/linux/arch/sh/boards/board-ap325rxa.c index 7ffd1b431..a40dc9d00 100644 --- a/linux/arch/sh/boards/board-ap325rxa.c +++ b/linux/arch/sh/boards/board-ap325rxa.c @@ -307,6 +307,9 @@ static int camera_set_capture(struct soc_camera_platform_info *info, return ret; } +static int ap325rxa_camera_add(struct soc_camera_link *icl, struct device *dev); +static void ap325rxa_camera_del(struct soc_camera_link *icl); + static struct soc_camera_platform_info camera_info = { .iface = 0, .format_name = "UYVY", @@ -320,6 +323,10 @@ static struct soc_camera_platform_info camera_info = { .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8, .set_capture = camera_set_capture, + .link = { + .add_device = ap325rxa_camera_add, + .del_device = ap325rxa_camera_del, + }, }; static struct platform_device camera_device = { @@ -329,15 +336,20 @@ static struct platform_device camera_device = { }, }; -static int __init camera_setup(void) +static int ap325rxa_camera_add(struct soc_camera_link *icl, + struct device *dev) { - if (camera_probe() > 0) - platform_device_register(&camera_device); + if (icl != &camera_info.link || camera_probe() <= 0) + return -ENODEV; - return 0; + return platform_device_register(&camera_device); } -late_initcall(camera_setup); +static void ap325rxa_camera_del(struct soc_camera_link *icl) +{ + if (icl == &camera_info.link) + platform_device_unregister(&camera_device); +} #endif /* CONFIG_I2C */ static int ov7725_power(struct device *dev, int mode) @@ -417,11 +429,19 @@ static struct ov772x_camera_info ov7725_info = { }, }; -static struct platform_device ap325rxa_camera = { - .name = "soc-camera-pdrv", - .id = 0, - .dev = { - .platform_data = &ov7725_info.link, +static struct platform_device ap325rxa_camera[] = { + { + .name = "soc-camera-pdrv", + .id = 0, + .dev = { + .platform_data = &ov7725_info.link, + }, + }, { + .name = "soc-camera-pdrv", + .id = 1, + .dev = { + .platform_data = &camera_info.link, + }, }, }; @@ -432,7 +452,8 @@ static struct platform_device *ap325rxa_devices[] __initdata = { &ceu_device, &nand_flash_device, &sdcard_cn3_device, - &ap325rxa_camera, + &ap325rxa_camera[0], + &ap325rxa_camera[1], }; static struct spi_board_info ap325rxa_spi_devices[] = { diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 4f315c1b7..8de620b78 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -1166,45 +1166,76 @@ void soc_camera_video_stop(struct soc_camera_device *icd) } EXPORT_SYMBOL(soc_camera_video_stop); -static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) +#ifdef CONFIG_I2C_BOARDINFO +static int soc_camera_init_i2c(struct platform_device *pdev, + struct soc_camera_link *icl) { - struct soc_camera_link *icl = pdev->dev.platform_data; - struct i2c_adapter *adap; struct i2c_client *client; + struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); + int ret; - if (!icl) - return -EINVAL; - - adap = i2c_get_adapter(icl->i2c_adapter_id); if (!adap) { - dev_warn(&pdev->dev, "Cannot get adapter #%d. No driver?\n", - icl->i2c_adapter_id); - /* -ENODEV and -ENXIO do not produce an error on probe()... */ - return -ENOENT; + ret = -ENODEV; + dev_err(&pdev->dev, "Cannot get adapter #%d. No driver?\n", + icl->i2c_adapter_id); + goto ei2cga; } icl->board_info->platform_data = icl; client = i2c_new_device(adap, icl->board_info); if (!client) { - i2c_put_adapter(adap); - return -ENOMEM; + ret = -ENOMEM; + goto ei2cnd; } platform_set_drvdata(pdev, client); return 0; +ei2cnd: + i2c_put_adapter(adap); +ei2cga: + return ret; } -static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) +static void soc_camera_free_i2c(struct platform_device *pdev) { struct i2c_client *client = platform_get_drvdata(pdev); if (!client) - return -ENODEV; + return; i2c_unregister_device(client); i2c_put_adapter(client->adapter); +} +#else +#define soc_camera_init_i2c(d, icl) (-ENODEV) +#define soc_camera_free_i2c(d) do {} while (0) +#endif +static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) +{ + struct soc_camera_link *icl = pdev->dev.platform_data; + + if (!icl) + return -EINVAL; + + if (icl->board_info) + return soc_camera_init_i2c(pdev, icl); + else if (!icl->add_device || !icl->del_device) + return -EINVAL; + + /* &pdev->dev will become &icd->dev */ + return icl->add_device(icl, &pdev->dev); +} + +static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) +{ + struct soc_camera_link *icl = pdev->dev.platform_data; + + if (icl->board_info) + soc_camera_free_i2c(pdev); + else + icl->del_device(icl); return 0; } diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 23ecead35..813e12061 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -102,6 +102,12 @@ struct soc_camera_link { int i2c_adapter_id; struct i2c_board_info *board_info; const char *module_name; + /* + * For non-I2C devices platform platform has to provide methods to + * add a device to the system and to remove + */ + int (*add_device)(struct soc_camera_link *, struct device *); + void (*del_device)(struct soc_camera_link *); /* Optional callbacks to power on or off and reset the sensor */ int (*power)(struct device *, int); int (*reset)(struct device *); diff --git a/linux/include/media/soc_camera_platform.h b/linux/include/media/soc_camera_platform.h index 1d092b467..af224dead 100644 --- a/linux/include/media/soc_camera_platform.h +++ b/linux/include/media/soc_camera_platform.h @@ -12,6 +12,7 @@ #define __SOC_CAMERA_H__ #include +#include struct soc_camera_platform_info { int iface; @@ -21,6 +22,7 @@ struct soc_camera_platform_info { unsigned long bus_param; void (*power)(int); int (*set_capture)(struct soc_camera_platform_info *info, int enable); + struct soc_camera_link link; }; #endif /* __SOC_CAMERA_H__ */ -- cgit v1.2.3 From 54b9f746c2e8e1fa753c1ce6b3ac30c78d5e2005 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:06:22 +0200 Subject: soc_camera_platform: pass device pointer from soc-camera core on .add_device() From: Guennadi Liakhovetski Add a struct device pointer to struct soc_camera_platform_info and let the user (ap325rxa) pass it down to soc_camera_platform.c in its .add_device() method. Signed-off-by: Guennadi Liakhovetski Cc: Paul Mundt Acked-by: Paul Mundt Priority: low --- arch/sh/boards/board-ap325rxa.c | 2 ++ include/media/soc_camera_platform.h | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) --- linux/arch/sh/boards/board-ap325rxa.c | 2 ++ linux/include/media/soc_camera_platform.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/linux/arch/sh/boards/board-ap325rxa.c b/linux/arch/sh/boards/board-ap325rxa.c index a40dc9d00..4fe0ed3f5 100644 --- a/linux/arch/sh/boards/board-ap325rxa.c +++ b/linux/arch/sh/boards/board-ap325rxa.c @@ -342,6 +342,8 @@ static int ap325rxa_camera_add(struct soc_camera_link *icl, if (icl != &camera_info.link || camera_probe() <= 0) return -ENODEV; + camera_info.dev = dev; + return platform_device_register(&camera_device); } diff --git a/linux/include/media/soc_camera_platform.h b/linux/include/media/soc_camera_platform.h index af224dead..3e8f020ab 100644 --- a/linux/include/media/soc_camera_platform.h +++ b/linux/include/media/soc_camera_platform.h @@ -14,6 +14,8 @@ #include #include +struct device; + struct soc_camera_platform_info { int iface; char *format_name; @@ -21,6 +23,7 @@ struct soc_camera_platform_info { struct v4l2_pix_format format; unsigned long bus_param; void (*power)(int); + struct device *dev; int (*set_capture)(struct soc_camera_platform_info *info, int enable); struct soc_camera_link link; }; -- cgit v1.2.3 From 0326f126a4d2f1e2cda2c11725a7f7d7d8273f7f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:28:22 +0200 Subject: soc-camera: convert to platform device From: Guennadi Liakhovetski Convert soc-camera core and all drivers to platform device API. We already converted platforms to register a platform device for each soc-camera client, now we remove the compatibility code and switch completely to the new scheme. This is a preparatory step for the v4l2-subdev conversion. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/drivers/media/video/mt9m001.c | 114 +++--- linux/drivers/media/video/mt9m111.c | 154 ++++---- linux/drivers/media/video/mt9t031.c | 116 +++--- linux/drivers/media/video/mt9v022.c | 119 +++---- linux/drivers/media/video/mx3_camera.c | 27 +- linux/drivers/media/video/ov772x.c | 157 +++++---- linux/drivers/media/video/pxa_camera.c | 29 +- linux/drivers/media/video/sh_mobile_ceu_camera.c | 13 +- linux/drivers/media/video/soc_camera.c | 431 +++++++++++------------ linux/drivers/media/video/soc_camera_platform.c | 76 ++-- linux/drivers/media/video/tw9910.c | 110 +++--- linux/include/media/soc_camera.h | 27 +- linux/include/media/soc_camera_platform.h | 3 +- 13 files changed, 699 insertions(+), 677 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index e609d68c4..ad308da71 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -69,8 +69,6 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { }; struct mt9m001 { - struct i2c_client *client; - struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ unsigned char autoexposure; }; @@ -111,11 +109,11 @@ static int reg_clear(struct i2c_client *client, const u8 reg, static int mt9m001_init(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; - dev_dbg(icd->vdev->parent, "%s\n", __func__); + dev_dbg(&icd->dev, "%s\n", __func__); if (icl->power) { ret = icl->power(&client->dev, 1); @@ -147,8 +145,8 @@ static int mt9m001_init(struct soc_camera_device *icd) static int mt9m001_release(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); /* Disable the chip */ reg_write(client, MT9M001_OUTPUT_CONTROL, 0); @@ -161,7 +159,7 @@ static int mt9m001_release(struct soc_camera_device *icd) static int mt9m001_start_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); /* Switch to master "normal" mode */ if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0) @@ -171,7 +169,7 @@ static int mt9m001_start_capture(struct soc_camera_device *icd) static int mt9m001_stop_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); /* Stop sensor readout */ if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0) @@ -182,8 +180,7 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd) static int mt9m001_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK; /* Only one width bit may be set */ @@ -205,8 +202,7 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd, static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); /* MT9M001 has all capture_format parameters fixed */ unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | @@ -223,8 +219,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) static int mt9m001_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); int ret; const u16 hblank = 9, vblank = 25; @@ -290,12 +286,13 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd, static int mt9m001_get_chip_id(struct soc_camera_device *icd, struct v4l2_dbg_chip_ident *id) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match.addr != mt9m001->client->addr) + if (id->match.addr != client->addr) return -ENODEV; id->ident = mt9m001->model; @@ -308,7 +305,7 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd, static int mt9m001_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -328,7 +325,7 @@ static int mt9m001_get_register(struct soc_camera_device *icd, static int mt9m001_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -381,15 +378,11 @@ static const struct v4l2_queryctrl mt9m001_controls[] = { } }; -static int mt9m001_video_probe(struct soc_camera_device *); -static void mt9m001_video_remove(struct soc_camera_device *); static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *); static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *); static struct soc_camera_ops mt9m001_ops = { .owner = THIS_MODULE, - .probe = mt9m001_video_probe, - .remove = mt9m001_video_remove, .init = mt9m001_init, .release = mt9m001_release, .start_capture = mt9m001_start_capture, @@ -412,8 +405,8 @@ static struct soc_camera_ops mt9m001_ops = { static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); int data; switch (ctrl->id) { @@ -432,8 +425,8 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); const struct v4l2_queryctrl *qctrl; int data; @@ -525,11 +518,11 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro /* Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one */ -static int mt9m001_video_probe(struct soc_camera_device *icd) +static int mt9m001_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct soc_camera_link *icl = to_soc_camera_link(icd); s32 data; int ret; unsigned long flags; @@ -540,6 +533,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + return ret; + /* Enable the chip */ data = reg_write(client, MT9M001_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); @@ -547,6 +545,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) /* Read out the chip version register */ data = reg_read(client, MT9M001_CHIP_VERSION); + soc_camera_video_stop(icd); + /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ switch (data) { case 0x8411: @@ -559,10 +559,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) icd->formats = mt9m001_monochrome_formats; break; default: - ret = -ENODEV; dev_err(&icd->dev, "No MT9M001 chip detected, register read %x\n", data); - goto ei2c; + return -ENODEV; } icd->num_formats = 0; @@ -588,26 +587,16 @@ static int mt9m001_video_probe(struct soc_camera_device *icd) dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, data == 0x8431 ? "C12STM" : "C12ST"); - /* Now that we know the model, we can start video */ - ret = soc_camera_video_start(icd); - if (ret) - goto eisis; - return 0; - -eisis: -ei2c: - return ret; } static void mt9m001_video_remove(struct soc_camera_device *icd) { - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); - struct soc_camera_link *icl = mt9m001->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr, + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr, icd->dev.parent, icd->vdev); - soc_camera_video_stop(icd); if (icl->free_bus) icl->free_bus(icl); } @@ -620,11 +609,17 @@ static int mt9m001_probe(struct i2c_client *client) #endif { struct mt9m001 *mt9m001; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct soc_camera_link *icl = client->dev.platform_data; + struct soc_camera_link *icl; int ret; + if (!icd) { + dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); if (!icl) { dev_err(&client->dev, "MT9M001 driver needs platform data\n"); return -EINVAL; @@ -640,13 +635,10 @@ static int mt9m001_probe(struct i2c_client *client) if (!mt9m001) return -ENOMEM; - mt9m001->client = client; i2c_set_clientdata(client, mt9m001); /* Second stage probe - when a capture adapter is there */ - icd = &mt9m001->icd; icd->ops = &mt9m001_ops; - icd->control = &client->dev; icd->x_min = 20; icd->y_min = 12; icd->x_current = 20; @@ -656,27 +648,29 @@ static int mt9m001_probe(struct i2c_client *client) icd->height_min = 32; icd->height_max = 1024; icd->y_skip_top = 1; - icd->iface = icl->bus_id; /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9m001->autoexposure = 1; - ret = soc_camera_device_register(icd); - if (ret) - goto eisdr; - - return 0; + ret = mt9m001_video_probe(icd, client); + if (ret) { + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + kfree(mt9m001); + } -eisdr: - kfree(mt9m001); return ret; } static int mt9m001_remove(struct i2c_client *client) { struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; - soc_camera_device_unregister(&mt9m001->icd); + icd->ops = NULL; + mt9m001_video_remove(icd); + i2c_set_clientdata(client, NULL); + client->driver = NULL; kfree(mt9m001); return 0; diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 77639ae5c..5c6ab7b53 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -148,8 +148,6 @@ enum mt9m111_context { }; struct mt9m111 { - struct i2c_client *client; - struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ enum mt9m111_context context; struct v4l2_rect rect; @@ -203,7 +201,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg, ret = reg_page_map_set(client, reg); if (!ret) - ret = i2c_smbus_write_word_data(client, (reg & 0xff), + ret = i2c_smbus_write_word_data(client, reg & 0xff, swab16(data)); dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); return ret; @@ -232,7 +230,7 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg, static int mt9m111_set_context(struct soc_camera_device *icd, enum mt9m111_context ctxt) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B @@ -249,8 +247,8 @@ static int mt9m111_set_context(struct soc_camera_device *icd, static int mt9m111_setup_rect(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret, is_raw_format; int width = rect->width; int height = rect->height; @@ -294,7 +292,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd, static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); @@ -315,7 +313,8 @@ static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd) static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int val = 0; if (mt9m111->swap_rgb_red_blue) @@ -329,7 +328,8 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int val = 0; if (mt9m111->swap_rgb_red_blue) @@ -343,7 +343,8 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int val = 0; if (mt9m111->swap_yuv_cb_cr) @@ -356,9 +357,9 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) static int mt9m111_enable(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; if (icl->power) { @@ -378,9 +379,9 @@ static int mt9m111_enable(struct soc_camera_device *icd) static int mt9m111_disable(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); @@ -395,8 +396,8 @@ static int mt9m111_disable(struct soc_camera_device *icd) static int mt9m111_reset(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); @@ -424,8 +425,7 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd) static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - struct soc_camera_link *icl = mt9m111->client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8; @@ -441,7 +441,8 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) static int mt9m111_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", @@ -456,7 +457,8 @@ static int mt9m111_set_crop(struct soc_camera_device *icd, static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; switch (pixfmt) { @@ -506,7 +508,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) static int mt9m111_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = mt9m111->rect.left, @@ -544,12 +547,13 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd, static int mt9m111_get_chip_id(struct soc_camera_device *icd, struct v4l2_dbg_chip_ident *id) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match.addr != mt9m111->client->addr) + if (id->match.addr != client->addr) return -ENODEV; id->ident = mt9m111->model; @@ -562,8 +566,8 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd, static int mt9m111_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int val; - struct i2c_client *client = to_i2c_client(icd->control); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; @@ -583,7 +587,7 @@ static int mt9m111_get_register(struct soc_camera_device *icd, static int mt9m111_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; @@ -635,8 +639,6 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { } }; -static int mt9m111_video_probe(struct soc_camera_device *); -static void mt9m111_video_remove(struct soc_camera_device *); static int mt9m111_get_control(struct soc_camera_device *, struct v4l2_control *); static int mt9m111_set_control(struct soc_camera_device *, @@ -647,8 +649,6 @@ static int mt9m111_release(struct soc_camera_device *icd); static struct soc_camera_ops mt9m111_ops = { .owner = THIS_MODULE, - .probe = mt9m111_video_probe, - .remove = mt9m111_video_remove, .init = mt9m111_init, .resume = mt9m111_resume, .release = mt9m111_release, @@ -672,8 +672,8 @@ static struct soc_camera_ops mt9m111_ops = { static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; if (mt9m111->context == HIGHPOWER) { @@ -693,7 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) static int mt9m111_get_global_gain(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int data; data = reg_read(GLOBAL_GAIN); @@ -705,7 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd) static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); u16 val; if (gain > 63 * 2 * 2) @@ -724,8 +724,8 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; if (on) @@ -741,8 +741,8 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; if (on) @@ -759,8 +759,8 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) static int mt9m111_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int data; switch (ctrl->id) { @@ -803,7 +803,8 @@ static int mt9m111_get_control(struct soc_camera_device *icd, static int mt9m111_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); const struct v4l2_queryctrl *qctrl; int ret; @@ -841,7 +842,8 @@ static int mt9m111_set_control(struct soc_camera_device *icd, static int mt9m111_restore_state(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); mt9m111_set_context(icd, mt9m111->context); mt9m111_set_pixfmt(icd, mt9m111->pixfmt); @@ -856,7 +858,8 @@ static int mt9m111_restore_state(struct soc_camera_device *icd) static int mt9m111_resume(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret = 0; if (mt9m111->powered) { @@ -871,7 +874,8 @@ static int mt9m111_resume(struct soc_camera_device *icd) static int mt9m111_init(struct soc_camera_device *icd) { - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); int ret; mt9m111->context = HIGHPOWER; @@ -902,10 +906,10 @@ static int mt9m111_release(struct soc_camera_device *icd) * Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one */ -static int mt9m111_video_probe(struct soc_camera_device *icd) +static int mt9m111_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); + struct mt9m111 *mt9m111 = i2c_get_clientdata(client); s32 data; int ret; @@ -917,6 +921,11 @@ static int mt9m111_video_probe(struct soc_camera_device *icd) to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + goto evstart; + ret = mt9m111_enable(icd); if (ret) goto ei2c; @@ -945,31 +954,18 @@ static int mt9m111_video_probe(struct soc_camera_device *icd) dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data); - ret = soc_camera_video_start(icd); - if (ret) - goto eisis; - mt9m111->autoexposure = 1; mt9m111->autowhitebalance = 1; mt9m111->swap_rgb_even_odd = 1; mt9m111->swap_rgb_red_blue = 1; - return 0; -eisis: ei2c: + soc_camera_video_stop(icd); +evstart: return ret; } -static void mt9m111_video_remove(struct soc_camera_device *icd) -{ - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); - - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr, - mt9m111->icd.dev.parent, mt9m111->icd.vdev); - soc_camera_video_stop(&mt9m111->icd); -} - #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int mt9m111_probe(struct i2c_client *client) #else @@ -978,11 +974,17 @@ static int mt9m111_probe(struct i2c_client *client, #endif { struct mt9m111 *mt9m111; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct soc_camera_link *icl = client->dev.platform_data; + struct soc_camera_link *icl; int ret; + if (!icd) { + dev_err(&client->dev, "MT9M11x: missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); if (!icl) { dev_err(&client->dev, "MT9M11x driver needs platform data\n"); return -EINVAL; @@ -998,13 +1000,10 @@ static int mt9m111_probe(struct i2c_client *client, if (!mt9m111) return -ENOMEM; - mt9m111->client = client; i2c_set_clientdata(client, mt9m111); /* Second stage probe - when a capture adapter is there */ - icd = &mt9m111->icd; icd->ops = &mt9m111_ops; - icd->control = &client->dev; icd->x_min = MT9M111_MIN_DARK_COLS; icd->y_min = MT9M111_MIN_DARK_ROWS; icd->x_current = icd->x_min; @@ -1014,22 +1013,25 @@ static int mt9m111_probe(struct i2c_client *client, icd->height_min = MT9M111_MIN_DARK_COLS; icd->height_max = MT9M111_MAX_HEIGHT; icd->y_skip_top = 0; - icd->iface = icl->bus_id; - ret = soc_camera_device_register(icd); - if (ret) - goto eisdr; - return 0; + ret = mt9m111_video_probe(icd, client); + if (ret) { + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + kfree(mt9m111); + } -eisdr: - kfree(mt9m111); return ret; } static int mt9m111_remove(struct i2c_client *client) { struct mt9m111 *mt9m111 = i2c_get_clientdata(client); - soc_camera_device_unregister(&mt9m111->icd); + struct soc_camera_device *icd = client->dev.platform_data; + + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + client->driver = NULL; kfree(mt9m111); return 0; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index a57051522..b389223bc 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -68,8 +68,6 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = { }; struct mt9t031 { - struct i2c_client *client; - struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ unsigned char autoexposure; u16 xskip; @@ -138,8 +136,8 @@ static int get_shutter(struct i2c_client *client, u32 *data) static int mt9t031_init(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; if (icl->power) { @@ -166,8 +164,8 @@ static int mt9t031_init(struct soc_camera_device *icd) static int mt9t031_release(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); /* Disable the chip */ reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); @@ -180,7 +178,7 @@ static int mt9t031_release(struct soc_camera_device *icd) static int mt9t031_start_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); /* Switch to master "normal" mode */ if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0) @@ -190,7 +188,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd) static int mt9t031_stop_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); /* Stop sensor readout */ if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0) @@ -201,7 +199,7 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd) static int mt9t031_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); /* The caller should have queried our parameters, check anyway */ if (flags & ~MT9T031_BUS_PARAM) @@ -217,8 +215,7 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd, static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - struct soc_camera_link *icl = mt9t031->client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); } @@ -238,8 +235,8 @@ static void recalculate_limits(struct soc_camera_device *icd, static int mt9t031_set_params(struct soc_camera_device *icd, struct v4l2_rect *rect, u16 xskip, u16 yskip) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); int ret; u16 xbin, ybin, width, height, left, top; const u16 hblank = MT9T031_HORIZONTAL_BLANK, @@ -336,7 +333,8 @@ static int mt9t031_set_params(struct soc_camera_device *icd, static int mt9t031_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); /* CROP - no change in scaling, or in limits */ return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); @@ -345,7 +343,8 @@ static int mt9t031_set_crop(struct soc_camera_device *icd, static int mt9t031_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); int ret; u16 xskip, yskip; struct v4l2_rect rect = { @@ -395,12 +394,13 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd, static int mt9t031_get_chip_id(struct soc_camera_device *icd, struct v4l2_dbg_chip_ident *id) { - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match.addr != mt9t031->client->addr) + if (id->match.addr != client->addr) return -ENODEV; id->ident = mt9t031->model; @@ -413,7 +413,7 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd, static int mt9t031_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -432,7 +432,7 @@ static int mt9t031_get_register(struct soc_camera_device *icd, static int mt9t031_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -493,15 +493,11 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { } }; -static int mt9t031_video_probe(struct soc_camera_device *); -static void mt9t031_video_remove(struct soc_camera_device *); static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *); static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *); static struct soc_camera_ops mt9t031_ops = { .owner = THIS_MODULE, - .probe = mt9t031_video_probe, - .remove = mt9t031_video_remove, .init = mt9t031_init, .release = mt9t031_release, .start_capture = mt9t031_start_capture, @@ -524,8 +520,8 @@ static struct soc_camera_ops mt9t031_ops = { static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); int data; switch (ctrl->id) { @@ -550,8 +546,8 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); const struct v4l2_queryctrl *qctrl; int data; @@ -657,10 +653,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro /* Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one */ -static int mt9t031_video_probe(struct soc_camera_device *icd) +static int mt9t031_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); + struct mt9t031 *mt9t031 = i2c_get_clientdata(client); s32 data; int ret; @@ -670,6 +666,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + return ret; + /* Enable the chip */ data = reg_write(client, MT9T031_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); @@ -677,6 +678,8 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) /* Read out the chip version register */ data = reg_read(client, MT9T031_CHIP_VERSION); + soc_camera_video_stop(icd); + switch (data) { case 0x1621: mt9t031->model = V4L2_IDENT_MT9T031; @@ -684,33 +687,14 @@ static int mt9t031_video_probe(struct soc_camera_device *icd) icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats); break; default: - ret = -ENODEV; dev_err(&icd->dev, "No MT9T031 chip detected, register read %x\n", data); - goto ei2c; + return -ENODEV; } dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data); - /* Now that we know the model, we can start video */ - ret = soc_camera_video_start(icd); - if (ret) - goto evstart; - return 0; - -evstart: -ei2c: - return ret; -} - -static void mt9t031_video_remove(struct soc_camera_device *icd) -{ - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); - - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9t031->client->addr, - icd->dev.parent, icd->vdev); - soc_camera_video_stop(icd); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) @@ -721,11 +705,17 @@ static int mt9t031_probe(struct i2c_client *client, #endif { struct mt9t031 *mt9t031; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct soc_camera_link *icl = client->dev.platform_data; + struct soc_camera_link *icl; int ret; + if (!icd) { + dev_err(&client->dev, "MT9T031: missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); if (!icl) { dev_err(&client->dev, "MT9T031 driver needs platform data\n"); return -EINVAL; @@ -741,13 +731,10 @@ static int mt9t031_probe(struct i2c_client *client, if (!mt9t031) return -ENOMEM; - mt9t031->client = client; i2c_set_clientdata(client, mt9t031); /* Second stage probe - when a capture adapter is there */ - icd = &mt9t031->icd; icd->ops = &mt9t031_ops; - icd->control = &client->dev; icd->x_min = MT9T031_COLUMN_SKIP; icd->y_min = MT9T031_ROW_SKIP; icd->x_current = icd->x_min; @@ -757,7 +744,6 @@ static int mt9t031_probe(struct i2c_client *client, icd->height_min = MT9T031_MIN_HEIGHT; icd->height_max = MT9T031_MAX_HEIGHT; icd->y_skip_top = 0; - icd->iface = icl->bus_id; /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9t031->autoexposure = 1; @@ -765,24 +751,24 @@ static int mt9t031_probe(struct i2c_client *client, mt9t031->xskip = 1; mt9t031->yskip = 1; - ret = soc_camera_device_register(icd); - if (ret) - goto eisdr; - - return 0; + ret = mt9t031_video_probe(icd, client); + if (ret) { + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + kfree(mt9t031); + } -eisdr: - i2c_set_clientdata(client, NULL); - kfree(mt9t031); return ret; } static int mt9t031_remove(struct i2c_client *client) { struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; - soc_camera_device_unregister(&mt9t031->icd); + icd->ops = NULL; i2c_set_clientdata(client, NULL); + client->driver = NULL; kfree(mt9t031); return 0; diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 4841e6eea..204481f77 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -85,8 +85,6 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { }; struct mt9v022 { - struct i2c_client *client; - struct soc_camera_device icd; int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ u16 chip_control; }; @@ -127,9 +125,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg, static int mt9v022_init(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); int ret; if (icl->power) { @@ -173,19 +171,19 @@ static int mt9v022_init(struct soc_camera_device *icd) static int mt9v022_release(struct soc_camera_device *icd) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); if (icl->power) - icl->power(&mt9v022->client->dev, 0); + icl->power(&client->dev, 0); return 0; } static int mt9v022_start_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); /* Switch to master "normal" mode */ mt9v022->chip_control &= ~0x10; if (reg_write(client, MT9V022_CHIP_CONTROL, @@ -196,8 +194,8 @@ static int mt9v022_start_capture(struct soc_camera_device *icd) static int mt9v022_stop_capture(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); /* Switch to snapshot mode */ mt9v022->chip_control |= 0x10; if (reg_write(client, MT9V022_CHIP_CONTROL, @@ -209,9 +207,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd) static int mt9v022_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; u16 pixclk = 0; @@ -263,8 +261,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned int width_flag; if (icl->query_bus_param) @@ -283,7 +280,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) static int mt9v022_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; /* Like in example app. Contradicts the datasheet though */ @@ -326,7 +323,8 @@ static int mt9v022_set_crop(struct soc_camera_device *icd, static int mt9v022_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = icd->x_current, @@ -374,12 +372,13 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd, static int mt9v022_get_chip_id(struct soc_camera_device *icd, struct v4l2_dbg_chip_ident *id) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; - if (id->match.addr != mt9v022->client->addr) + if (id->match.addr != client->addr) return -ENODEV; id->ident = mt9v022->model; @@ -392,7 +391,7 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd, static int mt9v022_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -412,7 +411,7 @@ static int mt9v022_get_register(struct soc_camera_device *icd, static int mt9v022_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -481,15 +480,11 @@ static const struct v4l2_queryctrl mt9v022_controls[] = { } }; -static int mt9v022_video_probe(struct soc_camera_device *); -static void mt9v022_video_remove(struct soc_camera_device *); static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *); static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *); static struct soc_camera_ops mt9v022_ops = { .owner = THIS_MODULE, - .probe = mt9v022_video_probe, - .remove = mt9v022_video_remove, .init = mt9v022_init, .release = mt9v022_release, .start_capture = mt9v022_start_capture, @@ -513,7 +508,7 @@ static struct soc_camera_ops mt9v022_ops = { static int mt9v022_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int data; switch (ctrl->id) { @@ -549,7 +544,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { int data; - struct i2c_client *client = to_i2c_client(icd->control); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); const struct v4l2_queryctrl *qctrl; qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); @@ -646,11 +641,11 @@ static int mt9v022_set_control(struct soc_camera_device *icd, /* Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one */ -static int mt9v022_video_probe(struct soc_camera_device *icd) +static int mt9v022_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(icd->control); - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = client->dev.platform_data; + struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct soc_camera_link *icl = to_soc_camera_link(icd); s32 data; int ret; unsigned long flags; @@ -659,6 +654,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + return ret; + /* Read out the chip version register */ data = reg_read(client, MT9V022_CHIP_VERSION); @@ -678,6 +678,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) udelay(200); if (reg_read(client, MT9V022_RESET)) { dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); + if (ret > 0) + ret = -EIO; goto ei2c; } @@ -694,7 +696,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) } if (ret < 0) - goto eisis; + goto ei2c; icd->num_formats = 0; @@ -716,29 +718,23 @@ static int mt9v022_video_probe(struct soc_camera_device *icd) if (flags & SOCAM_DATAWIDTH_8) icd->num_formats++; - ret = soc_camera_video_start(icd); - if (ret < 0) - goto eisis; - dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? "monochrome" : "colour"); - return 0; - -eisis: ei2c: + soc_camera_video_stop(icd); + return ret; } static void mt9v022_video_remove(struct soc_camera_device *icd) { - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); - struct soc_camera_link *icl = mt9v022->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr, icd->dev.parent, icd->vdev); - soc_camera_video_stop(icd); if (icl->free_bus) icl->free_bus(icl); } @@ -751,11 +747,17 @@ static int mt9v022_probe(struct i2c_client *client) #endif { struct mt9v022 *mt9v022; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct soc_camera_link *icl = client->dev.platform_data; + struct soc_camera_link *icl; int ret; + if (!icd) { + dev_err(&client->dev, "MT9V022: missing soc-camera data!\n"); + return -EINVAL; + } + + icl = to_soc_camera_link(icd); if (!icl) { dev_err(&client->dev, "MT9V022 driver needs platform data\n"); return -EINVAL; @@ -772,12 +774,9 @@ static int mt9v022_probe(struct i2c_client *client) return -ENOMEM; mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; - mt9v022->client = client; i2c_set_clientdata(client, mt9v022); - icd = &mt9v022->icd; icd->ops = &mt9v022_ops; - icd->control = &client->dev; icd->x_min = 1; icd->y_min = 4; icd->x_current = 1; @@ -787,24 +786,26 @@ static int mt9v022_probe(struct i2c_client *client) icd->height_min = 32; icd->height_max = 480; icd->y_skip_top = 1; - icd->iface = icl->bus_id; - - ret = soc_camera_device_register(icd); - if (ret) - goto eisdr; - return 0; + ret = mt9v022_video_probe(icd, client); + if (ret) { + icd->ops = NULL; + i2c_set_clientdata(client, NULL); + kfree(mt9v022); + } -eisdr: - kfree(mt9v022); return ret; } static int mt9v022_remove(struct i2c_client *client) { struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; - soc_camera_device_unregister(&mt9v022->icd); + icd->ops = NULL; + mt9v022_video_remove(icd); + i2c_set_clientdata(client, NULL); + client->driver = NULL; kfree(mt9v022); return 0; diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index 9770cb793..2edf77a62 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -503,18 +503,19 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) mx3_camera_activate(mx3_cam, icd); ret = icd->ops->init(icd); - if (ret < 0) { - clk_disable(mx3_cam->clk); + if (ret < 0) goto einit; - } mx3_cam->icd = icd; + dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n", + icd->devnum); + + return 0; + einit: + clk_disable(mx3_cam->clk); ebusy: - if (!ret) - dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n", - icd->devnum); return ret; } @@ -947,9 +948,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); + dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", + camera_flags, bus_flags, common_flags); if (!common_flags) { - dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n", - camera_flags, bus_flags); + dev_dbg(ici->dev, "no common flags"); return -EINVAL; } @@ -1002,8 +1004,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) SOCAM_DATAWIDTH_4; ret = icd->ops->set_bus_param(icd, common_flags); - if (ret < 0) + if (ret < 0) { + dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n", + common_flags, ret); return ret; + } /* * So far only gated clock mode is supported. Add a line @@ -1127,8 +1132,9 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) INIT_LIST_HEAD(&mx3_cam->capture); spin_lock_init(&mx3_cam->lock); - base = ioremap(res->start, res->end - res->start + 1); + base = ioremap(res->start, resource_size(res)); if (!base) { + pr_err("Couldn't map %x@%x\n", resource_size(res), res->start); err = -ENOMEM; goto eioremap; } @@ -1215,3 +1221,4 @@ module_exit(mx3_camera_exit); MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME); diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 4b0363940..297a46fc9 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -399,8 +399,6 @@ struct ov772x_win_size { struct ov772x_priv { struct ov772x_camera_info *info; - struct i2c_client *client; - struct soc_camera_device icd; const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; int model; @@ -619,53 +617,56 @@ static int ov772x_reset(struct i2c_client *client) static int ov772x_init(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret = 0; - if (priv->info->link.power) { - ret = priv->info->link.power(&priv->client->dev, 1); + if (icl->power) { + ret = icl->power(&client->dev, 1); if (ret < 0) return ret; } - if (priv->info->link.reset) - ret = priv->info->link.reset(&priv->client->dev); + if (icl->reset) + ret = icl->reset(&client->dev); return ret; } static int ov772x_release(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret = 0; - if (priv->info->link.power) - ret = priv->info->link.power(&priv->client->dev, 0); + if (icl->power) + ret = icl->power(&client->dev, 0); return ret; } static int ov772x_start_capture(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); if (!priv->win || !priv->fmt) { dev_err(&icd->dev, "norm or win select error\n"); return -EPERM; } - ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0); + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); dev_dbg(&icd->dev, - "format %s, win %s\n", priv->fmt->name, priv->win->name); + "format %s, win %s\n", priv->fmt->name, priv->win->name); return 0; } static int ov772x_stop_capture(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); return 0; } @@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd, static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - struct soc_camera_link *icl = &priv->info->link; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; @@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) static int ov772x_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); switch (ctrl->id) { case V4L2_CID_VFLIP: @@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd, static int ov772x_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); int ret = 0; u8 val; @@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd, priv->flag_vflip = ctrl->value; if (priv->info->flags & OV772X_FLAG_VFLIP) val ^= VFLIP_IMG; - ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val); + ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val); break; case V4L2_CID_HFLIP: val = ctrl->value ? HFLIP_IMG : 0x00; priv->flag_hflip = ctrl->value; if (priv->info->flags & OV772X_FLAG_HFLIP) val ^= HFLIP_IMG; - ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val); + ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val); break; } @@ -730,9 +734,10 @@ static int ov772x_set_control(struct soc_camera_device *icd, } static int ov772x_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) + struct v4l2_dbg_chip_ident *id) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); id->ident = priv->model; id->revision = 0; @@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd, static int ov772x_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); - int ret; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + int ret; reg->size = 1; if (reg->reg > 0xff) return -EINVAL; - ret = i2c_smbus_read_byte_data(priv->client, reg->reg); + ret = i2c_smbus_read_byte_data(client, reg->reg); if (ret < 0) return ret; @@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd, static int ov772x_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->reg > 0xff || reg->val > 0xff) return -EINVAL; - return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); + return i2c_smbus_write_byte_data(client, reg->reg, reg->val); } #endif @@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height) return win; } -static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, - u32 pixfmt) +static int ov772x_set_params(struct soc_camera_device *icd, + u32 width, u32 height, u32 pixfmt) { + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); int ret = -EINVAL; u8 val; int i; @@ -810,6 +817,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, break; } } + dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i); if (!priv->fmt) goto ov772x_set_fmt_error; @@ -821,7 +829,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, /* * reset hardware */ - ov772x_reset(priv->client); + ov772x_reset(client); /* * Edge Ctrl @@ -835,17 +843,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, * Remove it when manual mode. */ - ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00); + ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_TRSHLD, EDGE_THRESHOLD_MASK, priv->info->edgectrl.threshold); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_STRNGT, EDGE_STRENGTH_MASK, priv->info->edgectrl.strength); if (ret < 0) @@ -857,13 +865,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, * * set upper and lower limit */ - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_UPPER, EDGE_UPPER_MASK, priv->info->edgectrl.upper); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, EDGE_LOWER, EDGE_LOWER_MASK, priv->info->edgectrl.lower); if (ret < 0) @@ -873,7 +881,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, /* * set size format */ - ret = ov772x_write_array(priv->client, priv->win->regs); + ret = ov772x_write_array(client, priv->win->regs); if (ret < 0) goto ov772x_set_fmt_error; @@ -882,7 +890,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, */ val = priv->fmt->dsp3; if (val) { - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, DSP_CTRL3, UV_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; @@ -901,7 +909,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, if (priv->flag_hflip) val ^= HFLIP_IMG; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, COM3, SWAP_MASK | IMG_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; @@ -910,7 +918,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, * set COM7 */ val = priv->win->com7_bit | priv->fmt->com7; - ret = ov772x_mask_set(priv->client, + ret = ov772x_mask_set(client, COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), val); if (ret < 0) @@ -920,7 +928,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, ov772x_set_fmt_error: - ov772x_reset(priv->client); + ov772x_reset(client); priv->win = NULL; priv->fmt = NULL; @@ -930,22 +938,22 @@ ov772x_set_fmt_error: static int ov772x_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct ov772x_priv *priv = i2c_get_clientdata(client); if (!priv->fmt) return -EINVAL; - return ov772x_set_params(priv, rect->width, rect->height, + return ov772x_set_params(icd, rect->width, rect->height, priv->fmt->fourcc); } static int ov772x_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); struct v4l2_pix_format *pix = &f->fmt.pix; - return ov772x_set_params(priv, pix->width, pix->height, + return ov772x_set_params(icd, pix->width, pix->height, pix->pixelformat); } @@ -967,11 +975,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd, return 0; } -static int ov772x_video_probe(struct soc_camera_device *icd) +static int ov772x_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); + struct ov772x_priv *priv = i2c_get_clientdata(client); u8 pid, ver; const char *devname; + int ret; /* * We must have a parent by now. And it cannot be a wrong one. @@ -993,11 +1003,16 @@ static int ov772x_video_probe(struct soc_camera_device *icd) icd->formats = ov772x_fmt_lists; icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + return ret; + /* * check and show product ID and manufacturer ID */ - pid = i2c_smbus_read_byte_data(priv->client, PID); - ver = i2c_smbus_read_byte_data(priv->client, VER); + pid = i2c_smbus_read_byte_data(client, PID); + ver = i2c_smbus_read_byte_data(client, VER); switch (VERSION(pid, ver)) { case OV7720: @@ -1011,7 +1026,8 @@ static int ov772x_video_probe(struct soc_camera_device *icd) default: dev_err(&icd->dev, "Product ID error %x:%x\n", pid, ver); - return -ENODEV; + ret = -ENODEV; + goto ever; } dev_info(&icd->dev, @@ -1019,21 +1035,17 @@ static int ov772x_video_probe(struct soc_camera_device *icd) devname, pid, ver, - i2c_smbus_read_byte_data(priv->client, MIDH), - i2c_smbus_read_byte_data(priv->client, MIDL)); - - return soc_camera_video_start(icd); -} + i2c_smbus_read_byte_data(client, MIDH), + i2c_smbus_read_byte_data(client, MIDL)); -static void ov772x_video_remove(struct soc_camera_device *icd) -{ soc_camera_video_stop(icd); + +ever: + return ret; } static struct soc_camera_ops ov772x_ops = { .owner = THIS_MODULE, - .probe = ov772x_video_probe, - .remove = ov772x_video_remove, .init = ov772x_init, .release = ov772x_release, .start_capture = ov772x_start_capture, @@ -1062,20 +1074,26 @@ static struct soc_camera_ops ov772x_ops = { static int ov772x_probe(struct i2c_client *client) #else static int ov772x_probe(struct i2c_client *client, - const struct i2c_device_id *did) + const struct i2c_device_id *did) #endif { struct ov772x_priv *priv; struct ov772x_camera_info *info; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl; int ret; - if (!client->dev.platform_data) + if (!icd) { + dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); return -EINVAL; + } - info = container_of(client->dev.platform_data, - struct ov772x_camera_info, link); + icl = to_soc_camera_link(icd); + if (!icl) + return -EINVAL; + + info = container_of(icl, struct ov772x_camera_info, link); if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&adapter->dev, @@ -1089,19 +1107,15 @@ static int ov772x_probe(struct i2c_client *client, return -ENOMEM; priv->info = info; - priv->client = client; i2c_set_clientdata(client, priv); - icd = &priv->icd; icd->ops = &ov772x_ops; - icd->control = &client->dev; icd->width_max = MAX_WIDTH; icd->height_max = MAX_HEIGHT; - icd->iface = priv->info->link.bus_id; - - ret = soc_camera_device_register(icd); + ret = ov772x_video_probe(icd, client); if (ret) { + icd->ops = NULL; i2c_set_clientdata(client, NULL); kfree(priv); } @@ -1112,8 +1126,9 @@ static int ov772x_probe(struct i2c_client *client, static int ov772x_remove(struct i2c_client *client) { struct ov772x_priv *priv = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; - soc_camera_device_unregister(&priv->icd); + icd->ops = NULL; i2c_set_clientdata(client, NULL); kfree(priv); return 0; diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 92fb8b191..8b1537581 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -842,7 +842,8 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q, sizeof(struct pxa_buffer), icd); } -static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) +static u32 mclk_get_divisor(struct platform_device *pdev, + struct pxa_camera_dev *pcdev) { unsigned long mclk = pcdev->mclk; u32 div; @@ -854,7 +855,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) /* mclk <= ciclk / 4 (27.4.2) */ if (mclk > lcdclk / 4) { mclk = lcdclk / 4; - dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk); + dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk); } /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */ @@ -864,8 +865,8 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev) if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) pcdev->mclk = lcdclk / (2 * (div + 1)); - dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, " - "divisor %u\n", lcdclk, mclk, div); + dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n", + lcdclk, mclk, div); return div; } @@ -970,15 +971,20 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) goto ebusy; } - dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", - icd->devnum); - pxa_camera_activate(pcdev); ret = icd->ops->init(icd); + if (ret < 0) + goto einit; + + pcdev->icd = icd; - if (!ret) - pcdev->icd = icd; + dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", + icd->devnum); + return 0; + +einit: + pxa_camera_deactivate(pcdev); ebusy: return ret; } @@ -1587,8 +1593,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) pcdev->mclk = 20000000; } - pcdev->soc_host.dev = &pdev->dev; - pcdev->mclk_divisor = mclk_get_divisor(pcdev); + pcdev->mclk_divisor = mclk_get_divisor(pdev, pcdev); INIT_LIST_HEAD(&pcdev->capture); spin_lock_init(&pcdev->lock); @@ -1653,6 +1658,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; pcdev->soc_host.ops = &pxa_soc_camera_host_ops; pcdev->soc_host.priv = pcdev; + pcdev->soc_host.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; err = soc_camera_host_register(&pcdev->soc_host); @@ -1734,3 +1740,4 @@ module_exit(pxa_camera_exit); MODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); MODULE_AUTHOR("Guennadi Liakhovetski "); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" PXA_CAM_DRV_NAME); diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 1bae28a98..f8e4b5481 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -358,11 +358,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) "SuperH Mobile CEU driver attached to camera %d\n", icd->devnum); + clk_enable(pcdev->clk); + ret = icd->ops->init(icd); - if (ret) + if (ret) { + clk_disable(pcdev->clk); goto err; - - clk_enable(pcdev->clk); + } ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ while (ceu_read(pcdev, CSTSR) & 1) @@ -396,10 +398,10 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) } spin_unlock_irqrestore(&pcdev->lock, flags); - clk_disable(pcdev->clk); - icd->ops->release(icd); + clk_disable(pcdev->clk); + dev_info(&icd->dev, "SuperH Mobile CEU driver detached from camera %d\n", icd->devnum); @@ -938,3 +940,4 @@ module_exit(sh_mobile_ceu_exit); MODULE_DESCRIPTION("SuperH Mobile CEU driver"); MODULE_AUTHOR("Magnus Damm"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:sh_mobile_ceu"); diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 8de620b78..f248ae27f 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -21,15 +21,15 @@ #include #include #include -#include #include +#include #include #include #include #include -#include #include +#include #include #include "compat.h" @@ -39,7 +39,7 @@ static LIST_HEAD(hosts); static LIST_HEAD(devices); -static DEFINE_MUTEX(list_lock); +static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ const struct soc_camera_data_format *soc_camera_format_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc) @@ -210,6 +210,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv, return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK); } +/* Always entered with .video_lock held */ static int soc_camera_init_user_formats(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); @@ -258,9 +259,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) return 0; } +/* Always entered with .video_lock held */ static void soc_camera_free_user_formats(struct soc_camera_device *icd) { + icd->current_fmt = NULL; vfree(icd->user_formats); + icd->user_formats = NULL; } /* Called with .vb_lock held */ @@ -311,10 +315,6 @@ static int soc_camera_open(struct file *file) struct soc_camera_file *icf; int ret; - icf = vmalloc(sizeof(*icf)); - if (!icf) - return -ENOMEM; - /* * It is safe to dereference these pointers now as long as a user has * the video device open - we are protected by the held cdev reference. @@ -322,8 +322,17 @@ static int soc_camera_open(struct file *file) vdev = video_devdata(file); icd = container_of(vdev->parent, struct soc_camera_device, dev); + + if (!icd->ops) + /* No device driver attached */ + return -ENODEV; + ici = to_soc_camera_host(icd->dev.parent); + icf = vmalloc(sizeof(*icf)); + if (!icf) + return -ENOMEM; + if (!try_module_get(icd->ops->owner)) { dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); ret = -EINVAL; @@ -336,7 +345,7 @@ static int soc_camera_open(struct file *file) goto emgi; } - /* Protect against icd->remove() until we module_get() both drivers. */ + /* Protect against icd->ops->remove() until we module_get() both drivers. */ mutex_lock(&icd->video_lock); icf->icd = icd; @@ -351,11 +360,18 @@ static int soc_camera_open(struct file *file) .width = icd->width, .height = icd->height, .field = icd->field, - .pixelformat = icd->current_fmt->fourcc, - .colorspace = icd->current_fmt->colorspace, }, }; + ret = soc_camera_init_user_formats(icd); + if (ret < 0) + goto eiufmt; + + dev_dbg(&icd->dev, "Using fmt %x\n", icd->current_fmt->fourcc); + + f.fmt.pix.pixelformat = icd->current_fmt->fourcc; + f.fmt.pix.colorspace = icd->current_fmt->colorspace; + ret = ici->ops->add(icd); if (ret < 0) { dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); @@ -384,6 +400,8 @@ static int soc_camera_open(struct file *file) esfmt: ici->ops->remove(icd); eiciadd: + soc_camera_free_user_formats(icd); +eiufmt: icd->use_count--; mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); @@ -403,8 +421,10 @@ static int soc_camera_close(struct file *file) mutex_lock(&icd->video_lock); icd->use_count--; - if (!icd->use_count) + if (!icd->use_count) { ici->ops->remove(icd); + soc_camera_free_user_formats(icd); + } mutex_unlock(&icd->video_lock); @@ -765,29 +785,6 @@ static int soc_camera_s_register(struct file *file, void *fh, } #endif -static int device_register_link(struct soc_camera_device *icd) -{ - int ret = dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum); - - if (!ret) - ret = device_register(&icd->dev); - - if (ret < 0) { - /* Prevent calling device_unregister() */ - icd->dev.parent = NULL; - dev_err(&icd->dev, "Cannot register device: %d\n", ret); - /* Even if probe() was unsuccessful for all registered drivers, - * device_register() returns 0, and we add the link, just to - * document this camera's control device */ - } else if (icd->control) - /* Have to sysfs_remove_link() before device_unregister()? */ - if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj, - "control")) - dev_warn(&icd->dev, - "Failed creating the control symlink\n"); - return ret; -} - /* So far this function cannot fail */ static void scan_add_host(struct soc_camera_host *ici) { @@ -797,106 +794,124 @@ static void scan_add_host(struct soc_camera_host *ici) list_for_each_entry(icd, &devices, list) { if (icd->iface == ici->nr) { + int ret; icd->dev.parent = ici->dev; - device_register_link(icd); + dev_set_name(&icd->dev, "%u-%u", icd->iface, + icd->devnum); + ret = device_register(&icd->dev); + if (ret < 0) { + icd->dev.parent = NULL; + dev_err(&icd->dev, + "Cannot register device: %d\n", ret); + } } } mutex_unlock(&list_lock); } -/* return: 0 if no match found or a match found and - * device_register() successful, error code otherwise */ -static int scan_add_device(struct soc_camera_device *icd) +#ifdef CONFIG_I2C_BOARDINFO +static int soc_camera_init_i2c(struct soc_camera_device *icd, + struct soc_camera_link *icl) { - struct soc_camera_host *ici; - int ret = 0; + struct i2c_client *client; + struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); + int ret; - mutex_lock(&list_lock); + if (!adap) { + ret = -ENODEV; + dev_err(&icd->dev, "Cannot get I2C adapter #%d. No driver?\n", + icl->i2c_adapter_id); + goto ei2cga; + } - list_add_tail(&icd->list, &devices); + icl->board_info->platform_data = icd; - /* Watch out for class_for_each_device / class_find_device API by - * Dave Young */ - list_for_each_entry(ici, &hosts, list) { - if (icd->iface == ici->nr) { - ret = 1; - icd->dev.parent = ici->dev; - break; - } + client = i2c_new_device(adap, icl->board_info); + if (!client) { + ret = -ENOMEM; + goto ei2cnd; } - mutex_unlock(&list_lock); - - if (ret) - ret = device_register_link(icd); + /* + * We set icd drvdata at two locations - here and in + * soc_camera_video_start(). Depending on the module loading / + * initialisation order one of these locations will be entered first + */ + /* Use to_i2c_client(dev) to recover the i2c client */ + dev_set_drvdata(&icd->dev, &client->dev); + return 0; +ei2cnd: + i2c_put_adapter(adap); +ei2cga: return ret; } +static void soc_camera_free_i2c(struct soc_camera_device *icd) +{ + struct i2c_client *client = + to_i2c_client(to_soc_camera_control(icd)); + dev_set_drvdata(&icd->dev, NULL); + i2c_unregister_device(client); + i2c_put_adapter(client->adapter); +} +#else +#define soc_camera_init_i2c(icd, icl) (-ENODEV) +#define soc_camera_free_i2c(icd) do {} while (0) +#endif + +static int video_dev_create(struct soc_camera_device *icd); +/* Called during host-driver probe */ static int soc_camera_probe(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; - /* - * Possible race scenario: - * modprobe triggers __func__ - * at this moment respective gets rmmod'ed - * to protect take module references. - */ + dev_info(dev, "Probing %s\n", dev_name(dev)); - if (!try_module_get(icd->ops->owner)) { - dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); - ret = -EINVAL; - goto emgd; - } + ret = video_dev_create(icd); + if (ret < 0) + goto evdc; - if (!try_module_get(ici->ops->owner)) { - dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); + /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */ + if (icl->board_info) { + ret = soc_camera_init_i2c(icd, icl); + if (ret < 0) + goto eadddev; + } else if (!icl->add_device || !icl->del_device) { ret = -EINVAL; - goto emgi; + goto eadddev; + } else { + ret = icl->add_device(icl, &icd->dev); + if (ret < 0) + goto eadddev; } - mutex_lock(&icd->video_lock); - - /* We only call ->add() here to activate and probe the camera. - * We shall ->remove() and deactivate it immediately afterwards. */ - ret = ici->ops->add(icd); - if (ret < 0) - goto eiadd; - - ret = icd->ops->probe(icd); - if (ret >= 0) { - const struct v4l2_queryctrl *qctrl; + ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, icd->vdev->minor); + if (ret < 0) { + dev_err(&icd->dev, "video_register_device failed: %d\n", ret); + goto evidregd; + } - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); - icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = qctrl ? qctrl->default_value : - (unsigned short)~0; + /* Do we have to sysfs_remove_link() before device_unregister()? */ + if (to_soc_camera_control(icd) && + sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj, + "control")) + dev_warn(&icd->dev, "Failed creating the control symlink\n"); - ret = soc_camera_init_user_formats(icd); - if (ret < 0) { - if (icd->ops->remove) - icd->ops->remove(icd); - goto eiufmt; - } - icd->height = DEFAULT_HEIGHT; - icd->width = DEFAULT_WIDTH; - icd->field = V4L2_FIELD_ANY; - } + return 0; -eiufmt: - ici->ops->remove(icd); -eiadd: - mutex_unlock(&icd->video_lock); - module_put(ici->ops->owner); -emgi: - module_put(icd->ops->owner); -emgd: +evidregd: + if (icl->board_info) + soc_camera_free_i2c(icd); + else + icl->del_device(icl); +eadddev: + video_device_release(icd->vdev); +evdc: return ret; } @@ -905,13 +920,22 @@ emgd: static int soc_camera_remove(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); + struct soc_camera_link *icl = to_soc_camera_link(icd); + struct video_device *vdev = icd->vdev; - mutex_lock(&icd->video_lock); - if (icd->ops->remove) - icd->ops->remove(icd); - mutex_unlock(&icd->video_lock); + BUG_ON(!dev->parent); - soc_camera_free_user_formats(icd); + if (vdev) { + mutex_lock(&icd->video_lock); + video_unregister_device(vdev); + icd->vdev = NULL; + mutex_unlock(&icd->video_lock); + } + + if (icl->board_info) + soc_camera_free_i2c(icd); + else + icl->del_device(icl); return 0; } @@ -1006,10 +1030,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) list_for_each_entry(icd, &devices, list) { if (icd->dev.parent == ici->dev) { + /* The bus->remove will be called */ device_unregister(&icd->dev); /* Not before device_unregister(), .remove * needs parent to call ici->ops->remove() */ icd->dev.parent = NULL; + + /* If the host module is loaded again, device_register() + * would complain "already initialised" */ memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); } } @@ -1021,26 +1049,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) EXPORT_SYMBOL(soc_camera_host_unregister); /* Image capture device */ -int soc_camera_device_register(struct soc_camera_device *icd) +static int soc_camera_device_register(struct soc_camera_device *icd) { struct soc_camera_device *ix; int num = -1, i; - if (!icd || !icd->ops || - !icd->ops->probe || - !icd->ops->init || - !icd->ops->release || - !icd->ops->start_capture || - !icd->ops->stop_capture || - !icd->ops->set_crop || - !icd->ops->set_fmt || - !icd->ops->try_fmt || - !icd->ops->query_bus_param || - !icd->ops->set_bus_param) - return -EINVAL; - for (i = 0; i < 256 && num < 0; i++) { num = i; + /* Check if this index is available on this interface */ list_for_each_entry(ix, &devices, list) { if (ix->iface == icd->iface && ix->devnum == i) { num = -1; @@ -1062,21 +1078,15 @@ int soc_camera_device_register(struct soc_camera_device *icd) icd->host_priv = NULL; mutex_init(&icd->video_lock); - return scan_add_device(icd); + list_add_tail(&icd->list, &devices); + + return 0; } -EXPORT_SYMBOL(soc_camera_device_register); -void soc_camera_device_unregister(struct soc_camera_device *icd) +static void soc_camera_device_unregister(struct soc_camera_device *icd) { - mutex_lock(&list_lock); list_del(&icd->list); - - /* The bus->remove will be eventually called */ - if (icd->dev.parent) - device_unregister(&icd->dev); - mutex_unlock(&list_lock); } -EXPORT_SYMBOL(soc_camera_device_unregister); static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { .vidioc_querycap = soc_camera_querycap, @@ -1107,22 +1117,13 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { #endif }; -/* - * Usually called from the struct soc_camera_ops .probe() method, i.e., from - * soc_camera_probe() above with .video_lock held - */ -int soc_camera_video_start(struct soc_camera_device *icd) +static int video_dev_create(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - int err = -ENOMEM; - struct video_device *vdev; + struct video_device *vdev = video_device_alloc(); - if (!icd->dev.parent) - return -ENODEV; - - vdev = video_device_alloc(); if (!vdev) - goto evidallocd; + return -ENOMEM; dev_dbg(ici->dev, "Allocated video_device %p\n", vdev); strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); @@ -1133,118 +1134,110 @@ int soc_camera_video_start(struct soc_camera_device *icd) vdev->ioctl_ops = &soc_camera_ioctl_ops; vdev->release = video_device_release; vdev->minor = -1; - vdev->tvnorms = V4L2_STD_UNKNOWN, + vdev->tvnorms = V4L2_STD_UNKNOWN; - err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor); - if (err < 0) { - dev_err(vdev->parent, "video_register_device failed\n"); - goto evidregd; - } icd->vdev = vdev; return 0; +} -evidregd: - video_device_release(vdev); -evidallocd: - return err; +/* + * Usually called from the struct soc_camera_ops .probe() method, i.e., from + * soc_camera_probe() above with .video_lock held + */ +int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + const struct v4l2_queryctrl *qctrl; + + if (!icd->dev.parent) + return -ENODEV; + + if (!icd->ops || + !icd->ops->init || + !icd->ops->release || + !icd->ops->start_capture || + !icd->ops->stop_capture || + !icd->ops->set_fmt || + !icd->ops->try_fmt || + !icd->ops->query_bus_param || + !icd->ops->set_bus_param) + return -EINVAL; + + /* See comment in soc_camera_probe() */ + dev_set_drvdata(&icd->dev, dev); + + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); + icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); + icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; + + return ici->ops->add(icd); } EXPORT_SYMBOL(soc_camera_video_start); /* Called from client .remove() methods with .video_lock held */ void soc_camera_video_stop(struct soc_camera_device *icd) { - struct video_device *vdev = icd->vdev; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); dev_dbg(&icd->dev, "%s\n", __func__); - if (!icd->dev.parent || !vdev) - return; - - video_unregister_device(vdev); - icd->vdev = NULL; + ici->ops->remove(icd); } EXPORT_SYMBOL(soc_camera_video_stop); -#ifdef CONFIG_I2C_BOARDINFO -static int soc_camera_init_i2c(struct platform_device *pdev, - struct soc_camera_link *icl) +static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) { - struct i2c_client *client; - struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); + struct soc_camera_link *icl = pdev->dev.platform_data; + struct soc_camera_device *icd; int ret; - if (!adap) { - ret = -ENODEV; - dev_err(&pdev->dev, "Cannot get adapter #%d. No driver?\n", - icl->i2c_adapter_id); - goto ei2cga; - } + if (!icl) + return -EINVAL; - icl->board_info->platform_data = icl; - client = i2c_new_device(adap, icl->board_info); - if (!client) { - ret = -ENOMEM; - goto ei2cnd; - } + icd = kzalloc(sizeof(*icd), GFP_KERNEL); + if (!icd) + return -ENOMEM; - platform_set_drvdata(pdev, client); + icd->iface = icl->bus_id; + platform_set_drvdata(pdev, icd); + icd->dev.platform_data = icl; - return 0; -ei2cnd: - i2c_put_adapter(adap); -ei2cga: - return ret; -} + ret = soc_camera_device_register(icd); + if (ret < 0) + goto escdevreg; -static void soc_camera_free_i2c(struct platform_device *pdev) -{ - struct i2c_client *client = platform_get_drvdata(pdev); + return 0; - if (!client) - return; +escdevreg: + kfree(icd); - i2c_unregister_device(client); - i2c_put_adapter(client->adapter); + return ret; } -#else -#define soc_camera_init_i2c(d, icl) (-ENODEV) -#define soc_camera_free_i2c(d) do {} while (0) -#endif -static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) +/* Only called on rmmod for each platform device, since they are not + * hot-pluggable. Now we know, that all our users - hosts and devices have + * been unloaded already */ +static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) { - struct soc_camera_link *icl = pdev->dev.platform_data; + struct soc_camera_device *icd = platform_get_drvdata(pdev); - if (!icl) + if (!icd) return -EINVAL; - if (icl->board_info) - return soc_camera_init_i2c(pdev, icl); - else if (!icl->add_device || !icl->del_device) - return -EINVAL; + soc_camera_device_unregister(icd); - /* &pdev->dev will become &icd->dev */ - return icl->add_device(icl, &pdev->dev); -} + kfree(icd); -static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) -{ - struct soc_camera_link *icl = pdev->dev.platform_data; - - if (icl->board_info) - soc_camera_free_i2c(pdev); - else - icl->del_device(icl); return 0; } static struct platform_driver __refdata soc_camera_pdrv = { - .probe = soc_camera_pdrv_probe, - .remove = __devexit_p(soc_camera_pdrv_remove), - .driver = { - .name = "soc-camera-pdrv", - .owner = THIS_MODULE, + .remove = __devexit_p(soc_camera_pdrv_remove), + .driver = { + .name = "soc-camera-pdrv", + .owner = THIS_MODULE, }, }; @@ -1257,7 +1250,7 @@ static int __init soc_camera_init(void) if (ret) goto edrvr; - ret = platform_driver_register(&soc_camera_pdrv); + ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe); if (ret) goto epdr; diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index c48676356..d84c134f8 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -21,35 +21,32 @@ #include struct soc_camera_platform_priv { - struct soc_camera_platform_info *info; - struct soc_camera_device icd; struct soc_camera_data_format format; }; static struct soc_camera_platform_info * soc_camera_platform_get_info(struct soc_camera_device *icd) { - struct soc_camera_platform_priv *priv; - priv = container_of(icd, struct soc_camera_platform_priv, icd); - return priv->info; + struct platform_device *pdev = to_platform_device(dev_get_drvdata(&icd->dev)); + return pdev->dev.platform_data; } static int soc_camera_platform_init(struct soc_camera_device *icd) { - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); + struct soc_camera_link *icl = to_soc_camera_link(icd); - if (p->power) - p->power(1); + if (icl->power) + icl->power(dev_get_drvdata(&icd->dev), 1); return 0; } static int soc_camera_platform_release(struct soc_camera_device *icd) { - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); + struct soc_camera_link *icl = to_soc_camera_link(icd); - if (p->power) - p->power(0); + if (icl->power) + icl->power(dev_get_drvdata(&icd->dev), 0); return 0; } @@ -102,31 +99,29 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd, return 0; } -static int soc_camera_platform_video_probe(struct soc_camera_device *icd) +static int soc_camera_platform_video_probe(struct soc_camera_device *icd, + struct platform_device *pdev) { - struct soc_camera_platform_priv *priv; - priv = container_of(icd, struct soc_camera_platform_priv, icd); + struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); + struct soc_camera_platform_info *p = pdev->dev.platform_data; + int ret; - priv->format.name = priv->info->format_name; - priv->format.depth = priv->info->format_depth; - priv->format.fourcc = priv->info->format.pixelformat; - priv->format.colorspace = priv->info->format.colorspace; + priv->format.name = p->format_name; + priv->format.depth = p->format_depth; + priv->format.fourcc = p->format.pixelformat; + priv->format.colorspace = p->format.colorspace; icd->formats = &priv->format; icd->num_formats = 1; - return soc_camera_video_start(icd); -} - -static void soc_camera_platform_video_remove(struct soc_camera_device *icd) -{ + /* ..._video_start() does dev_set_drvdata(&icd->dev, &pdev->dev) */ + ret = soc_camera_video_start(icd, &pdev->dev); soc_camera_video_stop(icd); + return ret; } static struct soc_camera_ops soc_camera_platform_ops = { .owner = THIS_MODULE, - .probe = soc_camera_platform_video_probe, - .remove = soc_camera_platform_video_remove, .init = soc_camera_platform_init, .release = soc_camera_platform_release, .start_capture = soc_camera_platform_start_capture, @@ -141,11 +136,10 @@ static struct soc_camera_ops soc_camera_platform_ops = { static int soc_camera_platform_probe(struct platform_device *pdev) { struct soc_camera_platform_priv *priv; - struct soc_camera_platform_info *p; + struct soc_camera_platform_info *p = pdev->dev.platform_data; struct soc_camera_device *icd; int ret; - p = pdev->dev.platform_data; if (!p) return -EINVAL; @@ -153,31 +147,40 @@ static int soc_camera_platform_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - priv->info = p; platform_set_drvdata(pdev, priv); - icd = &priv->icd; + icd = to_soc_camera_dev(p->dev); + if (!icd) + goto enoicd; + icd->ops = &soc_camera_platform_ops; - icd->control = &pdev->dev; + dev_set_drvdata(&icd->dev, &pdev->dev); icd->width_min = 0; - icd->width_max = priv->info->format.width; + icd->width_max = p->format.width; icd->height_min = 0; - icd->height_max = priv->info->format.height; + icd->height_max = p->format.height; icd->y_skip_top = 0; - icd->iface = priv->info->iface; - ret = soc_camera_device_register(icd); - if (ret) + ret = soc_camera_platform_video_probe(icd, pdev); + if (ret) { + icd->ops = NULL; kfree(priv); + } return ret; + +enoicd: + kfree(priv); + return -EINVAL; } static int soc_camera_platform_remove(struct platform_device *pdev) { struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); + struct soc_camera_platform_info *p = pdev->dev.platform_data; + struct soc_camera_device *icd = to_soc_camera_dev(p->dev); - soc_camera_device_unregister(&priv->icd); + icd->ops = NULL; kfree(priv); return 0; } @@ -206,3 +209,4 @@ module_exit(soc_camera_platform_module_exit); MODULE_DESCRIPTION("SoC Camera Platform driver"); MODULE_AUTHOR("Magnus Damm"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:soc_camera_platform"); diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index f75787594..432dd3edc 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -224,8 +224,6 @@ struct tw9910_hsync_ctrl { struct tw9910_priv { struct tw9910_video_info *info; - struct i2c_client *client; - struct soc_camera_device icd; const struct tw9910_scale_ctrl *scale; }; @@ -511,35 +509,38 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height) */ static int tw9910_init(struct soc_camera_device *icd) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret = 0; - if (priv->info->link.power) { - ret = priv->info->link.power(&priv->client->dev, 1); + if (icl->power) { + ret = icl->power(&client->dev, 1); if (ret < 0) return ret; } - if (priv->info->link.reset) - ret = priv->info->link.reset(&priv->client->dev); + if (icl->reset) + ret = icl->reset(&client->dev); return ret; } static int tw9910_release(struct soc_camera_device *icd) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_link *icl = to_soc_camera_link(icd); int ret = 0; - if (priv->info->link.power) - ret = priv->info->link.power(&priv->client->dev, 0); + if (icl->power) + ret = icl->power(&client->dev, 0); return ret; } static int tw9910_start_capture(struct soc_camera_device *icd) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct tw9910_priv *priv = i2c_get_clientdata(client); if (!priv->scale) { dev_err(&icd->dev, "norm select error\n"); @@ -567,8 +568,9 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd, static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); - struct soc_camera_link *icl = priv->client->dev.platform_data; + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct tw9910_priv *priv = i2c_get_clientdata(client); + struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; @@ -610,13 +612,13 @@ static int tw9910_enum_input(struct soc_camera_device *icd, static int tw9910_get_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; if (reg->reg > 0xff) return -EINVAL; - ret = i2c_smbus_read_byte_data(priv->client, reg->reg); + ret = i2c_smbus_read_byte_data(client, reg->reg); if (ret < 0) return ret; @@ -631,20 +633,21 @@ static int tw9910_get_register(struct soc_camera_device *icd, static int tw9910_set_register(struct soc_camera_device *icd, struct v4l2_dbg_register *reg) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); if (reg->reg > 0xff || reg->val > 0xff) return -EINVAL; - return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); + return i2c_smbus_write_byte_data(client, reg->reg, reg->val); } #endif static int tw9910_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct tw9910_priv *priv = i2c_get_clientdata(client); int ret = -EINVAL; u8 val; @@ -658,8 +661,8 @@ static int tw9910_set_crop(struct soc_camera_device *icd, /* * reset hardware */ - tw9910_reset(priv->client); - ret = tw9910_write_array(priv->client, tw9910_default_regs); + tw9910_reset(client); + ret = tw9910_write_array(client, tw9910_default_regs); if (ret < 0) goto tw9910_set_fmt_error; @@ -670,7 +673,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd, if (SOCAM_DATAWIDTH_16 == priv->info->buswidth) val = LEN; - ret = tw9910_mask_set(priv->client, OPFORM, LEN, val); + ret = tw9910_mask_set(client, OPFORM, LEN, val); if (ret < 0) goto tw9910_set_fmt_error; @@ -698,28 +701,28 @@ static int tw9910_set_crop(struct soc_camera_device *icd, val = 0; } - ret = tw9910_mask_set(priv->client, VBICNTL, RTSEL_MASK, val); + ret = tw9910_mask_set(client, VBICNTL, RTSEL_MASK, val); if (ret < 0) goto tw9910_set_fmt_error; /* * set scale */ - ret = tw9910_set_scale(priv->client, priv->scale); + ret = tw9910_set_scale(client, priv->scale); if (ret < 0) goto tw9910_set_fmt_error; /* * set cropping */ - ret = tw9910_set_cropping(priv->client, &tw9910_cropping_ctrl); + ret = tw9910_set_cropping(client, &tw9910_cropping_ctrl); if (ret < 0) goto tw9910_set_fmt_error; /* * set hsync */ - ret = tw9910_set_hsync(priv->client, &tw9910_hsync_ctrl); + ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl); if (ret < 0) goto tw9910_set_fmt_error; @@ -727,7 +730,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd, tw9910_set_fmt_error: - tw9910_reset(priv->client); + tw9910_reset(client); priv->scale = NULL; return ret; @@ -784,9 +787,10 @@ static int tw9910_try_fmt(struct soc_camera_device *icd, return 0; } -static int tw9910_video_probe(struct soc_camera_device *icd) +static int tw9910_video_probe(struct soc_camera_device *icd, + struct i2c_client *client) { - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd); + struct tw9910_priv *priv = i2c_get_clientdata(client); s32 val; int ret; @@ -810,10 +814,18 @@ static int tw9910_video_probe(struct soc_camera_device *icd) icd->formats = tw9910_color_fmt; icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); + /* Switch master clock on */ + ret = soc_camera_video_start(icd, &client->dev); + if (ret) + return ret; + /* * check and show Product ID */ - val = i2c_smbus_read_byte_data(priv->client, ID); + val = i2c_smbus_read_byte_data(client, ID); + + soc_camera_video_stop(icd); + if (0x0B != GET_ID(val) || 0x00 != GET_ReV(val)) { dev_err(&icd->dev, @@ -824,25 +836,14 @@ static int tw9910_video_probe(struct soc_camera_device *icd) dev_info(&icd->dev, "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val)); - ret = soc_camera_video_start(icd); - if (ret < 0) - return ret; - icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; icd->vdev->current_norm = V4L2_STD_NTSC; return ret; } -static void tw9910_video_remove(struct soc_camera_device *icd) -{ - soc_camera_video_stop(icd); -} - static struct soc_camera_ops tw9910_ops = { .owner = THIS_MODULE, - .probe = tw9910_video_probe, - .remove = tw9910_video_remove, .init = tw9910_init, .release = tw9910_release, .start_capture = tw9910_start_capture, @@ -875,18 +876,25 @@ static int tw9910_probe(struct i2c_client *client, { struct tw9910_priv *priv; struct tw9910_video_info *info; - struct soc_camera_device *icd; + struct soc_camera_device *icd = client->dev.platform_data; + struct i2c_adapter *adapter = + to_i2c_adapter(client->dev.parent); + struct soc_camera_link *icl; const struct tw9910_scale_ctrl *scale; int i, ret; - if (!client->dev.platform_data) + if (!icd) { + dev_err(&client->dev, "TW9910: missing soc-camera data!\n"); return -EINVAL; + } - info = container_of(client->dev.platform_data, - struct tw9910_video_info, link); + icl = to_soc_camera_link(icd); + if (!icl) + return -EINVAL; - if (!i2c_check_functionality(to_i2c_adapter(client->dev.parent), - I2C_FUNC_SMBUS_BYTE_DATA)) { + info = container_of(icl, struct tw9910_video_info, link); + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { dev_err(&client->dev, "I2C-Adapter doesn't support " "I2C_FUNC_SMBUS_BYTE_DATA\n"); @@ -898,12 +906,9 @@ static int tw9910_probe(struct i2c_client *client, return -ENOMEM; priv->info = info; - priv->client = client; i2c_set_clientdata(client, priv); - icd = &priv->icd; icd->ops = &tw9910_ops; - icd->control = &client->dev; icd->iface = info->link.bus_id; /* @@ -929,9 +934,9 @@ static int tw9910_probe(struct i2c_client *client, icd->height_min = min(scale[i].height, icd->height_min); } - ret = soc_camera_device_register(icd); - + ret = tw9910_video_probe(icd, client); if (ret) { + icd->ops = NULL; i2c_set_clientdata(client, NULL); kfree(priv); } @@ -942,8 +947,9 @@ static int tw9910_probe(struct i2c_client *client, static int tw9910_remove(struct i2c_client *client) { struct tw9910_priv *priv = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; - soc_camera_device_unregister(&priv->icd); + icd->ops = NULL; i2c_set_clientdata(client, NULL); kfree(priv); return 0; diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 813e12061..d8b425612 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -20,7 +20,6 @@ struct soc_camera_device { struct list_head list; struct device dev; - struct device *control; unsigned short width; /* Current window */ unsigned short height; /* sizes */ unsigned short x_min; /* Camera capabilities */ @@ -131,17 +130,25 @@ static inline struct soc_camera_host *to_soc_camera_host(struct device *dev) return dev_get_drvdata(dev); } -extern int soc_camera_host_register(struct soc_camera_host *ici); -extern void soc_camera_host_unregister(struct soc_camera_host *ici); -extern int soc_camera_device_register(struct soc_camera_device *icd); -extern void soc_camera_device_unregister(struct soc_camera_device *icd); +static inline struct soc_camera_link *to_soc_camera_link(struct soc_camera_device *icd) +{ + return icd->dev.platform_data; +} -extern int soc_camera_video_start(struct soc_camera_device *icd); -extern void soc_camera_video_stop(struct soc_camera_device *icd); +static inline struct device *to_soc_camera_control(struct soc_camera_device *icd) +{ + return dev_get_drvdata(&icd->dev); +} -extern const struct soc_camera_data_format *soc_camera_format_by_fourcc( +int soc_camera_host_register(struct soc_camera_host *ici); +void soc_camera_host_unregister(struct soc_camera_host *ici); + +int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev); +void soc_camera_video_stop(struct soc_camera_device *icd); + +const struct soc_camera_data_format *soc_camera_format_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc); -extern const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( +const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc); struct soc_camera_data_format { @@ -170,8 +177,6 @@ struct soc_camera_format_xlate { struct soc_camera_ops { struct module *owner; - int (*probe)(struct soc_camera_device *); - void (*remove)(struct soc_camera_device *); int (*suspend)(struct soc_camera_device *, pm_message_t state); int (*resume)(struct soc_camera_device *); int (*init)(struct soc_camera_device *); diff --git a/linux/include/media/soc_camera_platform.h b/linux/include/media/soc_camera_platform.h index 3e8f020ab..b144f947f 100644 --- a/linux/include/media/soc_camera_platform.h +++ b/linux/include/media/soc_camera_platform.h @@ -18,11 +18,10 @@ struct device; struct soc_camera_platform_info { int iface; - char *format_name; + const char *format_name; unsigned long format_depth; struct v4l2_pix_format format; unsigned long bus_param; - void (*power)(int); struct device *dev; int (*set_capture)(struct soc_camera_platform_info *info, int enable); struct soc_camera_link link; -- cgit v1.2.3 From 2aeb5cc72300a33143580c17b6340a2bd7fc04cb Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:34:17 +0200 Subject: sh: soc-camera updates From: Guennadi Liakhovetski Update ap325rxa to specify .bus_id in struct soc_camera_link explicitly, remove unused .iface from struct soc_camera_platform_info. Signed-off-by: Guennadi Liakhovetski Cc: Paul Mundt Acked-by: Paul Mundt Priority: low --- arch/sh/boards/board-ap325rxa.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) --- linux/arch/sh/boards/board-ap325rxa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/arch/sh/boards/board-ap325rxa.c b/linux/arch/sh/boards/board-ap325rxa.c index 4fe0ed3f5..2a5dded5c 100644 --- a/linux/arch/sh/boards/board-ap325rxa.c +++ b/linux/arch/sh/boards/board-ap325rxa.c @@ -311,7 +311,6 @@ static int ap325rxa_camera_add(struct soc_camera_link *icl, struct device *dev); static void ap325rxa_camera_del(struct soc_camera_link *icl); static struct soc_camera_platform_info camera_info = { - .iface = 0, .format_name = "UYVY", .format_depth = 16, .format = { @@ -324,6 +323,7 @@ static struct soc_camera_platform_info camera_info = { SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8, .set_capture = camera_set_capture, .link = { + .bus_id = 0, .add_device = ap325rxa_camera_add, .del_device = ap325rxa_camera_del, }, @@ -424,6 +424,7 @@ static struct ov772x_camera_info ov7725_info = { .flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP, .edgectrl = OV772X_AUTO_EDGECTRL(0xf, 0), .link = { + .bus_id = 0, .power = ov7725_power, .board_info = &ap325rxa_i2c_camera[0], .i2c_adapter_id = 0, -- cgit v1.2.3 From f4d433778a3e919ae0496e7b680e15beb009f1f0 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:34:17 +0200 Subject: soc-camera: remove unused .iface from struct soc_camera_platform_info From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- include/media/soc_camera_platform.h | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) --- linux/include/media/soc_camera_platform.h | 1 - 1 file changed, 1 deletion(-) diff --git a/linux/include/media/soc_camera_platform.h b/linux/include/media/soc_camera_platform.h index b144f947f..bb70401b8 100644 --- a/linux/include/media/soc_camera_platform.h +++ b/linux/include/media/soc_camera_platform.h @@ -17,7 +17,6 @@ struct device; struct soc_camera_platform_info { - int iface; const char *format_name; unsigned long format_depth; struct v4l2_pix_format format; -- cgit v1.2.3 From 6da682d61e1e10ecacc24682f5ee009b48c3e1f3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:34:18 +0200 Subject: sh: prepare board-ap325rxa.c for v4l2-subdev conversion From: Guennadi Liakhovetski We will be registering and unregistering the soc_camera_platform platform device multiple times, therefore we need a .release() method and have to nullify the kobj. Signed-off-by: Guennadi Liakhovetski Cc: Paul Mundt Acked-by: Paul Mundt Priority: low --- arch/sh/boards/board-ap325rxa.c | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) --- linux/arch/sh/boards/board-ap325rxa.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/linux/arch/sh/boards/board-ap325rxa.c b/linux/arch/sh/boards/board-ap325rxa.c index 2a5dded5c..62cec8772 100644 --- a/linux/arch/sh/boards/board-ap325rxa.c +++ b/linux/arch/sh/boards/board-ap325rxa.c @@ -326,13 +326,19 @@ static struct soc_camera_platform_info camera_info = { .bus_id = 0, .add_device = ap325rxa_camera_add, .del_device = ap325rxa_camera_del, + .module_name = "soc_camera_platform", }, }; +static void dummy_release(struct device *dev) +{ +} + static struct platform_device camera_device = { .name = "soc_camera_platform", .dev = { .platform_data = &camera_info, + .release = dummy_release, }, }; @@ -349,8 +355,11 @@ static int ap325rxa_camera_add(struct soc_camera_link *icl, static void ap325rxa_camera_del(struct soc_camera_link *icl) { - if (icl == &camera_info.link) - platform_device_unregister(&camera_device); + if (icl != &camera_info.link) + return; + + platform_device_unregister(&camera_device); + memset(&migor_camera_device.dev.kobj, 0, sizeof(migor_camera_device.dev.kobj)); } #endif /* CONFIG_I2C */ -- cgit v1.2.3 From a9c698e163df3064b2a003395d6115985d8a4f78 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:43:33 +0200 Subject: soc-camera: (partially) convert to v4l2-(sub)dev API From: Guennadi Liakhovetski Convert the soc-camera framework to use the v4l2-(sub)dev API. Start using v4l2-subdev operations. Only a part of the interface between the soc_camera core, soc_camera host drivers on one side and soc_camera device drivers on the other side is replaced so far. The rest of the interface will be replaced in incremental steps, and will require extensions and, possibly, modifications to the v4l2-subdev code. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/drivers/media/video/mt9m001.c | 157 +++++------- linux/drivers/media/video/mt9m111.c | 309 ++++++++++------------- linux/drivers/media/video/mt9t031.c | 173 ++++++------- linux/drivers/media/video/mt9v022.c | 167 +++++------- linux/drivers/media/video/mx1_camera.c | 31 +-- linux/drivers/media/video/mx3_camera.c | 54 ++-- linux/drivers/media/video/ov772x.c | 169 +++++-------- linux/drivers/media/video/pxa_camera.c | 107 ++++---- linux/drivers/media/video/sh_mobile_ceu_camera.c | 45 ++-- linux/drivers/media/video/soc_camera.c | 250 ++++++++++-------- linux/drivers/media/video/soc_camera_platform.c | 115 ++++----- linux/drivers/media/video/tw9910.c | 151 +++++------ linux/include/media/soc_camera.h | 23 +- 13 files changed, 789 insertions(+), 962 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index ad308da71..45d8fad25 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -13,13 +13,13 @@ #include #include -#include +#include #include #include /* mt9m001 i2c address 0x5d - * The platform has to define i2c_board_info - * and call i2c_register_board_info() */ + * The platform has to define ctruct i2c_board_info objects and link to them + * from struct soc_camera_link */ /* mt9m001 selected register addresses */ #define MT9M001_CHIP_VERSION 0x00 @@ -69,10 +69,16 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { }; struct mt9m001 { + struct v4l2_subdev subdev; int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ unsigned char autoexposure; }; +static struct mt9m001 *to_mt9m001(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct mt9m001, subdev); +} + static int reg_read(struct i2c_client *client, const u8 reg) { s32 data = i2c_smbus_read_word_data(client, reg); @@ -110,32 +116,18 @@ static int reg_clear(struct i2c_client *client, const u8 reg, static int mt9m001_init(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; dev_dbg(&icd->dev, "%s\n", __func__); - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) { - dev_err(icd->vdev->parent, - "Platform failed to power-on the camera.\n"); - return ret; - } - } - - /* The camera could have been already on, we reset it additionally */ - if (icl->reset) - ret = icl->reset(&client->dev); - else - ret = -ENODEV; + /* + * We don't know, whether platform provides reset, + * issue a soft reset too + */ + ret = reg_write(client, MT9M001_RESET, 1); + if (!ret) + ret = reg_write(client, MT9M001_RESET, 0); - if (ret < 0) { - /* Either no platform reset, or platform reset failed */ - ret = reg_write(client, MT9M001_RESET, 1); - if (!ret) - ret = reg_write(client, MT9M001_RESET, 0); - } /* Disable chip, synchronous option update */ if (!ret) ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0); @@ -146,33 +138,19 @@ static int mt9m001_init(struct soc_camera_device *icd) static int mt9m001_release(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); /* Disable the chip */ reg_write(client, MT9M001_OUTPUT_CONTROL, 0); - if (icl->power) - icl->power(&client->dev, 0); - return 0; } -static int mt9m001_start_capture(struct soc_camera_device *icd) +static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; - /* Switch to master "normal" mode */ - if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0) - return -EIO; - return 0; -} - -static int mt9m001_stop_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - /* Stop sensor readout */ - if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0) + /* Switch to master "normal" mode or stop sensor readout */ + if (reg_write(client, MT9M001_OUTPUT_CONTROL, enable ? 2 : 0) < 0) return -EIO; return 0; } @@ -220,7 +198,7 @@ static int mt9m001_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct mt9m001 *mt9m001 = to_mt9m001(client); int ret; const u16 hblank = 9, vblank = 25; @@ -257,9 +235,10 @@ static int mt9m001_set_crop(struct soc_camera_device *icd, return ret; } -static int mt9m001_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_rect rect = { .left = icd->x_current, .top = icd->y_current, @@ -271,9 +250,10 @@ static int mt9m001_set_fmt(struct soc_camera_device *icd, return mt9m001_set_crop(icd, &rect); } -static int mt9m001_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; v4l_bound_align_image(&pix->width, 48, 1280, 1, @@ -283,11 +263,11 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd, return 0; } -static int mt9m001_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int mt9m001_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; @@ -302,10 +282,10 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int mt9m001_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9m001_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -322,10 +302,10 @@ static int mt9m001_get_register(struct soc_camera_device *icd, return 0; } -static int mt9m001_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9m001_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -378,35 +358,20 @@ static const struct v4l2_queryctrl mt9m001_controls[] = { } }; -static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *); -static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *); - static struct soc_camera_ops mt9m001_ops = { - .owner = THIS_MODULE, .init = mt9m001_init, .release = mt9m001_release, - .start_capture = mt9m001_start_capture, - .stop_capture = mt9m001_stop_capture, .set_crop = mt9m001_set_crop, - .set_fmt = mt9m001_set_fmt, - .try_fmt = mt9m001_try_fmt, .set_bus_param = mt9m001_set_bus_param, .query_bus_param = mt9m001_query_bus_param, .controls = mt9m001_controls, .num_controls = ARRAY_SIZE(mt9m001_controls), - .get_control = mt9m001_get_control, - .set_control = mt9m001_set_control, - .get_chip_id = mt9m001_get_chip_id, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = mt9m001_get_register, - .set_register = mt9m001_set_register, -#endif }; -static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +static int mt9m001_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); int data; switch (ctrl->id) { @@ -423,10 +388,11 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro return 0; } -static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); + struct soc_camera_device *icd = client->dev.platform_data; const struct v4l2_queryctrl *qctrl; int data; @@ -521,10 +487,9 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro static int mt9m001_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct mt9m001 *mt9m001 = to_mt9m001(client); struct soc_camera_link *icl = to_soc_camera_link(icd); s32 data; - int ret; unsigned long flags; /* We must have a parent by now. And it cannot be a wrong one. @@ -533,11 +498,6 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* Enable the chip */ data = reg_write(client, MT9M001_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); @@ -545,8 +505,6 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, /* Read out the chip version register */ data = reg_read(client, MT9M001_CHIP_VERSION); - soc_camera_video_stop(icd); - /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ switch (data) { case 0x8411: @@ -601,6 +559,27 @@ static void mt9m001_video_remove(struct soc_camera_device *icd) icl->free_bus(icl); } +static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { + .g_ctrl = mt9m001_g_ctrl, + .s_ctrl = mt9m001_s_ctrl, + .g_chip_ident = mt9m001_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9m001_g_register, + .s_register = mt9m001_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { + .s_stream = mt9m001_s_stream, + .s_fmt = mt9m001_s_fmt, + .try_fmt = mt9m001_try_fmt, +}; + +static struct v4l2_subdev_ops mt9m001_subdev_ops = { + .core = &mt9m001_subdev_core_ops, + .video = &mt9m001_subdev_video_ops, +}; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static int mt9m001_probe(struct i2c_client *client, const struct i2c_device_id *did) @@ -635,7 +614,7 @@ static int mt9m001_probe(struct i2c_client *client) if (!mt9m001) return -ENOMEM; - i2c_set_clientdata(client, mt9m001); + v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops); /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m001_ops; @@ -664,7 +643,7 @@ static int mt9m001_probe(struct i2c_client *client) static int mt9m001_remove(struct i2c_client *client) { - struct mt9m001 *mt9m001 = i2c_get_clientdata(client); + struct mt9m001 *mt9m001 = to_mt9m001(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 5c6ab7b53..4b00033c4 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -148,6 +148,7 @@ enum mt9m111_context { }; struct mt9m111 { + struct v4l2_subdev subdev; int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ enum mt9m111_context context; struct v4l2_rect rect; @@ -164,6 +165,11 @@ struct mt9m111 { unsigned int autowhitebalance:1; }; +static struct mt9m111 *to_mt9m111(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct mt9m111, subdev); +} + static int reg_page_map_set(struct i2c_client *client, const u16 reg) { int ret; @@ -227,10 +233,9 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg, return mt9m111_reg_write(client, reg, ret & ~data); } -static int mt9m111_set_context(struct soc_camera_device *icd, +static int mt9m111_set_context(struct i2c_client *client, enum mt9m111_context ctxt) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B @@ -244,11 +249,10 @@ static int mt9m111_set_context(struct soc_camera_device *icd, return reg_write(CONTEXT_CONTROL, valA); } -static int mt9m111_setup_rect(struct soc_camera_device *icd, +static int mt9m111_setup_rect(struct i2c_client *client, struct v4l2_rect *rect) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret, is_raw_format; int width = rect->width; int height = rect->height; @@ -290,9 +294,8 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd, return ret; } -static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) +static int mt9m111_setup_pixfmt(struct i2c_client *client, u16 outfmt) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt); @@ -301,20 +304,19 @@ static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt) return ret; } -static int mt9m111_setfmt_bayer8(struct soc_camera_device *icd) +static int mt9m111_setfmt_bayer8(struct i2c_client *client) { - return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_PROCESSED_BAYER); + return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_PROCESSED_BAYER); } -static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd) +static int mt9m111_setfmt_bayer10(struct i2c_client *client) { - return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_BYPASS_IFP); + return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_BYPASS_IFP); } -static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) +static int mt9m111_setfmt_rgb565(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int val = 0; if (mt9m111->swap_rgb_red_blue) @@ -323,13 +325,12 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd) val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565; - return mt9m111_setup_pixfmt(icd, val); + return mt9m111_setup_pixfmt(client, val); } -static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) +static int mt9m111_setfmt_rgb555(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int val = 0; if (mt9m111->swap_rgb_red_blue) @@ -338,13 +339,12 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd) val |= MT9M111_OUTFMT_SWAP_RGB_EVEN; val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555; - return mt9m111_setup_pixfmt(icd, val); + return mt9m111_setup_pixfmt(client, val); } -static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) +static int mt9m111_setfmt_yuv(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int val = 0; if (mt9m111->swap_yuv_cb_cr) @@ -352,52 +352,22 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd) if (mt9m111->swap_yuv_y_chromas) val |= MT9M111_OUTFMT_SWAP_YCbCr_C_Y; - return mt9m111_setup_pixfmt(icd, val); + return mt9m111_setup_pixfmt(client, val); } -static int mt9m111_enable(struct soc_camera_device *icd) +static int mt9m111_enable(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) { - dev_err(icd->vdev->parent, - "Platform failed to power-on the camera.\n"); - return ret; - } - } - ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE); if (!ret) mt9m111->powered = 1; return ret; } -static int mt9m111_disable(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); - int ret; - - ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); - if (!ret) - mt9m111->powered = 0; - - if (icl->power) - icl->power(&client->dev, 0); - - return ret; -} - -static int mt9m111_reset(struct soc_camera_device *icd) +static int mt9m111_reset(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); @@ -407,22 +377,9 @@ static int mt9m111_reset(struct soc_camera_device *icd) ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE | MT9M111_RESET_RESET_SOC); - if (icl->reset) - icl->reset(&client->dev); - return ret; } -static int mt9m111_start_capture(struct soc_camera_device *icd) -{ - return 0; -} - -static int mt9m111_stop_capture(struct soc_camera_device *icd) -{ - return 0; -} - static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) { struct soc_camera_link *icl = to_soc_camera_link(icd); @@ -442,60 +399,59 @@ static int mt9m111_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", __func__, rect->left, rect->top, rect->width, rect->height); - ret = mt9m111_setup_rect(icd, rect); + ret = mt9m111_setup_rect(client, rect); if (!ret) mt9m111->rect = *rect; return ret; } -static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) +static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; switch (pixfmt) { case V4L2_PIX_FMT_SBGGR8: - ret = mt9m111_setfmt_bayer8(icd); + ret = mt9m111_setfmt_bayer8(client); break; case V4L2_PIX_FMT_SBGGR16: - ret = mt9m111_setfmt_bayer10(icd); + ret = mt9m111_setfmt_bayer10(client); break; case V4L2_PIX_FMT_RGB555: - ret = mt9m111_setfmt_rgb555(icd); + ret = mt9m111_setfmt_rgb555(client); break; case V4L2_PIX_FMT_RGB565: - ret = mt9m111_setfmt_rgb565(icd); + ret = mt9m111_setfmt_rgb565(client); break; case V4L2_PIX_FMT_UYVY: mt9m111->swap_yuv_y_chromas = 0; mt9m111->swap_yuv_cb_cr = 0; - ret = mt9m111_setfmt_yuv(icd); + ret = mt9m111_setfmt_yuv(client); break; case V4L2_PIX_FMT_VYUY: mt9m111->swap_yuv_y_chromas = 0; mt9m111->swap_yuv_cb_cr = 1; - ret = mt9m111_setfmt_yuv(icd); + ret = mt9m111_setfmt_yuv(client); break; case V4L2_PIX_FMT_YUYV: mt9m111->swap_yuv_y_chromas = 1; mt9m111->swap_yuv_cb_cr = 0; - ret = mt9m111_setfmt_yuv(icd); + ret = mt9m111_setfmt_yuv(client); break; case V4L2_PIX_FMT_YVYU: mt9m111->swap_yuv_y_chromas = 1; mt9m111->swap_yuv_cb_cr = 1; - ret = mt9m111_setfmt_yuv(icd); + ret = mt9m111_setfmt_yuv(client); break; default: - dev_err(&icd->dev, "Pixel format not handled : %x\n", pixfmt); + dev_err(&client->dev, "Pixel format not handled : %x\n", pixfmt); ret = -EINVAL; } @@ -505,11 +461,10 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt) return ret; } -static int mt9m111_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = mt9m111->rect.left, @@ -519,20 +474,19 @@ static int mt9m111_set_fmt(struct soc_camera_device *icd, }; int ret; - dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", + dev_dbg(&client->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", __func__, pix->pixelformat, rect.left, rect.top, rect.width, rect.height); - ret = mt9m111_setup_rect(icd, &rect); + ret = mt9m111_setup_rect(client, &rect); if (!ret) - ret = mt9m111_set_pixfmt(icd, pix->pixelformat); + ret = mt9m111_set_pixfmt(client, pix->pixelformat); if (!ret) mt9m111->rect = rect; return ret; } -static int mt9m111_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9m111_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; @@ -544,11 +498,11 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd, return 0; } -static int mt9m111_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int mt9m111_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; @@ -563,10 +517,10 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int mt9m111_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9m111_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; int val; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) @@ -584,10 +538,10 @@ static int mt9m111_get_register(struct soc_camera_device *icd, return 0; } -static int mt9m111_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9m111_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) return -EINVAL; @@ -639,41 +593,24 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { } }; -static int mt9m111_get_control(struct soc_camera_device *, - struct v4l2_control *); -static int mt9m111_set_control(struct soc_camera_device *, - struct v4l2_control *); static int mt9m111_resume(struct soc_camera_device *icd); static int mt9m111_init(struct soc_camera_device *icd); static int mt9m111_release(struct soc_camera_device *icd); static struct soc_camera_ops mt9m111_ops = { - .owner = THIS_MODULE, .init = mt9m111_init, .resume = mt9m111_resume, .release = mt9m111_release, - .start_capture = mt9m111_start_capture, - .stop_capture = mt9m111_stop_capture, .set_crop = mt9m111_set_crop, - .set_fmt = mt9m111_set_fmt, - .try_fmt = mt9m111_try_fmt, .query_bus_param = mt9m111_query_bus_param, .set_bus_param = mt9m111_set_bus_param, .controls = mt9m111_controls, .num_controls = ARRAY_SIZE(mt9m111_controls), - .get_control = mt9m111_get_control, - .set_control = mt9m111_set_control, - .get_chip_id = mt9m111_get_chip_id, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = mt9m111_get_register, - .set_register = mt9m111_set_register, -#endif }; -static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) +static int mt9m111_set_flip(struct i2c_client *client, int flip, int mask) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; if (mt9m111->context == HIGHPOWER) { @@ -691,9 +628,8 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask) return ret; } -static int mt9m111_get_global_gain(struct soc_camera_device *icd) +static int mt9m111_get_global_gain(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int data; data = reg_read(GLOBAL_GAIN); @@ -703,9 +639,9 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd) return data; } -static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) +static int mt9m111_set_global_gain(struct i2c_client *client, int gain) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct soc_camera_device *icd = client->dev.platform_data; u16 val; if (gain > 63 * 2 * 2) @@ -722,10 +658,9 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) return reg_write(GLOBAL_GAIN, val); } -static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) +static int mt9m111_set_autoexposure(struct i2c_client *client, int on) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; if (on) @@ -739,10 +674,9 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on) return ret; } -static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) +static int mt9m111_set_autowhitebalance(struct i2c_client *client, int on) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; if (on) @@ -756,11 +690,10 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on) return ret; } -static int mt9m111_get_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int mt9m111_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); int data; switch (ctrl->id) { @@ -785,7 +718,7 @@ static int mt9m111_get_control(struct soc_camera_device *icd, ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS); break; case V4L2_CID_GAIN: - data = mt9m111_get_global_gain(icd); + data = mt9m111_get_global_gain(client); if (data < 0) return data; ctrl->value = data; @@ -800,38 +733,36 @@ static int mt9m111_get_control(struct soc_camera_device *icd, return 0; } -static int mt9m111_set_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); const struct v4l2_queryctrl *qctrl; int ret; qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id); - if (!qctrl) return -EINVAL; switch (ctrl->id) { case V4L2_CID_VFLIP: mt9m111->vflip = ctrl->value; - ret = mt9m111_set_flip(icd, ctrl->value, + ret = mt9m111_set_flip(client, ctrl->value, MT9M111_RMB_MIRROR_ROWS); break; case V4L2_CID_HFLIP: mt9m111->hflip = ctrl->value; - ret = mt9m111_set_flip(icd, ctrl->value, + ret = mt9m111_set_flip(client, ctrl->value, MT9M111_RMB_MIRROR_COLS); break; case V4L2_CID_GAIN: - ret = mt9m111_set_global_gain(icd, ctrl->value); + ret = mt9m111_set_global_gain(client, ctrl->value); break; case V4L2_CID_EXPOSURE_AUTO: - ret = mt9m111_set_autoexposure(icd, ctrl->value); + ret = mt9m111_set_autoexposure(client, ctrl->value); break; case V4L2_CID_AUTO_WHITE_BALANCE: - ret = mt9m111_set_autowhitebalance(icd, ctrl->value); + ret = mt9m111_set_autowhitebalance(client, ctrl->value); break; default: ret = -EINVAL; @@ -840,34 +771,34 @@ static int mt9m111_set_control(struct soc_camera_device *icd, return ret; } -static int mt9m111_restore_state(struct soc_camera_device *icd) +static int mt9m111_restore_state(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); - - mt9m111_set_context(icd, mt9m111->context); - mt9m111_set_pixfmt(icd, mt9m111->pixfmt); - mt9m111_setup_rect(icd, &mt9m111->rect); - mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); - mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); - mt9m111_set_global_gain(icd, icd->gain); - mt9m111_set_autoexposure(icd, mt9m111->autoexposure); - mt9m111_set_autowhitebalance(icd, mt9m111->autowhitebalance); + struct mt9m111 *mt9m111 = to_mt9m111(client); + struct soc_camera_device *icd = client->dev.platform_data; + + mt9m111_set_context(client, mt9m111->context); + mt9m111_set_pixfmt(client, mt9m111->pixfmt); + mt9m111_setup_rect(client, &mt9m111->rect); + mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); + mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); + mt9m111_set_global_gain(client, icd->gain); + mt9m111_set_autoexposure(client, mt9m111->autoexposure); + mt9m111_set_autowhitebalance(client, mt9m111->autowhitebalance); return 0; } static int mt9m111_resume(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret = 0; if (mt9m111->powered) { - ret = mt9m111_enable(icd); + ret = mt9m111_enable(client); if (!ret) - ret = mt9m111_reset(icd); + ret = mt9m111_reset(client); if (!ret) - ret = mt9m111_restore_state(icd); + ret = mt9m111_restore_state(client); } return ret; } @@ -875,17 +806,17 @@ static int mt9m111_resume(struct soc_camera_device *icd) static int mt9m111_init(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; mt9m111->context = HIGHPOWER; - ret = mt9m111_enable(icd); + ret = mt9m111_enable(client); if (!ret) - ret = mt9m111_reset(icd); + ret = mt9m111_reset(client); if (!ret) - ret = mt9m111_set_context(icd, mt9m111->context); + ret = mt9m111_set_context(client, mt9m111->context); if (!ret) - ret = mt9m111_set_autoexposure(icd, mt9m111->autoexposure); + ret = mt9m111_set_autoexposure(client, mt9m111->autoexposure); if (ret) dev_err(&icd->dev, "mt9m11x init failed: %d\n", ret); return ret; @@ -893,9 +824,14 @@ static int mt9m111_init(struct soc_camera_device *icd) static int mt9m111_release(struct soc_camera_device *icd) { + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; - ret = mt9m111_disable(icd); + ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); + if (!ret) + mt9m111->powered = 0; + if (ret < 0) dev_err(&icd->dev, "mt9m11x release failed: %d\n", ret); @@ -909,7 +845,7 @@ static int mt9m111_release(struct soc_camera_device *icd) static int mt9m111_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); s32 data; int ret; @@ -921,15 +857,10 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - goto evstart; - - ret = mt9m111_enable(icd); + ret = mt9m111_enable(client); if (ret) goto ei2c; - ret = mt9m111_reset(icd); + ret = mt9m111_reset(client); if (ret) goto ei2c; @@ -961,11 +892,29 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, mt9m111->swap_rgb_red_blue = 1; ei2c: - soc_camera_video_stop(icd); -evstart: return ret; } +static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { + .g_ctrl = mt9m111_g_ctrl, + .s_ctrl = mt9m111_s_ctrl, + .g_chip_ident = mt9m111_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9m111_g_register, + .s_register = mt9m111_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { + .s_fmt = mt9m111_s_fmt, + .try_fmt = mt9m111_try_fmt, +}; + +static struct v4l2_subdev_ops mt9m111_subdev_ops = { + .core = &mt9m111_subdev_core_ops, + .video = &mt9m111_subdev_video_ops, +}; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int mt9m111_probe(struct i2c_client *client) #else @@ -1000,7 +949,7 @@ static int mt9m111_probe(struct i2c_client *client, if (!mt9m111) return -ENOMEM; - i2c_set_clientdata(client, mt9m111); + v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops); /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m111_ops; @@ -1026,7 +975,7 @@ static int mt9m111_probe(struct i2c_client *client, static int mt9m111_remove(struct i2c_client *client) { - struct mt9m111 *mt9m111 = i2c_get_clientdata(client); + struct mt9m111 *mt9m111 = to_mt9m111(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index b389223bc..2aff92cfc 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -13,13 +13,13 @@ #include #include -#include +#include #include #include /* mt9t031 i2c address 0x5d - * The platform has to define i2c_board_info - * and call i2c_register_board_info() */ + * The platform has to define i2c_board_info and link to it from + * struct soc_camera_link */ /* mt9t031 selected register addresses */ #define MT9T031_CHIP_VERSION 0x00 @@ -68,12 +68,18 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = { }; struct mt9t031 { + struct v4l2_subdev subdev; int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ unsigned char autoexposure; u16 xskip; u16 yskip; }; +static struct mt9t031 *to_mt9t031(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct mt9t031, subdev); +} + static int reg_read(struct i2c_client *client, const u8 reg) { s32 data = i2c_smbus_read_word_data(client, reg); @@ -134,21 +140,10 @@ static int get_shutter(struct i2c_client *client, u32 *data) return ret < 0 ? ret : 0; } -static int mt9t031_init(struct soc_camera_device *icd) +static int mt9t031_idle(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); int ret; - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) { - dev_err(icd->vdev->parent, - "Platform failed to power-on the camera.\n"); - return ret; - } - } - /* Disable chip output, synchronous option update */ ret = reg_write(client, MT9T031_RESET, 1); if (ret >= 0) @@ -156,43 +151,46 @@ static int mt9t031_init(struct soc_camera_device *icd) if (ret >= 0) ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); - if (ret < 0 && icl->power) - icl->power(&client->dev, 0); - return ret >= 0 ? 0 : -EIO; } -static int mt9t031_release(struct soc_camera_device *icd) +static int mt9t031_disable(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - /* Disable the chip */ reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); - if (icl->power) - icl->power(&client->dev, 0); - return 0; } -static int mt9t031_start_capture(struct soc_camera_device *icd) +static int mt9t031_init(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - /* Switch to master "normal" mode */ - if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0) - return -EIO; - return 0; + return mt9t031_idle(client); } -static int mt9t031_stop_capture(struct soc_camera_device *icd) +static int mt9t031_release(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - /* Stop sensor readout */ - if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0) + return mt9t031_disable(client); +} + +static int mt9t031_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct i2c_client *client = sd->priv; + int ret; + + if (enable) + /* Switch to master "normal" mode */ + ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 2); + else + /* Stop sensor readout */ + ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); + + if (ret < 0) return -EIO; + return 0; } @@ -236,7 +234,7 @@ static int mt9t031_set_params(struct soc_camera_device *icd, struct v4l2_rect *rect, u16 xskip, u16 yskip) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct mt9t031 *mt9t031 = to_mt9t031(client); int ret; u16 xbin, ybin, width, height, left, top; const u16 hblank = MT9T031_HORIZONTAL_BLANK, @@ -334,17 +332,17 @@ static int mt9t031_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct mt9t031 *mt9t031 = to_mt9t031(client); /* CROP - no change in scaling, or in limits */ return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); } -static int mt9t031_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); + struct soc_camera_device *icd = client->dev.platform_data; int ret; u16 xskip, yskip; struct v4l2_rect rect = { @@ -379,8 +377,7 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, return ret; } -static int mt9t031_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9t031_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; @@ -391,11 +388,11 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd, return 0; } -static int mt9t031_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int mt9t031_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; @@ -410,10 +407,10 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int mt9t031_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9t031_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -429,10 +426,10 @@ static int mt9t031_get_register(struct soc_camera_device *icd, return 0; } -static int mt9t031_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9t031_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -493,35 +490,20 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { } }; -static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *); -static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *); - static struct soc_camera_ops mt9t031_ops = { - .owner = THIS_MODULE, .init = mt9t031_init, .release = mt9t031_release, - .start_capture = mt9t031_start_capture, - .stop_capture = mt9t031_stop_capture, .set_crop = mt9t031_set_crop, - .set_fmt = mt9t031_set_fmt, - .try_fmt = mt9t031_try_fmt, .set_bus_param = mt9t031_set_bus_param, .query_bus_param = mt9t031_query_bus_param, .controls = mt9t031_controls, .num_controls = ARRAY_SIZE(mt9t031_controls), - .get_control = mt9t031_get_control, - .set_control = mt9t031_set_control, - .get_chip_id = mt9t031_get_chip_id, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = mt9t031_get_register, - .set_register = mt9t031_set_register, -#endif }; -static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); int data; switch (ctrl->id) { @@ -544,10 +526,11 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro return 0; } -static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) +static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); + struct soc_camera_device *icd = client->dev.platform_data; const struct v4l2_queryctrl *qctrl; int data; @@ -653,12 +636,11 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro /* Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one */ -static int mt9t031_video_probe(struct soc_camera_device *icd, - struct i2c_client *client) +static int mt9t031_video_probe(struct i2c_client *client) { - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct soc_camera_device *icd = client->dev.platform_data; + struct mt9t031 *mt9t031 = to_mt9t031(client); s32 data; - int ret; /* We must have a parent by now. And it cannot be a wrong one. * So this entire test is completely redundant. */ @@ -666,11 +648,6 @@ static int mt9t031_video_probe(struct soc_camera_device *icd, to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* Enable the chip */ data = reg_write(client, MT9T031_CHIP_ENABLE, 1); dev_dbg(&icd->dev, "write: %d\n", data); @@ -678,8 +655,6 @@ static int mt9t031_video_probe(struct soc_camera_device *icd, /* Read out the chip version register */ data = reg_read(client, MT9T031_CHIP_VERSION); - soc_camera_video_stop(icd); - switch (data) { case 0x1621: mt9t031->model = V4L2_IDENT_MT9T031; @@ -697,6 +672,27 @@ static int mt9t031_video_probe(struct soc_camera_device *icd, return 0; } +static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { + .g_ctrl = mt9t031_g_ctrl, + .s_ctrl = mt9t031_s_ctrl, + .g_chip_ident = mt9t031_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9t031_g_register, + .s_register = mt9t031_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { + .s_stream = mt9t031_s_stream, + .s_fmt = mt9t031_s_fmt, + .try_fmt = mt9t031_try_fmt, +}; + +static struct v4l2_subdev_ops mt9t031_subdev_ops = { + .core = &mt9t031_subdev_core_ops, + .video = &mt9t031_subdev_video_ops, +}; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int mt9t031_probe(struct i2c_client *client) #else @@ -731,7 +727,7 @@ static int mt9t031_probe(struct i2c_client *client, if (!mt9t031) return -ENOMEM; - i2c_set_clientdata(client, mt9t031); + v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops); /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9t031_ops; @@ -751,7 +747,12 @@ static int mt9t031_probe(struct i2c_client *client, mt9t031->xskip = 1; mt9t031->yskip = 1; - ret = mt9t031_video_probe(icd, client); + mt9t031_idle(client); + + ret = mt9t031_video_probe(client); + + mt9t031_disable(client); + if (ret) { icd->ops = NULL; i2c_set_clientdata(client, NULL); @@ -763,7 +764,7 @@ static int mt9t031_probe(struct i2c_client *client, static int mt9t031_remove(struct i2c_client *client) { - struct mt9t031 *mt9t031 = i2c_get_clientdata(client); + struct mt9t031 *mt9t031 = to_mt9t031(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 204481f77..b09cd0913 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -14,13 +14,13 @@ #include #include -#include +#include #include #include /* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c - * The platform has to define i2c_board_info - * and call i2c_register_board_info() */ + * The platform has to define ctruct i2c_board_info objects and link to them + * from struct soc_camera_link */ static char *sensor_type; module_param(sensor_type, charp, S_IRUGO); @@ -85,10 +85,16 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { }; struct mt9v022 { + struct v4l2_subdev subdev; int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ u16 chip_control; }; +static struct mt9v022 *to_mt9v022(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct mt9v022, subdev); +} + static int reg_read(struct i2c_client *client, const u8 reg) { s32 data = i2c_smbus_read_word_data(client, reg); @@ -126,26 +132,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg, static int mt9v022_init(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); int ret; - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) { - dev_err(icd->vdev->parent, - "Platform failed to power-on the camera.\n"); - return ret; - } - } - - /* - * The camera could have been already on, we hard-reset it additionally, - * if available. Soft reset is done in video_probe(). - */ - if (icl->reset) - icl->reset(&client->dev); - /* Almost the default mode: master, parallel, simultaneous, and an * undocumented bit 0x200, which is present in table 7, but not in 8, * plus snapshot mode to disable scan for now */ @@ -169,37 +158,19 @@ static int mt9v022_init(struct soc_camera_device *icd) return ret; } -static int mt9v022_release(struct soc_camera_device *icd) +static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); - if (icl->power) - icl->power(&client->dev, 0); - - return 0; -} - -static int mt9v022_start_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); - /* Switch to master "normal" mode */ - mt9v022->chip_control &= ~0x10; - if (reg_write(client, MT9V022_CHIP_CONTROL, - mt9v022->chip_control) < 0) - return -EIO; - return 0; -} + if (enable) + /* Switch to master "normal" mode */ + mt9v022->chip_control &= ~0x10; + else + /* Switch to snapshot mode */ + mt9v022->chip_control |= 0x10; -static int mt9v022_stop_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); - /* Switch to snapshot mode */ - mt9v022->chip_control |= 0x10; - if (reg_write(client, MT9V022_CHIP_CONTROL, - mt9v022->chip_control) < 0) + if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0) return -EIO; return 0; } @@ -208,7 +179,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; int ret; @@ -320,11 +291,11 @@ static int mt9v022_set_crop(struct soc_camera_device *icd, return 0; } -static int mt9v022_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = icd->x_current, @@ -357,9 +328,10 @@ static int mt9v022_set_fmt(struct soc_camera_device *icd, return mt9v022_set_crop(icd, &rect); } -static int mt9v022_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; v4l_bound_align_image(&pix->width, 48, 752, 2 /* ? */, @@ -369,11 +341,11 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd, return 0; } -static int mt9v022_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int mt9v022_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) return -EINVAL; @@ -388,10 +360,10 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int mt9v022_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9v022_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -408,10 +380,10 @@ static int mt9v022_get_register(struct soc_camera_device *icd, return 0; } -static int mt9v022_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int mt9v022_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) return -EINVAL; @@ -480,35 +452,18 @@ static const struct v4l2_queryctrl mt9v022_controls[] = { } }; -static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *); -static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *); - static struct soc_camera_ops mt9v022_ops = { - .owner = THIS_MODULE, .init = mt9v022_init, - .release = mt9v022_release, - .start_capture = mt9v022_start_capture, - .stop_capture = mt9v022_stop_capture, .set_crop = mt9v022_set_crop, - .set_fmt = mt9v022_set_fmt, - .try_fmt = mt9v022_try_fmt, .set_bus_param = mt9v022_set_bus_param, .query_bus_param = mt9v022_query_bus_param, .controls = mt9v022_controls, .num_controls = ARRAY_SIZE(mt9v022_controls), - .get_control = mt9v022_get_control, - .set_control = mt9v022_set_control, - .get_chip_id = mt9v022_get_chip_id, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = mt9v022_get_register, - .set_register = mt9v022_set_register, -#endif }; -static int mt9v022_get_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; int data; switch (ctrl->id) { @@ -540,15 +495,14 @@ static int mt9v022_get_control(struct soc_camera_device *icd, return 0; } -static int mt9v022_set_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { int data; - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; const struct v4l2_queryctrl *qctrl; qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); - if (!qctrl) return -EINVAL; @@ -644,7 +598,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd, static int mt9v022_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_link *icl = to_soc_camera_link(icd); s32 data; int ret; @@ -654,11 +608,6 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* Read out the chip version register */ data = reg_read(client, MT9V022_CHIP_VERSION); @@ -723,8 +672,6 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, "monochrome" : "colour"); ei2c: - soc_camera_video_stop(icd); - return ret; } @@ -739,6 +686,27 @@ static void mt9v022_video_remove(struct soc_camera_device *icd) icl->free_bus(icl); } +static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { + .g_ctrl = mt9v022_g_ctrl, + .s_ctrl = mt9v022_s_ctrl, + .g_chip_ident = mt9v022_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9v022_g_register, + .s_register = mt9v022_s_register, +#endif +}; + +static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { + .s_stream = mt9v022_s_stream, + .s_fmt = mt9v022_s_fmt, + .try_fmt = mt9v022_try_fmt, +}; + +static struct v4l2_subdev_ops mt9v022_subdev_ops = { + .core = &mt9v022_subdev_core_ops, + .video = &mt9v022_subdev_video_ops, +}; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static int mt9v022_probe(struct i2c_client *client, const struct i2c_device_id *did) @@ -773,8 +741,9 @@ static int mt9v022_probe(struct i2c_client *client) if (!mt9v022) return -ENOMEM; + v4l2_i2c_subdev_init(&mt9v022->subdev, client, &mt9v022_subdev_ops); + mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; - i2c_set_clientdata(client, mt9v022); icd->ops = &mt9v022_ops; icd->x_min = 1; @@ -799,7 +768,7 @@ static int mt9v022_probe(struct i2c_client *client) static int mt9v022_remove(struct i2c_client *client) { - struct mt9v022 *mt9v022 = i2c_get_clientdata(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 736c31d23..ea4ceaec8 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -219,7 +219,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) int ret; if (unlikely(!pcdev->active)) { - dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n"); + dev_err(pcdev->icd->dev.parent, "DMA End IRQ with no active buffer\n"); return -EFAULT; } @@ -229,7 +229,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) vbuf->size, pcdev->res->start + CSIRXR, DMA_MODE_READ); if (unlikely(ret)) - dev_err(pcdev->soc_host.dev, "Failed to setup DMA sg list\n"); + dev_err(pcdev->icd->dev.parent, "Failed to setup DMA sg list\n"); return ret; } @@ -334,14 +334,14 @@ static void mx1_camera_dma_irq(int channel, void *data) imx_dma_disable(channel); if (unlikely(!pcdev->active)) { - dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n"); + dev_err(pcdev->icd->dev.parent, "DMA End IRQ with no active buffer\n"); goto out; } vb = &pcdev->active->vb; buf = container_of(vb, struct mx1_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(pcdev->soc_host.dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(pcdev->icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); mx1_camera_wakeup(pcdev, vb, buf); @@ -362,7 +362,7 @@ static void mx1_camera_init_videobuf(struct videobuf_queue *q, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx1_camera_dev *pcdev = ici->priv; - videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, ici->dev, + videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->dev.parent, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, @@ -381,7 +381,7 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev) * they get a nice Oops */ div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; - dev_dbg(pcdev->soc_host.dev, "System clock %lukHz, target freq %dkHz, " + dev_dbg(pcdev->icd->dev.parent, "System clock %lukHz, target freq %dkHz, " "divisor %lu\n", lcdclk / 1000, mclk / 1000, div); return div; @@ -391,7 +391,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) { unsigned int csicr1 = CSICR1_EN; - dev_dbg(pcdev->soc_host.dev, "Activate device\n"); + dev_dbg(pcdev->icd->dev.parent, "Activate device\n"); clk_enable(pcdev->clk); @@ -407,7 +407,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) { - dev_dbg(pcdev->soc_host.dev, "Deactivate device\n"); + dev_dbg(pcdev->icd->dev.parent, "Deactivate device\n"); /* Disable all CSI interface */ __raw_writel(0x00, pcdev->base + CSICR1); @@ -432,10 +432,8 @@ static int mx1_camera_add_device(struct soc_camera_device *icd) icd->devnum); mx1_camera_activate(pcdev); - ret = icd->ops->init(icd); - if (!ret) - pcdev->icd = icd; + pcdev->icd = icd; ebusy: return ret; @@ -459,8 +457,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) dev_info(&icd->dev, "MX1 Camera driver detached from camera %d\n", icd->devnum); - icd->ops->release(icd); - mx1_camera_deactivate(pcdev); pcdev->icd = NULL; @@ -546,11 +542,11 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(icd->dev.parent, "Format %x not found\n", pix->pixelformat); return -EINVAL; } - ret = icd->ops->set_fmt(icd, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; @@ -562,10 +558,11 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, static int mx1_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); /* TODO: limit to mx1 hardware capabilities */ /* limit to sensor capabilities */ - return icd->ops->try_fmt(icd, f); + return v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); } static int mx1_camera_reqbufs(struct soc_camera_file *icf, @@ -737,7 +734,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev) pcdev->soc_host.drv_name = DRIVER_NAME; pcdev->soc_host.ops = &mx1_soc_camera_host_ops; pcdev->soc_host.priv = pcdev; - pcdev->soc_host.dev = &pdev->dev; + pcdev->soc_host.v4l2_dev.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; err = soc_camera_host_register(&pcdev->soc_host); if (err) diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index 2edf77a62..677d355be 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -431,7 +431,7 @@ static void mx3_camera_init_videobuf(struct videobuf_queue *q, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; - videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, ici->dev, + videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, icd->dev.parent, &mx3_cam->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, @@ -494,17 +494,11 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; - int ret; - if (mx3_cam->icd) { - ret = -EBUSY; - goto ebusy; - } + if (mx3_cam->icd) + return -EBUSY; mx3_camera_activate(mx3_cam, icd); - ret = icd->ops->init(icd); - if (ret < 0) - goto einit; mx3_cam->icd = icd; @@ -512,12 +506,6 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) icd->devnum); return 0; - -einit: - clk_disable(mx3_cam->clk); -ebusy: - - return ret; } /* Called with .video_lock held */ @@ -534,8 +522,6 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd) *ichan = NULL; } - icd->ops->release(icd); - clk_disable(mx3_cam->clk); mx3_cam->icd = NULL; @@ -600,7 +586,7 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam, *flags |= SOCAM_DATAWIDTH_4; break; default: - dev_info(mx3_cam->soc_host.dev, "Unsupported bus width %d\n", + dev_info(mx3_cam->soc_host.v4l2_dev.dev, "Unsupported bus width %d\n", buswidth); return -EINVAL; } @@ -616,7 +602,7 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd, unsigned long bus_flags, camera_flags; int ret = test_platform_param(mx3_cam, depth, &bus_flags); - dev_dbg(ici->dev, "requested bus width %d bit: %d\n", depth, ret); + dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", depth, ret); if (ret < 0) return ret; @@ -639,7 +625,7 @@ static bool chan_filter(struct dma_chan *chan, void *arg) if (!rq) return false; - pdata = rq->mx3_cam->soc_host.dev->platform_data; + pdata = rq->mx3_cam->soc_host.v4l2_dev.dev->platform_data; return rq->id == chan->chan_id && pdata->dma_dev == chan->device->dev; @@ -699,7 +685,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->dev, "Providing format %s using %s\n", + dev_dbg(icd->dev.parent, "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -711,7 +697,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->dev, "Providing format %s using %s\n", + dev_dbg(icd->dev.parent, "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -724,7 +710,7 @@ passthrough: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->dev, + dev_dbg(icd->dev.parent, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -831,7 +817,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(icd->dev.parent, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -847,7 +833,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, configure_geometry(mx3_cam, &rect); - ret = icd->ops->set_fmt(icd, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; @@ -868,7 +854,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (pixfmt && !xlate) { - dev_warn(ici->dev, "Format %x not found\n", pixfmt); + dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -885,7 +871,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, /* camera has to see its format, but the user the original one */ pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = icd->ops->try_fmt(icd, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); pix->pixelformat = xlate->host_fmt->fourcc; field = pix->field; @@ -935,11 +921,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pixfmt); + dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); return -EINVAL; } - dev_dbg(ici->dev, "requested bus width %d bit: %d\n", + dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", icd->buswidth, ret); if (ret < 0) @@ -948,10 +934,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); - dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", + dev_dbg(icd->dev.parent, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", camera_flags, bus_flags, common_flags); if (!common_flags) { - dev_dbg(ici->dev, "no common flags"); + dev_dbg(icd->dev.parent, "no common flags"); return -EINVAL; } @@ -1005,7 +991,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) ret = icd->ops->set_bus_param(icd, common_flags); if (ret < 0) { - dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n", + dev_dbg(icd->dev.parent, "camera set_bus_param(%lx) returned %d\n", common_flags, ret); return ret; } @@ -1060,7 +1046,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF); - dev_dbg(ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw); + dev_dbg(icd->dev.parent, "Set SENS_CONF to %x\n", sens_conf | dw); return 0; } @@ -1145,7 +1131,7 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) soc_host->drv_name = MX3_CAM_DRV_NAME; soc_host->ops = &mx3_soc_camera_host_ops; soc_host->priv = mx3_cam; - soc_host->dev = &pdev->dev; + soc_host->v4l2_dev.dev = &pdev->dev; soc_host->nr = pdev->id; err = soc_camera_host_register(soc_host); diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 297a46fc9..4da12e8c4 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include @@ -398,6 +398,7 @@ struct ov772x_win_size { }; struct ov772x_priv { + struct v4l2_subdev subdev; struct ov772x_camera_info *info; const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; @@ -575,6 +576,11 @@ static const struct v4l2_queryctrl ov772x_controls[] = { * general function */ +static struct ov772x_priv *to_ov772x(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct ov772x_priv, subdev); +} + static int ov772x_write_array(struct i2c_client *client, const struct regval_list *vals) { @@ -615,61 +621,29 @@ static int ov772x_reset(struct i2c_client *client) * soc_camera_ops function */ -static int ov772x_init(struct soc_camera_device *icd) +static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - int ret = 0; + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) - return ret; + if (!enable) { + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); + return 0; } - if (icl->reset) - ret = icl->reset(&client->dev); - - return ret; -} - -static int ov772x_release(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - int ret = 0; - - if (icl->power) - ret = icl->power(&client->dev, 0); - - return ret; -} - -static int ov772x_start_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); - if (!priv->win || !priv->fmt) { - dev_err(&icd->dev, "norm or win select error\n"); + dev_err(&client->dev, "norm or win select error\n"); return -EPERM; } ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); - dev_dbg(&icd->dev, + dev_dbg(&client->dev, "format %s, win %s\n", priv->fmt->name, priv->win->name); return 0; } -static int ov772x_stop_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); - return 0; -} - static int ov772x_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { @@ -688,11 +662,10 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } -static int ov772x_get_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); switch (ctrl->id) { case V4L2_CID_VFLIP: @@ -705,11 +678,10 @@ static int ov772x_get_control(struct soc_camera_device *icd, return 0; } -static int ov772x_set_control(struct soc_camera_device *icd, - struct v4l2_control *ctrl) +static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); int ret = 0; u8 val; @@ -733,11 +705,11 @@ static int ov772x_set_control(struct soc_camera_device *icd, return ret; } -static int ov772x_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) +static int ov772x_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); id->ident = priv->model; id->revision = 0; @@ -746,10 +718,10 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int ov772x_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int ov772x_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; int ret; reg->size = 1; @@ -765,10 +737,10 @@ static int ov772x_get_register(struct soc_camera_device *icd, return 0; } -static int ov772x_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int ov772x_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->reg > 0xff || reg->val > 0xff) @@ -778,8 +750,7 @@ static int ov772x_set_register(struct soc_camera_device *icd, } #endif -static const struct ov772x_win_size* -ov772x_select_win(u32 width, u32 height) +static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) { __u32 diff; const struct ov772x_win_size *win; @@ -798,11 +769,10 @@ ov772x_select_win(u32 width, u32 height) return win; } -static int ov772x_set_params(struct soc_camera_device *icd, +static int ov772x_set_params(struct i2c_client *client, u32 width, u32 height, u32 pixfmt) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); int ret = -EINVAL; u8 val; int i; @@ -817,7 +787,6 @@ static int ov772x_set_params(struct soc_camera_device *icd, break; } } - dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i); if (!priv->fmt) goto ov772x_set_fmt_error; @@ -939,26 +908,26 @@ static int ov772x_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); if (!priv->fmt) return -EINVAL; - return ov772x_set_params(icd, rect->width, rect->height, + return ov772x_set_params(client, rect->width, rect->height, priv->fmt->fourcc); } -static int ov772x_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; struct v4l2_pix_format *pix = &f->fmt.pix; - return ov772x_set_params(icd, pix->width, pix->height, + return ov772x_set_params(client, pix->width, pix->height, pix->pixelformat); } -static int ov772x_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int ov772x_try_fmt(struct v4l2_subdev *sd, + struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; const struct ov772x_win_size *win; @@ -978,10 +947,9 @@ static int ov772x_try_fmt(struct soc_camera_device *icd, static int ov772x_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); u8 pid, ver; const char *devname; - int ret; /* * We must have a parent by now. And it cannot be a wrong one. @@ -1003,11 +971,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd, icd->formats = ov772x_fmt_lists; icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* * check and show product ID and manufacturer ID */ @@ -1026,8 +989,7 @@ static int ov772x_video_probe(struct soc_camera_device *icd, default: dev_err(&icd->dev, "Product ID error %x:%x\n", pid, ver); - ret = -ENODEV; - goto ever; + return -ENODEV; } dev_info(&icd->dev, @@ -1038,34 +1000,38 @@ static int ov772x_video_probe(struct soc_camera_device *icd, i2c_smbus_read_byte_data(client, MIDH), i2c_smbus_read_byte_data(client, MIDL)); - soc_camera_video_stop(icd); - -ever: - return ret; + return 0; } static struct soc_camera_ops ov772x_ops = { - .owner = THIS_MODULE, - .init = ov772x_init, - .release = ov772x_release, - .start_capture = ov772x_start_capture, - .stop_capture = ov772x_stop_capture, .set_crop = ov772x_set_crop, - .set_fmt = ov772x_set_fmt, - .try_fmt = ov772x_try_fmt, .set_bus_param = ov772x_set_bus_param, .query_bus_param = ov772x_query_bus_param, .controls = ov772x_controls, .num_controls = ARRAY_SIZE(ov772x_controls), - .get_control = ov772x_get_control, - .set_control = ov772x_set_control, - .get_chip_id = ov772x_get_chip_id, +}; + +static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { + .g_ctrl = ov772x_g_ctrl, + .s_ctrl = ov772x_s_ctrl, + .g_chip_ident = ov772x_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = ov772x_get_register, - .set_register = ov772x_set_register, + .g_register = ov772x_g_register, + .s_register = ov772x_s_register, #endif }; +static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { + .s_stream = ov772x_s_stream, + .s_fmt = ov772x_s_fmt, + .try_fmt = ov772x_try_fmt, +}; + +static struct v4l2_subdev_ops ov772x_subdev_ops = { + .core = &ov772x_subdev_core_ops, + .video = &ov772x_subdev_video_ops, +}; + /* * i2c_driver function */ @@ -1085,7 +1051,7 @@ static int ov772x_probe(struct i2c_client *client, int ret; if (!icd) { - dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); + dev_err(&client->dev, "OV772X: missing soc-camera data!\n"); return -EINVAL; } @@ -1106,8 +1072,9 @@ static int ov772x_probe(struct i2c_client *client, if (!priv) return -ENOMEM; - priv->info = info; - i2c_set_clientdata(client, priv); + priv->info = info; + + v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); icd->ops = &ov772x_ops; icd->width_max = MAX_WIDTH; @@ -1125,7 +1092,7 @@ static int ov772x_probe(struct i2c_client *client, static int ov772x_remove(struct i2c_client *client) { - struct ov772x_priv *priv = i2c_get_clientdata(client); + struct ov772x_priv *priv = to_ov772x(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 8b1537581..4c73b7d88 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -282,7 +282,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { if (buf->dmas[i].sg_cpu) - dma_free_coherent(ici->dev, buf->dmas[i].sg_size, + dma_free_coherent(ici->v4l2_dev.dev, buf->dmas[i].sg_size, buf->dmas[i].sg_cpu, buf->dmas[i].sg_dma); buf->dmas[i].sg_cpu = NULL; @@ -337,19 +337,20 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, struct scatterlist **sg_first, int *sg_first_ofs) { struct pxa_cam_dma *pxa_dma = &buf->dmas[channel]; + struct device *dev = pcdev->soc_host.v4l2_dev.dev; struct scatterlist *sg; int i, offset, sglen; int dma_len = 0, xfer_len = 0; if (pxa_dma->sg_cpu) - dma_free_coherent(pcdev->soc_host.dev, pxa_dma->sg_size, + dma_free_coherent(dev, pxa_dma->sg_size, pxa_dma->sg_cpu, pxa_dma->sg_dma); sglen = calculate_dma_sglen(*sg_first, dma->sglen, *sg_first_ofs, size); pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc); - pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->soc_host.dev, pxa_dma->sg_size, + pxa_dma->sg_cpu = dma_alloc_coherent(dev, pxa_dma->sg_size, &pxa_dma->sg_dma, GFP_KERNEL); if (!pxa_dma->sg_cpu) return -ENOMEM; @@ -357,7 +358,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, pxa_dma->sglen = sglen; offset = *sg_first_ofs; - dev_dbg(pcdev->soc_host.dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n", + dev_dbg(dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n", *sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma); @@ -380,7 +381,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, pxa_dma->sg_cpu[i].ddadr = pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc); - dev_vdbg(pcdev->soc_host.dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n", + dev_vdbg(dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n", pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc), sg_dma_address(sg) + offset, xfer_len); offset = 0; @@ -430,11 +431,12 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; + struct device *dev = pcdev->soc_host.v4l2_dev.dev; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); int ret; int size_y, size_u = 0, size_v = 0; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); /* Added list head initialization on alloc */ @@ -492,8 +494,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y, &sg, &next_ofs); if (ret) { - dev_err(pcdev->soc_host.dev, - "DMA initialization for Y/RGB failed\n"); + dev_err(dev, "DMA initialization for Y/RGB failed\n"); goto fail; } @@ -502,8 +503,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1, size_u, &sg, &next_ofs); if (ret) { - dev_err(pcdev->soc_host.dev, - "DMA initialization for U failed\n"); + dev_err(dev, "DMA initialization for U failed\n"); goto fail_u; } @@ -512,8 +512,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2, size_v, &sg, &next_ofs); if (ret) { - dev_err(pcdev->soc_host.dev, - "DMA initialization for V failed\n"); + dev_err(dev, "DMA initialization for V failed\n"); goto fail_v; } @@ -526,10 +525,10 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, return 0; fail_v: - dma_free_coherent(pcdev->soc_host.dev, buf->dmas[1].sg_size, + dma_free_coherent(dev, buf->dmas[1].sg_size, buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma); fail_u: - dma_free_coherent(pcdev->soc_host.dev, buf->dmas[0].sg_size, + dma_free_coherent(dev, buf->dmas[0].sg_size, buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma); fail: free_buffer(vq, buf); @@ -553,7 +552,7 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev) active = pcdev->active; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->soc_host.dev, "%s (channel=%d) ddadr=%08x\n", __func__, + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s (channel=%d) ddadr=%08x\n", __func__, i, active->dmas[i].sg_dma); DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma; DCSR(pcdev->dma_chans[i]) = DCSR_RUN; @@ -565,7 +564,7 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev) int i; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->soc_host.dev, "%s (channel=%d)\n", __func__, i); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s (channel=%d)\n", __func__, i); DCSR(pcdev->dma_chans[i]) = 0; } } @@ -601,7 +600,7 @@ static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev) { unsigned long cicr0, cifr; - dev_dbg(pcdev->soc_host.dev, "%s\n", __func__); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__); /* Reset the FIFOs */ cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; __raw_writel(cifr, pcdev->base + CIFR); @@ -621,7 +620,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev) __raw_writel(cicr0, pcdev->base + CICR0); pcdev->active = NULL; - dev_dbg(pcdev->soc_host.dev, "%s\n", __func__); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__); } /* Called under spinlock_irqsave(&pcdev->lock, ...) */ @@ -686,7 +685,8 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, do_gettimeofday(&vb->ts); vb->field_count++; wake_up(&vb->done); - dev_dbg(pcdev->soc_host.dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s dequeud buffer (vb=0x%p)\n", + __func__, vb); if (list_empty(&pcdev->capture)) { pxa_camera_stop_capture(pcdev); @@ -722,7 +722,8 @@ static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev) for (i = 0; i < pcdev->channels; i++) if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP) is_dma_stopped = 0; - dev_dbg(pcdev->soc_host.dev, "%s : top queued buffer=%p, dma_stopped=%d\n", + dev_dbg(pcdev->soc_host.v4l2_dev.dev, + "%s : top queued buffer=%p, dma_stopped=%d\n", __func__, pcdev->active, is_dma_stopped); if (pcdev->active && is_dma_stopped) pxa_camera_start_capture(pcdev); @@ -731,6 +732,7 @@ static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev) static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, enum pxa_camera_active_dma act_dma) { + struct device *dev = pcdev->soc_host.v4l2_dev.dev; struct pxa_buffer *buf; unsigned long flags; u32 status, camera_status, overrun; @@ -747,13 +749,13 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, overrun |= CISR_IFO_1 | CISR_IFO_2; if (status & DCSR_BUSERR) { - dev_err(pcdev->soc_host.dev, "DMA Bus Error IRQ!\n"); + dev_err(dev, "DMA Bus Error IRQ!\n"); goto out; } if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) { - dev_err(pcdev->soc_host.dev, "Unknown DMA IRQ source, " - "status: 0x%08x\n", status); + dev_err(dev, "Unknown DMA IRQ source, status: 0x%08x\n", + status); goto out; } @@ -776,7 +778,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, buf = container_of(vb, struct pxa_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(pcdev->soc_host.dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n", + dev_dbg(dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n", __func__, channel, status & DCSR_STARTINTR ? "SOF " : "", status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel)); @@ -787,7 +789,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, */ if (camera_status & overrun && !list_is_last(pcdev->capture.next, &pcdev->capture)) { - dev_dbg(pcdev->soc_host.dev, "FIFO overrun! CISR: %x\n", + dev_dbg(dev, "FIFO overrun! CISR: %x\n", camera_status); pxa_camera_stop_capture(pcdev); pxa_camera_start_capture(pcdev); @@ -846,6 +848,7 @@ static u32 mclk_get_divisor(struct platform_device *pdev, struct pxa_camera_dev *pcdev) { unsigned long mclk = pcdev->mclk; + struct device *dev = pcdev->soc_host.v4l2_dev.dev; u32 div; unsigned long lcdclk; @@ -855,7 +858,7 @@ static u32 mclk_get_divisor(struct platform_device *pdev, /* mclk <= ciclk / 4 (27.4.2) */ if (mclk > lcdclk / 4) { mclk = lcdclk / 4; - dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk); + dev_warn(dev, "Limiting master clock to %lu\n", mclk); } /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */ @@ -865,7 +868,7 @@ static u32 mclk_get_divisor(struct platform_device *pdev, if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) pcdev->mclk = lcdclk / (2 * (div + 1)); - dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n", + dev_dbg(dev, "LCD clock %luHz, target freq %luHz, divisor %u\n", lcdclk, mclk, div); return div; @@ -883,14 +886,15 @@ static void recalculate_fifo_timeout(struct pxa_camera_dev *pcdev, static void pxa_camera_activate(struct pxa_camera_dev *pcdev) { struct pxacamera_platform_data *pdata = pcdev->pdata; + struct device *dev = pcdev->soc_host.v4l2_dev.dev; u32 cicr4 = 0; - dev_dbg(pcdev->soc_host.dev, "Registered platform device at %p data %p\n", + dev_dbg(dev, "Registered platform device at %p data %p\n", pcdev, pdata); if (pdata && pdata->init) { - dev_dbg(pcdev->soc_host.dev, "%s: Init gpios\n", __func__); - pdata->init(pcdev->soc_host.dev); + dev_dbg(dev, "%s: Init gpios\n", __func__); + pdata->init(dev); } /* disable all interrupts */ @@ -932,7 +936,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) struct videobuf_buffer *vb; status = __raw_readl(pcdev->base + CISR); - dev_dbg(pcdev->soc_host.dev, "Camera interrupt status 0x%lx\n", status); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Camera interrupt status 0x%lx\n", status); if (!status) return IRQ_NONE; @@ -964,17 +968,11 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; - int ret; - if (pcdev->icd) { - ret = -EBUSY; - goto ebusy; - } + if (pcdev->icd) + return -EBUSY; pxa_camera_activate(pcdev); - ret = icd->ops->init(icd); - if (ret < 0) - goto einit; pcdev->icd = icd; @@ -982,11 +980,6 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) icd->devnum); return 0; - -einit: - pxa_camera_deactivate(pcdev); -ebusy: - return ret; } /* Called with .video_lock held */ @@ -1008,8 +1001,6 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) DCSR(pcdev->dma_chans[1]) = 0; DCSR(pcdev->dma_chans[2]) = 0; - icd->ops->release(icd); - pxa_camera_deactivate(pcdev); pcdev->icd = NULL; @@ -1265,7 +1256,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->v4l2_dev.dev, "Providing format %s using %s\n", pxa_camera_formats[0].name, icd->formats[idx].name); } @@ -1280,7 +1271,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->dev, "Providing format %s packed\n", + dev_dbg(ici->v4l2_dev.dev, "Providing format %s packed\n", icd->formats[idx].name); } break; @@ -1292,7 +1283,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->dev, + dev_dbg(ici->v4l2_dev.dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -1321,11 +1312,11 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, icd->sense = NULL; if (ret < 0) { - dev_warn(ici->dev, "Failed to crop to %ux%u@%u:%u\n", + dev_warn(ici->v4l2_dev.dev, "Failed to crop to %ux%u@%u:%u\n", rect->width, rect->height, rect->left, rect->top); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(ici->dev, + dev_err(ici->v4l2_dev.dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1353,7 +1344,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat); + dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -1364,16 +1355,16 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, icd->sense = &sense; cam_f.fmt.pix.pixelformat = cam_fmt->fourcc; - ret = icd->ops->set_fmt(icd, &cam_f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); icd->sense = NULL; if (ret < 0) { - dev_warn(ici->dev, "Failed to configure for format %x\n", + dev_warn(ici->v4l2_dev.dev, "Failed to configure for format %x\n", pix->pixelformat); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(ici->dev, + dev_err(ici->v4l2_dev.dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1401,7 +1392,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -1422,7 +1413,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, /* camera has to see its format, but the user the original one */ pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = icd->ops->try_fmt(icd, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); pix->pixelformat = xlate->host_fmt->fourcc; field = pix->field; @@ -1658,7 +1649,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME; pcdev->soc_host.ops = &pxa_soc_camera_host_ops; pcdev->soc_host.priv = pcdev; - pcdev->soc_host.dev = &pdev->dev; + pcdev->soc_host.v4l2_dev.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; err = soc_camera_host_register(&pcdev->soc_host); diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index f8e4b5481..f1ab7b690 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -349,10 +349,9 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - int ret = -EBUSY; if (pcdev->icd) - goto err; + return -EBUSY; dev_info(&icd->dev, "SuperH Mobile CEU driver attached to camera %d\n", @@ -360,19 +359,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) clk_enable(pcdev->clk); - ret = icd->ops->init(icd); - if (ret) { - clk_disable(pcdev->clk); - goto err; - } - ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ while (ceu_read(pcdev, CSTSR) & 1) msleep(1); pcdev->icd = icd; -err: - return ret; + + return 0; } /* Called with .video_lock held */ @@ -398,8 +391,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) } spin_unlock_irqrestore(&pcdev->lock, flags); - icd->ops->release(icd); - clk_disable(pcdev->clk); dev_info(&icd->dev, @@ -616,7 +607,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->dev, "Providing format %s using %s\n", + dev_dbg(ici->v4l2_dev.dev, "Providing format %s using %s\n", sh_mobile_ceu_formats[k].name, icd->formats[idx].name); } @@ -629,7 +620,7 @@ add_single_format: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->dev, + dev_dbg(ici->v4l2_dev.dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -651,18 +642,17 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct sh_mobile_ceu_dev *pcdev = ici->priv; __u32 pixfmt = f->fmt.pix.pixelformat; const struct soc_camera_format_xlate *xlate; - struct v4l2_format cam_f = *f; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); return -EINVAL; } - cam_f.fmt.pix.pixelformat = xlate->cam_fmt->fourcc; - ret = icd->ops->set_fmt(icd, &cam_f); - + f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc; + ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_fmt, f); + f->fmt.pix.pixelformat = pixfmt; if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; @@ -683,7 +673,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->dev, "Format %x not found\n", pixfmt); + dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -696,8 +686,11 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, DIV_ROUND_UP(xlate->host_fmt->depth, 8); f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc; + /* limit to sensor capabilities */ - ret = icd->ops->try_fmt(icd, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, try_fmt, f); + f->fmt.pix.pixelformat = pixfmt; if (ret < 0) return ret; @@ -773,7 +766,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, videobuf_queue_dma_contig_init(q, &sh_mobile_ceu_videobuf_ops, - ici->dev, &pcdev->lock, + ici->v4l2_dev.dev, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, pcdev->is_interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE, @@ -796,7 +789,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .init_videobuf = sh_mobile_ceu_init_videobuf, }; -static int sh_mobile_ceu_probe(struct platform_device *pdev) +static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) { struct sh_mobile_ceu_dev *pcdev; struct resource *res; @@ -874,7 +867,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) } pcdev->ici.priv = pcdev; - pcdev->ici.dev = &pdev->dev; + pcdev->ici.v4l2_dev.dev = &pdev->dev; pcdev->ici.nr = pdev->id; pcdev->ici.drv_name = dev_name(&pdev->dev); pcdev->ici.ops = &sh_mobile_ceu_host_ops; @@ -900,7 +893,7 @@ exit: return err; } -static int sh_mobile_ceu_remove(struct platform_device *pdev) +static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev) { struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); struct sh_mobile_ceu_dev *pcdev = container_of(soc_host, @@ -921,7 +914,7 @@ static struct platform_driver sh_mobile_ceu_driver = { .name = "sh_mobile_ceu", }, .probe = sh_mobile_ceu_probe, - .remove = sh_mobile_ceu_remove, + .remove = __exit_p(sh_mobile_ceu_remove), }; static int __init sh_mobile_ceu_init(void) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index f248ae27f..e759400cc 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -171,8 +171,6 @@ static int soc_camera_reqbufs(struct file *file, void *priv, WARN_ON(priv != file->private_data); - dev_dbg(&icd->dev, "%s: %d\n", __func__, p->memory); - ret = videobuf_reqbufs(&icf->vb_vidq, p); if (ret < 0) return ret; @@ -286,7 +284,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, return ret; } else if (!icd->current_fmt || icd->current_fmt->fourcc != pix->pixelformat) { - dev_err(ici->dev, + dev_err(ici->v4l2_dev.dev, "Host driver hasn't set up current format correctly!\n"); return -EINVAL; } @@ -309,20 +307,13 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, static int soc_camera_open(struct file *file) { - struct video_device *vdev; - struct soc_camera_device *icd; + struct video_device *vdev = video_devdata(file); + struct soc_camera_device *icd = container_of(vdev->parent, struct soc_camera_device, dev); + struct soc_camera_link *icl = to_soc_camera_link(icd); struct soc_camera_host *ici; struct soc_camera_file *icf; int ret; - /* - * It is safe to dereference these pointers now as long as a user has - * the video device open - we are protected by the held cdev reference. - */ - - vdev = video_devdata(file); - icd = container_of(vdev->parent, struct soc_camera_device, dev); - if (!icd->ops) /* No device driver attached */ return -ENODEV; @@ -333,12 +324,6 @@ static int soc_camera_open(struct file *file) if (!icf) return -ENOMEM; - if (!try_module_get(icd->ops->owner)) { - dev_err(&icd->dev, "Couldn't lock sensor driver.\n"); - ret = -EINVAL; - goto emgd; - } - if (!try_module_get(ici->ops->owner)) { dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); ret = -EINVAL; @@ -367,47 +352,65 @@ static int soc_camera_open(struct file *file) if (ret < 0) goto eiufmt; - dev_dbg(&icd->dev, "Using fmt %x\n", icd->current_fmt->fourcc); - f.fmt.pix.pixelformat = icd->current_fmt->fourcc; f.fmt.pix.colorspace = icd->current_fmt->colorspace; + if (icl->power) { + ret = icl->power(icd->pdev, 1); + if (ret < 0) + goto epower; + } + + /* The camera could have been already on, try to reset */ + if (icl->reset) + icl->reset(icd->pdev); + ret = ici->ops->add(icd); if (ret < 0) { dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); goto eiciadd; } + if (icd->ops->init) { + ret = icd->ops->init(icd); + if (ret < 0) + goto einit; + } + /* Try to configure with default parameters */ ret = soc_camera_set_fmt(icf, &f); if (ret < 0) goto esfmt; } - mutex_unlock(&icd->video_lock); - file->private_data = icf; dev_dbg(&icd->dev, "camera device open\n"); ici->ops->init_videobuf(&icf->vb_vidq, icd); + mutex_unlock(&icd->video_lock); + return 0; /* - * First three errors are entered with the .video_lock held + * First five errors are entered with the .video_lock held * and use_count == 1 */ esfmt: + if (icd->ops->release) + icd->ops->release(icd); +einit: ici->ops->remove(icd); eiciadd: + if (icl->power) + icl->power(icd->pdev, 0); +epower: soc_camera_free_user_formats(icd); eiufmt: icd->use_count--; mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); emgi: - module_put(icd->ops->owner); -emgd: vfree(icf); return ret; } @@ -422,13 +425,18 @@ static int soc_camera_close(struct file *file) mutex_lock(&icd->video_lock); icd->use_count--; if (!icd->use_count) { + struct soc_camera_link *icl = to_soc_camera_link(icd); + + if (icd->ops->release) + icd->ops->release(icd); ici->ops->remove(icd); + if (icl->power) + icl->power(icd->pdev, 0); soc_camera_free_user_formats(icd); } mutex_unlock(&icd->video_lock); - module_put(icd->ops->owner); module_put(ici->ops->owner); vfree(icf); @@ -576,18 +584,17 @@ static int soc_camera_streamon(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int ret; WARN_ON(priv != file->private_data); - dev_dbg(&icd->dev, "%s\n", __func__); - if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; mutex_lock(&icd->video_lock); - icd->ops->start_capture(icd); + v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_stream, 1); /* This calls buf_queue from host driver's videobuf_queue_ops */ ret = videobuf_streamon(&icf->vb_vidq); @@ -602,11 +609,10 @@ static int soc_camera_streamoff(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); WARN_ON(priv != file->private_data); - dev_dbg(&icd->dev, "%s\n", __func__); - if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -616,7 +622,7 @@ static int soc_camera_streamoff(struct file *file, void *priv, * remaining buffers. When the last buffer is freed, stop capture */ videobuf_streamoff(&icf->vb_vidq); - icd->ops->stop_capture(icd); + v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_stream, 0); mutex_unlock(&icd->video_lock); @@ -650,6 +656,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); WARN_ON(priv != file->private_data); @@ -666,9 +673,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, return 0; } - if (icd->ops->get_control) - return icd->ops->get_control(icd, ctrl); - return -EINVAL; + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_ctrl, ctrl); } static int soc_camera_s_ctrl(struct file *file, void *priv, @@ -676,12 +681,11 @@ static int soc_camera_s_ctrl(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); WARN_ON(priv != file->private_data); - if (icd->ops->set_control) - return icd->ops->set_control(icd, ctrl); - return -EINVAL; + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_ctrl, ctrl); } static int soc_camera_cropcap(struct file *file, void *fh, @@ -752,11 +756,9 @@ static int soc_camera_g_chip_ident(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - if (!icd->ops->get_chip_id) - return -EINVAL; - - return icd->ops->get_chip_id(icd, id); + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_chip_ident, id); } #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -765,11 +767,9 @@ static int soc_camera_g_register(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - if (!icd->ops->get_register) - return -EINVAL; - - return icd->ops->get_register(icd, reg); + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_register, reg); } static int soc_camera_s_register(struct file *file, void *fh, @@ -777,11 +777,9 @@ static int soc_camera_s_register(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - if (!icd->ops->set_register) - return -EINVAL; - - return icd->ops->set_register(icd, reg); + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_register, reg); } #endif @@ -795,7 +793,7 @@ static void scan_add_host(struct soc_camera_host *ici) list_for_each_entry(icd, &devices, list) { if (icd->iface == ici->nr) { int ret; - icd->dev.parent = ici->dev; + icd->dev.parent = ici->v4l2_dev.dev; dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum); ret = device_register(&icd->dev); @@ -815,7 +813,9 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, struct soc_camera_link *icl) { struct i2c_client *client; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); + struct v4l2_subdev *subdev; int ret; if (!adap) { @@ -827,17 +827,16 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, icl->board_info->platform_data = icd; - client = i2c_new_device(adap, icl->board_info); - if (!client) { + subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, + icl->module_name, icl->board_info, NULL); + if (!subdev) { ret = -ENOMEM; goto ei2cnd; } - /* - * We set icd drvdata at two locations - here and in - * soc_camera_video_start(). Depending on the module loading / - * initialisation order one of these locations will be entered first - */ + subdev->grp_id = (__u32)icd; + client = subdev->priv; + /* Use to_i2c_client(dev) to recover the i2c client */ dev_set_drvdata(&icd->dev, &client->dev); @@ -853,6 +852,7 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd) struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); dev_set_drvdata(&icd->dev, NULL); + v4l2_device_unregister_subdev(i2c_get_clientdata(client)); i2c_unregister_device(client); i2c_put_adapter(client->adapter); } @@ -861,16 +861,37 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd) #define soc_camera_free_i2c(icd) do {} while (0) #endif +static int soc_camera_video_start(struct soc_camera_device *icd); static int video_dev_create(struct soc_camera_device *icd); /* Called during host-driver probe */ static int soc_camera_probe(struct device *dev) { struct soc_camera_device *icd = to_soc_camera_dev(dev); + struct soc_camera_host *ici = to_soc_camera_host(dev->parent); struct soc_camera_link *icl = to_soc_camera_link(icd); + struct device *control = NULL; int ret; dev_info(dev, "Probing %s\n", dev_name(dev)); + if (icl->power) { + ret = icl->power(icd->pdev, 1); + if (ret < 0) { + dev_err(dev, + "Platform failed to power-on the camera.\n"); + goto epower; + } + } + + /* The camera could have been already on, try to reset */ + if (icl->reset) + icl->reset(icd->pdev); + + ret = ici->ops->add(icd); + if (ret < 0) + goto eadd; + + /* Must have icd->vdev before registering the device */ ret = video_dev_create(icd); if (ret < 0) goto evdc; @@ -884,34 +905,61 @@ static int soc_camera_probe(struct device *dev) ret = -EINVAL; goto eadddev; } else { + if (icl->module_name) + ret = request_module(icl->module_name); + ret = icl->add_device(icl, &icd->dev); if (ret < 0) goto eadddev; - } - ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, icd->vdev->minor); - if (ret < 0) { - dev_err(&icd->dev, "video_register_device failed: %d\n", ret); - goto evidregd; + /* FIXME: this is racy, have to use driver-binding notification */ + control = to_soc_camera_control(icd); + if (!control || !control->driver || + !try_module_get(control->driver->owner)) { + icl->del_device(icl); + goto enodrv; + } } + /* ..._video_start() will create a device node, so we have to protect */ + mutex_lock(&icd->video_lock); + + ret = soc_camera_video_start(icd); + if (ret < 0) + goto evidstart; + /* Do we have to sysfs_remove_link() before device_unregister()? */ if (to_soc_camera_control(icd) && sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj, "control")) dev_warn(&icd->dev, "Failed creating the control symlink\n"); + ici->ops->remove(icd); + + if (icl->power) + icl->power(icd->pdev, 0); + + mutex_unlock(&icd->video_lock); return 0; -evidregd: - if (icl->board_info) +evidstart: + mutex_unlock(&icd->video_lock); + if (icl->board_info) { soc_camera_free_i2c(icd); - else + } else { icl->del_device(icl); + module_put(control->driver->owner); + } +enodrv: eadddev: video_device_release(icd->vdev); evdc: + ici->ops->remove(icd); +eadd: + if (icl->power) + icl->power(icd->pdev, 0); +epower: return ret; } @@ -932,10 +980,16 @@ static int soc_camera_remove(struct device *dev) mutex_unlock(&icd->video_lock); } - if (icl->board_info) + if (icl->board_info) { soc_camera_free_i2c(icd); - else - icl->del_device(icl); + } else { + struct device_driver *drv = to_soc_camera_control(icd) ? + to_soc_camera_control(icd)->driver : NULL; + if (drv) { + icl->del_device(icl); + module_put(drv->owner); + } + } return 0; } @@ -985,6 +1039,7 @@ static void dummy_release(struct device *dev) int soc_camera_host_register(struct soc_camera_host *ici) { struct soc_camera_host *ix; + int ret; if (!ici || !ici->ops || !ici->ops->try_fmt || @@ -997,18 +1052,20 @@ int soc_camera_host_register(struct soc_camera_host *ici) !ici->ops->add || !ici->ops->remove || !ici->ops->poll || - !ici->dev) + !ici->v4l2_dev.dev) return -EINVAL; mutex_lock(&list_lock); list_for_each_entry(ix, &hosts, list) { if (ix->nr == ici->nr) { - mutex_unlock(&list_lock); - return -EBUSY; + ret = -EBUSY; + goto edevreg; } } - dev_set_drvdata(ici->dev, ici); + ret = v4l2_device_register(ici->v4l2_dev.dev, &ici->v4l2_dev); + if (ret < 0) + goto edevreg; list_add_tail(&ici->list, &hosts); mutex_unlock(&list_lock); @@ -1016,6 +1073,10 @@ int soc_camera_host_register(struct soc_camera_host *ici) scan_add_host(ici); return 0; + +edevreg: + mutex_unlock(&list_lock); + return ret; } EXPORT_SYMBOL(soc_camera_host_register); @@ -1029,7 +1090,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) list_del(&ici->list); list_for_each_entry(icd, &devices, list) { - if (icd->dev.parent == ici->dev) { + if (icd->iface == ici->nr) { /* The bus->remove will be called */ device_unregister(&icd->dev); /* Not before device_unregister(), .remove @@ -1044,7 +1105,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) mutex_unlock(&list_lock); - dev_set_drvdata(ici->dev, NULL); + v4l2_device_unregister(&ici->v4l2_dev); } EXPORT_SYMBOL(soc_camera_host_unregister); @@ -1124,7 +1185,6 @@ static int video_dev_create(struct soc_camera_device *icd) if (!vdev) return -ENOMEM; - dev_dbg(ici->dev, "Allocated video_device %p\n", vdev); strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); @@ -1142,50 +1202,35 @@ static int video_dev_create(struct soc_camera_device *icd) } /* - * Usually called from the struct soc_camera_ops .probe() method, i.e., from - * soc_camera_probe() above with .video_lock held + * Called from soc_camera_probe() above (with .video_lock held???) */ -int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev) +static int soc_camera_video_start(struct soc_camera_device *icd) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); const struct v4l2_queryctrl *qctrl; + int ret; if (!icd->dev.parent) return -ENODEV; if (!icd->ops || - !icd->ops->init || - !icd->ops->release || - !icd->ops->start_capture || - !icd->ops->stop_capture || - !icd->ops->set_fmt || - !icd->ops->try_fmt || !icd->ops->query_bus_param || !icd->ops->set_bus_param) return -EINVAL; - /* See comment in soc_camera_probe() */ - dev_set_drvdata(&icd->dev, dev); + ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, + icd->vdev->minor); + if (ret < 0) { + dev_err(&icd->dev, "video_register_device failed: %d\n", ret); + return ret; + } qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; - return ici->ops->add(icd); -} -EXPORT_SYMBOL(soc_camera_video_start); - -/* Called from client .remove() methods with .video_lock held */ -void soc_camera_video_stop(struct soc_camera_device *icd) -{ - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - - dev_dbg(&icd->dev, "%s\n", __func__); - - ici->ops->remove(icd); + return 0; } -EXPORT_SYMBOL(soc_camera_video_stop); static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) { @@ -1201,6 +1246,7 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) return -ENOMEM; icd->iface = icl->bus_id; + icd->pdev = &pdev->dev; platform_set_drvdata(pdev, icd); icd->dev.platform_data = icl; diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index d84c134f8..8168cf470 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -16,11 +16,12 @@ #include #include #include -#include +#include #include #include struct soc_camera_platform_priv { + struct v4l2_subdev subdev; struct soc_camera_data_format format; }; @@ -31,36 +32,10 @@ soc_camera_platform_get_info(struct soc_camera_device *icd) return pdev->dev.platform_data; } -static int soc_camera_platform_init(struct soc_camera_device *icd) +static int soc_camera_platform_s_stream(struct v4l2_subdev *sd, int enable) { - struct soc_camera_link *icl = to_soc_camera_link(icd); - - if (icl->power) - icl->power(dev_get_drvdata(&icd->dev), 1); - - return 0; -} - -static int soc_camera_platform_release(struct soc_camera_device *icd) -{ - struct soc_camera_link *icl = to_soc_camera_link(icd); - - if (icl->power) - icl->power(dev_get_drvdata(&icd->dev), 0); - - return 0; -} - -static int soc_camera_platform_start_capture(struct soc_camera_device *icd) -{ - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); - return p->set_capture(p, 1); -} - -static int soc_camera_platform_stop_capture(struct soc_camera_device *icd) -{ - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); - return p->set_capture(p, 0); + struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); + return p->set_capture(p, enable); } static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd, @@ -82,16 +57,10 @@ static int soc_camera_platform_set_crop(struct soc_camera_device *icd, return 0; } -static int soc_camera_platform_set_fmt(struct soc_camera_device *icd, +static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { - return 0; -} - -static int soc_camera_platform_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) -{ - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); + struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); struct v4l2_pix_format *pix = &f->fmt.pix; pix->width = p->format.width; @@ -99,12 +68,11 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd, return 0; } -static int soc_camera_platform_video_probe(struct soc_camera_device *icd, - struct platform_device *pdev) +static void soc_camera_platform_video_probe(struct soc_camera_device *icd, + struct platform_device *pdev) { struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); struct soc_camera_platform_info *p = pdev->dev.platform_data; - int ret; priv->format.name = p->format_name; priv->format.depth = p->format_depth; @@ -113,28 +81,29 @@ static int soc_camera_platform_video_probe(struct soc_camera_device *icd, icd->formats = &priv->format; icd->num_formats = 1; - - /* ..._video_start() does dev_set_drvdata(&icd->dev, &pdev->dev) */ - ret = soc_camera_video_start(icd, &pdev->dev); - soc_camera_video_stop(icd); - return ret; } +static struct v4l2_subdev_core_ops platform_subdev_core_ops; + +static struct v4l2_subdev_video_ops platform_subdev_video_ops = { + .s_stream = soc_camera_platform_s_stream, + .try_fmt = soc_camera_platform_try_fmt, +}; + +static struct v4l2_subdev_ops platform_subdev_ops = { + .core = &platform_subdev_core_ops, + .video = &platform_subdev_video_ops, +}; + static struct soc_camera_ops soc_camera_platform_ops = { - .owner = THIS_MODULE, - .init = soc_camera_platform_init, - .release = soc_camera_platform_release, - .start_capture = soc_camera_platform_start_capture, - .stop_capture = soc_camera_platform_stop_capture, .set_crop = soc_camera_platform_set_crop, - .set_fmt = soc_camera_platform_set_fmt, - .try_fmt = soc_camera_platform_try_fmt, .set_bus_param = soc_camera_platform_set_bus_param, .query_bus_param = soc_camera_platform_query_bus_param, }; static int soc_camera_platform_probe(struct platform_device *pdev) { + struct soc_camera_host *ici; struct soc_camera_platform_priv *priv; struct soc_camera_platform_info *p = pdev->dev.platform_data; struct soc_camera_device *icd; @@ -143,35 +112,48 @@ static int soc_camera_platform_probe(struct platform_device *pdev) if (!p) return -EINVAL; + if (!p->dev) { + dev_err(&pdev->dev, + "Platform has not set soc_camera_device pointer!\n"); + return -EINVAL; + } + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - platform_set_drvdata(pdev, priv); - icd = to_soc_camera_dev(p->dev); - if (!icd) - goto enoicd; - icd->ops = &soc_camera_platform_ops; + platform_set_drvdata(pdev, priv); dev_set_drvdata(&icd->dev, &pdev->dev); + icd->width_min = 0; icd->width_max = p->format.width; icd->height_min = 0; icd->height_max = p->format.height; icd->y_skip_top = 0; + icd->ops = &soc_camera_platform_ops; - ret = soc_camera_platform_video_probe(icd, pdev); - if (ret) { - icd->ops = NULL; - kfree(priv); - } + ici = to_soc_camera_host(icd->dev.parent); + + soc_camera_platform_video_probe(icd, pdev); + + v4l2_subdev_init(&priv->subdev, &platform_subdev_ops); + v4l2_set_subdevdata(&priv->subdev, p); + priv->subdev.grp_id = (__u32)icd; + strncpy(priv->subdev.name, dev_name(&pdev->dev), V4L2_SUBDEV_NAME_SIZE); + + ret = v4l2_device_register_subdev(&ici->v4l2_dev, &priv->subdev); + if (ret) + goto evdrs; return ret; -enoicd: +evdrs: + icd->ops = NULL; + platform_set_drvdata(pdev, NULL); kfree(priv); - return -EINVAL; + return ret; } static int soc_camera_platform_remove(struct platform_device *pdev) @@ -180,7 +162,9 @@ static int soc_camera_platform_remove(struct platform_device *pdev) struct soc_camera_platform_info *p = pdev->dev.platform_data; struct soc_camera_device *icd = to_soc_camera_dev(p->dev); + v4l2_device_unregister_subdev(&priv->subdev); icd->ops = NULL; + platform_set_drvdata(pdev, NULL); kfree(priv); return 0; } @@ -188,6 +172,7 @@ static int soc_camera_platform_remove(struct platform_device *pdev) static struct platform_driver soc_camera_platform_driver = { .driver = { .name = "soc_camera_platform", + .owner = THIS_MODULE, }, .probe = soc_camera_platform_probe, .remove = soc_camera_platform_remove, diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 432dd3edc..61dc1b812 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -223,6 +223,7 @@ struct tw9910_hsync_ctrl { }; struct tw9910_priv { + struct v4l2_subdev subdev; struct tw9910_video_info *info; const struct tw9910_scale_ctrl *scale; }; @@ -354,6 +355,11 @@ static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = { /* * general function */ +static struct tw9910_priv *to_tw9910(const struct i2c_client *client) +{ + return container_of(i2c_get_clientdata(client), struct tw9910_priv, subdev); +} + static int tw9910_set_scale(struct i2c_client *client, const struct tw9910_scale_ctrl *scale) { @@ -507,47 +513,20 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height) /* * soc_camera_ops function */ -static int tw9910_init(struct soc_camera_device *icd) +static int tw9910_s_stream(struct v4l2_subdev *sd, int enable) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - int ret = 0; + struct i2c_client *client = sd->priv; + struct tw9910_priv *priv = to_tw9910(client); - if (icl->power) { - ret = icl->power(&client->dev, 1); - if (ret < 0) - return ret; - } - - if (icl->reset) - ret = icl->reset(&client->dev); - - return ret; -} - -static int tw9910_release(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct soc_camera_link *icl = to_soc_camera_link(icd); - int ret = 0; - - if (icl->power) - ret = icl->power(&client->dev, 0); - - return ret; -} - -static int tw9910_start_capture(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct tw9910_priv *priv = i2c_get_clientdata(client); + if (!enable) + return 0; if (!priv->scale) { - dev_err(&icd->dev, "norm select error\n"); + dev_err(&client->dev, "norm select error\n"); return -EPERM; } - dev_dbg(&icd->dev, "%s %dx%d\n", + dev_dbg(&client->dev, "%s %dx%d\n", priv->scale->name, priv->scale->width, priv->scale->height); @@ -555,11 +534,6 @@ static int tw9910_start_capture(struct soc_camera_device *icd) return 0; } -static int tw9910_stop_capture(struct soc_camera_device *icd) -{ - return 0; -} - static int tw9910_set_bus_param(struct soc_camera_device *icd, unsigned long flags) { @@ -569,7 +543,7 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd, static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct tw9910_priv *priv = i2c_get_clientdata(client); + struct tw9910_priv *priv = to_tw9910(client); struct soc_camera_link *icl = to_soc_camera_link(icd); unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | @@ -578,21 +552,11 @@ static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } -static int tw9910_get_chip_id(struct soc_camera_device *icd, - struct v4l2_dbg_chip_ident *id) -{ - id->ident = V4L2_IDENT_TW9910; - id->revision = 0; - - return 0; -} - -static int tw9910_set_std(struct soc_camera_device *icd, - v4l2_std_id *a) +static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) { int ret = -EINVAL; - if (*a & (V4L2_STD_NTSC | V4L2_STD_PAL)) + if (norm & (V4L2_STD_NTSC | V4L2_STD_PAL)) ret = 0; return ret; @@ -608,11 +572,20 @@ static int tw9910_enum_input(struct soc_camera_device *icd, return 0; } +static int tw9910_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *id) +{ + id->ident = V4L2_IDENT_TW9910; + id->revision = 0; + + return 0; +} + #ifdef CONFIG_VIDEO_ADV_DEBUG -static int tw9910_get_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int tw9910_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; int ret; if (reg->reg > 0xff) @@ -630,10 +603,10 @@ static int tw9910_get_register(struct soc_camera_device *icd, return 0; } -static int tw9910_set_register(struct soc_camera_device *icd, - struct v4l2_dbg_register *reg) +static int tw9910_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct i2c_client *client = sd->priv; if (reg->reg > 0xff || reg->val > 0xff) @@ -647,7 +620,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct tw9910_priv *priv = i2c_get_clientdata(client); + struct tw9910_priv *priv = to_tw9910(client); int ret = -EINVAL; u8 val; @@ -736,9 +709,10 @@ tw9910_set_fmt_error: return ret; } -static int tw9910_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { .left = icd->x_current, @@ -761,16 +735,17 @@ static int tw9910_set_fmt(struct soc_camera_device *icd, return tw9910_set_crop(icd, &rect); } -static int tw9910_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) +static int tw9910_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; const struct tw9910_scale_ctrl *scale; if (V4L2_FIELD_ANY == pix->field) { pix->field = V4L2_FIELD_INTERLACED; } else if (V4L2_FIELD_INTERLACED != pix->field) { - dev_err(&icd->dev, "Field type invalid.\n"); + dev_err(&client->dev, "Field type invalid.\n"); return -EINVAL; } @@ -790,9 +765,8 @@ static int tw9910_try_fmt(struct soc_camera_device *icd, static int tw9910_video_probe(struct soc_camera_device *icd, struct i2c_client *client) { - struct tw9910_priv *priv = i2c_get_clientdata(client); + struct tw9910_priv *priv = to_tw9910(client); s32 val; - int ret; /* * We must have a parent by now. And it cannot be a wrong one. @@ -814,18 +788,11 @@ static int tw9910_video_probe(struct soc_camera_device *icd, icd->formats = tw9910_color_fmt; icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); - /* Switch master clock on */ - ret = soc_camera_video_start(icd, &client->dev); - if (ret) - return ret; - /* * check and show Product ID */ val = i2c_smbus_read_byte_data(client, ID); - soc_camera_video_stop(icd); - if (0x0B != GET_ID(val) || 0x00 != GET_ReV(val)) { dev_err(&icd->dev, @@ -839,29 +806,36 @@ static int tw9910_video_probe(struct soc_camera_device *icd, icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; icd->vdev->current_norm = V4L2_STD_NTSC; - return ret; + return 0; } static struct soc_camera_ops tw9910_ops = { - .owner = THIS_MODULE, - .init = tw9910_init, - .release = tw9910_release, - .start_capture = tw9910_start_capture, - .stop_capture = tw9910_stop_capture, .set_crop = tw9910_set_crop, - .set_fmt = tw9910_set_fmt, - .try_fmt = tw9910_try_fmt, .set_bus_param = tw9910_set_bus_param, .query_bus_param = tw9910_query_bus_param, - .get_chip_id = tw9910_get_chip_id, - .set_std = tw9910_set_std, .enum_input = tw9910_enum_input, +}; + +static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { + .g_chip_ident = tw9910_g_chip_ident, + .s_std = tw9910_s_std, #ifdef CONFIG_VIDEO_ADV_DEBUG - .get_register = tw9910_get_register, - .set_register = tw9910_set_register, + .g_register = tw9910_g_register, + .s_register = tw9910_s_register, #endif }; +static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { + .s_stream = tw9910_s_stream, + .s_fmt = tw9910_s_fmt, + .try_fmt = tw9910_try_fmt, +}; + +static struct v4l2_subdev_ops tw9910_subdev_ops = { + .core = &tw9910_subdev_core_ops, + .video = &tw9910_subdev_video_ops, +}; + /* * i2c_driver function */ @@ -906,7 +880,8 @@ static int tw9910_probe(struct i2c_client *client, return -ENOMEM; priv->info = info; - i2c_set_clientdata(client, priv); + + v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); icd->ops = &tw9910_ops; icd->iface = info->link.bus_id; @@ -946,7 +921,7 @@ static int tw9910_probe(struct i2c_client *client, static int tw9910_remove(struct i2c_client *client) { - struct tw9910_priv *priv = i2c_get_clientdata(client); + struct tw9910_priv *priv = to_tw9910(client); struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index d8b425612..3bc5b6b20 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -16,10 +16,12 @@ #include #include #include +#include struct soc_camera_device { struct list_head list; struct device dev; + struct device *pdev; /* Platform device */ unsigned short width; /* Current window */ unsigned short height; /* sizes */ unsigned short x_min; /* Camera capabilities */ @@ -45,7 +47,6 @@ struct soc_camera_device { struct soc_camera_format_xlate *user_formats; int num_user_formats; enum v4l2_field field; /* Preserve field over close() */ - struct module *owner; void *host_priv; /* Per-device host private data */ /* soc_camera.c private count. Only accessed with .video_lock held */ int use_count; @@ -58,8 +59,8 @@ struct soc_camera_file { }; struct soc_camera_host { + struct v4l2_device v4l2_dev; struct list_head list; - struct device *dev; unsigned char nr; /* Host number */ void *priv; const char *drv_name; @@ -127,7 +128,9 @@ static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) static inline struct soc_camera_host *to_soc_camera_host(struct device *dev) { - return dev_get_drvdata(dev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); + + return container_of(v4l2_dev, struct soc_camera_host, v4l2_dev); } static inline struct soc_camera_link *to_soc_camera_link(struct soc_camera_device *icd) @@ -143,9 +146,6 @@ static inline struct device *to_soc_camera_control(struct soc_camera_device *icd int soc_camera_host_register(struct soc_camera_host *ici); void soc_camera_host_unregister(struct soc_camera_host *ici); -int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev); -void soc_camera_video_stop(struct soc_camera_device *icd); - const struct soc_camera_data_format *soc_camera_format_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc); const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( @@ -176,28 +176,17 @@ struct soc_camera_format_xlate { }; struct soc_camera_ops { - struct module *owner; int (*suspend)(struct soc_camera_device *, pm_message_t state); int (*resume)(struct soc_camera_device *); int (*init)(struct soc_camera_device *); int (*release)(struct soc_camera_device *); - int (*start_capture)(struct soc_camera_device *); - int (*stop_capture)(struct soc_camera_device *); int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *); - int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *); - int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); unsigned long (*query_bus_param)(struct soc_camera_device *); int (*set_bus_param)(struct soc_camera_device *, unsigned long); int (*get_chip_id)(struct soc_camera_device *, struct v4l2_dbg_chip_ident *); int (*set_std)(struct soc_camera_device *, v4l2_std_id *); int (*enum_input)(struct soc_camera_device *, struct v4l2_input *); -#ifdef CONFIG_VIDEO_ADV_DEBUG - int (*get_register)(struct soc_camera_device *, struct v4l2_dbg_register *); - int (*set_register)(struct soc_camera_device *, struct v4l2_dbg_register *); -#endif - int (*get_control)(struct soc_camera_device *, struct v4l2_control *); - int (*set_control)(struct soc_camera_device *, struct v4l2_control *); const struct v4l2_queryctrl *controls; int num_controls; }; -- cgit v1.2.3 From 341bb0182d98a50527cda19a7519e0df95334303 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:44:14 +0200 Subject: V4L2: add a new V4L2_CID_BAND_STOP_FILTER integer control From: Guennadi Liakhovetski Add a new V4L2_CID_BAND_STOP_FILTER integer control, which either switches the band-stop filter off, or sets it to a certain strength. Signed-off-by: Guennadi Liakhovetski Priority: low --- include/linux/videodev2.h | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) --- linux/include/linux/videodev2.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index b61c3b61c..f94613802 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -906,9 +906,10 @@ enum v4l2_colorfx { V4L2_COLORFX_SEPIA = 2, }; #define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32) +#define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) /* last CID + 1 */ -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+33) +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+34) /* MPEG-class control IDs defined by V4L2 */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) -- cgit v1.2.3 From 4e4ce6d0b364f6dcab06b9f80942339fbfef9e0a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:44:14 +0200 Subject: ov772x: implement a band-stop filter support From: Guennadi Liakhovetski The V4L2_CID_BAND_STOP_FILTER control is used to switch the "Banding Filter" on OV772x cameras on and off and to set the minimum AEC value in BDBASE register. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 52 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 50 insertions(+), 2 deletions(-) --- linux/drivers/media/video/ov772x.c | 52 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 4da12e8c4..05e06f5b8 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -403,8 +403,9 @@ struct ov772x_priv { const struct ov772x_color_format *fmt; const struct ov772x_win_size *win; int model; - unsigned int flag_vflip:1; - unsigned int flag_hflip:1; + unsigned short flag_vflip:1; + unsigned short flag_hflip:1; + unsigned short band_filter; /* 256 - BDBASE, 0 if (!COM8[5]) */ }; #define ENDMARKER { 0xff, 0xff } @@ -569,6 +570,15 @@ static const struct v4l2_queryctrl ov772x_controls[] = { .step = 1, .default_value = 0, }, + { + .id = V4L2_CID_BAND_STOP_FILTER, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Band-stop filter", + .minimum = 0, + .maximum = 256, + .step = 1, + .default_value = 0, + }, }; @@ -674,6 +684,9 @@ static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_HFLIP: ctrl->value = priv->flag_hflip; break; + case V4L2_CID_BAND_STOP_FILTER: + ctrl->value = priv->band_filter; + break; } return 0; } @@ -700,6 +713,29 @@ static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) val ^= HFLIP_IMG; ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val); break; + case V4L2_CID_BAND_STOP_FILTER: + if ((unsigned)ctrl->value > 256) + ctrl->value = 256; + if (ctrl->value == priv->band_filter) + break; + if (!ctrl->value) { + /* Switch the filter off, it is on now */ + ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff); + if (!ret) + ret = ov772x_mask_set(client, COM8, + BNDF_ON_OFF, 0); + } else { + /* Switch the filter on, set AEC low limit */ + val = 256 - ctrl->value; + ret = ov772x_mask_set(client, COM8, + BNDF_ON_OFF, BNDF_ON_OFF); + if (!ret) + ret = ov772x_mask_set(client, BDBASE, + 0xff, val); + } + if (!ret) + priv->band_filter = ctrl->value; + break; } return ret; @@ -893,6 +929,18 @@ static int ov772x_set_params(struct i2c_client *client, if (ret < 0) goto ov772x_set_fmt_error; + /* + * set COM8 + */ + if (priv->band_filter) { + ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, 1); + if (!ret) + ret = ov772x_mask_set(client, BDBASE, + 0xff, 256 - priv->band_filter); + if (ret < 0) + goto ov772x_set_fmt_error; + } + return ret; ov772x_set_fmt_error: -- cgit v1.2.3 From ac97b8b24a867c8c2d3dd71d3c3d12b078b8091c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:44:15 +0200 Subject: soc-camera: add support for camera-host controls From: Guennadi Liakhovetski Until now soc-camera only supported client (sensor) controls. This patch enables camera-host drivers to implement their own controls too. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 24 ++++++++++++++++++++++++ include/media/soc_camera.h | 4 ++++ 2 files changed, 28 insertions(+), 0 deletions(-) --- linux/drivers/media/video/soc_camera.c | 24 ++++++++++++++++++++++++ linux/include/media/soc_camera.h | 4 ++++ 2 files changed, 28 insertions(+) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index e759400cc..42e7acd9b 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -634,6 +634,7 @@ static int soc_camera_queryctrl(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int i; WARN_ON(priv != file->private_data); @@ -641,6 +642,15 @@ static int soc_camera_queryctrl(struct file *file, void *priv, if (!qc->id) return -EINVAL; + /* First check host controls */ + for (i = 0; i < ici->ops->num_controls; i++) + if (qc->id == ici->ops->controls[i].id) { + memcpy(qc, &(ici->ops->controls[i]), + sizeof(*qc)); + return 0; + } + + /* Then device controls */ for (i = 0; i < icd->ops->num_controls; i++) if (qc->id == icd->ops->controls[i].id) { memcpy(qc, &(icd->ops->controls[i]), @@ -657,6 +667,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int ret; WARN_ON(priv != file->private_data); @@ -673,6 +684,12 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, return 0; } + if (ici->ops->get_ctrl) { + ret = ici->ops->get_ctrl(icd, ctrl); + if (ret != -ENOIOCTLCMD) + return ret; + } + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_ctrl, ctrl); } @@ -682,9 +699,16 @@ static int soc_camera_s_ctrl(struct file *file, void *priv, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int ret; WARN_ON(priv != file->private_data); + if (ici->ops->set_ctrl) { + ret = ici->ops->set_ctrl(icd, ctrl); + if (ret != -ENOIOCTLCMD) + return ret; + } + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_ctrl, ctrl); } diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 3bc5b6b20..2d116bbbc 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -83,7 +83,11 @@ struct soc_camera_host_ops { int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); int (*set_bus_param)(struct soc_camera_device *, __u32); + int (*get_ctrl)(struct soc_camera_device *, struct v4l2_control *); + int (*set_ctrl)(struct soc_camera_device *, struct v4l2_control *); unsigned int (*poll)(struct file *, poll_table *); + const struct v4l2_queryctrl *controls; + int num_controls; }; #define SOCAM_SENSOR_INVERT_PCLK (1 << 0) -- cgit v1.2.3 From cf579adf1e145c22f0c7178612e4781cc8b089cc Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:44:15 +0200 Subject: sh_mobile_ceu_camera: add a control for the camera low-pass filter From: Guennadi Liakhovetski Use the V4L2_CID_SHARPNESS control to switch SH-mobile camera low-pass filter. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/sh_mobile_ceu_camera.c | 54 +++++++++++++++++++++++++++- 1 files changed, 53 insertions(+), 1 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 54 +++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index f1ab7b690..99ea30896 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -497,7 +497,6 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CAPWR, (height << 16) | width); ceu_write(pcdev, CFLCR, 0); /* no scaling */ ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width); - ceu_write(pcdev, CLFCR, 0); /* no lowpass filter */ /* A few words about byte order (observed in Big Endian mode) * @@ -774,6 +773,55 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, icd); } +static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; + u32 val; + + switch (ctrl->id) { + case V4L2_CID_SHARPNESS: + val = ceu_read(pcdev, CLFCR); + ctrl->value = val ^ 1; + return 0; + } + return -ENOIOCTLCMD; +} + +static int sh_mobile_ceu_set_ctrl(struct soc_camera_device *icd, + struct v4l2_control *ctrl) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; + + switch (ctrl->id) { + case V4L2_CID_SHARPNESS: + switch (icd->current_fmt->fourcc) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + ceu_write(pcdev, CLFCR, !ctrl->value); + return 0; + } + return -EINVAL; + } + return -ENOIOCTLCMD; +} + +static const struct v4l2_queryctrl sh_mobile_ceu_controls[] = { + { + .id = V4L2_CID_SHARPNESS, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Low-pass filter", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, +}; + static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .owner = THIS_MODULE, .add = sh_mobile_ceu_add_device, @@ -782,11 +830,15 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .set_crop = sh_mobile_ceu_set_crop, .set_fmt = sh_mobile_ceu_set_fmt, .try_fmt = sh_mobile_ceu_try_fmt, + .set_ctrl = sh_mobile_ceu_set_ctrl, + .get_ctrl = sh_mobile_ceu_get_ctrl, .reqbufs = sh_mobile_ceu_reqbufs, .poll = sh_mobile_ceu_poll, .querycap = sh_mobile_ceu_querycap, .set_bus_param = sh_mobile_ceu_set_bus_param, .init_videobuf = sh_mobile_ceu_init_videobuf, + .controls = sh_mobile_ceu_controls, + .num_controls = ARRAY_SIZE(sh_mobile_ceu_controls), }; static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) -- cgit v1.2.3 From 67b6fcc4c0404e94f16820566585bb0ff9891b89 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:17 +0200 Subject: soc-camera: use struct v4l2_rect in struct soc_camera_device From: Guennadi Liakhovetski Switch to using struct v4l2_rect in struct soc_camera_device for uniformity and simplicity. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/drivers/media/video/mt9m001.c | 30 ++++++------ linux/drivers/media/video/mt9m111.c | 20 ++++---- linux/drivers/media/video/mt9t031.c | 49 ++++++++++--------- linux/drivers/media/video/mt9v022.c | 24 ++++----- linux/drivers/media/video/mx1_camera.c | 10 ++-- linux/drivers/media/video/mx3_camera.c | 25 +++++----- linux/drivers/media/video/ov772x.c | 6 +-- linux/drivers/media/video/pxa_camera.c | 14 +++--- linux/drivers/media/video/sh_mobile_ceu_camera.c | 28 ++++++----- linux/drivers/media/video/soc_camera.c | 62 ++++++++++++++---------- linux/drivers/media/video/soc_camera_platform.c | 12 ++--- linux/drivers/media/video/tw9910.c | 38 +++++++++------ linux/include/media/soc_camera.h | 10 +--- 13 files changed, 174 insertions(+), 154 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 45d8fad25..7a9435f9b 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -240,8 +240,8 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct i2c_client *client = sd->priv; struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_rect rect = { - .left = icd->x_current, - .top = icd->y_current, + .left = icd->rect_current.left, + .top = icd->rect_current.top, .width = f->fmt.pix.width, .height = f->fmt.pix.height, }; @@ -467,11 +467,13 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_EXPOSURE_AUTO: if (ctrl->value) { const u16 vblank = 25; - if (reg_write(client, MT9M001_SHUTTER_WIDTH, icd->height + + if (reg_write(client, MT9M001_SHUTTER_WIDTH, + icd->rect_current.height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (524 + (icd->height + icd->y_skip_top + vblank - 1) * + icd->exposure = (524 + (icd->rect_current.height + + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / 1048 + qctrl->minimum; mt9m001->autoexposure = 1; @@ -617,16 +619,16 @@ static int mt9m001_probe(struct i2c_client *client) v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops); /* Second stage probe - when a capture adapter is there */ - icd->ops = &mt9m001_ops; - icd->x_min = 20; - icd->y_min = 12; - icd->x_current = 20; - icd->y_current = 12; - icd->width_min = 48; - icd->width_max = 1280; - icd->height_min = 32; - icd->height_max = 1024; - icd->y_skip_top = 1; + icd->ops = &mt9m001_ops; + icd->rect_max.left = 20; + icd->rect_max.top = 12; + icd->rect_max.width = 1280; + icd->rect_max.height = 1024; + icd->rect_current.left = 20; + icd->rect_current.top = 12; + icd->width_min = 48; + icd->height_min = 32; + icd->y_skip_top = 1; /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9m001->autoexposure = 1; diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 4b00033c4..8770dfd2a 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -952,16 +952,16 @@ static int mt9m111_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops); /* Second stage probe - when a capture adapter is there */ - icd->ops = &mt9m111_ops; - icd->x_min = MT9M111_MIN_DARK_COLS; - icd->y_min = MT9M111_MIN_DARK_ROWS; - icd->x_current = icd->x_min; - icd->y_current = icd->y_min; - icd->width_min = MT9M111_MIN_DARK_ROWS; - icd->width_max = MT9M111_MAX_WIDTH; - icd->height_min = MT9M111_MIN_DARK_COLS; - icd->height_max = MT9M111_MAX_HEIGHT; - icd->y_skip_top = 0; + icd->ops = &mt9m111_ops; + icd->rect_max.left = MT9M111_MIN_DARK_COLS; + icd->rect_max.top = MT9M111_MIN_DARK_ROWS; + icd->rect_max.width = MT9M111_MAX_WIDTH; + icd->rect_max.height = MT9M111_MAX_HEIGHT; + icd->rect_current.left = icd->rect_max.left; + icd->rect_current.top = icd->rect_max.top; + icd->width_min = MT9M111_MIN_DARK_ROWS; + icd->height_min = MT9M111_MIN_DARK_COLS; + icd->y_skip_top = 0; ret = mt9m111_video_probe(icd, client); if (ret) { diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 2aff92cfc..405fe5c25 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -222,12 +222,12 @@ static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) static void recalculate_limits(struct soc_camera_device *icd, u16 xskip, u16 yskip) { - icd->x_min = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip; - icd->y_min = (MT9T031_ROW_SKIP + yskip - 1) / yskip; + icd->rect_max.left = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip; + icd->rect_max.top = (MT9T031_ROW_SKIP + yskip - 1) / yskip; icd->width_min = (MT9T031_MIN_WIDTH + xskip - 1) / xskip; icd->height_min = (MT9T031_MIN_HEIGHT + yskip - 1) / yskip; - icd->width_max = MT9T031_MAX_WIDTH / xskip; - icd->height_max = MT9T031_MAX_HEIGHT / yskip; + icd->rect_max.width = MT9T031_MAX_WIDTH / xskip; + icd->rect_max.height = MT9T031_MAX_HEIGHT / yskip; } static int mt9t031_set_params(struct soc_camera_device *icd, @@ -241,11 +241,13 @@ static int mt9t031_set_params(struct soc_camera_device *icd, vblank = MT9T031_VERTICAL_BLANK; /* Make sure we don't exceed sensor limits */ - if (rect->left + rect->width > icd->width_max) - rect->left = (icd->width_max - rect->width) / 2 + icd->x_min; + if (rect->left + rect->width > icd->rect_max.width) + rect->left = (icd->rect_max.width - rect->width) / 2 + + icd->rect_max.left; - if (rect->top + rect->height > icd->height_max) - rect->top = (icd->height_max - rect->height) / 2 + icd->y_min; + if (rect->top + rect->height > icd->rect_max.height) + rect->top = (icd->rect_max.height - rect->height) / 2 + + icd->rect_max.top; width = rect->width * xskip; height = rect->height * yskip; @@ -346,8 +348,8 @@ static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) int ret; u16 xskip, yskip; struct v4l2_rect rect = { - .left = icd->x_current, - .top = icd->y_current, + .left = icd->rect_current.left, + .top = icd->rect_current.top, .width = f->fmt.pix.width, .height = f->fmt.pix.height, }; @@ -618,12 +620,13 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (ctrl->value) { const u16 vblank = MT9T031_VERTICAL_BLANK; const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; - if (set_shutter(client, icd->height + + if (set_shutter(client, icd->rect_current.height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (shutter_max / 2 + (icd->height + - icd->y_skip_top + vblank - 1) * + icd->exposure = (shutter_max / 2 + + (icd->rect_current.height + + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / shutter_max + qctrl->minimum; mt9t031->autoexposure = 1; @@ -730,16 +733,16 @@ static int mt9t031_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops); /* Second stage probe - when a capture adapter is there */ - icd->ops = &mt9t031_ops; - icd->x_min = MT9T031_COLUMN_SKIP; - icd->y_min = MT9T031_ROW_SKIP; - icd->x_current = icd->x_min; - icd->y_current = icd->y_min; - icd->width_min = MT9T031_MIN_WIDTH; - icd->width_max = MT9T031_MAX_WIDTH; - icd->height_min = MT9T031_MIN_HEIGHT; - icd->height_max = MT9T031_MAX_HEIGHT; - icd->y_skip_top = 0; + icd->ops = &mt9t031_ops; + icd->rect_max.left = MT9T031_COLUMN_SKIP; + icd->rect_max.top = MT9T031_ROW_SKIP; + icd->rect_current.left = icd->rect_max.left; + icd->rect_current.top = icd->rect_max.top; + icd->width_min = MT9T031_MIN_WIDTH; + icd->rect_max.width = MT9T031_MAX_WIDTH; + icd->height_min = MT9T031_MIN_HEIGHT; + icd->rect_max.height = MT9T031_MAX_HEIGHT; + icd->y_skip_top = 0; /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9t031->autoexposure = 1; diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index b09cd0913..de74f7bda 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -298,8 +298,8 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { - .left = icd->x_current, - .top = icd->y_current, + .left = icd->rect_current.left, + .top = icd->rect_current.top, .width = pix->width, .height = pix->height, }; @@ -745,16 +745,16 @@ static int mt9v022_probe(struct i2c_client *client) mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; - icd->ops = &mt9v022_ops; - icd->x_min = 1; - icd->y_min = 4; - icd->x_current = 1; - icd->y_current = 4; - icd->width_min = 48; - icd->width_max = 752; - icd->height_min = 32; - icd->height_max = 480; - icd->y_skip_top = 1; + icd->ops = &mt9v022_ops; + icd->rect_max.left = 1; + icd->rect_max.top = 4; + icd->rect_max.width = 752; + icd->rect_max.height = 480; + icd->rect_current.left = 1; + icd->rect_current.top = 4; + icd->width_min = 48; + icd->height_min = 32; + icd->y_skip_top = 1; ret = mt9v022_video_probe(icd, client); if (ret) { diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index ea4ceaec8..948a4714b 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -126,7 +126,7 @@ static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, { struct soc_camera_device *icd = vq->priv_data; - *size = icd->width * icd->height * + *size = icd->rect_current.width * icd->rect_current.height * ((icd->current_fmt->depth + 7) >> 3); if (!*count) @@ -178,12 +178,12 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, buf->inwork = 1; if (buf->fmt != icd->current_fmt || - vb->width != icd->width || - vb->height != icd->height || + vb->width != icd->rect_current.width || + vb->height != icd->rect_current.height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->width; - vb->height = icd->height; + vb->width = icd->rect_current.width; + vb->height = icd->rect_current.height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index 677d355be..6c3b7f9b9 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -220,7 +220,7 @@ static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, if (!mx3_cam->idmac_channel[0]) return -EINVAL; - *size = icd->width * icd->height * bpp; + *size = icd->rect_current.width * icd->rect_current.height * bpp; if (!*count) *count = 32; @@ -241,7 +241,7 @@ static int mx3_videobuf_prepare(struct videobuf_queue *vq, struct mx3_camera_buffer *buf = container_of(vb, struct mx3_camera_buffer, vb); /* current_fmt _must_ always be set */ - size_t new_size = icd->width * icd->height * + size_t new_size = icd->rect_current.width * icd->rect_current.height * ((icd->current_fmt->depth + 7) >> 3); int ret; @@ -251,12 +251,12 @@ static int mx3_videobuf_prepare(struct videobuf_queue *vq, */ if (buf->fmt != icd->current_fmt || - vb->width != icd->width || - vb->height != icd->height || + vb->width != icd->rect_current.width || + vb->height != icd->rect_current.height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->width; - vb->height = icd->height; + vb->width = icd->rect_current.width; + vb->height = icd->rect_current.height; vb->field = field; if (vb->state != VIDEOBUF_NEEDS_INIT) free_buffer(vq, buf); @@ -354,9 +354,9 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, /* This is the configuration of one sg-element */ video->out_pixel_fmt = fourcc_to_ipu_pix(data_fmt->fourcc); - video->out_width = icd->width; - video->out_height = icd->height; - video->out_stride = icd->width; + video->out_width = icd->rect_current.width; + video->out_height = icd->rect_current.height; + video->out_stride = icd->rect_current.width; #ifdef DEBUG /* helps to see what DMA actually has written */ @@ -538,7 +538,8 @@ static bool channel_change_requested(struct soc_camera_device *icd, struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; /* Do buffers have to be re-allocated or channel re-configured? */ - return ichan && rect->width * rect->height > icd->width * icd->height; + return ichan && rect->width * rect->height > + icd->rect_current.width * icd->rect_current.height; } static int test_platform_param(struct mx3_camera_dev *mx3_cam, @@ -808,8 +809,8 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { - .left = icd->x_current, - .top = icd->y_current, + .left = icd->rect_current.left, + .top = icd->rect_current.top, .width = pix->width, .height = pix->height, }; diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 05e06f5b8..a853c3514 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -1124,9 +1124,9 @@ static int ov772x_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); - icd->ops = &ov772x_ops; - icd->width_max = MAX_WIDTH; - icd->height_max = MAX_HEIGHT; + icd->ops = &ov772x_ops; + icd->rect_max.width = MAX_WIDTH; + icd->rect_max.height = MAX_HEIGHT; ret = ov772x_video_probe(icd, client); if (ret) { diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 4c73b7d88..6f2aef033 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -251,7 +251,7 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); - *size = roundup(icd->width * icd->height * + *size = roundup(icd->rect_current.width * icd->rect_current.height * ((icd->current_fmt->depth + 7) >> 3), 8); if (0 == *count) @@ -455,12 +455,12 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, buf->inwork = 1; if (buf->fmt != icd->current_fmt || - vb->width != icd->width || - vb->height != icd->height || + vb->width != icd->rect_current.width || + vb->height != icd->rect_current.height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->width; - vb->height = icd->height; + vb->width = icd->rect_current.width; + vb->height = icd->rect_current.height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } @@ -1130,7 +1130,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) if (cicr0 & CICR0_ENB) __raw_writel(cicr0 & ~CICR0_ENB, pcdev->base + CICR0); - cicr1 = CICR1_PPL_VAL(icd->width - 1) | bpp | dw; + cicr1 = CICR1_PPL_VAL(icd->rect_current.width - 1) | bpp | dw; switch (pixfmt) { case V4L2_PIX_FMT_YUV422P: @@ -1159,7 +1159,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) } cicr2 = 0; - cicr3 = CICR3_LPF_VAL(icd->height - 1) | + cicr3 = CICR3_LPF_VAL(icd->rect_current.height - 1) | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); cicr4 |= pcdev->mclk_divisor; diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 99ea30896..4c33c3efd 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -148,7 +148,8 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, struct sh_mobile_ceu_dev *pcdev = ici->priv; int bytes_per_pixel = (icd->current_fmt->depth + 7) >> 3; - *size = PAGE_ALIGN(icd->width * icd->height * bytes_per_pixel); + *size = PAGE_ALIGN(icd->rect_current.width * icd->rect_current.height * + bytes_per_pixel); if (0 == *count) *count = 2; @@ -207,7 +208,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) phys_addr_top = videobuf_to_dma_contig(pcdev->active); ceu_write(pcdev, CDAYR, phys_addr_top); if (pcdev->is_interlaced) { - phys_addr_bottom = phys_addr_top + icd->width; + phys_addr_bottom = phys_addr_top + icd->rect_current.width; ceu_write(pcdev, CDBYR, phys_addr_bottom); } @@ -216,10 +217,12 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - phys_addr_top += icd->width * icd->height; + phys_addr_top += icd->rect_current.width * + icd->rect_current.height; ceu_write(pcdev, CDACR, phys_addr_top); if (pcdev->is_interlaced) { - phys_addr_bottom = phys_addr_top + icd->width; + phys_addr_bottom = phys_addr_top + + icd->rect_current.width; ceu_write(pcdev, CDBCR, phys_addr_bottom); } } @@ -253,12 +256,12 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, BUG_ON(NULL == icd->current_fmt); if (buf->fmt != icd->current_fmt || - vb->width != icd->width || - vb->height != icd->height || + vb->width != icd->rect_current.width || + vb->height != icd->rect_current.height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->width; - vb->height = icd->height; + vb->width = icd->rect_current.width; + vb->height = icd->rect_current.height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } @@ -477,17 +480,18 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, mdelay(1); if (yuv_mode) { - width = icd->width * 2; + width = icd->rect_current.width * 2; width = buswidth == 16 ? width / 2 : width; - cfszr_width = cdwdr_width = icd->width; + cfszr_width = cdwdr_width = icd->rect_current.width; } else { - width = icd->width * ((icd->current_fmt->depth + 7) >> 3); + width = icd->rect_current.width * + ((icd->current_fmt->depth + 7) >> 3); width = buswidth == 16 ? width / 2 : width; cfszr_width = buswidth == 8 ? width / 2 : width; cdwdr_width = buswidth == 16 ? width * 2 : width; } - height = icd->height; + height = icd->rect_current.height; if (pcdev->is_interlaced) { height /= 2; cdwdr_width *= 2; diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 42e7acd9b..9a7139e31 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -289,17 +289,17 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, return -EINVAL; } - icd->width = pix->width; - icd->height = pix->height; - icf->vb_vidq.field = - icd->field = pix->field; + icd->rect_current.width = pix->width; + icd->rect_current.height = pix->height; + icf->vb_vidq.field = + icd->field = pix->field; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", f->type); dev_dbg(&icd->dev, "set width: %d height: %d\n", - icd->width, icd->height); + icd->rect_current.width, icd->rect_current.height); /* set physical bus parameters */ return ici->ops->set_bus_param(icd, pix->pixelformat); @@ -342,8 +342,8 @@ static int soc_camera_open(struct file *file) struct v4l2_format f = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .fmt.pix = { - .width = icd->width, - .height = icd->height, + .width = icd->rect_current.width, + .height = icd->rect_current.height, .field = icd->field, }, }; @@ -554,8 +554,8 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, WARN_ON(priv != file->private_data); - pix->width = icd->width; - pix->height = icd->height; + pix->width = icd->rect_current.width; + pix->height = icd->rect_current.height; pix->field = icf->vb_vidq.field; pix->pixelformat = icd->current_fmt->fourcc; pix->bytesperline = pix->width * @@ -719,12 +719,9 @@ static int soc_camera_cropcap(struct file *file, void *fh, struct soc_camera_device *icd = icf->icd; a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - a->bounds.left = icd->x_min; - a->bounds.top = icd->y_min; - a->bounds.width = icd->width_max; - a->bounds.height = icd->height_max; - a->defrect.left = icd->x_min; - a->defrect.top = icd->y_min; + a->bounds = icd->rect_max; + a->defrect.left = icd->rect_max.left; + a->defrect.top = icd->rect_max.top; a->defrect.width = DEFAULT_WIDTH; a->defrect.height = DEFAULT_HEIGHT; a->pixelaspect.numerator = 1; @@ -739,11 +736,8 @@ static int soc_camera_g_crop(struct file *file, void *fh, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - a->c.left = icd->x_current; - a->c.top = icd->y_current; - a->c.width = icd->width; - a->c.height = icd->height; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->c = icd->rect_current; return 0; } @@ -762,13 +756,29 @@ static int soc_camera_s_crop(struct file *file, void *fh, /* Cropping is allowed during a running capture, guard consistency */ mutex_lock(&icf->vb_vidq.vb_lock); + if (a->c.width > icd->rect_max.width) + a->c.width = icd->rect_max.width; + + if (a->c.width < icd->width_min) + a->c.width = icd->width_min; + + if (a->c.height > icd->rect_max.height) + a->c.height = icd->rect_max.height; + + if (a->c.height < icd->height_min) + a->c.height = icd->height_min; + + if (a->c.width + a->c.left > icd->rect_max.width + icd->rect_max.left) + a->c.left = icd->rect_max.width + icd->rect_max.left - + a->c.width; + + if (a->c.height + a->c.top > icd->rect_max.height + icd->rect_max.top) + a->c.top = icd->rect_max.height + icd->rect_max.top - + a->c.height; + ret = ici->ops->set_crop(icd, &a->c); - if (!ret) { - icd->width = a->c.width; - icd->height = a->c.height; - icd->x_current = a->c.left; - icd->y_current = a->c.top; - } + if (!ret) + icd->rect_current = a->c; mutex_unlock(&icf->vb_vidq.vb_lock); diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index 8168cf470..9e406c113 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -127,12 +127,12 @@ static int soc_camera_platform_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); dev_set_drvdata(&icd->dev, &pdev->dev); - icd->width_min = 0; - icd->width_max = p->format.width; - icd->height_min = 0; - icd->height_max = p->format.height; - icd->y_skip_top = 0; - icd->ops = &soc_camera_platform_ops; + icd->width_min = 0; + icd->rect_max.width = p->format.width; + icd->height_min = 0; + icd->rect_max.height = p->format.height; + icd->y_skip_top = 0; + icd->ops = &soc_camera_platform_ops; ici = to_soc_camera_host(icd->dev.parent); diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 61dc1b812..f1a146807 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -715,8 +715,8 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { - .left = icd->x_current, - .top = icd->y_current, + .left = icd->rect_current.left, + .top = icd->rect_current.top, .width = pix->width, .height = pix->height, }; @@ -840,6 +840,19 @@ static struct v4l2_subdev_ops tw9910_subdev_ops = { * i2c_driver function */ +static void limit_to_scale(struct soc_camera_device *icd, + const struct tw9910_scale_ctrl *scale) +{ + if (scale->width > icd->rect_max.width) + icd->rect_max.width = scale->width; + if (scale->width < icd->width_min) + icd->width_min = scale->width; + if (scale->height > icd->rect_max.height) + icd->rect_max.height = scale->height; + if (scale->height < icd->height_min) + icd->height_min = scale->height; +} + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int tw9910_probe(struct i2c_client *client) #else @@ -889,25 +902,18 @@ static int tw9910_probe(struct i2c_client *client, /* * set width and height */ - icd->width_max = tw9910_ntsc_scales[0].width; /* set default */ + icd->rect_max.width = tw9910_ntsc_scales[0].width; /* set default */ icd->width_min = tw9910_ntsc_scales[0].width; - icd->height_max = tw9910_ntsc_scales[0].height; + icd->rect_max.height = tw9910_ntsc_scales[0].height; icd->height_min = tw9910_ntsc_scales[0].height; scale = tw9910_ntsc_scales; - for (i = 0; i < ARRAY_SIZE(tw9910_ntsc_scales); i++) { - icd->width_max = max(scale[i].width, icd->width_max); - icd->width_min = min(scale[i].width, icd->width_min); - icd->height_max = max(scale[i].height, icd->height_max); - icd->height_min = min(scale[i].height, icd->height_min); - } + for (i = 0; i < ARRAY_SIZE(tw9910_ntsc_scales); i++) + limit_to_scale(icd, scale + i); + scale = tw9910_pal_scales; - for (i = 0; i < ARRAY_SIZE(tw9910_pal_scales); i++) { - icd->width_max = max(scale[i].width, icd->width_max); - icd->width_min = min(scale[i].width, icd->width_min); - icd->height_max = max(scale[i].height, icd->height_max); - icd->height_min = min(scale[i].height, icd->height_min); - } + for (i = 0; i < ARRAY_SIZE(tw9910_pal_scales); i++) + limit_to_scale(icd, scale + i); ret = tw9910_video_probe(icd, client); if (ret) { diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 2d116bbbc..f623c010a 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -22,16 +22,10 @@ struct soc_camera_device { struct list_head list; struct device dev; struct device *pdev; /* Platform device */ - unsigned short width; /* Current window */ - unsigned short height; /* sizes */ - unsigned short x_min; /* Camera capabilities */ - unsigned short y_min; - unsigned short x_current; /* Current window location */ - unsigned short y_current; + struct v4l2_rect rect_current; /* Current window */ + struct v4l2_rect rect_max; /* Maximum window */ unsigned short width_min; - unsigned short width_max; unsigned short height_min; - unsigned short height_max; unsigned short y_skip_top; /* Lines to skip at the top */ unsigned short gain; unsigned short exposure; -- cgit v1.2.3 From bbbc50159e8cab3ba46fe1491657840d91490829 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:42 +0200 Subject: ov772x: successful S_FMT and S_CROP must update user-provided rectangle From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-) --- linux/drivers/media/video/ov772x.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index a853c3514..a9f9c04c1 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -806,7 +806,7 @@ static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) } static int ov772x_set_params(struct i2c_client *client, - u32 width, u32 height, u32 pixfmt) + u32 *width, u32 *height, u32 pixfmt) { struct ov772x_priv *priv = to_ov772x(client); int ret = -EINVAL; @@ -829,7 +829,7 @@ static int ov772x_set_params(struct i2c_client *client, /* * select win */ - priv->win = ov772x_select_win(width, height); + priv->win = ov772x_select_win(*width, *height); /* * reset hardware @@ -941,6 +941,9 @@ static int ov772x_set_params(struct i2c_client *client, goto ov772x_set_fmt_error; } + *width = priv->win->width; + *height = priv->win->height; + return ret; ov772x_set_fmt_error: @@ -961,7 +964,7 @@ static int ov772x_set_crop(struct soc_camera_device *icd, if (!priv->fmt) return -EINVAL; - return ov772x_set_params(client, rect->width, rect->height, + return ov772x_set_params(client, &rect->width, &rect->height, priv->fmt->fourcc); } @@ -970,7 +973,7 @@ static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct i2c_client *client = sd->priv; struct v4l2_pix_format *pix = &f->fmt.pix; - return ov772x_set_params(client, pix->width, pix->height, + return ov772x_set_params(client, &pix->width, &pix->height, pix->pixelformat); } -- cgit v1.2.3 From 5eccdb2f169fdba3dcf0eef1f8c87a8232fa3cf0 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:42 +0200 Subject: mt9t031: improve rectangle placement in invalid S_CROP From: Guennadi Liakhovetski 1. soc-camera always requests a valid rectangle, when calling .s_fmt(), no need to check and adjust 2. in .s_crop(), if the rectangle exceeds sensor limits, push it to the respective border instead of centering 3. take into account left and top borders when checking Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9t031.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-) --- linux/drivers/media/video/mt9t031.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 405fe5c25..b69a34c87 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -240,15 +240,6 @@ static int mt9t031_set_params(struct soc_camera_device *icd, const u16 hblank = MT9T031_HORIZONTAL_BLANK, vblank = MT9T031_VERTICAL_BLANK; - /* Make sure we don't exceed sensor limits */ - if (rect->left + rect->width > icd->rect_max.width) - rect->left = (icd->rect_max.width - rect->width) / 2 + - icd->rect_max.left; - - if (rect->top + rect->height > icd->rect_max.height) - rect->top = (icd->rect_max.height - rect->height) / 2 + - icd->rect_max.top; - width = rect->width * xskip; height = rect->height * yskip; left = rect->left * xskip; @@ -336,6 +327,15 @@ static int mt9t031_set_crop(struct soc_camera_device *icd, struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct mt9t031 *mt9t031 = to_mt9t031(client); + /* Make sure we don't exceed sensor limits */ + if (rect->left + rect->width > icd->rect_max.left + icd->rect_max.width) + rect->left = icd->rect_max.width + icd->rect_max.left - + rect->width; + + if (rect->top + rect->height > icd->rect_max.height + icd->rect_max.top) + rect->top = icd->rect_max.height + icd->rect_max.top - + rect->height; + /* CROP - no change in scaling, or in limits */ return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); } -- cgit v1.2.3 From 50dda2d882c41d334002fb2437c66080c5d87080 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:42 +0200 Subject: ov772x: S_CROP must return actually configured geometry From: Guennadi Liakhovetski V4L2 drivers are allowed to configure a geometry different than what has been requested by the user with S_CROP, but then they have to adjust the input rectangle accordingly. Fix ov772x to comply with this requirement. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) --- linux/drivers/media/video/ov772x.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index a9f9c04c1..700f655fd 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -960,12 +960,18 @@ static int ov772x_set_crop(struct soc_camera_device *icd, { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct ov772x_priv *priv = to_ov772x(client); + int ret; if (!priv->fmt) return -EINVAL; - return ov772x_set_params(client, &rect->width, &rect->height, - priv->fmt->fourcc); + ret = ov772x_set_params(client, &rect->width, &rect->height, + priv->fmt->fourcc); + if (!ret) { + rect->left = 0; + rect->top = 0; + } + return ret; } static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) -- cgit v1.2.3 From 1e42790cf4308ec89ea72d095fe8aa119ea43dc5 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:43 +0200 Subject: soc-camera: put pixel format initialisation back in probe, add .put_formats() From: Guennadi Liakhovetski The move of format translation initialisation into soc_camera_open() was temporary for the soc-camera as platform driver intermediate step, put it back into soc_camera_probe(). Also add a .put_formats() method to soc_camera_host_ops to free any resources host driver might have allocated in .get_formats(). Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 50 ++++++++++++++++++++++++++----------- include/media/soc_camera.h | 7 +++++ 2 files changed, 42 insertions(+), 15 deletions(-) --- linux/drivers/media/video/soc_camera.c | 50 ++++++++++++++++++++++++---------- linux/include/media/soc_camera.h | 7 +++++ 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 9a7139e31..dd348a0b3 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -212,7 +212,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv, static int soc_camera_init_user_formats(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - int i, fmts = 0; + int i, fmts = 0, ret; if (!ici->ops->get_formats) /* @@ -225,8 +225,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) * First pass - only count formats this host-sensor * configuration can provide */ - for (i = 0; i < icd->num_formats; i++) - fmts += ici->ops->get_formats(icd, i, NULL); + for (i = 0; i < icd->num_formats; i++) { + ret = ici->ops->get_formats(icd, i, NULL); + if (ret < 0) + return ret; + fmts += ret; + } if (!fmts) return -ENXIO; @@ -248,19 +252,32 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) icd->user_formats[i].cam_fmt = icd->formats + i; icd->user_formats[i].buswidth = icd->formats[i].depth; } else { - fmts += ici->ops->get_formats(icd, i, - &icd->user_formats[fmts]); + ret = ici->ops->get_formats(icd, i, + &icd->user_formats[fmts]); + if (ret < 0) + goto egfmt; + fmts += ret; } icd->current_fmt = icd->user_formats[0].host_fmt; return 0; + +egfmt: + icd->num_user_formats = 0; + vfree(icd->user_formats); + return ret; } /* Always entered with .video_lock held */ static void soc_camera_free_user_formats(struct soc_camera_device *icd) { + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + + if (ici->ops->put_formats) + ici->ops->put_formats(icd); icd->current_fmt = NULL; + icd->num_user_formats = 0; vfree(icd->user_formats); icd->user_formats = NULL; } @@ -345,16 +362,11 @@ static int soc_camera_open(struct file *file) .width = icd->rect_current.width, .height = icd->rect_current.height, .field = icd->field, + .pixelformat = icd->current_fmt->fourcc, + .colorspace = icd->current_fmt->colorspace, }, }; - ret = soc_camera_init_user_formats(icd); - if (ret < 0) - goto eiufmt; - - f.fmt.pix.pixelformat = icd->current_fmt->fourcc; - f.fmt.pix.colorspace = icd->current_fmt->colorspace; - if (icl->power) { ret = icl->power(icd->pdev, 1); if (ret < 0) @@ -405,8 +417,6 @@ eiciadd: if (icl->power) icl->power(icd->pdev, 0); epower: - soc_camera_free_user_formats(icd); -eiufmt: icd->use_count--; mutex_unlock(&icd->video_lock); module_put(ici->ops->owner); @@ -432,7 +442,6 @@ static int soc_camera_close(struct file *file) ici->ops->remove(icd); if (icl->power) icl->power(icd->pdev, 0); - soc_camera_free_user_formats(icd); } mutex_unlock(&icd->video_lock); @@ -955,6 +964,14 @@ static int soc_camera_probe(struct device *dev) } } + /* At this point client .probe() should have run already */ + ret = soc_camera_init_user_formats(icd); + if (ret < 0) + goto eiufmt; + + icd->rect_current = icd->rect_max; + icd->field = V4L2_FIELD_ANY; + /* ..._video_start() will create a device node, so we have to protect */ mutex_lock(&icd->video_lock); @@ -979,6 +996,8 @@ static int soc_camera_probe(struct device *dev) evidstart: mutex_unlock(&icd->video_lock); + soc_camera_free_user_formats(icd); +eiufmt: if (icl->board_info) { soc_camera_free_i2c(icd); } else { @@ -1024,6 +1043,7 @@ static int soc_camera_remove(struct device *dev) module_put(drv->owner); } } + soc_camera_free_user_formats(icd); return 0; } diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index f623c010a..2b7a8c663 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -67,8 +67,15 @@ struct soc_camera_host_ops { void (*remove)(struct soc_camera_device *); int (*suspend)(struct soc_camera_device *, pm_message_t); int (*resume)(struct soc_camera_device *); + /* + * .get_formats() is called for each client device format, but + * .put_formats() is only called once. Further, if any of the calls to + * .get_formats() fail, .put_formats() will not be called at all, the + * failing .get_formats() must then clean up internally. + */ int (*get_formats)(struct soc_camera_device *, int, struct soc_camera_format_xlate *); + void (*put_formats)(struct soc_camera_device *); int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *); int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *); int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); -- cgit v1.2.3 From 476b4e44d0836e75896fd12b0d5f33fdc706bee9 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:51 +0200 Subject: sh-mobile-ceu-camera: do not wait for interrupt when releasing buffers From: Guennadi Liakhovetski Patch [PATCH] video: use videobuf_waiton() in sh_mobile_ceu free_buffer() was not quite correct. It closed a race, but introduced a potential lock-up, if for some reason an interrupt does not come. This has been observed in tests with tw9910. This patch safely dequeues buffers without waiting for their completion. It also moves a buffer state assignment under a spinlock to make it atomic with queuing of the buffer. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/sh_mobile_ceu_camera.c | 27 +++++++++++++++++++++++++++ 1 files changed, 27 insertions(+), 0 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 4c33c3efd..f54a9f23f 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -309,6 +309,27 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; + unsigned long flags; + + spin_lock_irqsave(&pcdev->lock, flags); + + if (pcdev->active == vb) { + /* disable capture (release DMA buffer), reset */ + ceu_write(pcdev, CAPSR, 1 << 16); + pcdev->active = NULL; + } + + if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) && + !list_empty(&vb->queue)) { + vb->state = VIDEOBUF_ERROR; + list_del_init(&vb->queue); + } + + spin_unlock_irqrestore(&pcdev->lock, flags); + free_buffer(vq, container_of(vb, struct sh_mobile_ceu_buffer, vb)); } @@ -328,6 +349,10 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) spin_lock_irqsave(&pcdev->lock, flags); vb = pcdev->active; + if (!vb) + /* Stale interrupt from a released buffer */ + goto out; + list_del_init(&vb->queue); if (!list_empty(&pcdev->capture)) @@ -342,6 +367,8 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) do_gettimeofday(&vb->ts); vb->field_count++; wake_up(&vb->done); + +out: spin_unlock_irqrestore(&pcdev->lock, flags); return IRQ_HANDLED; -- cgit v1.2.3 From 4cba5b9dc9691179938d5481bda3c97e376e0964 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:51 +0200 Subject: soc-camera: use .s_std() from struct v4l2_subdev_core_ops From: Guennadi Liakhovetski Remove .set_std() method from struct soc_camera_ops, use .s_std() from struct v4l2_subdev_core_ops instead. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 7 ++----- include/media/soc_camera.h | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) --- linux/drivers/media/video/soc_camera.c | 7 ++----- linux/include/media/soc_camera.h | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index dd348a0b3..104496141 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -153,12 +153,9 @@ static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - int ret = 0; - - if (icd->ops->set_std) - ret = icd->ops->set_std(icd, a); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - return ret; + return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_std, *a); } static int soc_camera_reqbufs(struct file *file, void *priv, diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 2b7a8c663..7c44d4016 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -190,7 +190,6 @@ struct soc_camera_ops { int (*set_bus_param)(struct soc_camera_device *, unsigned long); int (*get_chip_id)(struct soc_camera_device *, struct v4l2_dbg_chip_ident *); - int (*set_std)(struct soc_camera_device *, v4l2_std_id *); int (*enum_input)(struct soc_camera_device *, struct v4l2_input *); const struct v4l2_queryctrl *controls; int num_controls; -- cgit v1.2.3 From 83741e5418caf367ba88caf33d4475755826ff4f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:52 +0200 Subject: sh-mobile-ceu-camera: implement host-side cropping From: Guennadi Liakhovetski Not all video capture devices can configure arbitrary cropping, whereas the CEU module on SuperH CPUs can crop with pixel precision. However, we want to use camera cropping if possible to save bandwidth and increase the frame-rate. This patch verifies whether the camera managed to crop exactly the requested rectangle, and if not, uses host-side cropping. To be able to crop on CEU we have to preserve camera rectangle too, for which the host_priv member in struct soc_camera_device is used. We now allocate memory dynamically, thus we have to use the .put_formats() method from struct soc_camera_host_ops to free it. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/sh_mobile_ceu_camera.c | 309 +++++++++++++++++++++++----- 1 files changed, 259 insertions(+), 50 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 309 +++++++++++++++++++---- 1 file changed, 259 insertions(+), 50 deletions(-) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index f54a9f23f..befc84ce1 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -94,10 +94,17 @@ struct sh_mobile_ceu_dev { spinlock_t lock; struct list_head capture; struct videobuf_buffer *active; - int is_interlaced; struct sh_mobile_ceu_info *pdata; + unsigned int is_interlaced:1; + unsigned int image_mode:1; + unsigned int is_16bit:1; +}; + +struct sh_mobile_ceu_cam { + struct v4l2_rect camera_rect; + const struct soc_camera_data_format *extra_fmt; const struct soc_camera_data_format *camera_fmt; }; @@ -430,14 +437,101 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) pcdev->icd = NULL; } +static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, + struct v4l2_rect *rect) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct sh_mobile_ceu_dev *pcdev = ici->priv; + int width, height, cfszr_width, cdwdr_width; + unsigned int left_offset, top_offset; + u32 camor; + + if (rect->left > cam->camera_rect.left) { + left_offset = rect->left - cam->camera_rect.left; + } else { + left_offset = 0; + rect->left = cam->camera_rect.left; + } + + if (rect->top > cam->camera_rect.top) { + top_offset = rect->top - cam->camera_rect.top; + } else { + top_offset = 0; + rect->top = cam->camera_rect.top; + } + + dev_dbg(&icd->dev, "Offsets %u:%u\n", left_offset, top_offset); + + if (pcdev->image_mode) { + width = rect->width; + if (!pcdev->is_16bit) + width *= 2; + cfszr_width = cdwdr_width = rect->width; + } else { + width = rect->width * + ((icd->current_fmt->depth + 7) >> 3); + width = pcdev->is_16bit ? width / 2 : width; + cfszr_width = pcdev->is_16bit ? width : width / 2; + cdwdr_width = pcdev->is_16bit ? width * 2 : width; + } + + height = rect->height; + if (pcdev->is_interlaced) { + height /= 2; + cdwdr_width *= 2; + } + + camor = left_offset | (top_offset << 16); + ceu_write(pcdev, CAMOR, camor); + ceu_write(pcdev, CAPWR, (height << 16) | width); + ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width); + ceu_write(pcdev, CDWDR, cdwdr_width); +} + +static u32 capture_save_reset(struct sh_mobile_ceu_dev *pcdev) +{ + u32 capsr = ceu_read(pcdev, CAPSR); + ceu_write(pcdev, CAPSR, 1 << 16); /* reset, stop capture */ + return capsr; +} + +static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr) +{ + unsigned long timeout = jiffies + 10 * HZ; + + /* + * Wait until the end of the current frame. It can take a long time, + * but if it has been aborted by a CAPSR reset, it shoule exit sooner. + */ + while ((ceu_read(pcdev, CSTSR) & 1) && time_before(jiffies, timeout)) + msleep(1); + + if (time_after(jiffies, timeout)) { + dev_err(pcdev->ici.v4l2_dev.dev, + "Timeout waiting for frame end! Interface problem?\n"); + return; + } + + /* Wait until reset clears, this shall not hang... */ + while (ceu_read(pcdev, CAPSR) & (1 << 16)) + udelay(10); + + /* Anything to restore? */ + if (capsr & ~(1 << 16)) + ceu_write(pcdev, CAPSR, capsr); +} + static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - int ret, buswidth, width, height, cfszr_width, cdwdr_width; + int ret; unsigned long camera_flags, common_flags, value; - int yuv_mode, yuv_lineskip; + int yuv_lineskip; + struct sh_mobile_ceu_cam *cam = icd->host_priv; + u32 capsr = capture_save_reset(pcdev); camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, @@ -451,10 +545,10 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, switch (common_flags & SOCAM_DATAWIDTH_MASK) { case SOCAM_DATAWIDTH_8: - buswidth = 8; + pcdev->is_16bit = 0; break; case SOCAM_DATAWIDTH_16: - buswidth = 16; + pcdev->is_16bit = 1; break; default: return -EINVAL; @@ -464,7 +558,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CRCMPR, 0); value = 0x00000010; /* data fetch by default */ - yuv_mode = yuv_lineskip = 0; + pcdev->image_mode = yuv_lineskip = 0; switch (icd->current_fmt->fourcc) { case V4L2_PIX_FMT_NV12: @@ -473,8 +567,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, /* fall-through */ case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - yuv_mode = 1; - switch (pcdev->camera_fmt->fourcc) { + pcdev->image_mode = 1; + switch (cam->camera_fmt->fourcc) { case V4L2_PIX_FMT_UYVY: value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ break; @@ -498,36 +592,16 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; value |= common_flags & SOCAM_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; - value |= buswidth == 16 ? 1 << 12 : 0; + value |= pcdev->is_16bit ? 1 << 12 : 0; ceu_write(pcdev, CAMCR, value); ceu_write(pcdev, CAPCR, 0x00300000); ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0); mdelay(1); + sh_mobile_ceu_set_rect(icd, &icd->rect_current); - if (yuv_mode) { - width = icd->rect_current.width * 2; - width = buswidth == 16 ? width / 2 : width; - cfszr_width = cdwdr_width = icd->rect_current.width; - } else { - width = icd->rect_current.width * - ((icd->current_fmt->depth + 7) >> 3); - width = buswidth == 16 ? width / 2 : width; - cfszr_width = buswidth == 8 ? width / 2 : width; - cdwdr_width = buswidth == 16 ? width * 2 : width; - } - - height = icd->rect_current.height; - if (pcdev->is_interlaced) { - height /= 2; - cdwdr_width *= 2; - } - - ceu_write(pcdev, CAMOR, 0); - ceu_write(pcdev, CAPWR, (height << 16) | width); ceu_write(pcdev, CFLCR, 0); /* no scaling */ - ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width); /* A few words about byte order (observed in Big Endian mode) * @@ -546,10 +620,16 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, value &= ~0x00000010; /* convert 4:2:2 -> 4:2:0 */ ceu_write(pcdev, CDOCR, value); - - ceu_write(pcdev, CDWDR, cdwdr_width); ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ + dev_dbg(&icd->dev, "S_FMT successful for %c%c%c%c %ux%u@%u.%u\n", + pixfmt & 0xff, (pixfmt >> 8) & 0xff, + (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff, + icd->rect_current.width, icd->rect_current.height, + icd->rect_current.left, icd->rect_current.top); + + capture_restore(pcdev, capsr); + /* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */ return 0; } @@ -602,21 +682,32 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int ret, k, n; int formats = 0; + struct sh_mobile_ceu_cam *cam; ret = sh_mobile_ceu_try_bus_param(icd); if (ret < 0) return 0; + if (!icd->host_priv) { + cam = kzalloc(sizeof(*cam), GFP_KERNEL); + if (!cam) + return -ENOMEM; + + icd->host_priv = cam; + } else { + cam = icd->host_priv; + } + /* Beginning of a pass */ if (!idx) - icd->host_priv = NULL; + cam->extra_fmt = NULL; switch (icd->formats[idx].fourcc) { case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_VYUY: case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_YVYU: - if (icd->host_priv) + if (cam->extra_fmt) goto add_single_format; /* @@ -628,7 +719,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, * the host_priv pointer and check whether the format you're * going to add now is already there. */ - icd->host_priv = (void *)sh_mobile_ceu_formats; + cam->extra_fmt = (void *)sh_mobile_ceu_formats; n = ARRAY_SIZE(sh_mobile_ceu_formats); formats += n; @@ -659,18 +750,130 @@ add_single_format: return formats; } +static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd) +{ + kfree(icd->host_priv); + icd->host_priv = NULL; +} + +static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2) +{ + return r1->width < r2->width || r1->height < r2->height; +} + static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { - return icd->ops->set_crop(icd, rect); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; + struct v4l2_rect cam_rect = *rect; + struct sh_mobile_ceu_cam *cam = icd->host_priv; + unsigned short width, height; + u32 capsr; + int ret; + + capsr = capture_save_reset(pcdev); + dev_dbg(&icd->dev, "CAPSR %x\n", capsr); + + ret = icd->ops->set_crop(icd, &cam_rect); + if (!ret && !memcmp(rect, &cam_rect, sizeof(*rect))) { + dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u.%u\n", + cam_rect.width, cam_rect.height, + cam_rect.left, cam_rect.top); + goto ceu_set_rect; + } + + /* Try to fix cropping, that camera hasn't managed to do */ + dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u.%u\n", + ret, cam_rect.width, cam_rect.height, + cam_rect.left, cam_rect.top); + + /* + * Popular special case - some cameras can only handle fixed sizes like + * QVGA, VGA,... Take care to avoid infinite loop. + */ + width = max(cam_rect.width, 1) * 2; + height = max(cam_rect.height, 1) * 2; + while (!ret && is_smaller(&cam_rect, rect) && + (icd->rect_max.width >= width && + icd->rect_max.height >= height)) { + cam_rect.width = width; + cam_rect.height = height; + + if (cam_rect.width + cam_rect.left > + icd->rect_max.width + icd->rect_max.left) + cam_rect.left = icd->rect_max.width + + icd->rect_max.left - cam_rect.width; + + if (cam_rect.height + cam_rect.top > + icd->rect_max.height + icd->rect_max.top) + cam_rect.top = icd->rect_max.height + + icd->rect_max.top - cam_rect.height; + + ret = icd->ops->set_crop(icd, &cam_rect); + dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u.%u\n", + ret, cam_rect.width, cam_rect.height, + cam_rect.left, cam_rect.top); + width *= 2; + height *= 2; + } + + /* + * If the camera failed to configure cropping, it should not modify the + * rectangle + */ + if ((ret < 0 && is_smaller(&icd->rect_current, rect)) || + is_smaller(&cam_rect, rect)) { + /* + * The camera failed to configure a suitable cropping, + * we cannot use the current rectangle, set to max + */ + cam_rect = icd->rect_max; + ret = icd->ops->set_crop(icd, &cam_rect); + dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u.%u\n", + ret, cam_rect.width, cam_rect.height, + cam_rect.left, cam_rect.top); + if (ret < 0) + /* All failed, hopefully resume current capture */ + goto resume_capture; + } + + /* We now have a rectangle, larger than requested, let's crop */ + + /* + * We have to preserve camera rectangle between close() / open(), + * because soc-camera core calls .set_fmt() on each first open() with + * last before last close() _user_ rectangle, which can be different + * from camera rectangle. + */ + dev_dbg(&icd->dev, "SH S_CROP from %ux%u@%u.%u to %ux%u@%u.%u\n", + cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top, + rect->width, rect->height, rect->left, rect->top); + + ret = 0; + +ceu_set_rect: + cam->camera_rect = cam_rect; + + /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */ + if (pcdev->active) + capsr |= 1; + sh_mobile_ceu_set_rect(icd, rect); + capture_restore(pcdev, capsr); + +resume_capture: + + /* Even if only camera cropping succeeded */ + return ret; } static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct sh_mobile_ceu_dev *pcdev = ici->priv; - __u32 pixfmt = f->fmt.pix.pixelformat; + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_pix_format *pix = &f->fmt.pix; + __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; int ret; @@ -680,13 +883,17 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, return -EINVAL; } - f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc; + pix->pixelformat = xlate->cam_fmt->fourcc; ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_fmt, f); - f->fmt.pix.pixelformat = pixfmt; + pix->pixelformat = pixfmt; if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; - pcdev->camera_fmt = xlate->cam_fmt; + cam->camera_fmt = xlate->cam_fmt; + cam->camera_rect.width = pix->width; + cam->camera_rect.height = pix->height; + cam->camera_rect.left = icd->rect_current.left; + cam->camera_rect.top = icd->rect_current.top; } return ret; @@ -698,7 +905,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; const struct soc_camera_format_xlate *xlate; - __u32 pixfmt = f->fmt.pix.pixelformat; + struct v4l2_pix_format *pix = &f->fmt.pix; + __u32 pixfmt = pix->pixelformat; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); @@ -709,27 +917,27 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, /* FIXME: calculate using depth and bus width */ - v4l_bound_align_image(&f->fmt.pix.width, 2, 2560, 1, - &f->fmt.pix.height, 4, 1920, 2, 0); + v4l_bound_align_image(&pix->width, 2, 2560, 1, + &pix->height, 4, 1920, 2, 0); - f->fmt.pix.bytesperline = f->fmt.pix.width * + pix->bytesperline = pix->width * DIV_ROUND_UP(xlate->host_fmt->depth, 8); - f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + pix->sizeimage = pix->height * pix->bytesperline; - f->fmt.pix.pixelformat = xlate->cam_fmt->fourcc; + pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, try_fmt, f); - f->fmt.pix.pixelformat = pixfmt; + pix->pixelformat = pixfmt; if (ret < 0) return ret; - switch (f->fmt.pix.field) { + switch (pix->field) { case V4L2_FIELD_INTERLACED: pcdev->is_interlaced = 1; break; case V4L2_FIELD_ANY: - f->fmt.pix.field = V4L2_FIELD_NONE; + pix->field = V4L2_FIELD_NONE; /* fall-through */ case V4L2_FIELD_NONE: pcdev->is_interlaced = 0; @@ -858,6 +1066,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .add = sh_mobile_ceu_add_device, .remove = sh_mobile_ceu_remove_device, .get_formats = sh_mobile_ceu_get_formats, + .put_formats = sh_mobile_ceu_put_formats, .set_crop = sh_mobile_ceu_set_crop, .set_fmt = sh_mobile_ceu_set_fmt, .try_fmt = sh_mobile_ceu_try_fmt, -- cgit v1.2.3 From 0b4b46ce45c942a26e9a5b68cd826cbbcfb39d8f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:52 +0200 Subject: tw9910: return updated geometry on successful S_FMT and S_CROP From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/tw9910.c | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-) --- linux/drivers/media/video/tw9910.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index f1a146807..29bafb3f3 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -699,6 +699,11 @@ static int tw9910_set_crop(struct soc_camera_device *icd, if (ret < 0) goto tw9910_set_fmt_error; + rect->width = priv->scale->width; + rect->height = priv->scale->height; + rect->left = 0; + rect->top = 0; + return ret; tw9910_set_fmt_error: @@ -720,7 +725,7 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) .width = pix->width, .height = pix->height, }; - int i; + int i, ret; /* * check color format @@ -732,7 +737,12 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) if (i == ARRAY_SIZE(tw9910_color_fmt)) return -EINVAL; - return tw9910_set_crop(icd, &rect); + ret = tw9910_set_crop(icd, &rect); + if (!ret) { + pix->width = rect.width; + pix->height = rect.height; + } + return ret; } static int tw9910_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) -- cgit v1.2.3 From 4325d71881ee891f6b5313cdb76c08c1d95d2091 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:52 +0200 Subject: soc-camera: S_CROP V4L2 API compliance fix From: Guennadi Liakhovetski V4L2 API mandates, that drivers do not update the argument of the S_CROP ioctl() with the actual geometry. Comply. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 39 ++++++++++++++++++++++--------------- 1 files changed, 23 insertions(+), 16 deletions(-) --- linux/drivers/media/video/soc_camera.c | 39 ++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 104496141..e4740359d 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -748,12 +748,19 @@ static int soc_camera_g_crop(struct file *file, void *fh, return 0; } +/* + * According to the V4L2 API, drivers shall not update the struct v4l2_crop + * argument with the actual geometry, instead, the user shall use G_CROP to + * retrieve it. However, we expect camera host and client drivers to update + * the argument, which we then use internally, but do not return to the user. + */ static int soc_camera_s_crop(struct file *file, void *fh, struct v4l2_crop *a) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_rect rect = a->c; int ret; if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) @@ -762,29 +769,29 @@ static int soc_camera_s_crop(struct file *file, void *fh, /* Cropping is allowed during a running capture, guard consistency */ mutex_lock(&icf->vb_vidq.vb_lock); - if (a->c.width > icd->rect_max.width) - a->c.width = icd->rect_max.width; + if (rect.width > icd->rect_max.width) + rect.width = icd->rect_max.width; - if (a->c.width < icd->width_min) - a->c.width = icd->width_min; + if (rect.width < icd->width_min) + rect.width = icd->width_min; - if (a->c.height > icd->rect_max.height) - a->c.height = icd->rect_max.height; + if (rect.height > icd->rect_max.height) + rect.height = icd->rect_max.height; - if (a->c.height < icd->height_min) - a->c.height = icd->height_min; + if (rect.height < icd->height_min) + rect.height = icd->height_min; - if (a->c.width + a->c.left > icd->rect_max.width + icd->rect_max.left) - a->c.left = icd->rect_max.width + icd->rect_max.left - - a->c.width; + if (rect.width + rect.left > icd->rect_max.width + icd->rect_max.left) + rect.left = icd->rect_max.width + icd->rect_max.left - + rect.width; - if (a->c.height + a->c.top > icd->rect_max.height + icd->rect_max.top) - a->c.top = icd->rect_max.height + icd->rect_max.top - - a->c.height; + if (rect.height + rect.top > icd->rect_max.height + icd->rect_max.top) + rect.top = icd->rect_max.height + icd->rect_max.top - + rect.height; - ret = ici->ops->set_crop(icd, &a->c); + ret = ici->ops->set_crop(icd, &rect); if (!ret) - icd->rect_current = a->c; + icd->rect_current = rect; mutex_unlock(&icf->vb_vidq.vb_lock); -- cgit v1.2.3 From fee3ccfc8db428f3108858be9c73a4c28a618e4d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:53 +0200 Subject: soc-camera: prohibit geometry change with initialised buffers From: Guennadi Liakhovetski Prohibit S_FMT and S_CROP with a different window width or height after video buffer initialisation. This simplifies the work to be done in specific host and client drivers, and it doesn't seem to make much sense to allow these changes. We do however allow S_CROP with equal width and height to just move the window, this doesn't affect video buffer management and is usually easy enough to implement. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-) --- linux/drivers/media/video/soc_camera.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index e4740359d..ec564a90e 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -518,8 +518,8 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, mutex_lock(&icf->vb_vidq.vb_lock); - if (videobuf_queue_is_busy(&icf->vb_vidq)) { - dev_err(&icd->dev, "S_FMT denied: queue busy\n"); + if (icf->vb_vidq.bufs[0]) { + dev_err(&icd->dev, "S_FMT denied: queue initialised\n"); ret = -EBUSY; goto unlock; } @@ -769,6 +769,15 @@ static int soc_camera_s_crop(struct file *file, void *fh, /* Cropping is allowed during a running capture, guard consistency */ mutex_lock(&icf->vb_vidq.vb_lock); + /* Prohibit window size change with initialised buffers */ + if (icf->vb_vidq.bufs[0] && (rect.width != icd->rect_current.width || + rect.height != icd->rect_current.height)) { + dev_err(&icd->dev, + "S_CROP denied: queue initialised and sizes differ\n"); + ret = -EBUSY; + goto unlock; + } + if (rect.width > icd->rect_max.width) rect.width = icd->rect_max.width; @@ -793,6 +802,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, if (!ret) icd->rect_current = rect; +unlock: mutex_unlock(&icf->vb_vidq.vb_lock); return ret; -- cgit v1.2.3 From 4eb5903e517a1d50a63f75fef61090f5f90b81ea Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:53 +0200 Subject: ov772x: do not use scaling for cropping From: Guennadi Liakhovetski OV772x sensors cannot crop, they only support two fixed formats: VGA and QVGA. We should not change the format when requested to crop, only S_FMT can do this. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/ov772x.c | 17 ++++++++--------- 1 files changed, 8 insertions(+), 9 deletions(-) --- linux/drivers/media/video/ov772x.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 700f655fd..e8bb337da 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -955,23 +955,22 @@ ov772x_set_fmt_error: return ret; } +/* Cannot crop, just return the current geometry */ static int ov772x_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct ov772x_priv *priv = to_ov772x(client); - int ret; - if (!priv->fmt) + if (!priv->fmt || !priv->win) return -EINVAL; - ret = ov772x_set_params(client, &rect->width, &rect->height, - priv->fmt->fourcc); - if (!ret) { - rect->left = 0; - rect->top = 0; - } - return ret; + rect->left = 0; + rect->top = 0; + rect->width = priv->win->width; + rect->height = priv->win->height; + + return 0; } static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) -- cgit v1.2.3 From 9be813fc0bfdb82513f0e232f0dda18b2dba8e84 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:53 +0200 Subject: tw9910: do not lie about cropping abilities From: Guennadi Liakhovetski The current tw9910 driver does not implement cropping correctly. Therefore, and also because various rectangles in struct soc_camera_device are in user scale, we cannot and shall not use rect_current as window location. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/tw9910.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) --- linux/drivers/media/video/tw9910.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 29bafb3f3..852c7859f 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -719,9 +719,10 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct i2c_client *client = sd->priv; struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; + /* See tw9910_set_crop() - no proper cropping support */ struct v4l2_rect rect = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, + .left = 0, + .top = 0, .width = pix->width, .height = pix->height, }; @@ -850,6 +851,7 @@ static struct v4l2_subdev_ops tw9910_subdev_ops = { * i2c_driver function */ +/* This is called during probe, so, setting rect_max is Ok here: scale == 1 */ static void limit_to_scale(struct soc_camera_device *icd, const struct tw9910_scale_ctrl *scale) { -- cgit v1.2.3 From 6bd7b0281dd65988d5cf613bc99541ef4a8f16cf Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:54 +0200 Subject: sh_mobile_ceu_camera: implement host-side image scaling From: Guennadi Liakhovetski Use host-side image scaling when the client fails to set the requested format. We also have to take scaling into account when performing host-side cropping. Similar to cropping we try to use client-side scaling as much as possible to preserve bus bandwidth and optimise the frame-rate. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/sh_mobile_ceu_camera.c | 392 +++++++++++++++++++++++----- 1 files changed, 321 insertions(+), 71 deletions(-) --- linux/drivers/media/video/sh_mobile_ceu_camera.c | 392 +++++++++++++++++++---- 1 file changed, 321 insertions(+), 71 deletions(-) diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index befc84ce1..a1108cc03 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -97,6 +97,8 @@ struct sh_mobile_ceu_dev { struct sh_mobile_ceu_info *pdata; + u32 cflcr; + unsigned int is_interlaced:1; unsigned int image_mode:1; unsigned int is_16bit:1; @@ -104,6 +106,7 @@ struct sh_mobile_ceu_dev { struct sh_mobile_ceu_cam { struct v4l2_rect camera_rect; + struct v4l2_rect camera_max; const struct soc_camera_data_format *extra_fmt; const struct soc_camera_data_format *camera_fmt; }; @@ -437,54 +440,119 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) pcdev->icd = NULL; } +/* + * See chapter 29.4.12 "Capture Filter Control Register (CFLCR)" + * in SH7722 Hardware Manual + */ +static unsigned int size_dst(unsigned int src, unsigned int scale) +{ + unsigned int mant_pre = scale >> 12; + if (!src || !scale) + return src; + return ((mant_pre + 2 * (src - 1)) / (2 * mant_pre) - 1) * + mant_pre * 4096 / scale + 1; +} + +static unsigned int size_src(unsigned int dst, unsigned int scale) +{ + unsigned int mant_pre = scale >> 12, tmp; + if (!dst || !scale) + return dst; + for (tmp = ((dst - 1) * scale + 2048 * mant_pre) / 4096 + 1; + size_dst(tmp, scale) < dst; + tmp++) + ; + return tmp; +} + +static u16 calc_scale(unsigned int src, unsigned int *dst) +{ + u16 scale; + + if (src == *dst) + return 0; + + scale = (src * 4096 / *dst) & ~7; + + while (scale > 4096 && size_dst(src, scale) < *dst) + scale -= 8; + + *dst = size_dst(src, scale); + + return scale; +} + +/* rect is guaranteed to not exceed the scaled camera rectangle */ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_cam *cam = icd->host_priv; struct sh_mobile_ceu_dev *pcdev = ici->priv; - int width, height, cfszr_width, cdwdr_width; - unsigned int left_offset, top_offset; + int width, height, cfszr_width, cdwdr_width, in_width, in_height; + unsigned int left_offset, top_offset, left, top; + unsigned int hscale = pcdev->cflcr & 0xffff; + unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; u32 camor; - if (rect->left > cam->camera_rect.left) { - left_offset = rect->left - cam->camera_rect.left; + /* Switch to the camera scale */ + left = size_src(rect->left, hscale); + top = size_src(rect->top, vscale); + + dev_dbg(&icd->dev, "Left %u * 0x%x = %u, top %u * 0x%x = %u\n", + rect->left, hscale, left, rect->top, vscale, top); + + if (left > cam->camera_rect.left) { + left_offset = left - cam->camera_rect.left; } else { left_offset = 0; - rect->left = cam->camera_rect.left; + left = cam->camera_rect.left; } - if (rect->top > cam->camera_rect.top) { - top_offset = rect->top - cam->camera_rect.top; + if (top > cam->camera_rect.top) { + top_offset = top - cam->camera_rect.top; } else { top_offset = 0; - rect->top = cam->camera_rect.top; + top = cam->camera_rect.top; } - dev_dbg(&icd->dev, "Offsets %u:%u\n", left_offset, top_offset); + dev_dbg(&icd->dev, "New left %u, top %u, offsets %u:%u\n", + rect->left, rect->top, left_offset, top_offset); if (pcdev->image_mode) { width = rect->width; - if (!pcdev->is_16bit) + in_width = cam->camera_rect.width; + if (!pcdev->is_16bit) { width *= 2; + in_width *= 2; + left_offset *= 2; + } cfszr_width = cdwdr_width = rect->width; } else { - width = rect->width * - ((icd->current_fmt->depth + 7) >> 3); - width = pcdev->is_16bit ? width / 2 : width; + unsigned int w_factor = (icd->current_fmt->depth + 7) >> 3; + if (!pcdev->is_16bit) + w_factor *= 2; + + width = rect->width * w_factor / 2; + in_width = cam->camera_rect.width * w_factor / 2; + left_offset = left_offset * w_factor / 2; + cfszr_width = pcdev->is_16bit ? width : width / 2; cdwdr_width = pcdev->is_16bit ? width * 2 : width; } height = rect->height; + in_height = cam->camera_rect.height; if (pcdev->is_interlaced) { height /= 2; + in_height /= 2; + top_offset /= 2; cdwdr_width *= 2; } camor = left_offset | (top_offset << 16); ceu_write(pcdev, CAMOR, camor); - ceu_write(pcdev, CAPWR, (height << 16) | width); + ceu_write(pcdev, CAPWR, (in_height << 16) | in_width); ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width); ceu_write(pcdev, CDWDR, cdwdr_width); } @@ -558,7 +626,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CRCMPR, 0); value = 0x00000010; /* data fetch by default */ - pcdev->image_mode = yuv_lineskip = 0; + yuv_lineskip = 0; switch (icd->current_fmt->fourcc) { case V4L2_PIX_FMT_NV12: @@ -567,7 +635,6 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, /* fall-through */ case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - pcdev->image_mode = 1; switch (cam->camera_fmt->fourcc) { case V4L2_PIX_FMT_UYVY: value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ @@ -601,7 +668,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, mdelay(1); sh_mobile_ceu_set_rect(icd, &icd->rect_current); - ceu_write(pcdev, CFLCR, 0); /* no scaling */ + ceu_write(pcdev, CFLCR, pcdev->cflcr); /* A few words about byte order (observed in Big Endian mode) * @@ -622,7 +689,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CDOCR, value); ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ - dev_dbg(&icd->dev, "S_FMT successful for %c%c%c%c %ux%u@%u.%u\n", + dev_dbg(&icd->dev, "S_FMT successful for %c%c%c%c %ux%u@%u:%u\n", pixfmt & 0xff, (pixfmt >> 8) & 0xff, (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff, icd->rect_current.width, icd->rect_current.height, @@ -694,6 +761,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, return -ENOMEM; icd->host_priv = cam; + cam->camera_max = icd->rect_max; } else { cam = icd->host_priv; } @@ -756,86 +824,150 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd) icd->host_priv = NULL; } +/* Check if any dimension of r1 is smaller than respective one of r2 */ static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2) { return r1->width < r2->width || r1->height < r2->height; } +/* Check if r1 fails to cover r2 */ +static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2) +{ + return r1->left > r2->left || r1->top > r2->top || + r1->left + r1->width < r2->left + r2->width || + r1->top + r1->height < r2->top + r2->height; +} + +/* + * CEU can scale and crop, but we don't want to waste bandwidth and kill the + * framerate by always requesting the maximum image from the client. For + * cropping we also have to take care of the current scale. The common for both + * scaling and cropping approach is: + * 1. try if the client can produce exactly what requested by the user + * 2. if (1) failed, try to double the client image until we get one big enough + * 3. if (2) failed, try to request the maximum image + */ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - struct v4l2_rect cam_rect = *rect; + struct v4l2_rect cam_rect, target, cam_max; struct sh_mobile_ceu_cam *cam = icd->host_priv; + unsigned int hscale = pcdev->cflcr & 0xffff; + unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; unsigned short width, height; u32 capsr; int ret; + /* Scale back up into client units */ + cam_rect.left = size_src(rect->left, hscale); + cam_rect.width = size_src(rect->width, hscale); + cam_rect.top = size_src(rect->top, vscale); + cam_rect.height = size_src(rect->height, vscale); + + target = cam_rect; + capsr = capture_save_reset(pcdev); - dev_dbg(&icd->dev, "CAPSR %x\n", capsr); + dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); + /* First attempt - see if the client can deliver a perfect result */ ret = icd->ops->set_crop(icd, &cam_rect); - if (!ret && !memcmp(rect, &cam_rect, sizeof(*rect))) { - dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u.%u\n", + if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) { + dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n", cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top); goto ceu_set_rect; } /* Try to fix cropping, that camera hasn't managed to do */ - dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u.%u\n", + dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u" + " to %ux%u@%u:%u\n", ret, cam_rect.width, cam_rect.height, - cam_rect.left, cam_rect.top); + cam_rect.left, cam_rect.top, + target.width, target.height, target.left, target.top); /* * Popular special case - some cameras can only handle fixed sizes like * QVGA, VGA,... Take care to avoid infinite loop. */ - width = max(cam_rect.width, 1) * 2; - height = max(cam_rect.height, 1) * 2; - while (!ret && is_smaller(&cam_rect, rect) && - (icd->rect_max.width >= width && - icd->rect_max.height >= height)) { + width = max(cam_rect.width, 1); + height = max(cam_rect.height, 1); + cam_max.width = size_src(icd->rect_max.width, hscale); + cam_max.left = size_src(icd->rect_max.left, hscale); + cam_max.height = size_src(icd->rect_max.height, vscale); + cam_max.top = size_src(icd->rect_max.top, vscale); + while (!ret && (is_smaller(&cam_rect, &target) || + is_inside(&cam_rect, &target)) && + cam_max.width >= width && cam_max.height >= height) { + + width *= 2; + height *= 2; cam_rect.width = width; cam_rect.height = height; + /* We do not know what the camera is capable of, play safe */ + if (cam_rect.left > target.left) + cam_rect.left = cam_max.left; + + if (cam_rect.left + cam_rect.width < target.left + target.width) + cam_rect.width = target.left + target.width - + cam_rect.left; + + if (cam_rect.top > target.top) + cam_rect.top = cam_max.top; + + if (cam_rect.top + cam_rect.height < target.top + target.height) + cam_rect.height = target.top + target.height - + cam_rect.top; + if (cam_rect.width + cam_rect.left > - icd->rect_max.width + icd->rect_max.left) - cam_rect.left = icd->rect_max.width + - icd->rect_max.left - cam_rect.width; + cam_max.width + cam_max.left) + cam_rect.left = max(cam_max.width + cam_max.left - + cam_rect.width, cam_max.left); if (cam_rect.height + cam_rect.top > - icd->rect_max.height + icd->rect_max.top) - cam_rect.top = icd->rect_max.height + - icd->rect_max.top - cam_rect.height; + cam_max.height + cam_max.top) + cam_rect.top = max(cam_max.height + cam_max.top - + cam_rect.height, cam_max.top); ret = icd->ops->set_crop(icd, &cam_rect); - dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u.%u\n", + dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n", ret, cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top); - width *= 2; - height *= 2; } /* * If the camera failed to configure cropping, it should not modify the * rectangle */ - if ((ret < 0 && is_smaller(&icd->rect_current, rect)) || - is_smaller(&cam_rect, rect)) { + if ((ret < 0 && (is_smaller(&icd->rect_current, rect) || + is_inside(&icd->rect_current, rect))) || + is_smaller(&cam_rect, &target) || is_inside(&cam_rect, &target)) { /* * The camera failed to configure a suitable cropping, * we cannot use the current rectangle, set to max */ - cam_rect = icd->rect_max; + cam_rect = cam_max; ret = icd->ops->set_crop(icd, &cam_rect); - dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u.%u\n", + dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", ret, cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top); if (ret < 0) /* All failed, hopefully resume current capture */ goto resume_capture; + + /* Finally, adjust the target rectangle */ + if (target.width > cam_rect.width) + target.width = cam_rect.width; + if (target.height > cam_rect.height) + target.height = cam_rect.height; + if (target.left + target.width > cam_rect.left + cam_rect.width) + target.left = cam_rect.left + cam_rect.width - + target.width; + if (target.top + target.height > cam_rect.top + cam_rect.height) + target.top = cam_rect.top + cam_rect.height - + target.height; } /* We now have a rectangle, larger than requested, let's crop */ @@ -846,8 +978,10 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, * last before last close() _user_ rectangle, which can be different * from camera rectangle. */ - dev_dbg(&icd->dev, "SH S_CROP from %ux%u@%u.%u to %ux%u@%u.%u\n", + dev_dbg(&icd->dev, + "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n", cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top, + target.width, target.height, target.left, target.top, rect->width, rect->height, rect->left, rect->top); ret = 0; @@ -855,27 +989,49 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, ceu_set_rect: cam->camera_rect = cam_rect; + rect->width = size_dst(target.width, hscale); + rect->left = size_dst(target.left, hscale); + rect->height = size_dst(target.height, vscale); + rect->top = size_dst(target.top, vscale); + + sh_mobile_ceu_set_rect(icd, rect); + +resume_capture: /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */ if (pcdev->active) capsr |= 1; - sh_mobile_ceu_set_rect(icd, rect); capture_restore(pcdev, capsr); -resume_capture: - /* Even if only camera cropping succeeded */ return ret; } +/* Similar to set_crop multistage iterative algorithm */ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_pix_format *pix = &f->fmt.pix; __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; - int ret; + unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h; + u16 vscale, hscale; + int ret, is_interlaced; + + switch (pix->field) { + case V4L2_FIELD_INTERLACED: + is_interlaced = 1; + break; + case V4L2_FIELD_ANY: + default: + pix->field = V4L2_FIELD_NONE; + /* fall-through */ + case V4L2_FIELD_NONE: + is_interlaced = 0; + break; + } xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { @@ -886,27 +1042,104 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, pix->pixelformat = xlate->cam_fmt->fourcc; ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_fmt, f); pix->pixelformat = pixfmt; - if (!ret) { - icd->buswidth = xlate->buswidth; - icd->current_fmt = xlate->host_fmt; - cam->camera_fmt = xlate->cam_fmt; - cam->camera_rect.width = pix->width; - cam->camera_rect.height = pix->height; - cam->camera_rect.left = icd->rect_current.left; - cam->camera_rect.top = icd->rect_current.top; + dev_dbg(&icd->dev, "Camera %d fmt %ux%u, requested %ux%u, max %ux%u\n", + ret, pix->width, pix->height, width, height, + icd->rect_max.width, icd->rect_max.height); + if (ret < 0) + return ret; + + switch (pixfmt) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + pcdev->image_mode = 1; + break; + default: + pcdev->image_mode = 0; } - return ret; + if ((abs(width - pix->width) < 4 && abs(height - pix->height) < 4) || + !pcdev->image_mode || is_interlaced) { + hscale = 0; + vscale = 0; + goto out; + } + + /* Camera set a format, but geometry is not precise, try to improve */ + /* + * FIXME: when soc-camera is converted to implement traditional S_FMT + * and S_CROP semantics, replace CEU limits with camera maxima + */ + tmp_w = pix->width; + tmp_h = pix->height; + while ((width > tmp_w || height > tmp_h) && + tmp_w < 2560 && tmp_h < 1920) { + tmp_w = min(2 * tmp_w, (__u32)2560); + tmp_h = min(2 * tmp_h, (__u32)1920); + pix->width = tmp_w; + pix->height = tmp_h; + pix->pixelformat = xlate->cam_fmt->fourcc; + ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, + video, s_fmt, f); + pix->pixelformat = pixfmt; + dev_dbg(&icd->dev, "Camera scaled to %ux%u\n", + pix->width, pix->height); + if (ret < 0) { + /* This shouldn't happen */ + dev_err(&icd->dev, "Client failed to set format: %d\n", + ret); + return ret; + } + } + + /* We cannot scale up */ + if (width > pix->width) + width = pix->width; + + if (height > pix->height) + height = pix->height; + + /* Let's rock: scale pix->{width x height} down to width x height */ + hscale = calc_scale(pix->width, &width); + vscale = calc_scale(pix->height, &height); + + dev_dbg(&icd->dev, "W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", + pix->width, hscale, width, pix->height, vscale, height); + +out: + pcdev->cflcr = hscale | (vscale << 16); + + icd->buswidth = xlate->buswidth; + icd->current_fmt = xlate->host_fmt; + cam->camera_fmt = xlate->cam_fmt; + cam->camera_rect.width = pix->width; + cam->camera_rect.height = pix->height; + + icd->rect_max.left = size_dst(cam->camera_max.left, hscale); + icd->rect_max.width = size_dst(cam->camera_max.width, hscale); + icd->rect_max.top = size_dst(cam->camera_max.top, vscale); + icd->rect_max.height = size_dst(cam->camera_max.height, vscale); + + icd->rect_current.left = icd->rect_max.left; + icd->rect_current.top = icd->rect_max.top; + + pcdev->is_interlaced = is_interlaced; + + pix->width = width; + pix->height = height; + + return 0; } static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct sh_mobile_ceu_dev *pcdev = ici->priv; const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; __u32 pixfmt = pix->pixelformat; + int width, height; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); @@ -920,6 +1153,9 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, v4l_bound_align_image(&pix->width, 2, 2560, 1, &pix->height, 4, 1920, 2, 0); + width = pix->width; + height = pix->height; + pix->bytesperline = pix->width * DIV_ROUND_UP(xlate->host_fmt->depth, 8); pix->sizeimage = pix->height * pix->bytesperline; @@ -927,24 +1163,38 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, try_fmt, f); + ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, + try_fmt, f); pix->pixelformat = pixfmt; if (ret < 0) return ret; - switch (pix->field) { - case V4L2_FIELD_INTERLACED: - pcdev->is_interlaced = 1; - break; - case V4L2_FIELD_ANY: - pix->field = V4L2_FIELD_NONE; - /* fall-through */ - case V4L2_FIELD_NONE: - pcdev->is_interlaced = 0; - break; - default: - ret = -EINVAL; - break; + switch (pixfmt) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + /* FIXME: check against rect_max after converting soc-camera */ + /* We can scale precisely, need a bigger image from camera */ + if (pix->width < width || pix->height < height) { + int tmp_w = pix->width, tmp_h = pix->height; + pix->width = 2560; + pix->height = 1920; + ret = v4l2_device_call_until_err(&ici->v4l2_dev, + (__u32)icd, video, + try_fmt, f); + if (ret < 0) { + /* Shouldn't actually happen... */ + dev_err(&icd->dev, + "FIXME: try_fmt() returned %d\n", ret); + pix->width = tmp_w; + pix->height = tmp_h; + } + } + if (pix->width > width) + pix->width = width; + if (pix->height > height) + pix->height = height; } return ret; -- cgit v1.2.3 From a94ff67f3f3091badb6034566504ad58206989ef Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:54 +0200 Subject: soc-camera: switch to s_crop v4l2-subdev video operation From: Guennadi Liakhovetski Remove set_crop soc-camera device method and switch to s_crop from v4l2-subdev video operations. Also extend non-i2c drivers to also hold a pointer to their v4l2-subdev instance in control device driver-data, i.e., in dev_get_drvdata((struct device *)to_soc_camera_control(icd)) Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9m001.c | 23 +++--- drivers/media/video/mt9m111.c | 9 +- drivers/media/video/mt9t031.c | 9 +- drivers/media/video/mt9v022.c | 23 +++--- drivers/media/video/mx1_camera.c | 8 ++- drivers/media/video/mx3_camera.c | 7 +- drivers/media/video/ov772x.c | 19 ----- drivers/media/video/pxa_camera.c | 7 +- drivers/media/video/sh_mobile_ceu_camera.c | 110 ++++++++++++++------------- drivers/media/video/soc_camera.c | 4 +- drivers/media/video/soc_camera_platform.c | 28 ++++---- drivers/media/video/tw9910.c | 31 ++++---- include/media/soc_camera.h | 3 +- 13 files changed, 142 insertions(+), 139 deletions(-) --- linux/drivers/media/video/mt9m001.c | 23 ++--- linux/drivers/media/video/mt9m111.c | 9 +- linux/drivers/media/video/mt9t031.c | 9 +- linux/drivers/media/video/mt9v022.c | 23 ++--- linux/drivers/media/video/mx1_camera.c | 8 +- linux/drivers/media/video/mx3_camera.c | 7 +- linux/drivers/media/video/ov772x.c | 19 ---- linux/drivers/media/video/pxa_camera.c | 7 +- linux/drivers/media/video/sh_mobile_ceu_camera.c | 110 ++++++++++++----------- linux/drivers/media/video/soc_camera.c | 4 +- linux/drivers/media/video/soc_camera_platform.c | 28 +++--- linux/drivers/media/video/tw9910.c | 31 +++---- linux/include/media/soc_camera.h | 3 +- 13 files changed, 142 insertions(+), 139 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 7a9435f9b..b74ef6cea 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -194,11 +194,12 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, flags); } -static int mt9m001_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) +static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct v4l2_rect *rect = &a->c; + struct i2c_client *client = sd->priv; struct mt9m001 *mt9m001 = to_mt9m001(client); + struct soc_camera_device *icd = client->dev.platform_data; int ret; const u16 hblank = 9, vblank = 25; @@ -239,15 +240,17 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; struct soc_camera_device *icd = client->dev.platform_data; - struct v4l2_rect rect = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, - .width = f->fmt.pix.width, - .height = f->fmt.pix.height, + struct v4l2_crop a = { + .c = { + .left = icd->rect_current.left, + .top = icd->rect_current.top, + .width = f->fmt.pix.width, + .height = f->fmt.pix.height, + }, }; /* No support for scaling so far, just crop. TODO: use skipping */ - return mt9m001_set_crop(icd, &rect); + return mt9m001_s_crop(sd, &a); } static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) @@ -361,7 +364,6 @@ static const struct v4l2_queryctrl mt9m001_controls[] = { static struct soc_camera_ops mt9m001_ops = { .init = mt9m001_init, .release = mt9m001_release, - .set_crop = mt9m001_set_crop, .set_bus_param = mt9m001_set_bus_param, .query_bus_param = mt9m001_query_bus_param, .controls = mt9m001_controls, @@ -575,6 +577,7 @@ static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { .s_stream = mt9m001_s_stream, .s_fmt = mt9m001_s_fmt, .try_fmt = mt9m001_try_fmt, + .s_crop = mt9m001_s_crop, }; static struct v4l2_subdev_ops mt9m001_subdev_ops = { diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 8770dfd2a..cab9de000 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -395,11 +395,12 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) return 0; } -static int mt9m111_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) +static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct v4l2_rect *rect = &a->c; + struct i2c_client *client = sd->priv; struct mt9m111 *mt9m111 = to_mt9m111(client); + struct soc_camera_device *icd = client->dev.platform_data; int ret; dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", @@ -601,7 +602,6 @@ static struct soc_camera_ops mt9m111_ops = { .init = mt9m111_init, .resume = mt9m111_resume, .release = mt9m111_release, - .set_crop = mt9m111_set_crop, .query_bus_param = mt9m111_query_bus_param, .set_bus_param = mt9m111_set_bus_param, .controls = mt9m111_controls, @@ -908,6 +908,7 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { .s_fmt = mt9m111_s_fmt, .try_fmt = mt9m111_try_fmt, + .s_crop = mt9m111_s_crop, }; static struct v4l2_subdev_ops mt9m111_subdev_ops = { diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index b69a34c87..6bcea4165 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -321,11 +321,12 @@ static int mt9t031_set_params(struct soc_camera_device *icd, return ret < 0 ? ret : 0; } -static int mt9t031_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) +static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct v4l2_rect *rect = &a->c; + struct i2c_client *client = sd->priv; struct mt9t031 *mt9t031 = to_mt9t031(client); + struct soc_camera_device *icd = client->dev.platform_data; /* Make sure we don't exceed sensor limits */ if (rect->left + rect->width > icd->rect_max.left + icd->rect_max.width) @@ -495,7 +496,6 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { static struct soc_camera_ops mt9t031_ops = { .init = mt9t031_init, .release = mt9t031_release, - .set_crop = mt9t031_set_crop, .set_bus_param = mt9t031_set_bus_param, .query_bus_param = mt9t031_query_bus_param, .controls = mt9t031_controls, @@ -689,6 +689,7 @@ static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { .s_stream = mt9t031_s_stream, .s_fmt = mt9t031_s_fmt, .try_fmt = mt9t031_try_fmt, + .s_crop = mt9t031_s_crop, }; static struct v4l2_subdev_ops mt9t031_subdev_ops = { diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index de74f7bda..088ffa464 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -248,10 +248,11 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) width_flag; } -static int mt9v022_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) +static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct v4l2_rect *rect = &a->c; + struct i2c_client *client = sd->priv; + struct soc_camera_device *icd = client->dev.platform_data; int ret; /* Like in example app. Contradicts the datasheet though */ @@ -297,11 +298,13 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_rect rect = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, - .width = pix->width, - .height = pix->height, + struct v4l2_crop a = { + .c = { + .left = icd->rect_current.left, + .top = icd->rect_current.top, + .width = pix->width, + .height = pix->height, + }, }; /* The caller provides a supported format, as verified per call to @@ -325,7 +328,7 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) } /* No support for scaling on this camera, just crop. */ - return mt9v022_set_crop(icd, &rect); + return mt9v022_s_crop(sd, &a); } static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) @@ -454,7 +457,6 @@ static const struct v4l2_queryctrl mt9v022_controls[] = { static struct soc_camera_ops mt9v022_ops = { .init = mt9v022_init, - .set_crop = mt9v022_set_crop, .set_bus_param = mt9v022_set_bus_param, .query_bus_param = mt9v022_query_bus_param, .controls = mt9v022_controls, @@ -700,6 +702,7 @@ static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { .s_stream = mt9v022_s_stream, .s_fmt = mt9v022_s_fmt, .try_fmt = mt9v022_try_fmt, + .s_crop = mt9v022_s_crop, }; static struct v4l2_subdev_ops mt9v022_subdev_ops = { diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 948a4714b..add496fca 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -463,9 +463,13 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) } static int mx1_camera_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) + struct v4l2_crop *a) { - return icd->ops->set_crop(icd, rect); + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct device *control = to_soc_camera_control(icd); + struct v4l2_subdev *sd = dev_get_drvdata(control); + + return v4l2_subdev_call(sd, video, s_crop, a); } static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index 6c3b7f9b9..de7ebfbf0 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -781,10 +781,13 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) } static int mx3_camera_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) + struct v4l2_crop *a) { + struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; + struct device *control = to_soc_camera_control(icd); + struct v4l2_subdev *sd = dev_get_drvdata(control); /* * We now know pixel formats and can decide upon DMA-channel(s) @@ -798,7 +801,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, configure_geometry(mx3_cam, rect); - return icd->ops->set_crop(icd, rect); + return v4l2_subdev_call(sd, video, s_crop, a); } static int mx3_camera_set_fmt(struct soc_camera_device *icd, diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index e8bb337da..c5b63f420 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -955,24 +955,6 @@ ov772x_set_fmt_error: return ret; } -/* Cannot crop, just return the current geometry */ -static int ov772x_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct ov772x_priv *priv = to_ov772x(client); - - if (!priv->fmt || !priv->win) - return -EINVAL; - - rect->left = 0; - rect->top = 0; - rect->width = priv->win->width; - rect->height = priv->win->height; - - return 0; -} - static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; @@ -1060,7 +1042,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd, } static struct soc_camera_ops ov772x_ops = { - .set_crop = ov772x_set_crop, .set_bus_param = ov772x_set_bus_param, .query_bus_param = ov772x_query_bus_param, .controls = ov772x_controls, diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 6f2aef033..d447e5b59 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1293,10 +1293,13 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, } static int pxa_camera_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) + struct v4l2_crop *a) { + struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; + struct device *control = to_soc_camera_control(icd); + struct v4l2_subdev *sd = dev_get_drvdata(control); struct soc_camera_sense sense = { .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, @@ -1307,7 +1310,7 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) icd->sense = &sense; - ret = icd->ops->set_crop(icd, rect); + ret = v4l2_subdev_call(sd, video, s_crop, a); icd->sense = NULL; diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index a1108cc03..c60088447 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -848,12 +848,16 @@ static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2) * 3. if (2) failed, try to request the maximum image */ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) + struct v4l2_crop *a) { + struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - struct v4l2_rect cam_rect, target, cam_max; + struct v4l2_crop cam_crop; + struct v4l2_rect *cam_rect = &cam_crop.c, target, cam_max; struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct device *control = to_soc_camera_control(icd); + struct v4l2_subdev *sd = dev_get_drvdata(control); unsigned int hscale = pcdev->cflcr & 0xffff; unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; unsigned short width, height; @@ -861,80 +865,80 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, int ret; /* Scale back up into client units */ - cam_rect.left = size_src(rect->left, hscale); - cam_rect.width = size_src(rect->width, hscale); - cam_rect.top = size_src(rect->top, vscale); - cam_rect.height = size_src(rect->height, vscale); + cam_rect->left = size_src(rect->left, hscale); + cam_rect->width = size_src(rect->width, hscale); + cam_rect->top = size_src(rect->top, vscale); + cam_rect->height = size_src(rect->height, vscale); - target = cam_rect; + target = *cam_rect; capsr = capture_save_reset(pcdev); dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); /* First attempt - see if the client can deliver a perfect result */ - ret = icd->ops->set_crop(icd, &cam_rect); + ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) { dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n", - cam_rect.width, cam_rect.height, - cam_rect.left, cam_rect.top); + cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); goto ceu_set_rect; } /* Try to fix cropping, that camera hasn't managed to do */ dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u" " to %ux%u@%u:%u\n", - ret, cam_rect.width, cam_rect.height, - cam_rect.left, cam_rect.top, + ret, cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top, target.width, target.height, target.left, target.top); /* * Popular special case - some cameras can only handle fixed sizes like * QVGA, VGA,... Take care to avoid infinite loop. */ - width = max(cam_rect.width, 1); - height = max(cam_rect.height, 1); + width = max(cam_rect->width, 1); + height = max(cam_rect->height, 1); cam_max.width = size_src(icd->rect_max.width, hscale); cam_max.left = size_src(icd->rect_max.left, hscale); cam_max.height = size_src(icd->rect_max.height, vscale); cam_max.top = size_src(icd->rect_max.top, vscale); - while (!ret && (is_smaller(&cam_rect, &target) || - is_inside(&cam_rect, &target)) && + while (!ret && (is_smaller(cam_rect, &target) || + is_inside(cam_rect, &target)) && cam_max.width >= width && cam_max.height >= height) { width *= 2; height *= 2; - cam_rect.width = width; - cam_rect.height = height; + cam_rect->width = width; + cam_rect->height = height; /* We do not know what the camera is capable of, play safe */ - if (cam_rect.left > target.left) - cam_rect.left = cam_max.left; + if (cam_rect->left > target.left) + cam_rect->left = cam_max.left; - if (cam_rect.left + cam_rect.width < target.left + target.width) - cam_rect.width = target.left + target.width - - cam_rect.left; + if (cam_rect->left + cam_rect->width < target.left + target.width) + cam_rect->width = target.left + target.width - + cam_rect->left; - if (cam_rect.top > target.top) - cam_rect.top = cam_max.top; + if (cam_rect->top > target.top) + cam_rect->top = cam_max.top; - if (cam_rect.top + cam_rect.height < target.top + target.height) - cam_rect.height = target.top + target.height - - cam_rect.top; + if (cam_rect->top + cam_rect->height < target.top + target.height) + cam_rect->height = target.top + target.height - + cam_rect->top; - if (cam_rect.width + cam_rect.left > + if (cam_rect->width + cam_rect->left > cam_max.width + cam_max.left) - cam_rect.left = max(cam_max.width + cam_max.left - - cam_rect.width, cam_max.left); + cam_rect->left = max(cam_max.width + cam_max.left - + cam_rect->width, cam_max.left); - if (cam_rect.height + cam_rect.top > + if (cam_rect->height + cam_rect->top > cam_max.height + cam_max.top) - cam_rect.top = max(cam_max.height + cam_max.top - - cam_rect.height, cam_max.top); + cam_rect->top = max(cam_max.height + cam_max.top - + cam_rect->height, cam_max.top); - ret = icd->ops->set_crop(icd, &cam_rect); + ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n", - ret, cam_rect.width, cam_rect.height, - cam_rect.left, cam_rect.top); + ret, cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); } /* @@ -943,30 +947,30 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, */ if ((ret < 0 && (is_smaller(&icd->rect_current, rect) || is_inside(&icd->rect_current, rect))) || - is_smaller(&cam_rect, &target) || is_inside(&cam_rect, &target)) { + is_smaller(cam_rect, &target) || is_inside(cam_rect, &target)) { /* * The camera failed to configure a suitable cropping, * we cannot use the current rectangle, set to max */ - cam_rect = cam_max; - ret = icd->ops->set_crop(icd, &cam_rect); + *cam_rect = cam_max; + ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", - ret, cam_rect.width, cam_rect.height, - cam_rect.left, cam_rect.top); - if (ret < 0) + ret, cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); + if (ret < 0 && ret != -ENOIOCTLCMD) /* All failed, hopefully resume current capture */ goto resume_capture; /* Finally, adjust the target rectangle */ - if (target.width > cam_rect.width) - target.width = cam_rect.width; - if (target.height > cam_rect.height) - target.height = cam_rect.height; - if (target.left + target.width > cam_rect.left + cam_rect.width) - target.left = cam_rect.left + cam_rect.width - + if (target.width > cam_rect->width) + target.width = cam_rect->width; + if (target.height > cam_rect->height) + target.height = cam_rect->height; + if (target.left + target.width > cam_rect->left + cam_rect->width) + target.left = cam_rect->left + cam_rect->width - target.width; - if (target.top + target.height > cam_rect.top + cam_rect.height) - target.top = cam_rect.top + cam_rect.height - + if (target.top + target.height > cam_rect->top + cam_rect->height) + target.top = cam_rect->top + cam_rect->height - target.height; } @@ -980,14 +984,14 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, */ dev_dbg(&icd->dev, "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n", - cam_rect.width, cam_rect.height, cam_rect.left, cam_rect.top, + cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, target.width, target.height, target.left, target.top, rect->width, rect->height, rect->left, rect->top); ret = 0; ceu_set_rect: - cam->camera_rect = cam_rect; + cam->camera_rect = *cam_rect; rect->width = size_dst(target.width, hscale); rect->left = size_dst(target.left, hscale); diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index ec564a90e..ab469554b 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -798,7 +798,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, rect.top = icd->rect_max.height + icd->rect_max.top - rect.height; - ret = ici->ops->set_crop(icd, &rect); + ret = ici->ops->set_crop(icd, a); if (!ret) icd->rect_current = rect; @@ -971,7 +971,7 @@ static int soc_camera_probe(struct device *dev) /* FIXME: this is racy, have to use driver-binding notification */ control = to_soc_camera_control(icd); - if (!control || !control->driver || + if (!control || !control->driver || !dev_get_drvdata(control) || !try_module_get(control->driver->owner)) { icl->del_device(icl); goto enodrv; diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index 9e406c113..aec2cadbd 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -25,10 +25,15 @@ struct soc_camera_platform_priv { struct soc_camera_data_format format; }; -static struct soc_camera_platform_info * -soc_camera_platform_get_info(struct soc_camera_device *icd) +static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev_get_drvdata(&icd->dev)); + struct v4l2_subdev *subdev = platform_get_drvdata(pdev); + return container_of(subdev, struct soc_camera_platform_priv, subdev); +} + +static struct soc_camera_platform_info *get_info(struct soc_camera_device *icd) +{ + struct platform_device *pdev = to_platform_device(to_soc_camera_control(icd)); return pdev->dev.platform_data; } @@ -47,16 +52,10 @@ static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd, static unsigned long soc_camera_platform_query_bus_param(struct soc_camera_device *icd) { - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd); + struct soc_camera_platform_info *p = get_info(icd); return p->bus_param; } -static int soc_camera_platform_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) -{ - return 0; -} - static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { @@ -71,7 +70,7 @@ static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, static void soc_camera_platform_video_probe(struct soc_camera_device *icd, struct platform_device *pdev) { - struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); + struct soc_camera_platform_priv *priv = get_priv(pdev); struct soc_camera_platform_info *p = pdev->dev.platform_data; priv->format.name = p->format_name; @@ -96,7 +95,6 @@ static struct v4l2_subdev_ops platform_subdev_ops = { }; static struct soc_camera_ops soc_camera_platform_ops = { - .set_crop = soc_camera_platform_set_crop, .set_bus_param = soc_camera_platform_set_bus_param, .query_bus_param = soc_camera_platform_query_bus_param, }; @@ -124,7 +122,9 @@ static int soc_camera_platform_probe(struct platform_device *pdev) icd = to_soc_camera_dev(p->dev); - platform_set_drvdata(pdev, priv); + /* soc-camera convention: control's drvdata points to the subdev */ + platform_set_drvdata(pdev, &priv->subdev); + /* Set the control device reference */ dev_set_drvdata(&icd->dev, &pdev->dev); icd->width_min = 0; @@ -158,7 +158,7 @@ evdrs: static int soc_camera_platform_remove(struct platform_device *pdev) { - struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev); + struct soc_camera_platform_priv *priv = get_priv(pdev); struct soc_camera_platform_info *p = pdev->dev.platform_data; struct soc_camera_device *icd = to_soc_camera_dev(p->dev); diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 852c7859f..266cf594c 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -616,11 +616,12 @@ static int tw9910_s_register(struct v4l2_subdev *sd, } #endif -static int tw9910_set_crop(struct soc_camera_device *icd, - struct v4l2_rect *rect) +static int tw9910_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct v4l2_rect *rect = &a->c; + struct i2c_client *client = sd->priv; struct tw9910_priv *priv = to_tw9910(client); + struct soc_camera_device *icd = client->dev.platform_data; int ret = -EINVAL; u8 val; @@ -716,15 +717,15 @@ tw9910_set_fmt_error: static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { - struct i2c_client *client = sd->priv; - struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; - /* See tw9910_set_crop() - no proper cropping support */ - struct v4l2_rect rect = { - .left = 0, - .top = 0, - .width = pix->width, - .height = pix->height, + /* See tw9910_s_crop() - no proper cropping support */ + struct v4l2_crop a = { + .c = { + .left = 0, + .top = 0, + .width = pix->width, + .height = pix->height, + }, }; int i, ret; @@ -738,10 +739,10 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) if (i == ARRAY_SIZE(tw9910_color_fmt)) return -EINVAL; - ret = tw9910_set_crop(icd, &rect); + ret = tw9910_s_crop(sd, &a); if (!ret) { - pix->width = rect.width; - pix->height = rect.height; + pix->width = a.c.width; + pix->height = a.c.height; } return ret; } @@ -821,7 +822,6 @@ static int tw9910_video_probe(struct soc_camera_device *icd, } static struct soc_camera_ops tw9910_ops = { - .set_crop = tw9910_set_crop, .set_bus_param = tw9910_set_bus_param, .query_bus_param = tw9910_query_bus_param, .enum_input = tw9910_enum_input, @@ -840,6 +840,7 @@ static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { .s_stream = tw9910_s_stream, .s_fmt = tw9910_s_fmt, .try_fmt = tw9910_try_fmt, + .s_crop = tw9910_s_crop, }; static struct v4l2_subdev_ops tw9910_subdev_ops = { diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 7c44d4016..0bad8f1d7 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -76,7 +76,7 @@ struct soc_camera_host_ops { int (*get_formats)(struct soc_camera_device *, int, struct soc_camera_format_xlate *); void (*put_formats)(struct soc_camera_device *); - int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *); + int (*set_crop)(struct soc_camera_device *, struct v4l2_crop *); int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *); int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); void (*init_videobuf)(struct videobuf_queue *, @@ -185,7 +185,6 @@ struct soc_camera_ops { int (*resume)(struct soc_camera_device *); int (*init)(struct soc_camera_device *); int (*release)(struct soc_camera_device *); - int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *); unsigned long (*query_bus_param)(struct soc_camera_device *); int (*set_bus_param)(struct soc_camera_device *, unsigned long); int (*get_chip_id)(struct soc_camera_device *, -- cgit v1.2.3 From 7cf68de59618e578e4c22038d200ae3f42ad4fbb Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:46:59 +0200 Subject: soc-camera: switch to using v4l2_subdev_call() From: Guennadi Liakhovetski Use v4l2_subdev_call() instead of v4l2_device_call_until_err() in all host drivers and in soc-camera core. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mx1_camera.c | 12 ++++------ drivers/media/video/mx3_camera.c | 10 ++++---- drivers/media/video/pxa_camera.c | 9 ++++--- drivers/media/video/sh_mobile_ceu_camera.c | 17 ++++++--------- drivers/media/video/soc_camera.c | 30 ++++++++++++++------------- include/media/soc_camera.h | 14 +++++++++--- 6 files changed, 48 insertions(+), 44 deletions(-) --- linux/drivers/media/video/mx1_camera.c | 12 ++++------ linux/drivers/media/video/mx3_camera.c | 10 ++++---- linux/drivers/media/video/pxa_camera.c | 9 +++---- linux/drivers/media/video/sh_mobile_ceu_camera.c | 17 ++++++-------- linux/drivers/media/video/soc_camera.c | 30 +++++++++++++----------- linux/include/media/soc_camera.h | 14 +++++++---- 6 files changed, 48 insertions(+), 44 deletions(-) diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index add496fca..ed7856bda 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -465,9 +465,7 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) static int mx1_camera_set_crop(struct soc_camera_device *icd, struct v4l2_crop *a) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct device *control = to_soc_camera_control(icd); - struct v4l2_subdev *sd = dev_get_drvdata(control); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); return v4l2_subdev_call(sd, video, s_crop, a); } @@ -539,7 +537,7 @@ static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) static int mx1_camera_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; int ret; @@ -550,7 +548,7 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, return -EINVAL; } - ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); + ret = v4l2_subdev_call(sd, video, s_fmt, f); if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; @@ -562,11 +560,11 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, static int mx1_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); /* TODO: limit to mx1 hardware capabilities */ /* limit to sensor capabilities */ - return v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); + return v4l2_subdev_call(sd, video, try_fmt, f); } static int mx1_camera_reqbufs(struct soc_camera_file *icf, diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index de7ebfbf0..f7888f30d 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -786,8 +786,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; - struct device *control = to_soc_camera_control(icd); - struct v4l2_subdev *sd = dev_get_drvdata(control); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); /* * We now know pixel formats and can decide upon DMA-channel(s) @@ -809,6 +808,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_rect rect = { @@ -837,7 +837,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, configure_geometry(mx3_cam, &rect); - ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); + ret = v4l2_subdev_call(sd, video, s_fmt, f); if (!ret) { icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; @@ -849,7 +849,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, static int mx3_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; __u32 pixfmt = pix->pixelformat; @@ -875,7 +875,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, /* camera has to see its format, but the user the original one */ pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); + ret = v4l2_subdev_call(sd, video, try_fmt, f); pix->pixelformat = xlate->host_fmt->fourcc; field = pix->field; diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index d447e5b59..c35b07ae3 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -1298,8 +1298,7 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; - struct device *control = to_soc_camera_control(icd); - struct v4l2_subdev *sd = dev_get_drvdata(control); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct soc_camera_sense sense = { .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, @@ -1335,6 +1334,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_data_format *cam_fmt = NULL; const struct soc_camera_format_xlate *xlate = NULL; struct soc_camera_sense sense = { @@ -1358,7 +1358,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, icd->sense = &sense; cam_f.fmt.pix.pixelformat = cam_fmt->fourcc; - ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, s_fmt, f); + ret = v4l2_subdev_call(sd, video, s_fmt, f); icd->sense = NULL; @@ -1387,6 +1387,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; __u32 pixfmt = pix->pixelformat; @@ -1416,7 +1417,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, /* camera has to see its format, but the user the original one */ pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = v4l2_device_call_until_err(&ici->v4l2_dev, 0, video, try_fmt, f); + ret = v4l2_subdev_call(sd, video, try_fmt, f); pix->pixelformat = xlate->host_fmt->fourcc; field = pix->field; diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index c60088447..01371416e 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -856,8 +856,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, struct v4l2_crop cam_crop; struct v4l2_rect *cam_rect = &cam_crop.c, target, cam_max; struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct device *control = to_soc_camera_control(icd); - struct v4l2_subdev *sd = dev_get_drvdata(control); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); unsigned int hscale = pcdev->cflcr & 0xffff; unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; unsigned short width, height; @@ -1018,6 +1017,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h; @@ -1044,7 +1044,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, } pix->pixelformat = xlate->cam_fmt->fourcc; - ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_fmt, f); + ret = v4l2_subdev_call(sd, video, s_fmt, f); pix->pixelformat = pixfmt; dev_dbg(&icd->dev, "Camera %d fmt %ux%u, requested %ux%u, max %ux%u\n", ret, pix->width, pix->height, width, height, @@ -1084,8 +1084,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, pix->width = tmp_w; pix->height = tmp_h; pix->pixelformat = xlate->cam_fmt->fourcc; - ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, - video, s_fmt, f); + ret = v4l2_subdev_call(sd, video, s_fmt, f); pix->pixelformat = pixfmt; dev_dbg(&icd->dev, "Camera scaled to %ux%u\n", pix->width, pix->height); @@ -1142,6 +1141,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); __u32 pixfmt = pix->pixelformat; int width, height; int ret; @@ -1167,8 +1167,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ - ret = v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, - try_fmt, f); + ret = v4l2_subdev_call(sd, video, try_fmt, f); pix->pixelformat = pixfmt; if (ret < 0) return ret; @@ -1184,9 +1183,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, int tmp_w = pix->width, tmp_h = pix->height; pix->width = 2560; pix->height = 1920; - ret = v4l2_device_call_until_err(&ici->v4l2_dev, - (__u32)icd, video, - try_fmt, f); + ret = v4l2_subdev_call(sd, video, try_fmt, f); if (ret < 0) { /* Shouldn't actually happen... */ dev_err(&icd->dev, diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index ab469554b..0517754f7 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -153,9 +153,9 @@ static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_std, *a); + return v4l2_subdev_call(sd, core, s_std, *a); } static int soc_camera_reqbufs(struct file *file, void *priv, @@ -590,7 +590,7 @@ static int soc_camera_streamon(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); int ret; WARN_ON(priv != file->private_data); @@ -600,7 +600,7 @@ static int soc_camera_streamon(struct file *file, void *priv, mutex_lock(&icd->video_lock); - v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_stream, 1); + v4l2_subdev_call(sd, video, s_stream, 1); /* This calls buf_queue from host driver's videobuf_queue_ops */ ret = videobuf_streamon(&icf->vb_vidq); @@ -615,7 +615,7 @@ static int soc_camera_streamoff(struct file *file, void *priv, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); WARN_ON(priv != file->private_data); @@ -628,7 +628,7 @@ static int soc_camera_streamoff(struct file *file, void *priv, * remaining buffers. When the last buffer is freed, stop capture */ videobuf_streamoff(&icf->vb_vidq); - v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, video, s_stream, 0); + v4l2_subdev_call(sd, video, s_stream, 0); mutex_unlock(&icd->video_lock); @@ -673,6 +673,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); int ret; WARN_ON(priv != file->private_data); @@ -696,7 +697,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, return ret; } - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_ctrl, ctrl); + return v4l2_subdev_call(sd, core, g_ctrl, ctrl); } static int soc_camera_s_ctrl(struct file *file, void *priv, @@ -705,6 +706,7 @@ static int soc_camera_s_ctrl(struct file *file, void *priv, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); int ret; WARN_ON(priv != file->private_data); @@ -715,7 +717,7 @@ static int soc_camera_s_ctrl(struct file *file, void *priv, return ret; } - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_ctrl, ctrl); + return v4l2_subdev_call(sd, core, s_ctrl, ctrl); } static int soc_camera_cropcap(struct file *file, void *fh, @@ -813,9 +815,9 @@ static int soc_camera_g_chip_ident(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_chip_ident, id); + return v4l2_subdev_call(sd, core, g_chip_ident, id); } #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -824,9 +826,9 @@ static int soc_camera_g_register(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, g_register, reg); + return v4l2_subdev_call(sd, core, g_register, reg); } static int soc_camera_s_register(struct file *file, void *fh, @@ -834,9 +836,9 @@ static int soc_camera_s_register(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - return v4l2_device_call_until_err(&ici->v4l2_dev, (__u32)icd, core, s_register, reg); + return v4l2_subdev_call(sd, core, s_register, reg); } #endif diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 0bad8f1d7..344d89904 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -126,28 +126,34 @@ struct soc_camera_link { void (*free_bus)(struct soc_camera_link *); }; -static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) +static inline struct soc_camera_device *to_soc_camera_dev(const struct device *dev) { return container_of(dev, struct soc_camera_device, dev); } -static inline struct soc_camera_host *to_soc_camera_host(struct device *dev) +static inline struct soc_camera_host *to_soc_camera_host(const struct device *dev) { struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); return container_of(v4l2_dev, struct soc_camera_host, v4l2_dev); } -static inline struct soc_camera_link *to_soc_camera_link(struct soc_camera_device *icd) +static inline struct soc_camera_link *to_soc_camera_link(const struct soc_camera_device *icd) { return icd->dev.platform_data; } -static inline struct device *to_soc_camera_control(struct soc_camera_device *icd) +static inline struct device *to_soc_camera_control(const struct soc_camera_device *icd) { return dev_get_drvdata(&icd->dev); } +static inline struct v4l2_subdev *soc_camera_to_subdev(const struct soc_camera_device *icd) +{ + struct device *control = to_soc_camera_control(icd); + return dev_get_drvdata(control); +} + int soc_camera_host_register(struct soc_camera_host *ici); void soc_camera_host_unregister(struct soc_camera_host *ici); -- cgit v1.2.3 From 3a76b0c22111746bd099bc5c9279dbedc734e3ac Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:47:00 +0200 Subject: soc-camera: Use I2C device for dev_{dbg,info,...} output in all clients From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9m001.c | 20 +++++++++++--------- drivers/media/video/mt9m111.c | 11 +++++------ drivers/media/video/mt9t031.c | 16 ++++++++-------- drivers/media/video/mt9v022.c | 16 ++++++++-------- drivers/media/video/ov772x.c | 6 +++--- drivers/media/video/tw9910.c | 6 +++--- 6 files changed, 38 insertions(+), 37 deletions(-) --- linux/drivers/media/video/mt9m001.c | 20 +++++++++++--------- linux/drivers/media/video/mt9m111.c | 11 +++++------ linux/drivers/media/video/mt9t031.c | 16 ++++++++-------- linux/drivers/media/video/mt9v022.c | 16 ++++++++-------- linux/drivers/media/video/ov772x.c | 6 +++--- linux/drivers/media/video/tw9910.c | 6 +++--- 6 files changed, 38 insertions(+), 37 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index b74ef6cea..d4ebab8c2 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -118,7 +118,7 @@ static int mt9m001_init(struct soc_camera_device *icd) struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; - dev_dbg(&icd->dev, "%s\n", __func__); + dev_dbg(&client->dev, "%s\n", __func__); /* * We don't know, whether platform provides reset, @@ -421,7 +421,7 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) unsigned long range = qctrl->default_value - qctrl->minimum; data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; - dev_dbg(&icd->dev, "Setting gain %d\n", data); + dev_dbg(&client->dev, "Setting gain %d\n", data); data = reg_write(client, MT9M001_GLOBAL_GAIN, data); if (data < 0) return -EIO; @@ -439,7 +439,7 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) else data = ((gain - 64) * 7 + 28) / 56 + 96; - dev_dbg(&icd->dev, "Setting gain from %d to %d\n", + dev_dbg(&client->dev, "Setting gain from %d to %d\n", reg_read(client, MT9M001_GLOBAL_GAIN), data); data = reg_write(client, MT9M001_GLOBAL_GAIN, data); if (data < 0) @@ -458,8 +458,10 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 + range / 2) / range + 1; - dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n", - reg_read(client, MT9M001_SHUTTER_WIDTH), shutter); + dev_dbg(&client->dev, + "Setting shutter width from %d to %lu\n", + reg_read(client, MT9M001_SHUTTER_WIDTH), + shutter); if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0) return -EIO; icd->exposure = ctrl->value; @@ -504,7 +506,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, /* Enable the chip */ data = reg_write(client, MT9M001_CHIP_ENABLE, 1); - dev_dbg(&icd->dev, "write: %d\n", data); + dev_dbg(&client->dev, "write: %d\n", data); /* Read out the chip version register */ data = reg_read(client, MT9M001_CHIP_VERSION); @@ -521,7 +523,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, icd->formats = mt9m001_monochrome_formats; break; default: - dev_err(&icd->dev, + dev_err(&client->dev, "No MT9M001 chip detected, register read %x\n", data); return -ENODEV; } @@ -546,7 +548,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, if (flags & SOCAM_DATAWIDTH_8) icd->num_formats++; - dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, + dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, data == 0x8431 ? "C12STM" : "C12ST"); return 0; @@ -557,7 +559,7 @@ static void mt9m001_video_remove(struct soc_camera_device *icd) struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr, + dev_dbg(&client->dev, "Video %x removed: %p, %p\n", client->addr, icd->dev.parent, icd->vdev); if (icl->free_bus) icl->free_bus(icl); diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index cab9de000..44e565faf 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -400,10 +400,9 @@ static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) struct v4l2_rect *rect = &a->c; struct i2c_client *client = sd->priv; struct mt9m111 *mt9m111 = to_mt9m111(client); - struct soc_camera_device *icd = client->dev.platform_data; int ret; - dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n", + dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n", __func__, rect->left, rect->top, rect->width, rect->height); @@ -818,7 +817,7 @@ static int mt9m111_init(struct soc_camera_device *icd) if (!ret) ret = mt9m111_set_autoexposure(client, mt9m111->autoexposure); if (ret) - dev_err(&icd->dev, "mt9m11x init failed: %d\n", ret); + dev_err(&client->dev, "mt9m11x init failed: %d\n", ret); return ret; } @@ -833,7 +832,7 @@ static int mt9m111_release(struct soc_camera_device *icd) mt9m111->powered = 0; if (ret < 0) - dev_err(&icd->dev, "mt9m11x release failed: %d\n", ret); + dev_err(&client->dev, "mt9m11x release failed: %d\n", ret); return ret; } @@ -875,7 +874,7 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, break; default: ret = -ENODEV; - dev_err(&icd->dev, + dev_err(&client->dev, "No MT9M11x chip detected, register read %x\n", data); goto ei2c; } @@ -883,7 +882,7 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, icd->formats = mt9m111_colour_formats; icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats); - dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data); + dev_info(&client->dev, "Detected a MT9M11x chip ID %x\n", data); mt9m111->autoexposure = 1; mt9m111->autowhitebalance = 1; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 6bcea4165..00877b4ae 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -248,7 +248,7 @@ static int mt9t031_set_params(struct soc_camera_device *icd, xbin = min(xskip, (u16)3); ybin = min(yskip, (u16)3); - dev_dbg(&icd->dev, "xskip %u, width %u/%u, yskip %u, height %u/%u\n", + dev_dbg(&client->dev, "xskip %u, width %u/%u, yskip %u, height %u/%u\n", xskip, width, rect->width, yskip, height, rect->height); /* Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper */ @@ -287,7 +287,7 @@ static int mt9t031_set_params(struct soc_camera_device *icd, ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE, ((ybin - 1) << 4) | (yskip - 1)); } - dev_dbg(&icd->dev, "new physical left %u, top %u\n", left, top); + dev_dbg(&client->dev, "new physical left %u, top %u\n", left, top); /* The caller provides a supported format, as guaranteed by * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ @@ -567,7 +567,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) unsigned long range = qctrl->default_value - qctrl->minimum; data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; - dev_dbg(&icd->dev, "Setting gain %d\n", data); + dev_dbg(&client->dev, "Setting gain %d\n", data); data = reg_write(client, MT9T031_GLOBAL_GAIN, data); if (data < 0) return -EIO; @@ -587,7 +587,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) /* calculated gain 65..1024 -> (1..120) << 8 + 0x60 */ data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60; - dev_dbg(&icd->dev, "Setting gain from 0x%x to 0x%x\n", + dev_dbg(&client->dev, "Set gain from 0x%x to 0x%x\n", reg_read(client, MT9T031_GLOBAL_GAIN), data); data = reg_write(client, MT9T031_GLOBAL_GAIN, data); if (data < 0) @@ -608,7 +608,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) u32 old; get_shutter(client, &old); - dev_dbg(&icd->dev, "Setting shutter width from %u to %u\n", + dev_dbg(&client->dev, "Set shutter from %u to %u\n", old, shutter); if (set_shutter(client, shutter) < 0) return -EIO; @@ -653,7 +653,7 @@ static int mt9t031_video_probe(struct i2c_client *client) /* Enable the chip */ data = reg_write(client, MT9T031_CHIP_ENABLE, 1); - dev_dbg(&icd->dev, "write: %d\n", data); + dev_dbg(&client->dev, "write: %d\n", data); /* Read out the chip version register */ data = reg_read(client, MT9T031_CHIP_VERSION); @@ -665,12 +665,12 @@ static int mt9t031_video_probe(struct i2c_client *client) icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats); break; default: - dev_err(&icd->dev, + dev_err(&client->dev, "No MT9T031 chip detected, register read %x\n", data); return -ENODEV; } - dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data); + dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data); return 0; } diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 088ffa464..fd2d13d6c 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -224,7 +224,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, if (ret < 0) return ret; - dev_dbg(&icd->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", + dev_dbg(&client->dev, "Calculated pixclk 0x%x, chip control 0x%x\n", pixclk, mt9v022->chip_control); return 0; @@ -287,7 +287,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) if (ret < 0) return ret; - dev_dbg(&icd->dev, "Frame %ux%u pixel\n", rect->width, rect->height); + dev_dbg(&client->dev, "Frame %ux%u pixel\n", rect->width, rect->height); return 0; } @@ -545,7 +545,7 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) return -EIO; - dev_info(&icd->dev, "Setting gain from %d to %lu\n", + dev_info(&client->dev, "Setting gain from %d to %lu\n", reg_read(client, MT9V022_ANALOG_GAIN), gain); if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0) return -EIO; @@ -566,7 +566,7 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) return -EIO; - dev_dbg(&icd->dev, "Shutter width from %d to %lu\n", + dev_dbg(&client->dev, "Shutter width from %d to %lu\n", reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH), shutter); if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, @@ -616,7 +616,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, /* must be 0x1311 or 0x1313 */ if (data != 0x1311 && data != 0x1313) { ret = -ENODEV; - dev_info(&icd->dev, "No MT9V022 detected, ID register 0x%x\n", + dev_info(&client->dev, "No MT9V022 found, ID register 0x%x\n", data); goto ei2c; } @@ -628,7 +628,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, /* 15 clock cycles */ udelay(200); if (reg_read(client, MT9V022_RESET)) { - dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); + dev_err(&client->dev, "Resetting MT9V022 failed!\n"); if (ret > 0) ret = -EIO; goto ei2c; @@ -669,7 +669,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, if (flags & SOCAM_DATAWIDTH_8) icd->num_formats++; - dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", + dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? "monochrome" : "colour"); @@ -682,7 +682,7 @@ static void mt9v022_video_remove(struct soc_camera_device *icd) struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr, + dev_dbg(&client->dev, "Video %x removed: %p, %p\n", client->addr, icd->dev.parent, icd->vdev); if (icl->free_bus) icl->free_bus(icl); diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index c5b63f420..392327b72 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -1002,7 +1002,7 @@ static int ov772x_video_probe(struct soc_camera_device *icd, */ if (SOCAM_DATAWIDTH_10 != priv->info->buswidth && SOCAM_DATAWIDTH_8 != priv->info->buswidth) { - dev_err(&icd->dev, "bus width error\n"); + dev_err(&client->dev, "bus width error\n"); return -ENODEV; } @@ -1025,12 +1025,12 @@ static int ov772x_video_probe(struct soc_camera_device *icd, priv->model = V4L2_IDENT_OV7725; break; default: - dev_err(&icd->dev, + dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); return -ENODEV; } - dev_info(&icd->dev, + dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", devname, pid, diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 266cf594c..e8c6cf119 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -793,7 +793,7 @@ static int tw9910_video_probe(struct soc_camera_device *icd, */ if (SOCAM_DATAWIDTH_16 != priv->info->buswidth && SOCAM_DATAWIDTH_8 != priv->info->buswidth) { - dev_err(&icd->dev, "bus width error\n"); + dev_err(&client->dev, "bus width error\n"); return -ENODEV; } @@ -807,12 +807,12 @@ static int tw9910_video_probe(struct soc_camera_device *icd, if (0x0B != GET_ID(val) || 0x00 != GET_ReV(val)) { - dev_err(&icd->dev, + dev_err(&client->dev, "Product ID error %x:%x\n", GET_ID(val), GET_ReV(val)); return -ENODEV; } - dev_info(&icd->dev, + dev_info(&client->dev, "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val)); icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; -- cgit v1.2.3 From d1d25e3f57f0395cafed266bfcb95fe4b21d45f3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:47:00 +0200 Subject: soc-camera: Use camera device object for core output From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/soc_camera.c | 8 +++----- 1 files changed, 3 insertions(+), 5 deletions(-) --- linux/drivers/media/video/soc_camera.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 0517754f7..6145846f7 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -298,7 +298,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, return ret; } else if (!icd->current_fmt || icd->current_fmt->fourcc != pix->pixelformat) { - dev_err(ici->v4l2_dev.dev, + dev_err(&icd->dev, "Host driver hasn't set up current format correctly!\n"); return -EINVAL; } @@ -427,7 +427,6 @@ static int soc_camera_close(struct file *file) struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct video_device *vdev = icd->vdev; mutex_lock(&icd->video_lock); icd->use_count--; @@ -447,7 +446,7 @@ static int soc_camera_close(struct file *file) vfree(icf); - dev_dbg(vdev->parent, "camera device close\n"); + dev_dbg(&icd->dev, "camera device close\n"); return 0; } @@ -457,10 +456,9 @@ static ssize_t soc_camera_read(struct file *file, char __user *buf, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; - struct video_device *vdev = icd->vdev; int err = -EINVAL; - dev_err(vdev->parent, "camera device read not implemented\n"); + dev_err(&icd->dev, "camera device read not implemented\n"); return err; } -- cgit v1.2.3 From bb52712a084d97b0bcfff36d62fc9c69c33858e5 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:47:00 +0200 Subject: soc-camera: Use video device object for output in host drivers From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mx1_camera.c | 38 ++++++++++-------- drivers/media/video/mx3_camera.c | 46 ++++++++++++--------- drivers/media/video/pxa_camera.c | 54 ++++++++++++++----------- drivers/media/video/sh_mobile_ceu_camera.c | 61 ++++++++++++++------------- 4 files changed, 110 insertions(+), 89 deletions(-) --- linux/drivers/media/video/mx1_camera.c | 38 ++++++++------- linux/drivers/media/video/mx3_camera.c | 46 ++++++++++-------- linux/drivers/media/video/pxa_camera.c | 54 +++++++++++---------- linux/drivers/media/video/sh_mobile_ceu_camera.c | 61 +++++++++++++----------- 4 files changed, 110 insertions(+), 89 deletions(-) diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index ed7856bda..1f1324a1d 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -135,7 +135,7 @@ static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, while (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) (*count)--; - dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); + dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); return 0; } @@ -147,7 +147,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf) BUG_ON(in_interrupt()); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); /* This waits until this buffer is out of danger, i.e., until it is no @@ -165,7 +165,7 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); int ret; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); /* Added list head initialization on alloc */ @@ -216,10 +216,11 @@ out: static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) { struct videobuf_buffer *vbuf = &pcdev->active->vb; + struct device *dev = pcdev->icd->dev.parent; int ret; if (unlikely(!pcdev->active)) { - dev_err(pcdev->icd->dev.parent, "DMA End IRQ with no active buffer\n"); + dev_err(dev, "DMA End IRQ with no active buffer\n"); return -EFAULT; } @@ -229,7 +230,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) vbuf->size, pcdev->res->start + CSIRXR, DMA_MODE_READ); if (unlikely(ret)) - dev_err(pcdev->icd->dev.parent, "Failed to setup DMA sg list\n"); + dev_err(dev, "Failed to setup DMA sg list\n"); return ret; } @@ -243,7 +244,7 @@ static void mx1_videobuf_queue(struct videobuf_queue *vq, struct mx1_camera_dev *pcdev = ici->priv; struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); list_add_tail(&vb->queue, &pcdev->capture); @@ -270,22 +271,23 @@ static void mx1_videobuf_release(struct videobuf_queue *vq, struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); #ifdef DEBUG struct soc_camera_device *icd = vq->priv_data; + struct device *dev = icd->dev.parent; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); switch (vb->state) { case VIDEOBUF_ACTIVE: - dev_dbg(&icd->dev, "%s (active)\n", __func__); + dev_dbg(dev, "%s (active)\n", __func__); break; case VIDEOBUF_QUEUED: - dev_dbg(&icd->dev, "%s (queued)\n", __func__); + dev_dbg(dev, "%s (queued)\n", __func__); break; case VIDEOBUF_PREPARED: - dev_dbg(&icd->dev, "%s (prepared)\n", __func__); + dev_dbg(dev, "%s (prepared)\n", __func__); break; default: - dev_dbg(&icd->dev, "%s (unknown)\n", __func__); + dev_dbg(dev, "%s (unknown)\n", __func__); break; } #endif @@ -325,6 +327,7 @@ static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev, static void mx1_camera_dma_irq(int channel, void *data) { struct mx1_camera_dev *pcdev = data; + struct device *dev = pcdev->icd->dev.parent; struct mx1_buffer *buf; struct videobuf_buffer *vb; unsigned long flags; @@ -334,14 +337,14 @@ static void mx1_camera_dma_irq(int channel, void *data) imx_dma_disable(channel); if (unlikely(!pcdev->active)) { - dev_err(pcdev->icd->dev.parent, "DMA End IRQ with no active buffer\n"); + dev_err(dev, "DMA End IRQ with no active buffer\n"); goto out; } vb = &pcdev->active->vb; buf = container_of(vb, struct mx1_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(pcdev->icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); mx1_camera_wakeup(pcdev, vb, buf); @@ -381,8 +384,9 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev) * they get a nice Oops */ div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; - dev_dbg(pcdev->icd->dev.parent, "System clock %lukHz, target freq %dkHz, " - "divisor %lu\n", lcdclk / 1000, mclk / 1000, div); + dev_dbg(pcdev->icd->dev.parent, + "System clock %lukHz, target freq %dkHz, divisor %lu\n", + lcdclk / 1000, mclk / 1000, div); return div; } @@ -428,7 +432,7 @@ static int mx1_camera_add_device(struct soc_camera_device *icd) goto ebusy; } - dev_info(&icd->dev, "MX1 Camera driver attached to camera %d\n", + dev_info(icd->dev.parent, "MX1 Camera driver attached to camera %d\n", icd->devnum); mx1_camera_activate(pcdev); @@ -454,7 +458,7 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) /* Stop DMA engine */ imx_dma_disable(pcdev->dma_chan); - dev_info(&icd->dev, "MX1 Camera driver detached from camera %d\n", + dev_info(icd->dev.parent, "MX1 Camera driver detached from camera %d\n", icd->devnum); mx1_camera_deactivate(pcdev); diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index f7888f30d..d5b51e990 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -178,7 +178,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx3_camera_buffer *buf BUG_ON(in_interrupt()); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); /* @@ -375,7 +375,8 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, spin_unlock_irq(&mx3_cam->lock); cookie = txd->tx_submit(txd); - dev_dbg(&icd->dev, "Submitted cookie %d DMA 0x%08x\n", cookie, sg_dma_address(&buf->sg)); + dev_dbg(icd->dev.parent, "Submitted cookie %d DMA 0x%08x\n", + cookie, sg_dma_address(&buf->sg)); spin_lock_irq(&mx3_cam->lock); @@ -402,9 +403,10 @@ static void mx3_videobuf_release(struct videobuf_queue *vq, container_of(vb, struct mx3_camera_buffer, vb); unsigned long flags; - dev_dbg(&icd->dev, "Release%s DMA 0x%08x (state %d), queue %sempty\n", + dev_dbg(icd->dev.parent, + "Release%s DMA 0x%08x (state %d), queue %sempty\n", mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg), - vb->state, list_empty(&vb->queue) ? "" : "not "); + vb->state, list_empty(&vb->queue) ? "" : "not "); spin_lock_irqsave(&mx3_cam->lock, flags); if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) && !list_empty(&vb->queue)) { @@ -484,7 +486,7 @@ static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam, clk_enable(mx3_cam->clk); rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk); - dev_dbg(&icd->dev, "Set SENS_CONF to %x, rate %ld\n", conf, rate); + dev_dbg(icd->dev.parent, "Set SENS_CONF to %x, rate %ld\n", conf, rate); if (rate) clk_set_rate(mx3_cam->clk, rate); } @@ -502,7 +504,7 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) mx3_cam->icd = icd; - dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n", + dev_info(icd->dev.parent, "MX3 Camera driver attached to camera %d\n", icd->devnum); return 0; @@ -526,7 +528,7 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd) mx3_cam->icd = NULL; - dev_info(&icd->dev, "MX3 Camera driver detached from camera %d\n", + dev_info(icd->dev.parent, "MX3 Camera driver detached from camera %d\n", icd->devnum); } @@ -603,7 +605,8 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd, unsigned long bus_flags, camera_flags; int ret = test_platform_param(mx3_cam, depth, &bus_flags); - dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", depth, ret); + dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", + depth, ret); if (ret < 0) return ret; @@ -612,7 +615,8 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd, ret = soc_camera_bus_param_compatible(camera_flags, bus_flags); if (ret < 0) - dev_warn(&icd->dev, "Flags incompatible: camera %lx, host %lx\n", + dev_warn(icd->dev.parent, + "Flags incompatible: camera %lx, host %lx\n", camera_flags, bus_flags); return ret; @@ -686,7 +690,8 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(icd->dev.parent, "Providing format %s using %s\n", + dev_dbg(icd->dev.parent, + "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -698,7 +703,8 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(icd->dev.parent, "Providing format %s using %s\n", + dev_dbg(icd->dev.parent, + "Providing format %s using %s\n", mx3_camera_formats[0].name, icd->formats[idx].name); } @@ -821,7 +827,8 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(icd->dev.parent, "Format %x not found\n", pix->pixelformat); + dev_warn(icd->dev.parent, "Format %x not found\n", + pix->pixelformat); return -EINVAL; } @@ -883,7 +890,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, if (field == V4L2_FIELD_ANY) { pix->field = V4L2_FIELD_NONE; } else if (field != V4L2_FIELD_NONE) { - dev_err(&icd->dev, "Field type %d unsupported.\n", field); + dev_err(icd->dev.parent, "Field type %d unsupported.\n", field); return -EINVAL; } @@ -922,14 +929,15 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) u32 dw, sens_conf; int ret = test_platform_param(mx3_cam, icd->buswidth, &bus_flags); const struct soc_camera_format_xlate *xlate; + struct device *dev = icd->dev.parent; xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); + dev_warn(dev, "Format %x not found\n", pixfmt); return -EINVAL; } - dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", + dev_dbg(dev, "requested bus width %d bit: %d\n", icd->buswidth, ret); if (ret < 0) @@ -938,10 +946,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) camera_flags = icd->ops->query_bus_param(icd); common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); - dev_dbg(icd->dev.parent, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", + dev_dbg(dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n", camera_flags, bus_flags, common_flags); if (!common_flags) { - dev_dbg(icd->dev.parent, "no common flags"); + dev_dbg(dev, "no common flags"); return -EINVAL; } @@ -995,7 +1003,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) ret = icd->ops->set_bus_param(icd, common_flags); if (ret < 0) { - dev_dbg(icd->dev.parent, "camera set_bus_param(%lx) returned %d\n", + dev_dbg(dev, "camera set_bus_param(%lx) returned %d\n", common_flags, ret); return ret; } @@ -1050,7 +1058,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF); - dev_dbg(icd->dev.parent, "Set SENS_CONF to %x\n", sens_conf | dw); + dev_dbg(dev, "Set SENS_CONF to %x\n", sens_conf | dw); return 0; } diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index c35b07ae3..611e7ff7f 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -249,7 +249,7 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, { struct soc_camera_device *icd = vq->priv_data; - dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); + dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); *size = roundup(icd->rect_current.width * icd->rect_current.height * ((icd->current_fmt->depth + 7) >> 3), 8); @@ -271,7 +271,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) BUG_ON(in_interrupt()); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, &buf->vb, buf->vb.baddr, buf->vb.bsize); /* This waits until this buffer is out of danger, i.e., until it is no @@ -552,7 +552,8 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev) active = pcdev->active; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s (channel=%d) ddadr=%08x\n", __func__, + dev_dbg(pcdev->soc_host.v4l2_dev.dev, + "%s (channel=%d) ddadr=%08x\n", __func__, i, active->dmas[i].sg_dma); DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma; DCSR(pcdev->dma_chans[i]) = DCSR_RUN; @@ -564,7 +565,8 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev) int i; for (i = 0; i < pcdev->channels; i++) { - dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s (channel=%d)\n", __func__, i); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, + "%s (channel=%d)\n", __func__, i); DCSR(pcdev->dma_chans[i]) = 0; } } @@ -632,8 +634,8 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq, struct pxa_camera_dev *pcdev = ici->priv; struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d active=%p\n", __func__, - vb, vb->baddr, vb->bsize, pcdev->active); + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d active=%p\n", + __func__, vb, vb->baddr, vb->bsize, pcdev->active); list_add_tail(&vb->queue, &pcdev->capture); @@ -650,22 +652,23 @@ static void pxa_videobuf_release(struct videobuf_queue *vq, struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); #ifdef DEBUG struct soc_camera_device *icd = vq->priv_data; + struct device *dev = icd->dev.parent; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, + dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); switch (vb->state) { case VIDEOBUF_ACTIVE: - dev_dbg(&icd->dev, "%s (active)\n", __func__); + dev_dbg(dev, "%s (active)\n", __func__); break; case VIDEOBUF_QUEUED: - dev_dbg(&icd->dev, "%s (queued)\n", __func__); + dev_dbg(dev, "%s (queued)\n", __func__); break; case VIDEOBUF_PREPARED: - dev_dbg(&icd->dev, "%s (prepared)\n", __func__); + dev_dbg(dev, "%s (prepared)\n", __func__); break; default: - dev_dbg(&icd->dev, "%s (unknown)\n", __func__); + dev_dbg(dev, "%s (unknown)\n", __func__); break; } #endif @@ -936,7 +939,8 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) struct videobuf_buffer *vb; status = __raw_readl(pcdev->base + CISR); - dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Camera interrupt status 0x%lx\n", status); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, + "Camera interrupt status 0x%lx\n", status); if (!status) return IRQ_NONE; @@ -976,7 +980,7 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) pcdev->icd = icd; - dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n", + dev_info(icd->dev.parent, "PXA Camera driver attached to camera %d\n", icd->devnum); return 0; @@ -990,7 +994,7 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) BUG_ON(icd != pcdev->icd); - dev_info(&icd->dev, "PXA Camera driver detached from camera %d\n", + dev_info(icd->dev.parent, "PXA Camera driver detached from camera %d\n", icd->devnum); /* disable capture, disable interrupts */ @@ -1236,7 +1240,7 @@ static int required_buswidth(const struct soc_camera_data_format *fmt) static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_format_xlate *xlate) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct device *dev = icd->dev.parent; int formats = 0, buswidth, ret; buswidth = required_buswidth(icd->formats + idx); @@ -1256,7 +1260,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->v4l2_dev.dev, "Providing format %s using %s\n", + dev_dbg(dev, "Providing format %s using %s\n", pxa_camera_formats[0].name, icd->formats[idx].name); } @@ -1271,7 +1275,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = buswidth; xlate++; - dev_dbg(ici->v4l2_dev.dev, "Providing format %s packed\n", + dev_dbg(dev, "Providing format %s packed\n", icd->formats[idx].name); } break; @@ -1283,7 +1287,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->v4l2_dev.dev, + dev_dbg(dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -1298,6 +1302,7 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, struct v4l2_rect *rect = &a->c; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; + struct device *dev = icd->dev.parent; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct soc_camera_sense sense = { .master_clock = pcdev->mclk, @@ -1314,11 +1319,11 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, icd->sense = NULL; if (ret < 0) { - dev_warn(ici->v4l2_dev.dev, "Failed to crop to %ux%u@%u:%u\n", + dev_warn(dev, "Failed to crop to %ux%u@%u:%u\n", rect->width, rect->height, rect->left, rect->top); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(ici->v4l2_dev.dev, + dev_err(dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1334,6 +1339,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; + struct device *dev = icd->dev.parent; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_data_format *cam_fmt = NULL; const struct soc_camera_format_xlate *xlate = NULL; @@ -1347,7 +1353,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pix->pixelformat); + dev_warn(dev, "Format %x not found\n", pix->pixelformat); return -EINVAL; } @@ -1363,11 +1369,11 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, icd->sense = NULL; if (ret < 0) { - dev_warn(ici->v4l2_dev.dev, "Failed to configure for format %x\n", + dev_warn(dev, "Failed to configure for format %x\n", pix->pixelformat); } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { - dev_err(ici->v4l2_dev.dev, + dev_err(dev, "pixel clock %lu set by the camera too high!", sense.pixel_clock); return -EIO; @@ -1425,7 +1431,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, if (field == V4L2_FIELD_ANY) { pix->field = V4L2_FIELD_NONE; } else if (field != V4L2_FIELD_NONE) { - dev_err(&icd->dev, "Field type %d unsupported.\n", field); + dev_err(icd->dev.parent, "Field type %d unsupported.\n", field); return -EINVAL; } diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 01371416e..142bdbc6f 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -169,7 +169,7 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, (*count)--; } - dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); + dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); return 0; } @@ -179,7 +179,7 @@ static void free_buffer(struct videobuf_queue *vq, { struct soc_camera_device *icd = vq->priv_data; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, &buf->vb, buf->vb.baddr, buf->vb.bsize); if (in_interrupt()) @@ -187,7 +187,7 @@ static void free_buffer(struct videobuf_queue *vq, videobuf_waiton(&buf->vb, 0, 0); videobuf_dma_contig_free(vq, &buf->vb); - dev_dbg(&icd->dev, "%s freed\n", __func__); + dev_dbg(icd->dev.parent, "%s freed\n", __func__); buf->vb.state = VIDEOBUF_NEEDS_INIT; } @@ -251,7 +251,7 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, buf = container_of(vb, struct sh_mobile_ceu_buffer, vb); - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, vb, vb->baddr, vb->bsize); /* Added list head initialization on alloc */ @@ -304,7 +304,7 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, + dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, vb, vb->baddr, vb->bsize); vb->state = VIDEOBUF_QUEUED; @@ -393,7 +393,7 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) if (pcdev->icd) return -EBUSY; - dev_info(&icd->dev, + dev_info(icd->dev.parent, "SuperH Mobile CEU driver attached to camera %d\n", icd->devnum); @@ -433,7 +433,7 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) clk_disable(pcdev->clk); - dev_info(&icd->dev, + dev_info(icd->dev.parent, "SuperH Mobile CEU driver detached from camera %d\n", icd->devnum); @@ -499,7 +499,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, left = size_src(rect->left, hscale); top = size_src(rect->top, vscale); - dev_dbg(&icd->dev, "Left %u * 0x%x = %u, top %u * 0x%x = %u\n", + dev_dbg(icd->dev.parent, "Left %u * 0x%x = %u, top %u * 0x%x = %u\n", rect->left, hscale, left, rect->top, vscale, top); if (left > cam->camera_rect.left) { @@ -516,7 +516,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, top = cam->camera_rect.top; } - dev_dbg(&icd->dev, "New left %u, top %u, offsets %u:%u\n", + dev_dbg(icd->dev.parent, "New left %u, top %u, offsets %u:%u\n", rect->left, rect->top, left_offset, top_offset); if (pcdev->image_mode) { @@ -689,7 +689,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CDOCR, value); ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ - dev_dbg(&icd->dev, "S_FMT successful for %c%c%c%c %ux%u@%u:%u\n", + dev_dbg(icd->dev.parent, "S_FMT successful for %c%c%c%c %ux%u@%u:%u\n", pixfmt & 0xff, (pixfmt >> 8) & 0xff, (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff, icd->rect_current.width, icd->rect_current.height, @@ -746,7 +746,6 @@ static const struct soc_camera_data_format sh_mobile_ceu_formats[] = { static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_format_xlate *xlate) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); int ret, k, n; int formats = 0; struct sh_mobile_ceu_cam *cam; @@ -796,7 +795,8 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->v4l2_dev.dev, "Providing format %s using %s\n", + dev_dbg(icd->dev.parent, + "Providing format %s using %s\n", sh_mobile_ceu_formats[k].name, icd->formats[idx].name); } @@ -809,7 +809,7 @@ add_single_format: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(ici->v4l2_dev.dev, + dev_dbg(icd->dev.parent, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -872,19 +872,21 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, target = *cam_rect; capsr = capture_save_reset(pcdev); - dev_dbg(&icd->dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); + dev_dbg(icd->dev.parent, "CAPSR 0x%x, CFLCR 0x%x\n", + capsr, pcdev->cflcr); /* First attempt - see if the client can deliver a perfect result */ ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) { - dev_dbg(&icd->dev, "Camera S_CROP successful for %ux%u@%u:%u\n", + dev_dbg(icd->dev.parent, + "Camera S_CROP successful for %ux%u@%u:%u\n", cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); goto ceu_set_rect; } /* Try to fix cropping, that camera hasn't managed to do */ - dev_dbg(&icd->dev, "Fix camera S_CROP %d for %ux%u@%u:%u" + dev_dbg(icd->dev.parent, "Fix camera S_CROP %d for %ux%u@%u:%u" " to %ux%u@%u:%u\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, @@ -935,7 +937,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, cam_rect->height, cam_max.top); ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); - dev_dbg(&icd->dev, "Camera S_CROP %d for %ux%u@%u:%u\n", + dev_dbg(icd->dev.parent, "Camera S_CROP %d for %ux%u@%u:%u\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); } @@ -953,7 +955,8 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, */ *cam_rect = cam_max; ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); - dev_dbg(&icd->dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", + dev_dbg(icd->dev.parent, + "Camera S_CROP %d for max %ux%u@%u:%u\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); if (ret < 0 && ret != -ENOIOCTLCMD) @@ -981,7 +984,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, * last before last close() _user_ rectangle, which can be different * from camera rectangle. */ - dev_dbg(&icd->dev, + dev_dbg(icd->dev.parent, "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n", cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, target.width, target.height, target.left, target.top, @@ -1039,14 +1042,15 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); + dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); return -EINVAL; } pix->pixelformat = xlate->cam_fmt->fourcc; ret = v4l2_subdev_call(sd, video, s_fmt, f); pix->pixelformat = pixfmt; - dev_dbg(&icd->dev, "Camera %d fmt %ux%u, requested %ux%u, max %ux%u\n", + dev_dbg(icd->dev.parent, + "Camera %d fmt %ux%u, requested %ux%u, max %ux%u\n", ret, pix->width, pix->height, width, height, icd->rect_max.width, icd->rect_max.height); if (ret < 0) @@ -1086,12 +1090,12 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, pix->pixelformat = xlate->cam_fmt->fourcc; ret = v4l2_subdev_call(sd, video, s_fmt, f); pix->pixelformat = pixfmt; - dev_dbg(&icd->dev, "Camera scaled to %ux%u\n", + dev_dbg(icd->dev.parent, "Camera scaled to %ux%u\n", pix->width, pix->height); if (ret < 0) { /* This shouldn't happen */ - dev_err(&icd->dev, "Client failed to set format: %d\n", - ret); + dev_err(icd->dev.parent, + "Client failed to set format: %d\n", ret); return ret; } } @@ -1107,7 +1111,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, hscale = calc_scale(pix->width, &width); vscale = calc_scale(pix->height, &height); - dev_dbg(&icd->dev, "W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", + dev_dbg(icd->dev.parent, "W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", pix->width, hscale, width, pix->height, vscale, height); out: @@ -1138,7 +1142,6 @@ out: static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); @@ -1148,7 +1151,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); + dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); return -EINVAL; } @@ -1186,7 +1189,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, ret = v4l2_subdev_call(sd, video, try_fmt, f); if (ret < 0) { /* Shouldn't actually happen... */ - dev_err(&icd->dev, + dev_err(icd->dev.parent, "FIXME: try_fmt() returned %d\n", ret); pix->width = tmp_w; pix->height = tmp_h; @@ -1255,7 +1258,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, videobuf_queue_dma_contig_init(q, &sh_mobile_ceu_videobuf_ops, - ici->v4l2_dev.dev, &pcdev->lock, + icd->dev.parent, &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, pcdev->is_interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE, -- cgit v1.2.3 From 30e8a71f69f2769f966054f168e9e4ced8a1d091 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:50:46 +0200 Subject: soc-camera: V4L2 API compliant scaling (S_FMT) and cropping (S_CROP) From: Guennadi Liakhovetski The initial soc-camera scaling and cropping implementation turned out to be incompliant with the V4L2 API, e.g., it expected the user to specify cropping in output window pixels, instead of input window pixels. This patch converts the soc-camera core and all drivers to comply with the standard. Signed-off-by: Guennadi Liakhovetski Priority: low --- linux/Documentation/video4linux/soc-camera.txt | 40 ++ linux/drivers/media/video/mt9m001.c | 142 +++- linux/drivers/media/video/mt9m111.c | 112 ++- linux/drivers/media/video/mt9t031.c | 220 +++--- linux/drivers/media/video/mt9v022.c | 131 +++- linux/drivers/media/video/mx1_camera.c | 10 +- linux/drivers/media/video/mx3_camera.c | 114 +++- linux/drivers/media/video/ov772x.c | 84 ++- linux/drivers/media/video/pxa_camera.c | 201 ++++-- linux/drivers/media/video/sh_mobile_ceu_camera.c | 828 ++++++++++++++++------- linux/drivers/media/video/soc_camera.c | 130 ++-- linux/drivers/media/video/soc_camera_platform.c | 4 - linux/drivers/media/video/tw9910.c | 120 +++- linux/include/media/soc_camera.h | 21 +- 14 files changed, 1524 insertions(+), 633 deletions(-) diff --git a/linux/Documentation/video4linux/soc-camera.txt b/linux/Documentation/video4linux/soc-camera.txt index 178ef3c5e..3f87c7da4 100644 --- a/linux/Documentation/video4linux/soc-camera.txt +++ b/linux/Documentation/video4linux/soc-camera.txt @@ -116,5 +116,45 @@ functionality. struct soc_camera_device also links to an array of struct soc_camera_data_format, listing pixel formats, supported by the camera. +VIDIOC_S_CROP and VIDIOC_S_FMT behaviour +---------------------------------------- + +Above user ioctls modify image geometry as follows: + +VIDIOC_S_CROP: sets location and sizes of the sensor window. Unit is one sensor +pixel. Changing sensor window sizes preserves any scaling factors, therefore +user window sizes change as well. + +VIDIOC_S_FMT: sets user window. Should preserve previously set sensor window as +much as possible by modifying scaling factors. If the sensor window cannot be +preserved precisely, it may be changed too. + +In soc-camera there are two locations, where scaling and cropping can taks +place: in the camera driver and in the host driver. User ioctls are first passed +to the host driver, which then generally passes them down to the camera driver. +It is more efficient to perform scaling and cropping in the camera driver to +save camera bus bandwidth and maximise the framerate. However, if the camera +driver failed to set the required parameters with sufficient precision, the host +driver may decide to also use its own scaling and cropping to fulfill the user's +request. + +Camera drivers are interfaced to the soc-camera core and to host drivers over +the v4l2-subdev API, which is completely functional, it doesn't pass any data. +Therefore all camera drivers shall reply to .g_fmt() requests with their current +output geometry. This is necessary to correctly configure the camera bus. +.s_fmt() and .try_fmt() have to be implemented too. Sensor window and scaling +factors have to be maintained by camera drivers internally. According to the +V4L2 API all capture drivers must support the VIDIOC_CROPCAP ioctl, hence we +rely on camera drivers implementing .cropcap(). If the camera driver does not +support cropping, it may choose to not implement .s_crop(), but to enable +cropping support by the camera host driver at least the .g_crop method must be +implemented. + +User window geometry is kept in .user_width and .user_height fields in struct +soc_camera_device and used by the soc-camera core and host drivers. The core +updates these fields upon successful completion of a .s_fmt() call, but if these +fields change elsewhere, e.g., during .s_crop() processing, the host driver is +responsible for updating them. + -- Author: Guennadi Liakhovetski diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index d4ebab8c2..3fcf57118 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -39,6 +39,13 @@ #define MT9M001_GLOBAL_GAIN 0x35 #define MT9M001_CHIP_ENABLE 0xF1 +#define MT9M001_MAX_WIDTH 1280 +#define MT9M001_MAX_HEIGHT 1024 +#define MT9M001_MIN_WIDTH 48 +#define MT9M001_MIN_HEIGHT 32 +#define MT9M001_COLUMN_SKIP 20 +#define MT9M001_ROW_SKIP 12 + static const struct soc_camera_data_format mt9m001_colour_formats[] = { /* Order important: first natively supported, * second supported with a GPIO extender */ @@ -70,6 +77,8 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { struct mt9m001 { struct v4l2_subdev subdev; + struct v4l2_rect rect; /* Sensor window */ + __u32 fourcc; int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ unsigned char autoexposure; }; @@ -196,13 +205,31 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd) static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; struct i2c_client *client = sd->priv; struct mt9m001 *mt9m001 = to_mt9m001(client); + struct v4l2_rect rect = a->c; struct soc_camera_device *icd = client->dev.platform_data; int ret; const u16 hblank = 9, vblank = 25; + if (mt9m001->fourcc == V4L2_PIX_FMT_SBGGR8 || + mt9m001->fourcc == V4L2_PIX_FMT_SBGGR16) + /* + * Bayer format - even number of rows for simplicity, + * but let the user play with the top row. + */ + rect.height = ALIGN(rect.height, 2); + + /* Datasheet requirement: see register description */ + rect.width = ALIGN(rect.width, 2); + rect.left = ALIGN(rect.left, 2); + + soc_camera_limit_side(&rect.left, &rect.width, + MT9M001_COLUMN_SKIP, MT9M001_MIN_WIDTH, MT9M001_MAX_WIDTH); + + soc_camera_limit_side(&rect.top, &rect.height, + MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT); + /* Blanking and start values - default... */ ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); if (!ret) @@ -211,46 +238,98 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) /* The caller provides a supported format, as verified per * call to icd->try_fmt() */ if (!ret) - ret = reg_write(client, MT9M001_COLUMN_START, rect->left); + ret = reg_write(client, MT9M001_COLUMN_START, rect.left); if (!ret) - ret = reg_write(client, MT9M001_ROW_START, rect->top); + ret = reg_write(client, MT9M001_ROW_START, rect.top); if (!ret) - ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect->width - 1); + ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect.width - 1); if (!ret) ret = reg_write(client, MT9M001_WINDOW_HEIGHT, - rect->height + icd->y_skip_top - 1); + rect.height + icd->y_skip_top - 1); if (!ret && mt9m001->autoexposure) { ret = reg_write(client, MT9M001_SHUTTER_WIDTH, - rect->height + icd->y_skip_top + vblank); + rect.height + icd->y_skip_top + vblank); if (!ret) { const struct v4l2_queryctrl *qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (524 + (rect->height + icd->y_skip_top + + icd->exposure = (524 + (rect.height + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / 1048 + qctrl->minimum; } } + if (!ret) + mt9m001->rect = rect; + return ret; } +static int mt9m001_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); + + a->c = mt9m001->rect; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = MT9M001_COLUMN_SKIP; + a->bounds.top = MT9M001_ROW_SKIP; + a->bounds.width = MT9M001_MAX_WIDTH; + a->bounds.height = MT9M001_MAX_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int mt9m001_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct mt9m001 *mt9m001 = to_mt9m001(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + pix->width = mt9m001->rect.width; + pix->height = mt9m001->rect.height; + pix->pixelformat = mt9m001->fourcc; + pix->field = V4L2_FIELD_NONE; + pix->colorspace = V4L2_COLORSPACE_SRGB; + + return 0; +} + static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; - struct soc_camera_device *icd = client->dev.platform_data; + struct mt9m001 *mt9m001 = to_mt9m001(client); + struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_crop a = { .c = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, - .width = f->fmt.pix.width, - .height = f->fmt.pix.height, + .left = mt9m001->rect.left, + .top = mt9m001->rect.top, + .width = pix->width, + .height = pix->height, }, }; + int ret; /* No support for scaling so far, just crop. TODO: use skipping */ - return mt9m001_s_crop(sd, &a); + ret = mt9m001_s_crop(sd, &a); + if (!ret) { + pix->width = mt9m001->rect.width; + pix->height = mt9m001->rect.height; + mt9m001->fourcc = pix->pixelformat; + } + + return ret; } static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) @@ -259,9 +338,14 @@ static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; - v4l_bound_align_image(&pix->width, 48, 1280, 1, - &pix->height, 32 + icd->y_skip_top, - 1024 + icd->y_skip_top, 0, 0); + v4l_bound_align_image(&pix->width, MT9M001_MIN_WIDTH, + MT9M001_MAX_WIDTH, 1, + &pix->height, MT9M001_MIN_HEIGHT + icd->y_skip_top, + MT9M001_MAX_HEIGHT + icd->y_skip_top, 0, 0); + + if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || + pix->pixelformat == V4L2_PIX_FMT_SBGGR16) + pix->height = ALIGN(pix->height - 1, 2); return 0; } @@ -472,11 +556,11 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (ctrl->value) { const u16 vblank = 25; if (reg_write(client, MT9M001_SHUTTER_WIDTH, - icd->rect_current.height + + mt9m001->rect.height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (524 + (icd->rect_current.height + + icd->exposure = (524 + (mt9m001->rect.height + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / 1048 + qctrl->minimum; @@ -548,6 +632,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, if (flags & SOCAM_DATAWIDTH_8) icd->num_formats++; + mt9m001->fourcc = icd->formats->fourcc; + dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, data == 0x8431 ? "C12STM" : "C12ST"); @@ -556,10 +642,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, static void mt9m001_video_remove(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&client->dev, "Video %x removed: %p, %p\n", client->addr, + dev_dbg(&icd->dev, "Video removed: %p, %p\n", icd->dev.parent, icd->vdev); if (icl->free_bus) icl->free_bus(icl); @@ -578,8 +663,11 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { .s_stream = mt9m001_s_stream, .s_fmt = mt9m001_s_fmt, + .g_fmt = mt9m001_g_fmt, .try_fmt = mt9m001_try_fmt, .s_crop = mt9m001_s_crop, + .g_crop = mt9m001_g_crop, + .cropcap = mt9m001_cropcap, }; static struct v4l2_subdev_ops mt9m001_subdev_ops = { @@ -625,15 +713,13 @@ static int mt9m001_probe(struct i2c_client *client) /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m001_ops; - icd->rect_max.left = 20; - icd->rect_max.top = 12; - icd->rect_max.width = 1280; - icd->rect_max.height = 1024; - icd->rect_current.left = 20; - icd->rect_current.top = 12; - icd->width_min = 48; - icd->height_min = 32; icd->y_skip_top = 1; + + mt9m001->rect.left = MT9M001_COLUMN_SKIP; + mt9m001->rect.top = MT9M001_ROW_SKIP; + mt9m001->rect.width = MT9M001_MAX_WIDTH; + mt9m001->rect.height = MT9M001_MAX_HEIGHT; + /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9m001->autoexposure = 1; diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 44e565faf..905054e08 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -194,7 +194,7 @@ static int mt9m111_reg_read(struct i2c_client *client, const u16 reg) ret = reg_page_map_set(client, reg); if (!ret) - ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff))); + ret = swab16(i2c_smbus_read_word_data(client, reg & 0xff)); dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret); return ret; @@ -257,8 +257,8 @@ static int mt9m111_setup_rect(struct i2c_client *client, int width = rect->width; int height = rect->height; - if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8) - || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16)) + if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 || + mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16) is_raw_format = 1; else is_raw_format = 0; @@ -395,23 +395,85 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) return 0; } +static int mt9m111_make_rect(struct i2c_client *client, + struct v4l2_rect *rect) +{ + struct mt9m111 *mt9m111 = to_mt9m111(client); + + if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 || + mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16) { + /* Bayer format - even size lengths */ + rect->width = ALIGN(rect->width, 2); + rect->height = ALIGN(rect->height, 2); + /* Let the user play with the starting pixel */ + } + + /* FIXME: the datasheet doesn't specify minimum sizes */ + soc_camera_limit_side(&rect->left, &rect->width, + MT9M111_MIN_DARK_COLS, 2, MT9M111_MAX_WIDTH); + + soc_camera_limit_side(&rect->top, &rect->height, + MT9M111_MIN_DARK_ROWS, 2, MT9M111_MAX_HEIGHT); + + return mt9m111_setup_rect(client, rect); +} + static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; + struct v4l2_rect rect = a->c; struct i2c_client *client = sd->priv; struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n", - __func__, rect->left, rect->top, rect->width, - rect->height); + __func__, rect.left, rect.top, rect.width, rect.height); - ret = mt9m111_setup_rect(client, rect); + ret = mt9m111_make_rect(client, &rect); if (!ret) - mt9m111->rect = *rect; + mt9m111->rect = rect; return ret; } +static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); + + a->c = mt9m111->rect; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = MT9M111_MIN_DARK_COLS; + a->bounds.top = MT9M111_MIN_DARK_ROWS; + a->bounds.width = MT9M111_MAX_WIDTH; + a->bounds.height = MT9M111_MAX_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int mt9m111_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct mt9m111 *mt9m111 = to_mt9m111(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + pix->width = mt9m111->rect.width; + pix->height = mt9m111->rect.height; + pix->pixelformat = mt9m111->pixfmt; + pix->field = V4L2_FIELD_NONE; + pix->colorspace = V4L2_COLORSPACE_SRGB; + + return 0; +} + static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt) { struct mt9m111 *mt9m111 = to_mt9m111(client); @@ -478,7 +540,7 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) __func__, pix->pixelformat, rect.left, rect.top, rect.width, rect.height); - ret = mt9m111_setup_rect(client, &rect); + ret = mt9m111_make_rect(client, &rect); if (!ret) ret = mt9m111_set_pixfmt(client, pix->pixelformat); if (!ret) @@ -489,11 +551,27 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) static int mt9m111_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; + bool bayer = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || + pix->pixelformat == V4L2_PIX_FMT_SBGGR16; + + /* + * With Bayer format enforce even side lengths, but let the user play + * with the starting pixel + */ if (pix->height > MT9M111_MAX_HEIGHT) pix->height = MT9M111_MAX_HEIGHT; + else if (pix->height < 2) + pix->height = 2; + else if (bayer) + pix->height = ALIGN(pix->height, 2); + if (pix->width > MT9M111_MAX_WIDTH) pix->width = MT9M111_MAX_WIDTH; + else if (pix->width < 2) + pix->width = 2; + else if (bayer) + pix->width = ALIGN(pix->width, 2); return 0; } @@ -906,8 +984,11 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { .s_fmt = mt9m111_s_fmt, + .g_fmt = mt9m111_g_fmt, .try_fmt = mt9m111_try_fmt, .s_crop = mt9m111_s_crop, + .g_crop = mt9m111_g_crop, + .cropcap = mt9m111_cropcap, }; static struct v4l2_subdev_ops mt9m111_subdev_ops = { @@ -953,16 +1034,13 @@ static int mt9m111_probe(struct i2c_client *client, /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m111_ops; - icd->rect_max.left = MT9M111_MIN_DARK_COLS; - icd->rect_max.top = MT9M111_MIN_DARK_ROWS; - icd->rect_max.width = MT9M111_MAX_WIDTH; - icd->rect_max.height = MT9M111_MAX_HEIGHT; - icd->rect_current.left = icd->rect_max.left; - icd->rect_current.top = icd->rect_max.top; - icd->width_min = MT9M111_MIN_DARK_ROWS; - icd->height_min = MT9M111_MIN_DARK_COLS; icd->y_skip_top = 0; + mt9m111->rect.left = MT9M111_MIN_DARK_COLS; + mt9m111->rect.top = MT9M111_MIN_DARK_ROWS; + mt9m111->rect.width = MT9M111_MAX_WIDTH; + mt9m111->rect.height = MT9M111_MAX_HEIGHT; + ret = mt9m111_video_probe(icd, client); if (ret) { icd->ops = NULL; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 00877b4ae..30d4aaf81 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -47,7 +47,7 @@ #define MT9T031_MAX_HEIGHT 1536 #define MT9T031_MAX_WIDTH 2048 #define MT9T031_MIN_HEIGHT 2 -#define MT9T031_MIN_WIDTH 2 +#define MT9T031_MIN_WIDTH 18 #define MT9T031_HORIZONTAL_BLANK 142 #define MT9T031_VERTICAL_BLANK 25 #define MT9T031_COLUMN_SKIP 32 @@ -69,10 +69,11 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = { struct mt9t031 { struct v4l2_subdev subdev; + struct v4l2_rect rect; /* Sensor window */ int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ - unsigned char autoexposure; u16 xskip; u16 yskip; + unsigned char autoexposure; }; static struct mt9t031 *to_mt9t031(const struct i2c_client *client) @@ -218,56 +219,68 @@ static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); } -/* Round up minima and round down maxima */ -static void recalculate_limits(struct soc_camera_device *icd, - u16 xskip, u16 yskip) +/* target must be _even_ */ +static u16 mt9t031_skip(s32 *source, s32 target, s32 max) { - icd->rect_max.left = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip; - icd->rect_max.top = (MT9T031_ROW_SKIP + yskip - 1) / yskip; - icd->width_min = (MT9T031_MIN_WIDTH + xskip - 1) / xskip; - icd->height_min = (MT9T031_MIN_HEIGHT + yskip - 1) / yskip; - icd->rect_max.width = MT9T031_MAX_WIDTH / xskip; - icd->rect_max.height = MT9T031_MAX_HEIGHT / yskip; + unsigned int skip; + + if (*source < target + target / 2) { + *source = target; + return 1; + } + + skip = min(max, *source + target / 2) / target; + if (skip > 8) + skip = 8; + *source = target * skip; + + return skip; } +/* rect is the sensor rectangle, the caller guarantees parameter validity */ static int mt9t031_set_params(struct soc_camera_device *icd, struct v4l2_rect *rect, u16 xskip, u16 yskip) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct mt9t031 *mt9t031 = to_mt9t031(client); int ret; - u16 xbin, ybin, width, height, left, top; + u16 xbin, ybin; const u16 hblank = MT9T031_HORIZONTAL_BLANK, vblank = MT9T031_VERTICAL_BLANK; - width = rect->width * xskip; - height = rect->height * yskip; - left = rect->left * xskip; - top = rect->top * yskip; - xbin = min(xskip, (u16)3); ybin = min(yskip, (u16)3); - dev_dbg(&client->dev, "xskip %u, width %u/%u, yskip %u, height %u/%u\n", - xskip, width, rect->width, yskip, height, rect->height); - - /* Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper */ + /* + * Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper. + * There is always a valid suitably aligned value. The worst case is + * xbin = 3, width = 2048. Then we will start at 36, the last read out + * pixel will be 2083, which is < 2085 - first black pixel. + * + * MT9T031 datasheet imposes window left border alignment, depending on + * the selected xskip. Failing to conform to this requirement produces + * dark horizontal stripes in the image. However, even obeying to this + * requirement doesn't eliminate the stripes in all configurations. They + * appear "locally reproducibly," but can differ between tests under + * different lighting conditions. + */ switch (xbin) { - case 2: - left = (left + 3) & ~3; + case 1: + rect->left &= ~1; break; - case 3: - left = roundup(left, 6); - } - - switch (ybin) { case 2: - top = (top + 3) & ~3; + rect->left &= ~3; break; case 3: - top = roundup(top, 6); + rect->left = rect->left > roundup(MT9T031_COLUMN_SKIP, 6) ? + (rect->left / 6) * 6 : roundup(MT9T031_COLUMN_SKIP, 6); } + rect->top &= ~1; + + dev_dbg(&client->dev, "skip %u:%u, rect %ux%u@%u:%u\n", + xskip, yskip, rect->width, rect->height, rect->left, rect->top); + /* Disable register update, reconfigure atomically */ ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 1); if (ret < 0) @@ -287,27 +300,29 @@ static int mt9t031_set_params(struct soc_camera_device *icd, ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE, ((ybin - 1) << 4) | (yskip - 1)); } - dev_dbg(&client->dev, "new physical left %u, top %u\n", left, top); + dev_dbg(&client->dev, "new physical left %u, top %u\n", + rect->left, rect->top); /* The caller provides a supported format, as guaranteed by * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ if (ret >= 0) - ret = reg_write(client, MT9T031_COLUMN_START, left); + ret = reg_write(client, MT9T031_COLUMN_START, rect->left); if (ret >= 0) - ret = reg_write(client, MT9T031_ROW_START, top); + ret = reg_write(client, MT9T031_ROW_START, rect->top); if (ret >= 0) - ret = reg_write(client, MT9T031_WINDOW_WIDTH, width - 1); + ret = reg_write(client, MT9T031_WINDOW_WIDTH, rect->width - 1); if (ret >= 0) ret = reg_write(client, MT9T031_WINDOW_HEIGHT, - height + icd->y_skip_top - 1); + rect->height + icd->y_skip_top - 1); if (ret >= 0 && mt9t031->autoexposure) { - ret = set_shutter(client, height + icd->y_skip_top + vblank); + ret = set_shutter(client, + rect->height + icd->y_skip_top + vblank); if (ret >= 0) { const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; const struct v4l2_queryctrl *qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (shutter_max / 2 + (height + + icd->exposure = (shutter_max / 2 + (rect->height + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / shutter_max + qctrl->minimum; @@ -318,27 +333,72 @@ static int mt9t031_set_params(struct soc_camera_device *icd, if (ret >= 0) ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1); + if (ret >= 0) { + mt9t031->rect = *rect; + mt9t031->xskip = xskip; + mt9t031->yskip = yskip; + } + return ret < 0 ? ret : 0; } static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; + struct v4l2_rect rect = a->c; struct i2c_client *client = sd->priv; struct mt9t031 *mt9t031 = to_mt9t031(client); struct soc_camera_device *icd = client->dev.platform_data; - /* Make sure we don't exceed sensor limits */ - if (rect->left + rect->width > icd->rect_max.left + icd->rect_max.width) - rect->left = icd->rect_max.width + icd->rect_max.left - - rect->width; + rect.width = ALIGN(rect.width, 2); + rect.height = ALIGN(rect.height, 2); + + soc_camera_limit_side(&rect.left, &rect.width, + MT9T031_COLUMN_SKIP, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH); + + soc_camera_limit_side(&rect.top, &rect.height, + MT9T031_ROW_SKIP, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT); + + return mt9t031_set_params(icd, &rect, mt9t031->xskip, mt9t031->yskip); +} + +static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); + + a->c = mt9t031->rect; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (rect->top + rect->height > icd->rect_max.height + icd->rect_max.top) - rect->top = icd->rect_max.height + icd->rect_max.top - - rect->height; + return 0; +} + +static int mt9t031_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = MT9T031_COLUMN_SKIP; + a->bounds.top = MT9T031_ROW_SKIP; + a->bounds.width = MT9T031_MAX_WIDTH; + a->bounds.height = MT9T031_MAX_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; - /* CROP - no change in scaling, or in limits */ - return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); + return 0; +} + +static int mt9t031_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct mt9t031 *mt9t031 = to_mt9t031(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + pix->width = mt9t031->rect.width / mt9t031->xskip; + pix->height = mt9t031->rect.height / mt9t031->yskip; + pix->pixelformat = V4L2_PIX_FMT_SGRBG10; + pix->field = V4L2_FIELD_NONE; + pix->colorspace = V4L2_COLORSPACE_SRGB; + + return 0; } static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) @@ -346,40 +406,25 @@ static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct i2c_client *client = sd->priv; struct mt9t031 *mt9t031 = to_mt9t031(client); struct soc_camera_device *icd = client->dev.platform_data; - int ret; + struct v4l2_pix_format *pix = &f->fmt.pix; u16 xskip, yskip; - struct v4l2_rect rect = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, - .width = f->fmt.pix.width, - .height = f->fmt.pix.height, - }; + struct v4l2_rect rect = mt9t031->rect; /* - * try_fmt has put rectangle within limits. - * S_FMT - use binning and skipping for scaling, recalculate - * limits, used for cropping + * try_fmt has put width and height within limits. + * S_FMT: use binning and skipping for scaling */ - /* Is this more optimal than just a division? */ - for (xskip = 8; xskip > 1; xskip--) - if (rect.width * xskip <= MT9T031_MAX_WIDTH) - break; - - for (yskip = 8; yskip > 1; yskip--) - if (rect.height * yskip <= MT9T031_MAX_HEIGHT) - break; - - recalculate_limits(icd, xskip, yskip); - - ret = mt9t031_set_params(icd, &rect, xskip, yskip); - if (!ret) { - mt9t031->xskip = xskip; - mt9t031->yskip = yskip; - } + xskip = mt9t031_skip(&rect.width, pix->width, MT9T031_MAX_WIDTH); + yskip = mt9t031_skip(&rect.height, pix->height, MT9T031_MAX_HEIGHT); - return ret; + /* mt9t031_set_params() doesn't change width and height */ + return mt9t031_set_params(icd, &rect, xskip, yskip); } +/* + * If a user window larger than sensor window is requested, we'll increase the + * sensor window. + */ static int mt9t031_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct v4l2_pix_format *pix = &f->fmt.pix; @@ -620,12 +665,12 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (ctrl->value) { const u16 vblank = MT9T031_VERTICAL_BLANK; const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; - if (set_shutter(client, icd->rect_current.height + + if (set_shutter(client, mt9t031->rect.height + icd->y_skip_top + vblank) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); icd->exposure = (shutter_max / 2 + - (icd->rect_current.height + + (mt9t031->rect.height + icd->y_skip_top + vblank - 1) * (qctrl->maximum - qctrl->minimum)) / shutter_max + qctrl->minimum; @@ -645,12 +690,6 @@ static int mt9t031_video_probe(struct i2c_client *client) struct mt9t031 *mt9t031 = to_mt9t031(client); s32 data; - /* We must have a parent by now. And it cannot be a wrong one. - * So this entire test is completely redundant. */ - if (!icd->dev.parent || - to_soc_camera_host(icd->dev.parent)->nr != icd->iface) - return -ENODEV; - /* Enable the chip */ data = reg_write(client, MT9T031_CHIP_ENABLE, 1); dev_dbg(&client->dev, "write: %d\n", data); @@ -688,8 +727,11 @@ static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { .s_stream = mt9t031_s_stream, .s_fmt = mt9t031_s_fmt, + .g_fmt = mt9t031_g_fmt, .try_fmt = mt9t031_try_fmt, .s_crop = mt9t031_s_crop, + .g_crop = mt9t031_g_crop, + .cropcap = mt9t031_cropcap, }; static struct v4l2_subdev_ops mt9t031_subdev_ops = { @@ -735,15 +777,13 @@ static int mt9t031_probe(struct i2c_client *client, /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9t031_ops; - icd->rect_max.left = MT9T031_COLUMN_SKIP; - icd->rect_max.top = MT9T031_ROW_SKIP; - icd->rect_current.left = icd->rect_max.left; - icd->rect_current.top = icd->rect_max.top; - icd->width_min = MT9T031_MIN_WIDTH; - icd->rect_max.width = MT9T031_MAX_WIDTH; - icd->height_min = MT9T031_MIN_HEIGHT; - icd->rect_max.height = MT9T031_MAX_HEIGHT; icd->y_skip_top = 0; + + mt9t031->rect.left = MT9T031_COLUMN_SKIP; + mt9t031->rect.top = MT9T031_ROW_SKIP; + mt9t031->rect.width = MT9T031_MAX_WIDTH; + mt9t031->rect.height = MT9T031_MAX_HEIGHT; + /* Simulated autoexposure. If enabled, we calculate shutter width * ourselves in the driver based on vertical blanking and frame width */ mt9t031->autoexposure = 1; diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index fd2d13d6c..3153fd5d2 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -55,6 +55,13 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); /* Progressive scan, master, defaults */ #define MT9V022_CHIP_CONTROL_DEFAULT 0x188 +#define MT9V022_MAX_WIDTH 752 +#define MT9V022_MAX_HEIGHT 480 +#define MT9V022_MIN_WIDTH 48 +#define MT9V022_MIN_HEIGHT 32 +#define MT9V022_COLUMN_SKIP 1 +#define MT9V022_ROW_SKIP 4 + static const struct soc_camera_data_format mt9v022_colour_formats[] = { /* Order important: first natively supported, * second supported with a GPIO extender */ @@ -86,6 +93,8 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { struct mt9v022 { struct v4l2_subdev subdev; + struct v4l2_rect rect; /* Sensor window */ + __u32 fourcc; int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ u16 chip_control; }; @@ -250,44 +259,101 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); + struct v4l2_rect rect = a->c; struct soc_camera_device *icd = client->dev.platform_data; int ret; + /* Bayer format - even size lengths */ + if (mt9v022->fourcc == V4L2_PIX_FMT_SBGGR8 || + mt9v022->fourcc == V4L2_PIX_FMT_SBGGR16) { + rect.width = ALIGN(rect.width, 2); + rect.height = ALIGN(rect.height, 2); + /* Let the user play with the starting pixel */ + } + + soc_camera_limit_side(&rect.left, &rect.width, + MT9V022_COLUMN_SKIP, MT9V022_MIN_WIDTH, MT9V022_MAX_WIDTH); + + soc_camera_limit_side(&rect.top, &rect.height, + MT9V022_ROW_SKIP, MT9V022_MIN_HEIGHT, MT9V022_MAX_HEIGHT); + /* Like in example app. Contradicts the datasheet though */ ret = reg_read(client, MT9V022_AEC_AGC_ENABLE); if (ret >= 0) { if (ret & 1) /* Autoexposure */ ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, - rect->height + icd->y_skip_top + 43); + rect.height + icd->y_skip_top + 43); else ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, - rect->height + icd->y_skip_top + 43); + rect.height + icd->y_skip_top + 43); } /* Setup frame format: defaults apart from width and height */ if (!ret) - ret = reg_write(client, MT9V022_COLUMN_START, rect->left); + ret = reg_write(client, MT9V022_COLUMN_START, rect.left); if (!ret) - ret = reg_write(client, MT9V022_ROW_START, rect->top); + ret = reg_write(client, MT9V022_ROW_START, rect.top); if (!ret) /* Default 94, Phytec driver says: * "width + horizontal blank >= 660" */ ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING, - rect->width > 660 - 43 ? 43 : - 660 - rect->width); + rect.width > 660 - 43 ? 43 : + 660 - rect.width); if (!ret) ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45); if (!ret) - ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect->width); + ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width); if (!ret) ret = reg_write(client, MT9V022_WINDOW_HEIGHT, - rect->height + icd->y_skip_top); + rect.height + icd->y_skip_top); if (ret < 0) return ret; - dev_dbg(&client->dev, "Frame %ux%u pixel\n", rect->width, rect->height); + dev_dbg(&client->dev, "Frame %ux%u pixel\n", rect.width, rect.height); + + mt9v022->rect = rect; + + return 0; +} + +static int mt9v022_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); + + a->c = mt9v022->rect; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = MT9V022_COLUMN_SKIP; + a->bounds.top = MT9V022_ROW_SKIP; + a->bounds.width = MT9V022_MAX_WIDTH; + a->bounds.height = MT9V022_MAX_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int mt9v022_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct mt9v022 *mt9v022 = to_mt9v022(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + pix->width = mt9v022->rect.width; + pix->height = mt9v022->rect.height; + pix->pixelformat = mt9v022->fourcc; + pix->field = V4L2_FIELD_NONE; + pix->colorspace = V4L2_COLORSPACE_SRGB; return 0; } @@ -296,16 +362,16 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; struct mt9v022 *mt9v022 = to_mt9v022(client); - struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_crop a = { .c = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, + .left = mt9v022->rect.left, + .top = mt9v022->rect.top, .width = pix->width, .height = pix->height, }, }; + int ret; /* The caller provides a supported format, as verified per call to * icd->try_fmt(), datawidth is from our supported format list */ @@ -328,7 +394,14 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) } /* No support for scaling on this camera, just crop. */ - return mt9v022_s_crop(sd, &a); + ret = mt9v022_s_crop(sd, &a); + if (!ret) { + pix->width = mt9v022->rect.width; + pix->height = mt9v022->rect.height; + mt9v022->fourcc = pix->pixelformat; + } + + return ret; } static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) @@ -336,10 +409,13 @@ static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) struct i2c_client *client = sd->priv; struct soc_camera_device *icd = client->dev.platform_data; struct v4l2_pix_format *pix = &f->fmt.pix; + int align = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || + pix->pixelformat == V4L2_PIX_FMT_SBGGR16; - v4l_bound_align_image(&pix->width, 48, 752, 2 /* ? */, - &pix->height, 32 + icd->y_skip_top, - 480 + icd->y_skip_top, 0, 0); + v4l_bound_align_image(&pix->width, MT9V022_MIN_WIDTH, + MT9V022_MAX_WIDTH, align, + &pix->height, MT9V022_MIN_HEIGHT + icd->y_skip_top, + MT9V022_MAX_HEIGHT + icd->y_skip_top, align, 0); return 0; } @@ -669,6 +745,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, if (flags & SOCAM_DATAWIDTH_8) icd->num_formats++; + mt9v022->fourcc = icd->formats->fourcc; + dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? "monochrome" : "colour"); @@ -679,10 +757,9 @@ ei2c: static void mt9v022_video_remove(struct soc_camera_device *icd) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct soc_camera_link *icl = to_soc_camera_link(icd); - dev_dbg(&client->dev, "Video %x removed: %p, %p\n", client->addr, + dev_dbg(&icd->dev, "Video removed: %p, %p\n", icd->dev.parent, icd->vdev); if (icl->free_bus) icl->free_bus(icl); @@ -701,8 +778,11 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { .s_stream = mt9v022_s_stream, .s_fmt = mt9v022_s_fmt, + .g_fmt = mt9v022_g_fmt, .try_fmt = mt9v022_try_fmt, .s_crop = mt9v022_s_crop, + .g_crop = mt9v022_g_crop, + .cropcap = mt9v022_cropcap, }; static struct v4l2_subdev_ops mt9v022_subdev_ops = { @@ -749,16 +829,13 @@ static int mt9v022_probe(struct i2c_client *client) mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; icd->ops = &mt9v022_ops; - icd->rect_max.left = 1; - icd->rect_max.top = 4; - icd->rect_max.width = 752; - icd->rect_max.height = 480; - icd->rect_current.left = 1; - icd->rect_current.top = 4; - icd->width_min = 48; - icd->height_min = 32; icd->y_skip_top = 1; + mt9v022->rect.left = MT9V022_COLUMN_SKIP; + mt9v022->rect.top = MT9V022_ROW_SKIP; + mt9v022->rect.width = MT9V022_MAX_WIDTH; + mt9v022->rect.height = MT9V022_MAX_HEIGHT; + ret = mt9v022_video_probe(icd, client); if (ret) { icd->ops = NULL; diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 1f1324a1d..3875483ab 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -126,7 +126,7 @@ static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, { struct soc_camera_device *icd = vq->priv_data; - *size = icd->rect_current.width * icd->rect_current.height * + *size = icd->user_width * icd->user_height * ((icd->current_fmt->depth + 7) >> 3); if (!*count) @@ -178,12 +178,12 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, buf->inwork = 1; if (buf->fmt != icd->current_fmt || - vb->width != icd->rect_current.width || - vb->height != icd->rect_current.height || + vb->width != icd->user_width || + vb->height != icd->user_height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->rect_current.width; - vb->height = icd->rect_current.height; + vb->width = icd->user_width; + vb->height = icd->user_height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } diff --git a/linux/drivers/media/video/mx3_camera.c b/linux/drivers/media/video/mx3_camera.c index d5b51e990..dff2e5e2d 100644 --- a/linux/drivers/media/video/mx3_camera.c +++ b/linux/drivers/media/video/mx3_camera.c @@ -220,7 +220,7 @@ static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, if (!mx3_cam->idmac_channel[0]) return -EINVAL; - *size = icd->rect_current.width * icd->rect_current.height * bpp; + *size = icd->user_width * icd->user_height * bpp; if (!*count) *count = 32; @@ -241,7 +241,7 @@ static int mx3_videobuf_prepare(struct videobuf_queue *vq, struct mx3_camera_buffer *buf = container_of(vb, struct mx3_camera_buffer, vb); /* current_fmt _must_ always be set */ - size_t new_size = icd->rect_current.width * icd->rect_current.height * + size_t new_size = icd->user_width * icd->user_height * ((icd->current_fmt->depth + 7) >> 3); int ret; @@ -251,12 +251,12 @@ static int mx3_videobuf_prepare(struct videobuf_queue *vq, */ if (buf->fmt != icd->current_fmt || - vb->width != icd->rect_current.width || - vb->height != icd->rect_current.height || + vb->width != icd->user_width || + vb->height != icd->user_height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->rect_current.width; - vb->height = icd->rect_current.height; + vb->width = icd->user_width; + vb->height = icd->user_height; vb->field = field; if (vb->state != VIDEOBUF_NEEDS_INIT) free_buffer(vq, buf); @@ -354,9 +354,9 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, /* This is the configuration of one sg-element */ video->out_pixel_fmt = fourcc_to_ipu_pix(data_fmt->fourcc); - video->out_width = icd->rect_current.width; - video->out_height = icd->rect_current.height; - video->out_stride = icd->rect_current.width; + video->out_width = icd->user_width; + video->out_height = icd->user_height; + video->out_stride = icd->user_width; #ifdef DEBUG /* helps to see what DMA actually has written */ @@ -541,7 +541,7 @@ static bool channel_change_requested(struct soc_camera_device *icd, /* Do buffers have to be re-allocated or channel re-configured? */ return ichan && rect->width * rect->height > - icd->rect_current.width * icd->rect_current.height; + icd->user_width * icd->user_height; } static int test_platform_param(struct mx3_camera_dev *mx3_cam, @@ -589,8 +589,8 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam, *flags |= SOCAM_DATAWIDTH_4; break; default: - dev_info(mx3_cam->soc_host.v4l2_dev.dev, "Unsupported bus width %d\n", - buswidth); + dev_warn(mx3_cam->soc_host.v4l2_dev.dev, + "Unsupported bus width %d\n", buswidth); return -EINVAL; } @@ -605,8 +605,7 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd, unsigned long bus_flags, camera_flags; int ret = test_platform_param(mx3_cam, depth, &bus_flags); - dev_dbg(icd->dev.parent, "requested bus width %d bit: %d\n", - depth, ret); + dev_dbg(icd->dev.parent, "request bus width %d bit: %d\n", depth, ret); if (ret < 0) return ret; @@ -727,13 +726,13 @@ passthrough: } static void configure_geometry(struct mx3_camera_dev *mx3_cam, - struct v4l2_rect *rect) + unsigned int width, unsigned int height) { u32 ctrl, width_field, height_field; /* Setup frame size - this cannot be changed on-the-fly... */ - width_field = rect->width - 1; - height_field = rect->height - 1; + width_field = width - 1; + height_field = height - 1; csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_SENS_FRM_SIZE); csi_reg_write(mx3_cam, width_field << 16, CSI_FLASH_STROBE_1); @@ -745,11 +744,6 @@ static void configure_geometry(struct mx3_camera_dev *mx3_cam, ctrl = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000; /* Sensor does the cropping */ csi_reg_write(mx3_cam, ctrl | 0 | (0 << 8), CSI_OUT_FRM_CTRL); - - /* - * No need to free resources here if we fail, we'll see if we need to - * do this next time we are called - */ } static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) @@ -786,6 +780,22 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) return 0; } +/* + * FIXME: learn to use stride != width, then we can keep stride properly aligned + * and support arbitrary (even) widths. + */ +static inline void stride_align(__s32 *width) +{ + if (((*width + 7) & ~7) < 4096) + *width = (*width + 7) & ~7; + else + *width = *width & ~7; +} + +/* + * As long as we don't implement host-side cropping and scaling, we can use + * default g_crop and cropcap from soc_camera.c + */ static int mx3_camera_set_crop(struct soc_camera_device *icd, struct v4l2_crop *a) { @@ -793,20 +803,51 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct mx3_camera_dev *mx3_cam = ici->priv; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct v4l2_format f = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE}; + struct v4l2_pix_format *pix = &f.fmt.pix; + int ret; - /* - * We now know pixel formats and can decide upon DMA-channel(s) - * So far only direct camera-to-memory is supported - */ - if (channel_change_requested(icd, rect)) { - int ret = acquire_dma_channel(mx3_cam); + soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); + soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096); + + ret = v4l2_subdev_call(sd, video, s_crop, a); + if (ret < 0) + return ret; + + /* The capture device might have changed its output */ + ret = v4l2_subdev_call(sd, video, g_fmt, &f); + if (ret < 0) + return ret; + + if (pix->width & 7) { + /* Ouch! We can only handle 8-byte aligned width... */ + stride_align(&pix->width); + ret = v4l2_subdev_call(sd, video, s_fmt, &f); if (ret < 0) return ret; } - configure_geometry(mx3_cam, rect); + if (pix->width != icd->user_width || pix->height != icd->user_height) { + /* + * We now know pixel formats and can decide upon DMA-channel(s) + * So far only direct camera-to-memory is supported + */ + if (channel_change_requested(icd, rect)) { + int ret = acquire_dma_channel(mx3_cam); + if (ret < 0) + return ret; + } - return v4l2_subdev_call(sd, video, s_crop, a); + configure_geometry(mx3_cam, pix->width, pix->height); + } + + dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", + pix->width, pix->height); + + icd->user_width = pix->width; + icd->user_height = pix->height; + + return ret; } static int mx3_camera_set_fmt(struct soc_camera_device *icd, @@ -817,12 +858,6 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_rect rect = { - .left = icd->rect_current.left, - .top = icd->rect_current.top, - .width = pix->width, - .height = pix->height, - }; int ret; xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); @@ -832,6 +867,9 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, return -EINVAL; } + stride_align(&pix->width); + dev_dbg(icd->dev.parent, "Set format %dx%d\n", pix->width, pix->height); + ret = acquire_dma_channel(mx3_cam); if (ret < 0) return ret; @@ -842,7 +880,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, * mxc_v4l2_s_fmt() */ - configure_geometry(mx3_cam, &rect); + configure_geometry(mx3_cam, pix->width, pix->height); ret = v4l2_subdev_call(sd, video, s_fmt, f); if (!ret) { @@ -850,6 +888,8 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, icd->current_fmt = xlate->host_fmt; } + dev_dbg(icd->dev.parent, "Sensor set %dx%d\n", pix->width, pix->height); + return ret; } diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 392327b72..2d48a7aeb 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -382,11 +382,10 @@ struct regval_list { }; struct ov772x_color_format { - char *name; - __u32 fourcc; - u8 dsp3; - u8 com3; - u8 com7; + const struct soc_camera_data_format *format; + u8 dsp3; + u8 com3; + u8 com7; }; struct ov772x_win_size { @@ -481,43 +480,43 @@ static const struct soc_camera_data_format ov772x_fmt_lists[] = { */ static const struct ov772x_color_format ov772x_cfmts[] = { { - SETFOURCC(YUYV), + .format = &ov772x_fmt_lists[0], .dsp3 = 0x0, .com3 = SWAP_YUV, .com7 = OFMT_YUV, }, { - SETFOURCC(YVYU), + .format = &ov772x_fmt_lists[1], .dsp3 = UV_ON, .com3 = SWAP_YUV, .com7 = OFMT_YUV, }, { - SETFOURCC(UYVY), + .format = &ov772x_fmt_lists[2], .dsp3 = 0x0, .com3 = 0x0, .com7 = OFMT_YUV, }, { - SETFOURCC(RGB555), + .format = &ov772x_fmt_lists[3], .dsp3 = 0x0, .com3 = SWAP_RGB, .com7 = FMT_RGB555 | OFMT_RGB, }, { - SETFOURCC(RGB555X), + .format = &ov772x_fmt_lists[4], .dsp3 = 0x0, .com3 = 0x0, .com7 = FMT_RGB555 | OFMT_RGB, }, { - SETFOURCC(RGB565), + .format = &ov772x_fmt_lists[5], .dsp3 = 0x0, .com3 = SWAP_RGB, .com7 = FMT_RGB565 | OFMT_RGB, }, { - SETFOURCC(RGB565X), + .format = &ov772x_fmt_lists[6], .dsp3 = 0x0, .com3 = 0x0, .com7 = FMT_RGB565 | OFMT_RGB, @@ -648,8 +647,8 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); - dev_dbg(&client->dev, - "format %s, win %s\n", priv->fmt->name, priv->win->name); + dev_dbg(&client->dev, "format %s, win %s\n", + priv->fmt->format->name, priv->win->name); return 0; } @@ -818,7 +817,7 @@ static int ov772x_set_params(struct i2c_client *client, */ priv->fmt = NULL; for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) { - if (pixfmt == ov772x_cfmts[i].fourcc) { + if (pixfmt == ov772x_cfmts[i].format->fourcc) { priv->fmt = ov772x_cfmts + i; break; } @@ -955,6 +954,56 @@ ov772x_set_fmt_error: return ret; } +static int ov772x_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + a->c.left = 0; + a->c.top = 0; + a->c.width = VGA_WIDTH; + a->c.height = VGA_HEIGHT; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = 0; + a->bounds.top = 0; + a->bounds.width = VGA_WIDTH; + a->bounds.height = VGA_HEIGHT; + a->defrect = a->bounds; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int ov772x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct ov772x_priv *priv = to_ov772x(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + if (!priv->win || !priv->fmt) { + u32 width = VGA_WIDTH, height = VGA_HEIGHT; + int ret = ov772x_set_params(client, &width, &height, + V4L2_PIX_FMT_YUYV); + if (ret < 0) + return ret; + } + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + pix->width = priv->win->width; + pix->height = priv->win->height; + pix->pixelformat = priv->fmt->format->fourcc; + pix->colorspace = priv->fmt->format->colorspace; + pix->field = V4L2_FIELD_NONE; + + return 0; +} + static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { struct i2c_client *client = sd->priv; @@ -1060,8 +1109,11 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { .s_stream = ov772x_s_stream, + .g_fmt = ov772x_g_fmt, .s_fmt = ov772x_s_fmt, .try_fmt = ov772x_try_fmt, + .cropcap = ov772x_cropcap, + .g_crop = ov772x_g_crop, }; static struct v4l2_subdev_ops ov772x_subdev_ops = { @@ -1114,8 +1166,6 @@ static int ov772x_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); icd->ops = &ov772x_ops; - icd->rect_max.width = MAX_WIDTH; - icd->rect_max.height = MAX_HEIGHT; ret = ov772x_video_probe(icd, client); if (ret) { diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 611e7ff7f..0364b35d5 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -237,6 +237,10 @@ struct pxa_camera_dev { u32 save_cicr[5]; }; +struct pxa_cam { + unsigned long flags; +}; + static const char *pxa_cam_driver_description = "PXA_Camera"; static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ @@ -251,7 +255,7 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); - *size = roundup(icd->rect_current.width * icd->rect_current.height * + *size = roundup(icd->user_width * icd->user_height * ((icd->current_fmt->depth + 7) >> 3), 8); if (0 == *count) @@ -455,12 +459,12 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, buf->inwork = 1; if (buf->fmt != icd->current_fmt || - vb->width != icd->rect_current.width || - vb->height != icd->rect_current.height || + vb->width != icd->user_width || + vb->height != icd->user_height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->rect_current.width; - vb->height = icd->rect_current.height; + vb->width = icd->user_width; + vb->height = icd->user_height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } @@ -851,7 +855,7 @@ static u32 mclk_get_divisor(struct platform_device *pdev, struct pxa_camera_dev *pcdev) { unsigned long mclk = pcdev->mclk; - struct device *dev = pcdev->soc_host.v4l2_dev.dev; + struct device *dev = &pdev->dev; u32 div; unsigned long lcdclk; @@ -1052,57 +1056,17 @@ static int test_platform_param(struct pxa_camera_dev *pcdev, return 0; } -static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +static void pxa_camera_setup_cicr(struct soc_camera_device *icd, + unsigned long flags, __u32 pixfmt) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct pxa_camera_dev *pcdev = ici->priv; - unsigned long dw, bpp, bus_flags, camera_flags, common_flags; + unsigned long dw, bpp; u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0; - int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); - - if (ret < 0) - return ret; - - camera_flags = icd->ops->query_bus_param(icd); - - common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); - if (!common_flags) - return -EINVAL; - - pcdev->channels = 1; - - /* Make choises, based on platform preferences */ - if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && - (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { - if (pcdev->platform_flags & PXA_CAMERA_HSP) - common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; - else - common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; - } - - if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && - (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { - if (pcdev->platform_flags & PXA_CAMERA_VSP) - common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; - else - common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; - } - - if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && - (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { - if (pcdev->platform_flags & PXA_CAMERA_PCP) - common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; - else - common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; - } - - ret = icd->ops->set_bus_param(icd, common_flags); - if (ret < 0) - return ret; /* Datawidth is now guaranteed to be equal to one of the three values. * We fix bit-per-pixel equal to data-width... */ - switch (common_flags & SOCAM_DATAWIDTH_MASK) { + switch (flags & SOCAM_DATAWIDTH_MASK) { case SOCAM_DATAWIDTH_10: dw = 4; bpp = 0x40; @@ -1123,18 +1087,18 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) cicr4 |= CICR4_PCLK_EN; if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN) cicr4 |= CICR4_MCLK_EN; - if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) + if (flags & SOCAM_PCLK_SAMPLE_FALLING) cicr4 |= CICR4_PCP; - if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) + if (flags & SOCAM_HSYNC_ACTIVE_LOW) cicr4 |= CICR4_HSP; - if (common_flags & SOCAM_VSYNC_ACTIVE_LOW) + if (flags & SOCAM_VSYNC_ACTIVE_LOW) cicr4 |= CICR4_VSP; cicr0 = __raw_readl(pcdev->base + CICR0); if (cicr0 & CICR0_ENB) __raw_writel(cicr0 & ~CICR0_ENB, pcdev->base + CICR0); - cicr1 = CICR1_PPL_VAL(icd->rect_current.width - 1) | bpp | dw; + cicr1 = CICR1_PPL_VAL(icd->user_width - 1) | bpp | dw; switch (pixfmt) { case V4L2_PIX_FMT_YUV422P: @@ -1163,7 +1127,7 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) } cicr2 = 0; - cicr3 = CICR3_LPF_VAL(icd->rect_current.height - 1) | + cicr3 = CICR3_LPF_VAL(icd->user_height - 1) | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); cicr4 |= pcdev->mclk_divisor; @@ -1177,6 +1141,59 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) CICR0_SIM_MP : (CICR0_SL_CAP_EN | CICR0_SIM_SP)); cicr0 |= CICR0_DMAEN | CICR0_IRQ_MASK; __raw_writel(cicr0, pcdev->base + CICR0); +} + +static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct pxa_camera_dev *pcdev = ici->priv; + unsigned long bus_flags, camera_flags, common_flags; + int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); + struct pxa_cam *cam = icd->host_priv; + + if (ret < 0) + return ret; + + camera_flags = icd->ops->query_bus_param(icd); + + common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags); + if (!common_flags) + return -EINVAL; + + pcdev->channels = 1; + + /* Make choises, based on platform preferences */ + if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { + if (pcdev->platform_flags & PXA_CAMERA_HSP) + common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && + (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { + if (pcdev->platform_flags & PXA_CAMERA_VSP) + common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; + else + common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; + } + + if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) && + (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) { + if (pcdev->platform_flags & PXA_CAMERA_PCP) + common_flags &= ~SOCAM_PCLK_SAMPLE_RISING; + else + common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; + } + + cam->flags = common_flags; + + ret = icd->ops->set_bus_param(icd, common_flags); + if (ret < 0) + return ret; + + pxa_camera_setup_cicr(icd, common_flags, pixfmt); return 0; } @@ -1242,6 +1259,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, { struct device *dev = icd->dev.parent; int formats = 0, buswidth, ret; + struct pxa_cam *cam; buswidth = required_buswidth(icd->formats + idx); @@ -1252,6 +1270,16 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, if (ret < 0) return 0; + if (!icd->host_priv) { + cam = kzalloc(sizeof(*cam), GFP_KERNEL); + if (!cam) + return -ENOMEM; + + icd->host_priv = cam; + } else { + cam = icd->host_priv; + } + switch (icd->formats[idx].fourcc) { case V4L2_PIX_FMT_UYVY: formats++; @@ -1296,6 +1324,19 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, return formats; } +static void pxa_camera_put_formats(struct soc_camera_device *icd) +{ + kfree(icd->host_priv); + icd->host_priv = NULL; +} + +static int pxa_camera_check_frame(struct v4l2_pix_format *pix) +{ + /* limit to pxa hardware capabilities */ + return pix->height < 32 || pix->height > 2048 || pix->width < 48 || + pix->width > 2048 || (pix->width & 0x01); +} + static int pxa_camera_set_crop(struct soc_camera_device *icd, struct v4l2_crop *a) { @@ -1308,6 +1349,9 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, .master_clock = pcdev->mclk, .pixel_clock_max = pcdev->ciclk / 4, }; + struct v4l2_format f; + struct v4l2_pix_format *pix = &f.fmt.pix, pix_tmp; + struct pxa_cam *cam = icd->host_priv; int ret; /* If PCLK is used to latch data from the sensor, check sense */ @@ -1321,7 +1365,37 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, if (ret < 0) { dev_warn(dev, "Failed to crop to %ux%u@%u:%u\n", rect->width, rect->height, rect->left, rect->top); - } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { + return ret; + } + + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, g_fmt, &f); + if (ret < 0) + return ret; + + pix_tmp = *pix; + if (pxa_camera_check_frame(pix)) { + /* + * Camera cropping produced a frame beyond our capabilities. + * FIXME: just extract a subframe, that we can process. + */ + v4l_bound_align_image(&pix->width, 48, 2048, 1, + &pix->height, 32, 2048, 0, + icd->current_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? + 4 : 0); + ret = v4l2_subdev_call(sd, video, s_fmt, &f); + if (ret < 0) + return ret; + + if (pxa_camera_check_frame(pix)) { + dev_warn(icd->dev.parent, + "Inconsistent state. Use S_FMT to repair\n"); + return -EINVAL; + } + } + + if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { dev_err(dev, "pixel clock %lu set by the camera too high!", @@ -1331,6 +1405,11 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, recalculate_fifo_timeout(pcdev, sense.pixel_clock); } + icd->user_width = pix->width; + icd->user_height = pix->height; + + pxa_camera_setup_cicr(icd, cam->flags, icd->current_fmt->fourcc); + return ret; } @@ -1371,6 +1450,11 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, if (ret < 0) { dev_warn(dev, "Failed to configure for format %x\n", pix->pixelformat); + } else if (pxa_camera_check_frame(pix)) { + dev_warn(dev, + "Camera driver produced an unsupported frame %dx%d\n", + pix->width, pix->height); + ret = -EINVAL; } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { if (sense.pixel_clock > sense.pixel_clock_max) { dev_err(dev, @@ -1414,7 +1498,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, */ v4l_bound_align_image(&pix->width, 48, 2048, 1, &pix->height, 32, 2048, 0, - xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0); + pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0); pix->bytesperline = pix->width * DIV_ROUND_UP(xlate->host_fmt->depth, 8); @@ -1424,7 +1508,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, pix->pixelformat = xlate->cam_fmt->fourcc; /* limit to sensor capabilities */ ret = v4l2_subdev_call(sd, video, try_fmt, f); - pix->pixelformat = xlate->host_fmt->fourcc; + pix->pixelformat = pixfmt; field = pix->field; @@ -1537,6 +1621,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .resume = pxa_camera_resume, .set_crop = pxa_camera_set_crop, .get_formats = pxa_camera_get_formats, + .put_formats = pxa_camera_put_formats, .set_fmt = pxa_camera_set_fmt, .try_fmt = pxa_camera_try_fmt, .init_videobuf = pxa_camera_init_videobuf, diff --git a/linux/drivers/media/video/sh_mobile_ceu_camera.c b/linux/drivers/media/video/sh_mobile_ceu_camera.c index 142bdbc6f..d35f66d8a 100644 --- a/linux/drivers/media/video/sh_mobile_ceu_camera.c +++ b/linux/drivers/media/video/sh_mobile_ceu_camera.c @@ -75,6 +75,13 @@ #define CDBYR2 0x98 /* Capture data bottom-field address Y register 2 */ #define CDBCR2 0x9c /* Capture data bottom-field address C register 2 */ +#undef DEBUG_GEOMETRY +#ifdef DEBUG_GEOMETRY +#define dev_geo dev_info +#else +#define dev_geo dev_dbg +#endif + /* per video frame buffer */ struct sh_mobile_ceu_buffer { struct videobuf_buffer vb; /* v4l buffer must be first */ @@ -105,8 +112,9 @@ struct sh_mobile_ceu_dev { }; struct sh_mobile_ceu_cam { - struct v4l2_rect camera_rect; - struct v4l2_rect camera_max; + struct v4l2_rect ceu_rect; + unsigned int cam_width; + unsigned int cam_height; const struct soc_camera_data_format *extra_fmt; const struct soc_camera_data_format *camera_fmt; }; @@ -158,7 +166,7 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, struct sh_mobile_ceu_dev *pcdev = ici->priv; int bytes_per_pixel = (icd->current_fmt->depth + 7) >> 3; - *size = PAGE_ALIGN(icd->rect_current.width * icd->rect_current.height * + *size = PAGE_ALIGN(icd->user_width * icd->user_height * bytes_per_pixel); if (0 == *count) @@ -178,8 +186,9 @@ static void free_buffer(struct videobuf_queue *vq, struct sh_mobile_ceu_buffer *buf) { struct soc_camera_device *icd = vq->priv_data; + struct device *dev = icd->dev.parent; - dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, + dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, &buf->vb, buf->vb.baddr, buf->vb.bsize); if (in_interrupt()) @@ -187,7 +196,7 @@ static void free_buffer(struct videobuf_queue *vq, videobuf_waiton(&buf->vb, 0, 0); videobuf_dma_contig_free(vq, &buf->vb); - dev_dbg(icd->dev.parent, "%s freed\n", __func__); + dev_dbg(dev, "%s freed\n", __func__); buf->vb.state = VIDEOBUF_NEEDS_INIT; } @@ -218,7 +227,7 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) phys_addr_top = videobuf_to_dma_contig(pcdev->active); ceu_write(pcdev, CDAYR, phys_addr_top); if (pcdev->is_interlaced) { - phys_addr_bottom = phys_addr_top + icd->rect_current.width; + phys_addr_bottom = phys_addr_top + icd->user_width; ceu_write(pcdev, CDBYR, phys_addr_bottom); } @@ -227,12 +236,12 @@ static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - phys_addr_top += icd->rect_current.width * - icd->rect_current.height; + phys_addr_top += icd->user_width * + icd->user_height; ceu_write(pcdev, CDACR, phys_addr_top); if (pcdev->is_interlaced) { phys_addr_bottom = phys_addr_top + - icd->rect_current.width; + icd->user_width; ceu_write(pcdev, CDBCR, phys_addr_bottom); } } @@ -266,12 +275,12 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, BUG_ON(NULL == icd->current_fmt); if (buf->fmt != icd->current_fmt || - vb->width != icd->rect_current.width || - vb->height != icd->rect_current.height || + vb->width != icd->user_width || + vb->height != icd->user_height || vb->field != field) { buf->fmt = icd->current_fmt; - vb->width = icd->rect_current.width; - vb->height = icd->rect_current.height; + vb->width = icd->user_width; + vb->height = icd->user_height; vb->field = field; vb->state = VIDEOBUF_NEEDS_INIT; } @@ -453,18 +462,6 @@ static unsigned int size_dst(unsigned int src, unsigned int scale) mant_pre * 4096 / scale + 1; } -static unsigned int size_src(unsigned int dst, unsigned int scale) -{ - unsigned int mant_pre = scale >> 12, tmp; - if (!dst || !scale) - return dst; - for (tmp = ((dst - 1) * scale + 2048 * mant_pre) / 4096 + 1; - size_dst(tmp, scale) < dst; - tmp++) - ; - return tmp; -} - static u16 calc_scale(unsigned int src, unsigned int *dst) { u16 scale; @@ -484,65 +481,46 @@ static u16 calc_scale(unsigned int src, unsigned int *dst) /* rect is guaranteed to not exceed the scaled camera rectangle */ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, - struct v4l2_rect *rect) + unsigned int out_width, + unsigned int out_height) { struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_rect *rect = &cam->ceu_rect; struct sh_mobile_ceu_dev *pcdev = ici->priv; - int width, height, cfszr_width, cdwdr_width, in_width, in_height; - unsigned int left_offset, top_offset, left, top; - unsigned int hscale = pcdev->cflcr & 0xffff; - unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; + unsigned int height, width, cdwdr_width, in_width, in_height; + unsigned int left_offset, top_offset; u32 camor; - /* Switch to the camera scale */ - left = size_src(rect->left, hscale); - top = size_src(rect->top, vscale); - - dev_dbg(icd->dev.parent, "Left %u * 0x%x = %u, top %u * 0x%x = %u\n", - rect->left, hscale, left, rect->top, vscale, top); - - if (left > cam->camera_rect.left) { - left_offset = left - cam->camera_rect.left; - } else { - left_offset = 0; - left = cam->camera_rect.left; - } - - if (top > cam->camera_rect.top) { - top_offset = top - cam->camera_rect.top; - } else { - top_offset = 0; - top = cam->camera_rect.top; - } + dev_dbg(icd->dev.parent, "Crop %ux%u@%u:%u\n", + rect->width, rect->height, rect->left, rect->top); - dev_dbg(icd->dev.parent, "New left %u, top %u, offsets %u:%u\n", - rect->left, rect->top, left_offset, top_offset); + left_offset = rect->left; + top_offset = rect->top; if (pcdev->image_mode) { - width = rect->width; - in_width = cam->camera_rect.width; + in_width = rect->width; if (!pcdev->is_16bit) { - width *= 2; in_width *= 2; left_offset *= 2; } - cfszr_width = cdwdr_width = rect->width; + width = cdwdr_width = out_width; } else { unsigned int w_factor = (icd->current_fmt->depth + 7) >> 3; + + width = out_width * w_factor / 2; + if (!pcdev->is_16bit) w_factor *= 2; - width = rect->width * w_factor / 2; - in_width = cam->camera_rect.width * w_factor / 2; + in_width = rect->width * w_factor / 2; left_offset = left_offset * w_factor / 2; - cfszr_width = pcdev->is_16bit ? width : width / 2; - cdwdr_width = pcdev->is_16bit ? width * 2 : width; + cdwdr_width = width * 2; } - height = rect->height; - in_height = cam->camera_rect.height; + height = out_height; + in_height = rect->height; if (pcdev->is_interlaced) { height /= 2; in_height /= 2; @@ -550,10 +528,17 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, cdwdr_width *= 2; } + /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */ camor = left_offset | (top_offset << 16); + + dev_geo(icd->dev.parent, + "CAMOR 0x%x, CAPWR 0x%x, CFSZR 0x%x, CDWDR 0x%x\n", camor, + (in_height << 16) | in_width, (height << 16) | width, + cdwdr_width); + ceu_write(pcdev, CAMOR, camor); ceu_write(pcdev, CAPWR, (in_height << 16) | in_width); - ceu_write(pcdev, CFSZR, (height << 16) | cfszr_width); + ceu_write(pcdev, CFSZR, (height << 16) | width); ceu_write(pcdev, CDWDR, cdwdr_width); } @@ -665,8 +650,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CAPCR, 0x00300000); ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0); + sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height); mdelay(1); - sh_mobile_ceu_set_rect(icd, &icd->rect_current); ceu_write(pcdev, CFLCR, pcdev->cflcr); @@ -689,11 +674,10 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, ceu_write(pcdev, CDOCR, value); ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ - dev_dbg(icd->dev.parent, "S_FMT successful for %c%c%c%c %ux%u@%u:%u\n", + dev_dbg(icd->dev.parent, "S_FMT successful for %c%c%c%c %ux%u\n", pixfmt & 0xff, (pixfmt >> 8) & 0xff, (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff, - icd->rect_current.width, icd->rect_current.height, - icd->rect_current.left, icd->rect_current.top); + icd->user_width, icd->user_height); capture_restore(pcdev, capsr); @@ -746,6 +730,7 @@ static const struct soc_camera_data_format sh_mobile_ceu_formats[] = { static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, struct soc_camera_format_xlate *xlate) { + struct device *dev = icd->dev.parent; int ret, k, n; int formats = 0; struct sh_mobile_ceu_cam *cam; @@ -760,7 +745,6 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, return -ENOMEM; icd->host_priv = cam; - cam->camera_max = icd->rect_max; } else { cam = icd->host_priv; } @@ -795,8 +779,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(icd->dev.parent, - "Providing format %s using %s\n", + dev_dbg(dev, "Providing format %s using %s\n", sh_mobile_ceu_formats[k].name, icd->formats[idx].name); } @@ -809,7 +792,7 @@ add_single_format: xlate->cam_fmt = icd->formats + idx; xlate->buswidth = icd->formats[idx].depth; xlate++; - dev_dbg(icd->dev.parent, + dev_dbg(dev, "Providing format %s in pass-through mode\n", icd->formats[idx].name); } @@ -838,176 +821,487 @@ static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2) r1->top + r1->height < r2->top + r2->height; } +static unsigned int scale_down(unsigned int size, unsigned int scale) +{ + return (size * 4096 + scale / 2) / scale; +} + +static unsigned int scale_up(unsigned int size, unsigned int scale) +{ + return (size * scale + 2048) / 4096; +} + +static unsigned int calc_generic_scale(unsigned int input, unsigned int output) +{ + return (input * 4096 + output / 2) / output; +} + +static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) +{ + struct v4l2_crop crop; + struct v4l2_cropcap cap; + int ret; + + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, g_crop, &crop); + if (!ret) { + *rect = crop.c; + return ret; + } + + /* Camera driver doesn't support .g_crop(), assume default rectangle */ + cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (ret < 0) + return ret; + + *rect = cap.defrect; + + return ret; +} + /* - * CEU can scale and crop, but we don't want to waste bandwidth and kill the - * framerate by always requesting the maximum image from the client. For - * cropping we also have to take care of the current scale. The common for both - * scaling and cropping approach is: + * The common for both scaling and cropping iterative approach is: * 1. try if the client can produce exactly what requested by the user * 2. if (1) failed, try to double the client image until we get one big enough * 3. if (2) failed, try to request the maximum image */ -static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, - struct v4l2_crop *a) +static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, + struct v4l2_crop *cam_crop) { - struct v4l2_rect *rect = &a->c; - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct sh_mobile_ceu_dev *pcdev = ici->priv; - struct v4l2_crop cam_crop; - struct v4l2_rect *cam_rect = &cam_crop.c, target, cam_max; - struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - unsigned int hscale = pcdev->cflcr & 0xffff; - unsigned int vscale = (pcdev->cflcr >> 16) & 0xffff; - unsigned short width, height; - u32 capsr; + struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; + struct device *dev = sd->v4l2_dev->dev; + struct v4l2_cropcap cap; int ret; + unsigned int width, height; - /* Scale back up into client units */ - cam_rect->left = size_src(rect->left, hscale); - cam_rect->width = size_src(rect->width, hscale); - cam_rect->top = size_src(rect->top, vscale); - cam_rect->height = size_src(rect->height, vscale); - - target = *cam_rect; + v4l2_subdev_call(sd, video, s_crop, crop); + ret = client_g_rect(sd, cam_rect); + if (ret < 0) + return ret; - capsr = capture_save_reset(pcdev); - dev_dbg(icd->dev.parent, "CAPSR 0x%x, CFLCR 0x%x\n", - capsr, pcdev->cflcr); - - /* First attempt - see if the client can deliver a perfect result */ - ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); - if (!ret && !memcmp(&target, &cam_rect, sizeof(target))) { - dev_dbg(icd->dev.parent, - "Camera S_CROP successful for %ux%u@%u:%u\n", - cam_rect->width, cam_rect->height, - cam_rect->left, cam_rect->top); - goto ceu_set_rect; + /* + * Now cam_crop contains the current camera input rectangle, and it must + * be within camera cropcap bounds + */ + if (!memcmp(rect, cam_rect, sizeof(*rect))) { + /* Even if camera S_CROP failed, but camera rectangle matches */ + dev_dbg(dev, "Camera S_CROP successful for %ux%u@%u:%u\n", + rect->width, rect->height, rect->left, rect->top); + return 0; } - /* Try to fix cropping, that camera hasn't managed to do */ - dev_dbg(icd->dev.parent, "Fix camera S_CROP %d for %ux%u@%u:%u" - " to %ux%u@%u:%u\n", - ret, cam_rect->width, cam_rect->height, + /* Try to fix cropping, that camera hasn't managed to set */ + dev_geo(dev, "Fix camera S_CROP for %ux%u@%u:%u to %ux%u@%u:%u\n", + cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, - target.width, target.height, target.left, target.top); + rect->width, rect->height, rect->left, rect->top); + + /* We need sensor maximum rectangle */ + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (ret < 0) + return ret; + + soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2, + cap.bounds.width); + soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4, + cap.bounds.height); /* * Popular special case - some cameras can only handle fixed sizes like * QVGA, VGA,... Take care to avoid infinite loop. */ - width = max(cam_rect->width, 1); - height = max(cam_rect->height, 1); - cam_max.width = size_src(icd->rect_max.width, hscale); - cam_max.left = size_src(icd->rect_max.left, hscale); - cam_max.height = size_src(icd->rect_max.height, vscale); - cam_max.top = size_src(icd->rect_max.top, vscale); - while (!ret && (is_smaller(cam_rect, &target) || - is_inside(cam_rect, &target)) && - cam_max.width >= width && cam_max.height >= height) { + width = max(cam_rect->width, 2); + height = max(cam_rect->height, 2); + + while (!ret && (is_smaller(cam_rect, rect) || + is_inside(cam_rect, rect)) && + (cap.bounds.width > width || cap.bounds.height > height)) { width *= 2; height *= 2; + cam_rect->width = width; cam_rect->height = height; - /* We do not know what the camera is capable of, play safe */ - if (cam_rect->left > target.left) - cam_rect->left = cam_max.left; + /* + * We do not know what capabilities the camera has to set up + * left and top borders. We could try to be smarter in iterating + * them, e.g., if camera current left is to the right of the + * target left, set it to the middle point between the current + * left and minimum left. But that would add too much + * complexity: we would have to iterate each border separately. + */ + if (cam_rect->left > rect->left) + cam_rect->left = cap.bounds.left; - if (cam_rect->left + cam_rect->width < target.left + target.width) - cam_rect->width = target.left + target.width - + if (cam_rect->left + cam_rect->width < rect->left + rect->width) + cam_rect->width = rect->left + rect->width - cam_rect->left; - if (cam_rect->top > target.top) - cam_rect->top = cam_max.top; + if (cam_rect->top > rect->top) + cam_rect->top = cap.bounds.top; - if (cam_rect->top + cam_rect->height < target.top + target.height) - cam_rect->height = target.top + target.height - + if (cam_rect->top + cam_rect->height < rect->top + rect->height) + cam_rect->height = rect->top + rect->height - cam_rect->top; - if (cam_rect->width + cam_rect->left > - cam_max.width + cam_max.left) - cam_rect->left = max(cam_max.width + cam_max.left - - cam_rect->width, cam_max.left); - - if (cam_rect->height + cam_rect->top > - cam_max.height + cam_max.top) - cam_rect->top = max(cam_max.height + cam_max.top - - cam_rect->height, cam_max.top); - - ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); - dev_dbg(icd->dev.parent, "Camera S_CROP %d for %ux%u@%u:%u\n", - ret, cam_rect->width, cam_rect->height, + v4l2_subdev_call(sd, video, s_crop, cam_crop); + ret = client_g_rect(sd, cam_rect); + dev_geo(dev, "Camera S_CROP %d for %ux%u@%u:%u\n", ret, + cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); } - /* - * If the camera failed to configure cropping, it should not modify the - * rectangle - */ - if ((ret < 0 && (is_smaller(&icd->rect_current, rect) || - is_inside(&icd->rect_current, rect))) || - is_smaller(cam_rect, &target) || is_inside(cam_rect, &target)) { + /* S_CROP must not modify the rectangle */ + if (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) { /* * The camera failed to configure a suitable cropping, * we cannot use the current rectangle, set to max */ - *cam_rect = cam_max; - ret = v4l2_subdev_call(sd, video, s_crop, &cam_crop); - dev_dbg(icd->dev.parent, - "Camera S_CROP %d for max %ux%u@%u:%u\n", - ret, cam_rect->width, cam_rect->height, + *cam_rect = cap.bounds; + v4l2_subdev_call(sd, video, s_crop, cam_crop); + ret = client_g_rect(sd, cam_rect); + dev_geo(dev, "Camera S_CROP %d for max %ux%u@%u:%u\n", ret, + cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); - if (ret < 0 && ret != -ENOIOCTLCMD) - /* All failed, hopefully resume current capture */ - goto resume_capture; - - /* Finally, adjust the target rectangle */ - if (target.width > cam_rect->width) - target.width = cam_rect->width; - if (target.height > cam_rect->height) - target.height = cam_rect->height; - if (target.left + target.width > cam_rect->left + cam_rect->width) - target.left = cam_rect->left + cam_rect->width - - target.width; - if (target.top + target.height > cam_rect->top + cam_rect->height) - target.top = cam_rect->top + cam_rect->height - - target.height; } - /* We now have a rectangle, larger than requested, let's crop */ + return ret; +} + +static int get_camera_scales(struct v4l2_subdev *sd, struct v4l2_rect *rect, + unsigned int *scale_h, unsigned int *scale_v) +{ + struct v4l2_format f; + int ret; + + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, g_fmt, &f); + if (ret < 0) + return ret; + + *scale_h = calc_generic_scale(rect->width, f.fmt.pix.width); + *scale_v = calc_generic_scale(rect->height, f.fmt.pix.height); + + return 0; +} + +static int get_camera_subwin(struct soc_camera_device *icd, + struct v4l2_rect *cam_subrect, + unsigned int cam_hscale, unsigned int cam_vscale) +{ + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_rect *ceu_rect = &cam->ceu_rect; + + if (!ceu_rect->width) { + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->dev.parent; + struct v4l2_format f; + struct v4l2_pix_format *pix = &f.fmt.pix; + int ret; + /* First time */ + + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, g_fmt, &f); + if (ret < 0) + return ret; + + dev_geo(dev, "camera fmt %ux%u\n", pix->width, pix->height); + + if (pix->width > 2560) { + ceu_rect->width = 2560; + ceu_rect->left = (pix->width - 2560) / 2; + } else { + ceu_rect->width = pix->width; + ceu_rect->left = 0; + } + + if (pix->height > 1920) { + ceu_rect->height = 1920; + ceu_rect->top = (pix->height - 1920) / 2; + } else { + ceu_rect->height = pix->height; + ceu_rect->top = 0; + } + + dev_geo(dev, "initialised CEU rect %ux%u@%u:%u\n", + ceu_rect->width, ceu_rect->height, + ceu_rect->left, ceu_rect->top); + } + + cam_subrect->width = scale_up(ceu_rect->width, cam_hscale); + cam_subrect->left = scale_up(ceu_rect->left, cam_hscale); + cam_subrect->height = scale_up(ceu_rect->height, cam_vscale); + cam_subrect->top = scale_up(ceu_rect->top, cam_vscale); + + return 0; +} + +static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f, + bool ceu_can_scale) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->dev.parent; + struct v4l2_pix_format *pix = &f->fmt.pix; + unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h; + unsigned int max_width, max_height; + struct v4l2_cropcap cap; + int ret; + + cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (ret < 0) + return ret; + + max_width = min(cap.bounds.width, 2560); + max_height = min(cap.bounds.height, 1920); + + ret = v4l2_subdev_call(sd, video, s_fmt, f); + if (ret < 0) + return ret; + + dev_geo(dev, "camera scaled to %ux%u\n", pix->width, pix->height); + + if ((width == pix->width && height == pix->height) || !ceu_can_scale) + return 0; + + /* Camera set a format, but geometry is not precise, try to improve */ + tmp_w = pix->width; + tmp_h = pix->height; + + /* width <= max_width && height <= max_height - guaranteed by try_fmt */ + while ((width > tmp_w || height > tmp_h) && + tmp_w < max_width && tmp_h < max_height) { + tmp_w = min(2 * tmp_w, max_width); + tmp_h = min(2 * tmp_h, max_height); + pix->width = tmp_w; + pix->height = tmp_h; + ret = v4l2_subdev_call(sd, video, s_fmt, f); + dev_geo(dev, "Camera scaled to %ux%u\n", + pix->width, pix->height); + if (ret < 0) { + /* This shouldn't happen */ + dev_err(dev, "Client failed to set format: %d\n", ret); + return ret; + } + } + + return 0; +} + +/** + * @rect - camera cropped rectangle + * @sub_rect - CEU cropped rectangle, mapped back to camera input area + * @ceu_rect - on output calculated CEU crop rectangle + */ +static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, + struct v4l2_rect *sub_rect, struct v4l2_rect *ceu_rect, + struct v4l2_format *f, bool ceu_can_scale) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct device *dev = icd->dev.parent; + struct v4l2_format f_tmp = *f; + struct v4l2_pix_format *pix_tmp = &f_tmp.fmt.pix; + unsigned int scale_h, scale_v; + int ret; + + /* 5. Apply iterative camera S_FMT for camera user window. */ + ret = client_s_fmt(icd, &f_tmp, ceu_can_scale); + if (ret < 0) + return ret; + + dev_geo(dev, "5: camera scaled to %ux%u\n", + pix_tmp->width, pix_tmp->height); + + /* 6. Retrieve camera output window (g_fmt) */ + + /* unneeded - it is already in "f_tmp" */ + + /* 7. Calculate new camera scales. */ + ret = get_camera_scales(sd, rect, &scale_h, &scale_v); + if (ret < 0) + return ret; + + dev_geo(dev, "7: camera scales %u:%u\n", scale_h, scale_v); + + cam->cam_width = pix_tmp->width; + cam->cam_height = pix_tmp->height; + f->fmt.pix.width = pix_tmp->width; + f->fmt.pix.height = pix_tmp->height; /* - * We have to preserve camera rectangle between close() / open(), - * because soc-camera core calls .set_fmt() on each first open() with - * last before last close() _user_ rectangle, which can be different - * from camera rectangle. + * 8. Calculate new CEU crop - apply camera scales to previously + * calculated "effective" crop. */ - dev_dbg(icd->dev.parent, - "SH S_CROP from %ux%u@%u:%u to %ux%u@%u:%u, scale to %ux%u@%u:%u\n", - cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top, - target.width, target.height, target.left, target.top, - rect->width, rect->height, rect->left, rect->top); + ceu_rect->left = scale_down(sub_rect->left, scale_h); + ceu_rect->width = scale_down(sub_rect->width, scale_h); + ceu_rect->top = scale_down(sub_rect->top, scale_v); + ceu_rect->height = scale_down(sub_rect->height, scale_v); + + dev_geo(dev, "8: new CEU rect %ux%u@%u:%u\n", + ceu_rect->width, ceu_rect->height, + ceu_rect->left, ceu_rect->top); + + return 0; +} + +/* Get combined scales */ +static int get_scales(struct soc_camera_device *icd, + unsigned int *scale_h, unsigned int *scale_v) +{ + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct v4l2_crop cam_crop; + unsigned int width_in, height_in; + int ret; - ret = 0; + cam_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -ceu_set_rect: - cam->camera_rect = *cam_rect; + ret = client_g_rect(sd, &cam_crop.c); + if (ret < 0) + return ret; - rect->width = size_dst(target.width, hscale); - rect->left = size_dst(target.left, hscale); - rect->height = size_dst(target.height, vscale); - rect->top = size_dst(target.top, vscale); + ret = get_camera_scales(sd, &cam_crop.c, scale_h, scale_v); + if (ret < 0) + return ret; - sh_mobile_ceu_set_rect(icd, rect); + width_in = scale_up(cam->ceu_rect.width, *scale_h); + height_in = scale_up(cam->ceu_rect.height, *scale_v); -resume_capture: - /* Set CAMOR, CAPWR, CFSZR, take care of CDWDR */ + *scale_h = calc_generic_scale(cam->ceu_rect.width, icd->user_width); + *scale_v = calc_generic_scale(cam->ceu_rect.height, icd->user_height); + + return 0; +} + +/* + * CEU can scale and crop, but we don't want to waste bandwidth and kill the + * framerate by always requesting the maximum image from the client. See + * Documentation/video4linux/sh_mobile_camera_ceu.txt for a description of + * scaling and cropping algorithms and for the meaning of referenced here steps. + */ +static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, + struct v4l2_crop *a) +{ + struct v4l2_rect *rect = &a->c; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + struct sh_mobile_ceu_dev *pcdev = ici->priv; + struct v4l2_crop cam_crop; + struct sh_mobile_ceu_cam *cam = icd->host_priv; + struct v4l2_rect *cam_rect = &cam_crop.c, *ceu_rect = &cam->ceu_rect; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->dev.parent; + struct v4l2_format f; + struct v4l2_pix_format *pix = &f.fmt.pix; + unsigned int scale_comb_h, scale_comb_v, scale_ceu_h, scale_ceu_v, + out_width, out_height; + u32 capsr, cflcr; + int ret; + + /* 1. Calculate current combined scales. */ + ret = get_scales(icd, &scale_comb_h, &scale_comb_v); + if (ret < 0) + return ret; + + dev_geo(dev, "1: combined scales %u:%u\n", scale_comb_h, scale_comb_v); + + /* 2. Apply iterative camera S_CROP for new input window. */ + ret = client_s_crop(sd, a, &cam_crop); + if (ret < 0) + return ret; + + dev_geo(dev, "2: camera cropped to %ux%u@%u:%u\n", + cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); + + /* On success cam_crop contains current camera crop */ + + /* + * 3. If old combined scales applied to new crop produce an impossible + * user window, adjust scales to produce nearest possible window. + */ + out_width = scale_down(rect->width, scale_comb_h); + out_height = scale_down(rect->height, scale_comb_v); + + if (out_width > 2560) + out_width = 2560; + else if (out_width < 2) + out_width = 2; + + if (out_height > 1920) + out_height = 1920; + else if (out_height < 4) + out_height = 4; + + dev_geo(dev, "3: Adjusted output %ux%u\n", out_width, out_height); + + /* 4. Use G_CROP to retrieve actual input window: already in cam_crop */ + + /* + * 5. Using actual input window and calculated combined scales calculate + * camera target output window. + */ + pix->width = scale_down(cam_rect->width, scale_comb_h); + pix->height = scale_down(cam_rect->height, scale_comb_v); + + dev_geo(dev, "5: camera target %ux%u\n", pix->width, pix->height); + + /* 6. - 9. */ + pix->pixelformat = cam->camera_fmt->fourcc; + pix->colorspace = cam->camera_fmt->colorspace; + + capsr = capture_save_reset(pcdev); + dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); + + /* Make relative to camera rectangle */ + rect->left -= cam_rect->left; + rect->top -= cam_rect->top; + + f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = client_scale(icd, cam_rect, rect, ceu_rect, &f, + pcdev->image_mode && !pcdev->is_interlaced); + + dev_geo(dev, "6-9: %d\n", ret); + + /* 10. Use CEU cropping to crop to the new window. */ + sh_mobile_ceu_set_rect(icd, out_width, out_height); + + dev_geo(dev, "10: CEU cropped to %ux%u@%u:%u\n", + ceu_rect->width, ceu_rect->height, + ceu_rect->left, ceu_rect->top); + + /* + * 11. Calculate CEU scales from camera scales from results of (10) and + * user window from (3) + */ + scale_ceu_h = calc_scale(ceu_rect->width, &out_width); + scale_ceu_v = calc_scale(ceu_rect->height, &out_height); + + dev_geo(dev, "11: CEU scales %u:%u\n", scale_ceu_h, scale_ceu_v); + + /* 12. Apply CEU scales. */ + cflcr = scale_ceu_h | (scale_ceu_v << 16); + if (cflcr != pcdev->cflcr) { + pcdev->cflcr = cflcr; + ceu_write(pcdev, CFLCR, cflcr); + } + + /* Restore capture */ if (pcdev->active) capsr |= 1; capture_restore(pcdev, capsr); + icd->user_width = out_width; + icd->user_height = out_height; + /* Even if only camera cropping succeeded */ return ret; } @@ -1020,121 +1314,137 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_format cam_f = *f; + struct v4l2_pix_format *cam_pix = &cam_f.fmt.pix; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->dev.parent; __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; - unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h; - u16 vscale, hscale; - int ret, is_interlaced; + struct v4l2_crop cam_crop; + struct v4l2_rect *cam_rect = &cam_crop.c, cam_subrect, ceu_rect; + unsigned int scale_cam_h, scale_cam_v; + u16 scale_v, scale_h; + int ret; + bool is_interlaced, image_mode; switch (pix->field) { case V4L2_FIELD_INTERLACED: - is_interlaced = 1; + is_interlaced = true; break; case V4L2_FIELD_ANY: default: pix->field = V4L2_FIELD_NONE; /* fall-through */ case V4L2_FIELD_NONE: - is_interlaced = 0; + is_interlaced = false; break; } xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); if (!xlate) { - dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); + dev_warn(dev, "Format %x not found\n", pixfmt); return -EINVAL; } - pix->pixelformat = xlate->cam_fmt->fourcc; - ret = v4l2_subdev_call(sd, video, s_fmt, f); - pix->pixelformat = pixfmt; - dev_dbg(icd->dev.parent, - "Camera %d fmt %ux%u, requested %ux%u, max %ux%u\n", - ret, pix->width, pix->height, width, height, - icd->rect_max.width, icd->rect_max.height); + /* 1. Calculate current camera scales. */ + cam_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = client_g_rect(sd, cam_rect); + if (ret < 0) + return ret; + + ret = get_camera_scales(sd, cam_rect, &scale_cam_h, &scale_cam_v); + if (ret < 0) + return ret; + + dev_geo(dev, "1: camera scales %u:%u\n", scale_cam_h, scale_cam_v); + + /* + * 2. Calculate "effective" input crop (sensor subwindow) - CEU crop + * scaled back at current camera scales onto input window. + */ + ret = get_camera_subwin(icd, &cam_subrect, scale_cam_h, scale_cam_v); if (ret < 0) return ret; + dev_geo(dev, "2: subwin %ux%u@%u:%u\n", + cam_subrect.width, cam_subrect.height, + cam_subrect.left, cam_subrect.top); + + /* + * 3. Calculate new combined scales from "effective" input window to + * requested user window. + */ + scale_h = calc_generic_scale(cam_subrect.width, pix->width); + scale_v = calc_generic_scale(cam_subrect.height, pix->height); + + dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); + + /* + * 4. Calculate camera output window by applying combined scales to real + * input window. + */ + cam_pix->width = scale_down(cam_rect->width, scale_h); + cam_pix->height = scale_down(cam_rect->height, scale_v); + cam_pix->pixelformat = xlate->cam_fmt->fourcc; + switch (pixfmt) { case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: - pcdev->image_mode = 1; + image_mode = true; break; default: - pcdev->image_mode = 0; + image_mode = false; } - if ((abs(width - pix->width) < 4 && abs(height - pix->height) < 4) || - !pcdev->image_mode || is_interlaced) { - hscale = 0; - vscale = 0; - goto out; - } + dev_geo(dev, "4: camera output %ux%u\n", + cam_pix->width, cam_pix->height); - /* Camera set a format, but geometry is not precise, try to improve */ - /* - * FIXME: when soc-camera is converted to implement traditional S_FMT - * and S_CROP semantics, replace CEU limits with camera maxima - */ - tmp_w = pix->width; - tmp_h = pix->height; - while ((width > tmp_w || height > tmp_h) && - tmp_w < 2560 && tmp_h < 1920) { - tmp_w = min(2 * tmp_w, (__u32)2560); - tmp_h = min(2 * tmp_h, (__u32)1920); - pix->width = tmp_w; - pix->height = tmp_h; - pix->pixelformat = xlate->cam_fmt->fourcc; - ret = v4l2_subdev_call(sd, video, s_fmt, f); - pix->pixelformat = pixfmt; - dev_dbg(icd->dev.parent, "Camera scaled to %ux%u\n", - pix->width, pix->height); - if (ret < 0) { - /* This shouldn't happen */ - dev_err(icd->dev.parent, - "Client failed to set format: %d\n", ret); - return ret; - } - } + /* 5. - 9. */ + ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &cam_f, + image_mode && !is_interlaced); + + dev_geo(dev, "5-9: client scale %d\n", ret); + + /* Done with the camera. Now see if we can improve the result */ + + dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", + ret, cam_pix->width, cam_pix->height, pix->width, pix->height); + if (ret < 0) + return ret; + + /* 10. Use CEU scaling to scale to the requested user window. */ /* We cannot scale up */ - if (width > pix->width) - width = pix->width; + if (pix->width > cam_pix->width) + pix->width = cam_pix->width; + if (pix->width > ceu_rect.width) + pix->width = ceu_rect.width; - if (height > pix->height) - height = pix->height; + if (pix->height > cam_pix->height) + pix->height = cam_pix->height; + if (pix->height > ceu_rect.height) + pix->height = ceu_rect.height; /* Let's rock: scale pix->{width x height} down to width x height */ - hscale = calc_scale(pix->width, &width); - vscale = calc_scale(pix->height, &height); + scale_h = calc_scale(ceu_rect.width, &pix->width); + scale_v = calc_scale(ceu_rect.height, &pix->height); - dev_dbg(icd->dev.parent, "W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", - pix->width, hscale, width, pix->height, vscale, height); + dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", + ceu_rect.width, scale_h, pix->width, + ceu_rect.height, scale_v, pix->height); -out: - pcdev->cflcr = hscale | (vscale << 16); + pcdev->cflcr = scale_h | (scale_v << 16); icd->buswidth = xlate->buswidth; icd->current_fmt = xlate->host_fmt; cam->camera_fmt = xlate->cam_fmt; - cam->camera_rect.width = pix->width; - cam->camera_rect.height = pix->height; - - icd->rect_max.left = size_dst(cam->camera_max.left, hscale); - icd->rect_max.width = size_dst(cam->camera_max.width, hscale); - icd->rect_max.top = size_dst(cam->camera_max.top, vscale); - icd->rect_max.height = size_dst(cam->camera_max.height, vscale); - - icd->rect_current.left = icd->rect_max.left; - icd->rect_current.top = icd->rect_max.top; + cam->ceu_rect = ceu_rect; pcdev->is_interlaced = is_interlaced; - - pix->width = width; - pix->height = height; + pcdev->image_mode = image_mode; return 0; } diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 6145846f7..2290118fb 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -279,6 +279,9 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd) icd->user_formats = NULL; } +#define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \ + ((x) >> 24) & 0xff + /* Called with .vb_lock held */ static int soc_camera_set_fmt(struct soc_camera_file *icf, struct v4l2_format *f) @@ -288,6 +291,9 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, struct v4l2_pix_format *pix = &f->fmt.pix; int ret; + dev_dbg(&icd->dev, "S_FMT(%c%c%c%c, %ux%u)\n", + pixfmtstr(pix->pixelformat), pix->width, pix->height); + /* We always call try_fmt() before set_fmt() or set_crop() */ ret = ici->ops->try_fmt(icd, f); if (ret < 0) @@ -303,17 +309,17 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, return -EINVAL; } - icd->rect_current.width = pix->width; - icd->rect_current.height = pix->height; - icf->vb_vidq.field = - icd->field = pix->field; + icd->user_width = pix->width; + icd->user_height = pix->height; + icf->vb_vidq.field = + icd->field = pix->field; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", f->type); dev_dbg(&icd->dev, "set width: %d height: %d\n", - icd->rect_current.width, icd->rect_current.height); + icd->user_width, icd->user_height); /* set physical bus parameters */ return ici->ops->set_bus_param(icd, pix->pixelformat); @@ -356,8 +362,8 @@ static int soc_camera_open(struct file *file) struct v4l2_format f = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .fmt.pix = { - .width = icd->rect_current.width, - .height = icd->rect_current.height, + .width = icd->user_width, + .height = icd->user_height, .field = icd->field, .pixelformat = icd->current_fmt->fourcc, .colorspace = icd->current_fmt->colorspace, @@ -558,8 +564,8 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, WARN_ON(priv != file->private_data); - pix->width = icd->rect_current.width; - pix->height = icd->rect_current.height; + pix->width = icd->user_width; + pix->height = icd->user_height; pix->field = icf->vb_vidq.field; pix->pixelformat = icd->current_fmt->fourcc; pix->bytesperline = pix->width * @@ -723,17 +729,9 @@ static int soc_camera_cropcap(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - a->bounds = icd->rect_max; - a->defrect.left = icd->rect_max.left; - a->defrect.top = icd->rect_max.top; - a->defrect.width = DEFAULT_WIDTH; - a->defrect.height = DEFAULT_HEIGHT; - a->pixelaspect.numerator = 1; - a->pixelaspect.denominator = 1; - - return 0; + return ici->ops->cropcap(icd, a); } static int soc_camera_g_crop(struct file *file, void *fh, @@ -741,11 +739,14 @@ static int soc_camera_g_crop(struct file *file, void *fh, { struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); + int ret; - a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - a->c = icd->rect_current; + mutex_lock(&icf->vb_vidq.vb_lock); + ret = ici->ops->get_crop(icd, a); + mutex_unlock(&icf->vb_vidq.vb_lock); - return 0; + return ret; } /* @@ -760,49 +761,33 @@ static int soc_camera_s_crop(struct file *file, void *fh, struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = icf->icd; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); - struct v4l2_rect rect = a->c; + struct v4l2_rect *rect = &a->c; + struct v4l2_crop current_crop; int ret; if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; + dev_dbg(&icd->dev, "S_CROP(%ux%u@%u:%u)\n", + rect->width, rect->height, rect->left, rect->top); + /* Cropping is allowed during a running capture, guard consistency */ mutex_lock(&icf->vb_vidq.vb_lock); + /* If get_crop fails, we'll let host and / or client drivers decide */ + ret = ici->ops->get_crop(icd, ¤t_crop); + /* Prohibit window size change with initialised buffers */ - if (icf->vb_vidq.bufs[0] && (rect.width != icd->rect_current.width || - rect.height != icd->rect_current.height)) { + if (icf->vb_vidq.bufs[0] && !ret && + (a->c.width != current_crop.c.width || + a->c.height != current_crop.c.height)) { dev_err(&icd->dev, "S_CROP denied: queue initialised and sizes differ\n"); ret = -EBUSY; - goto unlock; + } else { + ret = ici->ops->set_crop(icd, a); } - if (rect.width > icd->rect_max.width) - rect.width = icd->rect_max.width; - - if (rect.width < icd->width_min) - rect.width = icd->width_min; - - if (rect.height > icd->rect_max.height) - rect.height = icd->rect_max.height; - - if (rect.height < icd->height_min) - rect.height = icd->height_min; - - if (rect.width + rect.left > icd->rect_max.width + icd->rect_max.left) - rect.left = icd->rect_max.width + icd->rect_max.left - - rect.width; - - if (rect.height + rect.top > icd->rect_max.height + icd->rect_max.top) - rect.top = icd->rect_max.height + icd->rect_max.top - - rect.height; - - ret = ici->ops->set_crop(icd, a); - if (!ret) - icd->rect_current = rect; - -unlock: mutex_unlock(&icf->vb_vidq.vb_lock); return ret; @@ -927,6 +912,8 @@ static int soc_camera_probe(struct device *dev) struct soc_camera_host *ici = to_soc_camera_host(dev->parent); struct soc_camera_link *icl = to_soc_camera_link(icd); struct device *control = NULL; + struct v4l2_subdev *sd; + struct v4l2_format f = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE}; int ret; dev_info(dev, "Probing %s\n", dev_name(dev)); @@ -983,7 +970,6 @@ static int soc_camera_probe(struct device *dev) if (ret < 0) goto eiufmt; - icd->rect_current = icd->rect_max; icd->field = V4L2_FIELD_ANY; /* ..._video_start() will create a device node, so we have to protect */ @@ -993,9 +979,15 @@ static int soc_camera_probe(struct device *dev) if (ret < 0) goto evidstart; + /* Try to improve our guess of a reasonable window format */ + sd = soc_camera_to_subdev(icd); + if (!v4l2_subdev_call(sd, video, g_fmt, &f)) { + icd->user_width = f.fmt.pix.width; + icd->user_height = f.fmt.pix.height; + } + /* Do we have to sysfs_remove_link() before device_unregister()? */ - if (to_soc_camera_control(icd) && - sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj, + if (sysfs_create_link(&icd->dev.kobj, &to_soc_camera_control(icd)->kobj, "control")) dev_warn(&icd->dev, "Failed creating the control symlink\n"); @@ -1104,6 +1096,25 @@ static void dummy_release(struct device *dev) { } +static int default_cropcap(struct soc_camera_device *icd, + struct v4l2_cropcap *a) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + return v4l2_subdev_call(sd, video, cropcap, a); +} + +static int default_g_crop(struct soc_camera_device *icd, struct v4l2_crop *a) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + return v4l2_subdev_call(sd, video, g_crop, a); +} + +static int default_s_crop(struct soc_camera_device *icd, struct v4l2_crop *a) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + return v4l2_subdev_call(sd, video, s_crop, a); +} + int soc_camera_host_register(struct soc_camera_host *ici) { struct soc_camera_host *ix; @@ -1112,7 +1123,6 @@ int soc_camera_host_register(struct soc_camera_host *ici) if (!ici || !ici->ops || !ici->ops->try_fmt || !ici->ops->set_fmt || - !ici->ops->set_crop || !ici->ops->set_bus_param || !ici->ops->querycap || !ici->ops->init_videobuf || @@ -1123,6 +1133,13 @@ int soc_camera_host_register(struct soc_camera_host *ici) !ici->v4l2_dev.dev) return -EINVAL; + if (!ici->ops->set_crop) + ici->ops->set_crop = default_s_crop; + if (!ici->ops->get_crop) + ici->ops->get_crop = default_g_crop; + if (!ici->ops->cropcap) + ici->ops->cropcap = default_cropcap; + mutex_lock(&list_lock); list_for_each_entry(ix, &hosts, list) { if (ix->nr == ici->nr) { @@ -1322,6 +1339,9 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) if (ret < 0) goto escdevreg; + icd->user_width = DEFAULT_WIDTH; + icd->user_height = DEFAULT_HEIGHT; + return 0; escdevreg: diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index aec2cadbd..3825c3581 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -127,10 +127,6 @@ static int soc_camera_platform_probe(struct platform_device *pdev) /* Set the control device reference */ dev_set_drvdata(&icd->dev, &pdev->dev); - icd->width_min = 0; - icd->rect_max.width = p->format.width; - icd->height_min = 0; - icd->rect_max.height = p->format.height; icd->y_skip_top = 0; icd->ops = &soc_camera_platform_ops; diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index e8c6cf119..3ea12a66f 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -715,8 +715,88 @@ tw9910_set_fmt_error: return ret; } +static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) +{ + struct i2c_client *client = sd->priv; + struct tw9910_priv *priv = to_tw9910(client); + + if (!priv->scale) { + int ret; + struct v4l2_crop crop = { + .c = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }; + ret = tw9910_s_crop(sd, &crop); + if (ret < 0) + return ret; + } + + a->c.left = 0; + a->c.top = 0; + a->c.width = priv->scale->width; + a->c.height = priv->scale->height; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + return 0; +} + +static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) +{ + a->bounds.left = 0; + a->bounds.top = 0; + a->bounds.width = 768; + a->bounds.height = 576; + a->defrect.left = 0; + a->defrect.top = 0; + a->defrect.width = 640; + a->defrect.height = 480; + a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + a->pixelaspect.numerator = 1; + a->pixelaspect.denominator = 1; + + return 0; +} + +static int tw9910_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct i2c_client *client = sd->priv; + struct tw9910_priv *priv = to_tw9910(client); + struct v4l2_pix_format *pix = &f->fmt.pix; + + if (!priv->scale) { + int ret; + struct v4l2_crop crop = { + .c = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }; + ret = tw9910_s_crop(sd, &crop); + if (ret < 0) + return ret; + } + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + pix->width = priv->scale->width; + pix->height = priv->scale->height; + pix->pixelformat = V4L2_PIX_FMT_VYUY; + pix->colorspace = V4L2_COLORSPACE_SMPTE170M; + pix->field = V4L2_FIELD_INTERLACED; + + return 0; +} + static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) { + struct i2c_client *client = sd->priv; + struct tw9910_priv *priv = to_tw9910(client); struct v4l2_pix_format *pix = &f->fmt.pix; /* See tw9910_s_crop() - no proper cropping support */ struct v4l2_crop a = { @@ -741,8 +821,8 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) ret = tw9910_s_crop(sd, &a); if (!ret) { - pix->width = a.c.width; - pix->height = a.c.height; + pix->width = priv->scale->width; + pix->height = priv->scale->height; } return ret; } @@ -838,8 +918,11 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { .s_stream = tw9910_s_stream, + .g_fmt = tw9910_g_fmt, .s_fmt = tw9910_s_fmt, .try_fmt = tw9910_try_fmt, + .cropcap = tw9910_cropcap, + .g_crop = tw9910_g_crop, .s_crop = tw9910_s_crop, }; @@ -852,20 +935,6 @@ static struct v4l2_subdev_ops tw9910_subdev_ops = { * i2c_driver function */ -/* This is called during probe, so, setting rect_max is Ok here: scale == 1 */ -static void limit_to_scale(struct soc_camera_device *icd, - const struct tw9910_scale_ctrl *scale) -{ - if (scale->width > icd->rect_max.width) - icd->rect_max.width = scale->width; - if (scale->width < icd->width_min) - icd->width_min = scale->width; - if (scale->height > icd->rect_max.height) - icd->rect_max.height = scale->height; - if (scale->height < icd->height_min) - icd->height_min = scale->height; -} - #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int tw9910_probe(struct i2c_client *client) #else @@ -880,8 +949,7 @@ static int tw9910_probe(struct i2c_client *client, struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct soc_camera_link *icl; - const struct tw9910_scale_ctrl *scale; - int i, ret; + int ret; if (!icd) { dev_err(&client->dev, "TW9910: missing soc-camera data!\n"); @@ -912,22 +980,6 @@ static int tw9910_probe(struct i2c_client *client, icd->ops = &tw9910_ops; icd->iface = info->link.bus_id; - /* - * set width and height - */ - icd->rect_max.width = tw9910_ntsc_scales[0].width; /* set default */ - icd->width_min = tw9910_ntsc_scales[0].width; - icd->rect_max.height = tw9910_ntsc_scales[0].height; - icd->height_min = tw9910_ntsc_scales[0].height; - - scale = tw9910_ntsc_scales; - for (i = 0; i < ARRAY_SIZE(tw9910_ntsc_scales); i++) - limit_to_scale(icd, scale + i); - - scale = tw9910_pal_scales; - for (i = 0; i < ARRAY_SIZE(tw9910_pal_scales); i++) - limit_to_scale(icd, scale + i); - ret = tw9910_video_probe(icd, client); if (ret) { icd->ops = NULL; diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 344d89904..3185e8daa 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -22,8 +22,8 @@ struct soc_camera_device { struct list_head list; struct device dev; struct device *pdev; /* Platform device */ - struct v4l2_rect rect_current; /* Current window */ - struct v4l2_rect rect_max; /* Maximum window */ + s32 user_width; + s32 user_height; unsigned short width_min; unsigned short height_min; unsigned short y_skip_top; /* Lines to skip at the top */ @@ -76,6 +76,8 @@ struct soc_camera_host_ops { int (*get_formats)(struct soc_camera_device *, int, struct soc_camera_format_xlate *); void (*put_formats)(struct soc_camera_device *); + int (*cropcap)(struct soc_camera_device *, struct v4l2_cropcap *); + int (*get_crop)(struct soc_camera_device *, struct v4l2_crop *); int (*set_crop)(struct soc_camera_device *, struct v4l2_crop *); int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *); int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); @@ -277,6 +279,21 @@ static inline unsigned long soc_camera_bus_param_compatible( common_flags; } +static inline void soc_camera_limit_side(unsigned int *start, + unsigned int *length, unsigned int start_min, + unsigned int length_min, unsigned int length_max) +{ + if (*length < length_min) + *length = length_min; + else if (*length > length_max) + *length = length_max; + + if (*start < start_min) + *start = start_min; + else if (*start > start_min + length_max - *length) + *start = start_min + length_max - *length; +} + extern unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl, unsigned long flags); -- cgit v1.2.3 From 243028968448b7efc378c94fb7b5f285ab01fbba Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:53:23 +0200 Subject: soc-camera: remove .init() and .release() methods from struct soc_camera_ops From: Guennadi Liakhovetski Remove unneeded soc-camera operations, this also makes the soc-camera API to v4l2 subdevices thinner. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9m001.c | 22 ++++++-------------- drivers/media/video/mt9m111.c | 40 +++++++------------------------------ drivers/media/video/mt9t031.c | 23 +++++---------------- drivers/media/video/mt9v022.c | 8 ++++-- drivers/media/video/soc_camera.c | 11 ---------- include/media/soc_camera.h | 4 --- 6 files changed, 26 insertions(+), 82 deletions(-) --- linux/drivers/media/video/mt9m001.c | 22 ++++++------------- linux/drivers/media/video/mt9m111.c | 40 +++++++--------------------------- linux/drivers/media/video/mt9t031.c | 23 +++++-------------- linux/drivers/media/video/mt9v022.c | 8 ++++--- linux/drivers/media/video/soc_camera.c | 11 ---------- linux/include/media/soc_camera.h | 4 ---- 6 files changed, 26 insertions(+), 82 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 3fcf57118..9da7789e6 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -122,9 +122,8 @@ static int reg_clear(struct i2c_client *client, const u8 reg, return reg_write(client, reg, ret & ~data); } -static int mt9m001_init(struct soc_camera_device *icd) +static int mt9m001_init(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); int ret; dev_dbg(&client->dev, "%s\n", __func__); @@ -144,16 +143,6 @@ static int mt9m001_init(struct soc_camera_device *icd) return ret; } -static int mt9m001_release(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - /* Disable the chip */ - reg_write(client, MT9M001_OUTPUT_CONTROL, 0); - - return 0; -} - static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = sd->priv; @@ -446,8 +435,6 @@ static const struct v4l2_queryctrl mt9m001_controls[] = { }; static struct soc_camera_ops mt9m001_ops = { - .init = mt9m001_init, - .release = mt9m001_release, .set_bus_param = mt9m001_set_bus_param, .query_bus_param = mt9m001_query_bus_param, .controls = mt9m001_controls, @@ -581,6 +568,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, struct soc_camera_link *icl = to_soc_camera_link(icd); s32 data; unsigned long flags; + int ret; /* We must have a parent by now. And it cannot be a wrong one. * So this entire test is completely redundant. */ @@ -637,7 +625,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, data == 0x8431 ? "C12STM" : "C12ST"); - return 0; + ret = mt9m001_init(client); + if (ret < 0) + dev_err(&client->dev, "Failed to initialise the camera\n"); + + return ret; } static void mt9m001_video_remove(struct soc_camera_device *icd) diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 905054e08..957fe3e4f 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -672,13 +672,9 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { }; static int mt9m111_resume(struct soc_camera_device *icd); -static int mt9m111_init(struct soc_camera_device *icd); -static int mt9m111_release(struct soc_camera_device *icd); static struct soc_camera_ops mt9m111_ops = { - .init = mt9m111_init, .resume = mt9m111_resume, - .release = mt9m111_release, .query_bus_param = mt9m111_query_bus_param, .set_bus_param = mt9m111_set_bus_param, .controls = mt9m111_controls, @@ -880,9 +876,8 @@ static int mt9m111_resume(struct soc_camera_device *icd) return ret; } -static int mt9m111_init(struct soc_camera_device *icd) +static int mt9m111_init(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct mt9m111 *mt9m111 = to_mt9m111(client); int ret; @@ -899,22 +894,6 @@ static int mt9m111_init(struct soc_camera_device *icd) return ret; } -static int mt9m111_release(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct mt9m111 *mt9m111 = to_mt9m111(client); - int ret; - - ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); - if (!ret) - mt9m111->powered = 0; - - if (ret < 0) - dev_err(&client->dev, "mt9m11x release failed: %d\n", ret); - - return ret; -} - /* * Interface active, can use i2c. If it fails, it can indeed mean, that * this wasn't our capture interface, so, we wait for the right one @@ -934,10 +913,13 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, to_soc_camera_host(icd->dev.parent)->nr != icd->iface) return -ENODEV; - ret = mt9m111_enable(client); - if (ret) - goto ei2c; - ret = mt9m111_reset(client); + mt9m111->autoexposure = 1; + mt9m111->autowhitebalance = 1; + + mt9m111->swap_rgb_even_odd = 1; + mt9m111->swap_rgb_red_blue = 1; + + ret = mt9m111_init(client); if (ret) goto ei2c; @@ -962,12 +944,6 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, dev_info(&client->dev, "Detected a MT9M11x chip ID %x\n", data); - mt9m111->autoexposure = 1; - mt9m111->autowhitebalance = 1; - - mt9m111->swap_rgb_even_odd = 1; - mt9m111->swap_rgb_red_blue = 1; - ei2c: return ret; } diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 30d4aaf81..5d9de61ee 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -163,20 +163,6 @@ static int mt9t031_disable(struct i2c_client *client) return 0; } -static int mt9t031_init(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - return mt9t031_idle(client); -} - -static int mt9t031_release(struct soc_camera_device *icd) -{ - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - - return mt9t031_disable(client); -} - static int mt9t031_s_stream(struct v4l2_subdev *sd, int enable) { struct i2c_client *client = sd->priv; @@ -539,8 +525,6 @@ static const struct v4l2_queryctrl mt9t031_controls[] = { }; static struct soc_camera_ops mt9t031_ops = { - .init = mt9t031_init, - .release = mt9t031_release, .set_bus_param = mt9t031_set_bus_param, .query_bus_param = mt9t031_query_bus_param, .controls = mt9t031_controls, @@ -689,6 +673,7 @@ static int mt9t031_video_probe(struct i2c_client *client) struct soc_camera_device *icd = client->dev.platform_data; struct mt9t031 *mt9t031 = to_mt9t031(client); s32 data; + int ret; /* Enable the chip */ data = reg_write(client, MT9T031_CHIP_ENABLE, 1); @@ -711,7 +696,11 @@ static int mt9t031_video_probe(struct i2c_client *client) dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data); - return 0; + ret = mt9t031_idle(client); + if (ret < 0) + dev_err(&client->dev, "Failed to initialise the camera\n"); + + return ret; } static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 3153fd5d2..2d5f7d121 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -138,9 +138,8 @@ static int reg_clear(struct i2c_client *client, const u8 reg, return reg_write(client, reg, ret & ~data); } -static int mt9v022_init(struct soc_camera_device *icd) +static int mt9v022_init(struct i2c_client *client) { - struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); struct mt9v022 *mt9v022 = to_mt9v022(client); int ret; @@ -532,7 +531,6 @@ static const struct v4l2_queryctrl mt9v022_controls[] = { }; static struct soc_camera_ops mt9v022_ops = { - .init = mt9v022_init, .set_bus_param = mt9v022_set_bus_param, .query_bus_param = mt9v022_query_bus_param, .controls = mt9v022_controls, @@ -751,6 +749,10 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? "monochrome" : "colour"); + ret = mt9v022_init(client); + if (ret < 0) + dev_err(&client->dev, "Failed to initialise the camera\n"); + ei2c: return ret; } diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 2290118fb..4e620978f 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -386,12 +386,6 @@ static int soc_camera_open(struct file *file) goto eiciadd; } - if (icd->ops->init) { - ret = icd->ops->init(icd); - if (ret < 0) - goto einit; - } - /* Try to configure with default parameters */ ret = soc_camera_set_fmt(icf, &f); if (ret < 0) @@ -412,9 +406,6 @@ static int soc_camera_open(struct file *file) * and use_count == 1 */ esfmt: - if (icd->ops->release) - icd->ops->release(icd); -einit: ici->ops->remove(icd); eiciadd: if (icl->power) @@ -439,8 +430,6 @@ static int soc_camera_close(struct file *file) if (!icd->use_count) { struct soc_camera_link *icl = to_soc_camera_link(icd); - if (icd->ops->release) - icd->ops->release(icd); ici->ops->remove(icd); if (icl->power) icl->power(icd->pdev, 0); diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index 3185e8daa..f95cc4a2d 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -191,12 +191,8 @@ struct soc_camera_format_xlate { struct soc_camera_ops { int (*suspend)(struct soc_camera_device *, pm_message_t state); int (*resume)(struct soc_camera_device *); - int (*init)(struct soc_camera_device *); - int (*release)(struct soc_camera_device *); unsigned long (*query_bus_param)(struct soc_camera_device *); int (*set_bus_param)(struct soc_camera_device *, unsigned long); - int (*get_chip_id)(struct soc_camera_device *, - struct v4l2_dbg_chip_ident *); int (*enum_input)(struct soc_camera_device *, struct v4l2_input *); const struct v4l2_queryctrl *controls; int num_controls; -- cgit v1.2.3 From 0ac616e3dc8591b81ebfcb8a4d10b936c82fdeab Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:53:23 +0200 Subject: soc-camera: remove .gain and .exposure struct soc_camera_device members From: Guennadi Liakhovetski This makes the soc-camera interface for V4L2 subdevices thinner yet. Handle gain and exposure internally in each driver just like all other controls. Signed-off-by: Guennadi Liakhovetski Priority: low --- drivers/media/video/mt9m001.c | 43 ++++++++++++++++++++++++------------- drivers/media/video/mt9m111.c | 20 ++++++++++++++--- drivers/media/video/mt9t031.c | 37 +++++++++++++++++++++----------- drivers/media/video/mt9v022.c | 43 ++++++++++++++++++++++++++++--------- drivers/media/video/soc_camera.c | 19 ---------------- include/media/soc_camera.h | 2 - 6 files changed, 100 insertions(+), 64 deletions(-) --- linux/drivers/media/video/mt9m001.c | 43 ++++++++++++++++++++++------------ linux/drivers/media/video/mt9m111.c | 20 ++++++++++++---- linux/drivers/media/video/mt9t031.c | 37 +++++++++++++++++++---------- linux/drivers/media/video/mt9v022.c | 43 +++++++++++++++++++++++++--------- linux/drivers/media/video/soc_camera.c | 19 --------------- linux/include/media/soc_camera.h | 2 -- 6 files changed, 100 insertions(+), 64 deletions(-) diff --git a/linux/drivers/media/video/mt9m001.c b/linux/drivers/media/video/mt9m001.c index 9da7789e6..93052047c 100644 --- a/linux/drivers/media/video/mt9m001.c +++ b/linux/drivers/media/video/mt9m001.c @@ -80,6 +80,8 @@ struct mt9m001 { struct v4l2_rect rect; /* Sensor window */ __u32 fourcc; int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ + unsigned int gain; + unsigned int exposure; unsigned char autoexposure; }; @@ -129,8 +131,8 @@ static int mt9m001_init(struct i2c_client *client) dev_dbg(&client->dev, "%s\n", __func__); /* - * We don't know, whether platform provides reset, - * issue a soft reset too + * We don't know, whether platform provides reset, issue a soft reset + * too. This returns all registers to their default values. */ ret = reg_write(client, MT9M001_RESET, 1); if (!ret) @@ -200,6 +202,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) struct soc_camera_device *icd = client->dev.platform_data; int ret; const u16 hblank = 9, vblank = 25; + unsigned int total_h; if (mt9m001->fourcc == V4L2_PIX_FMT_SBGGR8 || mt9m001->fourcc == V4L2_PIX_FMT_SBGGR16) @@ -219,6 +222,8 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) soc_camera_limit_side(&rect.top, &rect.height, MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT); + total_h = rect.height + icd->y_skip_top + vblank; + /* Blanking and start values - default... */ ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); if (!ret) @@ -236,15 +241,13 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) ret = reg_write(client, MT9M001_WINDOW_HEIGHT, rect.height + icd->y_skip_top - 1); if (!ret && mt9m001->autoexposure) { - ret = reg_write(client, MT9M001_SHUTTER_WIDTH, - rect.height + icd->y_skip_top + vblank); + ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h); if (!ret) { const struct v4l2_queryctrl *qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (524 + (rect.height + icd->y_skip_top + - vblank - 1) * - (qctrl->maximum - qctrl->minimum)) / + mt9m001->exposure = (524 + (total_h - 1) * + (qctrl->maximum - qctrl->minimum)) / 1048 + qctrl->minimum; } } @@ -457,6 +460,12 @@ static int mt9m001_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_EXPOSURE_AUTO: ctrl->value = mt9m001->autoexposure; break; + case V4L2_CID_GAIN: + ctrl->value = mt9m001->gain; + break; + case V4L2_CID_EXPOSURE: + ctrl->value = mt9m001->exposure; + break; } return 0; } @@ -518,7 +527,7 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) } /* Success */ - icd->gain = ctrl->value; + mt9m001->gain = ctrl->value; break; case V4L2_CID_EXPOSURE: /* mt9m001 has maximum == default */ @@ -535,21 +544,21 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) shutter); if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0) return -EIO; - icd->exposure = ctrl->value; + mt9m001->exposure = ctrl->value; mt9m001->autoexposure = 0; } break; case V4L2_CID_EXPOSURE_AUTO: if (ctrl->value) { const u16 vblank = 25; + unsigned int total_h = mt9m001->rect.height + + icd->y_skip_top + vblank; if (reg_write(client, MT9M001_SHUTTER_WIDTH, - mt9m001->rect.height + - icd->y_skip_top + vblank) < 0) + total_h) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (524 + (mt9m001->rect.height + - icd->y_skip_top + vblank - 1) * - (qctrl->maximum - qctrl->minimum)) / + mt9m001->exposure = (524 + (total_h - 1) * + (qctrl->maximum - qctrl->minimum)) / 1048 + qctrl->minimum; mt9m001->autoexposure = 1; } else @@ -629,6 +638,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, if (ret < 0) dev_err(&client->dev, "Failed to initialise the camera\n"); + /* mt9m001_init() has reset the chip, returning registers to defaults */ + mt9m001->gain = 64; + mt9m001->exposure = 255; + return ret; } @@ -705,7 +718,7 @@ static int mt9m001_probe(struct i2c_client *client) /* Second stage probe - when a capture adapter is there */ icd->ops = &mt9m001_ops; - icd->y_skip_top = 1; + icd->y_skip_top = 0; mt9m001->rect.left = MT9M001_COLUMN_SKIP; mt9m001->rect.top = MT9M001_ROW_SKIP; diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 957fe3e4f..9ad087132 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -153,6 +153,7 @@ struct mt9m111 { enum mt9m111_context context; struct v4l2_rect rect; u32 pixfmt; + unsigned int gain; unsigned char autoexposure; unsigned char datawidth; unsigned int powered:1; @@ -672,8 +673,10 @@ static const struct v4l2_queryctrl mt9m111_controls[] = { }; static int mt9m111_resume(struct soc_camera_device *icd); +static int mt9m111_suspend(struct soc_camera_device *icd, pm_message_t state); static struct soc_camera_ops mt9m111_ops = { + .suspend = mt9m111_suspend, .resume = mt9m111_resume, .query_bus_param = mt9m111_query_bus_param, .set_bus_param = mt9m111_set_bus_param, @@ -714,13 +717,13 @@ static int mt9m111_get_global_gain(struct i2c_client *client) static int mt9m111_set_global_gain(struct i2c_client *client, int gain) { - struct soc_camera_device *icd = client->dev.platform_data; + struct mt9m111 *mt9m111 = to_mt9m111(client); u16 val; if (gain > 63 * 2 * 2) return -EINVAL; - icd->gain = gain; + mt9m111->gain = gain; if ((gain >= 64 * 2) && (gain < 63 * 2 * 2)) val = (1 << 10) | (1 << 9) | (gain / 4); else if ((gain >= 64) && (gain < 64 * 2)) @@ -844,17 +847,26 @@ static int mt9m111_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return ret; } +static int mt9m111_suspend(struct soc_camera_device *icd, pm_message_t state) +{ + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + struct mt9m111 *mt9m111 = to_mt9m111(client); + + mt9m111->gain = mt9m111_get_global_gain(client); + + return 0; +} + static int mt9m111_restore_state(struct i2c_client *client) { struct mt9m111 *mt9m111 = to_mt9m111(client); - struct soc_camera_device *icd = client->dev.platform_data; mt9m111_set_context(client, mt9m111->context); mt9m111_set_pixfmt(client, mt9m111->pixfmt); mt9m111_setup_rect(client, &mt9m111->rect); mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); - mt9m111_set_global_gain(client, icd->gain); + mt9m111_set_global_gain(client, mt9m111->gain); mt9m111_set_autoexposure(client, mt9m111->autoexposure); mt9m111_set_autowhitebalance(client, mt9m111->autowhitebalance); return 0; diff --git a/linux/drivers/media/video/mt9t031.c b/linux/drivers/media/video/mt9t031.c index 5d9de61ee..bf3b54f9f 100644 --- a/linux/drivers/media/video/mt9t031.c +++ b/linux/drivers/media/video/mt9t031.c @@ -73,6 +73,8 @@ struct mt9t031 { int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ u16 xskip; u16 yskip; + unsigned int gain; + unsigned int exposure; unsigned char autoexposure; }; @@ -301,16 +303,15 @@ static int mt9t031_set_params(struct soc_camera_device *icd, ret = reg_write(client, MT9T031_WINDOW_HEIGHT, rect->height + icd->y_skip_top - 1); if (ret >= 0 && mt9t031->autoexposure) { - ret = set_shutter(client, - rect->height + icd->y_skip_top + vblank); + unsigned int total_h = rect->height + icd->y_skip_top + vblank; + ret = set_shutter(client, total_h); if (ret >= 0) { const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; const struct v4l2_queryctrl *qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (shutter_max / 2 + (rect->height + - icd->y_skip_top + vblank - 1) * - (qctrl->maximum - qctrl->minimum)) / + mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * + (qctrl->maximum - qctrl->minimum)) / shutter_max + qctrl->minimum; } } @@ -553,6 +554,12 @@ static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) case V4L2_CID_EXPOSURE_AUTO: ctrl->value = mt9t031->autoexposure; break; + case V4L2_CID_GAIN: + ctrl->value = mt9t031->gain; + break; + case V4L2_CID_EXPOSURE: + ctrl->value = mt9t031->exposure; + break; } return 0; } @@ -624,7 +631,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) } /* Success */ - icd->gain = ctrl->value; + mt9t031->gain = ctrl->value; break; case V4L2_CID_EXPOSURE: /* mt9t031 has maximum == default */ @@ -641,7 +648,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) old, shutter); if (set_shutter(client, shutter) < 0) return -EIO; - icd->exposure = ctrl->value; + mt9t031->exposure = ctrl->value; mt9t031->autoexposure = 0; } break; @@ -649,14 +656,14 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (ctrl->value) { const u16 vblank = MT9T031_VERTICAL_BLANK; const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; - if (set_shutter(client, mt9t031->rect.height + - icd->y_skip_top + vblank) < 0) + unsigned int total_h = mt9t031->rect.height + + icd->y_skip_top + vblank; + + if (set_shutter(client, total_h) < 0) return -EIO; qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = (shutter_max / 2 + - (mt9t031->rect.height + - icd->y_skip_top + vblank - 1) * - (qctrl->maximum - qctrl->minimum)) / + mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * + (qctrl->maximum - qctrl->minimum)) / shutter_max + qctrl->minimum; mt9t031->autoexposure = 1; } else @@ -700,6 +707,10 @@ static int mt9t031_video_probe(struct i2c_client *client) if (ret < 0) dev_err(&client->dev, "Failed to initialise the camera\n"); + /* mt9t031_idle() has reset the chip to default. */ + mt9t031->exposure = 255; + mt9t031->gain = 64; + return ret; } diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 2d5f7d121..582fabcfd 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -45,7 +45,7 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); #define MT9V022_PIXEL_OPERATION_MODE 0x0f #define MT9V022_LED_OUT_CONTROL 0x1b #define MT9V022_ADC_MODE_CONTROL 0x1c -#define MT9V022_ANALOG_GAIN 0x34 +#define MT9V022_ANALOG_GAIN 0x35 #define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47 #define MT9V022_PIXCLK_FV_LV 0x74 #define MT9V022_DIGITAL_TEST_PATTERN 0x7f @@ -155,6 +155,10 @@ static int mt9v022_init(struct i2c_client *client) if (!ret) /* AEC, AGC on */ ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3); + if (!ret) + ret = reg_write(client, MT9V022_ANALOG_GAIN, 16); + if (!ret) + ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, 480); if (!ret) ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480); if (!ret) @@ -540,8 +544,12 @@ static struct soc_camera_ops mt9v022_ops = { static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct i2c_client *client = sd->priv; + const struct v4l2_queryctrl *qctrl; + unsigned long range; int data; + qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); + switch (ctrl->id) { case V4L2_CID_VFLIP: data = reg_read(client, MT9V022_READ_MODE); @@ -566,6 +574,24 @@ static int mt9v022_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (data < 0) return -EIO; ctrl->value = !!(data & 0x2); + break; + case V4L2_CID_GAIN: + data = reg_read(client, MT9V022_ANALOG_GAIN); + if (data < 0) + return -EIO; + + range = qctrl->maximum - qctrl->minimum; + ctrl->value = ((data - 16) * range + 24) / 48 + qctrl->minimum; + + break; + case V4L2_CID_EXPOSURE: + data = reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH); + if (data < 0) + return -EIO; + + range = qctrl->maximum - qctrl->minimum; + ctrl->value = ((data - 1) * range + 239) / 479 + qctrl->minimum; + break; } return 0; @@ -575,7 +601,6 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { int data; struct i2c_client *client = sd->priv; - struct soc_camera_device *icd = client->dev.platform_data; const struct v4l2_queryctrl *qctrl; qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); @@ -605,12 +630,9 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return -EINVAL; else { unsigned long range = qctrl->maximum - qctrl->minimum; - /* Datasheet says 16 to 64. autogain only works properly - * after setting gain to maximum 14. Larger values - * produce "white fly" noise effect. On the whole, - * manually setting analog gain does no good. */ + /* Valid values 16 to 64, 32 to 64 must be even. */ unsigned long gain = ((ctrl->value - qctrl->minimum) * - 10 + range / 2) / range + 4; + 48 + range / 2) / range + 16; if (gain >= 32) gain &= ~1; /* The user wants to set gain manually, hope, she @@ -619,11 +641,10 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) return -EIO; - dev_info(&client->dev, "Setting gain from %d to %lu\n", - reg_read(client, MT9V022_ANALOG_GAIN), gain); + dev_dbg(&client->dev, "Setting gain from %d to %lu\n", + reg_read(client, MT9V022_ANALOG_GAIN), gain); if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0) return -EIO; - icd->gain = ctrl->value; } break; case V4L2_CID_EXPOSURE: @@ -646,7 +667,6 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, shutter) < 0) return -EIO; - icd->exposure = ctrl->value; } break; case V4L2_CID_AUTOGAIN: @@ -831,6 +851,7 @@ static int mt9v022_probe(struct i2c_client *client) mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; icd->ops = &mt9v022_ops; + /* MT9V022 _really_ corrupts the first read out line. TODO: verify on i.MX31 */ icd->y_skip_top = 1; mt9v022->rect.left = MT9V022_COLUMN_SKIP; diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 4e620978f..6fac3d0eb 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -671,19 +671,6 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, WARN_ON(priv != file->private_data); - switch (ctrl->id) { - case V4L2_CID_GAIN: - if (icd->gain == (unsigned short)~0) - return -EINVAL; - ctrl->value = icd->gain; - return 0; - case V4L2_CID_EXPOSURE: - if (icd->exposure == (unsigned short)~0) - return -EINVAL; - ctrl->value = icd->exposure; - return 0; - } - if (ici->ops->get_ctrl) { ret = ici->ops->get_ctrl(icd, ctrl); if (ret != -ENOIOCTLCMD) @@ -1280,7 +1267,6 @@ static int video_dev_create(struct soc_camera_device *icd) */ static int soc_camera_video_start(struct soc_camera_device *icd) { - const struct v4l2_queryctrl *qctrl; int ret; if (!icd->dev.parent) @@ -1298,11 +1284,6 @@ static int soc_camera_video_start(struct soc_camera_device *icd) return ret; } - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN); - icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0; - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); - icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; - return 0; } diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index f95cc4a2d..fe20e3311 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -27,8 +27,6 @@ struct soc_camera_device { unsigned short width_min; unsigned short height_min; unsigned short y_skip_top; /* Lines to skip at the top */ - unsigned short gain; - unsigned short exposure; unsigned char iface; /* Host number */ unsigned char devnum; /* Device number per host */ unsigned char buswidth; /* See comment in .c */ -- cgit v1.2.3 From 92c15735f63a6159490a9b6110e81925d093a10d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Aug 2009 16:53:23 +0200 Subject: soc-camera: fix recently introduced overlong lines From: Guennadi Liakhovetski Signed-off-by: Guennadi Liakhovetski Cc: Paul Mundt Acked-by: Paul Mundt Priority: low --- arch/sh/boards/board-ap325rxa.c | 3 ++- drivers/media/video/mt9m111.c | 9 +++++---- drivers/media/video/mt9v022.c | 5 ++++- drivers/media/video/mx1_camera.c | 3 ++- drivers/media/video/ov772x.c | 6 ++++-- drivers/media/video/pxa_camera.c | 3 ++- drivers/media/video/soc_camera.c | 14 +++++++++++--- drivers/media/video/soc_camera_platform.c | 3 ++- drivers/media/video/tw9910.c | 3 ++- include/media/soc_camera.h | 15 ++++++++++----- 10 files changed, 44 insertions(+), 20 deletions(-) --- linux/arch/sh/boards/board-ap325rxa.c | 3 ++- linux/drivers/media/video/mt9m111.c | 9 +++++---- linux/drivers/media/video/mt9v022.c | 5 ++++- linux/drivers/media/video/mx1_camera.c | 3 ++- linux/drivers/media/video/ov772x.c | 6 ++++-- linux/drivers/media/video/pxa_camera.c | 3 ++- linux/drivers/media/video/soc_camera.c | 14 +++++++++++--- linux/drivers/media/video/soc_camera_platform.c | 3 ++- linux/drivers/media/video/tw9910.c | 3 ++- linux/include/media/soc_camera.h | 15 ++++++++++----- 10 files changed, 44 insertions(+), 20 deletions(-) diff --git a/linux/arch/sh/boards/board-ap325rxa.c b/linux/arch/sh/boards/board-ap325rxa.c index 62cec8772..21469489d 100644 --- a/linux/arch/sh/boards/board-ap325rxa.c +++ b/linux/arch/sh/boards/board-ap325rxa.c @@ -359,7 +359,8 @@ static void ap325rxa_camera_del(struct soc_camera_link *icl) return; platform_device_unregister(&camera_device); - memset(&migor_camera_device.dev.kobj, 0, sizeof(migor_camera_device.dev.kobj)); + memset(&migor_camera_device.dev.kobj, 0, + sizeof(migor_camera_device.dev.kobj)); } #endif /* CONFIG_I2C */ diff --git a/linux/drivers/media/video/mt9m111.c b/linux/drivers/media/video/mt9m111.c index 9ad087132..8171edb72 100644 --- a/linux/drivers/media/video/mt9m111.c +++ b/linux/drivers/media/video/mt9m111.c @@ -514,7 +514,8 @@ static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt) ret = mt9m111_setfmt_yuv(client); break; default: - dev_err(&client->dev, "Pixel format not handled : %x\n", pixfmt); + dev_err(&client->dev, "Pixel format not handled : %x\n", + pixfmt); ret = -EINVAL; } @@ -537,9 +538,9 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) }; int ret; - dev_dbg(&client->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", - __func__, pix->pixelformat, rect.left, rect.top, rect.width, - rect.height); + dev_dbg(&client->dev, + "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", __func__, + pix->pixelformat, rect.left, rect.top, rect.width, rect.height); ret = mt9m111_make_rect(client, &rect); if (!ret) diff --git a/linux/drivers/media/video/mt9v022.c b/linux/drivers/media/video/mt9v022.c index 582fabcfd..9da3dde10 100644 --- a/linux/drivers/media/video/mt9v022.c +++ b/linux/drivers/media/video/mt9v022.c @@ -851,7 +851,10 @@ static int mt9v022_probe(struct i2c_client *client) mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; icd->ops = &mt9v022_ops; - /* MT9V022 _really_ corrupts the first read out line. TODO: verify on i.MX31 */ + /* + * MT9V022 _really_ corrupts the first read out line. + * TODO: verify on i.MX31 + */ icd->y_skip_top = 1; mt9v022->rect.left = MT9V022_COLUMN_SKIP; diff --git a/linux/drivers/media/video/mx1_camera.c b/linux/drivers/media/video/mx1_camera.c index 3875483ab..5f37952c7 100644 --- a/linux/drivers/media/video/mx1_camera.c +++ b/linux/drivers/media/video/mx1_camera.c @@ -548,7 +548,8 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); if (!xlate) { - dev_warn(icd->dev.parent, "Format %x not found\n", pix->pixelformat); + dev_warn(icd->dev.parent, "Format %x not found\n", + pix->pixelformat); return -EINVAL; } diff --git a/linux/drivers/media/video/ov772x.c b/linux/drivers/media/video/ov772x.c index 2d48a7aeb..47e7c7c53 100644 --- a/linux/drivers/media/video/ov772x.c +++ b/linux/drivers/media/video/ov772x.c @@ -404,7 +404,8 @@ struct ov772x_priv { int model; unsigned short flag_vflip:1; unsigned short flag_hflip:1; - unsigned short band_filter; /* 256 - BDBASE, 0 if (!COM8[5]) */ + /* band_filter = COM8[5] ? 256 - BDBASE : 0 */ + unsigned short band_filter; }; #define ENDMARKER { 0xff, 0xff } @@ -587,7 +588,8 @@ static const struct v4l2_queryctrl ov772x_controls[] = { static struct ov772x_priv *to_ov772x(const struct i2c_client *client) { - return container_of(i2c_get_clientdata(client), struct ov772x_priv, subdev); + return container_of(i2c_get_clientdata(client), struct ov772x_priv, + subdev); } static int ov772x_write_array(struct i2c_client *client, diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 0364b35d5..8ab1a5792 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -286,7 +286,8 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { if (buf->dmas[i].sg_cpu) - dma_free_coherent(ici->v4l2_dev.dev, buf->dmas[i].sg_size, + dma_free_coherent(ici->v4l2_dev.dev, + buf->dmas[i].sg_size, buf->dmas[i].sg_cpu, buf->dmas[i].sg_dma); buf->dmas[i].sg_cpu = NULL; diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 6fac3d0eb..55d4d9a22 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -328,7 +328,9 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, static int soc_camera_open(struct file *file) { struct video_device *vdev = video_devdata(file); - struct soc_camera_device *icd = container_of(vdev->parent, struct soc_camera_device, dev); + struct soc_camera_device *icd = container_of(vdev->parent, + struct soc_camera_device, + dev); struct soc_camera_link *icl = to_soc_camera_link(icd); struct soc_camera_host *ici; struct soc_camera_file *icf; @@ -350,7 +352,10 @@ static int soc_camera_open(struct file *file) goto emgi; } - /* Protect against icd->ops->remove() until we module_get() both drivers. */ + /* + * Protect against icd->ops->remove() until we module_get() both + * drivers. + */ mutex_lock(&icd->video_lock); icf->icd = icd; @@ -932,7 +937,10 @@ static int soc_camera_probe(struct device *dev) if (ret < 0) goto eadddev; - /* FIXME: this is racy, have to use driver-binding notification */ + /* + * FIXME: this is racy, have to use driver-binding notification, + * when it is available + */ control = to_soc_camera_control(icd); if (!control || !control->driver || !dev_get_drvdata(control) || !try_module_get(control->driver->owner)) { diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index 3825c3581..1b6dd02a8 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -33,7 +33,8 @@ static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev) static struct soc_camera_platform_info *get_info(struct soc_camera_device *icd) { - struct platform_device *pdev = to_platform_device(to_soc_camera_control(icd)); + struct platform_device *pdev = + to_platform_device(to_soc_camera_control(icd)); return pdev->dev.platform_data; } diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c index 3ea12a66f..db56ae683 100644 --- a/linux/drivers/media/video/tw9910.c +++ b/linux/drivers/media/video/tw9910.c @@ -357,7 +357,8 @@ static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = { */ static struct tw9910_priv *to_tw9910(const struct i2c_client *client) { - return container_of(i2c_get_clientdata(client), struct tw9910_priv, subdev); + return container_of(i2c_get_clientdata(client), struct tw9910_priv, + subdev); } static int tw9910_set_scale(struct i2c_client *client, diff --git a/linux/include/media/soc_camera.h b/linux/include/media/soc_camera.h index fe20e3311..3d74e6003 100644 --- a/linux/include/media/soc_camera.h +++ b/linux/include/media/soc_camera.h @@ -126,29 +126,34 @@ struct soc_camera_link { void (*free_bus)(struct soc_camera_link *); }; -static inline struct soc_camera_device *to_soc_camera_dev(const struct device *dev) +static inline struct soc_camera_device *to_soc_camera_dev( + const struct device *dev) { return container_of(dev, struct soc_camera_device, dev); } -static inline struct soc_camera_host *to_soc_camera_host(const struct device *dev) +static inline struct soc_camera_host *to_soc_camera_host( + const struct device *dev) { struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); return container_of(v4l2_dev, struct soc_camera_host, v4l2_dev); } -static inline struct soc_camera_link *to_soc_camera_link(const struct soc_camera_device *icd) +static inline struct soc_camera_link *to_soc_camera_link( + const struct soc_camera_device *icd) { return icd->dev.platform_data; } -static inline struct device *to_soc_camera_control(const struct soc_camera_device *icd) +static inline struct device *to_soc_camera_control( + const struct soc_camera_device *icd) { return dev_get_drvdata(&icd->dev); } -static inline struct v4l2_subdev *soc_camera_to_subdev(const struct soc_camera_device *icd) +static inline struct v4l2_subdev *soc_camera_to_subdev( + const struct soc_camera_device *icd) { struct device *control = to_soc_camera_control(icd); return dev_get_drvdata(control); -- cgit v1.2.3 From 3041f901c7458733517662e5a5bedb4341fed496 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 26 Aug 2009 08:34:16 +0200 Subject: gspca - sn9c20x: Fix gscpa sn9c20x build errors. From: Randy Dunlap Reported-by: Toralf Forster Priority: high Signed-off-by: Randy Dunlap Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig index 6ae1522ec..8897283b0 100644 --- a/linux/drivers/media/video/gspca/Kconfig +++ b/linux/drivers/media/video/gspca/Kconfig @@ -123,7 +123,7 @@ config USB_GSPCA_SN9C20X config USB_GSPCA_SN9C20X_EVDEV bool "Enable evdev support" - depends on USB_GSPCA_SN9C20X + depends on USB_GSPCA_SN9C20X && INPUT ---help--- Say Y here in order to enable evdev support for sn9c20x webcam button. -- cgit v1.2.3 From 39260c5d799177f03ba4a0cea40f998ebff7d8c9 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 26 Aug 2009 20:39:27 +0200 Subject: Document the new V4L2_CID_BAND_STOP_FILTER control From: Guennadi Liakhovetski Add V4L2 API documentation for the new V4L2_CID_BAND_STOP_FILTER control Signed-off-by: Guennadi Liakhovetski --- v4l2-spec/controls.sgml | 8 ++++++++ v4l2-spec/v4l2.sgml | 9 ++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/v4l2-spec/controls.sgml b/v4l2-spec/controls.sgml index 477a97077..a806eddcd 100644 --- a/v4l2-spec/controls.sgml +++ b/v4l2-spec/controls.sgml @@ -1811,6 +1811,14 @@ mechanical obturation of the sensor and firmware image processing, but the device is not restricted to these methods. Devices that implement the privacy control must support read access and may support write access. + + + V4L2_CID_BAND_STOP_FILTER  + integer + Switch the band-stop filter of a +camera sensor on or off, or specify its strength. Such band-stop filters can +be used, for example, to filter out the fluorescent light component. + diff --git a/v4l2-spec/v4l2.sgml b/v4l2-spec/v4l2.sgml index 8e7610685..a433a1fc2 100644 --- a/v4l2-spec/v4l2.sgml +++ b/v4l2-spec/v4l2.sgml @@ -25,7 +25,7 @@ Video for Linux Two API Specification - Revision 0.27 + Revision 0.28 @@ -143,6 +143,13 @@ structs, ioctls) must be noted in more detail in the history chapter (compat.sgml), along with the possible impact on existing drivers and applications. --> + + 0.28 + 2009-08-26 + gl + Added V4L2_CID_BAND_STOP_FILTER documentation. + + 0.27 2009-08-15 -- cgit v1.2.3 From 4be4cfbd5a49c25a5d4fb78aed2e1246415ac7aa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 11 Aug 2009 23:47:18 +0200 Subject: v4l: introduce string control support. From: Hans Verkuil The upcoming RDS encoder needs support for string controls. This patch implements the core implementation. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-common.c | 2 + linux/drivers/media/video/v4l2-compat-ioctl32.c | 65 +++++++++++++++++-------- linux/drivers/media/video/v4l2-ioctl.c | 10 ++-- linux/include/linux/videodev2.h | 6 ++- 4 files changed, 57 insertions(+), 26 deletions(-) diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index fe1dfc00b..51c080c13 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -157,6 +157,8 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, return -EINVAL; if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED) return -EBUSY; + if (qctrl->type == V4L2_CTRL_TYPE_STRING) + return 0; if (qctrl->type == V4L2_CTRL_TYPE_BUTTON || qctrl->type == V4L2_CTRL_TYPE_INTEGER64 || qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index d9cee38cd..cd45c09ff 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -605,9 +605,35 @@ struct v4l2_ext_controls32 { compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */ }; +struct v4l2_ext_control32 { + __u32 id; + __u32 size; + __u32 reserved2[1]; + union { + __s32 value; + __s64 value64; + compat_caddr_t string; /* actually char * */ + }; +} __attribute__ ((packed)); + +/* The following function really belong in v4l2-common, but that causes + a circular dependency between modules. We need to think about this, but + for now this will do. */ + +/* Return non-zero if this control is a pointer type. Currently only + * type STRING is a pointer type. + * + * Note that there are currently no controls of this type, but at least the + * compat32 code is in place to properly handle such controls. Please + * remove this note once the first pointer controls are added. */ +static inline int ctrl_is_pointer(u32 id) +{ + return 0; +} + static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) { - struct v4l2_ext_control __user *ucontrols; + struct v4l2_ext_control32 __user *ucontrols; struct v4l2_ext_control __user *kcontrols; int n; compat_caddr_t p; @@ -631,15 +657,17 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control)); kp->controls = kcontrols; while (--n >= 0) { - if (copy_in_user(&kcontrols->id, &ucontrols->id, sizeof(__u32))) - return -EFAULT; - if (copy_in_user(&kcontrols->reserved2, &ucontrols->reserved2, sizeof(ucontrols->reserved2))) - return -EFAULT; - /* Note: if the void * part of the union ever becomes relevant - then we need to know the type of the control in order to do - the right thing here. Luckily, that is not yet an issue. */ - if (copy_in_user(&kcontrols->value, &ucontrols->value, sizeof(ucontrols->value))) + if (copy_in_user(kcontrols, ucontrols, sizeof(*kcontrols))) return -EFAULT; + if (ctrl_is_pointer(kcontrols->id)) { + void __user *s; + + if (get_user(p, &ucontrols->string)) + return -EFAULT; + s = compat_ptr(p); + if (put_user(s, &kcontrols->string)) + return -EFAULT; + } ucontrols++; kcontrols++; } @@ -648,7 +676,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) { - struct v4l2_ext_control __user *ucontrols; + struct v4l2_ext_control32 __user *ucontrols; struct v4l2_ext_control __user *kcontrols = kp->controls; int n = kp->count; compat_caddr_t p; @@ -669,15 +697,14 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext return -EFAULT; while (--n >= 0) { - if (copy_in_user(&ucontrols->id, &kcontrols->id, sizeof(__u32))) - return -EFAULT; - if (copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2, - sizeof(ucontrols->reserved2))) - return -EFAULT; - /* Note: if the void * part of the union ever becomes relevant - then we need to know the type of the control in order to do - the right thing here. Luckily, that is not yet an issue. */ - if (copy_in_user(&ucontrols->value, &kcontrols->value, sizeof(ucontrols->value))) + unsigned size = sizeof(*ucontrols); + + /* Do not modify the pointer when copying a pointer control. + The contents of the pointer was changed, not the pointer + itself. */ + if (ctrl_is_pointer(kcontrols->id)) + size -= sizeof(ucontrols->value64); + if (copy_in_user(ucontrols, kcontrols, size)) return -EFAULT; ucontrols++; kcontrols++; diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index d746d9555..d40c7bb2d 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -514,11 +514,12 @@ static inline void v4l_print_ext_ctrls(unsigned int cmd, dbgarg(cmd, ""); printk(KERN_CONT "class=0x%x", c->ctrl_class); for (i = 0; i < c->count; i++) { - if (show_vals) + if (show_vals && !c->controls[i].size) printk(KERN_CONT " id/val=0x%x/0x%x", c->controls[i].id, c->controls[i].value); else - printk(KERN_CONT " id=0x%x", c->controls[i].id); + printk(KERN_CONT " id=0x%x,size=%u", + c->controls[i].id, c->controls[i].size); } printk(KERN_CONT "\n"); }; @@ -529,10 +530,9 @@ static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) /* zero the reserved fields */ c->reserved[0] = c->reserved[1] = 0; - for (i = 0; i < c->count; i++) { + for (i = 0; i < c->count; i++) c->controls[i].reserved2[0] = 0; - c->controls[i].reserved2[1] = 0; - } + /* V4L2_CID_PRIVATE_BASE cannot be used as control class when using extended controls. Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index f94613802..409c505ff 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -167,6 +167,7 @@ enum v4l2_ctrl_type { V4L2_CTRL_TYPE_BUTTON = 4, V4L2_CTRL_TYPE_INTEGER64 = 5, V4L2_CTRL_TYPE_CTRL_CLASS = 6, + V4L2_CTRL_TYPE_STRING = 7, }; enum v4l2_tuner_type { @@ -795,11 +796,12 @@ struct v4l2_control { struct v4l2_ext_control { __u32 id; - __u32 reserved2[2]; + __u32 size; + __u32 reserved2[1]; union { __s32 value; __s64 value64; - void *reserved; + char *string; }; } __attribute__ ((packed)); -- cgit v1.2.3 From 31901a2ad985c7839b68b5b43788d5d62ea32f58 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 2 Aug 2009 11:58:43 +0200 Subject: v4l2-spec: document the new string control type. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- v4l2-spec/Makefile | 1 + v4l2-spec/compat.sgml | 3 ++ v4l2-spec/controls.sgml | 3 +- v4l2-spec/v4l2.sgml | 4 +-- v4l2-spec/vidioc-g-ext-ctrls.sgml | 72 ++++++++++++++++++++++++++++++++------- v4l2-spec/vidioc-queryctrl.sgml | 42 +++++++++++++++++------ 6 files changed, 98 insertions(+), 27 deletions(-) diff --git a/v4l2-spec/Makefile b/v4l2-spec/Makefile index 616445137..3b4c321c4 100644 --- a/v4l2-spec/Makefile +++ b/v4l2-spec/Makefile @@ -307,6 +307,7 @@ ERRORS = \ EINVAL \ ENFILE \ ENOMEM \ + ENOSPC \ ENOTTY \ ENXIO \ EMFILE \ diff --git a/v4l2-spec/compat.sgml b/v4l2-spec/compat.sgml index bcc372c18..c18ddf3db 100644 --- a/v4l2-spec/compat.sgml +++ b/v4l2-spec/compat.sgml @@ -2303,6 +2303,9 @@ more information. Added new capabilities for modulators and RDS encoders. + + Added support for string controls. + diff --git a/v4l2-spec/controls.sgml b/v4l2-spec/controls.sgml index a806eddcd..dbe4f6f86 100644 --- a/v4l2-spec/controls.sgml +++ b/v4l2-spec/controls.sgml @@ -492,8 +492,7 @@ supported. The control array is a &v4l2-ext-control; array. The v4l2_ext_control structure is very similar to &v4l2-control;, except for the fact that it also allows for 64-bit -values and pointers to be passed (although the latter is not yet used -anywhere). +values and pointers to be passed. It is important to realize that due to the flexibility of controls it is necessary to check whether the control you want to set diff --git a/v4l2-spec/v4l2.sgml b/v4l2-spec/v4l2.sgml index a433a1fc2..fe13602f7 100644 --- a/v4l2-spec/v4l2.sgml +++ b/v4l2-spec/v4l2.sgml @@ -159,10 +159,10 @@ applications. --> 0.26 - 2009-06-15 + 2009-07-23 hv Finalized the RDS capture API. Added modulator and RDS encoder -capabilities. +capabilities. Added support for string controls. diff --git a/v4l2-spec/vidioc-g-ext-ctrls.sgml b/v4l2-spec/vidioc-g-ext-ctrls.sgml index 510520254..44a8f5575 100644 --- a/v4l2-spec/vidioc-g-ext-ctrls.sgml +++ b/v4l2-spec/vidioc-g-ext-ctrls.sgml @@ -68,20 +68,35 @@ initialize the &v4l2-ext-control; array pointed to by the controls fields. To get the current value of a set of controls applications -initialize the id field of each -&v4l2-ext-control; and call the -VIDIOC_G_EXT_CTRLS ioctl. +initialize the id, +size and reserved2 fields +of each &v4l2-ext-control; and call the +VIDIOC_G_EXT_CTRLS ioctl. String controls controls +must also set the string field. + + If the size is too small to +receive the control result (only relevant for pointer-type controls +like strings), then the driver will set size +to a valid value and return an &ENOSPC;. You should re-allocate the +string memory to this new size and try again. It is possible that the +same issue occurs again if the string has grown in the meantime. It is +recommended to call &VIDIOC-QUERYCTRL; first and use +maximum+1 as the new size +value. It is guaranteed that that is sufficient memory. + To change the value of a set of controls applications -initialize the id and -value fields of a &v4l2-ext-control; and +initialize the id, size, +reserved2 and +value/string fields of each &v4l2-ext-control; and call the VIDIOC_S_EXT_CTRLS ioctl. The controls will only be set if all control values are valid. - To check if the a set of controls have correct values -applications initialize the id and -value fields of a &v4l2-ext-control; and + To check if a set of controls have correct values applications +initialize the id, size, +reserved2 and +value/string fields of each &v4l2-ext-control; and call the VIDIOC_TRY_EXT_CTRLS ioctl. It is up to the driver whether wrong values are automatically adjusted to a valid value or if an error is returned. @@ -112,7 +127,23 @@ application. __u32 - reserved2[2] + size + + The total size in bytes of the payload of this +control. This is normally 0, but for pointer controls this should be +set to the size of the memory containing the payload, or that will +receive the payload. If VIDIOC_G_EXT_CTRLS finds +that this value is less than is required to store +the payload result, then it is set to a value large enough to store the +payload result and ENOSPC is returned. Note that for string controls +this size field should not be confused with the length of the string. +This field refers to the size of the memory that contains the string. +The actual length of the string may well be much smaller. + + + + __u32 + reserved2[1] Reserved for future extensions. Drivers and applications must set the array to zero. @@ -135,9 +166,9 @@ applications must set the array to zero. - void * - reserved - Reserved for future pointer-type controls. Currently unused. + char * + string + A pointer to a string. @@ -202,9 +233,16 @@ class. V4L2_CTRL_CLASS_MPEG 0x990000 The class containing MPEG compression controls. -These controls are described in section . + + V4L2_CTRL_CLASS_CAMERA + 0x9a0000 + The class containing camera controls. +These controls are described in . + @@ -241,6 +279,14 @@ because another applications took over control of the device function this control belongs to. + + ENOSPC + + The space reserved for the control's payload is insufficient. +The field size is set to a value that is enough +to store the payload and this error code is returned. + + diff --git a/v4l2-spec/vidioc-queryctrl.sgml b/v4l2-spec/vidioc-queryctrl.sgml index 9908a964d..413930226 100644 --- a/v4l2-spec/vidioc-queryctrl.sgml +++ b/v4l2-spec/vidioc-queryctrl.sgml @@ -93,8 +93,8 @@ next supported control, or EINVAL if there is none. Drivers which do not support this flag yet always return EINVAL. - Additional information is required for menu controls, the -name of menu items. To query them applications set the + Additional information is required for menu controls: the +names of the menu items. To query them applications set the id and index fields of &v4l2-querymenu; and call the VIDIOC_QUERYMENU ioctl with a pointer to this @@ -138,9 +138,12 @@ string. This information is intended for the user. __s32 minimum Minimum value, inclusive. This field gives a lower -bound for V4L2_CTRL_TYPE_INTEGER controls. It may -not be valid for any other type of control, including -V4L2_CTRL_TYPE_INTEGER64 controls. Note this is a +bound for V4L2_CTRL_TYPE_INTEGER controls and the +lowest valid index (always 0) for V4L2_CTRL_TYPE_MENU controls. +For V4L2_CTRL_TYPE_STRING controls the minimum value +gives the minimum length of the string. This length does not include the terminating +zero. It may not be valid for any other type of control, including +V4L2_CTRL_TYPE_INTEGER64 controls. Note that this is a signed value. @@ -149,16 +152,21 @@ signed value. Maximum value, inclusive. This field gives an upper bound for V4L2_CTRL_TYPE_INTEGER controls and the highest valid index for V4L2_CTRL_TYPE_MENU -controls. It may not be valid for any other type of control, including -V4L2_CTRL_TYPE_INTEGER64 controls. Note this is a +controls. +For V4L2_CTRL_TYPE_STRING controls the maximum value +gives the maximum length of the string. This length does not include the terminating +zero. It may not be valid for any other type of control, including +V4L2_CTRL_TYPE_INTEGER64 controls. Note that this is a signed value. __s32 step This field gives a step size for -V4L2_CTRL_TYPE_INTEGER controls. It may not be -valid for any other type of control, including +V4L2_CTRL_TYPE_INTEGER controls. For +V4L2_CTRL_TYPE_STRING controls this field refers to +the string length that has to be a multiple of this step size. +It may not be valid for any other type of control, including V4L2_CTRL_TYPE_INTEGER64 controls.Generally drivers should not scale hardware control values. It may be necessary for example when the @@ -171,7 +179,7 @@ an integer control actually affecting hardware. Often the information is needed when the user can change controls by keyboard or GUI buttons, rather than a slider. When for example a hardware register accepts values 0-511 and the driver reports 0-65535, step should be -128.Note although signed, the step value is supposed to +128.Note that although signed, the step value is supposed to be always positive. @@ -295,6 +303,20 @@ Drivers must ignore the value passed with n/a A 64-bit integer valued control. Minimum, maximum and step size cannot be queried. + + + V4L2_CTRL_TYPE_STRING + >=0 + >=1 + >=0 + The minimum and maximum string lengths. The step size +means that the string must be (minimum + N * step) characters long for +N >= 0. These lengths do not include the terminating zero, so in order to +pass a string of length 8 to &VIDIOC-S-EXT-CTRLS; you need to set the +size field of &v4l2-ext-control; to 9. For &VIDIOC-G-EXT-CTRLS; you can +set the size field to maximum+1. +Which character encoding is used will depend on the string control itself and +should be part of the control documentation. V4L2_CTRL_TYPE_CTRL_CLASS -- cgit v1.2.3 From d129cf91ea1355d0b5ff68d3720bc89fca4c7570 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 2 Aug 2009 12:04:23 +0200 Subject: v4l2-ctl: modulator bug fixes From: Hans Verkuil Setting the modulator did not take all txsubchans combinations and the correct V4L2_TUNER_CAP_LOW into account (it used V4L2_TUNER_CAP_LOW from G_TUNER instead of G_MODULATOR). Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-ctl.cpp | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp index 60ebc5474..70b85d0d0 100644 --- a/v4l2-apps/util/v4l2-ctl.cpp +++ b/v4l2-apps/util/v4l2-ctl.cpp @@ -425,7 +425,9 @@ static void usage(void) " set the sub-carrier modulation [VIDIOC_S_MODULATOR]\n" " is one of:\n" " mono: Modulate as mono\n" + " mono-rds: Modulate as mono with RDS (radio only)\n" " stereo: Modulate as stereo\n" + " stereo-rds: Modulate as stereo with RDS (radio only)\n" " bilingual: Modulate as bilingual\n" " mono-sap: Modulate as mono with Second Audio Program\n" " stereo-sap: Modulate as stereo with Second Audio Program\n" @@ -988,6 +990,8 @@ static std::string txsubchans2s(int txsubchans) s += "bilingual"; if (txsubchans & V4L2_TUNER_SUB_SAP) s += "+sap"; + if (txsubchans & V4L2_TUNER_SUB_RDS) + s += "+rds"; return s; } @@ -1421,7 +1425,8 @@ int main(int argc, char **argv) struct v4l2_format raw_fmt_out; /* set_format/get_format for VBI output */ struct v4l2_format overlay_fmt; /* set_format/get_format video overlay */ struct v4l2_format overlay_fmt_out; /* set_format/get_format video overlay output */ - struct v4l2_tuner tuner; /* set_tuner/get_tuner */ + struct v4l2_tuner tuner; /* set_freq/get_freq */ + struct v4l2_modulator modulator;/* set_freq/get_freq */ struct v4l2_capability vcap; /* list_cap */ struct v4l2_input vin; /* list_inputs */ struct v4l2_output vout; /* list_outputs */ @@ -1459,6 +1464,7 @@ int main(int argc, char **argv) memset(&overlay_fmt_out, 0, sizeof(overlay_fmt_out)); memset(&raw_fmt_out, 0, sizeof(raw_fmt_out)); memset(&tuner, 0, sizeof(tuner)); + memset(&modulator, 0, sizeof(modulator)); memset(&vcap, 0, sizeof(vcap)); memset(&vin, 0, sizeof(vin)); memset(&vout, 0, sizeof(vout)); @@ -1768,6 +1774,10 @@ int main(int argc, char **argv) txsubchans = V4L2_TUNER_SUB_MONO; else if (!strcmp(optarg, "mono-sap")) txsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_SAP; + else if (!strcmp(optarg, "stereo-rds")) + txsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_RDS; + else if (!strcmp(optarg, "mono-rds")) + txsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_RDS; else { fprintf(stderr, "Unknown txsubchans value\n"); usage(); @@ -1978,11 +1988,17 @@ int main(int argc, char **argv) if (options[OptSetFreq]) { double fac = 16; - if (doioctl(fd, VIDIOC_G_TUNER, &tuner, "VIDIOC_G_TUNER") == 0) { - fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16; + if (capabilities & V4L2_CAP_MODULATOR) { + if (doioctl(fd, VIDIOC_G_MODULATOR, &modulator, "VIDIOC_G_MODULATOR") == 0) + fac = (modulator.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16; + } else { + vf.type = V4L2_TUNER_ANALOG_TV; + if (doioctl(fd, VIDIOC_G_TUNER, &tuner, "VIDIOC_G_TUNER") == 0) { + fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16; + vf.type = tuner.type; + } } vf.tuner = 0; - vf.type = tuner.type; vf.frequency = __u32(freq * fac); if (doioctl(fd, VIDIOC_S_FREQUENCY, &vf, "VIDIOC_S_FREQUENCY") == 0) @@ -2468,6 +2484,16 @@ set_vid_fmt_error: if (options[OptGetFreq]) { double fac = 16; + if (capabilities & V4L2_CAP_MODULATOR) { + if (doioctl(fd, VIDIOC_G_MODULATOR, &modulator, "VIDIOC_G_MODULATOR") == 0) + fac = (modulator.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16; + } else { + vf.type = V4L2_TUNER_ANALOG_TV; + if (doioctl(fd, VIDIOC_G_TUNER, &tuner, "VIDIOC_G_TUNER") == 0) { + fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16; + vf.type = tuner.type; + } + } if (doioctl(fd, VIDIOC_G_TUNER, &tuner, "VIDIOC_G_TUNER") == 0) { fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16; } -- cgit v1.2.3 From 83670264a7c9fca11f962b5b7f344e0909433439 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 2 Aug 2009 12:07:00 +0200 Subject: v4l2-ctl: add support for string controls From: Hans Verkuil Add support for string controls to v4l2-ctl. Also refactor the code to generalize the handling of control classes. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/v4l2-ctl.cpp | 227 ++++++++++++++++++++++++++------------------ 1 file changed, 136 insertions(+), 91 deletions(-) diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp index 70b85d0d0..955b95be0 100644 --- a/v4l2-apps/util/v4l2-ctl.cpp +++ b/v4l2-apps/util/v4l2-ctl.cpp @@ -148,20 +148,17 @@ static int verbose; static unsigned capabilities; -typedef std::vector ctrl_list; -static ctrl_list user_ctrls; -static ctrl_list mpeg_ctrls; -static ctrl_list camera_ctrls; +typedef std::map > class2ctrls_map; -typedef std::map ctrl_strmap; -static ctrl_strmap ctrl_str2id; +typedef std::map ctrl_qmap; +static ctrl_qmap ctrl_str2q; typedef std::map ctrl_idmap; static ctrl_idmap ctrl_id2str; typedef std::list ctrl_get_list; static ctrl_get_list get_ctrls; -typedef std::map ctrl_set_map; +typedef std::map ctrl_set_map; static ctrl_set_map set_ctrls; typedef std::vector dev_vec; @@ -583,6 +580,43 @@ static std::string name2var(unsigned char *name) return s; } +static std::string safename(const unsigned char *name) +{ + std::string s; + + while (*name) { + if (*name == '\n') { + s += "\\n"; + } + else if (*name == '\r') { + s += "\\r"; + } + else if (*name == '\f') { + s += "\\f"; + } + else if (*name == '\\') { + s += "\\\\"; + } + else if ((*name & 0x7f) < 0x20) { + char buf[3]; + + sprintf(buf, "%02x", *name); + s += "\\x"; + s += buf; + } + else { + s += *name; + } + name++; + } + return s; +} + +static std::string safename(const char *name) +{ + return safename((const unsigned char *)name); +} + static void print_qctrl(int fd, struct v4l2_queryctrl *queryctrl, struct v4l2_ext_control *ctrl, int show_menus) { @@ -602,6 +636,12 @@ static void print_qctrl(int fd, struct v4l2_queryctrl *queryctrl, case V4L2_CTRL_TYPE_INTEGER64: printf("%31s (int64): value=%lld", s.c_str(), ctrl->value64); break; + case V4L2_CTRL_TYPE_STRING: + printf("%31s (str) : min=%d max=%d step=%d value='%s'", + s.c_str(), + queryctrl->minimum, queryctrl->maximum, + queryctrl->step, safename(ctrl->string).c_str()); + break; case V4L2_CTRL_TYPE_BOOLEAN: printf("%31s (bool) : default=%d value=%d", s.c_str(), @@ -659,6 +699,11 @@ static int print_control(int fd, struct v4l2_queryctrl &qctrl, int show_menus) ctrls.controls = &ext_ctrl; if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_USER && qctrl.id < V4L2_CID_PRIVATE_BASE) { + if (qctrl.type == V4L2_CTRL_TYPE_STRING) { + ext_ctrl.size = qctrl.maximum + 1; + ext_ctrl.string = (char *)malloc(ext_ctrl.size); + ext_ctrl.string[0] = 0; + } if (ioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls)) { printf("error %d getting ext_ctrl %s\n", errno, qctrl.name); @@ -675,6 +720,8 @@ static int print_control(int fd, struct v4l2_queryctrl &qctrl, int show_menus) ext_ctrl.value = ctrl.value; } print_qctrl(fd, &qctrl, &ext_ctrl, show_menus); + if (qctrl.type == V4L2_CTRL_TYPE_STRING) + free(ext_ctrl.string); return 1; } @@ -708,7 +755,7 @@ static void find_controls(int fd) while (ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0) { if (qctrl.type != V4L2_CTRL_TYPE_CTRL_CLASS && !(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) { - ctrl_str2id[name2var(qctrl.name)] = qctrl.id; + ctrl_str2q[name2var(qctrl.name)] = qctrl; ctrl_id2str[qctrl.id] = name2var(qctrl.name); } qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; @@ -719,14 +766,14 @@ static void find_controls(int fd) qctrl.id = id; if (ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0 && !(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) { - ctrl_str2id[name2var(qctrl.name)] = qctrl.id; + ctrl_str2q[name2var(qctrl.name)] = qctrl; ctrl_id2str[qctrl.id] = name2var(qctrl.name); } } for (qctrl.id = V4L2_CID_PRIVATE_BASE; ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0; qctrl.id++) { if (!(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) { - ctrl_str2id[name2var(qctrl.name)] = qctrl.id; + ctrl_str2q[name2var(qctrl.name)] = qctrl; ctrl_id2str[qctrl.id] = name2var(qctrl.name); } } @@ -1926,13 +1973,13 @@ int main(int argc, char **argv) capabilities = vcap.capabilities; find_controls(fd); for (ctrl_get_list::iterator iter = get_ctrls.begin(); iter != get_ctrls.end(); ++iter) { - if (ctrl_str2id.find(*iter) == ctrl_str2id.end()) { + if (ctrl_str2q.find(*iter) == ctrl_str2q.end()) { fprintf(stderr, "unknown control '%s'\n", (*iter).c_str()); exit(1); } } for (ctrl_set_map::iterator iter = set_ctrls.begin(); iter != set_ctrls.end(); ++iter) { - if (ctrl_str2id.find(iter->first) == ctrl_str2id.end()) { + if (ctrl_str2q.find(iter->first) == ctrl_str2q.end()) { fprintf(stderr, "unknown control '%s'\n", iter->first.c_str()); exit(1); } @@ -2261,60 +2308,61 @@ set_vid_fmt_error: if (options[OptSetCtrl] && !set_ctrls.empty()) { struct v4l2_ext_controls ctrls = { 0 }; + class2ctrls_map class2ctrls; for (ctrl_set_map::iterator iter = set_ctrls.begin(); iter != set_ctrls.end(); ++iter) { struct v4l2_ext_control ctrl = { 0 }; - ctrl.id = ctrl_str2id[iter->first]; - ctrl.value = strtol(iter->second.c_str(), NULL, 0); - if (V4L2_CTRL_ID2CLASS(ctrl.id) == V4L2_CTRL_CLASS_MPEG) - mpeg_ctrls.push_back(ctrl); - else if (V4L2_CTRL_ID2CLASS(ctrl.id) == V4L2_CTRL_CLASS_CAMERA) - camera_ctrls.push_back(ctrl); - else - user_ctrls.push_back(ctrl); - } - for (unsigned i = 0; i < user_ctrls.size(); i++) { - struct v4l2_control ctrl; - - ctrl.id = user_ctrls[i].id; - ctrl.value = user_ctrls[i].value; - if (doioctl(fd, VIDIOC_S_CTRL, &ctrl, "VIDIOC_S_CTRL")) { - fprintf(stderr, "%s: %s\n", - ctrl_id2str[ctrl.id].c_str(), - strerror(errno)); - } - } - if (mpeg_ctrls.size()) { - ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; - ctrls.count = mpeg_ctrls.size(); - ctrls.controls = &mpeg_ctrls[0]; - if (doioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls, "VIDIOC_S_EXT_CTRLS")) { - if (ctrls.error_idx >= ctrls.count) { - fprintf(stderr, "Error setting MPEG controls: %s\n", - strerror(errno)); + ctrl.id = ctrl_str2q[iter->first].id; + if (ctrl_str2q[iter->first].type == V4L2_CTRL_TYPE_STRING) { + unsigned len = iter->second.length(); + unsigned maxlen = ctrl_str2q[iter->first].maximum; + + ctrl.size = maxlen + 1; + ctrl.string = (char *)malloc(ctrl.size); + if (len > maxlen) { + memcpy(ctrl.string, iter->second.c_str(), maxlen); + ctrl.string[maxlen] = 0; } else { - fprintf(stderr, "%s: %s\n", - ctrl_id2str[mpeg_ctrls[ctrls.error_idx].id].c_str(), - strerror(errno)); + strcpy(ctrl.string, iter->second.c_str()); } + } else { + ctrl.value = strtol(iter->second.c_str(), NULL, 0); } + class2ctrls[V4L2_CTRL_ID2CLASS(ctrl.id)].push_back(ctrl); } - if (camera_ctrls.size()) { - ctrls.ctrl_class = V4L2_CTRL_CLASS_CAMERA; - ctrls.count = camera_ctrls.size(); - ctrls.controls = &camera_ctrls[0]; - if (doioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls, "VIDIOC_S_EXT_CTRLS")) { - if (ctrls.error_idx >= ctrls.count) { - fprintf(stderr, "Error setting CAMERA controls: %s\n", - strerror(errno)); + for (class2ctrls_map::iterator iter = class2ctrls.begin(); + iter != class2ctrls.end(); ++iter) { + if (iter->first == V4L2_CTRL_CLASS_USER) { + for (unsigned i = 0; i < iter->second.size(); i++) { + struct v4l2_control ctrl; + + ctrl.id = iter->second[i].id; + ctrl.value = iter->second[i].value; + if (doioctl(fd, VIDIOC_S_CTRL, &ctrl, "VIDIOC_S_CTRL")) { + fprintf(stderr, "%s: %s\n", + ctrl_id2str[ctrl.id].c_str(), + strerror(errno)); + } } - else { - fprintf(stderr, "%s: %s\n", - ctrl_id2str[camera_ctrls[ctrls.error_idx].id].c_str(), - strerror(errno)); + continue; + } + if (iter->second.size()) { + ctrls.ctrl_class = iter->first; + ctrls.count = iter->second.size(); + ctrls.controls = &iter->second[0]; + if (doioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls, "VIDIOC_S_EXT_CTRLS")) { + if (ctrls.error_idx >= ctrls.count) { + fprintf(stderr, "Error setting MPEG controls: %s\n", + strerror(errno)); + } + else { + fprintf(stderr, "%s: %s\n", + ctrl_id2str[iter->second[ctrls.error_idx].id].c_str(), + strerror(errno)); + } } } } @@ -2585,49 +2633,46 @@ set_vid_fmt_error: if (options[OptGetCtrl] && !get_ctrls.empty()) { struct v4l2_ext_controls ctrls = { 0 }; + class2ctrls_map class2ctrls; - mpeg_ctrls.clear(); - camera_ctrls.clear(); - user_ctrls.clear(); for (ctrl_get_list::iterator iter = get_ctrls.begin(); iter != get_ctrls.end(); ++iter) { struct v4l2_ext_control ctrl = { 0 }; - ctrl.id = ctrl_str2id[*iter]; - if (V4L2_CTRL_ID2CLASS(ctrl.id) == V4L2_CTRL_CLASS_MPEG) - mpeg_ctrls.push_back(ctrl); - else if (V4L2_CTRL_ID2CLASS(ctrl.id) == V4L2_CTRL_CLASS_CAMERA) - camera_ctrls.push_back(ctrl); - else - user_ctrls.push_back(ctrl); - } - for (unsigned i = 0; i < user_ctrls.size(); i++) { - struct v4l2_control ctrl; - - ctrl.id = user_ctrls[i].id; - doioctl(fd, VIDIOC_G_CTRL, &ctrl, "VIDIOC_G_CTRL"); - printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value); - } - if (mpeg_ctrls.size()) { - ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; - ctrls.count = mpeg_ctrls.size(); - ctrls.controls = &mpeg_ctrls[0]; - doioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls, "VIDIOC_G_EXT_CTRLS"); - for (unsigned i = 0; i < mpeg_ctrls.size(); i++) { - struct v4l2_ext_control ctrl = mpeg_ctrls[i]; - - printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value); + ctrl.id = ctrl_str2q[*iter].id; + if (ctrl_str2q[*iter].type == V4L2_CTRL_TYPE_STRING) { + ctrl.size = ctrl_str2q[*iter].maximum + 1; + ctrl.string = (char *)malloc(ctrl.size); + ctrl.string[0] = 0; } + class2ctrls[V4L2_CTRL_ID2CLASS(ctrl.id)].push_back(ctrl); } - if (camera_ctrls.size()) { - ctrls.ctrl_class = V4L2_CTRL_CLASS_CAMERA; - ctrls.count = camera_ctrls.size(); - ctrls.controls = &camera_ctrls[0]; - doioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls, "VIDIOC_G_EXT_CTRLS"); - for (unsigned i = 0; i < camera_ctrls.size(); i++) { - struct v4l2_ext_control ctrl = camera_ctrls[i]; - - printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value); + for (class2ctrls_map::iterator iter = class2ctrls.begin(); + iter != class2ctrls.end(); ++iter) { + if (iter->first == V4L2_CTRL_CLASS_USER) { + for (unsigned i = 0; i < iter->second.size(); i++) { + struct v4l2_control ctrl; + + ctrl.id = iter->second[i].id; + doioctl(fd, VIDIOC_G_CTRL, &ctrl, "VIDIOC_G_CTRL"); + printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value); + } + continue; + } + if (iter->second.size()) { + ctrls.ctrl_class = iter->first; + ctrls.count = iter->second.size(); + ctrls.controls = &iter->second[0]; + doioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls, "VIDIOC_G_EXT_CTRLS"); + for (unsigned i = 0; i < iter->second.size(); i++) { + struct v4l2_ext_control ctrl = iter->second[i]; + + if (ctrl_str2q[ctrl_id2str[ctrl.id]].type == V4L2_CTRL_TYPE_STRING) + printf("%s: '%s'\n", ctrl_id2str[ctrl.id].c_str(), + safename(ctrl.string).c_str()); + else + printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value); + } } } } -- cgit v1.2.3 From 7c46bce9a57145883969881ed2dc1d95117b5d21 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 8 Aug 2009 13:34:18 +0200 Subject: v4l2-subdev.h: Add g/s_modulator callbacks to subdev api From: Eduardo Valentin Priority: normal Signed-off-by: Eduardo Valentin Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/include/media/v4l2-subdev.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux/include/media/v4l2-subdev.h b/linux/include/media/v4l2-subdev.h index 89a39ce17..d411345f2 100644 --- a/linux/include/media/v4l2-subdev.h +++ b/linux/include/media/v4l2-subdev.h @@ -137,6 +137,8 @@ struct v4l2_subdev_tuner_ops { int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq); int (*g_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt); int (*s_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt); + int (*g_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm); + int (*s_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm); int (*s_type_addr)(struct v4l2_subdev *sd, struct tuner_setup *type); int (*s_config)(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *config); int (*s_standby)(struct v4l2_subdev *sd); -- cgit v1.2.3 From 868fb03c63f6b85bb27bebc740c70993bb7ee3db Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 8 Aug 2009 13:38:58 +0200 Subject: v4l2: video device: Add V4L2_CTRL_CLASS_FM_TX controls From: Eduardo Valentin This patch adds a new class of extended controls. This class is intended to support FM Radio Modulators properties such as: rds, audio limiters, audio compression, pilot tone generation, tuning power levels and preemphasis properties. Priority: normal Signed-off-by: Eduardo Valentin Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/include/linux/videodev2.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index 409c505ff..6fc44b733 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -817,6 +817,7 @@ struct v4l2_ext_controls { #define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ #define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */ #define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ +#define V4L2_CTRL_CLASS_FM_TX 0x009b0000 /* FM Modulator control class */ #define V4L2_CTRL_ID_MASK (0x0fffffff) #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) @@ -1157,6 +1158,39 @@ enum v4l2_exposure_auto_type { #define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) +/* FM Modulator class control IDs */ +#define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) +#define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1) + +#define V4L2_CID_RDS_TX_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 1) +#define V4L2_CID_RDS_TX_PI (V4L2_CID_FM_TX_CLASS_BASE + 2) +#define V4L2_CID_RDS_TX_PTY (V4L2_CID_FM_TX_CLASS_BASE + 3) +#define V4L2_CID_RDS_TX_PS_NAME (V4L2_CID_FM_TX_CLASS_BASE + 5) +#define V4L2_CID_RDS_TX_RADIO_TEXT (V4L2_CID_FM_TX_CLASS_BASE + 6) + +#define V4L2_CID_AUDIO_LIMITER_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 64) +#define V4L2_CID_AUDIO_LIMITER_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 65) +#define V4L2_CID_AUDIO_LIMITER_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 66) + +#define V4L2_CID_AUDIO_COMPRESSION_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 80) +#define V4L2_CID_AUDIO_COMPRESSION_GAIN (V4L2_CID_FM_TX_CLASS_BASE + 81) +#define V4L2_CID_AUDIO_COMPRESSION_THRESHOLD (V4L2_CID_FM_TX_CLASS_BASE + 82) +#define V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME (V4L2_CID_FM_TX_CLASS_BASE + 83) +#define V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 84) + +#define V4L2_CID_PILOT_TONE_ENABLED (V4L2_CID_FM_TX_CLASS_BASE + 96) +#define V4L2_CID_PILOT_TONE_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 97) +#define V4L2_CID_PILOT_TONE_FREQUENCY (V4L2_CID_FM_TX_CLASS_BASE + 98) + +#define V4L2_CID_TUNE_PREEMPHASIS (V4L2_CID_FM_TX_CLASS_BASE + 112) +enum v4l2_preemphasis { + V4L2_PREEMPHASIS_DISABLED = 0, + V4L2_PREEMPHASIS_50_uS = 1, + V4L2_PREEMPHASIS_75_uS = 2, +}; +#define V4L2_CID_TUNE_POWER_LEVEL (V4L2_CID_FM_TX_CLASS_BASE + 113) +#define V4L2_CID_TUNE_ANTENNA_CAPACITOR (V4L2_CID_FM_TX_CLASS_BASE + 114) + /* * T U N I N G */ -- cgit v1.2.3 From 5f00630df328d9e746ca5f61f3413f5c80743663 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 11 Aug 2009 23:49:12 +0200 Subject: v4l2: video device: Add FM TX controls default configurations From: Eduardo Valentin This patch adds basic configurations for FM TX extended controls. That includes controls names, menu strings, pointer identification, type classification and flags configuration. Priority: normal Signed-off-by: Eduardo Valentin Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-common.c | 50 +++++++++++++++++++++++++ linux/drivers/media/video/v4l2-compat-ioctl32.c | 14 ++++--- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 51c080c13..203945635 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -343,6 +343,12 @@ const char **v4l2_ctrl_get_menu(u32 id) "Sepia", NULL }; + static const char *tune_preemphasis[] = { + "No preemphasis", + "50 useconds", + "75 useconds", + NULL, + }; switch (id) { case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: @@ -381,6 +387,8 @@ const char **v4l2_ctrl_get_menu(u32 id) return camera_exposure_auto; case V4L2_CID_COLORFX: return colorfx; + case V4L2_CID_TUNE_PREEMPHASIS: + return tune_preemphasis; default: return NULL; } @@ -479,6 +487,28 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_ZOOM_CONTINUOUS: return "Zoom, Continuous"; case V4L2_CID_PRIVACY: return "Privacy"; + /* FM Radio Modulator control */ + case V4L2_CID_FM_TX_CLASS: return "FM Radio Modulator Controls"; + case V4L2_CID_RDS_TX_DEVIATION: return "RDS Signal Deviation"; + case V4L2_CID_RDS_TX_PI: return "RDS Program ID"; + case V4L2_CID_RDS_TX_PTY: return "RDS Program Type"; + case V4L2_CID_RDS_TX_PS_NAME: return "RDS PS Name"; + case V4L2_CID_RDS_TX_RADIO_TEXT: return "RDS Radio Text"; + case V4L2_CID_AUDIO_LIMITER_ENABLED: return "Audio Limiter Feature Enabled"; + case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time"; + case V4L2_CID_AUDIO_LIMITER_DEVIATION: return "Audio Limiter Deviation"; + case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Feature Enabled"; + case V4L2_CID_AUDIO_COMPRESSION_GAIN: return "Audio Compression Gain"; + case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold"; + case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time"; + case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: return "Audio Compression Release Time"; + case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled"; + case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation"; + case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency"; + case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings"; + case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level"; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor"; + default: return NULL; } @@ -511,6 +541,9 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_EXPOSURE_AUTO_PRIORITY: case V4L2_CID_FOCUS_AUTO: case V4L2_CID_PRIVACY: + case V4L2_CID_AUDIO_LIMITER_ENABLED: + case V4L2_CID_AUDIO_COMPRESSION_ENABLED: + case V4L2_CID_PILOT_TONE_ENABLED: qctrl->type = V4L2_CTRL_TYPE_BOOLEAN; min = 0; max = step = 1; @@ -539,12 +572,18 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_MPEG_STREAM_VBI_FMT: case V4L2_CID_EXPOSURE_AUTO: case V4L2_CID_COLORFX: + case V4L2_CID_TUNE_PREEMPHASIS: qctrl->type = V4L2_CTRL_TYPE_MENU; step = 1; break; + case V4L2_CID_RDS_TX_PS_NAME: + case V4L2_CID_RDS_TX_RADIO_TEXT: + qctrl->type = V4L2_CTRL_TYPE_STRING; + break; case V4L2_CID_USER_CLASS: case V4L2_CID_CAMERA_CLASS: case V4L2_CID_MPEG_CLASS: + case V4L2_CID_FM_TX_CLASS: qctrl->type = V4L2_CTRL_TYPE_CTRL_CLASS; qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; min = max = step = def = 0; @@ -573,6 +612,17 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste case V4L2_CID_BLUE_BALANCE: case V4L2_CID_GAMMA: case V4L2_CID_SHARPNESS: + case V4L2_CID_RDS_TX_DEVIATION: + case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: + case V4L2_CID_AUDIO_LIMITER_DEVIATION: + case V4L2_CID_AUDIO_COMPRESSION_GAIN: + case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: + case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: + case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: + case V4L2_CID_PILOT_TONE_DEVIATION: + case V4L2_CID_PILOT_TONE_FREQUENCY: + case V4L2_CID_TUNE_POWER_LEVEL: + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; break; case V4L2_CID_PAN_RELATIVE: diff --git a/linux/drivers/media/video/v4l2-compat-ioctl32.c b/linux/drivers/media/video/v4l2-compat-ioctl32.c index cd45c09ff..3454e7c64 100644 --- a/linux/drivers/media/video/v4l2-compat-ioctl32.c +++ b/linux/drivers/media/video/v4l2-compat-ioctl32.c @@ -621,14 +621,16 @@ struct v4l2_ext_control32 { for now this will do. */ /* Return non-zero if this control is a pointer type. Currently only - * type STRING is a pointer type. - * - * Note that there are currently no controls of this type, but at least the - * compat32 code is in place to properly handle such controls. Please - * remove this note once the first pointer controls are added. */ + type STRING is a pointer type. */ static inline int ctrl_is_pointer(u32 id) { - return 0; + switch (id) { + case V4L2_CID_RDS_TX_PS_NAME: + case V4L2_CID_RDS_TX_RADIO_TEXT: + return 1; + default: + return 0; + } } static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) -- cgit v1.2.3 From 70c355bfe650b41cd70b5b55c2cc90cd810d0f13 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 8 Aug 2009 13:42:52 +0200 Subject: v4l2-spec: Add documentation description for FM TX extended control class From: Eduardo Valentin This single patch adds documentation description for FM Modulator (FM TX) Extended Control Class and its Control IDs. The text was added under "Extended Controls" section. The vidioc-g-ext-ctrls.sgml file was updated as well. Priority: normal Signed-off-by: Eduardo Valentin Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- v4l2-spec/Makefile | 1 + v4l2-spec/controls.sgml | 215 ++++++++++++++++++++++++++++++++++++++ v4l2-spec/vidioc-g-ext-ctrls.sgml | 7 ++ 3 files changed, 223 insertions(+) diff --git a/v4l2-spec/Makefile b/v4l2-spec/Makefile index 3b4c321c4..a88420286 100644 --- a/v4l2-spec/Makefile +++ b/v4l2-spec/Makefile @@ -245,6 +245,7 @@ ENUMS = \ v4l2_power_line_frequency \ v4l2_priority \ v4l2_tuner_type \ + v4l2_preemphasis \ STRUCTS = \ v4l2_audio \ diff --git a/v4l2-spec/controls.sgml b/v4l2-spec/controls.sgml index dbe4f6f86..869198601 100644 --- a/v4l2-spec/controls.sgml +++ b/v4l2-spec/controls.sgml @@ -458,6 +458,12 @@ video is actually encoded into that format. Unfortunately, the original control API lacked some features needed for these new uses and so it was extended into the (not terribly originally named) extended control API. + + Even though the MPEG encoding API was the first effort +to use the Extended Control API, nowadays there are also other classes +of Extended Controls, such as Camera Controls and FM Transmitter Controls. +The Extended Controls API as well as all Extended Controls classes are +described in the following text.
@@ -1823,6 +1829,215 @@ be used, for example, to filter out the fluorescent light component.
+ +
+ FM Transmitter Control Reference + + The FM Transmitter (FM_TX) class includes controls for common features of +FM transmissions capable devices. Currently this class includes parameters for audio +compression, pilot tone generation, audio deviation limiter, RDS transmission and +tuning power features. + + + FM_TX Control IDs + + + + + + + + + + + ID + Type + Description + + + + + + V4L2_CID_FM_TX_CLASS  + class + The FM_TX class +descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a +description of this control class. + + + V4L2_CID_RDS_TX_DEVIATION  + integer + + Configures RDS signal frequency deviation level in Hz. +The range and step are driver-specific. + + + V4L2_CID_RDS_TX_PI  + integer + + Sets the RDS Programme Identification field +for transmission. + + + V4L2_CID_RDS_TX_PTY  + integer + + Sets the RDS Programme Type field for transmission. +This encodes up to 31 pre-defined programme types. + + + V4L2_CID_RDS_TX_PS_NAME  + string + + Sets the Programme Service name (PS_NAME) for transmission. +It is intended for static display on a receiver. It is the primary aid to listeners in programme service +identification and selection. In Annex E of , the RDS specification, +there is a full description of the correct character encoding for Programme Service name strings. +Also from RDS specification, PS is usually a single eight character text. However, it is also possible +to find receivers which can scroll strings sized as 8 x N characters. So, this control must be configured +with steps of 8 characters. The result is it must always contain a string with size multiple of 8. + + + V4L2_CID_RDS_TX_RADIO_TEXT  + string + + Sets the Radio Text info for transmission. It is a textual description of +what is being broadcasted. RDS Radio Text can be applied when broadcaster wishes to transmit longer PS names, +programme-related information or any other text. In these cases, RadioText should be used in addition to +V4L2_CID_RDS_TX_PS_NAME. The encoding for Radio Text strings is also fully described +in Annex E of . The length of Radio Text strings depends on which RDS Block is being +used to transmit it, either 32 (2A block) or 64 (2B block). However, it is also possible +to find receivers which can scroll strings sized as 32 x N or 64 x N characters. So, this control must be configured +with steps of 32 or 64 characters. The result is it must always contain a string with size multiple of 32 or 64. + + + V4L2_CID_AUDIO_LIMITER_ENABLED  + boolean + + Enables or disables the audio deviation limiter feature. +The limiter is useful when trying to maximize the audio volume, minimize receiver-generated +distortion and prevent overmodulation. + + + + V4L2_CID_AUDIO_LIMITER_RELEASE_TIME  + integer + + Sets the audio deviation limiter feature release time. +Unit is in useconds. Step and range are driver-specific. + + + V4L2_CID_AUDIO_LIMITER_DEVIATION  + integer + + Configures audio frequency deviation level in Hz. +The range and step are driver-specific. + + + V4L2_CID_AUDIO_COMPRESSION_ENABLED  + boolean + + Enables or disables the audio compression feature. +This feature amplifies signals below the threshold by a fixed gain and compresses audio +signals above the threshold by the ratio of Threshold/(Gain + Threshold). + + + V4L2_CID_AUDIO_COMPRESSION_GAIN  + integer + + Sets the gain for audio compression feature. It is +a dB value. The range and step are driver-specific. + + + V4L2_CID_AUDIO_COMPRESSION_THRESHOLD  + integer + + Sets the threshold level for audio compression freature. +It is a dB value. The range and step are driver-specific. + + + V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME  + integer + + Sets the attack time for audio compression feature. +It is a useconds value. The range and step are driver-specific. + + + V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME  + integer + + Sets the release time for audio compression feature. +It is a useconds value. The range and step are driver-specific. + + + V4L2_CID_PILOT_TONE_ENABLED  + boolean + + Enables or disables the pilot tone generation feature. + + + V4L2_CID_PILOT_TONE_DEVIATION  + integer + + Configures pilot tone frequency deviation level. Unit is +in Hz. The range and step are driver-specific. + + + V4L2_CID_PILOT_TONE_FREQUENCY  + integer + + Configures pilot tone frequency value. Unit is +in Hz. The range and step are driver-specific. + + + V4L2_CID_TUNE_PREEMPHASIS  + integer + + Configures the pre-emphasis value for broadcasting. +A pre-emphasis filter is applied to the broadcast to accentuate the high audio frequencies. +Depending on the region, a time constant of either 50 or 75 useconds is used. The enum v4l2_preemphasis +defines possible values for pre-emphasis. Here they are: + + + + + V4L2_PREEMPHASIS_DISABLED  + No pre-emphasis is applied. + + + V4L2_PREEMPHASIS_50_uS  + A pre-emphasis of 50 uS is used. + + + V4L2_PREEMPHASIS_75_uS  + A pre-emphasis of 75 uS is used. + + + + + + + V4L2_CID_TUNE_POWER_LEVEL  + integer + + Sets the output power level for signal transmission. +Unit is in dBuV. Range and step are driver-specific. + + + V4L2_CID_TUNE_ANTENNA_CAPACITOR  + integer + + This selects the value of antenna tuning capacitor +manually or automatically if set to zero. Unit, range and step are driver-specific. + + + + +
+ +For more details about RDS specification, refer to + document, from CENELEC. +
+ + 0.29 + 2009-08-26 + ev + Added documentation for string controls and for FM Transmitter controls. + + 0.28 2009-08-26 diff --git a/v4l2-spec/vidioc-queryctrl.sgml b/v4l2-spec/vidioc-queryctrl.sgml index 413930226..abf56b22e 100644 --- a/v4l2-spec/vidioc-queryctrl.sgml +++ b/v4l2-spec/vidioc-queryctrl.sgml @@ -306,15 +306,15 @@ and step size cannot be queried. V4L2_CTRL_TYPE_STRING - >=0 - >=1 - >=0 + ≥ 0 + ≥ 1 + ≥ 0 The minimum and maximum string lengths. The step size means that the string must be (minimum + N * step) characters long for -N >= 0. These lengths do not include the terminating zero, so in order to +N ≥ 0. These lengths do not include the terminating zero, so in order to pass a string of length 8 to &VIDIOC-S-EXT-CTRLS; you need to set the size field of &v4l2-ext-control; to 9. For &VIDIOC-G-EXT-CTRLS; you can -set the size field to maximum+1. +set the size field to maximum + 1. Which character encoding is used will depend on the string control itself and should be part of the control documentation. -- cgit v1.2.3 From 2209c0b22bafab863c618952d3d9a076eaff5786 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Aug 2009 22:32:44 +0200 Subject: v4l2-ctl: add support for enumerating frame sizes and intervals From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/util/v4l2-ctl.cpp | 209 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 202 insertions(+), 7 deletions(-) diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp index 955b95be0..5b38e37b3 100644 --- a/v4l2-apps/util/v4l2-ctl.cpp +++ b/v4l2-apps/util/v4l2-ctl.cpp @@ -105,6 +105,9 @@ enum Option { OptStreamOn, OptListStandards, OptListFormats, + OptListFormatsExt, + OptListFrameSizes, + OptListFrameIntervals, OptLogStatus, OptVerbose, OptSilent, @@ -221,6 +224,9 @@ static struct option long_options[] = { {"streamon", no_argument, 0, OptStreamOn}, {"list-standards", no_argument, 0, OptListStandards}, {"list-formats", no_argument, 0, OptListFormats}, + {"list-formats-ext", no_argument, 0, OptListFormatsExt}, + {"list-framesizes", required_argument, 0, OptListFrameSizes}, + {"list-frameintervals", required_argument, 0, OptListFrameIntervals}, {"get-standard", no_argument, 0, OptGetStandard}, {"set-standard", required_argument, 0, OptSetStandard}, {"get-parm", no_argument, 0, OptGetParm}, @@ -319,6 +325,18 @@ static void usage(void) " set the audio mode of the tuner [VIDIOC_S_TUNER]\n" " Possible values: mono, stereo, lang2, lang1, bilingual\n" " --list-formats display supported video formats [VIDIOC_ENUM_FMT]\n" + " --list-formats-ext display supported video formats including frame sizes\n" + " and intervals\n" + " --list-framesizes=\n" + " list supported framesizes for pixelformat \n" + " [VIDIOC_ENUM_FRAMESIZES]\n" + " pixelformat is either the format index as reported by\n" + " --list-formats, or the fourcc value as a string\n" + " --list-frameintervals=width=,height=,pixelformat=\n" + " list supported frame intervals for pixelformat and\n" + " the given width and height [VIDIOC_ENUM_FRAMEINTERVALS]\n" + " pixelformat is either the format index as reported by\n" + " --list-formats, or the fourcc value as a string\n" " -V, --get-fmt-video\n" " query the video capture format [VIDIOC_G_FMT]\n" " -v, --set-fmt-video=width=,height=,pixelformat=\n" @@ -951,6 +969,72 @@ static void printfmt(const struct v4l2_format &vfmt) } } +static std::string frmtype2s(unsigned type) +{ + static const char *types[] = { + "Unknown", + "Discrete", + "Continuous", + "Stepwise" + }; + + if (type > 3) + type = 0; + return types[type]; +} + +static std::string fract2sec(const struct v4l2_fract &f) +{ + char buf[100]; + + sprintf(buf, "%.3f s", (1.0 * f.numerator) / f.denominator); + return buf; +} + +static std::string fract2fps(const struct v4l2_fract &f) +{ + char buf[100]; + + sprintf(buf, "%.3f fps", (1.0 * f.denominator) / f.numerator); + return buf; +} + +static void print_frmsize(const struct v4l2_frmsizeenum &frmsize, const char *prefix) +{ + printf("%s\tSize: %s ", prefix, frmtype2s(frmsize.type).c_str()); + if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + printf("%dx%d", frmsize.discrete.width, frmsize.discrete.height); + } else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { + printf("%dx%d - %dx%d with step %d/%d", + frmsize.stepwise.min_width, + frmsize.stepwise.min_height, + frmsize.stepwise.max_width, + frmsize.stepwise.max_height, + frmsize.stepwise.step_width, + frmsize.stepwise.step_height); + } + printf("\n"); +} + +static void print_frmival(const struct v4l2_frmivalenum &frmival, const char *prefix) +{ + printf("%s\tInterval: %s ", prefix, frmtype2s(frmival.type).c_str()); + if (frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { + printf("%s (%s)\n", fract2sec(frmival.discrete).c_str(), + fract2fps(frmival.discrete).c_str()); + } else if (frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { + printf("%s - %s with step %s\n", + fract2sec(frmival.stepwise.min).c_str(), + fract2sec(frmival.stepwise.max).c_str(), + fract2sec(frmival.stepwise.step).c_str()); + printf("%s\t : ", prefix); + printf("(%s - %s with step %s)\n", + fract2fps(frmival.stepwise.min).c_str(), + fract2fps(frmival.stepwise.max).c_str(), + fract2fps(frmival.stepwise.step).c_str()); + } +} + static void print_video_formats(int fd, enum v4l2_buf_type type) { struct v4l2_fmtdesc fmt; @@ -970,6 +1054,43 @@ static void print_video_formats(int fd, enum v4l2_buf_type type) } } +static void print_video_formats_ext(int fd, enum v4l2_buf_type type) +{ + struct v4l2_fmtdesc fmt; + struct v4l2_frmsizeenum frmsize; + struct v4l2_frmivalenum frmival; + + fmt.index = 0; + fmt.type = type; + while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) >= 0) { + printf("\tIndex : %d\n", fmt.index); + printf("\tType : %s\n", buftype2s(type).c_str()); + printf("\tPixel Format: '%s'", fcc2s(fmt.pixelformat).c_str()); + if (fmt.flags) + printf(" (compressed)"); + printf("\n"); + printf("\tName : %s\n", fmt.description); + frmsize.pixel_format = fmt.pixelformat; + frmsize.index = 0; + while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0) { + print_frmsize(frmsize, "\t"); + if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + frmival.index = 0; + frmival.pixel_format = fmt.pixelformat; + frmival.width = frmsize.discrete.width; + frmival.height = frmsize.discrete.height; + while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) >= 0) { + print_frmival(frmival, "\t\t"); + frmival.index++; + } + } + frmsize.index++; + } + printf("\n"); + fmt.index++; + } +} + static char *pts_to_string(char *str, unsigned long pts) { static char buf[256]; @@ -1441,6 +1562,17 @@ static enum v4l2_field parse_field(const char *s) return V4L2_FIELD_ANY; } +static __u32 find_pixel_format(int fd, unsigned index) +{ + struct v4l2_fmtdesc fmt; + + fmt.index = index; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (doioctl(fd, VIDIOC_ENUM_FMT, &fmt, "VIDIOC_ENUM_FMT")) + return 0; + return fmt.pixelformat; +} + int main(int argc, char **argv) { char *value, *subs; @@ -1479,6 +1611,8 @@ int main(int argc, char **argv) struct v4l2_output vout; /* list_outputs */ struct v4l2_audio vaudio; /* list audio inputs */ struct v4l2_audioout vaudout; /* audio outputs */ + struct v4l2_frmsizeenum frmsize;/* list frame sizes */ + struct v4l2_frmivalenum frmival;/* list frame intervals */ struct v4l2_rect vcrop; /* crop rect */ struct v4l2_rect vcrop_out; /* crop rect */ struct v4l2_rect vcrop_overlay; /* crop rect */ @@ -1517,6 +1651,8 @@ int main(int argc, char **argv) memset(&vout, 0, sizeof(vout)); memset(&vaudio, 0, sizeof(vaudio)); memset(&vaudout, 0, sizeof(vaudout)); + memset(&frmsize, 0, sizeof(frmsize)); + memset(&frmival, 0, sizeof(frmival)); memset(&vcrop, 0, sizeof(vcrop)); memset(&vcrop_out, 0, sizeof(vcrop_out)); memset(&vcrop_overlay, 0, sizeof(vcrop_overlay)); @@ -1710,6 +1846,41 @@ int main(int argc, char **argv) case OptOverlay: overlay = strtol(optarg, 0L, 0); break; + case OptListFrameSizes: + if (strlen(optarg) == 4) + frmsize.pixel_format = v4l2_fourcc(optarg[0], optarg[1], + optarg[2], optarg[3]); + else + frmsize.pixel_format = strtol(optarg, 0L, 0); + break; + case OptListFrameIntervals: + subs = optarg; + while (*subs != '\0') { + static const char *const subopts[] = { + "width", + "height", + "pixelformat", + NULL + }; + + switch (parse_subopt(&subs, subopts, &value)) { + case 0: + frmival.width = strtol(value, 0L, 0); + break; + case 1: + frmival.height = strtol(value, 0L, 0); + break; + case 2: + if (strlen(value) == 4) + frmival.pixel_format = + v4l2_fourcc(value[0], value[1], + value[2], value[3]); + else + frmival.pixel_format = strtol(value, 0L, 0); + break; + } + } + break; case OptSetCrop: parse_crop(optarg, set_crop, vcrop); break; @@ -2158,13 +2329,8 @@ int main(int argc, char **argv) if (set_fmts & FmtPixelFormat) { in_vfmt.fmt.pix.pixelformat = vfmt.fmt.pix.pixelformat; if (in_vfmt.fmt.pix.pixelformat < 256) { - struct v4l2_fmtdesc fmt; - - fmt.index = in_vfmt.fmt.pix.pixelformat; - fmt.type = in_vfmt.type; - if (doioctl(fd, VIDIOC_ENUM_FMT, &fmt, "VIDIOC_ENUM_FMT")) - goto set_vid_fmt_error; - in_vfmt.fmt.pix.pixelformat = fmt.pixelformat; + in_vfmt.fmt.pix.pixelformat = + find_pixel_format(fd, in_vfmt.fmt.pix.pixelformat); } } if (options[OptSetVideoFormat]) @@ -2842,6 +3008,35 @@ set_vid_fmt_error: print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_OVERLAY); } + if (options[OptListFormatsExt]) { + printf("ioctl: VIDIOC_ENUM_FMT\n"); + print_video_formats_ext(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE); + print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT); + print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_OVERLAY); + } + + if (options[OptListFrameSizes]) { + printf("ioctl: VIDIOC_ENUM_FRAMESIZES\n"); + if (frmsize.pixel_format < 256) + frmsize.pixel_format = find_pixel_format(fd, frmsize.pixel_format); + frmsize.index = 0; + while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0) { + print_frmsize(frmsize, ""); + frmsize.index++; + } + } + + if (options[OptListFrameIntervals]) { + printf("ioctl: VIDIOC_ENUM_FRAMEINTERVALS\n"); + if (frmival.pixel_format < 256) + frmival.pixel_format = find_pixel_format(fd, frmival.pixel_format); + frmival.index = 0; + while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) >= 0) { + print_frmival(frmival, ""); + frmival.index++; + } + } + if (options[OptGetSlicedVbiCap]) { struct v4l2_sliced_vbi_cap cap; -- cgit v1.2.3 From 5132986080f45c38e0a8f0677c61e5f4e280ea9a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Aug 2009 22:34:01 +0200 Subject: v4l2-sysfs-path: fix compile warning. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/util/v4l2-sysfs-path.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/util/v4l2-sysfs-path.c b/v4l2-apps/util/v4l2-sysfs-path.c index 2a6ab0cfc..4f0817017 100644 --- a/v4l2-apps/util/v4l2-sysfs-path.c +++ b/v4l2-apps/util/v4l2-sysfs-path.c @@ -245,13 +245,14 @@ void get_subdevs(char *path) char *s = strchr(entry->d_name, ':'); if (s) { printf("\t%s", entry->d_name); - if (!get_dev(entry->d_name, &major, &minor, extra)) + if (!get_dev(entry->d_name, &major, &minor, extra)) { if (*extra) printf(":%s (dev %d,%d)", extra, major, minor); else printf(" (dev %d,%d)", major, minor); + } printf("\n"); } } -- cgit v1.2.3 From 8b4cdbc446bbb6bcd5e0e92d49b195a6ef1c3a86 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 26 Aug 2009 22:44:46 +0200 Subject: versions.txt: av7110 no longer builds for kernels < 2.6.19. From: Hans Verkuil av7110_hw.c uses MODULE_FIRMWARE which didn't appear until 2.6.19. Priority: normal Signed-off-by: Hans Verkuil --- v4l/versions.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l/versions.txt b/v4l/versions.txt index 413ede9e8..d4c7bd380 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -79,6 +79,8 @@ VIDEO_USBVISION # Uses supports_autosuspend USB_MR800 USB_DSBR +# Uses MODULE_FIRMWARE +DVB_AV7110 # Uses remap_vmalloc_range() [2.6.18] -- cgit v1.2.3 From b98fedbf223090872b1b4b7ec8e89994b55fb9bb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Aug 2009 18:28:55 -0300 Subject: Fix a merge trouble From: Mauro Carvalho Chehab Unfortunately, mailimport added the new files at the wrong place. Fix it. Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/si4713.txt | 176 ++ linux/drivers/media/radio/radio-si4713.c | 367 ++++ linux/drivers/media/radio/si4713-i2c.c | 2067 ++++++++++++++++++++++ linux/drivers/media/radio/si4713-i2c.h | 237 +++ linux/include/media/radio-si4713.h | 30 + linux/include/media/si4713.h | 49 + linux/linux/Documentation/video4linux/si4713.txt | 176 -- linux/linux/drivers/media/radio/radio-si4713.c | 367 ---- linux/linux/drivers/media/radio/si4713-i2c.c | 2067 ---------------------- linux/linux/drivers/media/radio/si4713-i2c.h | 237 --- linux/linux/include/media/radio-si4713.h | 30 - linux/linux/include/media/si4713.h | 49 - 12 files changed, 2926 insertions(+), 2926 deletions(-) create mode 100644 linux/Documentation/video4linux/si4713.txt create mode 100644 linux/drivers/media/radio/radio-si4713.c create mode 100644 linux/drivers/media/radio/si4713-i2c.c create mode 100644 linux/drivers/media/radio/si4713-i2c.h create mode 100644 linux/include/media/radio-si4713.h create mode 100644 linux/include/media/si4713.h delete mode 100644 linux/linux/Documentation/video4linux/si4713.txt delete mode 100644 linux/linux/drivers/media/radio/radio-si4713.c delete mode 100644 linux/linux/drivers/media/radio/si4713-i2c.c delete mode 100644 linux/linux/drivers/media/radio/si4713-i2c.h delete mode 100644 linux/linux/include/media/radio-si4713.h delete mode 100644 linux/linux/include/media/si4713.h diff --git a/linux/Documentation/video4linux/si4713.txt b/linux/Documentation/video4linux/si4713.txt new file mode 100644 index 000000000..25abdb782 --- /dev/null +++ b/linux/Documentation/video4linux/si4713.txt @@ -0,0 +1,176 @@ +Driver for I2C radios for the Silicon Labs Si4713 FM Radio Transmitters + +Copyright (c) 2009 Nokia Corporation +Contact: Eduardo Valentin + + +Information about the Device +============================ +This chip is a Silicon Labs product. It is a I2C device, currently on 0x63 address. +Basically, it has transmission and signal noise level measurement features. + +The Si4713 integrates transmit functions for FM broadcast stereo transmission. +The chip also allows integrated receive power scanning to identify low signal +power FM channels. + +The chip is programmed using commands and responses. There are also several +properties which can change the behavior of this chip. + +Users must comply with local regulations on radio frequency (RF) transmission. + +Device driver description +========================= +There are two modules to handle this device. One is a I2C device driver +and the other is a platform driver. + +The I2C device driver exports a v4l2-subdev interface to the kernel. +All properties can also be accessed by v4l2 extended controls interface, by +using the v4l2-subdev calls (g_ext_ctrls, s_ext_ctrls). + +The platform device driver exports a v4l2 radio device interface to user land. +So, it uses the I2C device driver as a sub device in order to send the user +commands to the actual device. Basically it is a wrapper to the I2C device driver. + +Applications can use v4l2 radio API to specify frequency of operation, mute state, +etc. But mostly of its properties will be present in the extended controls. + +When the v4l2 mute property is set to 1 (true), the driver will turn the chip off. + +Properties description +====================== + +The properties can be accessed using v4l2 extended controls. +Here is an output from v4l2-ctl util: +/ # v4l2-ctl -d /dev/radio0 --all -L +Driver Info: + Driver name : radio-si4713 + Card type : Silicon Labs Si4713 Modulator + Bus info : + Driver version: 0 + Capabilities : 0x00080800 + RDS Output + Modulator +Audio output: 0 (FM Modulator Audio Out) +Frequency: 1408000 (88.000000 MHz) +Video Standard = 0x00000000 +Modulator: + Name : FM Modulator + Capabilities : 62.5 Hz stereo rds + Frequency range : 76.0 MHz - 108.0 MHz + Subchannel modulation: stereo+rds + +User Controls + + mute (bool) : default=1 value=0 + +FM Radio Modulator Controls + + rds_signal_deviation (int) : min=0 max=90000 step=10 default=200 value=200 flags=slider + rds_program_id (int) : min=0 max=65535 step=1 default=0 value=0 + rds_program_type (int) : min=0 max=31 step=1 default=0 value=0 + rds_ps_name (str) : min=0 max=96 step=8 value='si4713 ' + rds_radio_text (str) : min=0 max=384 step=32 value='' + audio_limiter_feature_enabled (bool) : default=1 value=1 + audio_limiter_release_time (int) : min=250 max=102390 step=50 default=5010 value=5010 flags=slider + audio_limiter_deviation (int) : min=0 max=90000 step=10 default=66250 value=66250 flags=slider +audio_compression_feature_enabl (bool) : default=1 value=1 + audio_compression_gain (int) : min=0 max=20 step=1 default=15 value=15 flags=slider + audio_compression_threshold (int) : min=-40 max=0 step=1 default=-40 value=-40 flags=slider + audio_compression_attack_time (int) : min=0 max=5000 step=500 default=0 value=0 flags=slider + audio_compression_release_time (int) : min=100000 max=1000000 step=100000 default=1000000 value=1000000 flags=slider + pilot_tone_feature_enabled (bool) : default=1 value=1 + pilot_tone_deviation (int) : min=0 max=90000 step=10 default=6750 value=6750 flags=slider + pilot_tone_frequency (int) : min=0 max=19000 step=1 default=19000 value=19000 flags=slider + pre_emphasis_settings (menu) : min=0 max=2 default=1 value=1 + tune_power_level (int) : min=0 max=120 step=1 default=88 value=88 flags=slider + tune_antenna_capacitor (int) : min=0 max=191 step=1 default=0 value=110 flags=slider +/ # + +Here is a summary of them: + +* Pilot is an audible tone sent by the device. + +pilot_frequency - Configures the frequency of the stereo pilot tone. +pilot_deviation - Configures pilot tone frequency deviation level. +pilot_enabled - Enables or disables the pilot tone feature. + +* The si4713 device is capable of applying audio compression to the transmitted signal. + +acomp_enabled - Enables or disables the audio dynamic range control feature. +acomp_gain - Sets the gain for audio dynamic range control. +acomp_threshold - Sets the threshold level for audio dynamic range control. +acomp_attack_time - Sets the attack time for audio dynamic range control. +acomp_release_time - Sets the release time for audio dynamic range control. + +* Limiter setups audio deviation limiter feature. Once a over deviation occurs, +it is possible to adjust the front-end gain of the audio input and always +prevent over deviation. + +limiter_enabled - Enables or disables the limiter feature. +limiter_deviation - Configures audio frequency deviation level. +limiter_release_time - Sets the limiter release time. + +* Tuning power + +power_level - Sets the output power level for signal transmission. +antenna_capacitor - This selects the value of antenna tuning capacitor manually +or automatically if set to zero. + +* RDS related + +rds_ps_name - Sets the RDS ps name field for transmission. +rds_radio_text - Sets the RDS radio text for transmission. +rds_pi - Sets the RDS PI field for transmission. +rds_pty - Sets the RDS PTY field for transmission. + +* Region related + +preemphasis - sets the preemphasis to be applied for transmission. + +RNL +=== + +This device also has an interface to measure received noise level. To do that, you should +ioctl the device node. Here is an code of example: + +int main (int argc, char *argv[]) +{ + struct si4713_rnl rnl; + int fd = open("/dev/radio0", O_RDWR); + int rval; + + if (argc < 2) + return -EINVAL; + + if (fd < 0) + return fd; + + sscanf(argv[1], "%d", &rnl.frequency); + + rval = ioctl(fd, SI4713_IOC_MEASURE_RNL, &rnl); + if (rval < 0) + return rval; + + printf("received noise level: %d\n", rnl.rnl); + + close(fd); +} + +The struct si4713_rnl and SI4713_IOC_MEASURE_RNL are defined under +include/media/si4713.h. + +Stereo/Mono and RDS subchannels +=============================== + +The device can also be configured using the available sub channels for +transmission. To do that use S/G_MODULATOR ioctl and configure txsubchans properly. +Refer to v4l2-spec for proper use of this ioctl. + +Testing +======= +Testing is usually done with v4l2-ctl utility for managing FM tuner cards. +The tool can be found in v4l-dvb repository under v4l2-apps/util directory. + +Example for setting rds ps name: +# v4l2-ctl -d /dev/radio0 --set-ctrl=rds_ps_name="Dummy" + diff --git a/linux/drivers/media/radio/radio-si4713.c b/linux/drivers/media/radio/radio-si4713.c new file mode 100644 index 000000000..65c14b704 --- /dev/null +++ b/linux/drivers/media/radio/radio-si4713.c @@ -0,0 +1,367 @@ +/* + * drivers/media/radio/radio-si4713.c + * + * Platform Driver for Silicon Labs Si4713 FM Radio Transmitter: + * + * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT + * Contact: Eduardo Valentin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* module parameters */ +static int radio_nr = -1; /* radio device minor (-1 ==> auto assign) */ +module_param(radio_nr, int, 0); +MODULE_PARM_DESC(radio_nr, + "Minor number for radio device (-1 ==> auto assign)"); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Eduardo Valentin "); +MODULE_DESCRIPTION("Platform driver for Si4713 FM Radio Transmitter"); +MODULE_VERSION("0.0.1"); + +/* Driver state struct */ +struct radio_si4713_device { + struct v4l2_device v4l2_dev; + struct video_device *radio_dev; +}; + +/* radio_si4713_fops - file operations interface */ +static const struct v4l2_file_operations radio_si4713_fops = { + .owner = THIS_MODULE, + .ioctl = video_ioctl2, +}; + +/* Video4Linux Interface */ +static int radio_si4713_fill_audout(struct v4l2_audioout *vao) +{ + /* TODO: check presence of audio output */ + strlcpy(vao->name, "FM Modulator Audio Out", 32); + + return 0; +} + +static int radio_si4713_enumaudout(struct file *file, void *priv, + struct v4l2_audioout *vao) +{ + return radio_si4713_fill_audout(vao); +} + +static int radio_si4713_g_audout(struct file *file, void *priv, + struct v4l2_audioout *vao) +{ + int rval = radio_si4713_fill_audout(vao); + + vao->index = 0; + + return rval; +} + +static int radio_si4713_s_audout(struct file *file, void *priv, + struct v4l2_audioout *vao) +{ + return vao->index ? -EINVAL : 0; +} + +/* radio_si4713_querycap - query device capabilities */ +static int radio_si4713_querycap(struct file *file, void *priv, + struct v4l2_capability *capability) +{ + struct radio_si4713_device *rsdev; + + rsdev = video_get_drvdata(video_devdata(file)); + + strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver)); + strlcpy(capability->card, "Silicon Labs Si4713 Modulator", + sizeof(capability->card)); + capability->capabilities = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT; + + return 0; +} + +/* radio_si4713_queryctrl - enumerate control items */ +static int radio_si4713_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + /* Must be sorted from low to high control ID! */ + static const u32 user_ctrls[] = { + V4L2_CID_USER_CLASS, + V4L2_CID_AUDIO_MUTE, + 0 + }; + + /* Must be sorted from low to high control ID! */ + static const u32 fmtx_ctrls[] = { + V4L2_CID_FM_TX_CLASS, + V4L2_CID_RDS_TX_DEVIATION, + V4L2_CID_RDS_TX_PI, + V4L2_CID_RDS_TX_PTY, + V4L2_CID_RDS_TX_PS_NAME, + V4L2_CID_RDS_TX_RADIO_TEXT, + V4L2_CID_AUDIO_LIMITER_ENABLED, + V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, + V4L2_CID_AUDIO_LIMITER_DEVIATION, + V4L2_CID_AUDIO_COMPRESSION_ENABLED, + V4L2_CID_AUDIO_COMPRESSION_GAIN, + V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, + V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, + V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, + V4L2_CID_PILOT_TONE_ENABLED, + V4L2_CID_PILOT_TONE_DEVIATION, + V4L2_CID_PILOT_TONE_FREQUENCY, + V4L2_CID_TUNE_PREEMPHASIS, + V4L2_CID_TUNE_POWER_LEVEL, + V4L2_CID_TUNE_ANTENNA_CAPACITOR, + 0 + }; + static const u32 *ctrl_classes[] = { + user_ctrls, + fmtx_ctrls, + NULL + }; + struct radio_si4713_device *rsdev; + + rsdev = video_get_drvdata(video_devdata(file)); + + qc->id = v4l2_ctrl_next(ctrl_classes, qc->id); + if (qc->id == 0) + return -EINVAL; + + if (qc->id == V4L2_CID_USER_CLASS || qc->id == V4L2_CID_FM_TX_CLASS) + return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0); + + return v4l2_device_call_until_err(&rsdev->v4l2_dev, 0, core, + queryctrl, qc); +} + +/* + * v4l2 ioctl call backs. + * we are just a wrapper for v4l2_sub_devs. + */ +static inline struct v4l2_device *get_v4l2_dev(struct file *file) +{ + return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev; +} + +static int radio_si4713_g_ext_ctrls(struct file *file, void *p, + struct v4l2_ext_controls *vecs) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, + g_ext_ctrls, vecs); +} + +static int radio_si4713_s_ext_ctrls(struct file *file, void *p, + struct v4l2_ext_controls *vecs) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, + s_ext_ctrls, vecs); +} + +static int radio_si4713_g_ctrl(struct file *file, void *p, + struct v4l2_control *vc) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, + g_ctrl, vc); +} + +static int radio_si4713_s_ctrl(struct file *file, void *p, + struct v4l2_control *vc) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, + s_ctrl, vc); +} + +static int radio_si4713_g_modulator(struct file *file, void *p, + struct v4l2_modulator *vm) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, + g_modulator, vm); +} + +static int radio_si4713_s_modulator(struct file *file, void *p, + struct v4l2_modulator *vm) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, + s_modulator, vm); +} + +static int radio_si4713_g_frequency(struct file *file, void *p, + struct v4l2_frequency *vf) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, + g_frequency, vf); +} + +static int radio_si4713_s_frequency(struct file *file, void *p, + struct v4l2_frequency *vf) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, + s_frequency, vf); +} + +static long radio_si4713_default(struct file *file, void *p, int cmd, void *arg) +{ + return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, + ioctl, cmd, arg); +} + +static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = { + .vidioc_enumaudout = radio_si4713_enumaudout, + .vidioc_g_audout = radio_si4713_g_audout, + .vidioc_s_audout = radio_si4713_s_audout, + .vidioc_querycap = radio_si4713_querycap, + .vidioc_queryctrl = radio_si4713_queryctrl, + .vidioc_g_ext_ctrls = radio_si4713_g_ext_ctrls, + .vidioc_s_ext_ctrls = radio_si4713_s_ext_ctrls, + .vidioc_g_ctrl = radio_si4713_g_ctrl, + .vidioc_s_ctrl = radio_si4713_s_ctrl, + .vidioc_g_modulator = radio_si4713_g_modulator, + .vidioc_s_modulator = radio_si4713_s_modulator, + .vidioc_g_frequency = radio_si4713_g_frequency, + .vidioc_s_frequency = radio_si4713_s_frequency, + .vidioc_default = radio_si4713_default, +}; + +/* radio_si4713_vdev_template - video device interface */ +static struct video_device radio_si4713_vdev_template = { + .fops = &radio_si4713_fops, + .name = "radio-si4713", + .release = video_device_release, + .ioctl_ops = &radio_si4713_ioctl_ops, +}; + +/* Platform driver interface */ +/* radio_si4713_pdriver_probe - probe for the device */ +static int radio_si4713_pdriver_probe(struct platform_device *pdev) +{ + struct radio_si4713_platform_data *pdata = pdev->dev.platform_data; + struct radio_si4713_device *rsdev; + struct i2c_adapter *adapter; + struct v4l2_subdev *sd; + int rval = 0; + + if (!pdata) { + dev_err(&pdev->dev, "Cannot proceed without platform data.\n"); + rval = -EINVAL; + goto exit; + } + + rsdev = kzalloc(sizeof *rsdev, GFP_KERNEL); + if (!rsdev) { + dev_err(&pdev->dev, "Failed to alloc video device.\n"); + rval = -ENOMEM; + goto exit; + } + + rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev); + if (rval) { + dev_err(&pdev->dev, "Failed to register v4l2 device.\n"); + goto free_rsdev; + } + + adapter = i2c_get_adapter(pdata->i2c_bus); + if (!adapter) { + dev_err(&pdev->dev, "Cannot get i2c adapter %d\n", + pdata->i2c_bus); + rval = -ENODEV; + goto unregister_v4l2_dev; + } + + sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter, "si4713_i2c", + pdata->subdev_board_info, NULL); + if (!sd) { + dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n"); + rval = -ENODEV; + goto unregister_v4l2_dev; + } + + rsdev->radio_dev = video_device_alloc(); + if (!rsdev->radio_dev) { + dev_err(&pdev->dev, "Failed to alloc video device.\n"); + rval = -ENOMEM; + goto unregister_v4l2_dev; + } + + memcpy(rsdev->radio_dev, &radio_si4713_vdev_template, + sizeof(radio_si4713_vdev_template)); + video_set_drvdata(rsdev->radio_dev, rsdev); + if (video_register_device(rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) { + dev_err(&pdev->dev, "Could not register video device.\n"); + rval = -EIO; + goto free_vdev; + } + dev_info(&pdev->dev, "New device successfully probed\n"); + + goto exit; + +free_vdev: + video_device_release(rsdev->radio_dev); +unregister_v4l2_dev: + v4l2_device_unregister(&rsdev->v4l2_dev); +free_rsdev: + kfree(rsdev); +exit: + return rval; +} + +/* radio_si4713_pdriver_remove - remove the device */ +static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev) +{ + struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); + struct radio_si4713_device *rsdev = container_of(v4l2_dev, + struct radio_si4713_device, + v4l2_dev); + + video_unregister_device(rsdev->radio_dev); + v4l2_device_unregister(&rsdev->v4l2_dev); + kfree(rsdev); + + return 0; +} + +static struct platform_driver radio_si4713_pdriver = { + .driver = { + .name = "radio-si4713", + }, + .probe = radio_si4713_pdriver_probe, + .remove = __exit_p(radio_si4713_pdriver_remove), +}; + +/* Module Interface */ +static int __init radio_si4713_module_init(void) +{ + return platform_driver_register(&radio_si4713_pdriver); +} + +static void __exit radio_si4713_module_exit(void) +{ + platform_driver_unregister(&radio_si4713_pdriver); +} + +module_init(radio_si4713_module_init); +module_exit(radio_si4713_module_exit); + diff --git a/linux/drivers/media/radio/si4713-i2c.c b/linux/drivers/media/radio/si4713-i2c.c new file mode 100644 index 000000000..8cbbe48b0 --- /dev/null +++ b/linux/drivers/media/radio/si4713-i2c.c @@ -0,0 +1,2067 @@ +/* + * drivers/media/radio/si4713-i2c.c + * + * Silicon Labs Si4713 FM Radio Transmitter I2C commands. + * + * Copyright (c) 2009 Nokia Corporation + * Contact: Eduardo Valentin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "si4713-i2c.h" + +/* module parameters */ +static int debug; +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug level (0 - 2)"); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Eduardo Valentin "); +MODULE_DESCRIPTION("I2C driver for Si4713 FM Radio Transmitter"); +MODULE_VERSION("0.0.1"); + +#define DEFAULT_RDS_PI 0x00 +#define DEFAULT_RDS_PTY 0x00 +#define DEFAULT_RDS_PS_NAME "" +#define DEFAULT_RDS_RADIO_TEXT DEFAULT_RDS_PS_NAME +#define DEFAULT_RDS_DEVIATION 0x00C8 +#define DEFAULT_RDS_PS_REPEAT_COUNT 0x0003 +#define DEFAULT_LIMITER_RTIME 0x1392 +#define DEFAULT_LIMITER_DEV 0x102CA +#define DEFAULT_PILOT_FREQUENCY 0x4A38 +#define DEFAULT_PILOT_DEVIATION 0x1A5E +#define DEFAULT_ACOMP_ATIME 0x0000 +#define DEFAULT_ACOMP_RTIME 0xF4240L +#define DEFAULT_ACOMP_GAIN 0x0F +#define DEFAULT_ACOMP_THRESHOLD (-0x28) +#define DEFAULT_MUTE 0x01 +#define DEFAULT_POWER_LEVEL 88 +#define DEFAULT_FREQUENCY 8800 +#define DEFAULT_PREEMPHASIS FMPE_EU +#define DEFAULT_TUNE_RNL 0xFF + +#define to_si4713_device(sd) container_of(sd, struct si4713_device, sd) + +/* frequency domain transformation (using times 10 to avoid floats) */ +#define FREQDEV_UNIT 100000 +#define FREQV4L2_MULTI 625 +#define si4713_to_v4l2(f) ((f * FREQDEV_UNIT) / FREQV4L2_MULTI) +#define v4l2_to_si4713(f) ((f * FREQV4L2_MULTI) / FREQDEV_UNIT) +#define FREQ_RANGE_LOW 7600 +#define FREQ_RANGE_HIGH 10800 + +#define MAX_ARGS 7 + +#define RDS_BLOCK 8 +#define RDS_BLOCK_CLEAR 0x03 +#define RDS_BLOCK_LOAD 0x04 +#define RDS_RADIOTEXT_2A 0x20 +#define RDS_RADIOTEXT_BLK_SIZE 4 +#define RDS_RADIOTEXT_INDEX_MAX 0x0F +#define RDS_CARRIAGE_RETURN 0x0D + +#define rds_ps_nblocks(len) ((len / RDS_BLOCK) + (len % RDS_BLOCK ? 1 : 0)) + +#define get_status_bit(p, b, m) (((p) & (m)) >> (b)) +#define set_bits(p, v, b, m) (((p) & ~(m)) | ((v) << (b))) + +#define ATTACK_TIME_UNIT 500 + +#define POWER_OFF 0x00 +#define POWER_ON 0x01 + +#define msb(x) ((u8)((u16) x >> 8)) +#define lsb(x) ((u8)((u16) x & 0x00FF)) +#define compose_u16(msb, lsb) (((u16)msb << 8) | lsb) +#define check_command_failed(status) (!(status & SI4713_CTS) || \ + (status & SI4713_ERR)) +/* mute definition */ +#define set_mute(p) ((p & 1) | ((p & 1) << 1)); +#define get_mute(p) (p & 0x01) + +#ifdef DEBUG +#define DBG_BUFFER(device, message, buffer, size) \ + { \ + int i; \ + char str[(size)*5]; \ + for (i = 0; i < size; i++) \ + sprintf(str + i * 5, " 0x%02x", buffer[i]); \ + v4l2_dbg(2, debug, device, "%s:%s\n", message, str); \ + } +#else +#define DBG_BUFFER(device, message, buffer, size) +#endif + +/* + * Values for limiter release time (sorted by second column) + * device release + * value time (us) + */ +static long limiter_times[] = { + 2000, 250, + 1000, 500, + 510, 1000, + 255, 2000, + 170, 3000, + 127, 4020, + 102, 5010, + 85, 6020, + 73, 7010, + 64, 7990, + 57, 8970, + 51, 10030, + 25, 20470, + 17, 30110, + 13, 39380, + 10, 51190, + 8, 63690, + 7, 73140, + 6, 85330, + 5, 102390, +}; + +/* + * Values for audio compression release time (sorted by second column) + * device release + * value time (us) + */ +static unsigned long acomp_rtimes[] = { + 0, 100000, + 1, 200000, + 2, 350000, + 3, 525000, + 4, 1000000, +}; + +/* + * Values for preemphasis (sorted by second column) + * device preemphasis + * value value (v4l2) + */ +static unsigned long preemphasis_values[] = { + FMPE_DISABLED, V4L2_PREEMPHASIS_DISABLED, + FMPE_EU, V4L2_PREEMPHASIS_50_uS, + FMPE_USA, V4L2_PREEMPHASIS_75_uS, +}; + +static int usecs_to_dev(unsigned long usecs, unsigned long const array[], + int size) +{ + int i; + int rval = -EINVAL; + + for (i = 0; i < size / 2; i++) + if (array[(i * 2) + 1] >= usecs) { + rval = array[i * 2]; + break; + } + + return rval; +} + +static unsigned long dev_to_usecs(int value, unsigned long const array[], + int size) +{ + int i; + int rval = -EINVAL; + + for (i = 0; i < size / 2; i++) + if (array[i * 2] == value) { + rval = array[(i * 2) + 1]; + break; + } + + return rval; +} + +/* si4713_handler: IRQ handler, just complete work */ +static irqreturn_t si4713_handler(int irq, void *dev) +{ + struct si4713_device *sdev = dev; + + v4l2_dbg(2, debug, &sdev->sd, + "%s: sending signal to completion work.\n", __func__); + complete(&sdev->work); + + return IRQ_HANDLED; +} + +/* + * si4713_send_command - sends a command to si4713 and waits its response + * @sdev: si4713_device structure for the device we are communicating + * @command: command id + * @args: command arguments we are sending (up to 7) + * @argn: actual size of @args + * @response: buffer to place the expected response from the device (up to 15) + * @respn: actual size of @response + * @usecs: amount of time to wait before reading the response (in usecs) + */ +static int si4713_send_command(struct si4713_device *sdev, const u8 command, + const u8 args[], const int argn, + u8 response[], const int respn, const int usecs) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd); + u8 data1[MAX_ARGS + 1]; + int err; + + if (!client->adapter) + return -ENODEV; + + /* First send the command and its arguments */ + data1[0] = command; + memcpy(data1 + 1, args, argn); + DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1); + + err = i2c_master_send(client, data1, argn + 1); + if (err != argn + 1) { + v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n", + command); + return (err > 0) ? -EIO : err; + } + + /* Wait response from interrupt */ + if (!wait_for_completion_timeout(&sdev->work, + usecs_to_jiffies(usecs) + 1)) + v4l2_warn(&sdev->sd, + "(%s) Device took too much time to answer.\n", + __func__); + + /* Then get the response */ + err = i2c_master_recv(client, response, respn); + if (err != respn) { + v4l2_err(&sdev->sd, + "Error while reading response for command 0x%02x\n", + command); + return (err > 0) ? -EIO : err; + } + + DBG_BUFFER(&sdev->sd, "Response", response, respn); + if (check_command_failed(response[0])) + return -EBUSY; + + return 0; +} + +/* + * si4713_read_property - reads a si4713 property + * @sdev: si4713_device structure for the device we are communicating + * @prop: property identification number + * @pv: property value to be returned on success + */ +static int si4713_read_property(struct si4713_device *sdev, u16 prop, u32 *pv) +{ + int err; + u8 val[SI4713_GET_PROP_NRESP]; + /* + * .First byte = 0 + * .Second byte = property's MSB + * .Third byte = property's LSB + */ + const u8 args[SI4713_GET_PROP_NARGS] = { + 0x00, + msb(prop), + lsb(prop), + }; + + err = si4713_send_command(sdev, SI4713_CMD_GET_PROPERTY, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (err < 0) + return err; + + *pv = compose_u16(val[2], val[3]); + + v4l2_dbg(1, debug, &sdev->sd, + "%s: property=0x%02x value=0x%02x status=0x%02x\n", + __func__, prop, *pv, val[0]); + + return err; +} + +/* + * si4713_write_property - modifies a si4713 property + * @sdev: si4713_device structure for the device we are communicating + * @prop: property identification number + * @val: new value for that property + */ +static int si4713_write_property(struct si4713_device *sdev, u16 prop, u16 val) +{ + int rval; + u8 resp[SI4713_SET_PROP_NRESP]; + /* + * .First byte = 0 + * .Second byte = property's MSB + * .Third byte = property's LSB + * .Fourth byte = value's MSB + * .Fifth byte = value's LSB + */ + const u8 args[SI4713_SET_PROP_NARGS] = { + 0x00, + msb(prop), + lsb(prop), + msb(val), + lsb(val), + }; + + rval = si4713_send_command(sdev, SI4713_CMD_SET_PROPERTY, + args, ARRAY_SIZE(args), + resp, ARRAY_SIZE(resp), + DEFAULT_TIMEOUT); + + if (rval < 0) + return rval; + + v4l2_dbg(1, debug, &sdev->sd, + "%s: property=0x%02x value=0x%02x status=0x%02x\n", + __func__, prop, val, resp[0]); + + /* + * As there is no command response for SET_PROPERTY, + * wait Tcomp time to finish before proceed, in order + * to have property properly set. + */ + msleep(TIMEOUT_SET_PROPERTY); + + return rval; +} + +/* + * si4713_powerup - Powers the device up + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_powerup(struct si4713_device *sdev) +{ + int err; + u8 resp[SI4713_PWUP_NRESP]; + /* + * .First byte = Enabled interrupts and boot function + * .Second byte = Input operation mode + */ + const u8 args[SI4713_PWUP_NARGS] = { + SI4713_PWUP_CTSIEN | SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX, + SI4713_PWUP_OPMOD_ANALOG, + }; + + if (sdev->power_state) + return 0; + + sdev->platform_data->set_power(1); + err = si4713_send_command(sdev, SI4713_CMD_POWER_UP, + args, ARRAY_SIZE(args), + resp, ARRAY_SIZE(resp), + TIMEOUT_POWER_UP); + + if (!err) { + v4l2_dbg(1, debug, &sdev->sd, "Powerup response: 0x%02x\n", + resp[0]); + v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n"); + sdev->power_state = POWER_ON; + + err = si4713_write_property(sdev, SI4713_GPO_IEN, + SI4713_STC_INT | SI4713_CTS); + } else { + sdev->platform_data->set_power(0); + } + + return err; +} + +/* + * si4713_powerdown - Powers the device down + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_powerdown(struct si4713_device *sdev) +{ + int err; + u8 resp[SI4713_PWDN_NRESP]; + + if (!sdev->power_state) + return 0; + + err = si4713_send_command(sdev, SI4713_CMD_POWER_DOWN, + NULL, 0, + resp, ARRAY_SIZE(resp), + DEFAULT_TIMEOUT); + + if (!err) { + v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n", + resp[0]); + v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n"); + sdev->platform_data->set_power(0); + sdev->power_state = POWER_OFF; + } + + return err; +} + +/* + * si4713_checkrev - Checks if we are treating a device with the correct rev. + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_checkrev(struct si4713_device *sdev) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd); + int rval; + u8 resp[SI4713_GETREV_NRESP]; + + mutex_lock(&sdev->mutex); + + rval = si4713_send_command(sdev, SI4713_CMD_GET_REV, + NULL, 0, + resp, ARRAY_SIZE(resp), + DEFAULT_TIMEOUT); + + if (rval < 0) + goto unlock; + + if (resp[1] == SI4713_PRODUCT_NUMBER) { + v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n", + client->addr << 1, client->adapter->name); + } else { + v4l2_err(&sdev->sd, "Invalid product number\n"); + rval = -EINVAL; + } + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +/* + * si4713_wait_stc - Waits STC interrupt and clears status bits. Usefull + * for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS + * @sdev: si4713_device structure for the device we are communicating + * @usecs: timeout to wait for STC interrupt signal + */ +static int si4713_wait_stc(struct si4713_device *sdev, const int usecs) +{ + int err; + u8 resp[SI4713_GET_STATUS_NRESP]; + + /* Wait response from STC interrupt */ + if (!wait_for_completion_timeout(&sdev->work, + usecs_to_jiffies(usecs) + 1)) + v4l2_warn(&sdev->sd, + "%s: device took too much time to answer (%d usec).\n", + __func__, usecs); + + /* Clear status bits */ + err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS, + NULL, 0, + resp, ARRAY_SIZE(resp), + DEFAULT_TIMEOUT); + + if (err < 0) + goto exit; + + v4l2_dbg(1, debug, &sdev->sd, + "%s: status bits: 0x%02x\n", __func__, resp[0]); + + if (!(resp[0] & SI4713_STC_INT)) + err = -EIO; + +exit: + return err; +} + +/* + * si4713_tx_tune_freq - Sets the state of the RF carrier and sets the tuning + * frequency between 76 and 108 MHz in 10 kHz units and + * steps of 50 kHz. + * @sdev: si4713_device structure for the device we are communicating + * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz) + */ +static int si4713_tx_tune_freq(struct si4713_device *sdev, u16 frequency) +{ + int err; + u8 val[SI4713_TXFREQ_NRESP]; + /* + * .First byte = 0 + * .Second byte = frequency's MSB + * .Third byte = frequency's LSB + */ + const u8 args[SI4713_TXFREQ_NARGS] = { + 0x00, + msb(frequency), + lsb(frequency), + }; + + err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_FREQ, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (err < 0) + return err; + + v4l2_dbg(1, debug, &sdev->sd, + "%s: frequency=0x%02x status=0x%02x\n", __func__, + frequency, val[0]); + + err = si4713_wait_stc(sdev, TIMEOUT_TX_TUNE); + if (err < 0) + return err; + + return compose_u16(args[1], args[2]); +} + +/* + * si4713_tx_tune_power - Sets the RF voltage level between 88 and 115 dBuV in + * 1 dB units. A value of 0x00 indicates off. The command + * also sets the antenna tuning capacitance. A value of 0 + * indicates autotuning, and a value of 1 - 191 indicates + * a manual override, which results in a tuning + * capacitance of 0.25 pF x @antcap. + * @sdev: si4713_device structure for the device we are communicating + * @power: tuning power (88 - 115 dBuV, unit/step 1 dB) + * @antcap: value of antenna tuning capacitor (0 - 191) + */ +static int si4713_tx_tune_power(struct si4713_device *sdev, u8 power, + u8 antcap) +{ + int err; + u8 val[SI4713_TXPWR_NRESP]; + /* + * .First byte = 0 + * .Second byte = 0 + * .Third byte = power + * .Fourth byte = antcap + */ + const u8 args[SI4713_TXPWR_NARGS] = { + 0x00, + 0x00, + power, + antcap, + }; + + if (((power > 0) && (power < SI4713_MIN_POWER)) || + power > SI4713_MAX_POWER || antcap > SI4713_MAX_ANTCAP) + return -EDOM; + + err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_POWER, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (err < 0) + return err; + + v4l2_dbg(1, debug, &sdev->sd, + "%s: power=0x%02x antcap=0x%02x status=0x%02x\n", + __func__, power, antcap, val[0]); + + return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE_POWER); +} + +/* + * si4713_tx_tune_measure - Enters receive mode and measures the received noise + * level in units of dBuV on the selected frequency. + * The Frequency must be between 76 and 108 MHz in 10 kHz + * units and steps of 50 kHz. The command also sets the + * antenna tuning capacitance. A value of 0 means + * autotuning, and a value of 1 to 191 indicates manual + * override. + * @sdev: si4713_device structure for the device we are communicating + * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz) + * @antcap: value of antenna tuning capacitor (0 - 191) + */ +static int si4713_tx_tune_measure(struct si4713_device *sdev, u16 frequency, + u8 antcap) +{ + int err; + u8 val[SI4713_TXMEA_NRESP]; + /* + * .First byte = 0 + * .Second byte = frequency's MSB + * .Third byte = frequency's LSB + * .Fourth byte = antcap + */ + const u8 args[SI4713_TXMEA_NARGS] = { + 0x00, + msb(frequency), + lsb(frequency), + antcap, + }; + + sdev->tune_rnl = DEFAULT_TUNE_RNL; + + if (antcap > SI4713_MAX_ANTCAP) + return -EDOM; + + err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_MEASURE, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (err < 0) + return err; + + v4l2_dbg(1, debug, &sdev->sd, + "%s: frequency=0x%02x antcap=0x%02x status=0x%02x\n", + __func__, frequency, antcap, val[0]); + + return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE); +} + +/* + * si4713_tx_tune_status- Returns the status of the tx_tune_freq, tx_tune_mea or + * tx_tune_power commands. This command return the current + * frequency, output voltage in dBuV, the antenna tunning + * capacitance value and the received noise level. The + * command also clears the stcint interrupt bit when the + * first bit of its arguments is high. + * @sdev: si4713_device structure for the device we are communicating + * @intack: 0x01 to clear the seek/tune complete interrupt status indicator. + * @frequency: returned frequency + * @power: returned power + * @antcap: returned antenna capacitance + * @noise: returned noise level + */ +static int si4713_tx_tune_status(struct si4713_device *sdev, u8 intack, + u16 *frequency, u8 *power, + u8 *antcap, u8 *noise) +{ + int err; + u8 val[SI4713_TXSTATUS_NRESP]; + /* + * .First byte = intack bit + */ + const u8 args[SI4713_TXSTATUS_NARGS] = { + intack & SI4713_INTACK_MASK, + }; + + err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_STATUS, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (!err) { + v4l2_dbg(1, debug, &sdev->sd, + "%s: status=0x%02x\n", __func__, val[0]); + *frequency = compose_u16(val[2], val[3]); + sdev->frequency = *frequency; + *power = val[5]; + *antcap = val[6]; + *noise = val[7]; + v4l2_dbg(1, debug, &sdev->sd, "%s: response: %d x 10 kHz " + "(power %d, antcap %d, rnl %d)\n", __func__, + *frequency, *power, *antcap, *noise); + } + + return err; +} + +/* + * si4713_tx_rds_buff - Loads the RDS group buffer FIFO or circular buffer. + * @sdev: si4713_device structure for the device we are communicating + * @mode: the buffer operation mode. + * @rdsb: RDS Block B + * @rdsc: RDS Block C + * @rdsd: RDS Block D + * @cbleft: returns the number of available circular buffer blocks minus the + * number of used circular buffer blocks. + */ +static int si4713_tx_rds_buff(struct si4713_device *sdev, u8 mode, u16 rdsb, + u16 rdsc, u16 rdsd, s8 *cbleft) +{ + int err; + u8 val[SI4713_RDSBUFF_NRESP]; + + const u8 args[SI4713_RDSBUFF_NARGS] = { + mode & SI4713_RDSBUFF_MODE_MASK, + msb(rdsb), + lsb(rdsb), + msb(rdsc), + lsb(rdsc), + msb(rdsd), + lsb(rdsd), + }; + + err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_BUFF, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (!err) { + v4l2_dbg(1, debug, &sdev->sd, + "%s: status=0x%02x\n", __func__, val[0]); + *cbleft = (s8)val[2] - val[3]; + v4l2_dbg(1, debug, &sdev->sd, "%s: response: interrupts" + " 0x%02x cb avail: %d cb used %d fifo avail" + " %d fifo used %d\n", __func__, val[1], + val[2], val[3], val[4], val[5]); + } + + return err; +} + +/* + * si4713_tx_rds_ps - Loads the program service buffer. + * @sdev: si4713_device structure for the device we are communicating + * @psid: program service id to be loaded. + * @pschar: assumed 4 size char array to be loaded into the program service + */ +static int si4713_tx_rds_ps(struct si4713_device *sdev, u8 psid, + unsigned char *pschar) +{ + int err; + u8 val[SI4713_RDSPS_NRESP]; + + const u8 args[SI4713_RDSPS_NARGS] = { + psid & SI4713_RDSPS_PSID_MASK, + pschar[0], + pschar[1], + pschar[2], + pschar[3], + }; + + err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_PS, + args, ARRAY_SIZE(args), val, + ARRAY_SIZE(val), DEFAULT_TIMEOUT); + + if (err < 0) + return err; + + v4l2_dbg(1, debug, &sdev->sd, "%s: status=0x%02x\n", __func__, val[0]); + + return err; +} + +static int si4713_set_power_state(struct si4713_device *sdev, u8 value) +{ + int rval; + + mutex_lock(&sdev->mutex); + + if (value) + rval = si4713_powerup(sdev); + else + rval = si4713_powerdown(sdev); + + mutex_unlock(&sdev->mutex); + return rval; +} + +static int si4713_set_mute(struct si4713_device *sdev, u16 mute) +{ + int rval = 0; + + mute = set_mute(mute); + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) + rval = si4713_write_property(sdev, + SI4713_TX_LINE_INPUT_MUTE, mute); + + if (rval >= 0) + sdev->mute = get_mute(mute); + + mutex_unlock(&sdev->mutex); + + return rval; +} + +static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name) +{ + int rval = 0, i; + u8 len = 0; + + /* We want to clear the whole thing */ + if (!strlen(ps_name)) + memset(ps_name, 0, MAX_RDS_PS_NAME + 1); + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + /* Write the new ps name and clear the padding */ + for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) { + rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)), + ps_name + i); + if (rval < 0) + goto unlock; + } + + /* Setup the size to be sent */ + if (strlen(ps_name)) + len = strlen(ps_name) - 1; + else + len = 1; + + rval = si4713_write_property(sdev, + SI4713_TX_RDS_PS_MESSAGE_COUNT, + rds_ps_nblocks(len)); + if (rval < 0) + goto unlock; + + rval = si4713_write_property(sdev, + SI4713_TX_RDS_PS_REPEAT_COUNT, + DEFAULT_RDS_PS_REPEAT_COUNT * 2); + if (rval < 0) + goto unlock; + } + + strncpy(sdev->rds_info.ps_name, ps_name, MAX_RDS_PS_NAME); + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt) +{ + int rval = 0, i; + u16 t_index = 0; + u8 b_index = 0, cr_inserted = 0; + s8 left; + + mutex_lock(&sdev->mutex); + + if (!sdev->power_state) + goto copy; + + rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left); + if (rval < 0) + goto unlock; + + if (!strlen(rt)) + goto copy; + + do { + /* RDS spec says that if the last block isn't used, + * then apply a carriage return + */ + if (t_index < (RDS_RADIOTEXT_INDEX_MAX * + RDS_RADIOTEXT_BLK_SIZE)) { + for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) { + if (!rt[t_index + i] || rt[t_index + i] == + RDS_CARRIAGE_RETURN) { + rt[t_index + i] = RDS_CARRIAGE_RETURN; + cr_inserted = 1; + break; + } + } + } + + rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_LOAD, + compose_u16(RDS_RADIOTEXT_2A, b_index++), + compose_u16(rt[t_index], rt[t_index + 1]), + compose_u16(rt[t_index + 2], rt[t_index + 3]), + &left); + if (rval < 0) + goto unlock; + + t_index += RDS_RADIOTEXT_BLK_SIZE; + + if (cr_inserted) + break; + } while (left > 0); + +copy: + strncpy(sdev->rds_info.radio_text, rt, MAX_RDS_RADIO_TEXT); + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id, + u32 **shadow, s32 *bit, s32 *mask, u16 *property, int *mul, + unsigned long **table, int *size) +{ + s32 rval = 0; + + switch (id) { + /* FM_TX class controls */ + case V4L2_CID_RDS_TX_PI: + *property = SI4713_TX_RDS_PI; + *mul = 1; + *shadow = &sdev->rds_info.pi; + break; + case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: + *property = SI4713_TX_ACOMP_THRESHOLD; + *mul = 1; + *shadow = &sdev->acomp_info.threshold; + break; + case V4L2_CID_AUDIO_COMPRESSION_GAIN: + *property = SI4713_TX_ACOMP_GAIN; + *mul = 1; + *shadow = &sdev->acomp_info.gain; + break; + case V4L2_CID_PILOT_TONE_FREQUENCY: + *property = SI4713_TX_PILOT_FREQUENCY; + *mul = 1; + *shadow = &sdev->pilot_info.frequency; + break; + case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: + *property = SI4713_TX_ACOMP_ATTACK_TIME; + *mul = ATTACK_TIME_UNIT; + *shadow = &sdev->acomp_info.attack_time; + break; + case V4L2_CID_PILOT_TONE_DEVIATION: + *property = SI4713_TX_PILOT_DEVIATION; + *mul = 10; + *shadow = &sdev->pilot_info.deviation; + break; + case V4L2_CID_AUDIO_LIMITER_DEVIATION: + *property = SI4713_TX_AUDIO_DEVIATION; + *mul = 10; + *shadow = &sdev->limiter_info.deviation; + break; + case V4L2_CID_RDS_TX_DEVIATION: + *property = SI4713_TX_RDS_DEVIATION; + *mul = 1; + *shadow = &sdev->rds_info.deviation; + break; + + case V4L2_CID_RDS_TX_PTY: + *property = SI4713_TX_RDS_PS_MISC; + *bit = 5; + *mask = 0x1F << 5; + *shadow = &sdev->rds_info.pty; + break; + case V4L2_CID_AUDIO_LIMITER_ENABLED: + *property = SI4713_TX_ACOMP_ENABLE; + *bit = 1; + *mask = 1 << 1; + *shadow = &sdev->limiter_info.enabled; + break; + case V4L2_CID_AUDIO_COMPRESSION_ENABLED: + *property = SI4713_TX_ACOMP_ENABLE; + *bit = 0; + *mask = 1 << 0; + *shadow = &sdev->acomp_info.enabled; + break; + case V4L2_CID_PILOT_TONE_ENABLED: + *property = SI4713_TX_COMPONENT_ENABLE; + *bit = 0; + *mask = 1 << 0; + *shadow = &sdev->pilot_info.enabled; + break; + + case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: + *property = SI4713_TX_LIMITER_RELEASE_TIME; + *table = limiter_times; + *size = ARRAY_SIZE(limiter_times); + *shadow = &sdev->limiter_info.release_time; + break; + case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: + *property = SI4713_TX_ACOMP_RELEASE_TIME; + *table = acomp_rtimes; + *size = ARRAY_SIZE(acomp_rtimes); + *shadow = &sdev->acomp_info.release_time; + break; + case V4L2_CID_TUNE_PREEMPHASIS: + *property = SI4713_TX_PREEMPHASIS; + *table = preemphasis_values; + *size = ARRAY_SIZE(preemphasis_values); + *shadow = &sdev->preemphasis; + break; + + default: + rval = -EINVAL; + }; + + return rval; +} + +static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc); + +/* write string property */ +static int si4713_write_econtrol_string(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + struct v4l2_queryctrl vqc; + int len; + s32 rval = 0; + + vqc.id = control->id; + rval = si4713_queryctrl(&sdev->sd, &vqc); + if (rval < 0) + goto exit; + + switch (control->id) { + case V4L2_CID_RDS_TX_PS_NAME: { + char ps_name[MAX_RDS_PS_NAME + 1]; + + len = control->size - 1; + if (len > MAX_RDS_PS_NAME) { + rval = -ERANGE; + goto exit; + } + rval = copy_from_user(ps_name, control->string, len); + if (rval < 0) + goto exit; + ps_name[len] = '\0'; + + if (strlen(ps_name) % vqc.step) { + rval = -ERANGE; + goto exit; + } + + rval = si4713_set_rds_ps_name(sdev, ps_name); + } + break; + + case V4L2_CID_RDS_TX_RADIO_TEXT: { + char radio_text[MAX_RDS_RADIO_TEXT + 1]; + + len = control->size - 1; + if (len > MAX_RDS_RADIO_TEXT) { + rval = -ERANGE; + goto exit; + } + rval = copy_from_user(radio_text, control->string, len); + if (rval < 0) + goto exit; + radio_text[len] = '\0'; + + if (strlen(radio_text) % vqc.step) { + rval = -ERANGE; + goto exit; + } + + rval = si4713_set_rds_radio_text(sdev, radio_text); + } + break; + + default: + rval = -EINVAL; + break; + }; + +exit: + return rval; +} + +static int validate_range(struct v4l2_subdev *sd, + struct v4l2_ext_control *control) +{ + struct v4l2_queryctrl vqc; + int rval; + + vqc.id = control->id; + rval = si4713_queryctrl(sd, &vqc); + if (rval < 0) + goto exit; + + if (control->value < vqc.minimum || control->value > vqc.maximum) + rval = -ERANGE; + +exit: + return rval; +} + +/* properties which use tx_tune_power*/ +static int si4713_write_econtrol_tune(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + s32 rval = 0; + u8 power, antcap; + + rval = validate_range(&sdev->sd, control); + if (rval < 0) + goto exit; + + mutex_lock(&sdev->mutex); + + switch (control->id) { + case V4L2_CID_TUNE_POWER_LEVEL: + power = control->value; + antcap = sdev->antenna_capacitor; + break; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + power = sdev->power_level; + antcap = control->value; + break; + default: + rval = -EINVAL; + goto unlock; + }; + + if (sdev->power_state) + rval = si4713_tx_tune_power(sdev, power, antcap); + + if (rval == 0) { + sdev->power_level = power; + sdev->antenna_capacitor = antcap; + } + +unlock: + mutex_unlock(&sdev->mutex); +exit: + return rval; +} + +static int si4713_write_econtrol_integers(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + s32 rval; + u32 *shadow = NULL, val = 0; + s32 bit = 0, mask = 0; + u16 property = 0; + int mul = 0; + unsigned long *table = NULL; + int size = 0; + + rval = validate_range(&sdev->sd, control); + if (rval < 0) + goto exit; + + rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, + &mask, &property, &mul, &table, &size); + if (rval < 0) + goto exit; + + val = control->value; + if (mul) { + val = control->value / mul; + } else if (table) { + rval = usecs_to_dev(control->value, table, size); + if (rval < 0) + goto exit; + val = rval; + rval = 0; + } + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + if (mask) { + rval = si4713_read_property(sdev, property, &val); + if (rval < 0) + goto unlock; + val = set_bits(val, control->value, bit, mask); + } + + rval = si4713_write_property(sdev, property, val); + if (rval < 0) + goto unlock; + if (mask) + val = control->value; + } + + if (mul) { + *shadow = val * mul; + } else if (table) { + rval = dev_to_usecs(val, table, size); + if (rval < 0) + goto unlock; + *shadow = rval; + rval = 0; + } else { + *shadow = val; + } + +unlock: + mutex_unlock(&sdev->mutex); +exit: + return rval; +} + +static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f); +static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *); +/* + * si4713_setup - Sets the device up with current configuration. + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_setup(struct si4713_device *sdev) +{ + struct v4l2_ext_control ctrl; + struct v4l2_frequency f; + struct v4l2_modulator vm; + struct si4713_device *tmp; + int rval = 0; + + tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + /* Get a local copy to avoid race */ + mutex_lock(&sdev->mutex); + memcpy(tmp, sdev, sizeof(*sdev)); + mutex_unlock(&sdev->mutex); + + ctrl.id = V4L2_CID_RDS_TX_PI; + ctrl.value = tmp->rds_info.pi; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_COMPRESSION_THRESHOLD; + ctrl.value = tmp->acomp_info.threshold; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_COMPRESSION_GAIN; + ctrl.value = tmp->acomp_info.gain; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_PILOT_TONE_FREQUENCY; + ctrl.value = tmp->pilot_info.frequency; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME; + ctrl.value = tmp->acomp_info.attack_time; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_PILOT_TONE_DEVIATION; + ctrl.value = tmp->pilot_info.deviation; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_LIMITER_DEVIATION; + ctrl.value = tmp->limiter_info.deviation; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_RDS_TX_DEVIATION; + ctrl.value = tmp->rds_info.deviation; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_RDS_TX_PTY; + ctrl.value = tmp->rds_info.pty; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_LIMITER_ENABLED; + ctrl.value = tmp->limiter_info.enabled; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ENABLED; + ctrl.value = tmp->acomp_info.enabled; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_PILOT_TONE_ENABLED; + ctrl.value = tmp->pilot_info.enabled; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_LIMITER_RELEASE_TIME; + ctrl.value = tmp->limiter_info.release_time; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME; + ctrl.value = tmp->acomp_info.release_time; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_TUNE_PREEMPHASIS; + ctrl.value = tmp->preemphasis; + rval |= si4713_write_econtrol_integers(sdev, &ctrl); + + ctrl.id = V4L2_CID_RDS_TX_PS_NAME; + rval |= si4713_set_rds_ps_name(sdev, tmp->rds_info.ps_name); + + ctrl.id = V4L2_CID_RDS_TX_RADIO_TEXT; + rval |= si4713_set_rds_radio_text(sdev, tmp->rds_info.radio_text); + + /* Device procedure needs to set frequency first */ + f.frequency = tmp->frequency ? tmp->frequency : DEFAULT_FREQUENCY; + f.frequency = si4713_to_v4l2(f.frequency); + rval |= si4713_s_frequency(&sdev->sd, &f); + + ctrl.id = V4L2_CID_TUNE_POWER_LEVEL; + ctrl.value = tmp->power_level; + rval |= si4713_write_econtrol_tune(sdev, &ctrl); + + ctrl.id = V4L2_CID_TUNE_ANTENNA_CAPACITOR; + ctrl.value = tmp->antenna_capacitor; + rval |= si4713_write_econtrol_tune(sdev, &ctrl); + + vm.index = 0; + if (tmp->stereo) + vm.txsubchans = V4L2_TUNER_SUB_STEREO; + else + vm.txsubchans = V4L2_TUNER_SUB_MONO; + if (tmp->rds_info.enabled) + vm.txsubchans |= V4L2_TUNER_SUB_RDS; + si4713_s_modulator(&sdev->sd, &vm); + + kfree(tmp); + + return rval; +} + +/* + * si4713_initialize - Sets the device up with default configuration. + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_initialize(struct si4713_device *sdev) +{ + int rval; + + rval = si4713_set_power_state(sdev, POWER_ON); + if (rval < 0) + goto exit; + + rval = si4713_checkrev(sdev); + if (rval < 0) + goto exit; + + rval = si4713_set_power_state(sdev, POWER_OFF); + if (rval < 0) + goto exit; + + mutex_lock(&sdev->mutex); + + sdev->rds_info.pi = DEFAULT_RDS_PI; + sdev->rds_info.pty = DEFAULT_RDS_PTY; + sdev->rds_info.deviation = DEFAULT_RDS_DEVIATION; + strlcpy(sdev->rds_info.ps_name, DEFAULT_RDS_PS_NAME, MAX_RDS_PS_NAME); + strlcpy(sdev->rds_info.radio_text, DEFAULT_RDS_RADIO_TEXT, + MAX_RDS_RADIO_TEXT); + sdev->rds_info.enabled = 1; + + sdev->limiter_info.release_time = DEFAULT_LIMITER_RTIME; + sdev->limiter_info.deviation = DEFAULT_LIMITER_DEV; + sdev->limiter_info.enabled = 1; + + sdev->pilot_info.deviation = DEFAULT_PILOT_DEVIATION; + sdev->pilot_info.frequency = DEFAULT_PILOT_FREQUENCY; + sdev->pilot_info.enabled = 1; + + sdev->acomp_info.release_time = DEFAULT_ACOMP_RTIME; + sdev->acomp_info.attack_time = DEFAULT_ACOMP_ATIME; + sdev->acomp_info.threshold = DEFAULT_ACOMP_THRESHOLD; + sdev->acomp_info.gain = DEFAULT_ACOMP_GAIN; + sdev->acomp_info.enabled = 1; + + sdev->frequency = DEFAULT_FREQUENCY; + sdev->preemphasis = DEFAULT_PREEMPHASIS; + sdev->mute = DEFAULT_MUTE; + sdev->power_level = DEFAULT_POWER_LEVEL; + sdev->antenna_capacitor = 0; + sdev->stereo = 1; + sdev->tune_rnl = DEFAULT_TUNE_RNL; + + mutex_unlock(&sdev->mutex); + +exit: + return rval; +} + +/* read string property */ +static int si4713_read_econtrol_string(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + s32 rval = 0; + + switch (control->id) { + case V4L2_CID_RDS_TX_PS_NAME: + if (strlen(sdev->rds_info.ps_name) + 1 > control->size) { + control->size = MAX_RDS_PS_NAME + 1; + rval = -ENOSPC; + goto exit; + } + rval = copy_to_user(control->string, sdev->rds_info.ps_name, + strlen(sdev->rds_info.ps_name) + 1); + break; + + case V4L2_CID_RDS_TX_RADIO_TEXT: + if (strlen(sdev->rds_info.radio_text) + 1 > control->size) { + control->size = MAX_RDS_RADIO_TEXT + 1; + rval = -ENOSPC; + goto exit; + } + rval = copy_to_user(control->string, sdev->rds_info.radio_text, + strlen(sdev->rds_info.radio_text) + 1); + break; + + default: + rval = -EINVAL; + break; + }; + +exit: + return rval; +} + +/* + * si4713_update_tune_status - update properties from tx_tune_status + * command. Must be called with sdev->mutex held. + * @sdev: si4713_device structure for the device we are communicating + */ +static int si4713_update_tune_status(struct si4713_device *sdev) +{ + int rval; + u16 f = 0; + u8 p = 0, a = 0, n = 0; + + rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n); + + if (rval < 0) + goto exit; + + sdev->power_level = p; + sdev->antenna_capacitor = a; + sdev->tune_rnl = n; + +exit: + return rval; +} + +/* properties which use tx_tune_status */ +static int si4713_read_econtrol_tune(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + s32 rval = 0; + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + rval = si4713_update_tune_status(sdev); + if (rval < 0) + goto unlock; + } + + switch (control->id) { + case V4L2_CID_TUNE_POWER_LEVEL: + control->value = sdev->power_level; + break; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + control->value = sdev->antenna_capacitor; + break; + default: + rval = -EINVAL; + }; + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +static int si4713_read_econtrol_integers(struct si4713_device *sdev, + struct v4l2_ext_control *control) +{ + s32 rval; + u32 *shadow = NULL, val = 0; + s32 bit = 0, mask = 0; + u16 property = 0; + int mul = 0; + unsigned long *table = NULL; + int size = 0; + + rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, + &mask, &property, &mul, &table, &size); + if (rval < 0) + goto exit; + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + rval = si4713_read_property(sdev, property, &val); + if (rval < 0) + goto unlock; + + /* Keep negative values for threshold */ + if (control->id == V4L2_CID_AUDIO_COMPRESSION_THRESHOLD) + *shadow = (s16)val; + else if (mask) + *shadow = get_status_bit(val, bit, mask); + else if (mul) + *shadow = val * mul; + else + *shadow = dev_to_usecs(val, table, size); + } + + control->value = *shadow; + +unlock: + mutex_unlock(&sdev->mutex); +exit: + return rval; +} + +/* + * Video4Linux Subdev Interface + */ +/* si4713_s_ext_ctrls - set extended controls value */ +static int si4713_s_ext_ctrls(struct v4l2_subdev *sd, + struct v4l2_ext_controls *ctrls) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int i; + + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) + return -EINVAL; + + for (i = 0; i < ctrls->count; i++) { + int err; + + switch ((ctrls->controls + i)->id) { + case V4L2_CID_RDS_TX_PS_NAME: + case V4L2_CID_RDS_TX_RADIO_TEXT: + err = si4713_write_econtrol_string(sdev, + ctrls->controls + i); + break; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + case V4L2_CID_TUNE_POWER_LEVEL: + err = si4713_write_econtrol_tune(sdev, + ctrls->controls + i); + break; + default: + err = si4713_write_econtrol_integers(sdev, + ctrls->controls + i); + } + + if (err < 0) { + ctrls->error_idx = i; + return err; + } + } + + return 0; +} + +/* si4713_g_ext_ctrls - get extended controls value */ +static int si4713_g_ext_ctrls(struct v4l2_subdev *sd, + struct v4l2_ext_controls *ctrls) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int i; + + if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) + return -EINVAL; + + for (i = 0; i < ctrls->count; i++) { + int err; + + switch ((ctrls->controls + i)->id) { + case V4L2_CID_RDS_TX_PS_NAME: + case V4L2_CID_RDS_TX_RADIO_TEXT: + err = si4713_read_econtrol_string(sdev, + ctrls->controls + i); + break; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + case V4L2_CID_TUNE_POWER_LEVEL: + err = si4713_read_econtrol_tune(sdev, + ctrls->controls + i); + break; + default: + err = si4713_read_econtrol_integers(sdev, + ctrls->controls + i); + } + + if (err < 0) { + ctrls->error_idx = i; + return err; + } + } + + return 0; +} + +/* si4713_queryctrl - enumerate control items */ +static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + int rval = 0; + + switch (qc->id) { + /* User class controls */ + case V4L2_CID_AUDIO_MUTE: + rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, DEFAULT_MUTE); + break; + /* FM_TX class controls */ + case V4L2_CID_RDS_TX_PI: + rval = v4l2_ctrl_query_fill(qc, 0, 0xFFFF, 1, DEFAULT_RDS_PI); + break; + case V4L2_CID_RDS_TX_PTY: + rval = v4l2_ctrl_query_fill(qc, 0, 31, 1, DEFAULT_RDS_PTY); + break; + case V4L2_CID_RDS_TX_DEVIATION: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_DEVIATION, + 10, DEFAULT_RDS_DEVIATION); + break; + case V4L2_CID_RDS_TX_PS_NAME: + /* + * Report step as 8. From RDS spec, psname + * should be 8. But there are receivers which scroll strings + * sized as 8xN. + */ + rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_PS_NAME, 8, 0); + break; + case V4L2_CID_RDS_TX_RADIO_TEXT: + /* + * Report step as 32 (2A block). From RDS spec, + * radio text should be 32 for 2A block. But there are receivers + * which scroll strings sized as 32xN. Setting default to 32. + */ + rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_RADIO_TEXT, 32, 0); + break; + + case V4L2_CID_AUDIO_LIMITER_ENABLED: + rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + break; + case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: + rval = v4l2_ctrl_query_fill(qc, 250, MAX_LIMITER_RELEASE_TIME, + 50, DEFAULT_LIMITER_RTIME); + break; + case V4L2_CID_AUDIO_LIMITER_DEVIATION: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_LIMITER_DEVIATION, + 10, DEFAULT_LIMITER_DEV); + break; + + case V4L2_CID_AUDIO_COMPRESSION_ENABLED: + rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + break; + case V4L2_CID_AUDIO_COMPRESSION_GAIN: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_GAIN, 1, + DEFAULT_ACOMP_GAIN); + break; + case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: + rval = v4l2_ctrl_query_fill(qc, MIN_ACOMP_THRESHOLD, + MAX_ACOMP_THRESHOLD, 1, + DEFAULT_ACOMP_THRESHOLD); + break; + case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_ATTACK_TIME, + 500, DEFAULT_ACOMP_ATIME); + break; + case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: + rval = v4l2_ctrl_query_fill(qc, 100000, MAX_ACOMP_RELEASE_TIME, + 100000, DEFAULT_ACOMP_RTIME); + break; + + case V4L2_CID_PILOT_TONE_ENABLED: + rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); + break; + case V4L2_CID_PILOT_TONE_DEVIATION: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_DEVIATION, + 10, DEFAULT_PILOT_DEVIATION); + break; + case V4L2_CID_PILOT_TONE_FREQUENCY: + rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_FREQUENCY, + 1, DEFAULT_PILOT_FREQUENCY); + break; + + case V4L2_CID_TUNE_PREEMPHASIS: + rval = v4l2_ctrl_query_fill(qc, V4L2_PREEMPHASIS_DISABLED, + V4L2_PREEMPHASIS_75_uS, 1, + V4L2_PREEMPHASIS_50_uS); + break; + case V4L2_CID_TUNE_POWER_LEVEL: + rval = v4l2_ctrl_query_fill(qc, 0, 120, 1, DEFAULT_POWER_LEVEL); + break; + case V4L2_CID_TUNE_ANTENNA_CAPACITOR: + rval = v4l2_ctrl_query_fill(qc, 0, 191, 1, 0); + break; + default: + rval = -EINVAL; + break; + }; + + return rval; +} + +/* si4713_g_ctrl - get the value of a control */ +static int si4713_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + + if (!sdev) + return -ENODEV; + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + rval = si4713_read_property(sdev, SI4713_TX_LINE_INPUT_MUTE, + &sdev->mute); + + if (rval < 0) + goto unlock; + } + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + ctrl->value = get_mute(sdev->mute); + break; + } + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +/* si4713_s_ctrl - set the value of a control */ +static int si4713_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + + if (!sdev) + return -ENODEV; + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value) { + rval = si4713_set_mute(sdev, ctrl->value); + if (rval < 0) + goto exit; + + rval = si4713_set_power_state(sdev, POWER_DOWN); + } else { + rval = si4713_set_power_state(sdev, POWER_UP); + if (rval < 0) + goto exit; + + rval = si4713_setup(sdev); + if (rval < 0) + goto exit; + + rval = si4713_set_mute(sdev, ctrl->value); + } + break; + } + +exit: + return rval; +} + +/* si4713_ioctl - deal with private ioctls (only rnl for now) */ +long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct si4713_device *sdev = to_si4713_device(sd); + struct si4713_rnl *rnl = arg; + u16 frequency; + int rval = 0; + + if (!arg) + return -EINVAL; + + mutex_lock(&sdev->mutex); + switch (cmd) { + case SI4713_IOC_MEASURE_RNL: + frequency = v4l2_to_si4713(rnl->frequency); + + if (sdev->power_state) { + /* Set desired measurement frequency */ + rval = si4713_tx_tune_measure(sdev, frequency, 0); + if (rval < 0) + goto unlock; + /* get results from tune status */ + rval = si4713_update_tune_status(sdev); + if (rval < 0) + goto unlock; + } + rnl->rnl = sdev->tune_rnl; + break; + + default: + /* nothing */ + rval = -ENOIOCTLCMD; + } + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = { + .queryctrl = si4713_queryctrl, + .g_ext_ctrls = si4713_g_ext_ctrls, + .s_ext_ctrls = si4713_s_ext_ctrls, + .g_ctrl = si4713_g_ctrl, + .s_ctrl = si4713_s_ctrl, + .ioctl = si4713_ioctl, +}; + +/* si4713_g_modulator - get modulator attributes */ +static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + + if (!sdev) { + rval = -ENODEV; + goto exit; + } + + if (vm->index > 0) { + rval = -EINVAL; + goto exit; + } + + strncpy(vm->name, "FM Modulator", 32); + vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW | + V4L2_TUNER_CAP_RDS; + + /* Report current frequency range limits */ + vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW); + vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH); + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + u32 comp_en = 0; + + rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE, + &comp_en); + if (rval < 0) + goto unlock; + + sdev->stereo = get_status_bit(comp_en, 1, 1 << 1); + sdev->rds_info.enabled = get_status_bit(comp_en, 2, 1 << 2); + } + + /* Report current audio mode: mono or stereo */ + if (sdev->stereo) + vm->txsubchans = V4L2_TUNER_SUB_STEREO; + else + vm->txsubchans = V4L2_TUNER_SUB_MONO; + + /* Report rds feature status */ + if (sdev->rds_info.enabled) + vm->txsubchans |= V4L2_TUNER_SUB_RDS; + else + vm->txsubchans &= ~V4L2_TUNER_SUB_RDS; + +unlock: + mutex_unlock(&sdev->mutex); +exit: + return rval; +} + +/* si4713_s_modulator - set modulator attributes */ +static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + u16 stereo, rds; + u32 p; + + if (!sdev) { + rval = -ENODEV; + goto exit; + } + + if (vm->index > 0) { + rval = -EINVAL; + goto exit; + } + + /* Set audio mode: mono or stereo */ + if (vm->txsubchans & V4L2_TUNER_SUB_STEREO) + stereo = 1; + else if (vm->txsubchans & V4L2_TUNER_SUB_MONO) + stereo = 0; + else + rval = -EINVAL; + if (rval < 0) + goto exit; + + rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS); + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + rval = si4713_read_property(sdev, + SI4713_TX_COMPONENT_ENABLE, &p); + if (rval < 0) + goto unlock; + + p = set_bits(p, stereo, 1, 1 << 1); + p = set_bits(p, rds, 2, 1 << 2); + + rval = si4713_write_property(sdev, + SI4713_TX_COMPONENT_ENABLE, p); + if (rval < 0) + goto unlock; + } + + sdev->stereo = stereo; + sdev->rds_info.enabled = rds; + +unlock: + mutex_unlock(&sdev->mutex); +exit: + return rval; +} + +/* si4713_g_frequency - get tuner or modulator radio frequency */ +static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + + f->type = V4L2_TUNER_RADIO; + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + u16 freq; + u8 p, a, n; + + rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n); + if (rval < 0) + goto unlock; + + sdev->frequency = freq; + } + + f->frequency = si4713_to_v4l2(sdev->frequency); + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +/* si4713_s_frequency - set tuner or modulator radio frequency */ +static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) +{ + struct si4713_device *sdev = to_si4713_device(sd); + int rval = 0; + u16 frequency = v4l2_to_si4713(f->frequency); + + /* Check frequency range */ + if (frequency < FREQ_RANGE_LOW || frequency > FREQ_RANGE_HIGH) + return -EDOM; + + mutex_lock(&sdev->mutex); + + if (sdev->power_state) { + rval = si4713_tx_tune_freq(sdev, frequency); + if (rval < 0) + goto unlock; + frequency = rval; + rval = 0; + } + sdev->frequency = frequency; + f->frequency = si4713_to_v4l2(frequency); + +unlock: + mutex_unlock(&sdev->mutex); + return rval; +} + +static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = { + .g_frequency = si4713_g_frequency, + .s_frequency = si4713_s_frequency, + .g_modulator = si4713_g_modulator, + .s_modulator = si4713_s_modulator, +}; + +static const struct v4l2_subdev_ops si4713_subdev_ops = { + .core = &si4713_subdev_core_ops, + .tuner = &si4713_subdev_tuner_ops, +}; + +/* + * I2C driver interface + */ +/* si4713_probe - probe for the device */ +static int si4713_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct si4713_device *sdev; + int rval; + + sdev = kzalloc(sizeof *sdev, GFP_KERNEL); + if (!sdev) { + dev_err(&client->dev, "Failed to alloc video device.\n"); + rval = -ENOMEM; + goto exit; + } + + sdev->platform_data = client->dev.platform_data; + if (!sdev->platform_data) { + v4l2_err(&sdev->sd, "No platform data registered.\n"); + rval = -ENODEV; + goto free_sdev; + } + + v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops); + + mutex_init(&sdev->mutex); + init_completion(&sdev->work); + + if (client->irq) { + rval = request_irq(client->irq, + si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, + client->name, sdev); + if (rval < 0) { + v4l2_err(&sdev->sd, "Could not request IRQ\n"); + goto free_sdev; + } + v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n"); + } else { + v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n"); + } + + rval = si4713_initialize(sdev); + if (rval < 0) { + v4l2_err(&sdev->sd, "Failed to probe device information.\n"); + goto free_irq; + } + + return 0; + +free_irq: + if (client->irq) + free_irq(client->irq, sdev); +free_sdev: + kfree(sdev); +exit: + return rval; +} + +/* si4713_remove - remove the device */ +static int si4713_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct si4713_device *sdev = to_si4713_device(sd); + + if (sdev->power_state) + si4713_set_power_state(sdev, POWER_DOWN); + + if (client->irq > 0) + free_irq(client->irq, sdev); + + v4l2_device_unregister_subdev(sd); + + kfree(sdev); + + return 0; +} + +/* si4713_i2c_driver - i2c driver interface */ +static const struct i2c_device_id si4713_id[] = { + { "si4713" , 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, si4713_id); + +static struct i2c_driver si4713_i2c_driver = { + .driver = { + .name = "si4713", + }, + .probe = si4713_probe, + .remove = si4713_remove, + .id_table = si4713_id, +}; + +/* Module Interface */ +static int __init si4713_module_init(void) +{ + return i2c_add_driver(&si4713_i2c_driver); +} + +static void __exit si4713_module_exit(void) +{ + i2c_del_driver(&si4713_i2c_driver); +} + +module_init(si4713_module_init); +module_exit(si4713_module_exit); + diff --git a/linux/drivers/media/radio/si4713-i2c.h b/linux/drivers/media/radio/si4713-i2c.h new file mode 100644 index 000000000..faf8cff12 --- /dev/null +++ b/linux/drivers/media/radio/si4713-i2c.h @@ -0,0 +1,237 @@ +/* + * drivers/media/radio/si4713-i2c.h + * + * Property and commands definitions for Si4713 radio transmitter chip. + * + * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT + * Contact: Eduardo Valentin + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#ifndef SI4713_I2C_H +#define SI4713_I2C_H + +#include +#include + +#define SI4713_PRODUCT_NUMBER 0x0D + +/* Command Timeouts */ +#define DEFAULT_TIMEOUT 500 +#define TIMEOUT_SET_PROPERTY 20 +#define TIMEOUT_TX_TUNE_POWER 30000 +#define TIMEOUT_TX_TUNE 110000 +#define TIMEOUT_POWER_UP 200000 + +/* + * Command and its arguments definitions + */ +#define SI4713_PWUP_CTSIEN (1<<7) +#define SI4713_PWUP_GPO2OEN (1<<6) +#define SI4713_PWUP_PATCH (1<<5) +#define SI4713_PWUP_XOSCEN (1<<4) +#define SI4713_PWUP_FUNC_TX 0x02 +#define SI4713_PWUP_FUNC_PATCH 0x0F +#define SI4713_PWUP_OPMOD_ANALOG 0x50 +#define SI4713_PWUP_OPMOD_DIGITAL 0x0F +#define SI4713_PWUP_NARGS 2 +#define SI4713_PWUP_NRESP 1 +#define SI4713_CMD_POWER_UP 0x01 + +#define SI4713_GETREV_NRESP 9 +#define SI4713_CMD_GET_REV 0x10 + +#define SI4713_PWDN_NRESP 1 +#define SI4713_CMD_POWER_DOWN 0x11 + +#define SI4713_SET_PROP_NARGS 5 +#define SI4713_SET_PROP_NRESP 1 +#define SI4713_CMD_SET_PROPERTY 0x12 + +#define SI4713_GET_PROP_NARGS 3 +#define SI4713_GET_PROP_NRESP 4 +#define SI4713_CMD_GET_PROPERTY 0x13 + +#define SI4713_GET_STATUS_NRESP 1 +#define SI4713_CMD_GET_INT_STATUS 0x14 + +#define SI4713_CMD_PATCH_ARGS 0x15 +#define SI4713_CMD_PATCH_DATA 0x16 + +#define SI4713_MAX_FREQ 10800 +#define SI4713_MIN_FREQ 7600 +#define SI4713_TXFREQ_NARGS 3 +#define SI4713_TXFREQ_NRESP 1 +#define SI4713_CMD_TX_TUNE_FREQ 0x30 + +#define SI4713_MAX_POWER 120 +#define SI4713_MIN_POWER 88 +#define SI4713_MAX_ANTCAP 191 +#define SI4713_MIN_ANTCAP 0 +#define SI4713_TXPWR_NARGS 4 +#define SI4713_TXPWR_NRESP 1 +#define SI4713_CMD_TX_TUNE_POWER 0x31 + +#define SI4713_TXMEA_NARGS 4 +#define SI4713_TXMEA_NRESP 1 +#define SI4713_CMD_TX_TUNE_MEASURE 0x32 + +#define SI4713_INTACK_MASK 0x01 +#define SI4713_TXSTATUS_NARGS 1 +#define SI4713_TXSTATUS_NRESP 8 +#define SI4713_CMD_TX_TUNE_STATUS 0x33 + +#define SI4713_OVERMOD_BIT (1 << 2) +#define SI4713_IALH_BIT (1 << 1) +#define SI4713_IALL_BIT (1 << 0) +#define SI4713_ASQSTATUS_NARGS 1 +#define SI4713_ASQSTATUS_NRESP 5 +#define SI4713_CMD_TX_ASQ_STATUS 0x34 + +#define SI4713_RDSBUFF_MODE_MASK 0x87 +#define SI4713_RDSBUFF_NARGS 7 +#define SI4713_RDSBUFF_NRESP 6 +#define SI4713_CMD_TX_RDS_BUFF 0x35 + +#define SI4713_RDSPS_PSID_MASK 0x1F +#define SI4713_RDSPS_NARGS 5 +#define SI4713_RDSPS_NRESP 1 +#define SI4713_CMD_TX_RDS_PS 0x36 + +#define SI4713_CMD_GPO_CTL 0x80 +#define SI4713_CMD_GPO_SET 0x81 + +/* + * Bits from status response + */ +#define SI4713_CTS (1<<7) +#define SI4713_ERR (1<<6) +#define SI4713_RDS_INT (1<<2) +#define SI4713_ASQ_INT (1<<1) +#define SI4713_STC_INT (1<<0) + +/* + * Property definitions + */ +#define SI4713_GPO_IEN 0x0001 +#define SI4713_DIG_INPUT_FORMAT 0x0101 +#define SI4713_DIG_INPUT_SAMPLE_RATE 0x0103 +#define SI4713_REFCLK_FREQ 0x0201 +#define SI4713_REFCLK_PRESCALE 0x0202 +#define SI4713_TX_COMPONENT_ENABLE 0x2100 +#define SI4713_TX_AUDIO_DEVIATION 0x2101 +#define SI4713_TX_PILOT_DEVIATION 0x2102 +#define SI4713_TX_RDS_DEVIATION 0x2103 +#define SI4713_TX_LINE_INPUT_LEVEL 0x2104 +#define SI4713_TX_LINE_INPUT_MUTE 0x2105 +#define SI4713_TX_PREEMPHASIS 0x2106 +#define SI4713_TX_PILOT_FREQUENCY 0x2107 +#define SI4713_TX_ACOMP_ENABLE 0x2200 +#define SI4713_TX_ACOMP_THRESHOLD 0x2201 +#define SI4713_TX_ACOMP_ATTACK_TIME 0x2202 +#define SI4713_TX_ACOMP_RELEASE_TIME 0x2203 +#define SI4713_TX_ACOMP_GAIN 0x2204 +#define SI4713_TX_LIMITER_RELEASE_TIME 0x2205 +#define SI4713_TX_ASQ_INTERRUPT_SOURCE 0x2300 +#define SI4713_TX_ASQ_LEVEL_LOW 0x2301 +#define SI4713_TX_ASQ_DURATION_LOW 0x2302 +#define SI4713_TX_ASQ_LEVEL_HIGH 0x2303 +#define SI4713_TX_ASQ_DURATION_HIGH 0x2304 +#define SI4713_TX_RDS_INTERRUPT_SOURCE 0x2C00 +#define SI4713_TX_RDS_PI 0x2C01 +#define SI4713_TX_RDS_PS_MIX 0x2C02 +#define SI4713_TX_RDS_PS_MISC 0x2C03 +#define SI4713_TX_RDS_PS_REPEAT_COUNT 0x2C04 +#define SI4713_TX_RDS_PS_MESSAGE_COUNT 0x2C05 +#define SI4713_TX_RDS_PS_AF 0x2C06 +#define SI4713_TX_RDS_FIFO_SIZE 0x2C07 + +#define PREEMPHASIS_USA 75 +#define PREEMPHASIS_EU 50 +#define PREEMPHASIS_DISABLED 0 +#define FMPE_USA 0x00 +#define FMPE_EU 0x01 +#define FMPE_DISABLED 0x02 + +#define POWER_UP 0x01 +#define POWER_DOWN 0x00 + +struct rds_info { + u32 pi; +#define MAX_RDS_PTY 31 + u32 pty; +#define MAX_RDS_DEVIATION 90000 + u32 deviation; +/* + * PSNAME is known to be defined as 8 character sized (RDS Spec). + * However, there is receivers which scroll PSNAME 8xN sized. + */ +#define MAX_RDS_PS_NAME 96 + u8 ps_name[MAX_RDS_PS_NAME + 1]; +/* + * MAX_RDS_RADIO_TEXT is known to be defined as 32 (2A group) or 64 (2B group) + * character sized (RDS Spec). + * However, there is receivers which scroll them as well. + */ +#define MAX_RDS_RADIO_TEXT 384 + u8 radio_text[MAX_RDS_RADIO_TEXT + 1]; + u32 enabled; +}; + +struct limiter_info { +#define MAX_LIMITER_RELEASE_TIME 102390 + u32 release_time; +#define MAX_LIMITER_DEVIATION 90000 + u32 deviation; + u32 enabled; +}; + +struct pilot_info { +#define MAX_PILOT_DEVIATION 90000 + u32 deviation; +#define MAX_PILOT_FREQUENCY 19000 + u32 frequency; + u32 enabled; +}; + +struct acomp_info { +#define MAX_ACOMP_RELEASE_TIME 1000000 + u32 release_time; +#define MAX_ACOMP_ATTACK_TIME 5000 + u32 attack_time; +#define MAX_ACOMP_THRESHOLD 0 +#define MIN_ACOMP_THRESHOLD (-40) + s32 threshold; +#define MAX_ACOMP_GAIN 20 + u32 gain; + u32 enabled; +}; + +/* + * si4713_device - private data + */ +struct si4713_device { + /* v4l2_subdev and i2c reference (v4l2_subdev priv data) */ + struct v4l2_subdev sd; + /* private data structures */ + struct mutex mutex; + struct completion work; + struct si4713_platform_data *platform_data; + struct rds_info rds_info; + struct limiter_info limiter_info; + struct pilot_info pilot_info; + struct acomp_info acomp_info; + u32 frequency; + u32 preemphasis; + u32 mute; + u32 power_level; + u32 power_state; + u32 antenna_capacitor; + u32 stereo; + u32 tune_rnl; +}; +#endif /* ifndef SI4713_I2C_H */ diff --git a/linux/include/media/radio-si4713.h b/linux/include/media/radio-si4713.h new file mode 100644 index 000000000..f6aae29c7 --- /dev/null +++ b/linux/include/media/radio-si4713.h @@ -0,0 +1,30 @@ +/* + * include/media/radio-si4713.h + * + * Board related data definitions for Si4713 radio transmitter chip. + * + * Copyright (c) 2009 Nokia Corporation + * Contact: Eduardo Valentin + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#ifndef RADIO_SI4713_H +#define RADIO_SI4713_H + +#include + +#define SI4713_NAME "radio-si4713" + +/* + * Platform dependent definition + */ +struct radio_si4713_platform_data { + int i2c_bus; + struct i2c_board_info *subdev_board_info; +}; + +#endif /* ifndef RADIO_SI4713_H*/ diff --git a/linux/include/media/si4713.h b/linux/include/media/si4713.h new file mode 100644 index 000000000..99850a54e --- /dev/null +++ b/linux/include/media/si4713.h @@ -0,0 +1,49 @@ +/* + * include/media/si4713.h + * + * Board related data definitions for Si4713 i2c device driver. + * + * Copyright (c) 2009 Nokia Corporation + * Contact: Eduardo Valentin + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#ifndef SI4713_H +#define SI4713_H + +/* The SI4713 I2C sensor chip has a fixed slave address of 0xc6 or 0x22. */ +#define SI4713_I2C_ADDR_BUSEN_HIGH 0x63 +#define SI4713_I2C_ADDR_BUSEN_LOW 0x11 + +/* + * Platform dependent definition + */ +struct si4713_platform_data { + /* Set power state, zero is off, non-zero is on. */ + int (*set_power)(int power); +}; + +/* + * Structure to query for Received Noise Level (RNL). + */ +struct si4713_rnl { + __u32 index; /* modulator index */ + __u32 frequency; /* frequency to peform rnl measurement */ + __s32 rnl; /* result of measurement in dBuV */ + __u32 reserved[4]; /* drivers and apps must init this to 0 */ +}; + +/* + * This is the ioctl number to query for rnl. Users must pass a + * struct si4713_rnl pointer specifying desired frequency in 'frequency' field + * following driver capabilities (i.e V4L2_TUNER_CAP_LOW). + * Driver must return measured value in the same struture, filling 'rnl' field. + */ +#define SI4713_IOC_MEASURE_RNL _IOWR('V', BASE_VIDIOC_PRIVATE + 0, \ + struct si4713_rnl) + +#endif /* ifndef SI4713_H*/ diff --git a/linux/linux/Documentation/video4linux/si4713.txt b/linux/linux/Documentation/video4linux/si4713.txt deleted file mode 100644 index 25abdb782..000000000 --- a/linux/linux/Documentation/video4linux/si4713.txt +++ /dev/null @@ -1,176 +0,0 @@ -Driver for I2C radios for the Silicon Labs Si4713 FM Radio Transmitters - -Copyright (c) 2009 Nokia Corporation -Contact: Eduardo Valentin - - -Information about the Device -============================ -This chip is a Silicon Labs product. It is a I2C device, currently on 0x63 address. -Basically, it has transmission and signal noise level measurement features. - -The Si4713 integrates transmit functions for FM broadcast stereo transmission. -The chip also allows integrated receive power scanning to identify low signal -power FM channels. - -The chip is programmed using commands and responses. There are also several -properties which can change the behavior of this chip. - -Users must comply with local regulations on radio frequency (RF) transmission. - -Device driver description -========================= -There are two modules to handle this device. One is a I2C device driver -and the other is a platform driver. - -The I2C device driver exports a v4l2-subdev interface to the kernel. -All properties can also be accessed by v4l2 extended controls interface, by -using the v4l2-subdev calls (g_ext_ctrls, s_ext_ctrls). - -The platform device driver exports a v4l2 radio device interface to user land. -So, it uses the I2C device driver as a sub device in order to send the user -commands to the actual device. Basically it is a wrapper to the I2C device driver. - -Applications can use v4l2 radio API to specify frequency of operation, mute state, -etc. But mostly of its properties will be present in the extended controls. - -When the v4l2 mute property is set to 1 (true), the driver will turn the chip off. - -Properties description -====================== - -The properties can be accessed using v4l2 extended controls. -Here is an output from v4l2-ctl util: -/ # v4l2-ctl -d /dev/radio0 --all -L -Driver Info: - Driver name : radio-si4713 - Card type : Silicon Labs Si4713 Modulator - Bus info : - Driver version: 0 - Capabilities : 0x00080800 - RDS Output - Modulator -Audio output: 0 (FM Modulator Audio Out) -Frequency: 1408000 (88.000000 MHz) -Video Standard = 0x00000000 -Modulator: - Name : FM Modulator - Capabilities : 62.5 Hz stereo rds - Frequency range : 76.0 MHz - 108.0 MHz - Subchannel modulation: stereo+rds - -User Controls - - mute (bool) : default=1 value=0 - -FM Radio Modulator Controls - - rds_signal_deviation (int) : min=0 max=90000 step=10 default=200 value=200 flags=slider - rds_program_id (int) : min=0 max=65535 step=1 default=0 value=0 - rds_program_type (int) : min=0 max=31 step=1 default=0 value=0 - rds_ps_name (str) : min=0 max=96 step=8 value='si4713 ' - rds_radio_text (str) : min=0 max=384 step=32 value='' - audio_limiter_feature_enabled (bool) : default=1 value=1 - audio_limiter_release_time (int) : min=250 max=102390 step=50 default=5010 value=5010 flags=slider - audio_limiter_deviation (int) : min=0 max=90000 step=10 default=66250 value=66250 flags=slider -audio_compression_feature_enabl (bool) : default=1 value=1 - audio_compression_gain (int) : min=0 max=20 step=1 default=15 value=15 flags=slider - audio_compression_threshold (int) : min=-40 max=0 step=1 default=-40 value=-40 flags=slider - audio_compression_attack_time (int) : min=0 max=5000 step=500 default=0 value=0 flags=slider - audio_compression_release_time (int) : min=100000 max=1000000 step=100000 default=1000000 value=1000000 flags=slider - pilot_tone_feature_enabled (bool) : default=1 value=1 - pilot_tone_deviation (int) : min=0 max=90000 step=10 default=6750 value=6750 flags=slider - pilot_tone_frequency (int) : min=0 max=19000 step=1 default=19000 value=19000 flags=slider - pre_emphasis_settings (menu) : min=0 max=2 default=1 value=1 - tune_power_level (int) : min=0 max=120 step=1 default=88 value=88 flags=slider - tune_antenna_capacitor (int) : min=0 max=191 step=1 default=0 value=110 flags=slider -/ # - -Here is a summary of them: - -* Pilot is an audible tone sent by the device. - -pilot_frequency - Configures the frequency of the stereo pilot tone. -pilot_deviation - Configures pilot tone frequency deviation level. -pilot_enabled - Enables or disables the pilot tone feature. - -* The si4713 device is capable of applying audio compression to the transmitted signal. - -acomp_enabled - Enables or disables the audio dynamic range control feature. -acomp_gain - Sets the gain for audio dynamic range control. -acomp_threshold - Sets the threshold level for audio dynamic range control. -acomp_attack_time - Sets the attack time for audio dynamic range control. -acomp_release_time - Sets the release time for audio dynamic range control. - -* Limiter setups audio deviation limiter feature. Once a over deviation occurs, -it is possible to adjust the front-end gain of the audio input and always -prevent over deviation. - -limiter_enabled - Enables or disables the limiter feature. -limiter_deviation - Configures audio frequency deviation level. -limiter_release_time - Sets the limiter release time. - -* Tuning power - -power_level - Sets the output power level for signal transmission. -antenna_capacitor - This selects the value of antenna tuning capacitor manually -or automatically if set to zero. - -* RDS related - -rds_ps_name - Sets the RDS ps name field for transmission. -rds_radio_text - Sets the RDS radio text for transmission. -rds_pi - Sets the RDS PI field for transmission. -rds_pty - Sets the RDS PTY field for transmission. - -* Region related - -preemphasis - sets the preemphasis to be applied for transmission. - -RNL -=== - -This device also has an interface to measure received noise level. To do that, you should -ioctl the device node. Here is an code of example: - -int main (int argc, char *argv[]) -{ - struct si4713_rnl rnl; - int fd = open("/dev/radio0", O_RDWR); - int rval; - - if (argc < 2) - return -EINVAL; - - if (fd < 0) - return fd; - - sscanf(argv[1], "%d", &rnl.frequency); - - rval = ioctl(fd, SI4713_IOC_MEASURE_RNL, &rnl); - if (rval < 0) - return rval; - - printf("received noise level: %d\n", rnl.rnl); - - close(fd); -} - -The struct si4713_rnl and SI4713_IOC_MEASURE_RNL are defined under -include/media/si4713.h. - -Stereo/Mono and RDS subchannels -=============================== - -The device can also be configured using the available sub channels for -transmission. To do that use S/G_MODULATOR ioctl and configure txsubchans properly. -Refer to v4l2-spec for proper use of this ioctl. - -Testing -======= -Testing is usually done with v4l2-ctl utility for managing FM tuner cards. -The tool can be found in v4l-dvb repository under v4l2-apps/util directory. - -Example for setting rds ps name: -# v4l2-ctl -d /dev/radio0 --set-ctrl=rds_ps_name="Dummy" - diff --git a/linux/linux/drivers/media/radio/radio-si4713.c b/linux/linux/drivers/media/radio/radio-si4713.c deleted file mode 100644 index 65c14b704..000000000 --- a/linux/linux/drivers/media/radio/radio-si4713.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * drivers/media/radio/radio-si4713.c - * - * Platform Driver for Silicon Labs Si4713 FM Radio Transmitter: - * - * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT - * Contact: Eduardo Valentin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* module parameters */ -static int radio_nr = -1; /* radio device minor (-1 ==> auto assign) */ -module_param(radio_nr, int, 0); -MODULE_PARM_DESC(radio_nr, - "Minor number for radio device (-1 ==> auto assign)"); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Eduardo Valentin "); -MODULE_DESCRIPTION("Platform driver for Si4713 FM Radio Transmitter"); -MODULE_VERSION("0.0.1"); - -/* Driver state struct */ -struct radio_si4713_device { - struct v4l2_device v4l2_dev; - struct video_device *radio_dev; -}; - -/* radio_si4713_fops - file operations interface */ -static const struct v4l2_file_operations radio_si4713_fops = { - .owner = THIS_MODULE, - .ioctl = video_ioctl2, -}; - -/* Video4Linux Interface */ -static int radio_si4713_fill_audout(struct v4l2_audioout *vao) -{ - /* TODO: check presence of audio output */ - strlcpy(vao->name, "FM Modulator Audio Out", 32); - - return 0; -} - -static int radio_si4713_enumaudout(struct file *file, void *priv, - struct v4l2_audioout *vao) -{ - return radio_si4713_fill_audout(vao); -} - -static int radio_si4713_g_audout(struct file *file, void *priv, - struct v4l2_audioout *vao) -{ - int rval = radio_si4713_fill_audout(vao); - - vao->index = 0; - - return rval; -} - -static int radio_si4713_s_audout(struct file *file, void *priv, - struct v4l2_audioout *vao) -{ - return vao->index ? -EINVAL : 0; -} - -/* radio_si4713_querycap - query device capabilities */ -static int radio_si4713_querycap(struct file *file, void *priv, - struct v4l2_capability *capability) -{ - struct radio_si4713_device *rsdev; - - rsdev = video_get_drvdata(video_devdata(file)); - - strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver)); - strlcpy(capability->card, "Silicon Labs Si4713 Modulator", - sizeof(capability->card)); - capability->capabilities = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT; - - return 0; -} - -/* radio_si4713_queryctrl - enumerate control items */ -static int radio_si4713_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - /* Must be sorted from low to high control ID! */ - static const u32 user_ctrls[] = { - V4L2_CID_USER_CLASS, - V4L2_CID_AUDIO_MUTE, - 0 - }; - - /* Must be sorted from low to high control ID! */ - static const u32 fmtx_ctrls[] = { - V4L2_CID_FM_TX_CLASS, - V4L2_CID_RDS_TX_DEVIATION, - V4L2_CID_RDS_TX_PI, - V4L2_CID_RDS_TX_PTY, - V4L2_CID_RDS_TX_PS_NAME, - V4L2_CID_RDS_TX_RADIO_TEXT, - V4L2_CID_AUDIO_LIMITER_ENABLED, - V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, - V4L2_CID_AUDIO_LIMITER_DEVIATION, - V4L2_CID_AUDIO_COMPRESSION_ENABLED, - V4L2_CID_AUDIO_COMPRESSION_GAIN, - V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, - V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, - V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, - V4L2_CID_PILOT_TONE_ENABLED, - V4L2_CID_PILOT_TONE_DEVIATION, - V4L2_CID_PILOT_TONE_FREQUENCY, - V4L2_CID_TUNE_PREEMPHASIS, - V4L2_CID_TUNE_POWER_LEVEL, - V4L2_CID_TUNE_ANTENNA_CAPACITOR, - 0 - }; - static const u32 *ctrl_classes[] = { - user_ctrls, - fmtx_ctrls, - NULL - }; - struct radio_si4713_device *rsdev; - - rsdev = video_get_drvdata(video_devdata(file)); - - qc->id = v4l2_ctrl_next(ctrl_classes, qc->id); - if (qc->id == 0) - return -EINVAL; - - if (qc->id == V4L2_CID_USER_CLASS || qc->id == V4L2_CID_FM_TX_CLASS) - return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0); - - return v4l2_device_call_until_err(&rsdev->v4l2_dev, 0, core, - queryctrl, qc); -} - -/* - * v4l2 ioctl call backs. - * we are just a wrapper for v4l2_sub_devs. - */ -static inline struct v4l2_device *get_v4l2_dev(struct file *file) -{ - return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev; -} - -static int radio_si4713_g_ext_ctrls(struct file *file, void *p, - struct v4l2_ext_controls *vecs) -{ - return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, - g_ext_ctrls, vecs); -} - -static int radio_si4713_s_ext_ctrls(struct file *file, void *p, - struct v4l2_ext_controls *vecs) -{ - return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, - s_ext_ctrls, vecs); -} - -static int radio_si4713_g_ctrl(struct file *file, void *p, - struct v4l2_control *vc) -{ - return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, - g_ctrl, vc); -} - -static int radio_si4713_s_ctrl(struct file *file, void *p, - struct v4l2_control *vc) -{ - return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, - s_ctrl, vc); -} - -static int radio_si4713_g_modulator(struct file *file, void *p, - struct v4l2_modulator *vm) -{ - return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, - g_modulator, vm); -} - -static int radio_si4713_s_modulator(struct file *file, void *p, - struct v4l2_modulator *vm) -{ - return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, - s_modulator, vm); -} - -static int radio_si4713_g_frequency(struct file *file, void *p, - struct v4l2_frequency *vf) -{ - return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, - g_frequency, vf); -} - -static int radio_si4713_s_frequency(struct file *file, void *p, - struct v4l2_frequency *vf) -{ - return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner, - s_frequency, vf); -} - -static long radio_si4713_default(struct file *file, void *p, int cmd, void *arg) -{ - return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core, - ioctl, cmd, arg); -} - -static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = { - .vidioc_enumaudout = radio_si4713_enumaudout, - .vidioc_g_audout = radio_si4713_g_audout, - .vidioc_s_audout = radio_si4713_s_audout, - .vidioc_querycap = radio_si4713_querycap, - .vidioc_queryctrl = radio_si4713_queryctrl, - .vidioc_g_ext_ctrls = radio_si4713_g_ext_ctrls, - .vidioc_s_ext_ctrls = radio_si4713_s_ext_ctrls, - .vidioc_g_ctrl = radio_si4713_g_ctrl, - .vidioc_s_ctrl = radio_si4713_s_ctrl, - .vidioc_g_modulator = radio_si4713_g_modulator, - .vidioc_s_modulator = radio_si4713_s_modulator, - .vidioc_g_frequency = radio_si4713_g_frequency, - .vidioc_s_frequency = radio_si4713_s_frequency, - .vidioc_default = radio_si4713_default, -}; - -/* radio_si4713_vdev_template - video device interface */ -static struct video_device radio_si4713_vdev_template = { - .fops = &radio_si4713_fops, - .name = "radio-si4713", - .release = video_device_release, - .ioctl_ops = &radio_si4713_ioctl_ops, -}; - -/* Platform driver interface */ -/* radio_si4713_pdriver_probe - probe for the device */ -static int radio_si4713_pdriver_probe(struct platform_device *pdev) -{ - struct radio_si4713_platform_data *pdata = pdev->dev.platform_data; - struct radio_si4713_device *rsdev; - struct i2c_adapter *adapter; - struct v4l2_subdev *sd; - int rval = 0; - - if (!pdata) { - dev_err(&pdev->dev, "Cannot proceed without platform data.\n"); - rval = -EINVAL; - goto exit; - } - - rsdev = kzalloc(sizeof *rsdev, GFP_KERNEL); - if (!rsdev) { - dev_err(&pdev->dev, "Failed to alloc video device.\n"); - rval = -ENOMEM; - goto exit; - } - - rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev); - if (rval) { - dev_err(&pdev->dev, "Failed to register v4l2 device.\n"); - goto free_rsdev; - } - - adapter = i2c_get_adapter(pdata->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "Cannot get i2c adapter %d\n", - pdata->i2c_bus); - rval = -ENODEV; - goto unregister_v4l2_dev; - } - - sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter, "si4713_i2c", - pdata->subdev_board_info, NULL); - if (!sd) { - dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n"); - rval = -ENODEV; - goto unregister_v4l2_dev; - } - - rsdev->radio_dev = video_device_alloc(); - if (!rsdev->radio_dev) { - dev_err(&pdev->dev, "Failed to alloc video device.\n"); - rval = -ENOMEM; - goto unregister_v4l2_dev; - } - - memcpy(rsdev->radio_dev, &radio_si4713_vdev_template, - sizeof(radio_si4713_vdev_template)); - video_set_drvdata(rsdev->radio_dev, rsdev); - if (video_register_device(rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) { - dev_err(&pdev->dev, "Could not register video device.\n"); - rval = -EIO; - goto free_vdev; - } - dev_info(&pdev->dev, "New device successfully probed\n"); - - goto exit; - -free_vdev: - video_device_release(rsdev->radio_dev); -unregister_v4l2_dev: - v4l2_device_unregister(&rsdev->v4l2_dev); -free_rsdev: - kfree(rsdev); -exit: - return rval; -} - -/* radio_si4713_pdriver_remove - remove the device */ -static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev) -{ - struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); - struct radio_si4713_device *rsdev = container_of(v4l2_dev, - struct radio_si4713_device, - v4l2_dev); - - video_unregister_device(rsdev->radio_dev); - v4l2_device_unregister(&rsdev->v4l2_dev); - kfree(rsdev); - - return 0; -} - -static struct platform_driver radio_si4713_pdriver = { - .driver = { - .name = "radio-si4713", - }, - .probe = radio_si4713_pdriver_probe, - .remove = __exit_p(radio_si4713_pdriver_remove), -}; - -/* Module Interface */ -static int __init radio_si4713_module_init(void) -{ - return platform_driver_register(&radio_si4713_pdriver); -} - -static void __exit radio_si4713_module_exit(void) -{ - platform_driver_unregister(&radio_si4713_pdriver); -} - -module_init(radio_si4713_module_init); -module_exit(radio_si4713_module_exit); - diff --git a/linux/linux/drivers/media/radio/si4713-i2c.c b/linux/linux/drivers/media/radio/si4713-i2c.c deleted file mode 100644 index 8cbbe48b0..000000000 --- a/linux/linux/drivers/media/radio/si4713-i2c.c +++ /dev/null @@ -1,2067 +0,0 @@ -/* - * drivers/media/radio/si4713-i2c.c - * - * Silicon Labs Si4713 FM Radio Transmitter I2C commands. - * - * Copyright (c) 2009 Nokia Corporation - * Contact: Eduardo Valentin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "si4713-i2c.h" - -/* module parameters */ -static int debug; -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug level (0 - 2)"); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Eduardo Valentin "); -MODULE_DESCRIPTION("I2C driver for Si4713 FM Radio Transmitter"); -MODULE_VERSION("0.0.1"); - -#define DEFAULT_RDS_PI 0x00 -#define DEFAULT_RDS_PTY 0x00 -#define DEFAULT_RDS_PS_NAME "" -#define DEFAULT_RDS_RADIO_TEXT DEFAULT_RDS_PS_NAME -#define DEFAULT_RDS_DEVIATION 0x00C8 -#define DEFAULT_RDS_PS_REPEAT_COUNT 0x0003 -#define DEFAULT_LIMITER_RTIME 0x1392 -#define DEFAULT_LIMITER_DEV 0x102CA -#define DEFAULT_PILOT_FREQUENCY 0x4A38 -#define DEFAULT_PILOT_DEVIATION 0x1A5E -#define DEFAULT_ACOMP_ATIME 0x0000 -#define DEFAULT_ACOMP_RTIME 0xF4240L -#define DEFAULT_ACOMP_GAIN 0x0F -#define DEFAULT_ACOMP_THRESHOLD (-0x28) -#define DEFAULT_MUTE 0x01 -#define DEFAULT_POWER_LEVEL 88 -#define DEFAULT_FREQUENCY 8800 -#define DEFAULT_PREEMPHASIS FMPE_EU -#define DEFAULT_TUNE_RNL 0xFF - -#define to_si4713_device(sd) container_of(sd, struct si4713_device, sd) - -/* frequency domain transformation (using times 10 to avoid floats) */ -#define FREQDEV_UNIT 100000 -#define FREQV4L2_MULTI 625 -#define si4713_to_v4l2(f) ((f * FREQDEV_UNIT) / FREQV4L2_MULTI) -#define v4l2_to_si4713(f) ((f * FREQV4L2_MULTI) / FREQDEV_UNIT) -#define FREQ_RANGE_LOW 7600 -#define FREQ_RANGE_HIGH 10800 - -#define MAX_ARGS 7 - -#define RDS_BLOCK 8 -#define RDS_BLOCK_CLEAR 0x03 -#define RDS_BLOCK_LOAD 0x04 -#define RDS_RADIOTEXT_2A 0x20 -#define RDS_RADIOTEXT_BLK_SIZE 4 -#define RDS_RADIOTEXT_INDEX_MAX 0x0F -#define RDS_CARRIAGE_RETURN 0x0D - -#define rds_ps_nblocks(len) ((len / RDS_BLOCK) + (len % RDS_BLOCK ? 1 : 0)) - -#define get_status_bit(p, b, m) (((p) & (m)) >> (b)) -#define set_bits(p, v, b, m) (((p) & ~(m)) | ((v) << (b))) - -#define ATTACK_TIME_UNIT 500 - -#define POWER_OFF 0x00 -#define POWER_ON 0x01 - -#define msb(x) ((u8)((u16) x >> 8)) -#define lsb(x) ((u8)((u16) x & 0x00FF)) -#define compose_u16(msb, lsb) (((u16)msb << 8) | lsb) -#define check_command_failed(status) (!(status & SI4713_CTS) || \ - (status & SI4713_ERR)) -/* mute definition */ -#define set_mute(p) ((p & 1) | ((p & 1) << 1)); -#define get_mute(p) (p & 0x01) - -#ifdef DEBUG -#define DBG_BUFFER(device, message, buffer, size) \ - { \ - int i; \ - char str[(size)*5]; \ - for (i = 0; i < size; i++) \ - sprintf(str + i * 5, " 0x%02x", buffer[i]); \ - v4l2_dbg(2, debug, device, "%s:%s\n", message, str); \ - } -#else -#define DBG_BUFFER(device, message, buffer, size) -#endif - -/* - * Values for limiter release time (sorted by second column) - * device release - * value time (us) - */ -static long limiter_times[] = { - 2000, 250, - 1000, 500, - 510, 1000, - 255, 2000, - 170, 3000, - 127, 4020, - 102, 5010, - 85, 6020, - 73, 7010, - 64, 7990, - 57, 8970, - 51, 10030, - 25, 20470, - 17, 30110, - 13, 39380, - 10, 51190, - 8, 63690, - 7, 73140, - 6, 85330, - 5, 102390, -}; - -/* - * Values for audio compression release time (sorted by second column) - * device release - * value time (us) - */ -static unsigned long acomp_rtimes[] = { - 0, 100000, - 1, 200000, - 2, 350000, - 3, 525000, - 4, 1000000, -}; - -/* - * Values for preemphasis (sorted by second column) - * device preemphasis - * value value (v4l2) - */ -static unsigned long preemphasis_values[] = { - FMPE_DISABLED, V4L2_PREEMPHASIS_DISABLED, - FMPE_EU, V4L2_PREEMPHASIS_50_uS, - FMPE_USA, V4L2_PREEMPHASIS_75_uS, -}; - -static int usecs_to_dev(unsigned long usecs, unsigned long const array[], - int size) -{ - int i; - int rval = -EINVAL; - - for (i = 0; i < size / 2; i++) - if (array[(i * 2) + 1] >= usecs) { - rval = array[i * 2]; - break; - } - - return rval; -} - -static unsigned long dev_to_usecs(int value, unsigned long const array[], - int size) -{ - int i; - int rval = -EINVAL; - - for (i = 0; i < size / 2; i++) - if (array[i * 2] == value) { - rval = array[(i * 2) + 1]; - break; - } - - return rval; -} - -/* si4713_handler: IRQ handler, just complete work */ -static irqreturn_t si4713_handler(int irq, void *dev) -{ - struct si4713_device *sdev = dev; - - v4l2_dbg(2, debug, &sdev->sd, - "%s: sending signal to completion work.\n", __func__); - complete(&sdev->work); - - return IRQ_HANDLED; -} - -/* - * si4713_send_command - sends a command to si4713 and waits its response - * @sdev: si4713_device structure for the device we are communicating - * @command: command id - * @args: command arguments we are sending (up to 7) - * @argn: actual size of @args - * @response: buffer to place the expected response from the device (up to 15) - * @respn: actual size of @response - * @usecs: amount of time to wait before reading the response (in usecs) - */ -static int si4713_send_command(struct si4713_device *sdev, const u8 command, - const u8 args[], const int argn, - u8 response[], const int respn, const int usecs) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd); - u8 data1[MAX_ARGS + 1]; - int err; - - if (!client->adapter) - return -ENODEV; - - /* First send the command and its arguments */ - data1[0] = command; - memcpy(data1 + 1, args, argn); - DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1); - - err = i2c_master_send(client, data1, argn + 1); - if (err != argn + 1) { - v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n", - command); - return (err > 0) ? -EIO : err; - } - - /* Wait response from interrupt */ - if (!wait_for_completion_timeout(&sdev->work, - usecs_to_jiffies(usecs) + 1)) - v4l2_warn(&sdev->sd, - "(%s) Device took too much time to answer.\n", - __func__); - - /* Then get the response */ - err = i2c_master_recv(client, response, respn); - if (err != respn) { - v4l2_err(&sdev->sd, - "Error while reading response for command 0x%02x\n", - command); - return (err > 0) ? -EIO : err; - } - - DBG_BUFFER(&sdev->sd, "Response", response, respn); - if (check_command_failed(response[0])) - return -EBUSY; - - return 0; -} - -/* - * si4713_read_property - reads a si4713 property - * @sdev: si4713_device structure for the device we are communicating - * @prop: property identification number - * @pv: property value to be returned on success - */ -static int si4713_read_property(struct si4713_device *sdev, u16 prop, u32 *pv) -{ - int err; - u8 val[SI4713_GET_PROP_NRESP]; - /* - * .First byte = 0 - * .Second byte = property's MSB - * .Third byte = property's LSB - */ - const u8 args[SI4713_GET_PROP_NARGS] = { - 0x00, - msb(prop), - lsb(prop), - }; - - err = si4713_send_command(sdev, SI4713_CMD_GET_PROPERTY, - args, ARRAY_SIZE(args), val, - ARRAY_SIZE(val), DEFAULT_TIMEOUT); - - if (err < 0) - return err; - - *pv = compose_u16(val[2], val[3]); - - v4l2_dbg(1, debug, &sdev->sd, - "%s: property=0x%02x value=0x%02x status=0x%02x\n", - __func__, prop, *pv, val[0]); - - return err; -} - -/* - * si4713_write_property - modifies a si4713 property - * @sdev: si4713_device structure for the device we are communicating - * @prop: property identification number - * @val: new value for that property - */ -static int si4713_write_property(struct si4713_device *sdev, u16 prop, u16 val) -{ - int rval; - u8 resp[SI4713_SET_PROP_NRESP]; - /* - * .First byte = 0 - * .Second byte = property's MSB - * .Third byte = property's LSB - * .Fourth byte = value's MSB - * .Fifth byte = value's LSB - */ - const u8 args[SI4713_SET_PROP_NARGS] = { - 0x00, - msb(prop), - lsb(prop), - msb(val), - lsb(val), - }; - - rval = si4713_send_command(sdev, SI4713_CMD_SET_PROPERTY, - args, ARRAY_SIZE(args), - resp, ARRAY_SIZE(resp), - DEFAULT_TIMEOUT); - - if (rval < 0) - return rval; - - v4l2_dbg(1, debug, &sdev->sd, - "%s: property=0x%02x value=0x%02x status=0x%02x\n", - __func__, prop, val, resp[0]); - - /* - * As there is no command response for SET_PROPERTY, - * wait Tcomp time to finish before proceed, in order - * to have property properly set. - */ - msleep(TIMEOUT_SET_PROPERTY); - - return rval; -} - -/* - * si4713_powerup - Powers the device up - * @sdev: si4713_device structure for the device we are communicating - */ -static int si4713_powerup(struct si4713_device *sdev) -{ - int err; - u8 resp[SI4713_PWUP_NRESP]; - /* - * .First byte = Enabled interrupts and boot function - * .Second byte = Input operation mode - */ - const u8 args[SI4713_PWUP_NARGS] = { - SI4713_PWUP_CTSIEN | SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX, - SI4713_PWUP_OPMOD_ANALOG, - }; - - if (sdev->power_state) - return 0; - - sdev->platform_data->set_power(1); - err = si4713_send_command(sdev, SI4713_CMD_POWER_UP, - args, ARRAY_SIZE(args), - resp, ARRAY_SIZE(resp), - TIMEOUT_POWER_UP); - - if (!err) { - v4l2_dbg(1, debug, &sdev->sd, "Powerup response: 0x%02x\n", - resp[0]); - v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n"); - sdev->power_state = POWER_ON; - - err = si4713_write_property(sdev, SI4713_GPO_IEN, - SI4713_STC_INT | SI4713_CTS); - } else { - sdev->platform_data->set_power(0); - } - - return err; -} - -/* - * si4713_powerdown - Powers the device down - * @sdev: si4713_device structure for the device we are communicating - */ -static int si4713_powerdown(struct si4713_device *sdev) -{ - int err; - u8 resp[SI4713_PWDN_NRESP]; - - if (!sdev->power_state) - return 0; - - err = si4713_send_command(sdev, SI4713_CMD_POWER_DOWN, - NULL, 0, - resp, ARRAY_SIZE(resp), - DEFAULT_TIMEOUT); - - if (!err) { - v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n", - resp[0]); - v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n"); - sdev->platform_data->set_power(0); - sdev->power_state = POWER_OFF; - } - - return err; -} - -/* - * si4713_checkrev - Checks if we are treating a device with the correct rev. - * @sdev: si4713_device structure for the device we are communicating - */ -static int si4713_checkrev(struct si4713_device *sdev) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd); - int rval; - u8 resp[SI4713_GETREV_NRESP]; - - mutex_lock(&sdev->mutex); - - rval = si4713_send_command(sdev, SI4713_CMD_GET_REV, - NULL, 0, - resp, ARRAY_SIZE(resp), - DEFAULT_TIMEOUT); - - if (rval < 0) - goto unlock; - - if (resp[1] == SI4713_PRODUCT_NUMBER) { - v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n", - client->addr << 1, client->adapter->name); - } else { - v4l2_err(&sdev->sd, "Invalid product number\n"); - rval = -EINVAL; - } - -unlock: - mutex_unlock(&sdev->mutex); - return rval; -} - -/* - * si4713_wait_stc - Waits STC interrupt and clears status bits. Usefull - * for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS - * @sdev: si4713_device structure for the device we are communicating - * @usecs: timeout to wait for STC interrupt signal - */ -static int si4713_wait_stc(struct si4713_device *sdev, const int usecs) -{ - int err; - u8 resp[SI4713_GET_STATUS_NRESP]; - - /* Wait response from STC interrupt */ - if (!wait_for_completion_timeout(&sdev->work, - usecs_to_jiffies(usecs) + 1)) - v4l2_warn(&sdev->sd, - "%s: device took too much time to answer (%d usec).\n", - __func__, usecs); - - /* Clear status bits */ - err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS, - NULL, 0, - resp, ARRAY_SIZE(resp), - DEFAULT_TIMEOUT); - - if (err < 0) - goto exit; - - v4l2_dbg(1, debug, &sdev->sd, - "%s: status bits: 0x%02x\n", __func__, resp[0]); - - if (!(resp[0] & SI4713_STC_INT)) - err = -EIO; - -exit: - return err; -} - -/* - * si4713_tx_tune_freq - Sets the state of the RF carrier and sets the tuning - * frequency between 76 and 108 MHz in 10 kHz units and - * steps of 50 kHz. - * @sdev: si4713_device structure for the device we are communicating - * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz) - */ -static int si4713_tx_tune_freq(struct si4713_device *sdev, u16 frequency) -{ - int err; - u8 val[SI4713_TXFREQ_NRESP]; - /* - * .First byte = 0 - * .Second byte = frequency's MSB - * .Third byte = frequency's LSB - */ - const u8 args[SI4713_TXFREQ_NARGS] = { - 0x00, - msb(frequency), - lsb(frequency), - }; - - err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_FREQ, - args, ARRAY_SIZE(args), val, - ARRAY_SIZE(val), DEFAULT_TIMEOUT); - - if (err < 0) - return err; - - v4l2_dbg(1, debug, &sdev->sd, - "%s: frequency=0x%02x status=0x%02x\n", __func__, - frequency, val[0]); - - err = si4713_wait_stc(sdev, TIMEOUT_TX_TUNE); - if (err < 0) - return err; - - return compose_u16(args[1], args[2]); -} - -/* - * si4713_tx_tune_power - Sets the RF voltage level between 88 and 115 dBuV in - * 1 dB units. A value of 0x00 indicates off. The command - * also sets the antenna tuning capacitance. A value of 0 - * indicates autotuning, and a value of 1 - 191 indicates - * a manual override, which results in a tuning - * capacitance of 0.25 pF x @antcap. - * @sdev: si4713_device structure for the device we are communicating - * @power: tuning power (88 - 115 dBuV, unit/step 1 dB) - * @antcap: value of antenna tuning capacitor (0 - 191) - */ -static int si4713_tx_tune_power(struct si4713_device *sdev, u8 power, - u8 antcap) -{ - int err; - u8 val[SI4713_TXPWR_NRESP]; - /* - * .First byte = 0 - * .Second byte = 0 - * .Third byte = power - * .Fourth byte = antcap - */ - const u8 args[SI4713_TXPWR_NARGS] = { - 0x00, - 0x00, - power, - antcap, - }; - - if (((power > 0) && (power < SI4713_MIN_POWER)) || - power > SI4713_MAX_POWER || antcap > SI4713_MAX_ANTCAP) - return -EDOM; - - err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_POWER, - args, ARRAY_SIZE(args), val, - ARRAY_SIZE(val), DEFAULT_TIMEOUT); - - if (err < 0) - return err; - - v4l2_dbg(1, debug, &sdev->sd, - "%s: power=0x%02x antcap=0x%02x status=0x%02x\n", - __func__, power, antcap, val[0]); - - return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE_POWER); -} - -/* - * si4713_tx_tune_measure - Enters receive mode and measures the received noise - * level in units of dBuV on the selected frequency. - * The Frequency must be between 76 and 108 MHz in 10 kHz - * units and steps of 50 kHz. The command also sets the - * antenna tuning capacitance. A value of 0 means - * autotuning, and a value of 1 to 191 indicates manual - * override. - * @sdev: si4713_device structure for the device we are communicating - * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz) - * @antcap: value of antenna tuning capacitor (0 - 191) - */ -static int si4713_tx_tune_measure(struct si4713_device *sdev, u16 frequency, - u8 antcap) -{ - int err; - u8 val[SI4713_TXMEA_NRESP]; - /* - * .First byte = 0 - * .Second byte = frequency's MSB - * .Third byte = frequency's LSB - * .Fourth byte = antcap - */ - const u8 args[SI4713_TXMEA_NARGS] = { - 0x00, - msb(frequency), - lsb(frequency), - antcap, - }; - - sdev->tune_rnl = DEFAULT_TUNE_RNL; - - if (antcap > SI4713_MAX_ANTCAP) - return -EDOM; - - err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_MEASURE, - args, ARRAY_SIZE(args), val, - ARRAY_SIZE(val), DEFAULT_TIMEOUT); - - if (err < 0) - return err; - - v4l2_dbg(1, debug, &sdev->sd, - "%s: frequency=0x%02x antcap=0x%02x status=0x%02x\n", - __func__, frequency, antcap, val[0]); - - return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE); -} - -/* - * si4713_tx_tune_status- Returns the status of the tx_tune_freq, tx_tune_mea or - * tx_tune_power commands. This command return the current - * frequency, output voltage in dBuV, the antenna tunning - * capacitance value and the received noise level. The - * command also clears the stcint interrupt bit when the - * first bit of its arguments is high. - * @sdev: si4713_device structure for the device we are communicating - * @intack: 0x01 to clear the seek/tune complete interrupt status indicator. - * @frequency: returned frequency - * @power: returned power - * @antcap: returned antenna capacitance - * @noise: returned noise level - */ -static int si4713_tx_tune_status(struct si4713_device *sdev, u8 intack, - u16 *frequency, u8 *power, - u8 *antcap, u8 *noise) -{ - int err; - u8 val[SI4713_TXSTATUS_NRESP]; - /* - * .First byte = intack bit - */ - const u8 args[SI4713_TXSTATUS_NARGS] = { - intack & SI4713_INTACK_MASK, - }; - - err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_STATUS, - args, ARRAY_SIZE(args), val, - ARRAY_SIZE(val), DEFAULT_TIMEOUT); - - if (!err) { - v4l2_dbg(1, debug, &sdev->sd, - "%s: status=0x%02x\n", __func__, val[0]); - *frequency = compose_u16(val[2], val[3]); - sdev->frequency = *frequency; - *power = val[5]; - *antcap = val[6]; - *noise = val[7]; - v4l2_dbg(1, debug, &sdev->sd, "%s: response: %d x 10 kHz " - "(power %d, antcap %d, rnl %d)\n", __func__, - *frequency, *power, *antcap, *noise); - } - - return err; -} - -/* - * si4713_tx_rds_buff - Loads the RDS group buffer FIFO or circular buffer. - * @sdev: si4713_device structure for the device we are communicating - * @mode: the buffer operation mode. - * @rdsb: RDS Block B - * @rdsc: RDS Block C - * @rdsd: RDS Block D - * @cbleft: returns the number of available circular buffer blocks minus the - * number of used circular buffer blocks. - */ -static int si4713_tx_rds_buff(struct si4713_device *sdev, u8 mode, u16 rdsb, - u16 rdsc, u16 rdsd, s8 *cbleft) -{ - int err; - u8 val[SI4713_RDSBUFF_NRESP]; - - const u8 args[SI4713_RDSBUFF_NARGS] = { - mode & SI4713_RDSBUFF_MODE_MASK, - msb(rdsb), - lsb(rdsb), - msb(rdsc), - lsb(rdsc), - msb(rdsd), - lsb(rdsd), - }; - - err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_BUFF, - args, ARRAY_SIZE(args), val, - ARRAY_SIZE(val), DEFAULT_TIMEOUT); - - if (!err) { - v4l2_dbg(1, debug, &sdev->sd, - "%s: status=0x%02x\n", __func__, val[0]); - *cbleft = (s8)val[2] - val[3]; - v4l2_dbg(1, debug, &sdev->sd, "%s: response: interrupts" - " 0x%02x cb avail: %d cb used %d fifo avail" - " %d fifo used %d\n", __func__, val[1], - val[2], val[3], val[4], val[5]); - } - - return err; -} - -/* - * si4713_tx_rds_ps - Loads the program service buffer. - * @sdev: si4713_device structure for the device we are communicating - * @psid: program service id to be loaded. - * @pschar: assumed 4 size char array to be loaded into the program service - */ -static int si4713_tx_rds_ps(struct si4713_device *sdev, u8 psid, - unsigned char *pschar) -{ - int err; - u8 val[SI4713_RDSPS_NRESP]; - - const u8 args[SI4713_RDSPS_NARGS] = { - psid & SI4713_RDSPS_PSID_MASK, - pschar[0], - pschar[1], - pschar[2], - pschar[3], - }; - - err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_PS, - args, ARRAY_SIZE(args), val, - ARRAY_SIZE(val), DEFAULT_TIMEOUT); - - if (err < 0) - return err; - - v4l2_dbg(1, debug, &sdev->sd, "%s: status=0x%02x\n", __func__, val[0]); - - return err; -} - -static int si4713_set_power_state(struct si4713_device *sdev, u8 value) -{ - int rval; - - mutex_lock(&sdev->mutex); - - if (value) - rval = si4713_powerup(sdev); - else - rval = si4713_powerdown(sdev); - - mutex_unlock(&sdev->mutex); - return rval; -} - -static int si4713_set_mute(struct si4713_device *sdev, u16 mute) -{ - int rval = 0; - - mute = set_mute(mute); - - mutex_lock(&sdev->mutex); - - if (sdev->power_state) - rval = si4713_write_property(sdev, - SI4713_TX_LINE_INPUT_MUTE, mute); - - if (rval >= 0) - sdev->mute = get_mute(mute); - - mutex_unlock(&sdev->mutex); - - return rval; -} - -static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name) -{ - int rval = 0, i; - u8 len = 0; - - /* We want to clear the whole thing */ - if (!strlen(ps_name)) - memset(ps_name, 0, MAX_RDS_PS_NAME + 1); - - mutex_lock(&sdev->mutex); - - if (sdev->power_state) { - /* Write the new ps name and clear the padding */ - for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) { - rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)), - ps_name + i); - if (rval < 0) - goto unlock; - } - - /* Setup the size to be sent */ - if (strlen(ps_name)) - len = strlen(ps_name) - 1; - else - len = 1; - - rval = si4713_write_property(sdev, - SI4713_TX_RDS_PS_MESSAGE_COUNT, - rds_ps_nblocks(len)); - if (rval < 0) - goto unlock; - - rval = si4713_write_property(sdev, - SI4713_TX_RDS_PS_REPEAT_COUNT, - DEFAULT_RDS_PS_REPEAT_COUNT * 2); - if (rval < 0) - goto unlock; - } - - strncpy(sdev->rds_info.ps_name, ps_name, MAX_RDS_PS_NAME); - -unlock: - mutex_unlock(&sdev->mutex); - return rval; -} - -static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt) -{ - int rval = 0, i; - u16 t_index = 0; - u8 b_index = 0, cr_inserted = 0; - s8 left; - - mutex_lock(&sdev->mutex); - - if (!sdev->power_state) - goto copy; - - rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left); - if (rval < 0) - goto unlock; - - if (!strlen(rt)) - goto copy; - - do { - /* RDS spec says that if the last block isn't used, - * then apply a carriage return - */ - if (t_index < (RDS_RADIOTEXT_INDEX_MAX * - RDS_RADIOTEXT_BLK_SIZE)) { - for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) { - if (!rt[t_index + i] || rt[t_index + i] == - RDS_CARRIAGE_RETURN) { - rt[t_index + i] = RDS_CARRIAGE_RETURN; - cr_inserted = 1; - break; - } - } - } - - rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_LOAD, - compose_u16(RDS_RADIOTEXT_2A, b_index++), - compose_u16(rt[t_index], rt[t_index + 1]), - compose_u16(rt[t_index + 2], rt[t_index + 3]), - &left); - if (rval < 0) - goto unlock; - - t_index += RDS_RADIOTEXT_BLK_SIZE; - - if (cr_inserted) - break; - } while (left > 0); - -copy: - strncpy(sdev->rds_info.radio_text, rt, MAX_RDS_RADIO_TEXT); - -unlock: - mutex_unlock(&sdev->mutex); - return rval; -} - -static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id, - u32 **shadow, s32 *bit, s32 *mask, u16 *property, int *mul, - unsigned long **table, int *size) -{ - s32 rval = 0; - - switch (id) { - /* FM_TX class controls */ - case V4L2_CID_RDS_TX_PI: - *property = SI4713_TX_RDS_PI; - *mul = 1; - *shadow = &sdev->rds_info.pi; - break; - case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: - *property = SI4713_TX_ACOMP_THRESHOLD; - *mul = 1; - *shadow = &sdev->acomp_info.threshold; - break; - case V4L2_CID_AUDIO_COMPRESSION_GAIN: - *property = SI4713_TX_ACOMP_GAIN; - *mul = 1; - *shadow = &sdev->acomp_info.gain; - break; - case V4L2_CID_PILOT_TONE_FREQUENCY: - *property = SI4713_TX_PILOT_FREQUENCY; - *mul = 1; - *shadow = &sdev->pilot_info.frequency; - break; - case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: - *property = SI4713_TX_ACOMP_ATTACK_TIME; - *mul = ATTACK_TIME_UNIT; - *shadow = &sdev->acomp_info.attack_time; - break; - case V4L2_CID_PILOT_TONE_DEVIATION: - *property = SI4713_TX_PILOT_DEVIATION; - *mul = 10; - *shadow = &sdev->pilot_info.deviation; - break; - case V4L2_CID_AUDIO_LIMITER_DEVIATION: - *property = SI4713_TX_AUDIO_DEVIATION; - *mul = 10; - *shadow = &sdev->limiter_info.deviation; - break; - case V4L2_CID_RDS_TX_DEVIATION: - *property = SI4713_TX_RDS_DEVIATION; - *mul = 1; - *shadow = &sdev->rds_info.deviation; - break; - - case V4L2_CID_RDS_TX_PTY: - *property = SI4713_TX_RDS_PS_MISC; - *bit = 5; - *mask = 0x1F << 5; - *shadow = &sdev->rds_info.pty; - break; - case V4L2_CID_AUDIO_LIMITER_ENABLED: - *property = SI4713_TX_ACOMP_ENABLE; - *bit = 1; - *mask = 1 << 1; - *shadow = &sdev->limiter_info.enabled; - break; - case V4L2_CID_AUDIO_COMPRESSION_ENABLED: - *property = SI4713_TX_ACOMP_ENABLE; - *bit = 0; - *mask = 1 << 0; - *shadow = &sdev->acomp_info.enabled; - break; - case V4L2_CID_PILOT_TONE_ENABLED: - *property = SI4713_TX_COMPONENT_ENABLE; - *bit = 0; - *mask = 1 << 0; - *shadow = &sdev->pilot_info.enabled; - break; - - case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: - *property = SI4713_TX_LIMITER_RELEASE_TIME; - *table = limiter_times; - *size = ARRAY_SIZE(limiter_times); - *shadow = &sdev->limiter_info.release_time; - break; - case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: - *property = SI4713_TX_ACOMP_RELEASE_TIME; - *table = acomp_rtimes; - *size = ARRAY_SIZE(acomp_rtimes); - *shadow = &sdev->acomp_info.release_time; - break; - case V4L2_CID_TUNE_PREEMPHASIS: - *property = SI4713_TX_PREEMPHASIS; - *table = preemphasis_values; - *size = ARRAY_SIZE(preemphasis_values); - *shadow = &sdev->preemphasis; - break; - - default: - rval = -EINVAL; - }; - - return rval; -} - -static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc); - -/* write string property */ -static int si4713_write_econtrol_string(struct si4713_device *sdev, - struct v4l2_ext_control *control) -{ - struct v4l2_queryctrl vqc; - int len; - s32 rval = 0; - - vqc.id = control->id; - rval = si4713_queryctrl(&sdev->sd, &vqc); - if (rval < 0) - goto exit; - - switch (control->id) { - case V4L2_CID_RDS_TX_PS_NAME: { - char ps_name[MAX_RDS_PS_NAME + 1]; - - len = control->size - 1; - if (len > MAX_RDS_PS_NAME) { - rval = -ERANGE; - goto exit; - } - rval = copy_from_user(ps_name, control->string, len); - if (rval < 0) - goto exit; - ps_name[len] = '\0'; - - if (strlen(ps_name) % vqc.step) { - rval = -ERANGE; - goto exit; - } - - rval = si4713_set_rds_ps_name(sdev, ps_name); - } - break; - - case V4L2_CID_RDS_TX_RADIO_TEXT: { - char radio_text[MAX_RDS_RADIO_TEXT + 1]; - - len = control->size - 1; - if (len > MAX_RDS_RADIO_TEXT) { - rval = -ERANGE; - goto exit; - } - rval = copy_from_user(radio_text, control->string, len); - if (rval < 0) - goto exit; - radio_text[len] = '\0'; - - if (strlen(radio_text) % vqc.step) { - rval = -ERANGE; - goto exit; - } - - rval = si4713_set_rds_radio_text(sdev, radio_text); - } - break; - - default: - rval = -EINVAL; - break; - }; - -exit: - return rval; -} - -static int validate_range(struct v4l2_subdev *sd, - struct v4l2_ext_control *control) -{ - struct v4l2_queryctrl vqc; - int rval; - - vqc.id = control->id; - rval = si4713_queryctrl(sd, &vqc); - if (rval < 0) - goto exit; - - if (control->value < vqc.minimum || control->value > vqc.maximum) - rval = -ERANGE; - -exit: - return rval; -} - -/* properties which use tx_tune_power*/ -static int si4713_write_econtrol_tune(struct si4713_device *sdev, - struct v4l2_ext_control *control) -{ - s32 rval = 0; - u8 power, antcap; - - rval = validate_range(&sdev->sd, control); - if (rval < 0) - goto exit; - - mutex_lock(&sdev->mutex); - - switch (control->id) { - case V4L2_CID_TUNE_POWER_LEVEL: - power = control->value; - antcap = sdev->antenna_capacitor; - break; - case V4L2_CID_TUNE_ANTENNA_CAPACITOR: - power = sdev->power_level; - antcap = control->value; - break; - default: - rval = -EINVAL; - goto unlock; - }; - - if (sdev->power_state) - rval = si4713_tx_tune_power(sdev, power, antcap); - - if (rval == 0) { - sdev->power_level = power; - sdev->antenna_capacitor = antcap; - } - -unlock: - mutex_unlock(&sdev->mutex); -exit: - return rval; -} - -static int si4713_write_econtrol_integers(struct si4713_device *sdev, - struct v4l2_ext_control *control) -{ - s32 rval; - u32 *shadow = NULL, val = 0; - s32 bit = 0, mask = 0; - u16 property = 0; - int mul = 0; - unsigned long *table = NULL; - int size = 0; - - rval = validate_range(&sdev->sd, control); - if (rval < 0) - goto exit; - - rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, - &mask, &property, &mul, &table, &size); - if (rval < 0) - goto exit; - - val = control->value; - if (mul) { - val = control->value / mul; - } else if (table) { - rval = usecs_to_dev(control->value, table, size); - if (rval < 0) - goto exit; - val = rval; - rval = 0; - } - - mutex_lock(&sdev->mutex); - - if (sdev->power_state) { - if (mask) { - rval = si4713_read_property(sdev, property, &val); - if (rval < 0) - goto unlock; - val = set_bits(val, control->value, bit, mask); - } - - rval = si4713_write_property(sdev, property, val); - if (rval < 0) - goto unlock; - if (mask) - val = control->value; - } - - if (mul) { - *shadow = val * mul; - } else if (table) { - rval = dev_to_usecs(val, table, size); - if (rval < 0) - goto unlock; - *shadow = rval; - rval = 0; - } else { - *shadow = val; - } - -unlock: - mutex_unlock(&sdev->mutex); -exit: - return rval; -} - -static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f); -static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *); -/* - * si4713_setup - Sets the device up with current configuration. - * @sdev: si4713_device structure for the device we are communicating - */ -static int si4713_setup(struct si4713_device *sdev) -{ - struct v4l2_ext_control ctrl; - struct v4l2_frequency f; - struct v4l2_modulator vm; - struct si4713_device *tmp; - int rval = 0; - - tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); - if (!tmp) - return -ENOMEM; - - /* Get a local copy to avoid race */ - mutex_lock(&sdev->mutex); - memcpy(tmp, sdev, sizeof(*sdev)); - mutex_unlock(&sdev->mutex); - - ctrl.id = V4L2_CID_RDS_TX_PI; - ctrl.value = tmp->rds_info.pi; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_AUDIO_COMPRESSION_THRESHOLD; - ctrl.value = tmp->acomp_info.threshold; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_AUDIO_COMPRESSION_GAIN; - ctrl.value = tmp->acomp_info.gain; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_PILOT_TONE_FREQUENCY; - ctrl.value = tmp->pilot_info.frequency; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME; - ctrl.value = tmp->acomp_info.attack_time; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_PILOT_TONE_DEVIATION; - ctrl.value = tmp->pilot_info.deviation; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_AUDIO_LIMITER_DEVIATION; - ctrl.value = tmp->limiter_info.deviation; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_RDS_TX_DEVIATION; - ctrl.value = tmp->rds_info.deviation; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_RDS_TX_PTY; - ctrl.value = tmp->rds_info.pty; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_AUDIO_LIMITER_ENABLED; - ctrl.value = tmp->limiter_info.enabled; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_AUDIO_COMPRESSION_ENABLED; - ctrl.value = tmp->acomp_info.enabled; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_PILOT_TONE_ENABLED; - ctrl.value = tmp->pilot_info.enabled; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_AUDIO_LIMITER_RELEASE_TIME; - ctrl.value = tmp->limiter_info.release_time; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME; - ctrl.value = tmp->acomp_info.release_time; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_TUNE_PREEMPHASIS; - ctrl.value = tmp->preemphasis; - rval |= si4713_write_econtrol_integers(sdev, &ctrl); - - ctrl.id = V4L2_CID_RDS_TX_PS_NAME; - rval |= si4713_set_rds_ps_name(sdev, tmp->rds_info.ps_name); - - ctrl.id = V4L2_CID_RDS_TX_RADIO_TEXT; - rval |= si4713_set_rds_radio_text(sdev, tmp->rds_info.radio_text); - - /* Device procedure needs to set frequency first */ - f.frequency = tmp->frequency ? tmp->frequency : DEFAULT_FREQUENCY; - f.frequency = si4713_to_v4l2(f.frequency); - rval |= si4713_s_frequency(&sdev->sd, &f); - - ctrl.id = V4L2_CID_TUNE_POWER_LEVEL; - ctrl.value = tmp->power_level; - rval |= si4713_write_econtrol_tune(sdev, &ctrl); - - ctrl.id = V4L2_CID_TUNE_ANTENNA_CAPACITOR; - ctrl.value = tmp->antenna_capacitor; - rval |= si4713_write_econtrol_tune(sdev, &ctrl); - - vm.index = 0; - if (tmp->stereo) - vm.txsubchans = V4L2_TUNER_SUB_STEREO; - else - vm.txsubchans = V4L2_TUNER_SUB_MONO; - if (tmp->rds_info.enabled) - vm.txsubchans |= V4L2_TUNER_SUB_RDS; - si4713_s_modulator(&sdev->sd, &vm); - - kfree(tmp); - - return rval; -} - -/* - * si4713_initialize - Sets the device up with default configuration. - * @sdev: si4713_device structure for the device we are communicating - */ -static int si4713_initialize(struct si4713_device *sdev) -{ - int rval; - - rval = si4713_set_power_state(sdev, POWER_ON); - if (rval < 0) - goto exit; - - rval = si4713_checkrev(sdev); - if (rval < 0) - goto exit; - - rval = si4713_set_power_state(sdev, POWER_OFF); - if (rval < 0) - goto exit; - - mutex_lock(&sdev->mutex); - - sdev->rds_info.pi = DEFAULT_RDS_PI; - sdev->rds_info.pty = DEFAULT_RDS_PTY; - sdev->rds_info.deviation = DEFAULT_RDS_DEVIATION; - strlcpy(sdev->rds_info.ps_name, DEFAULT_RDS_PS_NAME, MAX_RDS_PS_NAME); - strlcpy(sdev->rds_info.radio_text, DEFAULT_RDS_RADIO_TEXT, - MAX_RDS_RADIO_TEXT); - sdev->rds_info.enabled = 1; - - sdev->limiter_info.release_time = DEFAULT_LIMITER_RTIME; - sdev->limiter_info.deviation = DEFAULT_LIMITER_DEV; - sdev->limiter_info.enabled = 1; - - sdev->pilot_info.deviation = DEFAULT_PILOT_DEVIATION; - sdev->pilot_info.frequency = DEFAULT_PILOT_FREQUENCY; - sdev->pilot_info.enabled = 1; - - sdev->acomp_info.release_time = DEFAULT_ACOMP_RTIME; - sdev->acomp_info.attack_time = DEFAULT_ACOMP_ATIME; - sdev->acomp_info.threshold = DEFAULT_ACOMP_THRESHOLD; - sdev->acomp_info.gain = DEFAULT_ACOMP_GAIN; - sdev->acomp_info.enabled = 1; - - sdev->frequency = DEFAULT_FREQUENCY; - sdev->preemphasis = DEFAULT_PREEMPHASIS; - sdev->mute = DEFAULT_MUTE; - sdev->power_level = DEFAULT_POWER_LEVEL; - sdev->antenna_capacitor = 0; - sdev->stereo = 1; - sdev->tune_rnl = DEFAULT_TUNE_RNL; - - mutex_unlock(&sdev->mutex); - -exit: - return rval; -} - -/* read string property */ -static int si4713_read_econtrol_string(struct si4713_device *sdev, - struct v4l2_ext_control *control) -{ - s32 rval = 0; - - switch (control->id) { - case V4L2_CID_RDS_TX_PS_NAME: - if (strlen(sdev->rds_info.ps_name) + 1 > control->size) { - control->size = MAX_RDS_PS_NAME + 1; - rval = -ENOSPC; - goto exit; - } - rval = copy_to_user(control->string, sdev->rds_info.ps_name, - strlen(sdev->rds_info.ps_name) + 1); - break; - - case V4L2_CID_RDS_TX_RADIO_TEXT: - if (strlen(sdev->rds_info.radio_text) + 1 > control->size) { - control->size = MAX_RDS_RADIO_TEXT + 1; - rval = -ENOSPC; - goto exit; - } - rval = copy_to_user(control->string, sdev->rds_info.radio_text, - strlen(sdev->rds_info.radio_text) + 1); - break; - - default: - rval = -EINVAL; - break; - }; - -exit: - return rval; -} - -/* - * si4713_update_tune_status - update properties from tx_tune_status - * command. Must be called with sdev->mutex held. - * @sdev: si4713_device structure for the device we are communicating - */ -static int si4713_update_tune_status(struct si4713_device *sdev) -{ - int rval; - u16 f = 0; - u8 p = 0, a = 0, n = 0; - - rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n); - - if (rval < 0) - goto exit; - - sdev->power_level = p; - sdev->antenna_capacitor = a; - sdev->tune_rnl = n; - -exit: - return rval; -} - -/* properties which use tx_tune_status */ -static int si4713_read_econtrol_tune(struct si4713_device *sdev, - struct v4l2_ext_control *control) -{ - s32 rval = 0; - - mutex_lock(&sdev->mutex); - - if (sdev->power_state) { - rval = si4713_update_tune_status(sdev); - if (rval < 0) - goto unlock; - } - - switch (control->id) { - case V4L2_CID_TUNE_POWER_LEVEL: - control->value = sdev->power_level; - break; - case V4L2_CID_TUNE_ANTENNA_CAPACITOR: - control->value = sdev->antenna_capacitor; - break; - default: - rval = -EINVAL; - }; - -unlock: - mutex_unlock(&sdev->mutex); - return rval; -} - -static int si4713_read_econtrol_integers(struct si4713_device *sdev, - struct v4l2_ext_control *control) -{ - s32 rval; - u32 *shadow = NULL, val = 0; - s32 bit = 0, mask = 0; - u16 property = 0; - int mul = 0; - unsigned long *table = NULL; - int size = 0; - - rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, - &mask, &property, &mul, &table, &size); - if (rval < 0) - goto exit; - - mutex_lock(&sdev->mutex); - - if (sdev->power_state) { - rval = si4713_read_property(sdev, property, &val); - if (rval < 0) - goto unlock; - - /* Keep negative values for threshold */ - if (control->id == V4L2_CID_AUDIO_COMPRESSION_THRESHOLD) - *shadow = (s16)val; - else if (mask) - *shadow = get_status_bit(val, bit, mask); - else if (mul) - *shadow = val * mul; - else - *shadow = dev_to_usecs(val, table, size); - } - - control->value = *shadow; - -unlock: - mutex_unlock(&sdev->mutex); -exit: - return rval; -} - -/* - * Video4Linux Subdev Interface - */ -/* si4713_s_ext_ctrls - set extended controls value */ -static int si4713_s_ext_ctrls(struct v4l2_subdev *sd, - struct v4l2_ext_controls *ctrls) -{ - struct si4713_device *sdev = to_si4713_device(sd); - int i; - - if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) - return -EINVAL; - - for (i = 0; i < ctrls->count; i++) { - int err; - - switch ((ctrls->controls + i)->id) { - case V4L2_CID_RDS_TX_PS_NAME: - case V4L2_CID_RDS_TX_RADIO_TEXT: - err = si4713_write_econtrol_string(sdev, - ctrls->controls + i); - break; - case V4L2_CID_TUNE_ANTENNA_CAPACITOR: - case V4L2_CID_TUNE_POWER_LEVEL: - err = si4713_write_econtrol_tune(sdev, - ctrls->controls + i); - break; - default: - err = si4713_write_econtrol_integers(sdev, - ctrls->controls + i); - } - - if (err < 0) { - ctrls->error_idx = i; - return err; - } - } - - return 0; -} - -/* si4713_g_ext_ctrls - get extended controls value */ -static int si4713_g_ext_ctrls(struct v4l2_subdev *sd, - struct v4l2_ext_controls *ctrls) -{ - struct si4713_device *sdev = to_si4713_device(sd); - int i; - - if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) - return -EINVAL; - - for (i = 0; i < ctrls->count; i++) { - int err; - - switch ((ctrls->controls + i)->id) { - case V4L2_CID_RDS_TX_PS_NAME: - case V4L2_CID_RDS_TX_RADIO_TEXT: - err = si4713_read_econtrol_string(sdev, - ctrls->controls + i); - break; - case V4L2_CID_TUNE_ANTENNA_CAPACITOR: - case V4L2_CID_TUNE_POWER_LEVEL: - err = si4713_read_econtrol_tune(sdev, - ctrls->controls + i); - break; - default: - err = si4713_read_econtrol_integers(sdev, - ctrls->controls + i); - } - - if (err < 0) { - ctrls->error_idx = i; - return err; - } - } - - return 0; -} - -/* si4713_queryctrl - enumerate control items */ -static int si4713_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) -{ - int rval = 0; - - switch (qc->id) { - /* User class controls */ - case V4L2_CID_AUDIO_MUTE: - rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, DEFAULT_MUTE); - break; - /* FM_TX class controls */ - case V4L2_CID_RDS_TX_PI: - rval = v4l2_ctrl_query_fill(qc, 0, 0xFFFF, 1, DEFAULT_RDS_PI); - break; - case V4L2_CID_RDS_TX_PTY: - rval = v4l2_ctrl_query_fill(qc, 0, 31, 1, DEFAULT_RDS_PTY); - break; - case V4L2_CID_RDS_TX_DEVIATION: - rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_DEVIATION, - 10, DEFAULT_RDS_DEVIATION); - break; - case V4L2_CID_RDS_TX_PS_NAME: - /* - * Report step as 8. From RDS spec, psname - * should be 8. But there are receivers which scroll strings - * sized as 8xN. - */ - rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_PS_NAME, 8, 0); - break; - case V4L2_CID_RDS_TX_RADIO_TEXT: - /* - * Report step as 32 (2A block). From RDS spec, - * radio text should be 32 for 2A block. But there are receivers - * which scroll strings sized as 32xN. Setting default to 32. - */ - rval = v4l2_ctrl_query_fill(qc, 0, MAX_RDS_RADIO_TEXT, 32, 0); - break; - - case V4L2_CID_AUDIO_LIMITER_ENABLED: - rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); - break; - case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: - rval = v4l2_ctrl_query_fill(qc, 250, MAX_LIMITER_RELEASE_TIME, - 50, DEFAULT_LIMITER_RTIME); - break; - case V4L2_CID_AUDIO_LIMITER_DEVIATION: - rval = v4l2_ctrl_query_fill(qc, 0, MAX_LIMITER_DEVIATION, - 10, DEFAULT_LIMITER_DEV); - break; - - case V4L2_CID_AUDIO_COMPRESSION_ENABLED: - rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); - break; - case V4L2_CID_AUDIO_COMPRESSION_GAIN: - rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_GAIN, 1, - DEFAULT_ACOMP_GAIN); - break; - case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: - rval = v4l2_ctrl_query_fill(qc, MIN_ACOMP_THRESHOLD, - MAX_ACOMP_THRESHOLD, 1, - DEFAULT_ACOMP_THRESHOLD); - break; - case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: - rval = v4l2_ctrl_query_fill(qc, 0, MAX_ACOMP_ATTACK_TIME, - 500, DEFAULT_ACOMP_ATIME); - break; - case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: - rval = v4l2_ctrl_query_fill(qc, 100000, MAX_ACOMP_RELEASE_TIME, - 100000, DEFAULT_ACOMP_RTIME); - break; - - case V4L2_CID_PILOT_TONE_ENABLED: - rval = v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); - break; - case V4L2_CID_PILOT_TONE_DEVIATION: - rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_DEVIATION, - 10, DEFAULT_PILOT_DEVIATION); - break; - case V4L2_CID_PILOT_TONE_FREQUENCY: - rval = v4l2_ctrl_query_fill(qc, 0, MAX_PILOT_FREQUENCY, - 1, DEFAULT_PILOT_FREQUENCY); - break; - - case V4L2_CID_TUNE_PREEMPHASIS: - rval = v4l2_ctrl_query_fill(qc, V4L2_PREEMPHASIS_DISABLED, - V4L2_PREEMPHASIS_75_uS, 1, - V4L2_PREEMPHASIS_50_uS); - break; - case V4L2_CID_TUNE_POWER_LEVEL: - rval = v4l2_ctrl_query_fill(qc, 0, 120, 1, DEFAULT_POWER_LEVEL); - break; - case V4L2_CID_TUNE_ANTENNA_CAPACITOR: - rval = v4l2_ctrl_query_fill(qc, 0, 191, 1, 0); - break; - default: - rval = -EINVAL; - break; - }; - - return rval; -} - -/* si4713_g_ctrl - get the value of a control */ -static int si4713_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct si4713_device *sdev = to_si4713_device(sd); - int rval = 0; - - if (!sdev) - return -ENODEV; - - mutex_lock(&sdev->mutex); - - if (sdev->power_state) { - rval = si4713_read_property(sdev, SI4713_TX_LINE_INPUT_MUTE, - &sdev->mute); - - if (rval < 0) - goto unlock; - } - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - ctrl->value = get_mute(sdev->mute); - break; - } - -unlock: - mutex_unlock(&sdev->mutex); - return rval; -} - -/* si4713_s_ctrl - set the value of a control */ -static int si4713_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct si4713_device *sdev = to_si4713_device(sd); - int rval = 0; - - if (!sdev) - return -ENODEV; - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) { - rval = si4713_set_mute(sdev, ctrl->value); - if (rval < 0) - goto exit; - - rval = si4713_set_power_state(sdev, POWER_DOWN); - } else { - rval = si4713_set_power_state(sdev, POWER_UP); - if (rval < 0) - goto exit; - - rval = si4713_setup(sdev); - if (rval < 0) - goto exit; - - rval = si4713_set_mute(sdev, ctrl->value); - } - break; - } - -exit: - return rval; -} - -/* si4713_ioctl - deal with private ioctls (only rnl for now) */ -long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - struct si4713_device *sdev = to_si4713_device(sd); - struct si4713_rnl *rnl = arg; - u16 frequency; - int rval = 0; - - if (!arg) - return -EINVAL; - - mutex_lock(&sdev->mutex); - switch (cmd) { - case SI4713_IOC_MEASURE_RNL: - frequency = v4l2_to_si4713(rnl->frequency); - - if (sdev->power_state) { - /* Set desired measurement frequency */ - rval = si4713_tx_tune_measure(sdev, frequency, 0); - if (rval < 0) - goto unlock; - /* get results from tune status */ - rval = si4713_update_tune_status(sdev); - if (rval < 0) - goto unlock; - } - rnl->rnl = sdev->tune_rnl; - break; - - default: - /* nothing */ - rval = -ENOIOCTLCMD; - } - -unlock: - mutex_unlock(&sdev->mutex); - return rval; -} - -static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = { - .queryctrl = si4713_queryctrl, - .g_ext_ctrls = si4713_g_ext_ctrls, - .s_ext_ctrls = si4713_s_ext_ctrls, - .g_ctrl = si4713_g_ctrl, - .s_ctrl = si4713_s_ctrl, - .ioctl = si4713_ioctl, -}; - -/* si4713_g_modulator - get modulator attributes */ -static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) -{ - struct si4713_device *sdev = to_si4713_device(sd); - int rval = 0; - - if (!sdev) { - rval = -ENODEV; - goto exit; - } - - if (vm->index > 0) { - rval = -EINVAL; - goto exit; - } - - strncpy(vm->name, "FM Modulator", 32); - vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW | - V4L2_TUNER_CAP_RDS; - - /* Report current frequency range limits */ - vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW); - vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH); - - mutex_lock(&sdev->mutex); - - if (sdev->power_state) { - u32 comp_en = 0; - - rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE, - &comp_en); - if (rval < 0) - goto unlock; - - sdev->stereo = get_status_bit(comp_en, 1, 1 << 1); - sdev->rds_info.enabled = get_status_bit(comp_en, 2, 1 << 2); - } - - /* Report current audio mode: mono or stereo */ - if (sdev->stereo) - vm->txsubchans = V4L2_TUNER_SUB_STEREO; - else - vm->txsubchans = V4L2_TUNER_SUB_MONO; - - /* Report rds feature status */ - if (sdev->rds_info.enabled) - vm->txsubchans |= V4L2_TUNER_SUB_RDS; - else - vm->txsubchans &= ~V4L2_TUNER_SUB_RDS; - -unlock: - mutex_unlock(&sdev->mutex); -exit: - return rval; -} - -/* si4713_s_modulator - set modulator attributes */ -static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) -{ - struct si4713_device *sdev = to_si4713_device(sd); - int rval = 0; - u16 stereo, rds; - u32 p; - - if (!sdev) { - rval = -ENODEV; - goto exit; - } - - if (vm->index > 0) { - rval = -EINVAL; - goto exit; - } - - /* Set audio mode: mono or stereo */ - if (vm->txsubchans & V4L2_TUNER_SUB_STEREO) - stereo = 1; - else if (vm->txsubchans & V4L2_TUNER_SUB_MONO) - stereo = 0; - else - rval = -EINVAL; - if (rval < 0) - goto exit; - - rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS); - - mutex_lock(&sdev->mutex); - - if (sdev->power_state) { - rval = si4713_read_property(sdev, - SI4713_TX_COMPONENT_ENABLE, &p); - if (rval < 0) - goto unlock; - - p = set_bits(p, stereo, 1, 1 << 1); - p = set_bits(p, rds, 2, 1 << 2); - - rval = si4713_write_property(sdev, - SI4713_TX_COMPONENT_ENABLE, p); - if (rval < 0) - goto unlock; - } - - sdev->stereo = stereo; - sdev->rds_info.enabled = rds; - -unlock: - mutex_unlock(&sdev->mutex); -exit: - return rval; -} - -/* si4713_g_frequency - get tuner or modulator radio frequency */ -static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) -{ - struct si4713_device *sdev = to_si4713_device(sd); - int rval = 0; - - f->type = V4L2_TUNER_RADIO; - - mutex_lock(&sdev->mutex); - - if (sdev->power_state) { - u16 freq; - u8 p, a, n; - - rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n); - if (rval < 0) - goto unlock; - - sdev->frequency = freq; - } - - f->frequency = si4713_to_v4l2(sdev->frequency); - -unlock: - mutex_unlock(&sdev->mutex); - return rval; -} - -/* si4713_s_frequency - set tuner or modulator radio frequency */ -static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) -{ - struct si4713_device *sdev = to_si4713_device(sd); - int rval = 0; - u16 frequency = v4l2_to_si4713(f->frequency); - - /* Check frequency range */ - if (frequency < FREQ_RANGE_LOW || frequency > FREQ_RANGE_HIGH) - return -EDOM; - - mutex_lock(&sdev->mutex); - - if (sdev->power_state) { - rval = si4713_tx_tune_freq(sdev, frequency); - if (rval < 0) - goto unlock; - frequency = rval; - rval = 0; - } - sdev->frequency = frequency; - f->frequency = si4713_to_v4l2(frequency); - -unlock: - mutex_unlock(&sdev->mutex); - return rval; -} - -static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = { - .g_frequency = si4713_g_frequency, - .s_frequency = si4713_s_frequency, - .g_modulator = si4713_g_modulator, - .s_modulator = si4713_s_modulator, -}; - -static const struct v4l2_subdev_ops si4713_subdev_ops = { - .core = &si4713_subdev_core_ops, - .tuner = &si4713_subdev_tuner_ops, -}; - -/* - * I2C driver interface - */ -/* si4713_probe - probe for the device */ -static int si4713_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct si4713_device *sdev; - int rval; - - sdev = kzalloc(sizeof *sdev, GFP_KERNEL); - if (!sdev) { - dev_err(&client->dev, "Failed to alloc video device.\n"); - rval = -ENOMEM; - goto exit; - } - - sdev->platform_data = client->dev.platform_data; - if (!sdev->platform_data) { - v4l2_err(&sdev->sd, "No platform data registered.\n"); - rval = -ENODEV; - goto free_sdev; - } - - v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops); - - mutex_init(&sdev->mutex); - init_completion(&sdev->work); - - if (client->irq) { - rval = request_irq(client->irq, - si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, - client->name, sdev); - if (rval < 0) { - v4l2_err(&sdev->sd, "Could not request IRQ\n"); - goto free_sdev; - } - v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n"); - } else { - v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n"); - } - - rval = si4713_initialize(sdev); - if (rval < 0) { - v4l2_err(&sdev->sd, "Failed to probe device information.\n"); - goto free_irq; - } - - return 0; - -free_irq: - if (client->irq) - free_irq(client->irq, sdev); -free_sdev: - kfree(sdev); -exit: - return rval; -} - -/* si4713_remove - remove the device */ -static int si4713_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct si4713_device *sdev = to_si4713_device(sd); - - if (sdev->power_state) - si4713_set_power_state(sdev, POWER_DOWN); - - if (client->irq > 0) - free_irq(client->irq, sdev); - - v4l2_device_unregister_subdev(sd); - - kfree(sdev); - - return 0; -} - -/* si4713_i2c_driver - i2c driver interface */ -static const struct i2c_device_id si4713_id[] = { - { "si4713" , 0 }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, si4713_id); - -static struct i2c_driver si4713_i2c_driver = { - .driver = { - .name = "si4713", - }, - .probe = si4713_probe, - .remove = si4713_remove, - .id_table = si4713_id, -}; - -/* Module Interface */ -static int __init si4713_module_init(void) -{ - return i2c_add_driver(&si4713_i2c_driver); -} - -static void __exit si4713_module_exit(void) -{ - i2c_del_driver(&si4713_i2c_driver); -} - -module_init(si4713_module_init); -module_exit(si4713_module_exit); - diff --git a/linux/linux/drivers/media/radio/si4713-i2c.h b/linux/linux/drivers/media/radio/si4713-i2c.h deleted file mode 100644 index faf8cff12..000000000 --- a/linux/linux/drivers/media/radio/si4713-i2c.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * drivers/media/radio/si4713-i2c.h - * - * Property and commands definitions for Si4713 radio transmitter chip. - * - * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT - * Contact: Eduardo Valentin - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - * - */ - -#ifndef SI4713_I2C_H -#define SI4713_I2C_H - -#include -#include - -#define SI4713_PRODUCT_NUMBER 0x0D - -/* Command Timeouts */ -#define DEFAULT_TIMEOUT 500 -#define TIMEOUT_SET_PROPERTY 20 -#define TIMEOUT_TX_TUNE_POWER 30000 -#define TIMEOUT_TX_TUNE 110000 -#define TIMEOUT_POWER_UP 200000 - -/* - * Command and its arguments definitions - */ -#define SI4713_PWUP_CTSIEN (1<<7) -#define SI4713_PWUP_GPO2OEN (1<<6) -#define SI4713_PWUP_PATCH (1<<5) -#define SI4713_PWUP_XOSCEN (1<<4) -#define SI4713_PWUP_FUNC_TX 0x02 -#define SI4713_PWUP_FUNC_PATCH 0x0F -#define SI4713_PWUP_OPMOD_ANALOG 0x50 -#define SI4713_PWUP_OPMOD_DIGITAL 0x0F -#define SI4713_PWUP_NARGS 2 -#define SI4713_PWUP_NRESP 1 -#define SI4713_CMD_POWER_UP 0x01 - -#define SI4713_GETREV_NRESP 9 -#define SI4713_CMD_GET_REV 0x10 - -#define SI4713_PWDN_NRESP 1 -#define SI4713_CMD_POWER_DOWN 0x11 - -#define SI4713_SET_PROP_NARGS 5 -#define SI4713_SET_PROP_NRESP 1 -#define SI4713_CMD_SET_PROPERTY 0x12 - -#define SI4713_GET_PROP_NARGS 3 -#define SI4713_GET_PROP_NRESP 4 -#define SI4713_CMD_GET_PROPERTY 0x13 - -#define SI4713_GET_STATUS_NRESP 1 -#define SI4713_CMD_GET_INT_STATUS 0x14 - -#define SI4713_CMD_PATCH_ARGS 0x15 -#define SI4713_CMD_PATCH_DATA 0x16 - -#define SI4713_MAX_FREQ 10800 -#define SI4713_MIN_FREQ 7600 -#define SI4713_TXFREQ_NARGS 3 -#define SI4713_TXFREQ_NRESP 1 -#define SI4713_CMD_TX_TUNE_FREQ 0x30 - -#define SI4713_MAX_POWER 120 -#define SI4713_MIN_POWER 88 -#define SI4713_MAX_ANTCAP 191 -#define SI4713_MIN_ANTCAP 0 -#define SI4713_TXPWR_NARGS 4 -#define SI4713_TXPWR_NRESP 1 -#define SI4713_CMD_TX_TUNE_POWER 0x31 - -#define SI4713_TXMEA_NARGS 4 -#define SI4713_TXMEA_NRESP 1 -#define SI4713_CMD_TX_TUNE_MEASURE 0x32 - -#define SI4713_INTACK_MASK 0x01 -#define SI4713_TXSTATUS_NARGS 1 -#define SI4713_TXSTATUS_NRESP 8 -#define SI4713_CMD_TX_TUNE_STATUS 0x33 - -#define SI4713_OVERMOD_BIT (1 << 2) -#define SI4713_IALH_BIT (1 << 1) -#define SI4713_IALL_BIT (1 << 0) -#define SI4713_ASQSTATUS_NARGS 1 -#define SI4713_ASQSTATUS_NRESP 5 -#define SI4713_CMD_TX_ASQ_STATUS 0x34 - -#define SI4713_RDSBUFF_MODE_MASK 0x87 -#define SI4713_RDSBUFF_NARGS 7 -#define SI4713_RDSBUFF_NRESP 6 -#define SI4713_CMD_TX_RDS_BUFF 0x35 - -#define SI4713_RDSPS_PSID_MASK 0x1F -#define SI4713_RDSPS_NARGS 5 -#define SI4713_RDSPS_NRESP 1 -#define SI4713_CMD_TX_RDS_PS 0x36 - -#define SI4713_CMD_GPO_CTL 0x80 -#define SI4713_CMD_GPO_SET 0x81 - -/* - * Bits from status response - */ -#define SI4713_CTS (1<<7) -#define SI4713_ERR (1<<6) -#define SI4713_RDS_INT (1<<2) -#define SI4713_ASQ_INT (1<<1) -#define SI4713_STC_INT (1<<0) - -/* - * Property definitions - */ -#define SI4713_GPO_IEN 0x0001 -#define SI4713_DIG_INPUT_FORMAT 0x0101 -#define SI4713_DIG_INPUT_SAMPLE_RATE 0x0103 -#define SI4713_REFCLK_FREQ 0x0201 -#define SI4713_REFCLK_PRESCALE 0x0202 -#define SI4713_TX_COMPONENT_ENABLE 0x2100 -#define SI4713_TX_AUDIO_DEVIATION 0x2101 -#define SI4713_TX_PILOT_DEVIATION 0x2102 -#define SI4713_TX_RDS_DEVIATION 0x2103 -#define SI4713_TX_LINE_INPUT_LEVEL 0x2104 -#define SI4713_TX_LINE_INPUT_MUTE 0x2105 -#define SI4713_TX_PREEMPHASIS 0x2106 -#define SI4713_TX_PILOT_FREQUENCY 0x2107 -#define SI4713_TX_ACOMP_ENABLE 0x2200 -#define SI4713_TX_ACOMP_THRESHOLD 0x2201 -#define SI4713_TX_ACOMP_ATTACK_TIME 0x2202 -#define SI4713_TX_ACOMP_RELEASE_TIME 0x2203 -#define SI4713_TX_ACOMP_GAIN 0x2204 -#define SI4713_TX_LIMITER_RELEASE_TIME 0x2205 -#define SI4713_TX_ASQ_INTERRUPT_SOURCE 0x2300 -#define SI4713_TX_ASQ_LEVEL_LOW 0x2301 -#define SI4713_TX_ASQ_DURATION_LOW 0x2302 -#define SI4713_TX_ASQ_LEVEL_HIGH 0x2303 -#define SI4713_TX_ASQ_DURATION_HIGH 0x2304 -#define SI4713_TX_RDS_INTERRUPT_SOURCE 0x2C00 -#define SI4713_TX_RDS_PI 0x2C01 -#define SI4713_TX_RDS_PS_MIX 0x2C02 -#define SI4713_TX_RDS_PS_MISC 0x2C03 -#define SI4713_TX_RDS_PS_REPEAT_COUNT 0x2C04 -#define SI4713_TX_RDS_PS_MESSAGE_COUNT 0x2C05 -#define SI4713_TX_RDS_PS_AF 0x2C06 -#define SI4713_TX_RDS_FIFO_SIZE 0x2C07 - -#define PREEMPHASIS_USA 75 -#define PREEMPHASIS_EU 50 -#define PREEMPHASIS_DISABLED 0 -#define FMPE_USA 0x00 -#define FMPE_EU 0x01 -#define FMPE_DISABLED 0x02 - -#define POWER_UP 0x01 -#define POWER_DOWN 0x00 - -struct rds_info { - u32 pi; -#define MAX_RDS_PTY 31 - u32 pty; -#define MAX_RDS_DEVIATION 90000 - u32 deviation; -/* - * PSNAME is known to be defined as 8 character sized (RDS Spec). - * However, there is receivers which scroll PSNAME 8xN sized. - */ -#define MAX_RDS_PS_NAME 96 - u8 ps_name[MAX_RDS_PS_NAME + 1]; -/* - * MAX_RDS_RADIO_TEXT is known to be defined as 32 (2A group) or 64 (2B group) - * character sized (RDS Spec). - * However, there is receivers which scroll them as well. - */ -#define MAX_RDS_RADIO_TEXT 384 - u8 radio_text[MAX_RDS_RADIO_TEXT + 1]; - u32 enabled; -}; - -struct limiter_info { -#define MAX_LIMITER_RELEASE_TIME 102390 - u32 release_time; -#define MAX_LIMITER_DEVIATION 90000 - u32 deviation; - u32 enabled; -}; - -struct pilot_info { -#define MAX_PILOT_DEVIATION 90000 - u32 deviation; -#define MAX_PILOT_FREQUENCY 19000 - u32 frequency; - u32 enabled; -}; - -struct acomp_info { -#define MAX_ACOMP_RELEASE_TIME 1000000 - u32 release_time; -#define MAX_ACOMP_ATTACK_TIME 5000 - u32 attack_time; -#define MAX_ACOMP_THRESHOLD 0 -#define MIN_ACOMP_THRESHOLD (-40) - s32 threshold; -#define MAX_ACOMP_GAIN 20 - u32 gain; - u32 enabled; -}; - -/* - * si4713_device - private data - */ -struct si4713_device { - /* v4l2_subdev and i2c reference (v4l2_subdev priv data) */ - struct v4l2_subdev sd; - /* private data structures */ - struct mutex mutex; - struct completion work; - struct si4713_platform_data *platform_data; - struct rds_info rds_info; - struct limiter_info limiter_info; - struct pilot_info pilot_info; - struct acomp_info acomp_info; - u32 frequency; - u32 preemphasis; - u32 mute; - u32 power_level; - u32 power_state; - u32 antenna_capacitor; - u32 stereo; - u32 tune_rnl; -}; -#endif /* ifndef SI4713_I2C_H */ diff --git a/linux/linux/include/media/radio-si4713.h b/linux/linux/include/media/radio-si4713.h deleted file mode 100644 index f6aae29c7..000000000 --- a/linux/linux/include/media/radio-si4713.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * include/media/radio-si4713.h - * - * Board related data definitions for Si4713 radio transmitter chip. - * - * Copyright (c) 2009 Nokia Corporation - * Contact: Eduardo Valentin - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - * - */ - -#ifndef RADIO_SI4713_H -#define RADIO_SI4713_H - -#include - -#define SI4713_NAME "radio-si4713" - -/* - * Platform dependent definition - */ -struct radio_si4713_platform_data { - int i2c_bus; - struct i2c_board_info *subdev_board_info; -}; - -#endif /* ifndef RADIO_SI4713_H*/ diff --git a/linux/linux/include/media/si4713.h b/linux/linux/include/media/si4713.h deleted file mode 100644 index 99850a54e..000000000 --- a/linux/linux/include/media/si4713.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * include/media/si4713.h - * - * Board related data definitions for Si4713 i2c device driver. - * - * Copyright (c) 2009 Nokia Corporation - * Contact: Eduardo Valentin - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - * - */ - -#ifndef SI4713_H -#define SI4713_H - -/* The SI4713 I2C sensor chip has a fixed slave address of 0xc6 or 0x22. */ -#define SI4713_I2C_ADDR_BUSEN_HIGH 0x63 -#define SI4713_I2C_ADDR_BUSEN_LOW 0x11 - -/* - * Platform dependent definition - */ -struct si4713_platform_data { - /* Set power state, zero is off, non-zero is on. */ - int (*set_power)(int power); -}; - -/* - * Structure to query for Received Noise Level (RNL). - */ -struct si4713_rnl { - __u32 index; /* modulator index */ - __u32 frequency; /* frequency to peform rnl measurement */ - __s32 rnl; /* result of measurement in dBuV */ - __u32 reserved[4]; /* drivers and apps must init this to 0 */ -}; - -/* - * This is the ioctl number to query for rnl. Users must pass a - * struct si4713_rnl pointer specifying desired frequency in 'frequency' field - * following driver capabilities (i.e V4L2_TUNER_CAP_LOW). - * Driver must return measured value in the same struture, filling 'rnl' field. - */ -#define SI4713_IOC_MEASURE_RNL _IOWR('V', BASE_VIDIOC_PRIVATE + 0, \ - struct si4713_rnl) - -#endif /* ifndef SI4713_H*/ -- cgit v1.2.3 From 668392480789cab466a0a979ed95f9057d005379 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 09:06:07 -0300 Subject: ir-keymaps: standardize timeshift key From: Mauro Carvalho Chehab Each remote were using a different keycode for timeshift. Use the same keycode for all of them, using the map as defined at: http://linuxtv.org/wiki/index.php/Remote_Controllers Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index c9f204048..24a635529 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -331,7 +331,7 @@ EXPORT_SYMBOL_GPL(ir_codes_pixelview); present on PV MPEG 8000GT */ IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = { - [0x3c] = KEY_PAUSE, /* Timeshift */ + [0x3c] = KEY_TIME, /* Timeshift */ [0x12] = KEY_POWER, [0x3d] = KEY_1, @@ -492,7 +492,7 @@ IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { [0x78] = KEY_9, [0x10] = KEY_L, /* Live */ - [0x08] = KEY_T, /* Time Shift */ + [0x08] = KEY_TIME, /* Time Shift */ [0x18] = KEY_PLAYPAUSE, /* Play */ @@ -595,7 +595,7 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { [0x0c] = KEY_MUTE, [0x0f] = KEY_SCREEN, /* Full Screen */ [0x10] = KEY_FN, /* Funtion */ - [0x11] = KEY_T, /* Time shift */ + [0x11] = KEY_TIME, /* Time shift */ [0x12] = KEY_POWER, [0x13] = KEY_MEDIA, /* MTS */ [0x14] = KEY_SLOW, @@ -1293,7 +1293,7 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { [0x0f] = KEY_AUDIO, [0x1b] = KEY_VOLUMEUP, [0x1a] = KEY_CHANNELUP, - [0x0e] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ + [0x0e] = KEY_TIME, [0x1f] = KEY_VOLUMEDOWN, [0x1e] = KEY_CHANNELDOWN, @@ -1343,7 +1343,7 @@ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { [0x2a] = KEY_F21, /* LIVE TIMESHIFT */ [0x0e] = KEY_F22, /* MIN TIMESHIFT */ - [0x1e] = KEY_F23, /* TIMESHIFT */ + [0x1e] = KEY_TIMESHIFT, /* TIMESHIFT */ [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ }; EXPORT_SYMBOL_GPL(ir_codes_gotview7135); @@ -1384,8 +1384,8 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x46] = KEY_PLAY, [0x45] = KEY_PAUSE, /* Pause */ [0x44] = KEY_STOP, + [0x43] = KEY_TIME, /* Time Shift */ #if 0 - [0x43] = KEY_T, /* Time Shift */ [0x47] = KEY_Y, /* Time Shift OFF */ [0x4a] = KEY_O, /* TOP */ #endif @@ -1426,7 +1426,7 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [0x18] = KEY_VOLUMEDOWN, [0x19] = KEY_SHUFFLE, /* Snapshot */ [0x1a] = KEY_NEXTSONG, - [0x1b] = KEY_TEXT, /* Time Shift */ + [0x1b] = KEY_TIME, /* Time Shift */ [0x1c] = KEY_RADIO, /* FM Radio */ [0x1d] = KEY_RECORD, [0x1e] = KEY_PAUSE, @@ -1595,7 +1595,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [0x22] = KEY_PREVIOUS, [0x23] = KEY_PLAYPAUSE, [0x24] = KEY_NEXT, - [0x25] = KEY_ARCHIVE, /* Time Shifting */ + [0x25] = KEY_TIME, /* Time Shifting */ [0x26] = KEY_STOP, [0x27] = KEY_RECORD, [0x28] = KEY_SAVE, /* Screenshot */ @@ -2364,7 +2364,7 @@ IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { * Timeshift Record ChannelDown VolumeDown * * */ - [0x1B] = KEY_REWIND, + [0x1B] = KEY_TIME, [0x1D] = KEY_RECORD, [0x15] = KEY_CHANNELDOWN, [0x18] = KEY_VOLUMEDOWN, @@ -2516,7 +2516,7 @@ IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE] = { Also, it is not related to the time between keyup and keydown. */ - [0x19] = KEY_PAUSE, /* Timeshift */ + [0x19] = KEY_TIME, /* Timeshift */ [0x1a] = KEY_STOP, [0x1b] = KEY_RECORD, @@ -2687,7 +2687,7 @@ IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = { [0x0d] = KEY_AUDIO, /* stereo */ [0x0f] = KEY_PREVIOUS, /* Prev */ - [0x1b] = KEY_PAUSE, /* Timeshift */ + [0x1b] = KEY_TIME, /* Timeshift */ [0x1a] = KEY_NEXT, /* Next */ [0x0e] = KEY_STOP, -- cgit v1.2.3 From eff582b37eade3b542a8501d3f3f920f6eaeab65 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 09:37:00 -0300 Subject: ir-keymaps: Fix IR mappings for channel and volume +/- keys From: Mauro Carvalho Chehab Use standard definitions for channel controls, as defined at: http://linuxtv.org/wiki/index.php/Remote_Controllers While here, fix a few broken up/down/left/right mappings Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 71 ++++++++++++++------------------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 24a635529..d1b742fc2 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -49,19 +49,19 @@ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { [0x08] = KEY_8, [0x09] = KEY_9, - [0x5c] = KEY_POWER, /* power */ - [0x20] = KEY_ZOOM, /* full screen */ - [0x0f] = KEY_BACKSPACE, /* recall */ - [0x1b] = KEY_ENTER, /* mute */ - [0x41] = KEY_RECORD, /* record */ - [0x43] = KEY_STOP, /* stop */ + [0x5c] = KEY_POWER, /* power */ + [0x20] = KEY_ZOOM, /* full screen */ + [0x0f] = KEY_BACKSPACE, /* recall */ + [0x1b] = KEY_ENTER, /* mute */ + [0x41] = KEY_RECORD, /* record */ + [0x43] = KEY_STOP, /* stop */ [0x16] = KEY_S, - [0x1a] = KEY_POWER2, /* off */ + [0x1a] = KEY_POWER2, /* off */ [0x2e] = KEY_RED, - [0x1f] = KEY_DOWN, /* channel - */ - [0x1c] = KEY_UP, /* channel + */ - [0x10] = KEY_LEFT, /* volume - */ - [0x1e] = KEY_RIGHT, /* volume + */ + [0x1f] = KEY_CHANNELDOWN, /* channel - */ + [0x1c] = KEY_CHANNELUP, /* channel + */ + [0x10] = KEY_VOLUMEDOWN, /* volume - */ + [0x1e] = KEY_VOLUMEUP, /* volume + */ [0x14] = KEY_F1, }; EXPORT_SYMBOL_GPL(ir_codes_proteus_2309); @@ -1270,11 +1270,11 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [0x0b] = KEY_UP, /*XXX KEY_SCROLLUP? */ - [0x18] = KEY_LEFT, /*XXX KEY_BACK? */ + [0x0b] = KEY_UP, + [0x18] = KEY_LEFT, [0x16] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ - [0x0c] = KEY_RIGHT, /*XXX KEY_FORWARD? */ - [0x15] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */ + [0x0c] = KEY_RIGHT, + [0x15] = KEY_DOWN, /* 0x11 0x0d * * TV/AV MODE * @@ -1644,8 +1644,6 @@ IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = { [0x23] = KEY_RIGHT, [0x0d] = KEY_SELECT, - - [0x08] = KEY_BACK, [0x07] = KEY_REFRESH, @@ -1757,11 +1755,11 @@ IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { [0x03] = KEY_BRIGHTNESSDOWN, [0x28] = KEY_AUDIO, - [0x3c] = KEY_UP, - [0x3f] = KEY_LEFT, + [0x3c] = KEY_CHANNELUP, + [0x3f] = KEY_VOLUMEDOWN, [0x2e] = KEY_MUTE, - [0x3b] = KEY_RIGHT, - [0x00] = KEY_DOWN, + [0x3b] = KEY_VOLUMEUP, + [0x00] = KEY_CHANNELDOWN, [0x07] = KEY_BRIGHTNESSUP, [0x2c] = KEY_TEXT, @@ -1965,17 +1963,10 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { [0x14] = KEY_HOME, /* win start menu */ [0x15] = KEY_EXIT, /* exit */ -#if 0 [0x16] = KEY_CHANNELUP, /* UP */ [0x12] = KEY_CHANNELDOWN, /* DOWN */ [0x0c] = KEY_VOLUMEUP, /* RIGHT */ [0x17] = KEY_VOLUMEDOWN, /* LEFT */ -#else - [0x16] = KEY_UP, - [0x12] = KEY_DOWN, - [0x0c] = KEY_RIGHT, - [0x17] = KEY_LEFT, -#endif [0x18] = KEY_ENTER, /* OK */ @@ -2268,11 +2259,11 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [0x0b] = KEY_CHANNELUP, /* XXX KEY_UP */ - [0x18] = KEY_VOLUMEDOWN, /* XXX KEY_LEFT */ + [0x0b] = KEY_CHANNELUP, + [0x18] = KEY_VOLUMEDOWN, [0x16] = KEY_OK, /* XXX KEY_ENTER */ - [0x0c] = KEY_VOLUMEUP, /* XXX KEY_RIGHT */ - [0x15] = KEY_CHANNELDOWN, /* XXX KEY_DOWN */ + [0x0c] = KEY_VOLUMEUP, + [0x15] = KEY_CHANNELDOWN, /* 0x11 0x0d * * MUTE INFO * @@ -2450,10 +2441,10 @@ IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = { [0x13] = KEY_BRIGHTNESSDOWN, [0x2b] = KEY_MODE, /* stereo/mono */ [0x2c] = KEY_TEXT, /* teletext */ - [0x20] = KEY_UP, /* channel up */ - [0x21] = KEY_DOWN, /* channel down */ - [0x10] = KEY_RIGHT, /* volume up */ - [0x11] = KEY_LEFT, /* volume down */ + [0x20] = KEY_CHANNELUP, /* channel up */ + [0x21] = KEY_CHANELDOWN, /* channel down */ + [0x10] = KEY_VOLUMEUP, /* volume up */ + [0x11] = KEY_VOLUMEDOWN, /* volume down */ [0x0d] = KEY_MUTE, [0x1f] = KEY_RECORD, [0x17] = KEY_PLAY, @@ -2651,11 +2642,11 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = { [0x54] = KEY_RECORD, [0x4d] = KEY_PLAY, /* pause */ - [0x1e] = KEY_UP, /* video setting */ + [0x1e] = KEY_MENU, /* video setting */ [0x0e] = KEY_RIGHT, /* <- */ [0x1a] = KEY_LEFT, /* -> */ - [0x0a] = KEY_DOWN, /* video default */ + [0x0a] = KEY_CLEAR, /* video default */ [0x0c] = KEY_ZOOM, /* hide pannel */ [0x47] = KEY_SLEEP, /* shutdown */ }; @@ -2748,8 +2739,8 @@ IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { [0x18] = KEY_8, [0x19] = KEY_9, [0x10] = KEY_0, - [0x1c] = KEY_PAGEUP, /* ch+ */ - [0x0f] = KEY_PAGEDOWN, /* ch- */ + [0x1c] = KEY_CHANNELUP, /* ch+ */ + [0x0f] = KEY_CHANNELDOWN, /* ch- */ [0x1a] = KEY_VOLUMEUP, /* vol+ */ [0x0e] = KEY_VOLUMEDOWN, /* vol- */ [0x04] = KEY_RECORD, /* rec */ -- cgit v1.2.3 From 53346f9dc73de737bcab79ce76d1dc2f8bf7b625 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 09:48:21 -0300 Subject: ir-keymaps: use KEY_CAMERA for snapshots From: Mauro Carvalho Chehab KEY_CAMERA is already used for a long time with webcam drivers to take a picture. On other media drivers, due to the lack of a snapshot button, random KEY codes were sent, being KEY_SHUFFLE the most used one, probably due to cut-and-paste from other remotes, since one of them uses the same key for snapshot and shuffle. The better is to use KEY_CAMERA on all drivers solving this issue. This follows the IR standard map as defined at: http://linuxtv.org/wiki/index.php/Remote_Controllers Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index d1b742fc2..7e7a4ca29 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -356,7 +356,7 @@ IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = { [0x14] = KEY_VOLUMEDOWN, [0x13] = KEY_ZOOM, - [0x19] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x19] = KEY_CAMERA, /* SNAPSHOT */ [0x1a] = KEY_SEARCH, /* scan */ [0x37] = KEY_REWIND, /* << */ @@ -683,7 +683,7 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = { [0x0f] = KEY_CLOSE, /* Minimize */ [0x19] = KEY_ZOOM, /* Zoom */ - [0x1a] = KEY_SHUFFLE, /* Snapshot */ + [0x1a] = KEY_CAMERA, /* Snapshot */ [0x0d] = KEY_LANGUAGE, /* MTS */ [0x14] = KEY_VOLUMEDOWN,/* Vol- */ @@ -1089,7 +1089,7 @@ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [0x2b] = KEY_RECORD, /* recording */ [0x2c] = KEY_STOP, /* stop */ [0x2d] = KEY_PLAY, /* play */ - [0x2e] = KEY_SHUFFLE, /* snapshot / shuffle */ + [0x2e] = KEY_CAMERA, /* snapshot / shuffle */ [0x00] = KEY_0, [0x05] = KEY_1, @@ -1140,7 +1140,7 @@ IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [0x2a] = KEY_SEARCH, /* AUTOSCAN */ [0x1a] = KEY_SLEEP, /* FREEZE */ - [0x3a] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x3a] = KEY_CAMERA, /* SNAPSHOT */ [0x0a] = KEY_MUTE, /* MUTE */ [0x26] = KEY_RECORD, /* RECORD */ @@ -1301,7 +1301,7 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * MUTE SNAPSHOT* * */ [0x13] = KEY_MUTE, - [0x19] = KEY_RECORD, /*XXX*/ + [0x19] = KEY_CAMERA, /* 0x1d unused ? */ }; @@ -1331,8 +1331,8 @@ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { [0x0c] = KEY_VOLUMEDOWN, [0x28] = KEY_VOLUMEUP, [0x08] = KEY_MUTE, - [0x26] = KEY_SEARCH, /*SCAN*/ - [0x3f] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x26] = KEY_SEARCH, /* SCAN */ + [0x3f] = KEY_CAMERA, /* SNAPSHOT */ [0x12] = KEY_RECORD, [0x32] = KEY_STOP, [0x3c] = KEY_PLAY, @@ -1424,7 +1424,7 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [0x13] = KEY_MUTE, [0x15] = KEY_CHANNELDOWN, [0x18] = KEY_VOLUMEDOWN, - [0x19] = KEY_SHUFFLE, /* Snapshot */ + [0x19] = KEY_CAMERA, /* Snapshot */ [0x1a] = KEY_NEXTSONG, [0x1b] = KEY_TIME, /* Time Shift */ [0x1c] = KEY_RADIO, /* FM Radio */ @@ -2049,7 +2049,7 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE] = { [0x72] = KEY_CHANNELDOWN, [0x41] = KEY_RECORD, - [0x51] = KEY_SHUFFLE, /* Snapshot */ + [0x51] = KEY_CAMERA, /* Snapshot */ [0x75] = KEY_TIME, /* Timeshift */ [0x71] = KEY_TV2, /* PIP */ @@ -2297,7 +2297,7 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * FREEZE SNAPSHOT * * */ [0x58] = KEY_SLOW, - [0x5c] = KEY_SAVE, + [0x5c] = KEY_CAMERA, }; EXPORT_SYMBOL_GPL(ir_codes_behold); @@ -2337,7 +2337,7 @@ IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { [0x04] = KEY_4, [0x05] = KEY_5, [0x06] = KEY_6, - [0x19] = KEY_BOOKMARKS, /* Snapshot key */ + [0x19] = KEY_CAMERA, /* Snapshot key */ [0x07] = KEY_7, [0x08] = KEY_8, [0x09] = KEY_9, @@ -2408,7 +2408,7 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = { an alternate name written */ [0x1e] = KEY_UP, /* Video Setting */ [0x0a] = KEY_DOWN, /* Video Default */ - [0x05] = KEY_LEFT, /* Snapshot */ + [0x05] = KEY_CAMERA, /* Snapshot */ [0x0c] = KEY_RIGHT, /* Hide Panel */ /* Four buttons without label */ [0x49] = KEY_RED, @@ -2453,7 +2453,7 @@ IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = { [0x27] = KEY_FASTFORWARD, [0x26] = KEY_REWIND, [0x1e] = KEY_SEARCH, /* autoscan */ - [0x0e] = KEY_SHUFFLE, /* snapshot */ + [0x0e] = KEY_CAMERA, /* snapshot */ [0x2d] = KEY_SETUP, [0x0f] = KEY_SCREEN, /* full screen */ [0x14] = KEY_RADIO, /* FM radio */ @@ -2515,7 +2515,7 @@ IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE] = { [0x15] = KEY_AUDIO, /* ((*)) */ [0x0f] = KEY_ZOOM, - [0x1c] = KEY_SHUFFLE, /* snapshot */ + [0x1c] = KEY_CAMERA, /* snapshot */ [0x18] = KEY_RED, /* B */ [0x23] = KEY_GREEN, /* C */ @@ -2631,7 +2631,7 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = { [0x40] = KEY_LAST, /* recall */ [0x02] = KEY_MODE, /* TV/AV */ - [0x05] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x05] = KEY_CAMERA, /* SNAPSHOT */ [0x4c] = KEY_CHANNELUP, /* UP */ [0x00] = KEY_CHANNELDOWN, /* DOWN */ @@ -2687,7 +2687,7 @@ IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = { [0x1d] = KEY_RECORD, [0x13] = KEY_MUTE, - [0x19] = KEY_SHUFFLE, /* Snapshot */ + [0x19] = KEY_CAMERA, /* Snapshot */ }; EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys); @@ -2871,7 +2871,7 @@ IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = { [0x29] = KEY_CHANNEL, /* SURF */ [0x2b] = KEY_A, [0x2c] = KEY_B, - [0x2f] = KEY_SHUFFLE, /* Snapshot */ + [0x2f] = KEY_CAMERA, /* Snapshot */ [0x23] = KEY_RADIO, [0x02] = KEY_PREVIOUSSONG, [0x06] = KEY_NEXTSONG, -- cgit v1.2.3 From 53e62967f3826e6ee00f29ee836c49cd4ca3485d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 09:51:51 -0300 Subject: Fix compilation issues caused by typos From: Mauro Carvalho Chehab This patch should be folded with the original ones at -git. kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 7e7a4ca29..7ab7d0586 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -1343,7 +1343,7 @@ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { [0x2a] = KEY_F21, /* LIVE TIMESHIFT */ [0x0e] = KEY_F22, /* MIN TIMESHIFT */ - [0x1e] = KEY_TIMESHIFT, /* TIMESHIFT */ + [0x1e] = KEY_TIME, /* TIMESHIFT */ [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ }; EXPORT_SYMBOL_GPL(ir_codes_gotview7135); @@ -2442,7 +2442,7 @@ IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = { [0x2b] = KEY_MODE, /* stereo/mono */ [0x2c] = KEY_TEXT, /* teletext */ [0x20] = KEY_CHANNELUP, /* channel up */ - [0x21] = KEY_CHANELDOWN, /* channel down */ + [0x21] = KEY_CHANNELDOWN, /* channel down */ [0x10] = KEY_VOLUMEUP, /* volume up */ [0x11] = KEY_VOLUMEDOWN, /* volume down */ [0x0d] = KEY_MUTE, -- cgit v1.2.3 From 810944b9c6ecec7746372ac6ae94252d2d713531 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Aug 2009 22:06:28 -0300 Subject: FM1216MK5 FM radio From: Dmitri Belimov Implement Philips FM1216MK5. 1. Implement get_stereo function. 2. Add correct data byte for FM radio mode Priority: normal Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-simple.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux/drivers/media/common/tuners/tuner-simple.c b/linux/drivers/media/common/tuners/tuner-simple.c index 2ac1c8edb..4bac1d0c6 100644 --- a/linux/drivers/media/common/tuners/tuner-simple.c +++ b/linux/drivers/media/common/tuners/tuner-simple.c @@ -145,6 +145,8 @@ static inline int tuner_stereo(const int type, const int status) case TUNER_LG_NTSC_TAPE: case TUNER_TCL_MF02GIP_5N: return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); + case TUNER_PHILIPS_FM1216MK5: + return status | TUNER_STEREO; default: return status & TUNER_STEREO; } @@ -515,6 +517,10 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) case TUNER_TCL_MF02GIP_5N: buffer[3] = 0x19; break; + case TUNER_PHILIPS_FM1216MK5: + buffer[2] = 0x88; + buffer[3] = 0x09; + break; case TUNER_TNF_5335MF: buffer[3] = 0x11; break; -- cgit v1.2.3 From 640cb9f7f8d3aca8ad56e1f6a7bac42e15aa6962 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Aug 2009 22:10:55 -0300 Subject: support AverMedia Studio 505 From: Vasiliy Temnikov Added support to AverMedia Studio 505 Priority: normal Signed-off-by: Vasiliy Temnikov [dougsland@redhat.com: fixed rejects and removed the change to add dk as default secam variant] [mchehab@redhat.com: fix a few CodingStyle issues] Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.saa7134 | 1 + linux/drivers/media/video/saa7134/saa7134-cards.c | 43 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/saa7134-input.c | 1 + linux/drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 46 insertions(+) diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134 index dc0576afe..31d9f14d6 100644 --- a/linux/Documentation/video4linux/CARDLIST.saa7134 +++ b/linux/Documentation/video4linux/CARDLIST.saa7134 @@ -168,3 +168,4 @@ 167 -> Beholder BeholdTV 609 RDS [5ace:6092] 168 -> Beholder BeholdTV 609 RDS [5ace:6093] 169 -> Compro VideoMate S350/S300 [185b:c900] +170 -> AverMedia AverTV Studio 505 [1461:a115] diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index c401a37ea..cdb04fdbb 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -1364,6 +1364,42 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_AVERMEDIA_STUDIO_505] = { + /* Vasiliy Temnikov */ + .name = "AverMedia AverTV Studio 505", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = LINE2, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 0, + .amux = LINE2, + }, { + .name = name_comp2, + .vmux = 3, + .amux = LINE2, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + .mute = { + .name = name_mute, + .amux = LINE1, + }, + }, [SAA7134_BOARD_UPMOST_PURPLE_TV] = { .name = "UPMOST PURPLE TV", .audio_clock = 0x00187de7, @@ -5437,6 +5473,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x2115, .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_305, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7130, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xa115, + .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_505, + }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x1461, /* Avermedia Technologies Inc */ @@ -6607,6 +6649,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: case SAA7134_BOARD_KWORLD_XPERT: case SAA7134_BOARD_AVERMEDIA_STUDIO_305: + case SAA7134_BOARD_AVERMEDIA_STUDIO_505: case SAA7134_BOARD_AVERMEDIA_305: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_307: diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 146ac816a..8dbad5dbe 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -486,6 +486,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_305: case SAA7134_BOARD_AVERMEDIA_307: case SAA7134_BOARD_AVERMEDIA_STUDIO_305: + case SAA7134_BOARD_AVERMEDIA_STUDIO_505: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_STUDIO_507: case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA: diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index c0757f8a1..b59e0f18b 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -294,6 +294,7 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_609RDS_MK3 167 #define SAA7134_BOARD_BEHOLD_609RDS_MK5 168 #define SAA7134_BOARD_VIDEOMATE_S350 169 +#define SAA7134_BOARD_AVERMEDIA_STUDIO_505 170 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 52ef68ff244a5cd4707558c9aa803ecb9c1342dc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Aug 2009 22:13:43 -0300 Subject: Fix test of bandwidth range in cx22700_set_tps() From: Roel Kluin For the bandwidth to be less than 8 MHZ and greater than 6 MHZ is logically impossible. Priority: normal Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/cx22700.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/frontends/cx22700.c b/linux/drivers/media/dvb/frontends/cx22700.c index fbd838eca..5fbc0fc37 100644 --- a/linux/drivers/media/dvb/frontends/cx22700.c +++ b/linux/drivers/media/dvb/frontends/cx22700.c @@ -155,7 +155,7 @@ static int cx22700_set_tps (struct cx22700_state *state, struct dvb_ofdm_paramet p->hierarchy_information > HIERARCHY_4) return -EINVAL; - if (p->bandwidth < BANDWIDTH_8_MHZ && p->bandwidth > BANDWIDTH_6_MHZ) + if (p->bandwidth < BANDWIDTH_8_MHZ || p->bandwidth > BANDWIDTH_6_MHZ) return -EINVAL; if (p->bandwidth == BANDWIDTH_7_MHZ) -- cgit v1.2.3 From ffa87ee185160e8a3c127e3383a6038b7e85ffe4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Aug 2009 09:28:48 -0300 Subject: Use C99 comment CodingStyle From: Mauro Carvalho Chehab The ir-keymaps.c has frequent additions. As people tend to copy an old keyboard entry, a bad CodingStyle at an ancient entry may result on a freshly bad CodingStyle patch. So, better to fix the CodingStyle for the entire file. This patch is the first of a series of patches fixing it, generated by some perl magic plus manual handling. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 428 ++++++++++++++++---------------- 1 file changed, 216 insertions(+), 212 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 0b1566d34..471df71a3 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -65,41 +65,41 @@ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_proteus_2309); /* Matt Jesson >' - [ 0x3a ] = KEY_RECORD, // 'capture' - [ 0x0a ] = KEY_MUTE, // 'mute' - [ 0x2c ] = KEY_RECORD, // 'record' - [ 0x1c ] = KEY_PAUSE, // 'pause' - [ 0x3c ] = KEY_STOP, // 'stop' - [ 0x0c ] = KEY_PLAY, // 'play' - [ 0x2e ] = KEY_RED, // 'red' - [ 0x01 ] = KEY_BLUE, // 'blue' / 'cancel' - [ 0x0e ] = KEY_YELLOW, // 'yellow' / 'ok' - [ 0x21 ] = KEY_GREEN, // 'green' - [ 0x11 ] = KEY_CHANNELDOWN, // 'channel -' - [ 0x31 ] = KEY_CHANNELUP, // 'channel +' - [ 0x1e ] = KEY_VOLUMEDOWN, // 'volume -' - [ 0x3e ] = KEY_VOLUMEUP, // 'volume +' + [ 0x28 ] = KEY_0, /* '0' / 'enter' */ + [ 0x22 ] = KEY_1, /* '1' */ + [ 0x12 ] = KEY_2, /* '2' / 'up arrow' */ + [ 0x32 ] = KEY_3, /* '3' */ + [ 0x24 ] = KEY_4, /* '4' / 'left arrow' */ + [ 0x14 ] = KEY_5, /* '5' */ + [ 0x34 ] = KEY_6, /* '6' / 'right arrow' */ + [ 0x26 ] = KEY_7, /* '7' */ + [ 0x16 ] = KEY_8, /* '8' / 'down arrow' */ + [ 0x36 ] = KEY_9, /* '9' */ + + [ 0x20 ] = KEY_LIST, /* 'source' */ + [ 0x10 ] = KEY_TEXT, /* 'teletext' */ + [ 0x00 ] = KEY_POWER, /* 'power' */ + [ 0x04 ] = KEY_AUDIO, /* 'audio' */ + [ 0x06 ] = KEY_ZOOM, /* 'full screen' */ + [ 0x18 ] = KEY_VIDEO, /* 'display' */ + [ 0x38 ] = KEY_SEARCH, /* 'loop' */ + [ 0x08 ] = KEY_INFO, /* 'preview' */ + [ 0x2a ] = KEY_REWIND, /* 'backward <<' */ + [ 0x1a ] = KEY_FASTFORWARD, /* 'forward >>' */ + [ 0x3a ] = KEY_RECORD, /* 'capture' */ + [ 0x0a ] = KEY_MUTE, /* 'mute' */ + [ 0x2c ] = KEY_RECORD, /* 'record' */ + [ 0x1c ] = KEY_PAUSE, /* 'pause' */ + [ 0x3c ] = KEY_STOP, /* 'stop' */ + [ 0x0c ] = KEY_PLAY, /* 'play' */ + [ 0x2e ] = KEY_RED, /* 'red' */ + [ 0x01 ] = KEY_BLUE, /* 'blue' / 'cancel' */ + [ 0x0e ] = KEY_YELLOW, /* 'yellow' / 'ok' */ + [ 0x21 ] = KEY_GREEN, /* 'green' */ + [ 0x11 ] = KEY_CHANNELDOWN, /* 'channel -' */ + [ 0x31 ] = KEY_CHANNELUP, /* 'channel +' */ + [ 0x1e ] = KEY_VOLUMEDOWN, /* 'volume -' */ + [ 0x3e ] = KEY_VOLUMEUP, /* 'volume +' */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); @@ -226,32 +226,32 @@ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { [ 0x08 ] = KEY_8, [ 0x09 ] = KEY_9, [ 0x00 ] = KEY_0, - [ 0x17 ] = KEY_LAST, // +100 - [ 0x0a ] = KEY_LIST, // recall - - - [ 0x1c ] = KEY_TUNER, // TV/FM - [ 0x15 ] = KEY_SEARCH, // scan - [ 0x12 ] = KEY_POWER, // power - [ 0x1f ] = KEY_VOLUMEDOWN, // vol up - [ 0x1b ] = KEY_VOLUMEUP, // vol down - [ 0x1e ] = KEY_CHANNELDOWN, // chn up - [ 0x1a ] = KEY_CHANNELUP, // chn down - - [ 0x11 ] = KEY_VIDEO, // video - [ 0x0f ] = KEY_ZOOM, // full screen - [ 0x13 ] = KEY_MUTE, // mute/unmute - [ 0x10 ] = KEY_TEXT, // min - - [ 0x0d ] = KEY_STOP, // freeze - [ 0x0e ] = KEY_RECORD, // record - [ 0x1d ] = KEY_PLAYPAUSE, // stop - [ 0x19 ] = KEY_PLAY, // play - - [ 0x16 ] = KEY_GOTO, // osd - [ 0x14 ] = KEY_REFRESH, // default - [ 0x0c ] = KEY_KPPLUS, // fine tune >>>> - [ 0x18 ] = KEY_KPMINUS // fine tune <<<< + [ 0x17 ] = KEY_LAST, /* +100 */ + [ 0x0a ] = KEY_LIST, /* recall */ + + + [ 0x1c ] = KEY_TUNER, /* TV/FM */ + [ 0x15 ] = KEY_SEARCH, /* scan */ + [ 0x12 ] = KEY_POWER, /* power */ + [ 0x1f ] = KEY_VOLUMEDOWN, /* vol up */ + [ 0x1b ] = KEY_VOLUMEUP, /* vol down */ + [ 0x1e ] = KEY_CHANNELDOWN, /* chn up */ + [ 0x1a ] = KEY_CHANNELUP, /* chn down */ + + [ 0x11 ] = KEY_VIDEO, /* video */ + [ 0x0f ] = KEY_ZOOM, /* full screen */ + [ 0x13 ] = KEY_MUTE, /* mute/unmute */ + [ 0x10 ] = KEY_TEXT, /* min */ + + [ 0x0d ] = KEY_STOP, /* freeze */ + [ 0x0e ] = KEY_RECORD, /* record */ + [ 0x1d ] = KEY_PLAYPAUSE, /* stop */ + [ 0x19 ] = KEY_PLAY, /* play */ + + [ 0x16 ] = KEY_GOTO, /* osd */ + [ 0x14 ] = KEY_REFRESH, /* default */ + [ 0x0c ] = KEY_KPPLUS, /* fine tune >>>> */ + [ 0x18 ] = KEY_KPMINUS /* fine tune <<<< */ }; EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); @@ -260,38 +260,42 @@ EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { - [ 0x1e ] = KEY_POWER, // power - [ 0x07 ] = KEY_MEDIA, // source - [ 0x1c ] = KEY_SEARCH, // scan + [ 0x1e ] = KEY_POWER, /* power */ + [ 0x07 ] = KEY_MEDIA, /* source */ + [ 0x1c ] = KEY_SEARCH, /* scan */ -/* FIXME: duplicate keycodes? - * +#if 0 +/* FIXME: duplicate keycodes? */ + +/* * These four keys seem to share the same GPIO as CH+, CH-, <<< and >>> * The GPIO values are * 6397fb for both "Scan <" and "CH -", * 639ffb for "Scan >" and "CH+", * 6384fb for "Tune <" and "<<<", * 638cfb for "Tune >" and ">>>", regardless of the mask. - * - * [ 0x17 ] = KEY_BACK, // fm scan << - * [ 0x1f ] = KEY_FORWARD, // fm scan >> - * - * [ 0x04 ] = KEY_LEFT, // fm tuning < - * [ 0x0c ] = KEY_RIGHT, // fm tuning > - * + */ + [ 0x17 ] = KEY_BACK, /* fm scan << */ + [ 0x1f ] = KEY_FORWARD, /* fm scan >> */ + + [ 0x04 ] = KEY_LEFT, /* fm tuning < */ + [ 0x0c ] = KEY_RIGHT, /* fm tuning > */ + +/* * For now, these four keys are disabled. Pressing them will generate * the CH+/CH-/<<>> events */ +#endif - [ 0x03 ] = KEY_TUNER, // TV/FM + [ 0x03 ] = KEY_TUNER, /* TV/FM */ [ 0x00 ] = KEY_RECORD, [ 0x08 ] = KEY_STOP, [ 0x11 ] = KEY_PLAY, - [ 0x1a ] = KEY_PLAYPAUSE, // freeze - [ 0x19 ] = KEY_ZOOM, // zoom - [ 0x0f ] = KEY_TEXT, // min + [ 0x1a ] = KEY_PLAYPAUSE, /* freeze */ + [ 0x19 ] = KEY_ZOOM, /* zoom */ + [ 0x0f ] = KEY_TEXT, /* min */ [ 0x01 ] = KEY_1, [ 0x0b ] = KEY_2, @@ -303,21 +307,21 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { [ 0x0a ] = KEY_8, [ 0x12 ] = KEY_9, [ 0x02 ] = KEY_0, - [ 0x10 ] = KEY_LAST, // +100 - [ 0x13 ] = KEY_LIST, // recall + [ 0x10 ] = KEY_LAST, /* +100 */ + [ 0x13 ] = KEY_LIST, /* recall */ - [ 0x1f ] = KEY_CHANNELUP, // chn down - [ 0x17 ] = KEY_CHANNELDOWN, // chn up - [ 0x16 ] = KEY_VOLUMEUP, // vol down - [ 0x14 ] = KEY_VOLUMEDOWN, // vol up + [ 0x1f ] = KEY_CHANNELUP, /* chn down */ + [ 0x17 ] = KEY_CHANNELDOWN, /* chn up */ + [ 0x16 ] = KEY_VOLUMEUP, /* vol down */ + [ 0x14 ] = KEY_VOLUMEDOWN, /* vol up */ - [ 0x04 ] = KEY_KPMINUS, // <<< - [ 0x0e ] = KEY_SETUP, // function - [ 0x0c ] = KEY_KPPLUS, // >>> + [ 0x04 ] = KEY_KPMINUS, /* <<< */ + [ 0x0e ] = KEY_SETUP, /* function */ + [ 0x0c ] = KEY_KPPLUS, /* >>> */ - [ 0x0d ] = KEY_GOTO, // mts - [ 0x1d ] = KEY_REFRESH, // reset - [ 0x18 ] = KEY_MUTE // mute/unmute + [ 0x0d ] = KEY_GOTO, /* mts */ + [ 0x1d ] = KEY_REFRESH, /* reset */ + [ 0x18 ] = KEY_MUTE /* mute/unmute */ }; EXPORT_SYMBOL_GPL(ir_codes_pixelview); @@ -958,31 +962,31 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { [ 0x0c ] = KEY_8, [ 0x0d ] = KEY_9, - [ 0x0e ] = KEY_MODE, // Air/Cable - [ 0x11 ] = KEY_VIDEO, // Video - [ 0x15 ] = KEY_AUDIO, // Audio - [ 0x00 ] = KEY_POWER, // Power - [ 0x18 ] = KEY_TUNER, // AV Source - [ 0x02 ] = KEY_ZOOM, // Fullscreen - [ 0x1a ] = KEY_LANGUAGE, // Stereo - [ 0x1b ] = KEY_MUTE, // Mute - [ 0x14 ] = KEY_VOLUMEUP, // Volume + - [ 0x17 ] = KEY_VOLUMEDOWN, // Volume - - [ 0x12 ] = KEY_CHANNELUP, // Channel + - [ 0x13 ] = KEY_CHANNELDOWN, // Channel - - [ 0x06 ] = KEY_AGAIN, // Recall - [ 0x10 ] = KEY_ENTER, // Enter - - [ 0x19 ] = KEY_BACK, // Rewind ( <<< ) - [ 0x1f ] = KEY_FORWARD, // Forward ( >>> ) - [ 0x0a ] = KEY_ANGLE, // (no label, may be used as the PAUSE button) + [ 0x0e ] = KEY_MODE, /* Air/Cable */ + [ 0x11 ] = KEY_VIDEO, /* Video */ + [ 0x15 ] = KEY_AUDIO, /* Audio */ + [ 0x00 ] = KEY_POWER, /* Power */ + [ 0x18 ] = KEY_TUNER, /* AV Source */ + [ 0x02 ] = KEY_ZOOM, /* Fullscreen */ + [ 0x1a ] = KEY_LANGUAGE, /* Stereo */ + [ 0x1b ] = KEY_MUTE, /* Mute */ + [ 0x14 ] = KEY_VOLUMEUP, /* Volume + */ + [ 0x17 ] = KEY_VOLUMEDOWN, /* Volume - */ + [ 0x12 ] = KEY_CHANNELUP, /* Channel + */ + [ 0x13 ] = KEY_CHANNELDOWN, /* Channel - */ + [ 0x06 ] = KEY_AGAIN, /* Recall */ + [ 0x10 ] = KEY_ENTER, /* Enter */ + + [ 0x19 ] = KEY_BACK, /* Rewind ( <<< ) */ + [ 0x1f ] = KEY_FORWARD, /* Forward ( >>> ) */ + [ 0x0a ] = KEY_ANGLE, /* (no label, may be used as the PAUSE button) */ }; EXPORT_SYMBOL_GPL(ir_codes_flyvideo); IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_ZOOM, // Full Screen - [ 0x00 ] = KEY_POWER, // Power + [ 0x01 ] = KEY_ZOOM, /* Full Screen */ + [ 0x00 ] = KEY_POWER, /* Power */ [ 0x03 ] = KEY_1, [ 0x04 ] = KEY_2, @@ -993,30 +997,30 @@ IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { [ 0x0b ] = KEY_7, [ 0x0c ] = KEY_8, [ 0x0d ] = KEY_9, - [ 0x06 ] = KEY_AGAIN, // Recall + [ 0x06 ] = KEY_AGAIN, /* Recall */ [ 0x0f ] = KEY_0, - [ 0x10 ] = KEY_MUTE, // Mute - [ 0x02 ] = KEY_RADIO, // TV/Radio - [ 0x1b ] = KEY_LANGUAGE, // SAP (Second Audio Program) - - [ 0x14 ] = KEY_VOLUMEUP, // VOL+ - [ 0x17 ] = KEY_VOLUMEDOWN, // VOL- - [ 0x12 ] = KEY_CHANNELUP, // CH+ - [ 0x13 ] = KEY_CHANNELDOWN, // CH- - [ 0x1d ] = KEY_ENTER, // Enter - - [ 0x1a ] = KEY_MODE, // PIP - [ 0x18 ] = KEY_TUNER, // Source - - [ 0x1e ] = KEY_RECORD, // Record/Pause - [ 0x15 ] = KEY_ANGLE, // Swap (no label on key) - [ 0x1c ] = KEY_PAUSE, // Timeshift/Pause - [ 0x19 ] = KEY_BACK, // Rewind << - [ 0x0a ] = KEY_PLAYPAUSE, // Play/Pause - [ 0x1f ] = KEY_FORWARD, // Forward >> - [ 0x16 ] = KEY_PREVIOUS, // Back |<< - [ 0x11 ] = KEY_STOP, // Stop - [ 0x0e ] = KEY_NEXT, // End >>| + [ 0x10 ] = KEY_MUTE, /* Mute */ + [ 0x02 ] = KEY_RADIO, /* TV/Radio */ + [ 0x1b ] = KEY_LANGUAGE, /* SAP (Second Audio Program) */ + + [ 0x14 ] = KEY_VOLUMEUP, /* VOL+ */ + [ 0x17 ] = KEY_VOLUMEDOWN, /* VOL- */ + [ 0x12 ] = KEY_CHANNELUP, /* CH+ */ + [ 0x13 ] = KEY_CHANNELDOWN, /* CH- */ + [ 0x1d ] = KEY_ENTER, /* Enter */ + + [ 0x1a ] = KEY_MODE, /* PIP */ + [ 0x18 ] = KEY_TUNER, /* Source */ + + [ 0x1e ] = KEY_RECORD, /* Record/Pause */ + [ 0x15 ] = KEY_ANGLE, /* Swap (no label on key) */ + [ 0x1c ] = KEY_PAUSE, /* Timeshift/Pause */ + [ 0x19 ] = KEY_BACK, /* Rewind << */ + [ 0x0a ] = KEY_PLAYPAUSE, /* Play/Pause */ + [ 0x1f ] = KEY_FORWARD, /* Forward >> */ + [ 0x16 ] = KEY_PREVIOUS, /* Back |<< */ + [ 0x11 ] = KEY_STOP, /* Stop */ + [ 0x0e ] = KEY_NEXT, /* End >>| */ }; EXPORT_SYMBOL_GPL(ir_codes_flydvb); @@ -1034,15 +1038,15 @@ IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { [ 0x09 ] = KEY_9, [ 0x0a ] = KEY_POWER, - [ 0x0b ] = KEY_PROG1, // app - [ 0x0c ] = KEY_ZOOM, // zoom/fullscreen - [ 0x0d ] = KEY_CHANNELUP, // channel - [ 0x0e ] = KEY_CHANNELDOWN, // channel- + [ 0x0b ] = KEY_PROG1, /* app */ + [ 0x0c ] = KEY_ZOOM, /* zoom/fullscreen */ + [ 0x0d ] = KEY_CHANNELUP, /* channel */ + [ 0x0e ] = KEY_CHANNELDOWN, /* channel- */ [ 0x0f ] = KEY_VOLUMEUP, [ 0x10 ] = KEY_VOLUMEDOWN, - [ 0x11 ] = KEY_TUNER, // AV - [ 0x12 ] = KEY_NUMLOCK, // -/-- - [ 0x13 ] = KEY_AUDIO, // audio + [ 0x11 ] = KEY_TUNER, /* AV */ + [ 0x12 ] = KEY_NUMLOCK, /* -/-- */ + [ 0x13 ] = KEY_AUDIO, /* audio */ [ 0x14 ] = KEY_MUTE, [ 0x15 ] = KEY_UP, [ 0x16 ] = KEY_DOWN, @@ -1050,7 +1054,7 @@ IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { [ 0x18 ] = KEY_RIGHT, [ 0x19 ] = BTN_LEFT, [ 0x1a ] = BTN_RIGHT, - [ 0x1b ] = KEY_WWW, // text + [ 0x1b ] = KEY_WWW, /* text */ [ 0x1c ] = KEY_REWIND, [ 0x1d ] = KEY_FORWARD, [ 0x1e ] = KEY_RECORD, @@ -1067,38 +1071,38 @@ EXPORT_SYMBOL_GPL(ir_codes_cinergy); * updates from Job D. R. Borges */ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [ 0x12 ] = KEY_POWER, - [ 0x01 ] = KEY_TV, // DVR - [ 0x15 ] = KEY_DVD, // DVD - [ 0x17 ] = KEY_AUDIO, // music - // DVR mode / DVD mode / music mode - - [ 0x1b ] = KEY_MUTE, // mute - [ 0x02 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek - [ 0x1e ] = KEY_SUBTITLE, // closed captioning / subtitle / seek - [ 0x16 ] = KEY_ZOOM, // full screen - [ 0x1c ] = KEY_VIDEO, // video source / eject / delall - [ 0x1d ] = KEY_RESTART, // playback / angle / del - [ 0x2f ] = KEY_SEARCH, // scan / menu / playlist - [ 0x30 ] = KEY_CHANNEL, // CH surfing / bookmark / memo - - [ 0x31 ] = KEY_HELP, // help - [ 0x32 ] = KEY_MODE, // num/memo - [ 0x33 ] = KEY_ESC, // cancel - - [ 0x0c ] = KEY_UP, // up - [ 0x10 ] = KEY_DOWN, // down - [ 0x08 ] = KEY_LEFT, // left - [ 0x04 ] = KEY_RIGHT, // right - [ 0x03 ] = KEY_SELECT, // select - - [ 0x1f ] = KEY_REWIND, // rewind - [ 0x20 ] = KEY_PLAYPAUSE, // play/pause - [ 0x29 ] = KEY_FORWARD, // forward - [ 0x14 ] = KEY_AGAIN, // repeat - [ 0x2b ] = KEY_RECORD, // recording - [ 0x2c ] = KEY_STOP, // stop - [ 0x2d ] = KEY_PLAY, // play - [ 0x2e ] = KEY_SHUFFLE, // snapshot / shuffle + [ 0x01 ] = KEY_TV, /* DVR */ + [ 0x15 ] = KEY_DVD, /* DVD */ + [ 0x17 ] = KEY_AUDIO, /* music */ + /* DVR mode / DVD mode / music mode */ + + [ 0x1b ] = KEY_MUTE, /* mute */ + [ 0x02 ] = KEY_LANGUAGE, /* MTS/SAP / audio / autoseek */ + [ 0x1e ] = KEY_SUBTITLE, /* closed captioning / subtitle / seek */ + [ 0x16 ] = KEY_ZOOM, /* full screen */ + [ 0x1c ] = KEY_VIDEO, /* video source / eject / delall */ + [ 0x1d ] = KEY_RESTART, /* playback / angle / del */ + [ 0x2f ] = KEY_SEARCH, /* scan / menu / playlist */ + [ 0x30 ] = KEY_CHANNEL, /* CH surfing / bookmark / memo */ + + [ 0x31 ] = KEY_HELP, /* help */ + [ 0x32 ] = KEY_MODE, /* num/memo */ + [ 0x33 ] = KEY_ESC, /* cancel */ + + [ 0x0c ] = KEY_UP, /* up */ + [ 0x10 ] = KEY_DOWN, /* down */ + [ 0x08 ] = KEY_LEFT, /* left */ + [ 0x04 ] = KEY_RIGHT, /* right */ + [ 0x03 ] = KEY_SELECT, /* select */ + + [ 0x1f ] = KEY_REWIND, /* rewind */ + [ 0x20 ] = KEY_PLAYPAUSE, /* play/pause */ + [ 0x29 ] = KEY_FORWARD, /* forward */ + [ 0x14 ] = KEY_AGAIN, /* repeat */ + [ 0x2b ] = KEY_RECORD, /* recording */ + [ 0x2c ] = KEY_STOP, /* stop */ + [ 0x2d ] = KEY_PLAY, /* play */ + [ 0x2e ] = KEY_SHUFFLE, /* snapshot / shuffle */ [ 0x00 ] = KEY_0, [ 0x05 ] = KEY_1, @@ -1113,11 +1117,11 @@ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [ 0x2a ] = KEY_VOLUMEUP, [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x18 ] = KEY_CHANNELUP, // CH.tracking up - [ 0x19 ] = KEY_CHANNELDOWN, // CH.tracking down + [ 0x18 ] = KEY_CHANNELUP, /* CH.tracking up */ + [ 0x19 ] = KEY_CHANNELDOWN, /* CH.tracking down */ - [ 0x13 ] = KEY_ENTER, // enter - [ 0x21 ] = KEY_DOT, // . (decimal dot) + [ 0x13 ] = KEY_ENTER, /* enter */ + [ 0x21 ] = KEY_DOT, /* . (decimal dot) */ }; EXPORT_SYMBOL_GPL(ir_codes_eztv); @@ -1315,7 +1319,7 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { [ 0x13 ] = KEY_MUTE, [ 0x19 ] = KEY_RECORD, /*XXX*/ - // 0x1d unused ? + /* 0x1d unused ? */ }; EXPORT_SYMBOL_GPL(ir_codes_manli); @@ -1401,10 +1405,10 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [ 0x45 ] = KEY_PAUSE, /* Pause */ [ 0x44 ] = KEY_STOP, #if 0 - [ 0x43 ] = KEY_T, // Time Shift - [ 0x47 ] = KEY_Y, // Time Shift OFF - [ 0x4a ] = KEY_O, // TOP - [ 0x17 ] = KEY_F, // SURF CH + [ 0x43 ] = KEY_T, /* Time Shift */ + [ 0x47 ] = KEY_Y, /* Time Shift OFF */ + [ 0x4a ] = KEY_O, /* TOP */ + [ 0x17 ] = KEY_F, /* SURF CH */ #endif [ 0x40 ] = KEY_FORWARD, /* Forward ? */ [ 0x42 ] = KEY_REWIND, /* Backward ? */ @@ -1538,37 +1542,37 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [ 0x3d ] = KEY_SUSPEND, /* system standby */ #if 0 /* FIXME */ - [ 0x0a ] = KEY_RESERVED, // 1/2/3 digits (japan: 10) - [ 0x0e ] = KEY_RESERVED, // P.P. (personal preference) - [ 0x14 ] = KEY_RESERVED, // colour saturation + - [ 0x15 ] = KEY_RESERVED, // colour saturation - - [ 0x16 ] = KEY_RESERVED, // bass + - [ 0x17 ] = KEY_RESERVED, // bass - - [ 0x18 ] = KEY_RESERVED, // treble + - [ 0x19 ] = KEY_RESERVED, // treble - - [ 0x1a ] = KEY_RESERVED, // balance right - [ 0x1b ] = KEY_RESERVED, // balance left - [ 0x1c ] = KEY_RESERVED, // contrast + - [ 0x1d ] = KEY_RESERVED, // contrast - - [ 0x1f ] = KEY_RESERVED, // tint/hue + - [ 0x24 ] = KEY_RESERVED, // spacial stereo on/off - [ 0x25 ] = KEY_RESERVED, // mono / stereo (USA) - [ 0x27 ] = KEY_RESERVED, // tint / hue - - [ 0x28 ] = KEY_RESERVED, // RF switch/PIP select - [ 0x29 ] = KEY_RESERVED, // vote - [ 0x2a ] = KEY_RESERVED, // timed page/channel clck - [ 0x2b ] = KEY_RESERVED, // increment (USA) - [ 0x2c ] = KEY_RESERVED, // decrement (USA) - [ 0x2d ] = KEY_RESERVED, // - [ 0x2f ] = KEY_RESERVED, // PIP shift - [ 0x31 ] = KEY_RESERVED, // erase - [ 0x34 ] = KEY_RESERVED, // wind - [ 0x38 ] = KEY_RESERVED, // external 1 - [ 0x39 ] = KEY_RESERVED, // external 2 - [ 0x3a ] = KEY_RESERVED, // PIP display mode - [ 0x3b ] = KEY_RESERVED, // view data mode / advance - [ 0x3e ] = KEY_RESERVED, // crispener on/off - [ 0x3f ] = KEY_RESERVED, // system select + [ 0x0a ] = KEY_RESERVED, /* 1/2/3 digits (japan: 10) */ + [ 0x0e ] = KEY_RESERVED, /* P.P. (personal preference) */ + [ 0x14 ] = KEY_RESERVED, /* colour saturation + */ + [ 0x15 ] = KEY_RESERVED, /* colour saturation - */ + [ 0x16 ] = KEY_RESERVED, /* bass + */ + [ 0x17 ] = KEY_RESERVED, /* bass - */ + [ 0x18 ] = KEY_RESERVED, /* treble + */ + [ 0x19 ] = KEY_RESERVED, /* treble - */ + [ 0x1a ] = KEY_RESERVED, /* balance right */ + [ 0x1b ] = KEY_RESERVED, /* balance left */ + [ 0x1c ] = KEY_RESERVED, /* contrast + */ + [ 0x1d ] = KEY_RESERVED, /* contrast - */ + [ 0x1f ] = KEY_RESERVED, /* tint/hue + */ + [ 0x24 ] = KEY_RESERVED, /* spacial stereo on/off */ + [ 0x25 ] = KEY_RESERVED, /* mono / stereo (USA) */ + [ 0x27 ] = KEY_RESERVED, /* tint / hue - */ + [ 0x28 ] = KEY_RESERVED, /* RF switch/PIP select */ + [ 0x29 ] = KEY_RESERVED, /* vote */ + [ 0x2a ] = KEY_RESERVED, /* timed page/channel clck */ + [ 0x2b ] = KEY_RESERVED, /* increment (USA) */ + [ 0x2c ] = KEY_RESERVED, /* decrement (USA) */ + [ 0x2d ] = KEY_RESERVED, /* */ + [ 0x2f ] = KEY_RESERVED, /* PIP shift */ + [ 0x31 ] = KEY_RESERVED, /* erase */ + [ 0x34 ] = KEY_RESERVED, /* wind */ + [ 0x38 ] = KEY_RESERVED, /* external 1 */ + [ 0x39 ] = KEY_RESERVED, /* external 2 */ + [ 0x3a ] = KEY_RESERVED, /* PIP display mode */ + [ 0x3b ] = KEY_RESERVED, /* view data mode / advance */ + [ 0x3e ] = KEY_RESERVED, /* crispener on/off */ + [ 0x3f ] = KEY_RESERVED, /* system select */ #endif }; -- cgit v1.2.3 From 69e2a0c79f10cbafd694fdc7901ea3f1a98848bf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Aug 2009 09:31:30 -0300 Subject: CodingStyle: Use [0x0f] instead of [ 0x0f ] From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 3070 +++++++++++++++---------------- 1 file changed, 1535 insertions(+), 1535 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 471df71a3..cf9950bf3 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -27,7 +27,7 @@ /* empty keytable, can be used as placeholder for not-yet created keytables */ IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { - [ 0x2a ] = KEY_COFFEE, + [0x2a] = KEY_COFFEE, }; EXPORT_SYMBOL_GPL(ir_codes_empty); @@ -35,71 +35,71 @@ EXPORT_SYMBOL_GPL(ir_codes_empty); /* Michal Majchrowicz */ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { /* numeric */ - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x5c ] = KEY_POWER, /* power */ - [ 0x20 ] = KEY_F, /* full screen */ - [ 0x0f ] = KEY_BACKSPACE, /* recall */ - [ 0x1b ] = KEY_ENTER, /* mute */ - [ 0x41 ] = KEY_RECORD, /* record */ - [ 0x43 ] = KEY_STOP, /* stop */ - [ 0x16 ] = KEY_S, - [ 0x1a ] = KEY_Q, /* off */ - [ 0x2e ] = KEY_RED, - [ 0x1f ] = KEY_DOWN, /* channel - */ - [ 0x1c ] = KEY_UP, /* channel + */ - [ 0x10 ] = KEY_LEFT, /* volume - */ - [ 0x1e ] = KEY_RIGHT, /* volume + */ - [ 0x14 ] = KEY_F1, + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x5c] = KEY_POWER, /* power */ + [0x20] = KEY_F, /* full screen */ + [0x0f] = KEY_BACKSPACE, /* recall */ + [0x1b] = KEY_ENTER, /* mute */ + [0x41] = KEY_RECORD, /* record */ + [0x43] = KEY_STOP, /* stop */ + [0x16] = KEY_S, + [0x1a] = KEY_Q, /* off */ + [0x2e] = KEY_RED, + [0x1f] = KEY_DOWN, /* channel - */ + [0x1c] = KEY_UP, /* channel + */ + [0x10] = KEY_LEFT, /* volume - */ + [0x1e] = KEY_RIGHT, /* volume + */ + [0x14] = KEY_F1, }; EXPORT_SYMBOL_GPL(ir_codes_proteus_2309); /* Matt Jesson >' */ - [ 0x3a ] = KEY_RECORD, /* 'capture' */ - [ 0x0a ] = KEY_MUTE, /* 'mute' */ - [ 0x2c ] = KEY_RECORD, /* 'record' */ - [ 0x1c ] = KEY_PAUSE, /* 'pause' */ - [ 0x3c ] = KEY_STOP, /* 'stop' */ - [ 0x0c ] = KEY_PLAY, /* 'play' */ - [ 0x2e ] = KEY_RED, /* 'red' */ - [ 0x01 ] = KEY_BLUE, /* 'blue' / 'cancel' */ - [ 0x0e ] = KEY_YELLOW, /* 'yellow' / 'ok' */ - [ 0x21 ] = KEY_GREEN, /* 'green' */ - [ 0x11 ] = KEY_CHANNELDOWN, /* 'channel -' */ - [ 0x31 ] = KEY_CHANNELUP, /* 'channel +' */ - [ 0x1e ] = KEY_VOLUMEDOWN, /* 'volume -' */ - [ 0x3e ] = KEY_VOLUMEUP, /* 'volume +' */ + [0x28] = KEY_0, /* '0' / 'enter' */ + [0x22] = KEY_1, /* '1' */ + [0x12] = KEY_2, /* '2' / 'up arrow' */ + [0x32] = KEY_3, /* '3' */ + [0x24] = KEY_4, /* '4' / 'left arrow' */ + [0x14] = KEY_5, /* '5' */ + [0x34] = KEY_6, /* '6' / 'right arrow' */ + [0x26] = KEY_7, /* '7' */ + [0x16] = KEY_8, /* '8' / 'down arrow' */ + [0x36] = KEY_9, /* '9' */ + + [0x20] = KEY_LIST, /* 'source' */ + [0x10] = KEY_TEXT, /* 'teletext' */ + [0x00] = KEY_POWER, /* 'power' */ + [0x04] = KEY_AUDIO, /* 'audio' */ + [0x06] = KEY_ZOOM, /* 'full screen' */ + [0x18] = KEY_VIDEO, /* 'display' */ + [0x38] = KEY_SEARCH, /* 'loop' */ + [0x08] = KEY_INFO, /* 'preview' */ + [0x2a] = KEY_REWIND, /* 'backward <<' */ + [0x1a] = KEY_FASTFORWARD, /* 'forward >>' */ + [0x3a] = KEY_RECORD, /* 'capture' */ + [0x0a] = KEY_MUTE, /* 'mute' */ + [0x2c] = KEY_RECORD, /* 'record' */ + [0x1c] = KEY_PAUSE, /* 'pause' */ + [0x3c] = KEY_STOP, /* 'stop' */ + [0x0c] = KEY_PLAY, /* 'play' */ + [0x2e] = KEY_RED, /* 'red' */ + [0x01] = KEY_BLUE, /* 'blue' / 'cancel' */ + [0x0e] = KEY_YELLOW, /* 'yellow' / 'ok' */ + [0x21] = KEY_GREEN, /* 'green' */ + [0x11] = KEY_CHANNELDOWN, /* 'channel -' */ + [0x31] = KEY_CHANNELUP, /* 'channel +' */ + [0x1e] = KEY_VOLUMEDOWN, /* 'volume -' */ + [0x3e] = KEY_VOLUMEUP, /* 'volume +' */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); @@ -216,42 +216,42 @@ EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus); /* Attila Kondoros */ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - [ 0x00 ] = KEY_0, - [ 0x17 ] = KEY_LAST, /* +100 */ - [ 0x0a ] = KEY_LIST, /* recall */ - - - [ 0x1c ] = KEY_TUNER, /* TV/FM */ - [ 0x15 ] = KEY_SEARCH, /* scan */ - [ 0x12 ] = KEY_POWER, /* power */ - [ 0x1f ] = KEY_VOLUMEDOWN, /* vol up */ - [ 0x1b ] = KEY_VOLUMEUP, /* vol down */ - [ 0x1e ] = KEY_CHANNELDOWN, /* chn up */ - [ 0x1a ] = KEY_CHANNELUP, /* chn down */ - - [ 0x11 ] = KEY_VIDEO, /* video */ - [ 0x0f ] = KEY_ZOOM, /* full screen */ - [ 0x13 ] = KEY_MUTE, /* mute/unmute */ - [ 0x10 ] = KEY_TEXT, /* min */ - - [ 0x0d ] = KEY_STOP, /* freeze */ - [ 0x0e ] = KEY_RECORD, /* record */ - [ 0x1d ] = KEY_PLAYPAUSE, /* stop */ - [ 0x19 ] = KEY_PLAY, /* play */ - - [ 0x16 ] = KEY_GOTO, /* osd */ - [ 0x14 ] = KEY_REFRESH, /* default */ - [ 0x0c ] = KEY_KPPLUS, /* fine tune >>>> */ - [ 0x18 ] = KEY_KPMINUS /* fine tune <<<< */ + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x00] = KEY_0, + [0x17] = KEY_LAST, /* +100 */ + [0x0a] = KEY_LIST, /* recall */ + + + [0x1c] = KEY_TUNER, /* TV/FM */ + [0x15] = KEY_SEARCH, /* scan */ + [0x12] = KEY_POWER, /* power */ + [0x1f] = KEY_VOLUMEDOWN, /* vol up */ + [0x1b] = KEY_VOLUMEUP, /* vol down */ + [0x1e] = KEY_CHANNELDOWN, /* chn up */ + [0x1a] = KEY_CHANNELUP, /* chn down */ + + [0x11] = KEY_VIDEO, /* video */ + [0x0f] = KEY_ZOOM, /* full screen */ + [0x13] = KEY_MUTE, /* mute/unmute */ + [0x10] = KEY_TEXT, /* min */ + + [0x0d] = KEY_STOP, /* freeze */ + [0x0e] = KEY_RECORD, /* record */ + [0x1d] = KEY_PLAYPAUSE, /* stop */ + [0x19] = KEY_PLAY, /* play */ + + [0x16] = KEY_GOTO, /* osd */ + [0x14] = KEY_REFRESH, /* default */ + [0x0c] = KEY_KPPLUS, /* fine tune >>>> */ + [0x18] = KEY_KPMINUS /* fine tune <<<< */ }; EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); @@ -260,9 +260,9 @@ EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { - [ 0x1e ] = KEY_POWER, /* power */ - [ 0x07 ] = KEY_MEDIA, /* source */ - [ 0x1c ] = KEY_SEARCH, /* scan */ + [0x1e] = KEY_POWER, /* power */ + [0x07] = KEY_MEDIA, /* source */ + [0x1c] = KEY_SEARCH, /* scan */ #if 0 /* FIXME: duplicate keycodes? */ @@ -275,11 +275,11 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { * 6384fb for "Tune <" and "<<<", * 638cfb for "Tune >" and ">>>", regardless of the mask. */ - [ 0x17 ] = KEY_BACK, /* fm scan << */ - [ 0x1f ] = KEY_FORWARD, /* fm scan >> */ + [0x17] = KEY_BACK, /* fm scan << */ + [0x1f] = KEY_FORWARD, /* fm scan >> */ - [ 0x04 ] = KEY_LEFT, /* fm tuning < */ - [ 0x0c ] = KEY_RIGHT, /* fm tuning > */ + [0x04] = KEY_LEFT, /* fm tuning < */ + [0x0c] = KEY_RIGHT, /* fm tuning > */ /* * For now, these four keys are disabled. Pressing them will generate @@ -287,41 +287,41 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { */ #endif - [ 0x03 ] = KEY_TUNER, /* TV/FM */ - - [ 0x00 ] = KEY_RECORD, - [ 0x08 ] = KEY_STOP, - [ 0x11 ] = KEY_PLAY, - - [ 0x1a ] = KEY_PLAYPAUSE, /* freeze */ - [ 0x19 ] = KEY_ZOOM, /* zoom */ - [ 0x0f ] = KEY_TEXT, /* min */ - - [ 0x01 ] = KEY_1, - [ 0x0b ] = KEY_2, - [ 0x1b ] = KEY_3, - [ 0x05 ] = KEY_4, - [ 0x09 ] = KEY_5, - [ 0x15 ] = KEY_6, - [ 0x06 ] = KEY_7, - [ 0x0a ] = KEY_8, - [ 0x12 ] = KEY_9, - [ 0x02 ] = KEY_0, - [ 0x10 ] = KEY_LAST, /* +100 */ - [ 0x13 ] = KEY_LIST, /* recall */ - - [ 0x1f ] = KEY_CHANNELUP, /* chn down */ - [ 0x17 ] = KEY_CHANNELDOWN, /* chn up */ - [ 0x16 ] = KEY_VOLUMEUP, /* vol down */ - [ 0x14 ] = KEY_VOLUMEDOWN, /* vol up */ - - [ 0x04 ] = KEY_KPMINUS, /* <<< */ - [ 0x0e ] = KEY_SETUP, /* function */ - [ 0x0c ] = KEY_KPPLUS, /* >>> */ - - [ 0x0d ] = KEY_GOTO, /* mts */ - [ 0x1d ] = KEY_REFRESH, /* reset */ - [ 0x18 ] = KEY_MUTE /* mute/unmute */ + [0x03] = KEY_TUNER, /* TV/FM */ + + [0x00] = KEY_RECORD, + [0x08] = KEY_STOP, + [0x11] = KEY_PLAY, + + [0x1a] = KEY_PLAYPAUSE, /* freeze */ + [0x19] = KEY_ZOOM, /* zoom */ + [0x0f] = KEY_TEXT, /* min */ + + [0x01] = KEY_1, + [0x0b] = KEY_2, + [0x1b] = KEY_3, + [0x05] = KEY_4, + [0x09] = KEY_5, + [0x15] = KEY_6, + [0x06] = KEY_7, + [0x0a] = KEY_8, + [0x12] = KEY_9, + [0x02] = KEY_0, + [0x10] = KEY_LAST, /* +100 */ + [0x13] = KEY_LIST, /* recall */ + + [0x1f] = KEY_CHANNELUP, /* chn down */ + [0x17] = KEY_CHANNELDOWN, /* chn up */ + [0x16] = KEY_VOLUMEUP, /* vol down */ + [0x14] = KEY_VOLUMEDOWN, /* vol up */ + + [0x04] = KEY_KPMINUS, /* <<< */ + [0x0e] = KEY_SETUP, /* function */ + [0x0c] = KEY_KPPLUS, /* >>> */ + + [0x0d] = KEY_GOTO, /* mts */ + [0x1d] = KEY_REFRESH, /* reset */ + [0x18] = KEY_MUTE /* mute/unmute */ }; EXPORT_SYMBOL_GPL(ir_codes_pixelview); @@ -372,102 +372,102 @@ IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_pixelview_new); IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - [ 0x0a ] = KEY_TV, - [ 0x0b ] = KEY_AUX, - [ 0x0c ] = KEY_DVD, - [ 0x0d ] = KEY_POWER, - [ 0x0e ] = KEY_MHP, /* labelled 'Picture' */ - [ 0x0f ] = KEY_AUDIO, - [ 0x10 ] = KEY_INFO, - [ 0x11 ] = KEY_F13, /* 16:9 */ - [ 0x12 ] = KEY_F14, /* 14:9 */ - [ 0x13 ] = KEY_EPG, - [ 0x14 ] = KEY_EXIT, - [ 0x15 ] = KEY_MENU, - [ 0x16 ] = KEY_UP, - [ 0x17 ] = KEY_DOWN, - [ 0x18 ] = KEY_LEFT, - [ 0x19 ] = KEY_RIGHT, - [ 0x1a ] = KEY_ENTER, - [ 0x1b ] = KEY_CHANNELUP, - [ 0x1c ] = KEY_CHANNELDOWN, - [ 0x1d ] = KEY_VOLUMEUP, - [ 0x1e ] = KEY_VOLUMEDOWN, - [ 0x1f ] = KEY_RED, - [ 0x20 ] = KEY_GREEN, - [ 0x21 ] = KEY_YELLOW, - [ 0x22 ] = KEY_BLUE, - [ 0x23 ] = KEY_SUBTITLE, - [ 0x24 ] = KEY_F15, /* AD */ - [ 0x25 ] = KEY_TEXT, - [ 0x26 ] = KEY_MUTE, - [ 0x27 ] = KEY_REWIND, - [ 0x28 ] = KEY_STOP, - [ 0x29 ] = KEY_PLAY, - [ 0x2a ] = KEY_FASTFORWARD, - [ 0x2b ] = KEY_F16, /* chapter */ - [ 0x2c ] = KEY_PAUSE, - [ 0x2d ] = KEY_PLAY, - [ 0x2e ] = KEY_RECORD, - [ 0x2f ] = KEY_F17, /* picture in picture */ - [ 0x30 ] = KEY_KPPLUS, /* zoom in */ - [ 0x31 ] = KEY_KPMINUS, /* zoom out */ - [ 0x32 ] = KEY_F18, /* capture */ - [ 0x33 ] = KEY_F19, /* web */ - [ 0x34 ] = KEY_EMAIL, - [ 0x35 ] = KEY_PHONE, - [ 0x36 ] = KEY_PC + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x0a] = KEY_TV, + [0x0b] = KEY_AUX, + [0x0c] = KEY_DVD, + [0x0d] = KEY_POWER, + [0x0e] = KEY_MHP, /* labelled 'Picture' */ + [0x0f] = KEY_AUDIO, + [0x10] = KEY_INFO, + [0x11] = KEY_F13, /* 16:9 */ + [0x12] = KEY_F14, /* 14:9 */ + [0x13] = KEY_EPG, + [0x14] = KEY_EXIT, + [0x15] = KEY_MENU, + [0x16] = KEY_UP, + [0x17] = KEY_DOWN, + [0x18] = KEY_LEFT, + [0x19] = KEY_RIGHT, + [0x1a] = KEY_ENTER, + [0x1b] = KEY_CHANNELUP, + [0x1c] = KEY_CHANNELDOWN, + [0x1d] = KEY_VOLUMEUP, + [0x1e] = KEY_VOLUMEDOWN, + [0x1f] = KEY_RED, + [0x20] = KEY_GREEN, + [0x21] = KEY_YELLOW, + [0x22] = KEY_BLUE, + [0x23] = KEY_SUBTITLE, + [0x24] = KEY_F15, /* AD */ + [0x25] = KEY_TEXT, + [0x26] = KEY_MUTE, + [0x27] = KEY_REWIND, + [0x28] = KEY_STOP, + [0x29] = KEY_PLAY, + [0x2a] = KEY_FASTFORWARD, + [0x2b] = KEY_F16, /* chapter */ + [0x2c] = KEY_PAUSE, + [0x2d] = KEY_PLAY, + [0x2e] = KEY_RECORD, + [0x2f] = KEY_F17, /* picture in picture */ + [0x30] = KEY_KPPLUS, /* zoom in */ + [0x31] = KEY_KPMINUS, /* zoom out */ + [0x32] = KEY_F18, /* capture */ + [0x33] = KEY_F19, /* web */ + [0x34] = KEY_EMAIL, + [0x35] = KEY_PHONE, + [0x36] = KEY_PC }; EXPORT_SYMBOL_GPL(ir_codes_nebula); /* DigitalNow DNTV Live DVB-T Remote */ IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_ESC, /* 'go up a level?' */ + [0x00] = KEY_ESC, /* 'go up a level?' */ /* Keys 0 to 9 */ - [ 0x0a ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0b ] = KEY_TUNER, /* tv/fm */ - [ 0x0c ] = KEY_SEARCH, /* scan */ - [ 0x0d ] = KEY_STOP, - [ 0x0e ] = KEY_PAUSE, - [ 0x0f ] = KEY_LIST, /* source */ - - [ 0x10 ] = KEY_MUTE, - [ 0x11 ] = KEY_REWIND, /* backward << */ - [ 0x12 ] = KEY_POWER, - [ 0x13 ] = KEY_S, /* snap */ - [ 0x14 ] = KEY_AUDIO, /* stereo */ - [ 0x15 ] = KEY_CLEAR, /* reset */ - [ 0x16 ] = KEY_PLAY, - [ 0x17 ] = KEY_ENTER, - [ 0x18 ] = KEY_ZOOM, /* full screen */ - [ 0x19 ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x1a ] = KEY_CHANNELUP, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1c ] = KEY_INFO, /* preview */ - [ 0x1d ] = KEY_RECORD, /* record */ - [ 0x1e ] = KEY_CHANNELDOWN, - [ 0x1f ] = KEY_VOLUMEDOWN, + [0x0a] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0b] = KEY_TUNER, /* tv/fm */ + [0x0c] = KEY_SEARCH, /* scan */ + [0x0d] = KEY_STOP, + [0x0e] = KEY_PAUSE, + [0x0f] = KEY_LIST, /* source */ + + [0x10] = KEY_MUTE, + [0x11] = KEY_REWIND, /* backward << */ + [0x12] = KEY_POWER, + [0x13] = KEY_S, /* snap */ + [0x14] = KEY_AUDIO, /* stereo */ + [0x15] = KEY_CLEAR, /* reset */ + [0x16] = KEY_PLAY, + [0x17] = KEY_ENTER, + [0x18] = KEY_ZOOM, /* full screen */ + [0x19] = KEY_FASTFORWARD, /* forward >> */ + [0x1a] = KEY_CHANNELUP, + [0x1b] = KEY_VOLUMEUP, + [0x1c] = KEY_INFO, /* preview */ + [0x1d] = KEY_RECORD, /* record */ + [0x1e] = KEY_CHANNELDOWN, + [0x1f] = KEY_VOLUMEDOWN, }; EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t); @@ -476,51 +476,51 @@ EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t); /* IO-DATA BCTV7E Remote */ IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { - [ 0x40 ] = KEY_TV, - [ 0x20 ] = KEY_RADIO, /* FM */ - [ 0x60 ] = KEY_EPG, - [ 0x00 ] = KEY_POWER, + [0x40] = KEY_TV, + [0x20] = KEY_RADIO, /* FM */ + [0x60] = KEY_EPG, + [0x00] = KEY_POWER, /* Keys 0 to 9 */ - [ 0x44 ] = KEY_0, /* 10 */ - [ 0x50 ] = KEY_1, - [ 0x30 ] = KEY_2, - [ 0x70 ] = KEY_3, - [ 0x48 ] = KEY_4, - [ 0x28 ] = KEY_5, - [ 0x68 ] = KEY_6, - [ 0x58 ] = KEY_7, - [ 0x38 ] = KEY_8, - [ 0x78 ] = KEY_9, - - [ 0x10 ] = KEY_L, /* Live */ - [ 0x08 ] = KEY_T, /* Time Shift */ - - [ 0x18 ] = KEY_PLAYPAUSE, /* Play */ - - [ 0x24 ] = KEY_ENTER, /* 11 */ - [ 0x64 ] = KEY_ESC, /* 12 */ - [ 0x04 ] = KEY_M, /* Multi */ - - [ 0x54 ] = KEY_VIDEO, - [ 0x34 ] = KEY_CHANNELUP, - [ 0x74 ] = KEY_VOLUMEUP, - [ 0x14 ] = KEY_MUTE, - - [ 0x4c ] = KEY_S, /* SVIDEO */ - [ 0x2c ] = KEY_CHANNELDOWN, - [ 0x6c ] = KEY_VOLUMEDOWN, - [ 0x0c ] = KEY_ZOOM, - - [ 0x5c ] = KEY_PAUSE, - [ 0x3c ] = KEY_C, /* || (red) */ - [ 0x7c ] = KEY_RECORD, /* recording */ - [ 0x1c ] = KEY_STOP, - - [ 0x41 ] = KEY_REWIND, /* backward << */ - [ 0x21 ] = KEY_PLAY, - [ 0x61 ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x01 ] = KEY_NEXT, /* skip >| */ + [0x44] = KEY_0, /* 10 */ + [0x50] = KEY_1, + [0x30] = KEY_2, + [0x70] = KEY_3, + [0x48] = KEY_4, + [0x28] = KEY_5, + [0x68] = KEY_6, + [0x58] = KEY_7, + [0x38] = KEY_8, + [0x78] = KEY_9, + + [0x10] = KEY_L, /* Live */ + [0x08] = KEY_T, /* Time Shift */ + + [0x18] = KEY_PLAYPAUSE, /* Play */ + + [0x24] = KEY_ENTER, /* 11 */ + [0x64] = KEY_ESC, /* 12 */ + [0x04] = KEY_M, /* Multi */ + + [0x54] = KEY_VIDEO, + [0x34] = KEY_CHANNELUP, + [0x74] = KEY_VOLUMEUP, + [0x14] = KEY_MUTE, + + [0x4c] = KEY_S, /* SVIDEO */ + [0x2c] = KEY_CHANNELDOWN, + [0x6c] = KEY_VOLUMEDOWN, + [0x0c] = KEY_ZOOM, + + [0x5c] = KEY_PAUSE, + [0x3c] = KEY_C, /* || (red) */ + [0x7c] = KEY_RECORD, /* recording */ + [0x1c] = KEY_STOP, + + [0x41] = KEY_REWIND, /* backward << */ + [0x21] = KEY_PLAY, + [0x61] = KEY_FASTFORWARD, /* forward >> */ + [0x01] = KEY_NEXT, /* skip >| */ }; EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e); @@ -530,51 +530,51 @@ EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e); /* ADS Tech Instant TV DVB-T PCI Remote */ IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x4d ] = KEY_0, - [ 0x57 ] = KEY_1, - [ 0x4f ] = KEY_2, - [ 0x53 ] = KEY_3, - [ 0x56 ] = KEY_4, - [ 0x4e ] = KEY_5, - [ 0x5e ] = KEY_6, - [ 0x54 ] = KEY_7, - [ 0x4c ] = KEY_8, - [ 0x5c ] = KEY_9, - - [ 0x5b ] = KEY_POWER, - [ 0x5f ] = KEY_MUTE, - [ 0x55 ] = KEY_GOTO, - [ 0x5d ] = KEY_SEARCH, - [ 0x17 ] = KEY_EPG, /* Guide */ - [ 0x1f ] = KEY_MENU, - [ 0x0f ] = KEY_UP, - [ 0x46 ] = KEY_DOWN, - [ 0x16 ] = KEY_LEFT, - [ 0x1e ] = KEY_RIGHT, - [ 0x0e ] = KEY_SELECT, /* Enter */ - [ 0x5a ] = KEY_INFO, - [ 0x52 ] = KEY_EXIT, - [ 0x59 ] = KEY_PREVIOUS, - [ 0x51 ] = KEY_NEXT, - [ 0x58 ] = KEY_REWIND, - [ 0x50 ] = KEY_FORWARD, - [ 0x44 ] = KEY_PLAYPAUSE, - [ 0x07 ] = KEY_STOP, - [ 0x1b ] = KEY_RECORD, - [ 0x13 ] = KEY_TUNER, /* Live */ - [ 0x0a ] = KEY_A, - [ 0x12 ] = KEY_B, - [ 0x03 ] = KEY_PROG1, /* 1 */ - [ 0x01 ] = KEY_PROG2, /* 2 */ - [ 0x00 ] = KEY_PROG3, /* 3 */ - [ 0x06 ] = KEY_DVD, - [ 0x48 ] = KEY_AUX, /* Photo */ - [ 0x40 ] = KEY_VIDEO, - [ 0x19 ] = KEY_AUDIO, /* Music */ - [ 0x0b ] = KEY_CHANNELUP, - [ 0x08 ] = KEY_CHANNELDOWN, - [ 0x15 ] = KEY_VOLUMEUP, - [ 0x1c ] = KEY_VOLUMEDOWN, + [0x4d] = KEY_0, + [0x57] = KEY_1, + [0x4f] = KEY_2, + [0x53] = KEY_3, + [0x56] = KEY_4, + [0x4e] = KEY_5, + [0x5e] = KEY_6, + [0x54] = KEY_7, + [0x4c] = KEY_8, + [0x5c] = KEY_9, + + [0x5b] = KEY_POWER, + [0x5f] = KEY_MUTE, + [0x55] = KEY_GOTO, + [0x5d] = KEY_SEARCH, + [0x17] = KEY_EPG, /* Guide */ + [0x1f] = KEY_MENU, + [0x0f] = KEY_UP, + [0x46] = KEY_DOWN, + [0x16] = KEY_LEFT, + [0x1e] = KEY_RIGHT, + [0x0e] = KEY_SELECT, /* Enter */ + [0x5a] = KEY_INFO, + [0x52] = KEY_EXIT, + [0x59] = KEY_PREVIOUS, + [0x51] = KEY_NEXT, + [0x58] = KEY_REWIND, + [0x50] = KEY_FORWARD, + [0x44] = KEY_PLAYPAUSE, + [0x07] = KEY_STOP, + [0x1b] = KEY_RECORD, + [0x13] = KEY_TUNER, /* Live */ + [0x0a] = KEY_A, + [0x12] = KEY_B, + [0x03] = KEY_PROG1, /* 1 */ + [0x01] = KEY_PROG2, /* 2 */ + [0x00] = KEY_PROG3, /* 3 */ + [0x06] = KEY_DVD, + [0x48] = KEY_AUX, /* Photo */ + [0x40] = KEY_VIDEO, + [0x19] = KEY_AUDIO, /* Music */ + [0x0b] = KEY_CHANNELUP, + [0x08] = KEY_CHANNELDOWN, + [0x15] = KEY_VOLUMEUP, + [0x1c] = KEY_VOLUMEDOWN, }; EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci); @@ -585,31 +585,31 @@ EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci); IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0c ] = KEY_MUTE, - [ 0x0f ] = KEY_SCREEN, /* Full Screen */ - [ 0x10 ] = KEY_F, /* Funtion */ - [ 0x11 ] = KEY_T, /* Time shift */ - [ 0x12 ] = KEY_POWER, - [ 0x13 ] = KEY_MEDIA, /* MTS */ - [ 0x14 ] = KEY_SLOW, - [ 0x16 ] = KEY_REWIND, /* backward << */ - [ 0x17 ] = KEY_ENTER, /* Return */ - [ 0x18 ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x1a ] = KEY_CHANNELUP, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1e ] = KEY_CHANNELDOWN, - [ 0x1f ] = KEY_VOLUMEDOWN, + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0c] = KEY_MUTE, + [0x0f] = KEY_SCREEN, /* Full Screen */ + [0x10] = KEY_F, /* Funtion */ + [0x11] = KEY_T, /* Time shift */ + [0x12] = KEY_POWER, + [0x13] = KEY_MEDIA, /* MTS */ + [0x14] = KEY_SLOW, + [0x16] = KEY_REWIND, /* backward << */ + [0x17] = KEY_ENTER, /* Return */ + [0x18] = KEY_FASTFORWARD, /* forward >> */ + [0x1a] = KEY_CHANNELUP, + [0x1b] = KEY_VOLUMEUP, + [0x1e] = KEY_CHANNELDOWN, + [0x1f] = KEY_VOLUMEDOWN, }; EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere); @@ -707,47 +707,47 @@ EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus); /* Cinergy 1400 DVB-T */ IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_POWER, - [ 0x02 ] = KEY_1, - [ 0x03 ] = KEY_2, - [ 0x04 ] = KEY_3, - [ 0x05 ] = KEY_4, - [ 0x06 ] = KEY_5, - [ 0x07 ] = KEY_6, - [ 0x08 ] = KEY_7, - [ 0x09 ] = KEY_8, - [ 0x0a ] = KEY_9, - [ 0x0c ] = KEY_0, - - [ 0x0b ] = KEY_VIDEO, - [ 0x0d ] = KEY_REFRESH, - [ 0x0e ] = KEY_SELECT, - [ 0x0f ] = KEY_EPG, - [ 0x10 ] = KEY_UP, - [ 0x11 ] = KEY_LEFT, - [ 0x12 ] = KEY_OK, - [ 0x13 ] = KEY_RIGHT, - [ 0x14 ] = KEY_DOWN, - [ 0x15 ] = KEY_TEXT, - [ 0x16 ] = KEY_INFO, - - [ 0x17 ] = KEY_RED, - [ 0x18 ] = KEY_GREEN, - [ 0x19 ] = KEY_YELLOW, - [ 0x1a ] = KEY_BLUE, - - [ 0x1b ] = KEY_CHANNELUP, - [ 0x1c ] = KEY_VOLUMEUP, - [ 0x1d ] = KEY_MUTE, - [ 0x1e ] = KEY_VOLUMEDOWN, - [ 0x1f ] = KEY_CHANNELDOWN, - - [ 0x40 ] = KEY_PAUSE, - [ 0x4c ] = KEY_PLAY, - [ 0x58 ] = KEY_RECORD, - [ 0x54 ] = KEY_PREVIOUS, - [ 0x48 ] = KEY_STOP, - [ 0x5c ] = KEY_NEXT, + [0x01] = KEY_POWER, + [0x02] = KEY_1, + [0x03] = KEY_2, + [0x04] = KEY_3, + [0x05] = KEY_4, + [0x06] = KEY_5, + [0x07] = KEY_6, + [0x08] = KEY_7, + [0x09] = KEY_8, + [0x0a] = KEY_9, + [0x0c] = KEY_0, + + [0x0b] = KEY_VIDEO, + [0x0d] = KEY_REFRESH, + [0x0e] = KEY_SELECT, + [0x0f] = KEY_EPG, + [0x10] = KEY_UP, + [0x11] = KEY_LEFT, + [0x12] = KEY_OK, + [0x13] = KEY_RIGHT, + [0x14] = KEY_DOWN, + [0x15] = KEY_TEXT, + [0x16] = KEY_INFO, + + [0x17] = KEY_RED, + [0x18] = KEY_GREEN, + [0x19] = KEY_YELLOW, + [0x1a] = KEY_BLUE, + + [0x1b] = KEY_CHANNELUP, + [0x1c] = KEY_VOLUMEUP, + [0x1d] = KEY_MUTE, + [0x1e] = KEY_VOLUMEDOWN, + [0x1f] = KEY_CHANNELDOWN, + + [0x40] = KEY_PAUSE, + [0x4c] = KEY_PLAY, + [0x58] = KEY_RECORD, + [0x54] = KEY_PREVIOUS, + [0x48] = KEY_STOP, + [0x5c] = KEY_NEXT, }; EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400); @@ -756,48 +756,48 @@ EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400); /* AVERTV STUDIO 303 Remote */ IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = { - [ 0x2a ] = KEY_1, - [ 0x32 ] = KEY_2, - [ 0x3a ] = KEY_3, - [ 0x4a ] = KEY_4, - [ 0x52 ] = KEY_5, - [ 0x5a ] = KEY_6, - [ 0x6a ] = KEY_7, - [ 0x72 ] = KEY_8, - [ 0x7a ] = KEY_9, - [ 0x0e ] = KEY_0, - - [ 0x02 ] = KEY_POWER, - [ 0x22 ] = KEY_VIDEO, - [ 0x42 ] = KEY_AUDIO, - [ 0x62 ] = KEY_ZOOM, - [ 0x0a ] = KEY_TV, - [ 0x12 ] = KEY_CD, - [ 0x1a ] = KEY_TEXT, - - [ 0x16 ] = KEY_SUBTITLE, - [ 0x1e ] = KEY_REWIND, - [ 0x06 ] = KEY_PRINT, - - [ 0x2e ] = KEY_SEARCH, - [ 0x36 ] = KEY_SLEEP, - [ 0x3e ] = KEY_SHUFFLE, - [ 0x26 ] = KEY_MUTE, - - [ 0x4e ] = KEY_RECORD, - [ 0x56 ] = KEY_PAUSE, - [ 0x5e ] = KEY_STOP, - [ 0x46 ] = KEY_PLAY, - - [ 0x6e ] = KEY_RED, - [ 0x0b ] = KEY_GREEN, - [ 0x66 ] = KEY_YELLOW, - [ 0x03 ] = KEY_BLUE, - - [ 0x76 ] = KEY_LEFT, - [ 0x7e ] = KEY_RIGHT, - [ 0x13 ] = KEY_DOWN, - [ 0x1b ] = KEY_UP, + [0x2a] = KEY_1, + [0x32] = KEY_2, + [0x3a] = KEY_3, + [0x4a] = KEY_4, + [0x52] = KEY_5, + [0x5a] = KEY_6, + [0x6a] = KEY_7, + [0x72] = KEY_8, + [0x7a] = KEY_9, + [0x0e] = KEY_0, + + [0x02] = KEY_POWER, + [0x22] = KEY_VIDEO, + [0x42] = KEY_AUDIO, + [0x62] = KEY_ZOOM, + [0x0a] = KEY_TV, + [0x12] = KEY_CD, + [0x1a] = KEY_TEXT, + + [0x16] = KEY_SUBTITLE, + [0x1e] = KEY_REWIND, + [0x06] = KEY_PRINT, + + [0x2e] = KEY_SEARCH, + [0x36] = KEY_SLEEP, + [0x3e] = KEY_SHUFFLE, + [0x26] = KEY_MUTE, + + [0x4e] = KEY_RECORD, + [0x56] = KEY_PAUSE, + [0x5e] = KEY_STOP, + [0x46] = KEY_PLAY, + + [0x6e] = KEY_RED, + [0x0b] = KEY_GREEN, + [0x66] = KEY_YELLOW, + [0x03] = KEY_BLUE, + + [0x76] = KEY_LEFT, + [0x7e] = KEY_RIGHT, + [0x13] = KEY_DOWN, + [0x1b] = KEY_UP, }; EXPORT_SYMBOL_GPL(ir_codes_avertv_303); @@ -806,263 +806,263 @@ EXPORT_SYMBOL_GPL(ir_codes_avertv_303); /* DigitalNow DNTV Live! DVB-T Pro Remote */ IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { - [ 0x16 ] = KEY_POWER, - [ 0x5b ] = KEY_HOME, - - [ 0x55 ] = KEY_TV, /* live tv */ - [ 0x58 ] = KEY_TUNER, /* digital Radio */ - [ 0x5a ] = KEY_RADIO, /* FM radio */ - [ 0x59 ] = KEY_DVD, /* dvd menu */ - [ 0x03 ] = KEY_1, - [ 0x01 ] = KEY_2, - [ 0x06 ] = KEY_3, - [ 0x09 ] = KEY_4, - [ 0x1d ] = KEY_5, - [ 0x1f ] = KEY_6, - [ 0x0d ] = KEY_7, - [ 0x19 ] = KEY_8, - [ 0x1b ] = KEY_9, - [ 0x0c ] = KEY_CANCEL, - [ 0x15 ] = KEY_0, - [ 0x4a ] = KEY_CLEAR, - [ 0x13 ] = KEY_BACK, - [ 0x00 ] = KEY_TAB, - [ 0x4b ] = KEY_UP, - [ 0x4e ] = KEY_LEFT, - [ 0x4f ] = KEY_OK, - [ 0x52 ] = KEY_RIGHT, - [ 0x51 ] = KEY_DOWN, - [ 0x1e ] = KEY_VOLUMEUP, - [ 0x0a ] = KEY_VOLUMEDOWN, - [ 0x02 ] = KEY_CHANNELDOWN, - [ 0x05 ] = KEY_CHANNELUP, - [ 0x11 ] = KEY_RECORD, - [ 0x14 ] = KEY_PLAY, - [ 0x4c ] = KEY_PAUSE, - [ 0x1a ] = KEY_STOP, - [ 0x40 ] = KEY_REWIND, - [ 0x12 ] = KEY_FASTFORWARD, - [ 0x41 ] = KEY_PREVIOUSSONG, /* replay |< */ - [ 0x42 ] = KEY_NEXTSONG, /* skip >| */ - [ 0x54 ] = KEY_CAMERA, /* capture */ - [ 0x50 ] = KEY_LANGUAGE, /* sap */ - [ 0x47 ] = KEY_TV2, /* pip */ - [ 0x4d ] = KEY_SCREEN, - [ 0x43 ] = KEY_SUBTITLE, - [ 0x10 ] = KEY_MUTE, - [ 0x49 ] = KEY_AUDIO, /* l/r */ - [ 0x07 ] = KEY_SLEEP, - [ 0x08 ] = KEY_VIDEO, /* a/v */ - [ 0x0e ] = KEY_PREVIOUS, /* recall */ - [ 0x45 ] = KEY_ZOOM, /* zoom + */ - [ 0x46 ] = KEY_ANGLE, /* zoom - */ - [ 0x56 ] = KEY_RED, - [ 0x57 ] = KEY_GREEN, - [ 0x5c ] = KEY_YELLOW, - [ 0x5d ] = KEY_BLUE, + [0x16] = KEY_POWER, + [0x5b] = KEY_HOME, + + [0x55] = KEY_TV, /* live tv */ + [0x58] = KEY_TUNER, /* digital Radio */ + [0x5a] = KEY_RADIO, /* FM radio */ + [0x59] = KEY_DVD, /* dvd menu */ + [0x03] = KEY_1, + [0x01] = KEY_2, + [0x06] = KEY_3, + [0x09] = KEY_4, + [0x1d] = KEY_5, + [0x1f] = KEY_6, + [0x0d] = KEY_7, + [0x19] = KEY_8, + [0x1b] = KEY_9, + [0x0c] = KEY_CANCEL, + [0x15] = KEY_0, + [0x4a] = KEY_CLEAR, + [0x13] = KEY_BACK, + [0x00] = KEY_TAB, + [0x4b] = KEY_UP, + [0x4e] = KEY_LEFT, + [0x4f] = KEY_OK, + [0x52] = KEY_RIGHT, + [0x51] = KEY_DOWN, + [0x1e] = KEY_VOLUMEUP, + [0x0a] = KEY_VOLUMEDOWN, + [0x02] = KEY_CHANNELDOWN, + [0x05] = KEY_CHANNELUP, + [0x11] = KEY_RECORD, + [0x14] = KEY_PLAY, + [0x4c] = KEY_PAUSE, + [0x1a] = KEY_STOP, + [0x40] = KEY_REWIND, + [0x12] = KEY_FASTFORWARD, + [0x41] = KEY_PREVIOUSSONG, /* replay |< */ + [0x42] = KEY_NEXTSONG, /* skip >| */ + [0x54] = KEY_CAMERA, /* capture */ + [0x50] = KEY_LANGUAGE, /* sap */ + [0x47] = KEY_TV2, /* pip */ + [0x4d] = KEY_SCREEN, + [0x43] = KEY_SUBTITLE, + [0x10] = KEY_MUTE, + [0x49] = KEY_AUDIO, /* l/r */ + [0x07] = KEY_SLEEP, + [0x08] = KEY_VIDEO, /* a/v */ + [0x0e] = KEY_PREVIOUS, /* recall */ + [0x45] = KEY_ZOOM, /* zoom + */ + [0x46] = KEY_ANGLE, /* zoom - */ + [0x56] = KEY_RED, + [0x57] = KEY_GREEN, + [0x5c] = KEY_YELLOW, + [0x5d] = KEY_BLUE, }; EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro); IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_CHANNEL, - [ 0x02 ] = KEY_SELECT, - [ 0x03 ] = KEY_MUTE, - [ 0x04 ] = KEY_POWER, - [ 0x05 ] = KEY_1, - [ 0x06 ] = KEY_2, - [ 0x07 ] = KEY_3, - [ 0x08 ] = KEY_CHANNELUP, - [ 0x09 ] = KEY_4, - [ 0x0a ] = KEY_5, - [ 0x0b ] = KEY_6, - [ 0x0c ] = KEY_CHANNELDOWN, - [ 0x0d ] = KEY_7, - [ 0x0e ] = KEY_8, - [ 0x0f ] = KEY_9, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_0, - [ 0x12 ] = KEY_MENU, - [ 0x13 ] = KEY_PRINT, - [ 0x14 ] = KEY_VOLUMEDOWN, - [ 0x16 ] = KEY_PAUSE, - [ 0x18 ] = KEY_RECORD, - [ 0x19 ] = KEY_REWIND, - [ 0x1a ] = KEY_PLAY, - [ 0x1b ] = KEY_FORWARD, - [ 0x1c ] = KEY_BACKSPACE, - [ 0x1e ] = KEY_STOP, - [ 0x40 ] = KEY_ZOOM, + [0x01] = KEY_CHANNEL, + [0x02] = KEY_SELECT, + [0x03] = KEY_MUTE, + [0x04] = KEY_POWER, + [0x05] = KEY_1, + [0x06] = KEY_2, + [0x07] = KEY_3, + [0x08] = KEY_CHANNELUP, + [0x09] = KEY_4, + [0x0a] = KEY_5, + [0x0b] = KEY_6, + [0x0c] = KEY_CHANNELDOWN, + [0x0d] = KEY_7, + [0x0e] = KEY_8, + [0x0f] = KEY_9, + [0x10] = KEY_VOLUMEUP, + [0x11] = KEY_0, + [0x12] = KEY_MENU, + [0x13] = KEY_PRINT, + [0x14] = KEY_VOLUMEDOWN, + [0x16] = KEY_PAUSE, + [0x18] = KEY_RECORD, + [0x19] = KEY_REWIND, + [0x1a] = KEY_PLAY, + [0x1b] = KEY_FORWARD, + [0x1c] = KEY_BACKSPACE, + [0x1e] = KEY_STOP, + [0x40] = KEY_ZOOM, }; EXPORT_SYMBOL_GPL(ir_codes_em_terratec); IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = { - [ 0x3a ] = KEY_0, - [ 0x31 ] = KEY_1, - [ 0x32 ] = KEY_2, - [ 0x33 ] = KEY_3, - [ 0x34 ] = KEY_4, - [ 0x35 ] = KEY_5, - [ 0x36 ] = KEY_6, - [ 0x37 ] = KEY_7, - [ 0x38 ] = KEY_8, - [ 0x39 ] = KEY_9, - - [ 0x2f ] = KEY_POWER, - - [ 0x2e ] = KEY_P, - [ 0x1f ] = KEY_L, - [ 0x2b ] = KEY_I, - - [ 0x2d ] = KEY_SCREEN, - [ 0x1e ] = KEY_ZOOM, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x0f ] = KEY_VOLUMEDOWN, - [ 0x17 ] = KEY_CHANNELUP, - [ 0x1c ] = KEY_CHANNELDOWN, - [ 0x25 ] = KEY_INFO, - - [ 0x3c ] = KEY_MUTE, - - [ 0x3d ] = KEY_LEFT, - [ 0x3b ] = KEY_RIGHT, - - [ 0x3f ] = KEY_UP, - [ 0x3e ] = KEY_DOWN, - [ 0x1a ] = KEY_ENTER, - - [ 0x1d ] = KEY_MENU, - [ 0x19 ] = KEY_AGAIN, - [ 0x16 ] = KEY_PREVIOUSSONG, - [ 0x13 ] = KEY_NEXTSONG, - [ 0x15 ] = KEY_PAUSE, - [ 0x0e ] = KEY_REWIND, - [ 0x0d ] = KEY_PLAY, - [ 0x0b ] = KEY_STOP, - [ 0x07 ] = KEY_FORWARD, - [ 0x27 ] = KEY_RECORD, - [ 0x26 ] = KEY_TUNER, - [ 0x29 ] = KEY_TEXT, - [ 0x2a ] = KEY_MEDIA, - [ 0x18 ] = KEY_EPG, + [0x3a] = KEY_0, + [0x31] = KEY_1, + [0x32] = KEY_2, + [0x33] = KEY_3, + [0x34] = KEY_4, + [0x35] = KEY_5, + [0x36] = KEY_6, + [0x37] = KEY_7, + [0x38] = KEY_8, + [0x39] = KEY_9, + + [0x2f] = KEY_POWER, + + [0x2e] = KEY_P, + [0x1f] = KEY_L, + [0x2b] = KEY_I, + + [0x2d] = KEY_SCREEN, + [0x1e] = KEY_ZOOM, + [0x1b] = KEY_VOLUMEUP, + [0x0f] = KEY_VOLUMEDOWN, + [0x17] = KEY_CHANNELUP, + [0x1c] = KEY_CHANNELDOWN, + [0x25] = KEY_INFO, + + [0x3c] = KEY_MUTE, + + [0x3d] = KEY_LEFT, + [0x3b] = KEY_RIGHT, + + [0x3f] = KEY_UP, + [0x3e] = KEY_DOWN, + [0x1a] = KEY_ENTER, + + [0x1d] = KEY_MENU, + [0x19] = KEY_AGAIN, + [0x16] = KEY_PREVIOUSSONG, + [0x13] = KEY_NEXTSONG, + [0x15] = KEY_PAUSE, + [0x0e] = KEY_REWIND, + [0x0d] = KEY_PLAY, + [0x0b] = KEY_STOP, + [0x07] = KEY_FORWARD, + [0x27] = KEY_RECORD, + [0x26] = KEY_TUNER, + [0x29] = KEY_TEXT, + [0x2a] = KEY_MEDIA, + [0x18] = KEY_EPG, }; EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey); IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { - [ 0x0f ] = KEY_0, - [ 0x03 ] = KEY_1, - [ 0x04 ] = KEY_2, - [ 0x05 ] = KEY_3, - [ 0x07 ] = KEY_4, - [ 0x08 ] = KEY_5, - [ 0x09 ] = KEY_6, - [ 0x0b ] = KEY_7, - [ 0x0c ] = KEY_8, - [ 0x0d ] = KEY_9, - - [ 0x0e ] = KEY_MODE, /* Air/Cable */ - [ 0x11 ] = KEY_VIDEO, /* Video */ - [ 0x15 ] = KEY_AUDIO, /* Audio */ - [ 0x00 ] = KEY_POWER, /* Power */ - [ 0x18 ] = KEY_TUNER, /* AV Source */ - [ 0x02 ] = KEY_ZOOM, /* Fullscreen */ - [ 0x1a ] = KEY_LANGUAGE, /* Stereo */ - [ 0x1b ] = KEY_MUTE, /* Mute */ - [ 0x14 ] = KEY_VOLUMEUP, /* Volume + */ - [ 0x17 ] = KEY_VOLUMEDOWN, /* Volume - */ - [ 0x12 ] = KEY_CHANNELUP, /* Channel + */ - [ 0x13 ] = KEY_CHANNELDOWN, /* Channel - */ - [ 0x06 ] = KEY_AGAIN, /* Recall */ - [ 0x10 ] = KEY_ENTER, /* Enter */ - - [ 0x19 ] = KEY_BACK, /* Rewind ( <<< ) */ - [ 0x1f ] = KEY_FORWARD, /* Forward ( >>> ) */ - [ 0x0a ] = KEY_ANGLE, /* (no label, may be used as the PAUSE button) */ + [0x0f] = KEY_0, + [0x03] = KEY_1, + [0x04] = KEY_2, + [0x05] = KEY_3, + [0x07] = KEY_4, + [0x08] = KEY_5, + [0x09] = KEY_6, + [0x0b] = KEY_7, + [0x0c] = KEY_8, + [0x0d] = KEY_9, + + [0x0e] = KEY_MODE, /* Air/Cable */ + [0x11] = KEY_VIDEO, /* Video */ + [0x15] = KEY_AUDIO, /* Audio */ + [0x00] = KEY_POWER, /* Power */ + [0x18] = KEY_TUNER, /* AV Source */ + [0x02] = KEY_ZOOM, /* Fullscreen */ + [0x1a] = KEY_LANGUAGE, /* Stereo */ + [0x1b] = KEY_MUTE, /* Mute */ + [0x14] = KEY_VOLUMEUP, /* Volume + */ + [0x17] = KEY_VOLUMEDOWN, /* Volume - */ + [0x12] = KEY_CHANNELUP, /* Channel + */ + [0x13] = KEY_CHANNELDOWN, /* Channel - */ + [0x06] = KEY_AGAIN, /* Recall */ + [0x10] = KEY_ENTER, /* Enter */ + + [0x19] = KEY_BACK, /* Rewind ( <<< ) */ + [0x1f] = KEY_FORWARD, /* Forward ( >>> ) */ + [0x0a] = KEY_ANGLE, /* (no label, may be used as the PAUSE button) */ }; EXPORT_SYMBOL_GPL(ir_codes_flyvideo); IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_ZOOM, /* Full Screen */ - [ 0x00 ] = KEY_POWER, /* Power */ - - [ 0x03 ] = KEY_1, - [ 0x04 ] = KEY_2, - [ 0x05 ] = KEY_3, - [ 0x07 ] = KEY_4, - [ 0x08 ] = KEY_5, - [ 0x09 ] = KEY_6, - [ 0x0b ] = KEY_7, - [ 0x0c ] = KEY_8, - [ 0x0d ] = KEY_9, - [ 0x06 ] = KEY_AGAIN, /* Recall */ - [ 0x0f ] = KEY_0, - [ 0x10 ] = KEY_MUTE, /* Mute */ - [ 0x02 ] = KEY_RADIO, /* TV/Radio */ - [ 0x1b ] = KEY_LANGUAGE, /* SAP (Second Audio Program) */ - - [ 0x14 ] = KEY_VOLUMEUP, /* VOL+ */ - [ 0x17 ] = KEY_VOLUMEDOWN, /* VOL- */ - [ 0x12 ] = KEY_CHANNELUP, /* CH+ */ - [ 0x13 ] = KEY_CHANNELDOWN, /* CH- */ - [ 0x1d ] = KEY_ENTER, /* Enter */ - - [ 0x1a ] = KEY_MODE, /* PIP */ - [ 0x18 ] = KEY_TUNER, /* Source */ - - [ 0x1e ] = KEY_RECORD, /* Record/Pause */ - [ 0x15 ] = KEY_ANGLE, /* Swap (no label on key) */ - [ 0x1c ] = KEY_PAUSE, /* Timeshift/Pause */ - [ 0x19 ] = KEY_BACK, /* Rewind << */ - [ 0x0a ] = KEY_PLAYPAUSE, /* Play/Pause */ - [ 0x1f ] = KEY_FORWARD, /* Forward >> */ - [ 0x16 ] = KEY_PREVIOUS, /* Back |<< */ - [ 0x11 ] = KEY_STOP, /* Stop */ - [ 0x0e ] = KEY_NEXT, /* End >>| */ + [0x01] = KEY_ZOOM, /* Full Screen */ + [0x00] = KEY_POWER, /* Power */ + + [0x03] = KEY_1, + [0x04] = KEY_2, + [0x05] = KEY_3, + [0x07] = KEY_4, + [0x08] = KEY_5, + [0x09] = KEY_6, + [0x0b] = KEY_7, + [0x0c] = KEY_8, + [0x0d] = KEY_9, + [0x06] = KEY_AGAIN, /* Recall */ + [0x0f] = KEY_0, + [0x10] = KEY_MUTE, /* Mute */ + [0x02] = KEY_RADIO, /* TV/Radio */ + [0x1b] = KEY_LANGUAGE, /* SAP (Second Audio Program) */ + + [0x14] = KEY_VOLUMEUP, /* VOL+ */ + [0x17] = KEY_VOLUMEDOWN, /* VOL- */ + [0x12] = KEY_CHANNELUP, /* CH+ */ + [0x13] = KEY_CHANNELDOWN, /* CH- */ + [0x1d] = KEY_ENTER, /* Enter */ + + [0x1a] = KEY_MODE, /* PIP */ + [0x18] = KEY_TUNER, /* Source */ + + [0x1e] = KEY_RECORD, /* Record/Pause */ + [0x15] = KEY_ANGLE, /* Swap (no label on key) */ + [0x1c] = KEY_PAUSE, /* Timeshift/Pause */ + [0x19] = KEY_BACK, /* Rewind << */ + [0x0a] = KEY_PLAYPAUSE, /* Play/Pause */ + [0x1f] = KEY_FORWARD, /* Forward >> */ + [0x16] = KEY_PREVIOUS, /* Back |<< */ + [0x11] = KEY_STOP, /* Stop */ + [0x0e] = KEY_NEXT, /* End >>| */ }; EXPORT_SYMBOL_GPL(ir_codes_flydvb); IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0a ] = KEY_POWER, - [ 0x0b ] = KEY_PROG1, /* app */ - [ 0x0c ] = KEY_ZOOM, /* zoom/fullscreen */ - [ 0x0d ] = KEY_CHANNELUP, /* channel */ - [ 0x0e ] = KEY_CHANNELDOWN, /* channel- */ - [ 0x0f ] = KEY_VOLUMEUP, - [ 0x10 ] = KEY_VOLUMEDOWN, - [ 0x11 ] = KEY_TUNER, /* AV */ - [ 0x12 ] = KEY_NUMLOCK, /* -/-- */ - [ 0x13 ] = KEY_AUDIO, /* audio */ - [ 0x14 ] = KEY_MUTE, - [ 0x15 ] = KEY_UP, - [ 0x16 ] = KEY_DOWN, - [ 0x17 ] = KEY_LEFT, - [ 0x18 ] = KEY_RIGHT, - [ 0x19 ] = BTN_LEFT, - [ 0x1a ] = BTN_RIGHT, - [ 0x1b ] = KEY_WWW, /* text */ - [ 0x1c ] = KEY_REWIND, - [ 0x1d ] = KEY_FORWARD, - [ 0x1e ] = KEY_RECORD, - [ 0x1f ] = KEY_PLAY, - [ 0x20 ] = KEY_PREVIOUSSONG, - [ 0x21 ] = KEY_NEXTSONG, - [ 0x22 ] = KEY_PAUSE, - [ 0x23 ] = KEY_STOP, + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0a] = KEY_POWER, + [0x0b] = KEY_PROG1, /* app */ + [0x0c] = KEY_ZOOM, /* zoom/fullscreen */ + [0x0d] = KEY_CHANNELUP, /* channel */ + [0x0e] = KEY_CHANNELDOWN, /* channel- */ + [0x0f] = KEY_VOLUMEUP, + [0x10] = KEY_VOLUMEDOWN, + [0x11] = KEY_TUNER, /* AV */ + [0x12] = KEY_NUMLOCK, /* -/-- */ + [0x13] = KEY_AUDIO, /* audio */ + [0x14] = KEY_MUTE, + [0x15] = KEY_UP, + [0x16] = KEY_DOWN, + [0x17] = KEY_LEFT, + [0x18] = KEY_RIGHT, + [0x19] = BTN_LEFT, + [0x1a] = BTN_RIGHT, + [0x1b] = KEY_WWW, /* text */ + [0x1c] = KEY_REWIND, + [0x1d] = KEY_FORWARD, + [0x1e] = KEY_RECORD, + [0x1f] = KEY_PLAY, + [0x20] = KEY_PREVIOUSSONG, + [0x21] = KEY_NEXTSONG, + [0x22] = KEY_PAUSE, + [0x23] = KEY_STOP, }; EXPORT_SYMBOL_GPL(ir_codes_cinergy); @@ -1070,165 +1070,165 @@ EXPORT_SYMBOL_GPL(ir_codes_cinergy); /* Alfons Geser * updates from Job D. R. Borges */ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { - [ 0x12 ] = KEY_POWER, - [ 0x01 ] = KEY_TV, /* DVR */ - [ 0x15 ] = KEY_DVD, /* DVD */ - [ 0x17 ] = KEY_AUDIO, /* music */ + [0x12] = KEY_POWER, + [0x01] = KEY_TV, /* DVR */ + [0x15] = KEY_DVD, /* DVD */ + [0x17] = KEY_AUDIO, /* music */ /* DVR mode / DVD mode / music mode */ - [ 0x1b ] = KEY_MUTE, /* mute */ - [ 0x02 ] = KEY_LANGUAGE, /* MTS/SAP / audio / autoseek */ - [ 0x1e ] = KEY_SUBTITLE, /* closed captioning / subtitle / seek */ - [ 0x16 ] = KEY_ZOOM, /* full screen */ - [ 0x1c ] = KEY_VIDEO, /* video source / eject / delall */ - [ 0x1d ] = KEY_RESTART, /* playback / angle / del */ - [ 0x2f ] = KEY_SEARCH, /* scan / menu / playlist */ - [ 0x30 ] = KEY_CHANNEL, /* CH surfing / bookmark / memo */ - - [ 0x31 ] = KEY_HELP, /* help */ - [ 0x32 ] = KEY_MODE, /* num/memo */ - [ 0x33 ] = KEY_ESC, /* cancel */ - - [ 0x0c ] = KEY_UP, /* up */ - [ 0x10 ] = KEY_DOWN, /* down */ - [ 0x08 ] = KEY_LEFT, /* left */ - [ 0x04 ] = KEY_RIGHT, /* right */ - [ 0x03 ] = KEY_SELECT, /* select */ - - [ 0x1f ] = KEY_REWIND, /* rewind */ - [ 0x20 ] = KEY_PLAYPAUSE, /* play/pause */ - [ 0x29 ] = KEY_FORWARD, /* forward */ - [ 0x14 ] = KEY_AGAIN, /* repeat */ - [ 0x2b ] = KEY_RECORD, /* recording */ - [ 0x2c ] = KEY_STOP, /* stop */ - [ 0x2d ] = KEY_PLAY, /* play */ - [ 0x2e ] = KEY_SHUFFLE, /* snapshot / shuffle */ - - [ 0x00 ] = KEY_0, - [ 0x05 ] = KEY_1, - [ 0x06 ] = KEY_2, - [ 0x07 ] = KEY_3, - [ 0x09 ] = KEY_4, - [ 0x0a ] = KEY_5, - [ 0x0b ] = KEY_6, - [ 0x0d ] = KEY_7, - [ 0x0e ] = KEY_8, - [ 0x0f ] = KEY_9, - - [ 0x2a ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x18 ] = KEY_CHANNELUP, /* CH.tracking up */ - [ 0x19 ] = KEY_CHANNELDOWN, /* CH.tracking down */ - - [ 0x13 ] = KEY_ENTER, /* enter */ - [ 0x21 ] = KEY_DOT, /* . (decimal dot) */ + [0x1b] = KEY_MUTE, /* mute */ + [0x02] = KEY_LANGUAGE, /* MTS/SAP / audio / autoseek */ + [0x1e] = KEY_SUBTITLE, /* closed captioning / subtitle / seek */ + [0x16] = KEY_ZOOM, /* full screen */ + [0x1c] = KEY_VIDEO, /* video source / eject / delall */ + [0x1d] = KEY_RESTART, /* playback / angle / del */ + [0x2f] = KEY_SEARCH, /* scan / menu / playlist */ + [0x30] = KEY_CHANNEL, /* CH surfing / bookmark / memo */ + + [0x31] = KEY_HELP, /* help */ + [0x32] = KEY_MODE, /* num/memo */ + [0x33] = KEY_ESC, /* cancel */ + + [0x0c] = KEY_UP, /* up */ + [0x10] = KEY_DOWN, /* down */ + [0x08] = KEY_LEFT, /* left */ + [0x04] = KEY_RIGHT, /* right */ + [0x03] = KEY_SELECT, /* select */ + + [0x1f] = KEY_REWIND, /* rewind */ + [0x20] = KEY_PLAYPAUSE, /* play/pause */ + [0x29] = KEY_FORWARD, /* forward */ + [0x14] = KEY_AGAIN, /* repeat */ + [0x2b] = KEY_RECORD, /* recording */ + [0x2c] = KEY_STOP, /* stop */ + [0x2d] = KEY_PLAY, /* play */ + [0x2e] = KEY_SHUFFLE, /* snapshot / shuffle */ + + [0x00] = KEY_0, + [0x05] = KEY_1, + [0x06] = KEY_2, + [0x07] = KEY_3, + [0x09] = KEY_4, + [0x0a] = KEY_5, + [0x0b] = KEY_6, + [0x0d] = KEY_7, + [0x0e] = KEY_8, + [0x0f] = KEY_9, + + [0x2a] = KEY_VOLUMEUP, + [0x11] = KEY_VOLUMEDOWN, + [0x18] = KEY_CHANNELUP, /* CH.tracking up */ + [0x19] = KEY_CHANNELDOWN, /* CH.tracking down */ + + [0x13] = KEY_ENTER, /* enter */ + [0x21] = KEY_DOT, /* . (decimal dot) */ }; EXPORT_SYMBOL_GPL(ir_codes_eztv); /* Alex Hermann */ IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { - [ 0x28 ] = KEY_1, - [ 0x18 ] = KEY_2, - [ 0x38 ] = KEY_3, - [ 0x24 ] = KEY_4, - [ 0x14 ] = KEY_5, - [ 0x34 ] = KEY_6, - [ 0x2c ] = KEY_7, - [ 0x1c ] = KEY_8, - [ 0x3c ] = KEY_9, - [ 0x22 ] = KEY_0, - - [ 0x20 ] = KEY_TV, /* TV/FM */ - [ 0x10 ] = KEY_CD, /* CD */ - [ 0x30 ] = KEY_TEXT, /* TELETEXT */ - [ 0x00 ] = KEY_POWER, /* POWER */ - - [ 0x08 ] = KEY_VIDEO, /* VIDEO */ - [ 0x04 ] = KEY_AUDIO, /* AUDIO */ - [ 0x0c ] = KEY_ZOOM, /* FULL SCREEN */ - - [ 0x12 ] = KEY_SUBTITLE, /* DISPLAY */ - [ 0x32 ] = KEY_REWIND, /* LOOP */ - [ 0x02 ] = KEY_PRINT, /* PREVIEW */ - - [ 0x2a ] = KEY_SEARCH, /* AUTOSCAN */ - [ 0x1a ] = KEY_SLEEP, /* FREEZE */ - [ 0x3a ] = KEY_SHUFFLE, /* SNAPSHOT */ - [ 0x0a ] = KEY_MUTE, /* MUTE */ - - [ 0x26 ] = KEY_RECORD, /* RECORD */ - [ 0x16 ] = KEY_PAUSE, /* PAUSE */ - [ 0x36 ] = KEY_STOP, /* STOP */ - [ 0x06 ] = KEY_PLAY, /* PLAY */ - - [ 0x2e ] = KEY_RED, /* RED */ - [ 0x21 ] = KEY_GREEN, /* GREEN */ - [ 0x0e ] = KEY_YELLOW, /* YELLOW */ - [ 0x01 ] = KEY_BLUE, /* BLUE */ - - [ 0x1e ] = KEY_VOLUMEDOWN, /* VOLUME- */ - [ 0x3e ] = KEY_VOLUMEUP, /* VOLUME+ */ - [ 0x11 ] = KEY_CHANNELDOWN, /* CHANNEL/PAGE- */ - [ 0x31 ] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ + [0x28] = KEY_1, + [0x18] = KEY_2, + [0x38] = KEY_3, + [0x24] = KEY_4, + [0x14] = KEY_5, + [0x34] = KEY_6, + [0x2c] = KEY_7, + [0x1c] = KEY_8, + [0x3c] = KEY_9, + [0x22] = KEY_0, + + [0x20] = KEY_TV, /* TV/FM */ + [0x10] = KEY_CD, /* CD */ + [0x30] = KEY_TEXT, /* TELETEXT */ + [0x00] = KEY_POWER, /* POWER */ + + [0x08] = KEY_VIDEO, /* VIDEO */ + [0x04] = KEY_AUDIO, /* AUDIO */ + [0x0c] = KEY_ZOOM, /* FULL SCREEN */ + + [0x12] = KEY_SUBTITLE, /* DISPLAY */ + [0x32] = KEY_REWIND, /* LOOP */ + [0x02] = KEY_PRINT, /* PREVIEW */ + + [0x2a] = KEY_SEARCH, /* AUTOSCAN */ + [0x1a] = KEY_SLEEP, /* FREEZE */ + [0x3a] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x0a] = KEY_MUTE, /* MUTE */ + + [0x26] = KEY_RECORD, /* RECORD */ + [0x16] = KEY_PAUSE, /* PAUSE */ + [0x36] = KEY_STOP, /* STOP */ + [0x06] = KEY_PLAY, /* PLAY */ + + [0x2e] = KEY_RED, /* RED */ + [0x21] = KEY_GREEN, /* GREEN */ + [0x0e] = KEY_YELLOW, /* YELLOW */ + [0x01] = KEY_BLUE, /* BLUE */ + + [0x1e] = KEY_VOLUMEDOWN, /* VOLUME- */ + [0x3e] = KEY_VOLUMEUP, /* VOLUME+ */ + [0x11] = KEY_CHANNELDOWN, /* CHANNEL/PAGE- */ + [0x31] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia); IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE] = { - [ 0x14 ] = KEY_MUTE, - [ 0x24 ] = KEY_ZOOM, - - [ 0x01 ] = KEY_DVD, - [ 0x23 ] = KEY_RADIO, - [ 0x00 ] = KEY_TV, - - [ 0x0a ] = KEY_REWIND, - [ 0x08 ] = KEY_PLAYPAUSE, - [ 0x0f ] = KEY_FORWARD, - - [ 0x02 ] = KEY_PREVIOUS, - [ 0x07 ] = KEY_STOP, - [ 0x06 ] = KEY_NEXT, - - [ 0x0c ] = KEY_UP, - [ 0x0e ] = KEY_DOWN, - [ 0x0b ] = KEY_LEFT, - [ 0x0d ] = KEY_RIGHT, - [ 0x11 ] = KEY_OK, - - [ 0x03 ] = KEY_MENU, - [ 0x09 ] = KEY_SETUP, - [ 0x05 ] = KEY_VIDEO, - [ 0x22 ] = KEY_CHANNEL, - - [ 0x12 ] = KEY_VOLUMEUP, - [ 0x15 ] = KEY_VOLUMEDOWN, - [ 0x10 ] = KEY_CHANNELUP, - [ 0x13 ] = KEY_CHANNELDOWN, - - [ 0x04 ] = KEY_RECORD, - - [ 0x16 ] = KEY_1, - [ 0x17 ] = KEY_2, - [ 0x18 ] = KEY_3, - [ 0x19 ] = KEY_4, - [ 0x1a ] = KEY_5, - [ 0x1b ] = KEY_6, - [ 0x1c ] = KEY_7, - [ 0x1d ] = KEY_8, - [ 0x1e ] = KEY_9, - [ 0x1f ] = KEY_0, - - [ 0x20 ] = KEY_LANGUAGE, - [ 0x21 ] = KEY_SLEEP, + [0x14] = KEY_MUTE, + [0x24] = KEY_ZOOM, + + [0x01] = KEY_DVD, + [0x23] = KEY_RADIO, + [0x00] = KEY_TV, + + [0x0a] = KEY_REWIND, + [0x08] = KEY_PLAYPAUSE, + [0x0f] = KEY_FORWARD, + + [0x02] = KEY_PREVIOUS, + [0x07] = KEY_STOP, + [0x06] = KEY_NEXT, + + [0x0c] = KEY_UP, + [0x0e] = KEY_DOWN, + [0x0b] = KEY_LEFT, + [0x0d] = KEY_RIGHT, + [0x11] = KEY_OK, + + [0x03] = KEY_MENU, + [0x09] = KEY_SETUP, + [0x05] = KEY_VIDEO, + [0x22] = KEY_CHANNEL, + + [0x12] = KEY_VOLUMEUP, + [0x15] = KEY_VOLUMEDOWN, + [0x10] = KEY_CHANNELUP, + [0x13] = KEY_CHANNELDOWN, + + [0x04] = KEY_RECORD, + + [0x16] = KEY_1, + [0x17] = KEY_2, + [0x18] = KEY_3, + [0x19] = KEY_4, + [0x1a] = KEY_5, + [0x1b] = KEY_6, + [0x1c] = KEY_7, + [0x1d] = KEY_8, + [0x1e] = KEY_9, + [0x1f] = KEY_0, + + [0x20] = KEY_LANGUAGE, + [0x21] = KEY_SLEEP, }; EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr); /* Michael Tokarev http://www.corpit.ru/mjt/beholdTV/remote_control.jpg - keytable is used by MANLI MTV00[ 0x0c ] and BeholdTV 40[13] at + keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at least, and probably other cards too. The "ascii-art picture" below (in comments, first row is the keycode in hex, and subsequent row(s) shows @@ -1241,8 +1241,8 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * FUNCTION POWER * * FM (|) * * */ - [ 0x1c ] = KEY_RADIO, /*XXX*/ - [ 0x12 ] = KEY_POWER, + [0x1c] = KEY_RADIO, /*XXX*/ + [0x12] = KEY_POWER, /* 0x01 0x02 0x03 * * 1 2 3 * @@ -1253,29 +1253,29 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * 0x07 0x08 0x09 * * 7 8 9 * * */ - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, /* 0x0a 0x00 0x17 * * RECALL 0 +100 * * PLUS * * */ - [ 0x0a ] = KEY_AGAIN, /*XXX KEY_REWIND? */ - [ 0x00 ] = KEY_0, - [ 0x17 ] = KEY_DIGITS, /*XXX*/ + [0x0a] = KEY_AGAIN, /*XXX KEY_REWIND? */ + [0x00] = KEY_0, + [0x17] = KEY_DIGITS, /*XXX*/ /* 0x14 0x10 * * MENU INFO * * OSD */ - [ 0x14 ] = KEY_MENU, - [ 0x10 ] = KEY_INFO, + [0x14] = KEY_MENU, + [0x10] = KEY_INFO, /* 0x0b * * Up * @@ -1286,18 +1286,18 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [ 0x0b ] = KEY_UP, /*XXX KEY_SCROLLUP? */ - [ 0x18 ] = KEY_LEFT, /*XXX KEY_BACK? */ - [ 0x16 ] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ - [ 0x0c ] = KEY_RIGHT, /*XXX KEY_FORWARD? */ - [ 0x15 ] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */ + [0x0b] = KEY_UP, /*XXX KEY_SCROLLUP? */ + [0x18] = KEY_LEFT, /*XXX KEY_BACK? */ + [0x16] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ + [0x0c] = KEY_RIGHT, /*XXX KEY_FORWARD? */ + [0x15] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */ /* 0x11 0x0d * * TV/AV MODE * * SOURCE STEREO * * */ - [ 0x11 ] = KEY_TV, /*XXX*/ - [ 0x0d ] = KEY_MODE, /*XXX there's no KEY_STEREO */ + [0x11] = KEY_TV, /*XXX*/ + [0x0d] = KEY_MODE, /*XXX there's no KEY_STEREO */ /* 0x0f 0x1b 0x1a * * AUDIO Vol+ Chan+ * @@ -1306,18 +1306,18 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * 0x0e 0x1f 0x1e * * SLEEP Vol- Chan- * * */ - [ 0x0f ] = KEY_AUDIO, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1a ] = KEY_CHANNELUP, - [ 0x0e ] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ - [ 0x1f ] = KEY_VOLUMEDOWN, - [ 0x1e ] = KEY_CHANNELDOWN, + [0x0f] = KEY_AUDIO, + [0x1b] = KEY_VOLUMEUP, + [0x1a] = KEY_CHANNELUP, + [0x0e] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ + [0x1f] = KEY_VOLUMEDOWN, + [0x1e] = KEY_CHANNELDOWN, /* 0x13 0x19 * * MUTE SNAPSHOT* * */ - [ 0x13 ] = KEY_MUTE, - [ 0x19 ] = KEY_RECORD, /*XXX*/ + [0x13] = KEY_MUTE, + [0x19] = KEY_RECORD, /*XXX*/ /* 0x1d unused ? */ }; @@ -1327,91 +1327,91 @@ EXPORT_SYMBOL_GPL(ir_codes_manli); /* Mike Baikov */ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { - [ 0x11 ] = KEY_POWER, - [ 0x35 ] = KEY_TV, - [ 0x1b ] = KEY_0, - [ 0x29 ] = KEY_1, - [ 0x19 ] = KEY_2, - [ 0x39 ] = KEY_3, - [ 0x1f ] = KEY_4, - [ 0x2c ] = KEY_5, - [ 0x21 ] = KEY_6, - [ 0x24 ] = KEY_7, - [ 0x18 ] = KEY_8, - [ 0x2b ] = KEY_9, - [ 0x3b ] = KEY_AGAIN, /* LOOP */ - [ 0x06 ] = KEY_AUDIO, - [ 0x31 ] = KEY_PRINT, /* PREVIEW */ - [ 0x3e ] = KEY_VIDEO, - [ 0x10 ] = KEY_CHANNELUP, - [ 0x20 ] = KEY_CHANNELDOWN, - [ 0x0c ] = KEY_VOLUMEDOWN, - [ 0x28 ] = KEY_VOLUMEUP, - [ 0x08 ] = KEY_MUTE, - [ 0x26 ] = KEY_SEARCH, /*SCAN*/ - [ 0x3f ] = KEY_SHUFFLE, /* SNAPSHOT */ - [ 0x12 ] = KEY_RECORD, - [ 0x32 ] = KEY_STOP, - [ 0x3c ] = KEY_PLAY, - [ 0x1d ] = KEY_REWIND, - [ 0x2d ] = KEY_PAUSE, - [ 0x0d ] = KEY_FORWARD, - [ 0x05 ] = KEY_ZOOM, /*FULL*/ - - [ 0x2a ] = KEY_F21, /* LIVE TIMESHIFT */ - [ 0x0e ] = KEY_F22, /* MIN TIMESHIFT */ - [ 0x1e ] = KEY_F23, /* TIMESHIFT */ - [ 0x38 ] = KEY_F24, /* NORMAL TIMESHIFT */ + [0x11] = KEY_POWER, + [0x35] = KEY_TV, + [0x1b] = KEY_0, + [0x29] = KEY_1, + [0x19] = KEY_2, + [0x39] = KEY_3, + [0x1f] = KEY_4, + [0x2c] = KEY_5, + [0x21] = KEY_6, + [0x24] = KEY_7, + [0x18] = KEY_8, + [0x2b] = KEY_9, + [0x3b] = KEY_AGAIN, /* LOOP */ + [0x06] = KEY_AUDIO, + [0x31] = KEY_PRINT, /* PREVIEW */ + [0x3e] = KEY_VIDEO, + [0x10] = KEY_CHANNELUP, + [0x20] = KEY_CHANNELDOWN, + [0x0c] = KEY_VOLUMEDOWN, + [0x28] = KEY_VOLUMEUP, + [0x08] = KEY_MUTE, + [0x26] = KEY_SEARCH, /*SCAN*/ + [0x3f] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x12] = KEY_RECORD, + [0x32] = KEY_STOP, + [0x3c] = KEY_PLAY, + [0x1d] = KEY_REWIND, + [0x2d] = KEY_PAUSE, + [0x0d] = KEY_FORWARD, + [0x05] = KEY_ZOOM, /*FULL*/ + + [0x2a] = KEY_F21, /* LIVE TIMESHIFT */ + [0x0e] = KEY_F22, /* MIN TIMESHIFT */ + [0x1e] = KEY_F23, /* TIMESHIFT */ + [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ }; EXPORT_SYMBOL_GPL(ir_codes_gotview7135); IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { - [ 0x03 ] = KEY_POWER, - [ 0x6f ] = KEY_MUTE, - [ 0x10 ] = KEY_BACKSPACE, /* Recall */ - - [ 0x11 ] = KEY_0, - [ 0x04 ] = KEY_1, - [ 0x05 ] = KEY_2, - [ 0x06 ] = KEY_3, - [ 0x08 ] = KEY_4, - [ 0x09 ] = KEY_5, - [ 0x0a ] = KEY_6, - [ 0x0c ] = KEY_7, - [ 0x0d ] = KEY_8, - [ 0x0e ] = KEY_9, - [ 0x12 ] = KEY_DOT, /* 100+ */ - - [ 0x07 ] = KEY_VOLUMEUP, - [ 0x0b ] = KEY_VOLUMEDOWN, - [ 0x1a ] = KEY_KPPLUS, - [ 0x18 ] = KEY_KPMINUS, - [ 0x15 ] = KEY_UP, - [ 0x1d ] = KEY_DOWN, - [ 0x0f ] = KEY_CHANNELUP, - [ 0x13 ] = KEY_CHANNELDOWN, - [ 0x48 ] = KEY_ZOOM, - - [ 0x1b ] = KEY_VIDEO, /* Video source */ + [0x03] = KEY_POWER, + [0x6f] = KEY_MUTE, + [0x10] = KEY_BACKSPACE, /* Recall */ + + [0x11] = KEY_0, + [0x04] = KEY_1, + [0x05] = KEY_2, + [0x06] = KEY_3, + [0x08] = KEY_4, + [0x09] = KEY_5, + [0x0a] = KEY_6, + [0x0c] = KEY_7, + [0x0d] = KEY_8, + [0x0e] = KEY_9, + [0x12] = KEY_DOT, /* 100+ */ + + [0x07] = KEY_VOLUMEUP, + [0x0b] = KEY_VOLUMEDOWN, + [0x1a] = KEY_KPPLUS, + [0x18] = KEY_KPMINUS, + [0x15] = KEY_UP, + [0x1d] = KEY_DOWN, + [0x0f] = KEY_CHANNELUP, + [0x13] = KEY_CHANNELDOWN, + [0x48] = KEY_ZOOM, + + [0x1b] = KEY_VIDEO, /* Video source */ #if 0 - [ 0x1f ] = KEY_S, /* Snapshot */ + [0x1f] = KEY_S, /* Snapshot */ #endif - [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */ - [ 0x19 ] = KEY_SEARCH, /* Auto Scan */ + [0x49] = KEY_LANGUAGE, /* MTS Select */ + [0x19] = KEY_SEARCH, /* Auto Scan */ - [ 0x4b ] = KEY_RECORD, - [ 0x46 ] = KEY_PLAY, - [ 0x45 ] = KEY_PAUSE, /* Pause */ - [ 0x44 ] = KEY_STOP, + [0x4b] = KEY_RECORD, + [0x46] = KEY_PLAY, + [0x45] = KEY_PAUSE, /* Pause */ + [0x44] = KEY_STOP, #if 0 - [ 0x43 ] = KEY_T, /* Time Shift */ - [ 0x47 ] = KEY_Y, /* Time Shift OFF */ - [ 0x4a ] = KEY_O, /* TOP */ - [ 0x17 ] = KEY_F, /* SURF CH */ + [0x43] = KEY_T, /* Time Shift */ + [0x47] = KEY_Y, /* Time Shift OFF */ + [0x4a] = KEY_O, /* TOP */ + [0x17] = KEY_F, /* SURF CH */ #endif - [ 0x40 ] = KEY_FORWARD, /* Forward ? */ - [ 0x42 ] = KEY_REWIND, /* Backward ? */ + [0x40] = KEY_FORWARD, /* Forward ? */ + [0x42] = KEY_REWIND, /* Backward ? */ }; @@ -1422,35 +1422,35 @@ EXPORT_SYMBOL_GPL(ir_codes_purpletv); Pavel Mihaylov Also for the remote bundled with Kozumi KTV-01C card */ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0a ] = KEY_AGAIN, /* Recall */ - [ 0x0b ] = KEY_CHANNELUP, - [ 0x0c ] = KEY_VOLUMEUP, - [ 0x0d ] = KEY_MODE, /* Stereo */ - [ 0x0e ] = KEY_STOP, - [ 0x0f ] = KEY_PREVIOUSSONG, - [ 0x10 ] = KEY_ZOOM, - [ 0x11 ] = KEY_TUNER, /* Source */ - [ 0x12 ] = KEY_POWER, - [ 0x13 ] = KEY_MUTE, - [ 0x15 ] = KEY_CHANNELDOWN, - [ 0x18 ] = KEY_VOLUMEDOWN, - [ 0x19 ] = KEY_SHUFFLE, /* Snapshot */ - [ 0x1a ] = KEY_NEXTSONG, - [ 0x1b ] = KEY_TEXT, /* Time Shift */ - [ 0x1c ] = KEY_RADIO, /* FM Radio */ - [ 0x1d ] = KEY_RECORD, - [ 0x1e ] = KEY_PAUSE, + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0a] = KEY_AGAIN, /* Recall */ + [0x0b] = KEY_CHANNELUP, + [0x0c] = KEY_VOLUMEUP, + [0x0d] = KEY_MODE, /* Stereo */ + [0x0e] = KEY_STOP, + [0x0f] = KEY_PREVIOUSSONG, + [0x10] = KEY_ZOOM, + [0x11] = KEY_TUNER, /* Source */ + [0x12] = KEY_POWER, + [0x13] = KEY_MUTE, + [0x15] = KEY_CHANNELDOWN, + [0x18] = KEY_VOLUMEDOWN, + [0x19] = KEY_SHUFFLE, /* Snapshot */ + [0x1a] = KEY_NEXTSONG, + [0x1b] = KEY_TEXT, /* Time Shift */ + [0x1c] = KEY_RADIO, /* FM Radio */ + [0x1d] = KEY_RECORD, + [0x1e] = KEY_PAUSE, /* additional codes for Kozumi's remote */ [0x14] = KEY_INFO, /* OSD */ [0x16] = KEY_OK, /* OK */ @@ -1462,41 +1462,41 @@ EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna); /* Mark Phalan */ IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x12 ] = KEY_POWER, - [ 0x10 ] = KEY_MUTE, - [ 0x1f ] = KEY_VOLUMEDOWN, - [ 0x1b ] = KEY_VOLUMEUP, - [ 0x1a ] = KEY_CHANNELUP, - [ 0x1e ] = KEY_CHANNELDOWN, - [ 0x0e ] = KEY_PAGEUP, - [ 0x1d ] = KEY_PAGEDOWN, - [ 0x13 ] = KEY_SOUND, - - [ 0x18 ] = KEY_KPPLUSMINUS, /* CH +/- */ - [ 0x16 ] = KEY_SUBTITLE, /* CC */ - [ 0x0d ] = KEY_TEXT, /* TTX */ - [ 0x0b ] = KEY_TV, /* AIR/CBL */ - [ 0x11 ] = KEY_PC, /* PC/TV */ - [ 0x17 ] = KEY_OK, /* CH RTN */ - [ 0x19 ] = KEY_MODE, /* FUNC */ - [ 0x0c ] = KEY_SEARCH, /* AUTOSCAN */ + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x12] = KEY_POWER, + [0x10] = KEY_MUTE, + [0x1f] = KEY_VOLUMEDOWN, + [0x1b] = KEY_VOLUMEUP, + [0x1a] = KEY_CHANNELUP, + [0x1e] = KEY_CHANNELDOWN, + [0x0e] = KEY_PAGEUP, + [0x1d] = KEY_PAGEDOWN, + [0x13] = KEY_SOUND, + + [0x18] = KEY_KPPLUSMINUS, /* CH +/- */ + [0x16] = KEY_SUBTITLE, /* CC */ + [0x0d] = KEY_TEXT, /* TTX */ + [0x0b] = KEY_TV, /* AIR/CBL */ + [0x11] = KEY_PC, /* PC/TV */ + [0x17] = KEY_OK, /* CH RTN */ + [0x19] = KEY_MODE, /* FUNC */ + [0x0c] = KEY_SEARCH, /* AUTOSCAN */ /* Not sure what to do with these ones! */ - [ 0x0f ] = KEY_SELECT, /* SOURCE */ - [ 0x0a ] = KEY_KPPLUS, /* +100 */ - [ 0x14 ] = KEY_EQUAL, /* SYNC */ - [ 0x1c ] = KEY_MEDIA, /* PC/TV */ + [0x0f] = KEY_SELECT, /* SOURCE */ + [0x0a] = KEY_KPPLUS, /* +100 */ + [0x14] = KEY_EQUAL, /* SYNC */ + [0x1c] = KEY_MEDIA, /* PC/TV */ }; EXPORT_SYMBOL_GPL(ir_codes_pv951); @@ -1506,73 +1506,73 @@ EXPORT_SYMBOL_GPL(ir_codes_pv951); /* used by old (black) Hauppauge remotes */ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0b ] = KEY_CHANNEL, /* channel / program (japan: 11) */ - [ 0x0c ] = KEY_POWER, /* standby */ - [ 0x0d ] = KEY_MUTE, /* mute / demute */ - [ 0x0f ] = KEY_TV, /* display */ - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x12 ] = KEY_BRIGHTNESSUP, - [ 0x13 ] = KEY_BRIGHTNESSDOWN, - [ 0x1e ] = KEY_SEARCH, /* search + */ - [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ - [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ - [ 0x22 ] = KEY_CHANNEL, /* alt / channel */ - [ 0x23 ] = KEY_LANGUAGE, /* 1st / 2nd language */ - [ 0x26 ] = KEY_SLEEP, /* sleeptimer */ - [ 0x2e ] = KEY_MENU, /* 2nd controls (USA: menu) */ - [ 0x30 ] = KEY_PAUSE, - [ 0x32 ] = KEY_REWIND, - [ 0x33 ] = KEY_GOTO, - [ 0x35 ] = KEY_PLAY, - [ 0x36 ] = KEY_STOP, - [ 0x37 ] = KEY_RECORD, /* recording */ - [ 0x3c ] = KEY_TEXT, /* teletext submode (Japan: 12) */ - [ 0x3d ] = KEY_SUSPEND, /* system standby */ + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0b] = KEY_CHANNEL, /* channel / program (japan: 11) */ + [0x0c] = KEY_POWER, /* standby */ + [0x0d] = KEY_MUTE, /* mute / demute */ + [0x0f] = KEY_TV, /* display */ + [0x10] = KEY_VOLUMEUP, + [0x11] = KEY_VOLUMEDOWN, + [0x12] = KEY_BRIGHTNESSUP, + [0x13] = KEY_BRIGHTNESSDOWN, + [0x1e] = KEY_SEARCH, /* search + */ + [0x20] = KEY_CHANNELUP, /* channel / program + */ + [0x21] = KEY_CHANNELDOWN, /* channel / program - */ + [0x22] = KEY_CHANNEL, /* alt / channel */ + [0x23] = KEY_LANGUAGE, /* 1st / 2nd language */ + [0x26] = KEY_SLEEP, /* sleeptimer */ + [0x2e] = KEY_MENU, /* 2nd controls (USA: menu) */ + [0x30] = KEY_PAUSE, + [0x32] = KEY_REWIND, + [0x33] = KEY_GOTO, + [0x35] = KEY_PLAY, + [0x36] = KEY_STOP, + [0x37] = KEY_RECORD, /* recording */ + [0x3c] = KEY_TEXT, /* teletext submode (Japan: 12) */ + [0x3d] = KEY_SUSPEND, /* system standby */ #if 0 /* FIXME */ - [ 0x0a ] = KEY_RESERVED, /* 1/2/3 digits (japan: 10) */ - [ 0x0e ] = KEY_RESERVED, /* P.P. (personal preference) */ - [ 0x14 ] = KEY_RESERVED, /* colour saturation + */ - [ 0x15 ] = KEY_RESERVED, /* colour saturation - */ - [ 0x16 ] = KEY_RESERVED, /* bass + */ - [ 0x17 ] = KEY_RESERVED, /* bass - */ - [ 0x18 ] = KEY_RESERVED, /* treble + */ - [ 0x19 ] = KEY_RESERVED, /* treble - */ - [ 0x1a ] = KEY_RESERVED, /* balance right */ - [ 0x1b ] = KEY_RESERVED, /* balance left */ - [ 0x1c ] = KEY_RESERVED, /* contrast + */ - [ 0x1d ] = KEY_RESERVED, /* contrast - */ - [ 0x1f ] = KEY_RESERVED, /* tint/hue + */ - [ 0x24 ] = KEY_RESERVED, /* spacial stereo on/off */ - [ 0x25 ] = KEY_RESERVED, /* mono / stereo (USA) */ - [ 0x27 ] = KEY_RESERVED, /* tint / hue - */ - [ 0x28 ] = KEY_RESERVED, /* RF switch/PIP select */ - [ 0x29 ] = KEY_RESERVED, /* vote */ - [ 0x2a ] = KEY_RESERVED, /* timed page/channel clck */ - [ 0x2b ] = KEY_RESERVED, /* increment (USA) */ - [ 0x2c ] = KEY_RESERVED, /* decrement (USA) */ - [ 0x2d ] = KEY_RESERVED, /* */ - [ 0x2f ] = KEY_RESERVED, /* PIP shift */ - [ 0x31 ] = KEY_RESERVED, /* erase */ - [ 0x34 ] = KEY_RESERVED, /* wind */ - [ 0x38 ] = KEY_RESERVED, /* external 1 */ - [ 0x39 ] = KEY_RESERVED, /* external 2 */ - [ 0x3a ] = KEY_RESERVED, /* PIP display mode */ - [ 0x3b ] = KEY_RESERVED, /* view data mode / advance */ - [ 0x3e ] = KEY_RESERVED, /* crispener on/off */ - [ 0x3f ] = KEY_RESERVED, /* system select */ + [0x0a] = KEY_RESERVED, /* 1/2/3 digits (japan: 10) */ + [0x0e] = KEY_RESERVED, /* P.P. (personal preference) */ + [0x14] = KEY_RESERVED, /* colour saturation + */ + [0x15] = KEY_RESERVED, /* colour saturation - */ + [0x16] = KEY_RESERVED, /* bass + */ + [0x17] = KEY_RESERVED, /* bass - */ + [0x18] = KEY_RESERVED, /* treble + */ + [0x19] = KEY_RESERVED, /* treble - */ + [0x1a] = KEY_RESERVED, /* balance right */ + [0x1b] = KEY_RESERVED, /* balance left */ + [0x1c] = KEY_RESERVED, /* contrast + */ + [0x1d] = KEY_RESERVED, /* contrast - */ + [0x1f] = KEY_RESERVED, /* tint/hue + */ + [0x24] = KEY_RESERVED, /* spacial stereo on/off */ + [0x25] = KEY_RESERVED, /* mono / stereo (USA) */ + [0x27] = KEY_RESERVED, /* tint / hue - */ + [0x28] = KEY_RESERVED, /* RF switch/PIP select */ + [0x29] = KEY_RESERVED, /* vote */ + [0x2a] = KEY_RESERVED, /* timed page/channel clck */ + [0x2b] = KEY_RESERVED, /* increment (USA) */ + [0x2c] = KEY_RESERVED, /* decrement (USA) */ + [0x2d] = KEY_RESERVED, /* */ + [0x2f] = KEY_RESERVED, /* PIP shift */ + [0x31] = KEY_RESERVED, /* erase */ + [0x34] = KEY_RESERVED, /* wind */ + [0x38] = KEY_RESERVED, /* external 1 */ + [0x39] = KEY_RESERVED, /* external 2 */ + [0x3a] = KEY_RESERVED, /* PIP display mode */ + [0x3b] = KEY_RESERVED, /* view data mode / advance */ + [0x3e] = KEY_RESERVED, /* crispener on/off */ + [0x3f] = KEY_RESERVED, /* system select */ #endif }; @@ -1581,123 +1581,123 @@ EXPORT_SYMBOL_GPL(ir_codes_rc5_tv); /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x12 ] = KEY_0, - [ 0x05 ] = KEY_1, - [ 0x06 ] = KEY_2, - [ 0x07 ] = KEY_3, - [ 0x09 ] = KEY_4, - [ 0x0a ] = KEY_5, - [ 0x0b ] = KEY_6, - [ 0x0d ] = KEY_7, - [ 0x0e ] = KEY_8, - [ 0x0f ] = KEY_9, - - [ 0x00 ] = KEY_POWER, - [ 0x1b ] = KEY_AUDIO, /* Audio Source */ - [ 0x02 ] = KEY_TUNER, /* TV/FM, not on Y0400052 */ - [ 0x1e ] = KEY_VIDEO, /* Video Source */ - [ 0x16 ] = KEY_INFO, /* Display information */ - [ 0x04 ] = KEY_VOLUMEUP, - [ 0x08 ] = KEY_VOLUMEDOWN, - [ 0x0c ] = KEY_CHANNELUP, - [ 0x10 ] = KEY_CHANNELDOWN, - [ 0x03 ] = KEY_ZOOM, /* fullscreen */ - [ 0x1f ] = KEY_TEXT, /* closed caption/teletext */ - [ 0x20 ] = KEY_SLEEP, - [ 0x29 ] = KEY_CLEAR, /* boss key */ - [ 0x14 ] = KEY_MUTE, - [ 0x2b ] = KEY_RED, - [ 0x2c ] = KEY_GREEN, - [ 0x2d ] = KEY_YELLOW, - [ 0x2e ] = KEY_BLUE, - [ 0x18 ] = KEY_KPPLUS, /* fine tune + , not on Y040052 */ - [ 0x19 ] = KEY_KPMINUS, /* fine tune - , not on Y040052 */ - [ 0x2a ] = KEY_MEDIA, /* PIP (Picture in picture */ - [ 0x21 ] = KEY_DOT, - [ 0x13 ] = KEY_ENTER, - [ 0x11 ] = KEY_LAST, /* Recall (last channel */ - [ 0x22 ] = KEY_PREVIOUS, - [ 0x23 ] = KEY_PLAYPAUSE, - [ 0x24 ] = KEY_NEXT, - [ 0x25 ] = KEY_ARCHIVE, /* Time Shifting */ - [ 0x26 ] = KEY_STOP, - [ 0x27 ] = KEY_RECORD, - [ 0x28 ] = KEY_SAVE, /* Screenshot */ - [ 0x2f ] = KEY_MENU, - [ 0x30 ] = KEY_CANCEL, - [ 0x31 ] = KEY_CHANNEL, /* Channel Surf */ - [ 0x32 ] = KEY_SUBTITLE, - [ 0x33 ] = KEY_LANGUAGE, - [ 0x34 ] = KEY_REWIND, - [ 0x35 ] = KEY_FASTFORWARD, - [ 0x36 ] = KEY_TV, - [ 0x37 ] = KEY_RADIO, /* FM */ - [ 0x38 ] = KEY_DVD, - - [ 0x3e ] = KEY_F21, /* MCE +VOL, on Y04G0033 */ - [ 0x3a ] = KEY_F22, /* MCE -VOL, on Y04G0033 */ - [ 0x3b ] = KEY_F23, /* MCE +CH, on Y04G0033 */ - [ 0x3f ] = KEY_F24 /* MCE -CH, on Y04G0033 */ + [0x12] = KEY_0, + [0x05] = KEY_1, + [0x06] = KEY_2, + [0x07] = KEY_3, + [0x09] = KEY_4, + [0x0a] = KEY_5, + [0x0b] = KEY_6, + [0x0d] = KEY_7, + [0x0e] = KEY_8, + [0x0f] = KEY_9, + + [0x00] = KEY_POWER, + [0x1b] = KEY_AUDIO, /* Audio Source */ + [0x02] = KEY_TUNER, /* TV/FM, not on Y0400052 */ + [0x1e] = KEY_VIDEO, /* Video Source */ + [0x16] = KEY_INFO, /* Display information */ + [0x04] = KEY_VOLUMEUP, + [0x08] = KEY_VOLUMEDOWN, + [0x0c] = KEY_CHANNELUP, + [0x10] = KEY_CHANNELDOWN, + [0x03] = KEY_ZOOM, /* fullscreen */ + [0x1f] = KEY_TEXT, /* closed caption/teletext */ + [0x20] = KEY_SLEEP, + [0x29] = KEY_CLEAR, /* boss key */ + [0x14] = KEY_MUTE, + [0x2b] = KEY_RED, + [0x2c] = KEY_GREEN, + [0x2d] = KEY_YELLOW, + [0x2e] = KEY_BLUE, + [0x18] = KEY_KPPLUS, /* fine tune + , not on Y040052 */ + [0x19] = KEY_KPMINUS, /* fine tune - , not on Y040052 */ + [0x2a] = KEY_MEDIA, /* PIP (Picture in picture */ + [0x21] = KEY_DOT, + [0x13] = KEY_ENTER, + [0x11] = KEY_LAST, /* Recall (last channel */ + [0x22] = KEY_PREVIOUS, + [0x23] = KEY_PLAYPAUSE, + [0x24] = KEY_NEXT, + [0x25] = KEY_ARCHIVE, /* Time Shifting */ + [0x26] = KEY_STOP, + [0x27] = KEY_RECORD, + [0x28] = KEY_SAVE, /* Screenshot */ + [0x2f] = KEY_MENU, + [0x30] = KEY_CANCEL, + [0x31] = KEY_CHANNEL, /* Channel Surf */ + [0x32] = KEY_SUBTITLE, + [0x33] = KEY_LANGUAGE, + [0x34] = KEY_REWIND, + [0x35] = KEY_FASTFORWARD, + [0x36] = KEY_TV, + [0x37] = KEY_RADIO, /* FM */ + [0x38] = KEY_DVD, + + [0x3e] = KEY_F21, /* MCE +VOL, on Y04G0033 */ + [0x3a] = KEY_F22, /* MCE -VOL, on Y04G0033 */ + [0x3b] = KEY_F23, /* MCE +CH, on Y04G0033 */ + [0x3f] = KEY_F24 /* MCE -CH, on Y04G0033 */ }; EXPORT_SYMBOL_GPL(ir_codes_winfast); IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = { - [ 0x59 ] = KEY_MUTE, - [ 0x4a ] = KEY_POWER, - - [ 0x18 ] = KEY_TEXT, - [ 0x26 ] = KEY_TV, - [ 0x3d ] = KEY_PRINT, + [0x59] = KEY_MUTE, + [0x4a] = KEY_POWER, - [ 0x48 ] = KEY_RED, - [ 0x04 ] = KEY_GREEN, - [ 0x11 ] = KEY_YELLOW, - [ 0x00 ] = KEY_BLUE, + [0x18] = KEY_TEXT, + [0x26] = KEY_TV, + [0x3d] = KEY_PRINT, - [ 0x2d ] = KEY_VOLUMEUP, - [ 0x1e ] = KEY_VOLUMEDOWN, + [0x48] = KEY_RED, + [0x04] = KEY_GREEN, + [0x11] = KEY_YELLOW, + [0x00] = KEY_BLUE, - [ 0x49 ] = KEY_MENU, - - [ 0x16 ] = KEY_CHANNELUP, - [ 0x17 ] = KEY_CHANNELDOWN, - - [ 0x20 ] = KEY_UP, - [ 0x21 ] = KEY_DOWN, - [ 0x22 ] = KEY_LEFT, - [ 0x23 ] = KEY_RIGHT, - [ 0x0d ] = KEY_SELECT, - - - - [ 0x08 ] = KEY_BACK, - [ 0x07 ] = KEY_REFRESH, - - [ 0x2f ] = KEY_ZOOM, - [ 0x29 ] = KEY_RECORD, + [0x2d] = KEY_VOLUMEUP, + [0x1e] = KEY_VOLUMEDOWN, - [ 0x4b ] = KEY_PAUSE, - [ 0x4d ] = KEY_REWIND, - [ 0x2e ] = KEY_PLAY, - [ 0x4e ] = KEY_FORWARD, - [ 0x53 ] = KEY_PREVIOUS, - [ 0x4c ] = KEY_STOP, - [ 0x54 ] = KEY_NEXT, + [0x49] = KEY_MENU, - [ 0x69 ] = KEY_0, - [ 0x6a ] = KEY_1, - [ 0x6b ] = KEY_2, - [ 0x6c ] = KEY_3, - [ 0x6d ] = KEY_4, - [ 0x6e ] = KEY_5, - [ 0x6f ] = KEY_6, - [ 0x70 ] = KEY_7, - [ 0x71 ] = KEY_8, - [ 0x72 ] = KEY_9, + [0x16] = KEY_CHANNELUP, + [0x17] = KEY_CHANNELDOWN, - [ 0x74 ] = KEY_CHANNEL, - [ 0x0a ] = KEY_BACKSPACE, + [0x20] = KEY_UP, + [0x21] = KEY_DOWN, + [0x22] = KEY_LEFT, + [0x23] = KEY_RIGHT, + [0x0d] = KEY_SELECT, + + + + [0x08] = KEY_BACK, + [0x07] = KEY_REFRESH, + + [0x2f] = KEY_ZOOM, + [0x29] = KEY_RECORD, + + [0x4b] = KEY_PAUSE, + [0x4d] = KEY_REWIND, + [0x2e] = KEY_PLAY, + [0x4e] = KEY_FORWARD, + [0x53] = KEY_PREVIOUS, + [0x4c] = KEY_STOP, + [0x54] = KEY_NEXT, + + [0x69] = KEY_0, + [0x6a] = KEY_1, + [0x6b] = KEY_2, + [0x6c] = KEY_3, + [0x6d] = KEY_4, + [0x6e] = KEY_5, + [0x6f] = KEY_6, + [0x70] = KEY_7, + [0x71] = KEY_8, + [0x72] = KEY_9, + + [0x74] = KEY_CHANNEL, + [0x0a] = KEY_BACKSPACE, }; EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color); @@ -1707,103 +1707,103 @@ EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color); * almost rc5 coding, but some non-standard keys */ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - - [ 0x0a ] = KEY_TEXT, /* keypad asterisk as well */ - [ 0x0b ] = KEY_RED, /* red button */ - [ 0x0c ] = KEY_RADIO, - [ 0x0d ] = KEY_MENU, - [ 0x0e ] = KEY_SUBTITLE, /* also the # key */ - [ 0x0f ] = KEY_MUTE, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x12 ] = KEY_PREVIOUS, /* previous channel */ - [ 0x14 ] = KEY_UP, - [ 0x15 ] = KEY_DOWN, - [ 0x16 ] = KEY_LEFT, - [ 0x17 ] = KEY_RIGHT, - [ 0x18 ] = KEY_VIDEO, /* Videos */ - [ 0x19 ] = KEY_AUDIO, /* Music */ + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + + [0x0a] = KEY_TEXT, /* keypad asterisk as well */ + [0x0b] = KEY_RED, /* red button */ + [0x0c] = KEY_RADIO, + [0x0d] = KEY_MENU, + [0x0e] = KEY_SUBTITLE, /* also the # key */ + [0x0f] = KEY_MUTE, + [0x10] = KEY_VOLUMEUP, + [0x11] = KEY_VOLUMEDOWN, + [0x12] = KEY_PREVIOUS, /* previous channel */ + [0x14] = KEY_UP, + [0x15] = KEY_DOWN, + [0x16] = KEY_LEFT, + [0x17] = KEY_RIGHT, + [0x18] = KEY_VIDEO, /* Videos */ + [0x19] = KEY_AUDIO, /* Music */ /* 0x1a: Pictures - presume this means "Multimedia Home Platform" - no "PICTURES" key in input.h */ - [ 0x1a ] = KEY_MHP, - - [ 0x1b ] = KEY_EPG, /* Guide */ - [ 0x1c ] = KEY_TV, - [ 0x1e ] = KEY_NEXTSONG, /* skip >| */ - [ 0x1f ] = KEY_EXIT, /* back/exit */ - [ 0x20 ] = KEY_CHANNELUP, /* channel / program + */ - [ 0x21 ] = KEY_CHANNELDOWN, /* channel / program - */ - [ 0x22 ] = KEY_CHANNEL, /* source (old black remote) */ - [ 0x24 ] = KEY_PREVIOUSSONG, /* replay |< */ - [ 0x25 ] = KEY_ENTER, /* OK */ - [ 0x26 ] = KEY_SLEEP, /* minimize (old black remote) */ - [ 0x29 ] = KEY_BLUE, /* blue key */ - [ 0x2e ] = KEY_GREEN, /* green button */ - [ 0x30 ] = KEY_PAUSE, /* pause */ - [ 0x32 ] = KEY_REWIND, /* backward << */ - [ 0x34 ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x35 ] = KEY_PLAY, - [ 0x36 ] = KEY_STOP, - [ 0x37 ] = KEY_RECORD, /* recording */ - [ 0x38 ] = KEY_YELLOW, /* yellow key */ - [ 0x3b ] = KEY_SELECT, /* top right button */ - [ 0x3c ] = KEY_ZOOM, /* full */ - [ 0x3d ] = KEY_POWER, /* system power (green button) */ + [0x1a] = KEY_MHP, + + [0x1b] = KEY_EPG, /* Guide */ + [0x1c] = KEY_TV, + [0x1e] = KEY_NEXTSONG, /* skip >| */ + [0x1f] = KEY_EXIT, /* back/exit */ + [0x20] = KEY_CHANNELUP, /* channel / program + */ + [0x21] = KEY_CHANNELDOWN, /* channel / program - */ + [0x22] = KEY_CHANNEL, /* source (old black remote) */ + [0x24] = KEY_PREVIOUSSONG, /* replay |< */ + [0x25] = KEY_ENTER, /* OK */ + [0x26] = KEY_SLEEP, /* minimize (old black remote) */ + [0x29] = KEY_BLUE, /* blue key */ + [0x2e] = KEY_GREEN, /* green button */ + [0x30] = KEY_PAUSE, /* pause */ + [0x32] = KEY_REWIND, /* backward << */ + [0x34] = KEY_FASTFORWARD, /* forward >> */ + [0x35] = KEY_PLAY, + [0x36] = KEY_STOP, + [0x37] = KEY_RECORD, /* recording */ + [0x38] = KEY_YELLOW, /* yellow key */ + [0x3b] = KEY_SELECT, /* top right button */ + [0x3c] = KEY_ZOOM, /* full */ + [0x3d] = KEY_POWER, /* system power (green button) */ }; EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { - [ 0x1d ] = KEY_SWITCHVIDEOMODE, /* switch inputs */ - [ 0x2a ] = KEY_FRONT, - - [ 0x3e ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x06 ] = KEY_3, - [ 0x0a ] = KEY_4, - [ 0x0e ] = KEY_5, - [ 0x12 ] = KEY_6, - [ 0x16 ] = KEY_7, - [ 0x1a ] = KEY_8, - [ 0x1e ] = KEY_9, - [ 0x3a ] = KEY_0, - [ 0x22 ] = KEY_NUMLOCK, /* -/-- */ - [ 0x20 ] = KEY_REFRESH, - - [ 0x03 ] = KEY_BRIGHTNESSDOWN, - [ 0x28 ] = KEY_AUDIO, - [ 0x3c ] = KEY_UP, - [ 0x3f ] = KEY_LEFT, - [ 0x2e ] = KEY_MUTE, - [ 0x3b ] = KEY_RIGHT, - [ 0x00 ] = KEY_DOWN, - [ 0x07 ] = KEY_BRIGHTNESSUP, - [ 0x2c ] = KEY_TEXT, - - [ 0x37 ] = KEY_RECORD, - [ 0x17 ] = KEY_PLAY, - [ 0x13 ] = KEY_PAUSE, - [ 0x26 ] = KEY_STOP, - [ 0x18 ] = KEY_FASTFORWARD, - [ 0x14 ] = KEY_REWIND, - [ 0x33 ] = KEY_ZOOM, - [ 0x32 ] = KEY_KEYBOARD, - [ 0x30 ] = KEY_GOTO, /* Pointing arrow */ - [ 0x36 ] = KEY_MACRO, /* Maximize/Minimize (yellow) */ - [ 0x0b ] = KEY_RADIO, - [ 0x10 ] = KEY_POWER, + [0x1d] = KEY_SWITCHVIDEOMODE, /* switch inputs */ + [0x2a] = KEY_FRONT, + + [0x3e] = KEY_1, + [0x02] = KEY_2, + [0x06] = KEY_3, + [0x0a] = KEY_4, + [0x0e] = KEY_5, + [0x12] = KEY_6, + [0x16] = KEY_7, + [0x1a] = KEY_8, + [0x1e] = KEY_9, + [0x3a] = KEY_0, + [0x22] = KEY_NUMLOCK, /* -/-- */ + [0x20] = KEY_REFRESH, + + [0x03] = KEY_BRIGHTNESSDOWN, + [0x28] = KEY_AUDIO, + [0x3c] = KEY_UP, + [0x3f] = KEY_LEFT, + [0x2e] = KEY_MUTE, + [0x3b] = KEY_RIGHT, + [0x00] = KEY_DOWN, + [0x07] = KEY_BRIGHTNESSUP, + [0x2c] = KEY_TEXT, + + [0x37] = KEY_RECORD, + [0x17] = KEY_PLAY, + [0x13] = KEY_PAUSE, + [0x26] = KEY_STOP, + [0x18] = KEY_FASTFORWARD, + [0x14] = KEY_REWIND, + [0x33] = KEY_ZOOM, + [0x32] = KEY_KEYBOARD, + [0x30] = KEY_GOTO, /* Pointing arrow */ + [0x36] = KEY_MACRO, /* Maximize/Minimize (yellow) */ + [0x0b] = KEY_RADIO, + [0x10] = KEY_POWER, }; @@ -1814,45 +1814,45 @@ EXPORT_SYMBOL_GPL(ir_codes_npgtech); Key comments are the functions given in the manual */ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x20 ] = KEY_0, - [ 0x21 ] = KEY_1, - [ 0x22 ] = KEY_2, - [ 0x23 ] = KEY_3, - [ 0x24 ] = KEY_4, - [ 0x25 ] = KEY_5, - [ 0x26 ] = KEY_6, - [ 0x27 ] = KEY_7, - [ 0x28 ] = KEY_8, - [ 0x29 ] = KEY_9, - - [ 0x78 ] = KEY_TUNER, /* Video Source */ - [ 0x2c ] = KEY_EXIT, /* Open/Close software */ - [ 0x2a ] = KEY_SELECT, /* 2 Digit Select */ - [ 0x69 ] = KEY_AGAIN, /* Recall */ - - [ 0x32 ] = KEY_BRIGHTNESSUP, /* Brightness increase */ - [ 0x33 ] = KEY_BRIGHTNESSDOWN, /* Brightness decrease */ - [ 0x6b ] = KEY_KPPLUS, /* (not named >>>>>) */ - [ 0x6c ] = KEY_KPMINUS, /* (not named <<<<<) */ - - [ 0x2d ] = KEY_MUTE, /* Mute */ - [ 0x30 ] = KEY_VOLUMEUP, /* Volume up */ - [ 0x31 ] = KEY_VOLUMEDOWN, /* Volume down */ - [ 0x60 ] = KEY_CHANNELUP, /* Channel up */ - [ 0x61 ] = KEY_CHANNELDOWN, /* Channel down */ - - [ 0x3f ] = KEY_RECORD, /* Record */ - [ 0x37 ] = KEY_PLAY, /* Play */ - [ 0x36 ] = KEY_PAUSE, /* Pause */ - [ 0x2b ] = KEY_STOP, /* Stop */ - [ 0x67 ] = KEY_FASTFORWARD, /* Foward */ - [ 0x66 ] = KEY_REWIND, /* Rewind */ - [ 0x3e ] = KEY_SEARCH, /* Auto Scan */ - [ 0x2e ] = KEY_CAMERA, /* Capture Video */ - [ 0x6d ] = KEY_MENU, /* Show/Hide Control */ - [ 0x2f ] = KEY_ZOOM, /* Full Screen */ - [ 0x34 ] = KEY_RADIO, /* FM */ - [ 0x65 ] = KEY_POWER, /* Computer power */ + [0x20] = KEY_0, + [0x21] = KEY_1, + [0x22] = KEY_2, + [0x23] = KEY_3, + [0x24] = KEY_4, + [0x25] = KEY_5, + [0x26] = KEY_6, + [0x27] = KEY_7, + [0x28] = KEY_8, + [0x29] = KEY_9, + + [0x78] = KEY_TUNER, /* Video Source */ + [0x2c] = KEY_EXIT, /* Open/Close software */ + [0x2a] = KEY_SELECT, /* 2 Digit Select */ + [0x69] = KEY_AGAIN, /* Recall */ + + [0x32] = KEY_BRIGHTNESSUP, /* Brightness increase */ + [0x33] = KEY_BRIGHTNESSDOWN, /* Brightness decrease */ + [0x6b] = KEY_KPPLUS, /* (not named >>>>>) */ + [0x6c] = KEY_KPMINUS, /* (not named <<<<<) */ + + [0x2d] = KEY_MUTE, /* Mute */ + [0x30] = KEY_VOLUMEUP, /* Volume up */ + [0x31] = KEY_VOLUMEDOWN, /* Volume down */ + [0x60] = KEY_CHANNELUP, /* Channel up */ + [0x61] = KEY_CHANNELDOWN, /* Channel down */ + + [0x3f] = KEY_RECORD, /* Record */ + [0x37] = KEY_PLAY, /* Play */ + [0x36] = KEY_PAUSE, /* Pause */ + [0x2b] = KEY_STOP, /* Stop */ + [0x67] = KEY_FASTFORWARD, /* Foward */ + [0x66] = KEY_REWIND, /* Rewind */ + [0x3e] = KEY_SEARCH, /* Auto Scan */ + [0x2e] = KEY_CAMERA, /* Capture Video */ + [0x6d] = KEY_MENU, /* Show/Hide Control */ + [0x2f] = KEY_ZOOM, /* Full Screen */ + [0x34] = KEY_RADIO, /* FM */ + [0x65] = KEY_POWER, /* Computer power */ }; EXPORT_SYMBOL_GPL(ir_codes_norwood); @@ -1863,51 +1863,51 @@ EXPORT_SYMBOL_GPL(ir_codes_norwood); * This is a "middle of the road" approach, differences are noted */ IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = { - [ 0x00 ] = KEY_0, - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, - [ 0x0a ] = KEY_ENTER, - [ 0x0b ] = KEY_RED, - [ 0x0c ] = KEY_POWER, /* RADIO on Hauppauge */ - [ 0x0d ] = KEY_MUTE, - [ 0x0f ] = KEY_A, /* TV on Hauppauge */ - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_VOLUMEDOWN, - [ 0x14 ] = KEY_B, - [ 0x1c ] = KEY_UP, - [ 0x1d ] = KEY_DOWN, - [ 0x1e ] = KEY_OPTION, /* RESERVED on Hauppauge */ - [ 0x1f ] = KEY_BREAK, - [ 0x20 ] = KEY_CHANNELUP, - [ 0x21 ] = KEY_CHANNELDOWN, - [ 0x22 ] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ - [ 0x24 ] = KEY_RESTART, - [ 0x25 ] = KEY_OK, - [ 0x26 ] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ - [ 0x28 ] = KEY_ENTER, /* VCR mode on Zenith */ - [ 0x29 ] = KEY_PAUSE, - [ 0x2b ] = KEY_RIGHT, - [ 0x2c ] = KEY_LEFT, - [ 0x2e ] = KEY_MENU, /* FULL SCREEN on Hauppauge */ - [ 0x30 ] = KEY_SLOW, - [ 0x31 ] = KEY_PREVIOUS, /* VCR mode on Zenith */ - [ 0x32 ] = KEY_REWIND, - [ 0x34 ] = KEY_FASTFORWARD, - [ 0x35 ] = KEY_PLAY, - [ 0x36 ] = KEY_STOP, - [ 0x37 ] = KEY_RECORD, - [ 0x38 ] = KEY_TUNER, /* TV/VCR on Zenith */ - [ 0x3a ] = KEY_C, - [ 0x3c ] = KEY_EXIT, - [ 0x3d ] = KEY_POWER2, - [ 0x3e ] = KEY_TUNER, + [0x00] = KEY_0, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x0a] = KEY_ENTER, + [0x0b] = KEY_RED, + [0x0c] = KEY_POWER, /* RADIO on Hauppauge */ + [0x0d] = KEY_MUTE, + [0x0f] = KEY_A, /* TV on Hauppauge */ + [0x10] = KEY_VOLUMEUP, + [0x11] = KEY_VOLUMEDOWN, + [0x14] = KEY_B, + [0x1c] = KEY_UP, + [0x1d] = KEY_DOWN, + [0x1e] = KEY_OPTION, /* RESERVED on Hauppauge */ + [0x1f] = KEY_BREAK, + [0x20] = KEY_CHANNELUP, + [0x21] = KEY_CHANNELDOWN, + [0x22] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ + [0x24] = KEY_RESTART, + [0x25] = KEY_OK, + [0x26] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ + [0x28] = KEY_ENTER, /* VCR mode on Zenith */ + [0x29] = KEY_PAUSE, + [0x2b] = KEY_RIGHT, + [0x2c] = KEY_LEFT, + [0x2e] = KEY_MENU, /* FULL SCREEN on Hauppauge */ + [0x30] = KEY_SLOW, + [0x31] = KEY_PREVIOUS, /* VCR mode on Zenith */ + [0x32] = KEY_REWIND, + [0x34] = KEY_FASTFORWARD, + [0x35] = KEY_PLAY, + [0x36] = KEY_STOP, + [0x37] = KEY_RECORD, + [0x38] = KEY_TUNER, /* TV/VCR on Zenith */ + [0x3a] = KEY_C, + [0x3c] = KEY_EXIT, + [0x3d] = KEY_POWER2, + [0x3e] = KEY_TUNER, }; EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); @@ -1919,49 +1919,49 @@ EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); */ IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE] = { /* Keys 0 to 9 */ - [ 0x15 ] = KEY_0, - [ 0x29 ] = KEY_1, - [ 0x2d ] = KEY_2, - [ 0x2b ] = KEY_3, - [ 0x09 ] = KEY_4, - [ 0x0d ] = KEY_5, - [ 0x0b ] = KEY_6, - [ 0x31 ] = KEY_7, - [ 0x35 ] = KEY_8, - [ 0x33 ] = KEY_9, - - [ 0x3e ] = KEY_RADIO, /* radio */ - [ 0x03 ] = KEY_MENU, /* dvd/menu */ - [ 0x2a ] = KEY_VOLUMEUP, - [ 0x19 ] = KEY_VOLUMEDOWN, - [ 0x37 ] = KEY_UP, - [ 0x3b ] = KEY_DOWN, - [ 0x27 ] = KEY_LEFT, - [ 0x2f ] = KEY_RIGHT, - [ 0x25 ] = KEY_VIDEO, /* video */ - [ 0x39 ] = KEY_AUDIO, /* music */ - - [ 0x21 ] = KEY_TV, /* tv */ - [ 0x1d ] = KEY_EXIT, /* back */ - [ 0x0a ] = KEY_CHANNELUP, /* channel / program + */ - [ 0x1b ] = KEY_CHANNELDOWN, /* channel / program - */ - [ 0x1a ] = KEY_ENTER, /* enter */ - - [ 0x06 ] = KEY_PAUSE, /* play/pause */ - [ 0x1e ] = KEY_PREVIOUS, /* rew */ - [ 0x26 ] = KEY_NEXT, /* forward */ - [ 0x0e ] = KEY_REWIND, /* backward << */ - [ 0x3a ] = KEY_FASTFORWARD, /* forward >> */ - [ 0x36 ] = KEY_STOP, - [ 0x2e ] = KEY_RECORD, /* recording */ - [ 0x16 ] = KEY_POWER, /* the button that reads "close" */ - - [ 0x11 ] = KEY_ZOOM, /* full screen */ - [ 0x13 ] = KEY_MACRO, /* recall */ - [ 0x23 ] = KEY_HOME, /* home */ - [ 0x05 ] = KEY_PVR, /* picture */ - [ 0x3d ] = KEY_MUTE, /* mute */ - [ 0x01 ] = KEY_DVD, /* dvd */ + [0x15] = KEY_0, + [0x29] = KEY_1, + [0x2d] = KEY_2, + [0x2b] = KEY_3, + [0x09] = KEY_4, + [0x0d] = KEY_5, + [0x0b] = KEY_6, + [0x31] = KEY_7, + [0x35] = KEY_8, + [0x33] = KEY_9, + + [0x3e] = KEY_RADIO, /* radio */ + [0x03] = KEY_MENU, /* dvd/menu */ + [0x2a] = KEY_VOLUMEUP, + [0x19] = KEY_VOLUMEDOWN, + [0x37] = KEY_UP, + [0x3b] = KEY_DOWN, + [0x27] = KEY_LEFT, + [0x2f] = KEY_RIGHT, + [0x25] = KEY_VIDEO, /* video */ + [0x39] = KEY_AUDIO, /* music */ + + [0x21] = KEY_TV, /* tv */ + [0x1d] = KEY_EXIT, /* back */ + [0x0a] = KEY_CHANNELUP, /* channel / program + */ + [0x1b] = KEY_CHANNELDOWN, /* channel / program - */ + [0x1a] = KEY_ENTER, /* enter */ + + [0x06] = KEY_PAUSE, /* play/pause */ + [0x1e] = KEY_PREVIOUS, /* rew */ + [0x26] = KEY_NEXT, /* forward */ + [0x0e] = KEY_REWIND, /* backward << */ + [0x3a] = KEY_FASTFORWARD, /* forward >> */ + [0x36] = KEY_STOP, + [0x2e] = KEY_RECORD, /* recording */ + [0x16] = KEY_POWER, /* the button that reads "close" */ + + [0x11] = KEY_ZOOM, /* full screen */ + [0x13] = KEY_MACRO, /* recall */ + [0x23] = KEY_HOME, /* home */ + [0x05] = KEY_PVR, /* picture */ + [0x3d] = KEY_MUTE, /* mute */ + [0x01] = KEY_DVD, /* dvd */ }; EXPORT_SYMBOL_GPL(ir_codes_asus_pc39); @@ -1973,78 +1973,78 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { /* Power button does nothing, neither in Windows app, although it sends data (used for BIOS wakeup?) */ - [ 0x0d ] = KEY_MUTE, - - [ 0x1e ] = KEY_TV, - [ 0x00 ] = KEY_VIDEO, - [ 0x01 ] = KEY_AUDIO, /* music */ - [ 0x02 ] = KEY_MHP, /* picture */ - - [ 0x1f ] = KEY_1, - [ 0x03 ] = KEY_2, - [ 0x04 ] = KEY_3, - [ 0x05 ] = KEY_4, - [ 0x1c ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x1d ] = KEY_9, - [ 0x0a ] = KEY_0, - - [ 0x09 ] = KEY_LIST, /* -/-- */ - [ 0x0b ] = KEY_LAST, /* recall */ - - [ 0x14 ] = KEY_HOME, /* win start menu */ - [ 0x15 ] = KEY_EXIT, /* exit */ + [0x0d] = KEY_MUTE, + + [0x1e] = KEY_TV, + [0x00] = KEY_VIDEO, + [0x01] = KEY_AUDIO, /* music */ + [0x02] = KEY_MHP, /* picture */ + + [0x1f] = KEY_1, + [0x03] = KEY_2, + [0x04] = KEY_3, + [0x05] = KEY_4, + [0x1c] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x1d] = KEY_9, + [0x0a] = KEY_0, + + [0x09] = KEY_LIST, /* -/-- */ + [0x0b] = KEY_LAST, /* recall */ + + [0x14] = KEY_HOME, /* win start menu */ + [0x15] = KEY_EXIT, /* exit */ #if 0 - [ 0x16 ] = KEY_CHANNELUP, /* UP */ - [ 0x12 ] = KEY_CHANNELDOWN, /* DOWN */ - [ 0x0c ] = KEY_VOLUMEUP, /* RIGHT */ - [ 0x17 ] = KEY_VOLUMEDOWN, /* LEFT */ + [0x16] = KEY_CHANNELUP, /* UP */ + [0x12] = KEY_CHANNELDOWN, /* DOWN */ + [0x0c] = KEY_VOLUMEUP, /* RIGHT */ + [0x17] = KEY_VOLUMEDOWN, /* LEFT */ #else - [ 0x16 ] = KEY_UP, - [ 0x12 ] = KEY_DOWN, - [ 0x0c ] = KEY_RIGHT, - [ 0x17 ] = KEY_LEFT, + [0x16] = KEY_UP, + [0x12] = KEY_DOWN, + [0x0c] = KEY_RIGHT, + [0x17] = KEY_LEFT, #endif - [ 0x18 ] = KEY_ENTER, /* OK */ + [0x18] = KEY_ENTER, /* OK */ - [ 0x0e ] = KEY_ESC, - [ 0x13 ] = KEY_D, /* desktop */ - [ 0x11 ] = KEY_TAB, - [ 0x19 ] = KEY_SWITCHVIDEOMODE, /* switch */ + [0x0e] = KEY_ESC, + [0x13] = KEY_D, /* desktop */ + [0x11] = KEY_TAB, + [0x19] = KEY_SWITCHVIDEOMODE, /* switch */ - [ 0x1a ] = KEY_MENU, - [ 0x1b ] = KEY_ZOOM, /* fullscreen */ - [ 0x44 ] = KEY_TIME, /* time shift */ - [ 0x40 ] = KEY_MODE, /* source */ + [0x1a] = KEY_MENU, + [0x1b] = KEY_ZOOM, /* fullscreen */ + [0x44] = KEY_TIME, /* time shift */ + [0x40] = KEY_MODE, /* source */ - [ 0x5a ] = KEY_RECORD, - [ 0x42 ] = KEY_PLAY, /* play/pause */ - [ 0x45 ] = KEY_STOP, - [ 0x43 ] = KEY_CAMERA, /* camera icon */ + [0x5a] = KEY_RECORD, + [0x42] = KEY_PLAY, /* play/pause */ + [0x45] = KEY_STOP, + [0x43] = KEY_CAMERA, /* camera icon */ - [ 0x48 ] = KEY_REWIND, - [ 0x4a ] = KEY_FASTFORWARD, - [ 0x49 ] = KEY_PREVIOUS, - [ 0x4b ] = KEY_NEXT, + [0x48] = KEY_REWIND, + [0x4a] = KEY_FASTFORWARD, + [0x49] = KEY_PREVIOUS, + [0x4b] = KEY_NEXT, - [ 0x4c ] = KEY_FAVORITES, /* tv wall */ - [ 0x4d ] = KEY_SOUND, /* DVD sound */ - [ 0x4e ] = KEY_LANGUAGE, /* DVD lang */ - [ 0x4f ] = KEY_TEXT, /* DVD text */ + [0x4c] = KEY_FAVORITES, /* tv wall */ + [0x4d] = KEY_SOUND, /* DVD sound */ + [0x4e] = KEY_LANGUAGE, /* DVD lang */ + [0x4f] = KEY_TEXT, /* DVD text */ - [ 0x50 ] = KEY_SLEEP, /* shutdown */ - [ 0x51 ] = KEY_MODE, /* stereo > main */ - [ 0x52 ] = KEY_SELECT, /* stereo > sap */ - [ 0x53 ] = KEY_PROG1, /* teletext */ + [0x50] = KEY_SLEEP, /* shutdown */ + [0x51] = KEY_MODE, /* stereo > main */ + [0x52] = KEY_SELECT, /* stereo > sap */ + [0x53] = KEY_PROG1, /* teletext */ - [ 0x59 ] = KEY_RED, /* AP1 */ - [ 0x41 ] = KEY_GREEN, /* AP2 */ - [ 0x47 ] = KEY_YELLOW, /* AP3 */ - [ 0x57 ] = KEY_BLUE, /* AP4 */ + [0x59] = KEY_RED, /* AP1 */ + [0x41] = KEY_GREEN, /* AP2 */ + [0x47] = KEY_YELLOW, /* AP3 */ + [0x57] = KEY_BLUE, /* AP4 */ }; EXPORT_SYMBOL_GPL(ir_codes_encore_enltv); @@ -2102,45 +2102,45 @@ EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2); /* for the Technotrend 1500 bundled remotes (grey and black): */ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_POWER, - [ 0x02 ] = KEY_SHUFFLE, /* ? double-arrow key */ - [ 0x03 ] = KEY_1, - [ 0x04 ] = KEY_2, - [ 0x05 ] = KEY_3, - [ 0x06 ] = KEY_4, - [ 0x07 ] = KEY_5, - [ 0x08 ] = KEY_6, - [ 0x09 ] = KEY_7, - [ 0x0a ] = KEY_8, - [ 0x0b ] = KEY_9, - [ 0x0c ] = KEY_0, - [ 0x0d ] = KEY_UP, - [ 0x0e ] = KEY_LEFT, - [ 0x0f ] = KEY_OK, - [ 0x10 ] = KEY_RIGHT, - [ 0x11 ] = KEY_DOWN, - [ 0x12 ] = KEY_INFO, - [ 0x13 ] = KEY_EXIT, - [ 0x14 ] = KEY_RED, - [ 0x15 ] = KEY_GREEN, - [ 0x16 ] = KEY_YELLOW, - [ 0x17 ] = KEY_BLUE, - [ 0x18 ] = KEY_MUTE, - [ 0x19 ] = KEY_TEXT, - [ 0x1a ] = KEY_MODE, /* ? TV/Radio */ - [ 0x21 ] = KEY_OPTION, - [ 0x22 ] = KEY_EPG, - [ 0x23 ] = KEY_CHANNELUP, - [ 0x24 ] = KEY_CHANNELDOWN, - [ 0x25 ] = KEY_VOLUMEUP, - [ 0x26 ] = KEY_VOLUMEDOWN, - [ 0x27 ] = KEY_SETUP, - [ 0x3a ] = KEY_RECORD, /* these keys are only in the black remote */ - [ 0x3b ] = KEY_PLAY, - [ 0x3c ] = KEY_STOP, - [ 0x3d ] = KEY_REWIND, - [ 0x3e ] = KEY_PAUSE, - [ 0x3f ] = KEY_FORWARD, + [0x01] = KEY_POWER, + [0x02] = KEY_SHUFFLE, /* ? double-arrow key */ + [0x03] = KEY_1, + [0x04] = KEY_2, + [0x05] = KEY_3, + [0x06] = KEY_4, + [0x07] = KEY_5, + [0x08] = KEY_6, + [0x09] = KEY_7, + [0x0a] = KEY_8, + [0x0b] = KEY_9, + [0x0c] = KEY_0, + [0x0d] = KEY_UP, + [0x0e] = KEY_LEFT, + [0x0f] = KEY_OK, + [0x10] = KEY_RIGHT, + [0x11] = KEY_DOWN, + [0x12] = KEY_INFO, + [0x13] = KEY_EXIT, + [0x14] = KEY_RED, + [0x15] = KEY_GREEN, + [0x16] = KEY_YELLOW, + [0x17] = KEY_BLUE, + [0x18] = KEY_MUTE, + [0x19] = KEY_TEXT, + [0x1a] = KEY_MODE, /* ? TV/Radio */ + [0x21] = KEY_OPTION, + [0x22] = KEY_EPG, + [0x23] = KEY_CHANNELUP, + [0x24] = KEY_CHANNELDOWN, + [0x25] = KEY_VOLUMEUP, + [0x26] = KEY_VOLUMEDOWN, + [0x27] = KEY_SETUP, + [0x3a] = KEY_RECORD, /* these keys are only in the black remote */ + [0x3b] = KEY_PLAY, + [0x3c] = KEY_STOP, + [0x3d] = KEY_REWIND, + [0x3e] = KEY_PAUSE, + [0x3f] = KEY_FORWARD, }; EXPORT_SYMBOL_GPL(ir_codes_tt_1500); @@ -2148,60 +2148,60 @@ EXPORT_SYMBOL_GPL(ir_codes_tt_1500); /* DViCO FUSION HDTV MCE remote */ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = { - [ 0x0b ] = KEY_1, - [ 0x17 ] = KEY_2, - [ 0x1b ] = KEY_3, - [ 0x07 ] = KEY_4, - [ 0x50 ] = KEY_5, - [ 0x54 ] = KEY_6, - [ 0x48 ] = KEY_7, - [ 0x4c ] = KEY_8, - [ 0x58 ] = KEY_9, - [ 0x03 ] = KEY_0, - - [ 0x5e ] = KEY_OK, - [ 0x51 ] = KEY_UP, - [ 0x53 ] = KEY_DOWN, - [ 0x5b ] = KEY_LEFT, - [ 0x5f ] = KEY_RIGHT, - - [ 0x02 ] = KEY_TV, /* Labeled DTV on remote */ - [ 0x0e ] = KEY_MP3, - [ 0x1a ] = KEY_DVD, - [ 0x1e ] = KEY_FAVORITES, /* Labeled CPF on remote */ - [ 0x16 ] = KEY_SETUP, - [ 0x46 ] = KEY_POWER2, /* TV On/Off button on remote */ - [ 0x0a ] = KEY_EPG, /* Labeled Guide on remote */ - - [ 0x49 ] = KEY_BACK, - [ 0x59 ] = KEY_INFO, /* Labeled MORE on remote */ - [ 0x4d ] = KEY_MENU, /* Labeled DVDMENU on remote */ - [ 0x55 ] = KEY_CYCLEWINDOWS, /* Labeled ALT-TAB on remote */ - - [ 0x0f ] = KEY_PREVIOUSSONG, /* Labeled |<< REPLAY on remote */ - [ 0x12 ] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */ - [ 0x42 ] = KEY_ENTER, /* Labeled START with a green + [0x0b] = KEY_1, + [0x17] = KEY_2, + [0x1b] = KEY_3, + [0x07] = KEY_4, + [0x50] = KEY_5, + [0x54] = KEY_6, + [0x48] = KEY_7, + [0x4c] = KEY_8, + [0x58] = KEY_9, + [0x03] = KEY_0, + + [0x5e] = KEY_OK, + [0x51] = KEY_UP, + [0x53] = KEY_DOWN, + [0x5b] = KEY_LEFT, + [0x5f] = KEY_RIGHT, + + [0x02] = KEY_TV, /* Labeled DTV on remote */ + [0x0e] = KEY_MP3, + [0x1a] = KEY_DVD, + [0x1e] = KEY_FAVORITES, /* Labeled CPF on remote */ + [0x16] = KEY_SETUP, + [0x46] = KEY_POWER2, /* TV On/Off button on remote */ + [0x0a] = KEY_EPG, /* Labeled Guide on remote */ + + [0x49] = KEY_BACK, + [0x59] = KEY_INFO, /* Labeled MORE on remote */ + [0x4d] = KEY_MENU, /* Labeled DVDMENU on remote */ + [0x55] = KEY_CYCLEWINDOWS, /* Labeled ALT-TAB on remote */ + + [0x0f] = KEY_PREVIOUSSONG, /* Labeled |<< REPLAY on remote */ + [0x12] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */ + [0x42] = KEY_ENTER, /* Labeled START with a green * MS windows logo on remote */ - [ 0x15 ] = KEY_VOLUMEUP, - [ 0x05 ] = KEY_VOLUMEDOWN, - [ 0x11 ] = KEY_CHANNELUP, - [ 0x09 ] = KEY_CHANNELDOWN, - - [ 0x52 ] = KEY_CAMERA, - [ 0x5a ] = KEY_TUNER, - [ 0x19 ] = KEY_OPEN, - - [ 0x13 ] = KEY_MODE, /* 4:3 16:9 select */ - [ 0x1f ] = KEY_ZOOM, - - [ 0x43 ] = KEY_REWIND, - [ 0x47 ] = KEY_PLAYPAUSE, - [ 0x4f ] = KEY_FASTFORWARD, - [ 0x57 ] = KEY_MUTE, - [ 0x0d ] = KEY_STOP, - [ 0x01 ] = KEY_RECORD, - [ 0x4e ] = KEY_POWER, + [0x15] = KEY_VOLUMEUP, + [0x05] = KEY_VOLUMEDOWN, + [0x11] = KEY_CHANNELUP, + [0x09] = KEY_CHANNELDOWN, + + [0x52] = KEY_CAMERA, + [0x5a] = KEY_TUNER, + [0x19] = KEY_OPEN, + + [0x13] = KEY_MODE, /* 4:3 16:9 select */ + [0x1f] = KEY_ZOOM, + + [0x43] = KEY_REWIND, + [0x47] = KEY_PLAYPAUSE, + [0x4f] = KEY_FASTFORWARD, + [0x57] = KEY_MUTE, + [0x0d] = KEY_STOP, + [0x01] = KEY_RECORD, + [0x4e] = KEY_POWER, }; EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce); @@ -2257,8 +2257,8 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { /* 0x1c 0x12 * * TV/FM POWER * * */ - [ 0x1c ] = KEY_TUNER, /*XXX KEY_TV KEY_RADIO */ - [ 0x12 ] = KEY_POWER, + [0x1c] = KEY_TUNER, /*XXX KEY_TV KEY_RADIO */ + [0x12] = KEY_POWER, /* 0x01 0x02 0x03 * * 1 2 3 * @@ -2269,28 +2269,28 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * 0x07 0x08 0x09 * * 7 8 9 * * */ - [ 0x01 ] = KEY_1, - [ 0x02 ] = KEY_2, - [ 0x03 ] = KEY_3, - [ 0x04 ] = KEY_4, - [ 0x05 ] = KEY_5, - [ 0x06 ] = KEY_6, - [ 0x07 ] = KEY_7, - [ 0x08 ] = KEY_8, - [ 0x09 ] = KEY_9, + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, /* 0x0a 0x00 0x17 * * RECALL 0 MODE * * */ - [ 0x0a ] = KEY_AGAIN, - [ 0x00 ] = KEY_0, - [ 0x17 ] = KEY_MODE, + [0x0a] = KEY_AGAIN, + [0x00] = KEY_0, + [0x17] = KEY_MODE, /* 0x14 0x10 * * ASPECT FULLSCREEN * * */ - [ 0x14 ] = KEY_SCREEN, - [ 0x10 ] = KEY_ZOOM, + [0x14] = KEY_SCREEN, + [0x10] = KEY_ZOOM, /* 0x0b * * Up * @@ -2301,17 +2301,17 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [ 0x0b ] = KEY_CHANNELUP, /*XXX KEY_UP */ - [ 0x18 ] = KEY_VOLUMEDOWN, /*XXX KEY_LEFT */ - [ 0x16 ] = KEY_OK, /*XXX KEY_ENTER */ - [ 0x0c ] = KEY_VOLUMEUP, /*XXX KEY_RIGHT */ - [ 0x15 ] = KEY_CHANNELDOWN, /*XXX KEY_DOWN */ + [0x0b] = KEY_CHANNELUP, /*XXX KEY_UP */ + [0x18] = KEY_VOLUMEDOWN, /*XXX KEY_LEFT */ + [0x16] = KEY_OK, /*XXX KEY_ENTER */ + [0x0c] = KEY_VOLUMEUP, /*XXX KEY_RIGHT */ + [0x15] = KEY_CHANNELDOWN, /*XXX KEY_DOWN */ /* 0x11 0x0d * * MUTE INFO * * */ - [ 0x11 ] = KEY_MUTE, - [ 0x0d ] = KEY_INFO, + [0x11] = KEY_MUTE, + [0x0d] = KEY_INFO, /* 0x0f 0x1b 0x1a * * RECORD PLAY/PAUSE STOP * @@ -2320,26 +2320,26 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { *TELETEXT AUDIO SOURCE * * RED YELLOW * * */ - [ 0x0f ] = KEY_RECORD, - [ 0x1b ] = KEY_PLAYPAUSE, - [ 0x1a ] = KEY_STOP, - [ 0x0e ] = KEY_TEXT, - [ 0x1f ] = KEY_RED, /*XXX KEY_AUDIO */ - [ 0x1e ] = KEY_YELLOW, /*XXX KEY_SOURCE */ + [0x0f] = KEY_RECORD, + [0x1b] = KEY_PLAYPAUSE, + [0x1a] = KEY_STOP, + [0x0e] = KEY_TEXT, + [0x1f] = KEY_RED, /*XXX KEY_AUDIO */ + [0x1e] = KEY_YELLOW, /*XXX KEY_SOURCE */ /* 0x1d 0x13 0x19 * * SLEEP PREVIEW DVB * * GREEN BLUE * * */ - [ 0x1d ] = KEY_SLEEP, - [ 0x13 ] = KEY_GREEN, - [ 0x19 ] = KEY_BLUE, /*XXX KEY_SAT */ + [0x1d] = KEY_SLEEP, + [0x13] = KEY_GREEN, + [0x19] = KEY_BLUE, /*XXX KEY_SAT */ /* 0x58 0x5c * * FREEZE SNAPSHOT * * */ - [ 0x58 ] = KEY_SLOW, - [ 0x5c ] = KEY_SAVE, + [0x58] = KEY_SLOW, + [0x5c] = KEY_SAVE, }; -- cgit v1.2.3 From a7fe8361bede9ae74c6f658604bd8024cfb1295a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Aug 2009 09:50:21 -0300 Subject: Properly indent comments with tabs From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 758 ++++++++++++++++---------------- 1 file changed, 379 insertions(+), 379 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index cf9950bf3..37db62ea5 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -46,60 +46,60 @@ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { [0x08] = KEY_8, [0x09] = KEY_9, - [0x5c] = KEY_POWER, /* power */ - [0x20] = KEY_F, /* full screen */ - [0x0f] = KEY_BACKSPACE, /* recall */ - [0x1b] = KEY_ENTER, /* mute */ - [0x41] = KEY_RECORD, /* record */ - [0x43] = KEY_STOP, /* stop */ + [0x5c] = KEY_POWER, /* power */ + [0x20] = KEY_F, /* full screen */ + [0x0f] = KEY_BACKSPACE, /* recall */ + [0x1b] = KEY_ENTER, /* mute */ + [0x41] = KEY_RECORD, /* record */ + [0x43] = KEY_STOP, /* stop */ [0x16] = KEY_S, - [0x1a] = KEY_Q, /* off */ + [0x1a] = KEY_Q, /* off */ [0x2e] = KEY_RED, - [0x1f] = KEY_DOWN, /* channel - */ - [0x1c] = KEY_UP, /* channel + */ - [0x10] = KEY_LEFT, /* volume - */ - [0x1e] = KEY_RIGHT, /* volume + */ + [0x1f] = KEY_DOWN, /* channel - */ + [0x1c] = KEY_UP, /* channel + */ + [0x10] = KEY_LEFT, /* volume - */ + [0x1e] = KEY_RIGHT, /* volume + */ [0x14] = KEY_F1, }; EXPORT_SYMBOL_GPL(ir_codes_proteus_2309); /* Matt Jesson >' */ - [0x3a] = KEY_RECORD, /* 'capture' */ - [0x0a] = KEY_MUTE, /* 'mute' */ - [0x2c] = KEY_RECORD, /* 'record' */ - [0x1c] = KEY_PAUSE, /* 'pause' */ - [0x3c] = KEY_STOP, /* 'stop' */ - [0x0c] = KEY_PLAY, /* 'play' */ - [0x2e] = KEY_RED, /* 'red' */ - [0x01] = KEY_BLUE, /* 'blue' / 'cancel' */ - [0x0e] = KEY_YELLOW, /* 'yellow' / 'ok' */ - [0x21] = KEY_GREEN, /* 'green' */ - [0x11] = KEY_CHANNELDOWN, /* 'channel -' */ - [0x31] = KEY_CHANNELUP, /* 'channel +' */ - [0x1e] = KEY_VOLUMEDOWN, /* 'volume -' */ - [0x3e] = KEY_VOLUMEUP, /* 'volume +' */ + [0x28] = KEY_0, /* '0' / 'enter' */ + [0x22] = KEY_1, /* '1' */ + [0x12] = KEY_2, /* '2' / 'up arrow' */ + [0x32] = KEY_3, /* '3' */ + [0x24] = KEY_4, /* '4' / 'left arrow' */ + [0x14] = KEY_5, /* '5' */ + [0x34] = KEY_6, /* '6' / 'right arrow' */ + [0x26] = KEY_7, /* '7' */ + [0x16] = KEY_8, /* '8' / 'down arrow' */ + [0x36] = KEY_9, /* '9' */ + + [0x20] = KEY_LIST, /* 'source' */ + [0x10] = KEY_TEXT, /* 'teletext' */ + [0x00] = KEY_POWER, /* 'power' */ + [0x04] = KEY_AUDIO, /* 'audio' */ + [0x06] = KEY_ZOOM, /* 'full screen' */ + [0x18] = KEY_VIDEO, /* 'display' */ + [0x38] = KEY_SEARCH, /* 'loop' */ + [0x08] = KEY_INFO, /* 'preview' */ + [0x2a] = KEY_REWIND, /* 'backward <<' */ + [0x1a] = KEY_FASTFORWARD, /* 'forward >>' */ + [0x3a] = KEY_RECORD, /* 'capture' */ + [0x0a] = KEY_MUTE, /* 'mute' */ + [0x2c] = KEY_RECORD, /* 'record' */ + [0x1c] = KEY_PAUSE, /* 'pause' */ + [0x3c] = KEY_STOP, /* 'stop' */ + [0x0c] = KEY_PLAY, /* 'play' */ + [0x2e] = KEY_RED, /* 'red' */ + [0x01] = KEY_BLUE, /* 'blue' / 'cancel' */ + [0x0e] = KEY_YELLOW, /* 'yellow' / 'ok' */ + [0x21] = KEY_GREEN, /* 'green' */ + [0x11] = KEY_CHANNELDOWN, /* 'channel -' */ + [0x31] = KEY_CHANNELUP, /* 'channel +' */ + [0x1e] = KEY_VOLUMEDOWN, /* 'volume -' */ + [0x3e] = KEY_VOLUMEUP, /* 'volume +' */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); @@ -192,7 +192,7 @@ IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE] = { [0x27] = KEY_ANGLE, /* Size */ [0x28] = KEY_SELECT, /* Select */ [0x29] = KEY_BLUE, /* Blue/Picture */ - [0x2a] = KEY_BACKSPACE, /* Back */ + [0x2a] = KEY_BACKSPACE, /* Back */ [0x2b] = KEY_MEDIA, /* PIP (Picture-in-picture) */ [0x2c] = KEY_DOWN, [0x2e] = KEY_DOT, @@ -207,9 +207,9 @@ IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE] = { [0x3e] = KEY_OK, /* Ok */ [0x3f] = KEY_RIGHT, [0x40] = KEY_NEXT, /* Next */ - [0x41] = KEY_PREVIOUS, /* Previous */ + [0x41] = KEY_PREVIOUS, /* Previous */ [0x42] = KEY_CHANNELDOWN, /* Channel down */ - [0x43] = KEY_CHANNELUP /* Channel up */ + [0x43] = KEY_CHANNELUP, /* Channel up */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus); @@ -226,32 +226,32 @@ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { [0x08] = KEY_8, [0x09] = KEY_9, [0x00] = KEY_0, - [0x17] = KEY_LAST, /* +100 */ - [0x0a] = KEY_LIST, /* recall */ - - - [0x1c] = KEY_TUNER, /* TV/FM */ - [0x15] = KEY_SEARCH, /* scan */ - [0x12] = KEY_POWER, /* power */ - [0x1f] = KEY_VOLUMEDOWN, /* vol up */ - [0x1b] = KEY_VOLUMEUP, /* vol down */ - [0x1e] = KEY_CHANNELDOWN, /* chn up */ - [0x1a] = KEY_CHANNELUP, /* chn down */ - - [0x11] = KEY_VIDEO, /* video */ - [0x0f] = KEY_ZOOM, /* full screen */ - [0x13] = KEY_MUTE, /* mute/unmute */ - [0x10] = KEY_TEXT, /* min */ - - [0x0d] = KEY_STOP, /* freeze */ - [0x0e] = KEY_RECORD, /* record */ - [0x1d] = KEY_PLAYPAUSE, /* stop */ - [0x19] = KEY_PLAY, /* play */ - - [0x16] = KEY_GOTO, /* osd */ - [0x14] = KEY_REFRESH, /* default */ - [0x0c] = KEY_KPPLUS, /* fine tune >>>> */ - [0x18] = KEY_KPMINUS /* fine tune <<<< */ + [0x17] = KEY_LAST, /* +100 */ + [0x0a] = KEY_LIST, /* recall */ + + + [0x1c] = KEY_TUNER, /* TV/FM */ + [0x15] = KEY_SEARCH, /* scan */ + [0x12] = KEY_POWER, /* power */ + [0x1f] = KEY_VOLUMEDOWN, /* vol up */ + [0x1b] = KEY_VOLUMEUP, /* vol down */ + [0x1e] = KEY_CHANNELDOWN, /* chn up */ + [0x1a] = KEY_CHANNELUP, /* chn down */ + + [0x11] = KEY_VIDEO, /* video */ + [0x0f] = KEY_ZOOM, /* full screen */ + [0x13] = KEY_MUTE, /* mute/unmute */ + [0x10] = KEY_TEXT, /* min */ + + [0x0d] = KEY_STOP, /* freeze */ + [0x0e] = KEY_RECORD, /* record */ + [0x1d] = KEY_PLAYPAUSE, /* stop */ + [0x19] = KEY_PLAY, /* play */ + + [0x16] = KEY_GOTO, /* osd */ + [0x14] = KEY_REFRESH, /* default */ + [0x0c] = KEY_KPPLUS, /* fine tune >>>> */ + [0x18] = KEY_KPMINUS, /* fine tune <<<< */ }; EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); @@ -260,9 +260,9 @@ EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { - [0x1e] = KEY_POWER, /* power */ - [0x07] = KEY_MEDIA, /* source */ - [0x1c] = KEY_SEARCH, /* scan */ + [0x1e] = KEY_POWER, /* power */ + [0x07] = KEY_MEDIA, /* source */ + [0x1c] = KEY_SEARCH, /* scan */ #if 0 /* FIXME: duplicate keycodes? */ @@ -275,11 +275,11 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { * 6384fb for "Tune <" and "<<<", * 638cfb for "Tune >" and ">>>", regardless of the mask. */ - [0x17] = KEY_BACK, /* fm scan << */ - [0x1f] = KEY_FORWARD, /* fm scan >> */ + [0x17] = KEY_BACK, /* fm scan << */ + [0x1f] = KEY_FORWARD, /* fm scan >> */ - [0x04] = KEY_LEFT, /* fm tuning < */ - [0x0c] = KEY_RIGHT, /* fm tuning > */ + [0x04] = KEY_LEFT, /* fm tuning < */ + [0x0c] = KEY_RIGHT, /* fm tuning > */ /* * For now, these four keys are disabled. Pressing them will generate @@ -287,15 +287,15 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { */ #endif - [0x03] = KEY_TUNER, /* TV/FM */ + [0x03] = KEY_TUNER, /* TV/FM */ [0x00] = KEY_RECORD, [0x08] = KEY_STOP, [0x11] = KEY_PLAY, - [0x1a] = KEY_PLAYPAUSE, /* freeze */ - [0x19] = KEY_ZOOM, /* zoom */ - [0x0f] = KEY_TEXT, /* min */ + [0x1a] = KEY_PLAYPAUSE, /* freeze */ + [0x19] = KEY_ZOOM, /* zoom */ + [0x0f] = KEY_TEXT, /* min */ [0x01] = KEY_1, [0x0b] = KEY_2, @@ -307,21 +307,21 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { [0x0a] = KEY_8, [0x12] = KEY_9, [0x02] = KEY_0, - [0x10] = KEY_LAST, /* +100 */ - [0x13] = KEY_LIST, /* recall */ + [0x10] = KEY_LAST, /* +100 */ + [0x13] = KEY_LIST, /* recall */ - [0x1f] = KEY_CHANNELUP, /* chn down */ - [0x17] = KEY_CHANNELDOWN, /* chn up */ - [0x16] = KEY_VOLUMEUP, /* vol down */ - [0x14] = KEY_VOLUMEDOWN, /* vol up */ + [0x1f] = KEY_CHANNELUP, /* chn down */ + [0x17] = KEY_CHANNELDOWN, /* chn up */ + [0x16] = KEY_VOLUMEUP, /* vol down */ + [0x14] = KEY_VOLUMEDOWN, /* vol up */ - [0x04] = KEY_KPMINUS, /* <<< */ - [0x0e] = KEY_SETUP, /* function */ - [0x0c] = KEY_KPPLUS, /* >>> */ + [0x04] = KEY_KPMINUS, /* <<< */ + [0x0e] = KEY_SETUP, /* function */ + [0x0c] = KEY_KPPLUS, /* >>> */ - [0x0d] = KEY_GOTO, /* mts */ - [0x1d] = KEY_REFRESH, /* reset */ - [0x18] = KEY_MUTE /* mute/unmute */ + [0x0d] = KEY_GOTO, /* mts */ + [0x1d] = KEY_REFRESH, /* reset */ + [0x18] = KEY_MUTE, /* mute/unmute */ }; EXPORT_SYMBOL_GPL(ir_codes_pixelview); @@ -426,7 +426,7 @@ IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { [0x33] = KEY_F19, /* web */ [0x34] = KEY_EMAIL, [0x35] = KEY_PHONE, - [0x36] = KEY_PC + [0x36] = KEY_PC, }; EXPORT_SYMBOL_GPL(ir_codes_nebula); @@ -482,7 +482,7 @@ IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { [0x00] = KEY_POWER, /* Keys 0 to 9 */ - [0x44] = KEY_0, /* 10 */ + [0x44] = KEY_0, /* 10 */ [0x50] = KEY_1, [0x30] = KEY_2, [0x70] = KEY_3, @@ -653,53 +653,53 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = { << FUNC >> RESET */ - [0x01] = KEY_KP1, /* 1 */ - [0x0b] = KEY_KP2, /* 2 */ - [0x1b] = KEY_KP3, /* 3 */ - [0x05] = KEY_KP4, /* 4 */ - [0x09] = KEY_KP5, /* 5 */ - [0x15] = KEY_KP6, /* 6 */ - [0x06] = KEY_KP7, /* 7 */ - [0x0a] = KEY_KP8, /* 8 */ - [0x12] = KEY_KP9, /* 9 */ - [0x02] = KEY_KP0, /* 0 */ - [0x10] = KEY_KPPLUS, /* + */ - [0x13] = KEY_AGAIN, /* Recall */ - - [0x1e] = KEY_POWER, /* Power */ - [0x07] = KEY_TUNER, /* Source */ - [0x1c] = KEY_SEARCH, /* Scan */ - [0x18] = KEY_MUTE, /* Mute */ - - [0x03] = KEY_RADIO, /* TV/FM */ + [0x01] = KEY_KP1, /* 1 */ + [0x0b] = KEY_KP2, /* 2 */ + [0x1b] = KEY_KP3, /* 3 */ + [0x05] = KEY_KP4, /* 4 */ + [0x09] = KEY_KP5, /* 5 */ + [0x15] = KEY_KP6, /* 6 */ + [0x06] = KEY_KP7, /* 7 */ + [0x0a] = KEY_KP8, /* 8 */ + [0x12] = KEY_KP9, /* 9 */ + [0x02] = KEY_KP0, /* 0 */ + [0x10] = KEY_KPPLUS, /* + */ + [0x13] = KEY_AGAIN, /* Recall */ + + [0x1e] = KEY_POWER, /* Power */ + [0x07] = KEY_TUNER, /* Source */ + [0x1c] = KEY_SEARCH, /* Scan */ + [0x18] = KEY_MUTE, /* Mute */ + + [0x03] = KEY_RADIO, /* TV/FM */ /* The next four keys are duplicates that appear to send the same IR code as Ch+, Ch-, >>, and << . The raw code assigned to them is the actual code + 0x20 - they will never be detected as such unless some way is discovered to distinguish these buttons from those that have the same code. */ - [0x3f] = KEY_RIGHT, /* |> and Ch+ */ - [0x37] = KEY_LEFT, /* <| and Ch- */ - [0x2c] = KEY_UP, /* ^^Up and >> */ - [0x24] = KEY_DOWN, /* vvDn and << */ - - [0x00] = KEY_RECORD, /* Record */ - [0x08] = KEY_STOP, /* Stop */ - [0x11] = KEY_PLAY, /* Play */ - - [0x0f] = KEY_CLOSE, /* Minimize */ - [0x19] = KEY_ZOOM, /* Zoom */ - [0x1a] = KEY_SHUFFLE, /* Snapshot */ - [0x0d] = KEY_LANGUAGE, /* MTS */ - - [0x14] = KEY_VOLUMEDOWN, /* Vol- */ - [0x16] = KEY_VOLUMEUP, /* Vol+ */ - [0x17] = KEY_CHANNELDOWN, /* Ch- */ - [0x1f] = KEY_CHANNELUP, /* Ch+ */ - - [0x04] = KEY_REWIND, /* << */ - [0x0e] = KEY_MENU, /* Function */ - [0x0c] = KEY_FASTFORWARD, /* >> */ - [0x1d] = KEY_RESTART, /* Reset */ + [0x3f] = KEY_RIGHT, /* |> and Ch+ */ + [0x37] = KEY_LEFT, /* <| and Ch- */ + [0x2c] = KEY_UP, /* ^^Up and >> */ + [0x24] = KEY_DOWN, /* vvDn and << */ + + [0x00] = KEY_RECORD, /* Record */ + [0x08] = KEY_STOP, /* Stop */ + [0x11] = KEY_PLAY, /* Play */ + + [0x0f] = KEY_CLOSE, /* Minimize */ + [0x19] = KEY_ZOOM, /* Zoom */ + [0x1a] = KEY_SHUFFLE, /* Snapshot */ + [0x0d] = KEY_LANGUAGE, /* MTS */ + + [0x14] = KEY_VOLUMEDOWN,/* Vol- */ + [0x16] = KEY_VOLUMEUP, /* Vol+ */ + [0x17] = KEY_CHANNELDOWN,/* Ch- */ + [0x1f] = KEY_CHANNELUP, /* Ch+ */ + + [0x04] = KEY_REWIND, /* << */ + [0x0e] = KEY_MENU, /* Function */ + [0x0c] = KEY_FASTFORWARD,/* >> */ + [0x1d] = KEY_RESTART, /* Reset */ }; EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus); @@ -843,9 +843,9 @@ IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { [0x40] = KEY_REWIND, [0x12] = KEY_FASTFORWARD, [0x41] = KEY_PREVIOUSSONG, /* replay |< */ - [0x42] = KEY_NEXTSONG, /* skip >| */ + [0x42] = KEY_NEXTSONG, /* skip >| */ [0x54] = KEY_CAMERA, /* capture */ - [0x50] = KEY_LANGUAGE, /* sap */ + [0x50] = KEY_LANGUAGE, /* sap */ [0x47] = KEY_TV2, /* pip */ [0x4d] = KEY_SCREEN, [0x43] = KEY_SUBTITLE, @@ -853,7 +853,7 @@ IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { [0x49] = KEY_AUDIO, /* l/r */ [0x07] = KEY_SLEEP, [0x08] = KEY_VIDEO, /* a/v */ - [0x0e] = KEY_PREVIOUS, /* recall */ + [0x0e] = KEY_PREVIOUS, /* recall */ [0x45] = KEY_ZOOM, /* zoom + */ [0x46] = KEY_ANGLE, /* zoom - */ [0x56] = KEY_RED, @@ -962,24 +962,24 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { [0x0c] = KEY_8, [0x0d] = KEY_9, - [0x0e] = KEY_MODE, /* Air/Cable */ - [0x11] = KEY_VIDEO, /* Video */ - [0x15] = KEY_AUDIO, /* Audio */ - [0x00] = KEY_POWER, /* Power */ - [0x18] = KEY_TUNER, /* AV Source */ - [0x02] = KEY_ZOOM, /* Fullscreen */ - [0x1a] = KEY_LANGUAGE, /* Stereo */ - [0x1b] = KEY_MUTE, /* Mute */ - [0x14] = KEY_VOLUMEUP, /* Volume + */ - [0x17] = KEY_VOLUMEDOWN, /* Volume - */ - [0x12] = KEY_CHANNELUP, /* Channel + */ - [0x13] = KEY_CHANNELDOWN, /* Channel - */ - [0x06] = KEY_AGAIN, /* Recall */ - [0x10] = KEY_ENTER, /* Enter */ - - [0x19] = KEY_BACK, /* Rewind ( <<< ) */ - [0x1f] = KEY_FORWARD, /* Forward ( >>> ) */ - [0x0a] = KEY_ANGLE, /* (no label, may be used as the PAUSE button) */ + [0x0e] = KEY_MODE, /* Air/Cable */ + [0x11] = KEY_VIDEO, /* Video */ + [0x15] = KEY_AUDIO, /* Audio */ + [0x00] = KEY_POWER, /* Power */ + [0x18] = KEY_TUNER, /* AV Source */ + [0x02] = KEY_ZOOM, /* Fullscreen */ + [0x1a] = KEY_LANGUAGE, /* Stereo */ + [0x1b] = KEY_MUTE, /* Mute */ + [0x14] = KEY_VOLUMEUP, /* Volume + */ + [0x17] = KEY_VOLUMEDOWN,/* Volume - */ + [0x12] = KEY_CHANNELUP, /* Channel + */ + [0x13] = KEY_CHANNELDOWN,/* Channel - */ + [0x06] = KEY_AGAIN, /* Recall */ + [0x10] = KEY_ENTER, /* Enter */ + + [0x19] = KEY_BACK, /* Rewind ( <<< ) */ + [0x1f] = KEY_FORWARD, /* Forward ( >>> ) */ + [0x0a] = KEY_ANGLE, /* no label, may be used as the PAUSE button */ }; EXPORT_SYMBOL_GPL(ir_codes_flyvideo); @@ -1038,15 +1038,15 @@ IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { [0x09] = KEY_9, [0x0a] = KEY_POWER, - [0x0b] = KEY_PROG1, /* app */ - [0x0c] = KEY_ZOOM, /* zoom/fullscreen */ - [0x0d] = KEY_CHANNELUP, /* channel */ - [0x0e] = KEY_CHANNELDOWN, /* channel- */ + [0x0b] = KEY_PROG1, /* app */ + [0x0c] = KEY_ZOOM, /* zoom/fullscreen */ + [0x0d] = KEY_CHANNELUP, /* channel */ + [0x0e] = KEY_CHANNELDOWN,/* channel- */ [0x0f] = KEY_VOLUMEUP, [0x10] = KEY_VOLUMEDOWN, - [0x11] = KEY_TUNER, /* AV */ - [0x12] = KEY_NUMLOCK, /* -/-- */ - [0x13] = KEY_AUDIO, /* audio */ + [0x11] = KEY_TUNER, /* AV */ + [0x12] = KEY_NUMLOCK, /* -/-- */ + [0x13] = KEY_AUDIO, /* audio */ [0x14] = KEY_MUTE, [0x15] = KEY_UP, [0x16] = KEY_DOWN, @@ -1054,7 +1054,7 @@ IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { [0x18] = KEY_RIGHT, [0x19] = BTN_LEFT, [0x1a] = BTN_RIGHT, - [0x1b] = KEY_WWW, /* text */ + [0x1b] = KEY_WWW, /* text */ [0x1c] = KEY_REWIND, [0x1d] = KEY_FORWARD, [0x1e] = KEY_RECORD, @@ -1071,38 +1071,38 @@ EXPORT_SYMBOL_GPL(ir_codes_cinergy); * updates from Job D. R. Borges */ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [0x12] = KEY_POWER, - [0x01] = KEY_TV, /* DVR */ - [0x15] = KEY_DVD, /* DVD */ - [0x17] = KEY_AUDIO, /* music */ - /* DVR mode / DVD mode / music mode */ - - [0x1b] = KEY_MUTE, /* mute */ - [0x02] = KEY_LANGUAGE, /* MTS/SAP / audio / autoseek */ - [0x1e] = KEY_SUBTITLE, /* closed captioning / subtitle / seek */ - [0x16] = KEY_ZOOM, /* full screen */ - [0x1c] = KEY_VIDEO, /* video source / eject / delall */ - [0x1d] = KEY_RESTART, /* playback / angle / del */ - [0x2f] = KEY_SEARCH, /* scan / menu / playlist */ - [0x30] = KEY_CHANNEL, /* CH surfing / bookmark / memo */ - - [0x31] = KEY_HELP, /* help */ - [0x32] = KEY_MODE, /* num/memo */ - [0x33] = KEY_ESC, /* cancel */ - - [0x0c] = KEY_UP, /* up */ - [0x10] = KEY_DOWN, /* down */ - [0x08] = KEY_LEFT, /* left */ - [0x04] = KEY_RIGHT, /* right */ - [0x03] = KEY_SELECT, /* select */ - - [0x1f] = KEY_REWIND, /* rewind */ - [0x20] = KEY_PLAYPAUSE, /* play/pause */ - [0x29] = KEY_FORWARD, /* forward */ - [0x14] = KEY_AGAIN, /* repeat */ - [0x2b] = KEY_RECORD, /* recording */ - [0x2c] = KEY_STOP, /* stop */ - [0x2d] = KEY_PLAY, /* play */ - [0x2e] = KEY_SHUFFLE, /* snapshot / shuffle */ + [0x01] = KEY_TV, /* DVR */ + [0x15] = KEY_DVD, /* DVD */ + [0x17] = KEY_AUDIO, /* music */ + /* DVR mode / DVD mode / music mode */ + + [0x1b] = KEY_MUTE, /* mute */ + [0x02] = KEY_LANGUAGE, /* MTS/SAP / audio / autoseek */ + [0x1e] = KEY_SUBTITLE, /* closed captioning / subtitle / seek */ + [0x16] = KEY_ZOOM, /* full screen */ + [0x1c] = KEY_VIDEO, /* video source / eject / delall */ + [0x1d] = KEY_RESTART, /* playback / angle / del */ + [0x2f] = KEY_SEARCH, /* scan / menu / playlist */ + [0x30] = KEY_CHANNEL, /* CH surfing / bookmark / memo */ + + [0x31] = KEY_HELP, /* help */ + [0x32] = KEY_MODE, /* num/memo */ + [0x33] = KEY_ESC, /* cancel */ + + [0x0c] = KEY_UP, /* up */ + [0x10] = KEY_DOWN, /* down */ + [0x08] = KEY_LEFT, /* left */ + [0x04] = KEY_RIGHT, /* right */ + [0x03] = KEY_SELECT, /* select */ + + [0x1f] = KEY_REWIND, /* rewind */ + [0x20] = KEY_PLAYPAUSE, /* play/pause */ + [0x29] = KEY_FORWARD, /* forward */ + [0x14] = KEY_AGAIN, /* repeat */ + [0x2b] = KEY_RECORD, /* recording */ + [0x2c] = KEY_STOP, /* stop */ + [0x2d] = KEY_PLAY, /* play */ + [0x2e] = KEY_SHUFFLE, /* snapshot / shuffle */ [0x00] = KEY_0, [0x05] = KEY_1, @@ -1117,11 +1117,11 @@ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [0x2a] = KEY_VOLUMEUP, [0x11] = KEY_VOLUMEDOWN, - [0x18] = KEY_CHANNELUP, /* CH.tracking up */ - [0x19] = KEY_CHANNELDOWN, /* CH.tracking down */ + [0x18] = KEY_CHANNELUP, /* CH.tracking up */ + [0x19] = KEY_CHANNELDOWN,/* CH.tracking down */ - [0x13] = KEY_ENTER, /* enter */ - [0x21] = KEY_DOT, /* . (decimal dot) */ + [0x13] = KEY_ENTER, /* enter */ + [0x21] = KEY_DOT, /* . (decimal dot) */ }; EXPORT_SYMBOL_GPL(ir_codes_eztv); @@ -1148,7 +1148,7 @@ IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [0x04] = KEY_AUDIO, /* AUDIO */ [0x0c] = KEY_ZOOM, /* FULL SCREEN */ - [0x12] = KEY_SUBTITLE, /* DISPLAY */ + [0x12] = KEY_SUBTITLE, /* DISPLAY */ [0x32] = KEY_REWIND, /* LOOP */ [0x02] = KEY_PRINT, /* PREVIEW */ @@ -1168,9 +1168,9 @@ IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [0x01] = KEY_BLUE, /* BLUE */ [0x1e] = KEY_VOLUMEDOWN, /* VOLUME- */ - [0x3e] = KEY_VOLUMEUP, /* VOLUME+ */ + [0x3e] = KEY_VOLUMEUP, /* VOLUME+ */ [0x11] = KEY_CHANNELDOWN, /* CHANNEL/PAGE- */ - [0x31] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ + [0x31] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ }; EXPORT_SYMBOL_GPL(ir_codes_avermedia); @@ -1297,7 +1297,7 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * SOURCE STEREO * * */ [0x11] = KEY_TV, /*XXX*/ - [0x0d] = KEY_MODE, /*XXX there's no KEY_STEREO */ + [0x0d] = KEY_MODE, /*XXX there's no KEY_STEREO */ /* 0x0f 0x1b 0x1a * * AUDIO Vol+ Chan+ * @@ -1309,7 +1309,7 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { [0x0f] = KEY_AUDIO, [0x1b] = KEY_VOLUMEUP, [0x1a] = KEY_CHANNELUP, - [0x0e] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ + [0x0e] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */ [0x1f] = KEY_VOLUMEDOWN, [0x1e] = KEY_CHANNELDOWN, @@ -1339,29 +1339,29 @@ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { [0x24] = KEY_7, [0x18] = KEY_8, [0x2b] = KEY_9, - [0x3b] = KEY_AGAIN, /* LOOP */ + [0x3b] = KEY_AGAIN, /* LOOP */ [0x06] = KEY_AUDIO, - [0x31] = KEY_PRINT, /* PREVIEW */ + [0x31] = KEY_PRINT, /* PREVIEW */ [0x3e] = KEY_VIDEO, [0x10] = KEY_CHANNELUP, [0x20] = KEY_CHANNELDOWN, [0x0c] = KEY_VOLUMEDOWN, [0x28] = KEY_VOLUMEUP, [0x08] = KEY_MUTE, - [0x26] = KEY_SEARCH, /*SCAN*/ - [0x3f] = KEY_SHUFFLE, /* SNAPSHOT */ + [0x26] = KEY_SEARCH, /*SCAN*/ + [0x3f] = KEY_SHUFFLE, /* SNAPSHOT */ [0x12] = KEY_RECORD, [0x32] = KEY_STOP, [0x3c] = KEY_PLAY, [0x1d] = KEY_REWIND, [0x2d] = KEY_PAUSE, [0x0d] = KEY_FORWARD, - [0x05] = KEY_ZOOM, /*FULL*/ + [0x05] = KEY_ZOOM, /*FULL*/ - [0x2a] = KEY_F21, /* LIVE TIMESHIFT */ - [0x0e] = KEY_F22, /* MIN TIMESHIFT */ - [0x1e] = KEY_F23, /* TIMESHIFT */ - [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ + [0x2a] = KEY_F21, /* LIVE TIMESHIFT */ + [0x0e] = KEY_F22, /* MIN TIMESHIFT */ + [0x1e] = KEY_F23, /* TIMESHIFT */ + [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ }; EXPORT_SYMBOL_GPL(ir_codes_gotview7135); @@ -1369,7 +1369,7 @@ EXPORT_SYMBOL_GPL(ir_codes_gotview7135); IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x03] = KEY_POWER, [0x6f] = KEY_MUTE, - [0x10] = KEY_BACKSPACE, /* Recall */ + [0x10] = KEY_BACKSPACE, /* Recall */ [0x11] = KEY_0, [0x04] = KEY_1, @@ -1381,7 +1381,7 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x0c] = KEY_7, [0x0d] = KEY_8, [0x0e] = KEY_9, - [0x12] = KEY_DOT, /* 100+ */ + [0x12] = KEY_DOT, /* 100+ */ [0x07] = KEY_VOLUMEUP, [0x0b] = KEY_VOLUMEDOWN, @@ -1393,25 +1393,25 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x13] = KEY_CHANNELDOWN, [0x48] = KEY_ZOOM, - [0x1b] = KEY_VIDEO, /* Video source */ + [0x1b] = KEY_VIDEO, /* Video source */ #if 0 - [0x1f] = KEY_S, /* Snapshot */ + [0x1f] = KEY_S, /* Snapshot */ #endif - [0x49] = KEY_LANGUAGE, /* MTS Select */ - [0x19] = KEY_SEARCH, /* Auto Scan */ + [0x49] = KEY_LANGUAGE, /* MTS Select */ + [0x19] = KEY_SEARCH, /* Auto Scan */ [0x4b] = KEY_RECORD, [0x46] = KEY_PLAY, - [0x45] = KEY_PAUSE, /* Pause */ + [0x45] = KEY_PAUSE, /* Pause */ [0x44] = KEY_STOP, #if 0 - [0x43] = KEY_T, /* Time Shift */ - [0x47] = KEY_Y, /* Time Shift OFF */ - [0x4a] = KEY_O, /* TOP */ - [0x17] = KEY_F, /* SURF CH */ + [0x43] = KEY_T, /* Time Shift */ + [0x47] = KEY_Y, /* Time Shift OFF */ + [0x4a] = KEY_O, /* TOP */ + [0x17] = KEY_F, /* SURF CH */ #endif - [0x40] = KEY_FORWARD, /* Forward ? */ - [0x42] = KEY_REWIND, /* Backward ? */ + [0x40] = KEY_FORWARD, /* Forward ? */ + [0x42] = KEY_REWIND, /* Backward ? */ }; @@ -1433,29 +1433,29 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [0x08] = KEY_8, [0x09] = KEY_9, - [0x0a] = KEY_AGAIN, /* Recall */ + [0x0a] = KEY_AGAIN, /* Recall */ [0x0b] = KEY_CHANNELUP, [0x0c] = KEY_VOLUMEUP, - [0x0d] = KEY_MODE, /* Stereo */ + [0x0d] = KEY_MODE, /* Stereo */ [0x0e] = KEY_STOP, [0x0f] = KEY_PREVIOUSSONG, [0x10] = KEY_ZOOM, - [0x11] = KEY_TUNER, /* Source */ + [0x11] = KEY_TUNER, /* Source */ [0x12] = KEY_POWER, [0x13] = KEY_MUTE, [0x15] = KEY_CHANNELDOWN, [0x18] = KEY_VOLUMEDOWN, - [0x19] = KEY_SHUFFLE, /* Snapshot */ + [0x19] = KEY_SHUFFLE, /* Snapshot */ [0x1a] = KEY_NEXTSONG, - [0x1b] = KEY_TEXT, /* Time Shift */ - [0x1c] = KEY_RADIO, /* FM Radio */ + [0x1b] = KEY_TEXT, /* Time Shift */ + [0x1c] = KEY_RADIO, /* FM Radio */ [0x1d] = KEY_RECORD, [0x1e] = KEY_PAUSE, /* additional codes for Kozumi's remote */ - [0x14] = KEY_INFO, /* OSD */ - [0x16] = KEY_OK, /* OK */ - [0x17] = KEY_DIGITS, /* Plus */ - [0x1f] = KEY_PLAY, /* Play */ + [0x14] = KEY_INFO, /* OSD */ + [0x16] = KEY_OK, /* OK */ + [0x17] = KEY_DIGITS, /* Plus */ + [0x1f] = KEY_PLAY, /* Play */ }; EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna); @@ -1489,14 +1489,14 @@ IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { [0x0b] = KEY_TV, /* AIR/CBL */ [0x11] = KEY_PC, /* PC/TV */ [0x17] = KEY_OK, /* CH RTN */ - [0x19] = KEY_MODE, /* FUNC */ - [0x0c] = KEY_SEARCH, /* AUTOSCAN */ + [0x19] = KEY_MODE, /* FUNC */ + [0x0c] = KEY_SEARCH, /* AUTOSCAN */ /* Not sure what to do with these ones! */ - [0x0f] = KEY_SELECT, /* SOURCE */ + [0x0f] = KEY_SELECT, /* SOURCE */ [0x0a] = KEY_KPPLUS, /* +100 */ [0x14] = KEY_EQUAL, /* SYNC */ - [0x1c] = KEY_MEDIA, /* PC/TV */ + [0x1c] = KEY_MEDIA, /* PC/TV */ }; EXPORT_SYMBOL_GPL(ir_codes_pv951); @@ -1526,10 +1526,10 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [0x12] = KEY_BRIGHTNESSUP, [0x13] = KEY_BRIGHTNESSDOWN, [0x1e] = KEY_SEARCH, /* search + */ - [0x20] = KEY_CHANNELUP, /* channel / program + */ + [0x20] = KEY_CHANNELUP, /* channel / program + */ [0x21] = KEY_CHANNELDOWN, /* channel / program - */ [0x22] = KEY_CHANNEL, /* alt / channel */ - [0x23] = KEY_LANGUAGE, /* 1st / 2nd language */ + [0x23] = KEY_LANGUAGE, /* 1st / 2nd language */ [0x26] = KEY_SLEEP, /* sleeptimer */ [0x2e] = KEY_MENU, /* 2nd controls (USA: menu) */ [0x30] = KEY_PAUSE, @@ -1538,41 +1538,41 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [0x35] = KEY_PLAY, [0x36] = KEY_STOP, [0x37] = KEY_RECORD, /* recording */ - [0x3c] = KEY_TEXT, /* teletext submode (Japan: 12) */ + [0x3c] = KEY_TEXT, /* teletext submode (Japan: 12) */ [0x3d] = KEY_SUSPEND, /* system standby */ #if 0 /* FIXME */ - [0x0a] = KEY_RESERVED, /* 1/2/3 digits (japan: 10) */ - [0x0e] = KEY_RESERVED, /* P.P. (personal preference) */ - [0x14] = KEY_RESERVED, /* colour saturation + */ - [0x15] = KEY_RESERVED, /* colour saturation - */ - [0x16] = KEY_RESERVED, /* bass + */ - [0x17] = KEY_RESERVED, /* bass - */ - [0x18] = KEY_RESERVED, /* treble + */ - [0x19] = KEY_RESERVED, /* treble - */ - [0x1a] = KEY_RESERVED, /* balance right */ - [0x1b] = KEY_RESERVED, /* balance left */ - [0x1c] = KEY_RESERVED, /* contrast + */ - [0x1d] = KEY_RESERVED, /* contrast - */ - [0x1f] = KEY_RESERVED, /* tint/hue + */ - [0x24] = KEY_RESERVED, /* spacial stereo on/off */ - [0x25] = KEY_RESERVED, /* mono / stereo (USA) */ - [0x27] = KEY_RESERVED, /* tint / hue - */ - [0x28] = KEY_RESERVED, /* RF switch/PIP select */ - [0x29] = KEY_RESERVED, /* vote */ - [0x2a] = KEY_RESERVED, /* timed page/channel clck */ - [0x2b] = KEY_RESERVED, /* increment (USA) */ - [0x2c] = KEY_RESERVED, /* decrement (USA) */ - [0x2d] = KEY_RESERVED, /* */ - [0x2f] = KEY_RESERVED, /* PIP shift */ - [0x31] = KEY_RESERVED, /* erase */ - [0x34] = KEY_RESERVED, /* wind */ - [0x38] = KEY_RESERVED, /* external 1 */ - [0x39] = KEY_RESERVED, /* external 2 */ - [0x3a] = KEY_RESERVED, /* PIP display mode */ - [0x3b] = KEY_RESERVED, /* view data mode / advance */ - [0x3e] = KEY_RESERVED, /* crispener on/off */ - [0x3f] = KEY_RESERVED, /* system select */ + [0x0a] = KEY_RESERVED, /* 1/2/3 digits (japan: 10) */ + [0x0e] = KEY_RESERVED, /* P.P. (personal preference) */ + [0x14] = KEY_RESERVED, /* colour saturation + */ + [0x15] = KEY_RESERVED, /* colour saturation - */ + [0x16] = KEY_RESERVED, /* bass + */ + [0x17] = KEY_RESERVED, /* bass - */ + [0x18] = KEY_RESERVED, /* treble + */ + [0x19] = KEY_RESERVED, /* treble - */ + [0x1a] = KEY_RESERVED, /* balance right */ + [0x1b] = KEY_RESERVED, /* balance left */ + [0x1c] = KEY_RESERVED, /* contrast + */ + [0x1d] = KEY_RESERVED, /* contrast - */ + [0x1f] = KEY_RESERVED, /* tint/hue + */ + [0x24] = KEY_RESERVED, /* spacial stereo on/off */ + [0x25] = KEY_RESERVED, /* mono / stereo (USA) */ + [0x27] = KEY_RESERVED, /* tint / hue - */ + [0x28] = KEY_RESERVED, /* RF switch/PIP select */ + [0x29] = KEY_RESERVED, /* vote */ + [0x2a] = KEY_RESERVED, /* timed page/channel clck */ + [0x2b] = KEY_RESERVED, /* increment (USA) */ + [0x2c] = KEY_RESERVED, /* decrement (USA) */ + [0x2d] = KEY_RESERVED, /* */ + [0x2f] = KEY_RESERVED, /* PIP shift */ + [0x31] = KEY_RESERVED, /* erase */ + [0x34] = KEY_RESERVED, /* wind */ + [0x38] = KEY_RESERVED, /* external 1 */ + [0x39] = KEY_RESERVED, /* external 2 */ + [0x3a] = KEY_RESERVED, /* PIP display mode */ + [0x3b] = KEY_RESERVED, /* view data mode / advance */ + [0x3e] = KEY_RESERVED, /* crispener on/off */ + [0x3f] = KEY_RESERVED, /* system select */ #endif }; @@ -1593,10 +1593,10 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [0x0f] = KEY_9, [0x00] = KEY_POWER, - [0x1b] = KEY_AUDIO, /* Audio Source */ + [0x1b] = KEY_AUDIO, /* Audio Source */ [0x02] = KEY_TUNER, /* TV/FM, not on Y0400052 */ - [0x1e] = KEY_VIDEO, /* Video Source */ - [0x16] = KEY_INFO, /* Display information */ + [0x1e] = KEY_VIDEO, /* Video Source */ + [0x16] = KEY_INFO, /* Display information */ [0x04] = KEY_VOLUMEUP, [0x08] = KEY_VOLUMEDOWN, [0x0c] = KEY_CHANNELUP, @@ -1604,7 +1604,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [0x03] = KEY_ZOOM, /* fullscreen */ [0x1f] = KEY_TEXT, /* closed caption/teletext */ [0x20] = KEY_SLEEP, - [0x29] = KEY_CLEAR, /* boss key */ + [0x29] = KEY_CLEAR, /* boss key */ [0x14] = KEY_MUTE, [0x2b] = KEY_RED, [0x2c] = KEY_GREEN, @@ -1612,32 +1612,32 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [0x2e] = KEY_BLUE, [0x18] = KEY_KPPLUS, /* fine tune + , not on Y040052 */ [0x19] = KEY_KPMINUS, /* fine tune - , not on Y040052 */ - [0x2a] = KEY_MEDIA, /* PIP (Picture in picture */ + [0x2a] = KEY_MEDIA, /* PIP (Picture in picture */ [0x21] = KEY_DOT, [0x13] = KEY_ENTER, - [0x11] = KEY_LAST, /* Recall (last channel */ + [0x11] = KEY_LAST, /* Recall (last channel */ [0x22] = KEY_PREVIOUS, [0x23] = KEY_PLAYPAUSE, [0x24] = KEY_NEXT, - [0x25] = KEY_ARCHIVE, /* Time Shifting */ + [0x25] = KEY_ARCHIVE, /* Time Shifting */ [0x26] = KEY_STOP, [0x27] = KEY_RECORD, - [0x28] = KEY_SAVE, /* Screenshot */ + [0x28] = KEY_SAVE, /* Screenshot */ [0x2f] = KEY_MENU, [0x30] = KEY_CANCEL, - [0x31] = KEY_CHANNEL, /* Channel Surf */ + [0x31] = KEY_CHANNEL, /* Channel Surf */ [0x32] = KEY_SUBTITLE, [0x33] = KEY_LANGUAGE, [0x34] = KEY_REWIND, [0x35] = KEY_FASTFORWARD, [0x36] = KEY_TV, - [0x37] = KEY_RADIO, /* FM */ + [0x37] = KEY_RADIO, /* FM */ [0x38] = KEY_DVD, - [0x3e] = KEY_F21, /* MCE +VOL, on Y04G0033 */ - [0x3a] = KEY_F22, /* MCE -VOL, on Y04G0033 */ - [0x3b] = KEY_F23, /* MCE +CH, on Y04G0033 */ - [0x3f] = KEY_F24 /* MCE -CH, on Y04G0033 */ + [0x3e] = KEY_F21, /* MCE +VOL, on Y04G0033 */ + [0x3a] = KEY_F22, /* MCE -VOL, on Y04G0033 */ + [0x3b] = KEY_F23, /* MCE +CH, on Y04G0033 */ + [0x3f] = KEY_F24 /* MCE -CH, on Y04G0033 */ }; EXPORT_SYMBOL_GPL(ir_codes_winfast); @@ -1718,15 +1718,15 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { [0x08] = KEY_8, [0x09] = KEY_9, - [0x0a] = KEY_TEXT, /* keypad asterisk as well */ + [0x0a] = KEY_TEXT, /* keypad asterisk as well */ [0x0b] = KEY_RED, /* red button */ [0x0c] = KEY_RADIO, [0x0d] = KEY_MENU, - [0x0e] = KEY_SUBTITLE, /* also the # key */ + [0x0e] = KEY_SUBTITLE, /* also the # key */ [0x0f] = KEY_MUTE, [0x10] = KEY_VOLUMEUP, [0x11] = KEY_VOLUMEDOWN, - [0x12] = KEY_PREVIOUS, /* previous channel */ + [0x12] = KEY_PREVIOUS, /* previous channel */ [0x14] = KEY_UP, [0x15] = KEY_DOWN, [0x16] = KEY_LEFT, @@ -1741,9 +1741,9 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { [0x1b] = KEY_EPG, /* Guide */ [0x1c] = KEY_TV, - [0x1e] = KEY_NEXTSONG, /* skip >| */ + [0x1e] = KEY_NEXTSONG, /* skip >| */ [0x1f] = KEY_EXIT, /* back/exit */ - [0x20] = KEY_CHANNELUP, /* channel / program + */ + [0x20] = KEY_CHANNELUP, /* channel / program + */ [0x21] = KEY_CHANNELDOWN, /* channel / program - */ [0x22] = KEY_CHANNEL, /* source (old black remote) */ [0x24] = KEY_PREVIOUSSONG, /* replay |< */ @@ -1766,7 +1766,7 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { - [0x1d] = KEY_SWITCHVIDEOMODE, /* switch inputs */ + [0x1d] = KEY_SWITCHVIDEOMODE, /* switch inputs */ [0x2a] = KEY_FRONT, [0x3e] = KEY_1, @@ -1779,7 +1779,7 @@ IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { [0x1a] = KEY_8, [0x1e] = KEY_9, [0x3a] = KEY_0, - [0x22] = KEY_NUMLOCK, /* -/-- */ + [0x22] = KEY_NUMLOCK, /* -/-- */ [0x20] = KEY_REFRESH, [0x03] = KEY_BRIGHTNESSDOWN, @@ -1800,8 +1800,8 @@ IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { [0x14] = KEY_REWIND, [0x33] = KEY_ZOOM, [0x32] = KEY_KEYBOARD, - [0x30] = KEY_GOTO, /* Pointing arrow */ - [0x36] = KEY_MACRO, /* Maximize/Minimize (yellow) */ + [0x30] = KEY_GOTO, /* Pointing arrow */ + [0x36] = KEY_MACRO, /* Maximize/Minimize (yellow) */ [0x0b] = KEY_RADIO, [0x10] = KEY_POWER, @@ -1825,34 +1825,34 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = { [0x28] = KEY_8, [0x29] = KEY_9, - [0x78] = KEY_TUNER, /* Video Source */ - [0x2c] = KEY_EXIT, /* Open/Close software */ - [0x2a] = KEY_SELECT, /* 2 Digit Select */ - [0x69] = KEY_AGAIN, /* Recall */ - - [0x32] = KEY_BRIGHTNESSUP, /* Brightness increase */ - [0x33] = KEY_BRIGHTNESSDOWN, /* Brightness decrease */ - [0x6b] = KEY_KPPLUS, /* (not named >>>>>) */ - [0x6c] = KEY_KPMINUS, /* (not named <<<<<) */ - - [0x2d] = KEY_MUTE, /* Mute */ - [0x30] = KEY_VOLUMEUP, /* Volume up */ - [0x31] = KEY_VOLUMEDOWN, /* Volume down */ - [0x60] = KEY_CHANNELUP, /* Channel up */ - [0x61] = KEY_CHANNELDOWN, /* Channel down */ - - [0x3f] = KEY_RECORD, /* Record */ - [0x37] = KEY_PLAY, /* Play */ - [0x36] = KEY_PAUSE, /* Pause */ - [0x2b] = KEY_STOP, /* Stop */ - [0x67] = KEY_FASTFORWARD, /* Foward */ - [0x66] = KEY_REWIND, /* Rewind */ - [0x3e] = KEY_SEARCH, /* Auto Scan */ - [0x2e] = KEY_CAMERA, /* Capture Video */ - [0x6d] = KEY_MENU, /* Show/Hide Control */ - [0x2f] = KEY_ZOOM, /* Full Screen */ - [0x34] = KEY_RADIO, /* FM */ - [0x65] = KEY_POWER, /* Computer power */ + [0x78] = KEY_TUNER, /* Video Source */ + [0x2c] = KEY_EXIT, /* Open/Close software */ + [0x2a] = KEY_SELECT, /* 2 Digit Select */ + [0x69] = KEY_AGAIN, /* Recall */ + + [0x32] = KEY_BRIGHTNESSUP, /* Brightness increase */ + [0x33] = KEY_BRIGHTNESSDOWN, /* Brightness decrease */ + [0x6b] = KEY_KPPLUS, /* (not named >>>>>) */ + [0x6c] = KEY_KPMINUS, /* (not named <<<<<) */ + + [0x2d] = KEY_MUTE, /* Mute */ + [0x30] = KEY_VOLUMEUP, /* Volume up */ + [0x31] = KEY_VOLUMEDOWN,/* Volume down */ + [0x60] = KEY_CHANNELUP, /* Channel up */ + [0x61] = KEY_CHANNELDOWN,/* Channel down */ + + [0x3f] = KEY_RECORD, /* Record */ + [0x37] = KEY_PLAY, /* Play */ + [0x36] = KEY_PAUSE, /* Pause */ + [0x2b] = KEY_STOP, /* Stop */ + [0x67] = KEY_FASTFORWARD,/* Foward */ + [0x66] = KEY_REWIND, /* Rewind */ + [0x3e] = KEY_SEARCH, /* Auto Scan */ + [0x2e] = KEY_CAMERA, /* Capture Video */ + [0x6d] = KEY_MENU, /* Show/Hide Control */ + [0x2f] = KEY_ZOOM, /* Full Screen */ + [0x34] = KEY_RADIO, /* FM */ + [0x65] = KEY_POWER, /* Computer power */ }; EXPORT_SYMBOL_GPL(ir_codes_norwood); @@ -1875,35 +1875,35 @@ IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = { [0x09] = KEY_9, [0x0a] = KEY_ENTER, [0x0b] = KEY_RED, - [0x0c] = KEY_POWER, /* RADIO on Hauppauge */ + [0x0c] = KEY_POWER, /* RADIO on Hauppauge */ [0x0d] = KEY_MUTE, - [0x0f] = KEY_A, /* TV on Hauppauge */ + [0x0f] = KEY_A, /* TV on Hauppauge */ [0x10] = KEY_VOLUMEUP, [0x11] = KEY_VOLUMEDOWN, [0x14] = KEY_B, [0x1c] = KEY_UP, [0x1d] = KEY_DOWN, - [0x1e] = KEY_OPTION, /* RESERVED on Hauppauge */ + [0x1e] = KEY_OPTION, /* RESERVED on Hauppauge */ [0x1f] = KEY_BREAK, [0x20] = KEY_CHANNELUP, [0x21] = KEY_CHANNELDOWN, - [0x22] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */ + [0x22] = KEY_PREVIOUS, /* Prev Ch on Zenith, SOURCE on Hauppauge */ [0x24] = KEY_RESTART, [0x25] = KEY_OK, - [0x26] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ - [0x28] = KEY_ENTER, /* VCR mode on Zenith */ + [0x26] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ + [0x28] = KEY_ENTER, /* VCR mode on Zenith */ [0x29] = KEY_PAUSE, [0x2b] = KEY_RIGHT, [0x2c] = KEY_LEFT, - [0x2e] = KEY_MENU, /* FULL SCREEN on Hauppauge */ + [0x2e] = KEY_MENU, /* FULL SCREEN on Hauppauge */ [0x30] = KEY_SLOW, - [0x31] = KEY_PREVIOUS, /* VCR mode on Zenith */ + [0x31] = KEY_PREVIOUS, /* VCR mode on Zenith */ [0x32] = KEY_REWIND, [0x34] = KEY_FASTFORWARD, [0x35] = KEY_PLAY, [0x36] = KEY_STOP, [0x37] = KEY_RECORD, - [0x38] = KEY_TUNER, /* TV/VCR on Zenith */ + [0x38] = KEY_TUNER, /* TV/VCR on Zenith */ [0x3a] = KEY_C, [0x3c] = KEY_EXIT, [0x3d] = KEY_POWER2, @@ -1943,12 +1943,12 @@ IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE] = { [0x21] = KEY_TV, /* tv */ [0x1d] = KEY_EXIT, /* back */ - [0x0a] = KEY_CHANNELUP, /* channel / program + */ + [0x0a] = KEY_CHANNELUP, /* channel / program + */ [0x1b] = KEY_CHANNELDOWN, /* channel / program - */ [0x1a] = KEY_ENTER, /* enter */ [0x06] = KEY_PAUSE, /* play/pause */ - [0x1e] = KEY_PREVIOUS, /* rew */ + [0x1e] = KEY_PREVIOUS, /* rew */ [0x26] = KEY_NEXT, /* forward */ [0x0e] = KEY_REWIND, /* backward << */ [0x3a] = KEY_FASTFORWARD, /* forward >> */ @@ -1991,15 +1991,15 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { [0x1d] = KEY_9, [0x0a] = KEY_0, - [0x09] = KEY_LIST, /* -/-- */ - [0x0b] = KEY_LAST, /* recall */ + [0x09] = KEY_LIST, /* -/-- */ + [0x0b] = KEY_LAST, /* recall */ [0x14] = KEY_HOME, /* win start menu */ [0x15] = KEY_EXIT, /* exit */ #if 0 - [0x16] = KEY_CHANNELUP, /* UP */ + [0x16] = KEY_CHANNELUP, /* UP */ [0x12] = KEY_CHANNELDOWN, /* DOWN */ - [0x0c] = KEY_VOLUMEUP, /* RIGHT */ + [0x0c] = KEY_VOLUMEUP, /* RIGHT */ [0x17] = KEY_VOLUMEDOWN, /* LEFT */ #else [0x16] = KEY_UP, @@ -2011,7 +2011,7 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { [0x18] = KEY_ENTER, /* OK */ [0x0e] = KEY_ESC, - [0x13] = KEY_D, /* desktop */ + [0x13] = KEY_D, /* desktop */ [0x11] = KEY_TAB, [0x19] = KEY_SWITCHVIDEOMODE, /* switch */ @@ -2030,9 +2030,9 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { [0x49] = KEY_PREVIOUS, [0x4b] = KEY_NEXT, - [0x4c] = KEY_FAVORITES, /* tv wall */ + [0x4c] = KEY_FAVORITES, /* tv wall */ [0x4d] = KEY_SOUND, /* DVD sound */ - [0x4e] = KEY_LANGUAGE, /* DVD lang */ + [0x4e] = KEY_LANGUAGE, /* DVD lang */ [0x4f] = KEY_TEXT, /* DVD text */ [0x50] = KEY_SLEEP, /* shutdown */ @@ -2089,9 +2089,9 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE] = { [0x72] = KEY_CHANNELDOWN, [0x41] = KEY_RECORD, - [0x51] = KEY_SHUFFLE, /* Snapshot */ - [0x75] = KEY_TIME, /* Timeshift */ - [0x71] = KEY_TV2, /* PIP */ + [0x51] = KEY_SHUFFLE, /* Snapshot */ + [0x75] = KEY_TIME, /* Timeshift */ + [0x71] = KEY_TV2, /* PIP */ [0x45] = KEY_REWIND, [0x6f] = KEY_PAUSE, @@ -2103,7 +2103,7 @@ EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2); /* for the Technotrend 1500 bundled remotes (grey and black): */ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { [0x01] = KEY_POWER, - [0x02] = KEY_SHUFFLE, /* ? double-arrow key */ + [0x02] = KEY_SHUFFLE, /* ? double-arrow key */ [0x03] = KEY_1, [0x04] = KEY_2, [0x05] = KEY_3, @@ -2127,7 +2127,7 @@ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { [0x17] = KEY_BLUE, [0x18] = KEY_MUTE, [0x19] = KEY_TEXT, - [0x1a] = KEY_MODE, /* ? TV/Radio */ + [0x1a] = KEY_MODE, /* ? TV/Radio */ [0x21] = KEY_OPTION, [0x22] = KEY_EPG, [0x23] = KEY_CHANNELUP, @@ -2135,7 +2135,7 @@ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { [0x25] = KEY_VOLUMEUP, [0x26] = KEY_VOLUMEDOWN, [0x27] = KEY_SETUP, - [0x3a] = KEY_RECORD, /* these keys are only in the black remote */ + [0x3a] = KEY_RECORD, /* these keys are only in the black remote */ [0x3b] = KEY_PLAY, [0x3c] = KEY_STOP, [0x3d] = KEY_REWIND, @@ -2168,7 +2168,7 @@ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = { [0x02] = KEY_TV, /* Labeled DTV on remote */ [0x0e] = KEY_MP3, [0x1a] = KEY_DVD, - [0x1e] = KEY_FAVORITES, /* Labeled CPF on remote */ + [0x1e] = KEY_FAVORITES, /* Labeled CPF on remote */ [0x16] = KEY_SETUP, [0x46] = KEY_POWER2, /* TV On/Off button on remote */ [0x0a] = KEY_EPG, /* Labeled Guide on remote */ @@ -2179,9 +2179,9 @@ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = { [0x55] = KEY_CYCLEWINDOWS, /* Labeled ALT-TAB on remote */ [0x0f] = KEY_PREVIOUSSONG, /* Labeled |<< REPLAY on remote */ - [0x12] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */ - [0x42] = KEY_ENTER, /* Labeled START with a green - * MS windows logo on remote */ + [0x12] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */ + [0x42] = KEY_ENTER, /* Labeled START with a green + MS windows logo on remote */ [0x15] = KEY_VOLUMEUP, [0x05] = KEY_VOLUMEDOWN, @@ -2257,7 +2257,7 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { /* 0x1c 0x12 * * TV/FM POWER * * */ - [0x1c] = KEY_TUNER, /*XXX KEY_TV KEY_RADIO */ + [0x1c] = KEY_TUNER, /* XXX KEY_TV / KEY_RADIO */ [0x12] = KEY_POWER, /* 0x01 0x02 0x03 * @@ -2301,11 +2301,11 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [0x0b] = KEY_CHANNELUP, /*XXX KEY_UP */ - [0x18] = KEY_VOLUMEDOWN, /*XXX KEY_LEFT */ - [0x16] = KEY_OK, /*XXX KEY_ENTER */ - [0x0c] = KEY_VOLUMEUP, /*XXX KEY_RIGHT */ - [0x15] = KEY_CHANNELDOWN, /*XXX KEY_DOWN */ + [0x0b] = KEY_CHANNELUP, /* XXX KEY_UP */ + [0x18] = KEY_VOLUMEDOWN, /* XXX KEY_LEFT */ + [0x16] = KEY_OK, /* XXX KEY_ENTER */ + [0x0c] = KEY_VOLUMEUP, /* XXX KEY_RIGHT */ + [0x15] = KEY_CHANNELDOWN, /* XXX KEY_DOWN */ /* 0x11 0x0d * * MUTE INFO * @@ -2324,8 +2324,8 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { [0x1b] = KEY_PLAYPAUSE, [0x1a] = KEY_STOP, [0x0e] = KEY_TEXT, - [0x1f] = KEY_RED, /*XXX KEY_AUDIO */ - [0x1e] = KEY_YELLOW, /*XXX KEY_SOURCE */ + [0x1f] = KEY_RED, /*XXX KEY_AUDIO */ + [0x1e] = KEY_YELLOW, /*XXX KEY_SOURCE */ /* 0x1d 0x13 0x19 * * SLEEP PREVIEW DVB * @@ -2333,7 +2333,7 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * */ [0x1d] = KEY_SLEEP, [0x13] = KEY_GREEN, - [0x19] = KEY_BLUE, /*XXX KEY_SAT */ + [0x19] = KEY_BLUE, /* XXX KEY_SAT */ /* 0x58 0x5c * * FREEZE SNAPSHOT * @@ -2361,7 +2361,7 @@ IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { [0x13] = KEY_MUTE, [0x11] = KEY_PROPS, - [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */ + [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */ [0x12] = KEY_POWER, /* 0x01 0x02 0x03 0x0D * @@ -2380,7 +2380,7 @@ IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { [0x04] = KEY_4, [0x05] = KEY_5, [0x06] = KEY_6, - [0x19] = KEY_BOOKMARKS, /* Snapshot key */ + [0x19] = KEY_BOOKMARKS, /* Snapshot key */ [0x07] = KEY_7, [0x08] = KEY_8, [0x09] = KEY_9, @@ -2446,7 +2446,7 @@ IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = { [0x04] = KEY_LIST, /* -/-- */ /* small arrows above numbers */ [0x1a] = KEY_NEXT, /* also Fast Forward */ - [0x0e] = KEY_PREVIOUS, /* also Rewind */ + [0x0e] = KEY_PREVIOUS, /* also Rewind */ /* these are in a rather non standard layout and have an alternate name written */ [0x1e] = KEY_UP, /* Video Setting */ @@ -2887,7 +2887,7 @@ IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = { [0x00] = KEY_TV, [0x01] = KEY_DVD, [0x04] = KEY_RECORD, - [0x05] = KEY_VIDEO, /* TV/Video */ + [0x05] = KEY_VIDEO, /* TV/Video */ [0x07] = KEY_STOP, [0x08] = KEY_PLAYPAUSE, [0x0a] = KEY_REWIND, @@ -2909,13 +2909,13 @@ IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = { [0x1f] = KEY_0, [0x21] = KEY_SLEEP, [0x24] = KEY_ZOOM, - [0x25] = KEY_LAST, /* Recall */ - [0x26] = KEY_SUBTITLE, /* CC */ - [0x27] = KEY_LANGUAGE, /* MTS */ - [0x29] = KEY_CHANNEL, /* SURF */ + [0x25] = KEY_LAST, /* Recall */ + [0x26] = KEY_SUBTITLE, /* CC */ + [0x27] = KEY_LANGUAGE, /* MTS */ + [0x29] = KEY_CHANNEL, /* SURF */ [0x2b] = KEY_A, [0x2c] = KEY_B, - [0x2f] = KEY_SHUFFLE, /* Snapshot */ + [0x2f] = KEY_SHUFFLE, /* Snapshot */ [0x23] = KEY_RADIO, [0x02] = KEY_PREVIOUSSONG, [0x06] = KEY_NEXTSONG, -- cgit v1.2.3 From b3662c3abe7526be7701c10712ac2ec2e231aca0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Aug 2009 09:54:44 -0300 Subject: Fix a number of EXPORT_SYMBOL warnings From: Mauro Carvalho Chehab Make Checkpatch tool happy: -:2349: WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable On all cases, it were just a blank line at the wrong place. Yet, fixing it is trivial Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 39 +-------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 37db62ea5..307b275f2 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -29,7 +29,6 @@ IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { [0x2a] = KEY_COFFEE, }; - EXPORT_SYMBOL_GPL(ir_codes_empty); /* Michal Majchrowicz */ @@ -61,8 +60,8 @@ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { [0x1e] = KEY_RIGHT, /* volume + */ [0x14] = KEY_F1, }; - EXPORT_SYMBOL_GPL(ir_codes_proteus_2309); + /* Matt Jesson */ @@ -253,7 +251,6 @@ IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { [0x0c] = KEY_KPPLUS, /* fine tune >>>> */ [0x18] = KEY_KPMINUS, /* fine tune <<<< */ }; - EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); /* ---------------------------------------------------------------------- */ @@ -323,7 +320,6 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { [0x1d] = KEY_REFRESH, /* reset */ [0x18] = KEY_MUTE, /* mute/unmute */ }; - EXPORT_SYMBOL_GPL(ir_codes_pixelview); /* @@ -428,7 +424,6 @@ IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { [0x35] = KEY_PHONE, [0x36] = KEY_PC, }; - EXPORT_SYMBOL_GPL(ir_codes_nebula); /* DigitalNow DNTV Live DVB-T Remote */ @@ -469,7 +464,6 @@ IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { [0x1e] = KEY_CHANNELDOWN, [0x1f] = KEY_VOLUMEDOWN, }; - EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t); /* ---------------------------------------------------------------------- */ @@ -522,7 +516,6 @@ IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { [0x61] = KEY_FASTFORWARD, /* forward >> */ [0x01] = KEY_NEXT, /* skip >| */ }; - EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e); /* ---------------------------------------------------------------------- */ @@ -576,7 +569,6 @@ IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = { [0x15] = KEY_VOLUMEUP, [0x1c] = KEY_VOLUMEDOWN, }; - EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci); /* ---------------------------------------------------------------------- */ @@ -611,7 +603,6 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { [0x1e] = KEY_CHANNELDOWN, [0x1f] = KEY_VOLUMEDOWN, }; - EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere); /* ---------------------------------------------------------------------- */ @@ -749,7 +740,6 @@ IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { [0x48] = KEY_STOP, [0x5c] = KEY_NEXT, }; - EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400); /* ---------------------------------------------------------------------- */ @@ -799,7 +789,6 @@ IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = { [0x13] = KEY_DOWN, [0x1b] = KEY_UP, }; - EXPORT_SYMBOL_GPL(ir_codes_avertv_303); /* ---------------------------------------------------------------------- */ @@ -861,7 +850,6 @@ IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { [0x5c] = KEY_YELLOW, [0x5d] = KEY_BLUE, }; - EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro); IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { @@ -894,7 +882,6 @@ IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { [0x1e] = KEY_STOP, [0x40] = KEY_ZOOM, }; - EXPORT_SYMBOL_GPL(ir_codes_em_terratec); IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = { @@ -947,7 +934,6 @@ IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = { [0x2a] = KEY_MEDIA, [0x18] = KEY_EPG, }; - EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey); IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { @@ -981,7 +967,6 @@ IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { [0x1f] = KEY_FORWARD, /* Forward ( >>> ) */ [0x0a] = KEY_ANGLE, /* no label, may be used as the PAUSE button */ }; - EXPORT_SYMBOL_GPL(ir_codes_flyvideo); IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { @@ -1022,7 +1007,6 @@ IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { [0x11] = KEY_STOP, /* Stop */ [0x0e] = KEY_NEXT, /* End >>| */ }; - EXPORT_SYMBOL_GPL(ir_codes_flydvb); IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { @@ -1064,7 +1048,6 @@ IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { [0x22] = KEY_PAUSE, [0x23] = KEY_STOP, }; - EXPORT_SYMBOL_GPL(ir_codes_cinergy); /* Alfons Geser @@ -1123,7 +1106,6 @@ IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { [0x13] = KEY_ENTER, /* enter */ [0x21] = KEY_DOT, /* . (decimal dot) */ }; - EXPORT_SYMBOL_GPL(ir_codes_eztv); /* Alex Hermann */ @@ -1172,7 +1154,6 @@ IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { [0x11] = KEY_CHANNELDOWN, /* CHANNEL/PAGE- */ [0x31] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ }; - EXPORT_SYMBOL_GPL(ir_codes_avermedia); IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE] = { @@ -1223,7 +1204,6 @@ IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE] = { [0x20] = KEY_LANGUAGE, [0x21] = KEY_SLEEP, }; - EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr); /* Michael Tokarev @@ -1321,7 +1301,6 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { /* 0x1d unused ? */ }; - EXPORT_SYMBOL_GPL(ir_codes_manli); /* Mike Baikov */ @@ -1363,7 +1342,6 @@ IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { [0x1e] = KEY_F23, /* TIMESHIFT */ [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ }; - EXPORT_SYMBOL_GPL(ir_codes_gotview7135); IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { @@ -1414,7 +1392,6 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x42] = KEY_REWIND, /* Backward ? */ }; - EXPORT_SYMBOL_GPL(ir_codes_purpletv); /* Mapping for the 28 key remote control as seen at @@ -1457,7 +1434,6 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [0x17] = KEY_DIGITS, /* Plus */ [0x1f] = KEY_PLAY, /* Play */ }; - EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna); /* Mark Phalan */ @@ -1498,7 +1474,6 @@ IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { [0x14] = KEY_EQUAL, /* SYNC */ [0x1c] = KEY_MEDIA, /* PC/TV */ }; - EXPORT_SYMBOL_GPL(ir_codes_pv951); /* generic RC5 keytable */ @@ -1575,7 +1550,6 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [0x3f] = KEY_RESERVED, /* system select */ #endif }; - EXPORT_SYMBOL_GPL(ir_codes_rc5_tv); /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ @@ -1639,7 +1613,6 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [0x3b] = KEY_F23, /* MCE +CH, on Y04G0033 */ [0x3f] = KEY_F24 /* MCE -CH, on Y04G0033 */ }; - EXPORT_SYMBOL_GPL(ir_codes_winfast); IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = { @@ -1699,7 +1672,6 @@ IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = { [0x74] = KEY_CHANNEL, [0x0a] = KEY_BACKSPACE, }; - EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color); /* Hauppauge: the newer, gray remotes (seems there are multiple @@ -1762,7 +1734,6 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { [0x3c] = KEY_ZOOM, /* full */ [0x3d] = KEY_POWER, /* system power (green button) */ }; - EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { @@ -1806,7 +1777,6 @@ IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { [0x10] = KEY_POWER, }; - EXPORT_SYMBOL_GPL(ir_codes_npgtech); /* Norwood Micro (non-Pro) TV Tuner @@ -1854,7 +1824,6 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = { [0x34] = KEY_RADIO, /* FM */ [0x65] = KEY_POWER, /* Computer power */ }; - EXPORT_SYMBOL_GPL(ir_codes_norwood); /* From reading the following remotes: @@ -1909,7 +1878,6 @@ IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = { [0x3d] = KEY_POWER2, [0x3e] = KEY_TUNER, }; - EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); /* @@ -1963,7 +1931,6 @@ IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE] = { [0x3d] = KEY_MUTE, /* mute */ [0x01] = KEY_DVD, /* dvd */ }; - EXPORT_SYMBOL_GPL(ir_codes_asus_pc39); @@ -2142,7 +2109,6 @@ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { [0x3e] = KEY_PAUSE, [0x3f] = KEY_FORWARD, }; - EXPORT_SYMBOL_GPL(ir_codes_tt_1500); /* DViCO FUSION HDTV MCE remote */ @@ -2203,7 +2169,6 @@ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = { [0x01] = KEY_RECORD, [0x4e] = KEY_POWER, }; - EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce); /* Pinnacle PCTV HD 800i mini remote */ @@ -2342,7 +2307,6 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { [0x5c] = KEY_SAVE, }; - EXPORT_SYMBOL_GPL(ir_codes_behold); /* Beholder Intl. Ltd. 2008 @@ -2764,7 +2728,6 @@ IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE] = { [0x16] = KEY_MUTE, [0x17] = KEY_VOLUMEDOWN, }; - EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600); /* DVBWorld remotes -- cgit v1.2.3 From 28eb88eba7aecf59b64289d178d22b255eac1a78 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 28 Aug 2009 04:12:06 -0300 Subject: keytable: Improve it to work with 16 bit keycodes From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/keytable.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/v4l2-apps/util/keytable.c b/v4l2-apps/util/keytable.c index 3b922f12b..4b39a43f0 100644 --- a/v4l2-apps/util/keytable.c +++ b/v4l2-apps/util/keytable.c @@ -1,6 +1,6 @@ /* keytable.c - This program allows checking/replacing keys at IR - Copyright (C) 2006 Mauro Carvalho Chehab + Copyright (C) 2006-2009 Mauro Carvalho Chehab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,7 +29,7 @@ void prtcode (int *codes) for (p=keynames;p->name!=NULL;p++) { if (p->value == (unsigned)codes[1]) { - printf("scancode %d = %s (0x%02x)\n", codes[0], p->name, codes[1]); + printf("scancode 0x%04x = %s (0x%02x)\n", codes[0], p->name, codes[1]); return; } } @@ -55,7 +55,7 @@ int parse_code(char *string) int main (int argc, char *argv[]) { int fd; - unsigned int i; + unsigned int i, j; int codes[2]; if (argc<2 || argc>4) { @@ -104,10 +104,12 @@ int main (int argc, char *argv[]) } /* Clears old table */ - for (i=0;i<256;i++) { - codes[0] = i; - codes[1] = 0; - ioctl(fd, EVIOCSKEYCODE, codes); + for (j = 0; j < 256; j++) { + for (i = 0; i < 256; i++) { + codes[0] = (j << 8) | i; + codes[1] = KEY_UNKNOWN; + ioctl(fd, EVIOCSKEYCODE, codes); + } } while (fgets(s,sizeof(s),fin)) { @@ -116,14 +118,21 @@ int main (int argc, char *argv[]) perror ("parsing input file scancode"); return -1; } + if (!strcasecmp(scancode, "scancode")) { + scancode = strtok(NULL,"\n\t =:"); + if (!scancode) { + perror ("parsing input file scancode"); + return -1; + } + } - keycode=strtok(NULL,"\n\t "); + keycode=strtok(NULL,"\n\t =:("); if (!keycode) { perror ("parsing input file keycode"); return -1; } - // printf ("parsing %s=%s:",scancode,keycode); + // printf ("parsing %s=%s:", scancode, keycode); value=parse_code(keycode); // printf ("\tvalue=%d\n",value); @@ -136,6 +145,7 @@ int main (int argc, char *argv[]) codes [0] = (unsigned) strtol(scancode, NULL, 0); codes [1] = (unsigned) value; + // printf("\t%04x=%04x\n",codes[0], codes[1]); if(ioctl(fd, EVIOCSKEYCODE, codes)) perror ("EVIOCSKEYCODE"); @@ -146,12 +156,13 @@ int main (int argc, char *argv[]) } /* Get scancode table */ - for (i=0;i<256;i++) { - codes[0] = i; - if(ioctl(fd, EVIOCGKEYCODE, codes)==0) - prtcode(codes); + for (j = 0; j < 256; j++) { + for (i = 0; i < 256; i++) { + codes[0] = (j << 8) | i; + if(ioctl(fd, EVIOCGKEYCODE, codes)==0) + prtcode(codes); + } } - return 0; } -- cgit v1.2.3 From 99451276a3fae1aa2b2cfd7ea23a702627df4242 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 08:37:58 -0300 Subject: ir-keymaps: replace KEY_KP[0-9] to KEY_[0-9] From: Mauro Carvalho Chehab This is needed to match the standard mapping defined at: http://linuxtv.org/wiki/index.php/Remote_Controllers#Remote_Controllers Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 307b275f2..35d35e872 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -644,16 +644,16 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = { << FUNC >> RESET */ - [0x01] = KEY_KP1, /* 1 */ - [0x0b] = KEY_KP2, /* 2 */ - [0x1b] = KEY_KP3, /* 3 */ - [0x05] = KEY_KP4, /* 4 */ - [0x09] = KEY_KP5, /* 5 */ - [0x15] = KEY_KP6, /* 6 */ - [0x06] = KEY_KP7, /* 7 */ - [0x0a] = KEY_KP8, /* 8 */ - [0x12] = KEY_KP9, /* 9 */ - [0x02] = KEY_KP0, /* 0 */ + [0x01] = KEY_1, /* 1 */ + [0x0b] = KEY_2, /* 2 */ + [0x1b] = KEY_3, /* 3 */ + [0x05] = KEY_4, /* 4 */ + [0x09] = KEY_5, /* 5 */ + [0x15] = KEY_6, /* 6 */ + [0x06] = KEY_7, /* 7 */ + [0x0a] = KEY_8, /* 8 */ + [0x12] = KEY_9, /* 9 */ + [0x02] = KEY_0, /* 0 */ [0x10] = KEY_KPPLUS, /* + */ [0x13] = KEY_AGAIN, /* Recall */ -- cgit v1.2.3 From 2decedc3e9cf2bfc4220e752cf3b56e1a6314629 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 08:43:20 -0300 Subject: ir-keymaps: add a link to the IR standard layout page From: Mauro Carvalho Chehab While we're still discussing it, let's point to the wiki page. In the future, this should be added at V4L2 API spec DocBooks. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 35d35e872..1f2ead284 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -1,8 +1,6 @@ /* - - - Keytables for supported remote controls. This file is part of - video4linux. + Keytables for supported remote controls, used on drivers/media + devices. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +15,13 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + * NOTICE FOR DEVELOPERS: + * The IR mappings should be as close as possible to what's + * specified at: + * http://linuxtv.org/wiki/index.php/Remote_Controllers */ #include -- cgit v1.2.3 From f517214d8e0dc0bfabeb958ffd7540e51ab383d0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 09:01:54 -0300 Subject: ir-keymaps: Replace most KEY_[A-Z] to the proper definitions From: Mauro Carvalho Chehab There are several IR's that were using IR to type a letter that it is known by some random application. Instead, the better is to use the standard definitions found at: http://linuxtv.org/wiki/index.php/Remote_Controllers And, if needed, submit a patch for the application to understand the media keys. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 62 ++++++++++++++++----------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 1f2ead284..c9f204048 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -50,13 +50,13 @@ IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { [0x09] = KEY_9, [0x5c] = KEY_POWER, /* power */ - [0x20] = KEY_F, /* full screen */ + [0x20] = KEY_ZOOM, /* full screen */ [0x0f] = KEY_BACKSPACE, /* recall */ [0x1b] = KEY_ENTER, /* mute */ [0x41] = KEY_RECORD, /* record */ [0x43] = KEY_STOP, /* stop */ [0x16] = KEY_S, - [0x1a] = KEY_Q, /* off */ + [0x1a] = KEY_POWER2, /* off */ [0x2e] = KEY_RED, [0x1f] = KEY_DOWN, /* channel - */ [0x1c] = KEY_UP, /* channel + */ @@ -454,7 +454,7 @@ IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { [0x10] = KEY_MUTE, [0x11] = KEY_REWIND, /* backward << */ [0x12] = KEY_POWER, - [0x13] = KEY_S, /* snap */ + [0x13] = KEY_CAMERA, /* snap */ [0x14] = KEY_AUDIO, /* stereo */ [0x15] = KEY_CLEAR, /* reset */ [0x16] = KEY_PLAY, @@ -505,13 +505,13 @@ IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { [0x74] = KEY_VOLUMEUP, [0x14] = KEY_MUTE, - [0x4c] = KEY_S, /* SVIDEO */ + [0x4c] = KEY_VCR, /* SVIDEO */ [0x2c] = KEY_CHANNELDOWN, [0x6c] = KEY_VOLUMEDOWN, [0x0c] = KEY_ZOOM, [0x5c] = KEY_PAUSE, - [0x3c] = KEY_C, /* || (red) */ + [0x3c] = KEY_RED, /* || (red) */ [0x7c] = KEY_RECORD, /* recording */ [0x1c] = KEY_STOP, @@ -594,7 +594,7 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { [0x0c] = KEY_MUTE, [0x0f] = KEY_SCREEN, /* Full Screen */ - [0x10] = KEY_F, /* Funtion */ + [0x10] = KEY_FN, /* Funtion */ [0x11] = KEY_T, /* Time shift */ [0x12] = KEY_POWER, [0x13] = KEY_MEDIA, /* MTS */ @@ -1376,9 +1376,7 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x48] = KEY_ZOOM, [0x1b] = KEY_VIDEO, /* Video source */ -#if 0 - [0x1f] = KEY_S, /* Snapshot */ -#endif + [0x1f] = KEY_CAMERA, /* Snapshot */ [0x49] = KEY_LANGUAGE, /* MTS Select */ [0x19] = KEY_SEARCH, /* Auto Scan */ @@ -1390,8 +1388,8 @@ IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { [0x43] = KEY_T, /* Time Shift */ [0x47] = KEY_Y, /* Time Shift OFF */ [0x4a] = KEY_O, /* TOP */ - [0x17] = KEY_F, /* SURF CH */ #endif + [0x17] = KEY_CHANNEL, /* SURF CH */ [0x40] = KEY_FORWARD, /* Forward ? */ [0x42] = KEY_REWIND, /* Backward ? */ @@ -1982,7 +1980,7 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { [0x18] = KEY_ENTER, /* OK */ [0x0e] = KEY_ESC, - [0x13] = KEY_D, /* desktop */ + [0x13] = KEY_CYCLEWINDOWS, /* desktop */ [0x11] = KEY_TAB, [0x19] = KEY_SWITCHVIDEOMODE, /* switch */ @@ -2738,8 +2736,8 @@ EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600); Igor M. Liplianin */ IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { - [0x0a] = KEY_Q, /*power*/ - [0x0c] = KEY_M, /*mute*/ + [0x0a] = KEY_POWER2, /* power */ + [0x0c] = KEY_MUTE, /* mute */ [0x11] = KEY_1, [0x12] = KEY_2, [0x13] = KEY_3, @@ -2750,25 +2748,25 @@ IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { [0x18] = KEY_8, [0x19] = KEY_9, [0x10] = KEY_0, - [0x1c] = KEY_PAGEUP, /*ch+*/ - [0x0f] = KEY_PAGEDOWN, /*ch-*/ - [0x1a] = KEY_O, /*vol+*/ - [0x0e] = KEY_Z, /*vol-*/ - [0x04] = KEY_R, /*rec*/ - [0x09] = KEY_D, /*fav*/ - [0x08] = KEY_BACKSPACE, /*rewind*/ - [0x07] = KEY_A, /*fast*/ - [0x0b] = KEY_P, /*pause*/ - [0x02] = KEY_ESC, /*cancel*/ - [0x03] = KEY_G, /*tab*/ - [0x00] = KEY_UP, /*up*/ - [0x1f] = KEY_ENTER, /*ok*/ - [0x01] = KEY_DOWN, /*down*/ - [0x05] = KEY_C, /*cap*/ - [0x06] = KEY_S, /*stop*/ - [0x40] = KEY_F, /*full*/ - [0x1e] = KEY_W, /*tvmode*/ - [0x1b] = KEY_B, /*recall*/ + [0x1c] = KEY_PAGEUP, /* ch+ */ + [0x0f] = KEY_PAGEDOWN, /* ch- */ + [0x1a] = KEY_VOLUMEUP, /* vol+ */ + [0x0e] = KEY_VOLUMEDOWN, /* vol- */ + [0x04] = KEY_RECORD, /* rec */ + [0x09] = KEY_CHANNEL, /* fav */ + [0x08] = KEY_BACKSPACE, /* rewind */ + [0x07] = KEY_FASTFORWARD, /* fast */ + [0x0b] = KEY_PAUSE, /* pause */ + [0x02] = KEY_ESC, /* cancel */ + [0x03] = KEY_TAB, /* tab */ + [0x00] = KEY_UP, /* up */ + [0x1f] = KEY_ENTER, /* ok */ + [0x01] = KEY_DOWN, /* down */ + [0x05] = KEY_RECORD, /* cap */ + [0x06] = KEY_STOP, /* stop */ + [0x40] = KEY_ZOOM, /* full */ + [0x1e] = KEY_TV, /* tvmode */ + [0x1b] = KEY_B, /* recall */ }; EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec); -- cgit v1.2.3 From c83c64ea49e5de51e8b0a6245c1f31c040d97e9d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sat, 29 Aug 2009 22:36:50 +0200 Subject: soc-camera: remove now unneeded subdevice group ID assignments From: Guennadi Liakhovetski Since we are not using v4l2_device_call_* calls any more, we don't need to initialise subdevice .grp_id any more. This also fixes compiler warnings on 64-bit platforms. Signed-off-by: Guennadi Liakhovetski --- drivers/media/video/soc_camera.c | 1 - drivers/media/video/soc_camera_platform.c | 1 - 2 files changed, 0 insertions(+), 2 deletions(-) --- linux/drivers/media/video/soc_camera.c | 1 - linux/drivers/media/video/soc_camera_platform.c | 1 - 2 files changed, 2 deletions(-) diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 55d4d9a22..cb7c9afd3 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -857,7 +857,6 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, goto ei2cnd; } - subdev->grp_id = (__u32)icd; client = subdev->priv; /* Use to_i2c_client(dev) to recover the i2c client */ diff --git a/linux/drivers/media/video/soc_camera_platform.c b/linux/drivers/media/video/soc_camera_platform.c index 1b6dd02a8..b6a575ce5 100644 --- a/linux/drivers/media/video/soc_camera_platform.c +++ b/linux/drivers/media/video/soc_camera_platform.c @@ -137,7 +137,6 @@ static int soc_camera_platform_probe(struct platform_device *pdev) v4l2_subdev_init(&priv->subdev, &platform_subdev_ops); v4l2_set_subdevdata(&priv->subdev, p); - priv->subdev.grp_id = (__u32)icd; strncpy(priv->subdev.name, dev_name(&pdev->dev), V4L2_SUBDEV_NAME_SIZE); ret = v4l2_device_register_subdev(&ici->v4l2_dev, &priv->subdev); -- cgit v1.2.3 From 24b6a4f985331c1ba25c91903a0bbef6ec979fa3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 1 Aug 2009 11:04:06 +0000 Subject: The current AVC debugging can clog the log down a lot since many From: Henrik Kurelid applications tend to check the signal strength very often. This patch enables users to select which AVC messages to log using a bitmask. In addition, it also enables the possibility to debug application PMTs sent to the driver. This will be usable since the CA support is still poorly tested for lots of CAMs and CA systems. Signed-off-by: Henrik Kurelid Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/firewire/firedtv-avc.c | 83 ++++++++++++++++++++------ 1 file changed, 66 insertions(+), 17 deletions(-) diff --git a/linux/drivers/media/dvb/firewire/firedtv-avc.c b/linux/drivers/media/dvb/firewire/firedtv-avc.c index a2041df5f..570bea0dd 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-avc.c +++ b/linux/drivers/media/dvb/firewire/firedtv-avc.c @@ -89,14 +89,31 @@ struct avc_response_frame { u8 operand[509]; }; -#define AVC_DEBUG_FCP_SUBACTIONS 1 -#define AVC_DEBUG_FCP_PAYLOADS 2 +#define AVC_DEBUG_READ_DESCRIPTOR 0x0001 +#define AVC_DEBUG_DSIT 0x0002 +#define AVC_DEBUG_DSD 0x0004 +#define AVC_DEBUG_REGISTER_REMOTE_CONTROL 0x0008 +#define AVC_DEBUG_LNB_CONTROL 0x0010 +#define AVC_DEBUG_TUNE_QPSK 0x0020 +#define AVC_DEBUG_TUNE_QPSK2 0x0040 +#define AVC_DEBUG_HOST2CA 0x0080 +#define AVC_DEBUG_CA2HOST 0x0100 +#define AVC_DEBUG_APPLICATION_PMT 0x4000 +#define AVC_DEBUG_FCP_PAYLOADS 0x8000 static int avc_debug; module_param_named(debug, avc_debug, int, 0644); -MODULE_PARM_DESC(debug, "Verbose logging (default = 0" - ", FCP subactions = " __stringify(AVC_DEBUG_FCP_SUBACTIONS) - ", FCP payloads = " __stringify(AVC_DEBUG_FCP_PAYLOADS) +MODULE_PARM_DESC(debug, "Verbose logging bitmask (none (default) = 0" + ", FCP subaction(READ DESCRIPTOR) = " __stringify(AVC_DEBUG_READ_DESCRIPTOR) + ", FCP subaction(DSIT) = " __stringify(AVC_DEBUG_DSIT) + ", FCP subaction(REGISTER_REMOTE_CONTROL) = " __stringify(AVC_DEBUG_REGISTER_REMOTE_CONTROL) + ", FCP subaction(LNB CONTROL) = " __stringify(AVC_DEBUG_LNB_CONTROL) + ", FCP subaction(TUNE QPSK) = " __stringify(AVC_DEBUG_TUNE_QPSK) + ", FCP subaction(TUNE QPSK2) = " __stringify(AVC_DEBUG_TUNE_QPSK2) + ", FCP subaction(HOST2CA) = " __stringify(AVC_DEBUG_HOST2CA) + ", FCP subaction(CA2HOST) = " __stringify(AVC_DEBUG_CA2HOST) + ", Application sent PMT = " __stringify(AVC_DEBUG_APPLICATION_PMT) + ", FCP payloads(for selected subactions) = " __stringify(AVC_DEBUG_FCP_PAYLOADS) ", or all = -1)"); static const char *debug_fcp_ctype(unsigned int ctype) @@ -142,29 +159,58 @@ static const char *debug_fcp_opcode(unsigned int opcode, return "Vendor"; } +static int debug_fcp_opcode_flag_set(unsigned int opcode, + const u8 *data, int length) +{ + switch (opcode) { + case AVC_OPCODE_VENDOR: break; + case AVC_OPCODE_READ_DESCRIPTOR: return avc_debug & AVC_DEBUG_READ_DESCRIPTOR; + case AVC_OPCODE_DSIT: return avc_debug & AVC_DEBUG_DSIT; + case AVC_OPCODE_DSD: return avc_debug & AVC_DEBUG_DSD; + default: return 1; + } + + if (length < 7 || + data[3] != SFE_VENDOR_DE_COMPANYID_0 || + data[4] != SFE_VENDOR_DE_COMPANYID_1 || + data[5] != SFE_VENDOR_DE_COMPANYID_2) + return 1; + + switch (data[6]) { + case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return avc_debug & AVC_DEBUG_REGISTER_REMOTE_CONTROL; + case SFE_VENDOR_OPCODE_LNB_CONTROL: return avc_debug & AVC_DEBUG_LNB_CONTROL; + case SFE_VENDOR_OPCODE_TUNE_QPSK: return avc_debug & AVC_DEBUG_TUNE_QPSK; + case SFE_VENDOR_OPCODE_TUNE_QPSK2: return avc_debug & AVC_DEBUG_TUNE_QPSK2; + case SFE_VENDOR_OPCODE_HOST2CA: return avc_debug & AVC_DEBUG_HOST2CA; + case SFE_VENDOR_OPCODE_CA2HOST: return avc_debug & AVC_DEBUG_CA2HOST; + } + return 1; +} + static void debug_fcp(const u8 *data, int length) { unsigned int subunit_type, subunit_id, op; const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> "; - if (avc_debug & AVC_DEBUG_FCP_SUBACTIONS) { - subunit_type = data[1] >> 3; - subunit_id = data[1] & 7; - op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; + subunit_type = data[1] >> 3; + subunit_id = data[1] & 7; + op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; + if (debug_fcp_opcode_flag_set(op, data, length)) { printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n", prefix, subunit_type, subunit_id, length, debug_fcp_ctype(data[0]), debug_fcp_opcode(op, data, length)); + if (avc_debug & AVC_DEBUG_FCP_PAYLOADS) + print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, + 16, 1, data, length, false); } +} - if (avc_debug & AVC_DEBUG_FCP_PAYLOADS) -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22) - print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1, - data, length, false); -#else - print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1, - (void *)data, length, false); -#endif +static void debug_pmt(char *msg, int length) +{ + printk(KERN_INFO "APP PMT -> l=%d\n", length); + print_hex_dump(KERN_INFO, "APP PMT -> ", DUMP_PREFIX_NONE, + 16, 1, msg, length, false); } static int __avc_write(struct firedtv *fdtv, @@ -988,6 +1034,9 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) int es_info_length; int crc32_csum; + if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT)) + debug_pmt(msg, length); + memset(c, 0, sizeof(*c)); c->ctype = AVC_CTYPE_CONTROL; -- cgit v1.2.3 From 559336d7b9a068df9a2506a8f490ec04b31611cc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 1 Aug 2009 11:05:16 +0000 Subject: firedtv: combine some debug logging code From: Stefan Richter Shrinks source and kernel object size a bit. Signed-off-by: Stefan Richter Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/firewire/firedtv-avc.c | 109 +++++++++++-------------- 1 file changed, 49 insertions(+), 60 deletions(-) diff --git a/linux/drivers/media/dvb/firewire/firedtv-avc.c b/linux/drivers/media/dvb/firewire/firedtv-avc.c index 570bea0dd..d1b67fe0f 100644 --- a/linux/drivers/media/dvb/firewire/firedtv-avc.c +++ b/linux/drivers/media/dvb/firewire/firedtv-avc.c @@ -103,18 +103,19 @@ struct avc_response_frame { static int avc_debug; module_param_named(debug, avc_debug, int, 0644); -MODULE_PARM_DESC(debug, "Verbose logging bitmask (none (default) = 0" - ", FCP subaction(READ DESCRIPTOR) = " __stringify(AVC_DEBUG_READ_DESCRIPTOR) - ", FCP subaction(DSIT) = " __stringify(AVC_DEBUG_DSIT) - ", FCP subaction(REGISTER_REMOTE_CONTROL) = " __stringify(AVC_DEBUG_REGISTER_REMOTE_CONTROL) - ", FCP subaction(LNB CONTROL) = " __stringify(AVC_DEBUG_LNB_CONTROL) - ", FCP subaction(TUNE QPSK) = " __stringify(AVC_DEBUG_TUNE_QPSK) - ", FCP subaction(TUNE QPSK2) = " __stringify(AVC_DEBUG_TUNE_QPSK2) - ", FCP subaction(HOST2CA) = " __stringify(AVC_DEBUG_HOST2CA) - ", FCP subaction(CA2HOST) = " __stringify(AVC_DEBUG_CA2HOST) - ", Application sent PMT = " __stringify(AVC_DEBUG_APPLICATION_PMT) - ", FCP payloads(for selected subactions) = " __stringify(AVC_DEBUG_FCP_PAYLOADS) - ", or all = -1)"); +MODULE_PARM_DESC(debug, "Verbose logging (none = 0" + ", FCP subactions" + ": READ DESCRIPTOR = " __stringify(AVC_DEBUG_READ_DESCRIPTOR) + ", DSIT = " __stringify(AVC_DEBUG_DSIT) + ", REGISTER_REMOTE_CONTROL = " __stringify(AVC_DEBUG_REGISTER_REMOTE_CONTROL) + ", LNB CONTROL = " __stringify(AVC_DEBUG_LNB_CONTROL) + ", TUNE QPSK = " __stringify(AVC_DEBUG_TUNE_QPSK) + ", TUNE QPSK2 = " __stringify(AVC_DEBUG_TUNE_QPSK2) + ", HOST2CA = " __stringify(AVC_DEBUG_HOST2CA) + ", CA2HOST = " __stringify(AVC_DEBUG_CA2HOST) + "; Application sent PMT = " __stringify(AVC_DEBUG_APPLICATION_PMT) + ", FCP payloads = " __stringify(AVC_DEBUG_FCP_PAYLOADS) + ", or a combination, or all = -1)"); static const char *debug_fcp_ctype(unsigned int ctype) { @@ -135,71 +136,59 @@ static const char *debug_fcp_opcode(unsigned int opcode, const u8 *data, int length) { switch (opcode) { - case AVC_OPCODE_VENDOR: break; - case AVC_OPCODE_READ_DESCRIPTOR: return "ReadDescriptor"; - case AVC_OPCODE_DSIT: return "DirectSelectInfo.Type"; - case AVC_OPCODE_DSD: return "DirectSelectData"; - default: return "?"; - } - - if (length < 7 || - data[3] != SFE_VENDOR_DE_COMPANYID_0 || - data[4] != SFE_VENDOR_DE_COMPANYID_1 || - data[5] != SFE_VENDOR_DE_COMPANYID_2) - return "Vendor"; - - switch (data[6]) { - case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC"; - case SFE_VENDOR_OPCODE_LNB_CONTROL: return "LNBControl"; - case SFE_VENDOR_OPCODE_TUNE_QPSK: return "TuneQPSK"; - case SFE_VENDOR_OPCODE_TUNE_QPSK2: return "TuneQPSK2"; - case SFE_VENDOR_OPCODE_HOST2CA: return "Host2CA"; - case SFE_VENDOR_OPCODE_CA2HOST: return "CA2Host"; - } - return "Vendor"; -} - -static int debug_fcp_opcode_flag_set(unsigned int opcode, - const u8 *data, int length) -{ - switch (opcode) { - case AVC_OPCODE_VENDOR: break; - case AVC_OPCODE_READ_DESCRIPTOR: return avc_debug & AVC_DEBUG_READ_DESCRIPTOR; - case AVC_OPCODE_DSIT: return avc_debug & AVC_DEBUG_DSIT; - case AVC_OPCODE_DSD: return avc_debug & AVC_DEBUG_DSD; - default: return 1; + case AVC_OPCODE_VENDOR: + break; + case AVC_OPCODE_READ_DESCRIPTOR: + return avc_debug & AVC_DEBUG_READ_DESCRIPTOR ? + "ReadDescriptor" : NULL; + case AVC_OPCODE_DSIT: + return avc_debug & AVC_DEBUG_DSIT ? + "DirectSelectInfo.Type" : NULL; + case AVC_OPCODE_DSD: + return avc_debug & AVC_DEBUG_DSD ? "DirectSelectData" : NULL; + default: + return "Unknown"; } if (length < 7 || data[3] != SFE_VENDOR_DE_COMPANYID_0 || data[4] != SFE_VENDOR_DE_COMPANYID_1 || data[5] != SFE_VENDOR_DE_COMPANYID_2) - return 1; + return "Vendor/Unknown"; switch (data[6]) { - case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return avc_debug & AVC_DEBUG_REGISTER_REMOTE_CONTROL; - case SFE_VENDOR_OPCODE_LNB_CONTROL: return avc_debug & AVC_DEBUG_LNB_CONTROL; - case SFE_VENDOR_OPCODE_TUNE_QPSK: return avc_debug & AVC_DEBUG_TUNE_QPSK; - case SFE_VENDOR_OPCODE_TUNE_QPSK2: return avc_debug & AVC_DEBUG_TUNE_QPSK2; - case SFE_VENDOR_OPCODE_HOST2CA: return avc_debug & AVC_DEBUG_HOST2CA; - case SFE_VENDOR_OPCODE_CA2HOST: return avc_debug & AVC_DEBUG_CA2HOST; + case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: + return avc_debug & AVC_DEBUG_REGISTER_REMOTE_CONTROL ? + "RegisterRC" : NULL; + case SFE_VENDOR_OPCODE_LNB_CONTROL: + return avc_debug & AVC_DEBUG_LNB_CONTROL ? "LNBControl" : NULL; + case SFE_VENDOR_OPCODE_TUNE_QPSK: + return avc_debug & AVC_DEBUG_TUNE_QPSK ? "TuneQPSK" : NULL; + case SFE_VENDOR_OPCODE_TUNE_QPSK2: + return avc_debug & AVC_DEBUG_TUNE_QPSK2 ? "TuneQPSK2" : NULL; + case SFE_VENDOR_OPCODE_HOST2CA: + return avc_debug & AVC_DEBUG_HOST2CA ? "Host2CA" : NULL; + case SFE_VENDOR_OPCODE_CA2HOST: + return avc_debug & AVC_DEBUG_CA2HOST ? "CA2Host" : NULL; } - return 1; + return "Vendor/Unknown"; } static void debug_fcp(const u8 *data, int length) { - unsigned int subunit_type, subunit_id, op; - const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> "; + unsigned int subunit_type, subunit_id, opcode; + const char *op, *prefix; + prefix = data[0] > 7 ? "FCP <- " : "FCP -> "; subunit_type = data[1] >> 3; - subunit_id = data[1] & 7; - op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; - if (debug_fcp_opcode_flag_set(op, data, length)) { + subunit_id = data[1] & 7; + opcode = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; + op = debug_fcp_opcode(opcode, data, length); + + if (op) { printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n", prefix, subunit_type, subunit_id, length, - debug_fcp_ctype(data[0]), - debug_fcp_opcode(op, data, length)); + debug_fcp_ctype(data[0]), op); if (avc_debug & AVC_DEBUG_FCP_PAYLOADS) print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1, data, length, false); -- cgit v1.2.3 From e882a8f9d4352445264dd40b64a75eb9a0786ab5 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 3 Aug 2009 13:17:05 +0200 Subject: libv4l: fixup 320x240 output for pac7302 cameras From: Hans de Goede libv4l: fixup 320x240 output for pac7302 cameras Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 1 + v4l2-apps/libv4l/libv4lconvert/flip.c | 1 + 2 files changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index 9f170bdfd..25a7c22c9 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -2,6 +2,7 @@ libv4l-0.6.1 ------------ * Add more laptop models to the upside down devices table * Makefile changes to make life easier for the Debian package (Gregor Jasny) +* Bugfix: fixup 320x240 output for pac7302 cameras libv4l-0.6.0 ------------ diff --git a/v4l2-apps/libv4l/libv4lconvert/flip.c b/v4l2-apps/libv4l/libv4lconvert/flip.c index 8c4d8233c..732b49f59 100644 --- a/v4l2-apps/libv4l/libv4lconvert/flip.c +++ b/v4l2-apps/libv4l/libv4lconvert/flip.c @@ -219,6 +219,7 @@ void v4lconvert_rotate90(unsigned char *src, unsigned char *dest, fmt->fmt.pix.height); break; } + v4lconvert_fixup_fmt(fmt); } void v4lconvert_flip(unsigned char *src, unsigned char *dest, -- cgit v1.2.3 From e922843e4bdd6a2519d782016b36f1320e81ab30 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 4 Aug 2009 15:38:05 +1000 Subject: Support for Kaiser Baas ExpressCard Dual HD Tuner From: James A Webb The card is reported as YUAN High-Tech Development Co., Ltd STK7700D Priority: normal [mchehab@redhat.com: fix merge conflicts and properly name USB PID] Signed-off-by: James A Webb CC: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 7 ++++++- linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index 81cda8061..4de8f0248 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1502,6 +1502,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T3) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_T5) }, { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D) }, + { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D_2) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1629,7 +1630,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { } }, - .num_device_descs = 4, + .num_device_descs = 5, .devices = { { "Pinnacle PCTV 2000e", { &dib0700_usb_id_table[11], NULL }, @@ -1647,6 +1648,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { &dib0700_usb_id_table[14], NULL }, { NULL }, }, + { "YUAN High-Tech DiBcom STK7700D", + { &dib0700_usb_id_table[55], NULL }, + { NULL }, + }, }, diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 3324a73d5..185a5069b 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -255,6 +255,7 @@ #define USB_PID_YUAN_PD378S 0x2edc #define USB_PID_YUAN_MC770 0x0871 #define USB_PID_YUAN_STK7700D 0x1efc +#define USB_PID_YUAN_STK7700D_2 0x1e8c #define USB_PID_DW2102 0x2102 #define USB_PID_XTENSIONS_XD_380 0x0381 #define USB_PID_TELESTAR_STARSTICK_2 0x8000 -- cgit v1.2.3 From b211096b9b4ad13c5f37ed5003d6073b64f85cb3 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 5 Aug 2009 11:53:16 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 2a9038116..9a5281938 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -72,7 +72,9 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "X55SV ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, - /* These 2 PACKARD BELL's are Asus notebook in disguise */ + /* These 3 PACKARD BELL's seem to be Asus notebook in disguise */ + { 0x04f2, 0xb012, 0, "PACKARD BELL BV", "T32A ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_BG45", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_BG46", -- cgit v1.2.3 From bec7ef49fd57d561fc61bd37458342d20ac939aa Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 5 Aug 2009 12:19:55 +0200 Subject: libv4l: README improvements From: bifferos libv4l: README improvements Priority: normal Signed-off-by: bifferos Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 1 + v4l2-apps/libv4l/README | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index 25a7c22c9..458c146c3 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -3,6 +3,7 @@ libv4l-0.6.1 * Add more laptop models to the upside down devices table * Makefile changes to make life easier for the Debian package (Gregor Jasny) * Bugfix: fixup 320x240 output for pac7302 cameras +* README improvements / clarifications (Bifferos) libv4l-0.6.0 ------------ diff --git a/v4l2-apps/libv4l/README b/v4l2-apps/libv4l/README index 481d5b92e..811813ee2 100644 --- a/v4l2-apps/libv4l/README +++ b/v4l2-apps/libv4l/README @@ -25,13 +25,13 @@ libv4lconvert/libv4lconvert.c for the full list. For more details on the v4lconvert_ functions see libv4lconvert.h. Later on libv4lconvert was expanded to also be able to do various video -processing functions improve webcam video quality on a software basis. So +processing functions to improve webcam video quality on a software basis. So the name no longer 100% covers the functionality. The video processing is split in to 2 parts, libv4lconvert/control and libv4lconvert/processing. The control part is used to offer video controls which can be used to control the video processing functions made available by libv4lconvert/processing. -These controls are stored application wide (untill reboot) by using a +These controls are stored application wide (until reboot) by using a persistent shared memory object. libv4lconvert/processing offers the actual video processing functionality. @@ -80,6 +80,12 @@ $ export LD_PRELOAD=/usr/local/lib/libv4l/v4l1compat.so $ camorama +Prerequisites +------------- + +libv4l requires shmem file system support in the kernel (CONFIG_SHMEM). + + Installation Instructions ------------------------- @@ -88,9 +94,15 @@ Simple type the following commands from the libv4l-x.y.z directory make make install PREFIX=/usr/local -Note: make install also supports the DESTDIR=... paramter for installation +Note: make install also supports the DESTDIR=... parameter for installation into chroots. +If you require static libraries to also be built, these can be compiled +along with the dynamic equivalents by defining LINKTYPE to 'static', e.g.: + +make LINKTYPE=static +make install LINKTYPE=static + FAQ --- -- cgit v1.2.3 From 8175e2d510324afe6dad11293f8bc271a1d2e14b Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 5 Aug 2009 12:25:06 +0200 Subject: libv4l: README improvements From: Hans de Goede libv4l: README improvements Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/README | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/v4l2-apps/libv4l/README b/v4l2-apps/libv4l/README index 811813ee2..20eee5858 100644 --- a/v4l2-apps/libv4l/README +++ b/v4l2-apps/libv4l/README @@ -129,10 +129,13 @@ So clearly this belongs in a library, and in a library with a license which allows this code to be used from as many different applications as possible. Hence libv4l was born. + Q: Under which license may I use and distribute libv4l? -A: All libv4l components are licensed under the GNU Library General Publishing +A: The libv4l libraries are licensed under the GNU Library General Publishing License version 2 or (at your option) any later version. See the included -COPYING.LIB file. +COPYING.LIB file. The decompression helpers are licensed under the GNU +Library Publishing License version 2 (as they are derived from kernel code) + Q: Okay so I get the use of having a libv4lconvert, but why libv4l1 ? A: Many v4l2 drivers do not offer full v4l1 compatibility. They often do not @@ -150,9 +153,8 @@ applications. Q: Why should I use libv4l2 in my app instead of direct device access -combined with libv4lconvert? - -libv4l2 is mainly meant for quickly and easily adding support for more + combined with libv4lconvert? +A: libv4l2 is mainly meant for quickly and easily adding support for more pixelformats to existing v4l2 applications. So if you feel better directly accessing the device in combination with libv4lconvert thats fine too. @@ -163,3 +165,11 @@ zero-copy access to the captured frame, and then it can write the converted data directly to the buffer the application provided to v4l2_read(). Thus another reason to use liv4l2 is to get the no memcpy advantage of the mmap capture method combined with the simplicity of making a simple read() call. + + +Q: Where to send bugreports / questions? +A: Please send libv4l questions / bugreports to the: + Linux Media Mailing List + Subscription is not necessary to send mail to this list. If you're not + subscribed please put yourself in the CC of your original mail so you + will receive replies. -- cgit v1.2.3 From faf2479d2dfa16ad1c7a316f0443df4fa6f9c3c8 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 5 Aug 2009 12:28:07 +0200 Subject: libv4l: update my email address From: Hans de Goede libv4l: update my email address Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/include/libv4l1.h | 2 +- v4l2-apps/libv4l/include/libv4l2.h | 2 +- v4l2-apps/libv4l/include/libv4lconvert.h | 2 +- v4l2-apps/libv4l/libv4l1/libv4l1-priv.h | 2 +- v4l2-apps/libv4l/libv4l1/libv4l1.c | 2 +- v4l2-apps/libv4l/libv4l1/log.c | 2 +- v4l2-apps/libv4l/libv4l1/v4l1compat.c | 2 +- v4l2-apps/libv4l/libv4l2/libv4l2-priv.h | 2 +- v4l2-apps/libv4l/libv4l2/libv4l2.c | 2 +- v4l2-apps/libv4l/libv4l2/v4l2convert.c | 2 +- v4l2-apps/libv4l/libv4lconvert/bayer.c | 2 +- v4l2-apps/libv4l/libv4lconvert/crop.c | 2 +- v4l2-apps/libv4l/libv4lconvert/flip.c | 2 +- v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h | 2 +- v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 2 +- v4l2-apps/libv4l/libv4lconvert/rgbyuv.c | 2 +- v4l2-apps/libv4l/libv4lconvert/spca501.c | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/v4l2-apps/libv4l/include/libv4l1.h b/v4l2-apps/libv4l/include/libv4l1.h index 4ddf8efdb..a2f8bd8d4 100644 --- a/v4l2-apps/libv4l/include/libv4l1.h +++ b/v4l2-apps/libv4l/include/libv4l1.h @@ -1,5 +1,5 @@ /* -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/include/libv4l2.h b/v4l2-apps/libv4l/include/libv4l2.h index 7ecbb2cee..5488b2b10 100644 --- a/v4l2-apps/libv4l/include/libv4l2.h +++ b/v4l2-apps/libv4l/include/libv4l2.h @@ -1,5 +1,5 @@ /* -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/include/libv4lconvert.h b/v4l2-apps/libv4l/include/libv4lconvert.h index b274c938b..09ce17cae 100644 --- a/v4l2-apps/libv4l/include/libv4lconvert.h +++ b/v4l2-apps/libv4l/include/libv4lconvert.h @@ -1,5 +1,5 @@ /* -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4l1/libv4l1-priv.h b/v4l2-apps/libv4l/libv4l1/libv4l1-priv.h index 370686b3a..33abcdcb0 100644 --- a/v4l2-apps/libv4l/libv4l1/libv4l1-priv.h +++ b/v4l2-apps/libv4l/libv4l1/libv4l1-priv.h @@ -1,5 +1,5 @@ /* -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4l1/libv4l1.c b/v4l2-apps/libv4l/libv4l1/libv4l1.c index 9b23926be..29df658b1 100644 --- a/v4l2-apps/libv4l/libv4l1/libv4l1.c +++ b/v4l2-apps/libv4l/libv4l1/libv4l1.c @@ -1,7 +1,7 @@ /* # libv4l1 userspace v4l1 api emulation for v4l2 devices -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4l1/log.c b/v4l2-apps/libv4l/libv4l1/log.c index fd095817f..68060e65a 100644 --- a/v4l2-apps/libv4l/libv4l1/log.c +++ b/v4l2-apps/libv4l/libv4l1/log.c @@ -1,5 +1,5 @@ /* -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4l1/v4l1compat.c b/v4l2-apps/libv4l/libv4l1/v4l1compat.c index 704ec22dd..50fc2bab1 100644 --- a/v4l2-apps/libv4l/libv4l1/v4l1compat.c +++ b/v4l2-apps/libv4l/libv4l1/v4l1compat.c @@ -2,7 +2,7 @@ # open/close/ioctl/mmap/munmap library call wrapper doing v4l1 api emulation # for v4l2 devices -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4l2/libv4l2-priv.h b/v4l2-apps/libv4l/libv4l2/libv4l2-priv.h index 0bfd53e2a..d976093d5 100644 --- a/v4l2-apps/libv4l/libv4l2/libv4l2-priv.h +++ b/v4l2-apps/libv4l/libv4l2/libv4l2-priv.h @@ -1,5 +1,5 @@ /* -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4l2/libv4l2.c b/v4l2-apps/libv4l/libv4l2/libv4l2.c index b71c9b4c6..b7e9ae7c4 100644 --- a/v4l2-apps/libv4l/libv4l2/libv4l2.c +++ b/v4l2-apps/libv4l/libv4l2/libv4l2.c @@ -1,5 +1,5 @@ /* -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4l2/v4l2convert.c b/v4l2-apps/libv4l/libv4l2/v4l2convert.c index 4b75a5ebf..e402f78d8 100644 --- a/v4l2-apps/libv4l/libv4l2/v4l2convert.c +++ b/v4l2-apps/libv4l/libv4l2/v4l2convert.c @@ -3,7 +3,7 @@ # for v4l2 applications which want to be able to simply capture bgr24 / yuv420 # from v4l2 devices with more exotic frame formats. -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4lconvert/bayer.c b/v4l2-apps/libv4l/libv4lconvert/bayer.c index 033ee2724..d299629a6 100644 --- a/v4l2-apps/libv4l/libv4lconvert/bayer.c +++ b/v4l2-apps/libv4l/libv4lconvert/bayer.c @@ -1,6 +1,6 @@ /* * lib4lconvert, video4linux2 format conversion lib - * (C) 2008 Hans de Goede + * (C) 2008 Hans de Goede * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/v4l2-apps/libv4l/libv4lconvert/crop.c b/v4l2-apps/libv4l/libv4lconvert/crop.c index 46c87f0ce..b2d878963 100644 --- a/v4l2-apps/libv4l/libv4lconvert/crop.c +++ b/v4l2-apps/libv4l/libv4lconvert/crop.c @@ -2,7 +2,7 @@ # RGB and YUV crop routines -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4lconvert/flip.c b/v4l2-apps/libv4l/libv4lconvert/flip.c index 732b49f59..dc9b858c9 100644 --- a/v4l2-apps/libv4l/libv4lconvert/flip.c +++ b/v4l2-apps/libv4l/libv4lconvert/flip.c @@ -2,7 +2,7 @@ # RGB / YUV flip/rotate routines -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h index 4e3456bee..a61a2eeb7 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h @@ -1,5 +1,5 @@ /* -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c index 32849e8ca..fda9f8e80 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -1,5 +1,5 @@ /* -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c index 66fd3ee60..5c43ce07f 100644 --- a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c +++ b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c @@ -1,7 +1,7 @@ /* # RGB <-> YUV conversion routines -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # RGB565 conversion routines # (C) 2009 Mauro Carvalho Chehab diff --git a/v4l2-apps/libv4l/libv4lconvert/spca501.c b/v4l2-apps/libv4l/libv4lconvert/spca501.c index f491512e3..f4fbc594a 100644 --- a/v4l2-apps/libv4l/libv4lconvert/spca501.c +++ b/v4l2-apps/libv4l/libv4lconvert/spca501.c @@ -1,5 +1,5 @@ /* -# (C) 2008 Hans de Goede +# (C) 2008 Hans de Goede # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by -- cgit v1.2.3 From 28613ab5f9bf6dacca2969ce9490ad9d8f273c21 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 7 Aug 2009 17:26:11 +0200 Subject: libv4l: fix a compiler warning From: Hans de Goede libv4l: fix a compiler warning Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 9a5281938..e62862f66 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -154,7 +154,7 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { static const struct v4l2_queryctrl fake_controls[]; -static int v4lcontrol_get_dmi_string(const char *string, char *buf, int size) +static void v4lcontrol_get_dmi_string(const char *string, char *buf, int size) { FILE *f; char *s, sysfs_name[512]; -- cgit v1.2.3 From 90d3f51e152f48265166745c978c52b38f68394d Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 9 Aug 2009 16:56:38 +0200 Subject: libv4l: fix upside down devices table ordering From: Hans de Goede libv4l: fix upside down devices table ordering Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index e62862f66..f25406560 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -58,12 +58,6 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { { 0x093a, 0x2476, 0, NULL, NULL, V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED|V4LCONTROL_WANTS_WB, 1500 }, /* Laptops */ - { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vc ", - V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, - { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vn ", - V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, - { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N51Vg ", - V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "F7SR ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "W7S ", @@ -92,6 +86,12 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { /* Note no whitespace padding, this is not a typo */ { 0x04f2, 0xb071, 0, "ASUSTeK Computer INC.", "N5051Tp", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vc ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vn ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N51Vg ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* Note no whitespace padding for board vendor, this is not a typo */ { 0x064e, 0xa111, 0, "ASUSTeK Computer Inc.", "F5RL ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, -- cgit v1.2.3 From d7e3fb8e89ce1a275dcab13dffc4364d6c1727b0 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 9 Aug 2009 17:02:39 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index f25406560..49dec9a57 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -92,6 +92,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N51Vg ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb16b, 0, "ASUSTeK Computer Inc. ", "U80A ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* Note no whitespace padding for board vendor, this is not a typo */ { 0x064e, 0xa111, 0, "ASUSTeK Computer Inc.", "F5RL ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, -- cgit v1.2.3 From a04851e3e1559d3472062014fdabf29939ee351e Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 10 Aug 2009 10:02:44 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 49dec9a57..8bf458dcb 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -79,6 +79,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K50IJ ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K50IN ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K70AB ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "N10J ", @@ -102,6 +104,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "N20A ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "X58LE ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x090c, 0xe370, 0, "ASUSTeK Computer Inc. ", "U6S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Ke ", -- cgit v1.2.3 From 35bee292fab703bb1156a3e5fe30518d55c0dcbf Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Tue, 11 Aug 2009 14:04:30 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 8bf458dcb..55ebf1b54 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -129,6 +129,9 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0xa311, 0, "ASUSTeK Computer Inc. ", "A3F ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x5986, 0x0200, 0, "LENOVO", "SPEEDY ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED, 0, NULL, NULL, NULL, + "Lenovo IdeaPad Y510" }, { 0x5986, 0x0205, 0, "LENOVO", "Base Board Product Name", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED, 0, NULL, NULL, NULL, "Lenovo IdeaPad U330" }, -- cgit v1.2.3 From a535ec7ac67e962087811181dc3dcb59760df467 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 12 Aug 2009 09:15:17 +0200 Subject: libv4l: Also look for dmi info under /sys/class/dmi/id From: Hans de Goede libv4l was looking for dmi strings in sysfs under /sys/devices/virtual/dmi/id but with some kernel configurations this does not exist. It turns out that the dmi strings do exist under /sys/class/dmi/id here. It seems that all systems with dmi info in sysfs have /sys/class/dmi/id so default to using that instead. To be sure fall back to /sys/devices/virtual/dmi/id (the old behavor) when /sys/class/dmi/id is not found. Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 55ebf1b54..a20c114a1 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -169,11 +169,19 @@ static void v4lcontrol_get_dmi_string(const char *string, char *buf, int size) char *s, sysfs_name[512]; snprintf(sysfs_name, sizeof(sysfs_name), - "/sys/devices/virtual/dmi/id/%s", string); + "/sys/class/dmi/id/%s", string); f = fopen(sysfs_name, "r"); if (!f) { - buf[0] = 0; - return; + /* Try again with a different sysfs path, not sure if this is needed + but we used to look under /sys/devices/virtual/dmi/id in older + libv4l versions, but this did not work with some kernels */ + snprintf(sysfs_name, sizeof(sysfs_name), + "/sys/devices/virtual/dmi/id/%s", string); + f = fopen(sysfs_name, "r"); + if (!f) { + buf[0] = 0; + return; + } } s = fgets(buf, size, f); -- cgit v1.2.3 From 1717b46f2e34d1655a665db31979f4bfaf969c06 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 09:50:33 +0200 Subject: libv4l: Fix reqbuf Device or Resource busy error when using read From: Hans de Goede Some applications such as v4l2-apps/test/capture-example.c, in read mode use select() together with read() and do a select() before the first read(). This causes issues together with certain drivers (gspca for example), do not allow switching from read mode to mmap mode and they assume read() mode if a select or poll() is done before any buffers are requested. When not using libv4l2, this is not an issue but libv4l2 uses mmap mode under the hood when converting as that safes a memcpy for each frame read. This fails with such drivers when the application has done a select() before the first read() as the driver now is in "read mode" and disallows switching to mmap mode. This patch fixes this by falling back to using read() for v4l2_read() when using mmap mode fails. Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 1 + v4l2-apps/libv4l/libv4l2/libv4l2-priv.h | 3 + v4l2-apps/libv4l/libv4l2/libv4l2.c | 107 +++++++++++++++++++++++++++----- 3 files changed, 96 insertions(+), 15 deletions(-) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index 458c146c3..93371a1fc 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -4,6 +4,7 @@ libv4l-0.6.1 * Makefile changes to make life easier for the Debian package (Gregor Jasny) * Bugfix: fixup 320x240 output for pac7302 cameras * README improvements / clarifications (Bifferos) +* Bugfix: fix reqbuf Device or Resource busy error when using v4l2_read() libv4l-0.6.0 ------------ diff --git a/v4l2-apps/libv4l/libv4l2/libv4l2-priv.h b/v4l2-apps/libv4l/libv4l2/libv4l2-priv.h index d976093d5..8256cfdb6 100644 --- a/v4l2-apps/libv4l/libv4l2/libv4l2-priv.h +++ b/v4l2-apps/libv4l/libv4l2/libv4l2-priv.h @@ -80,6 +80,9 @@ struct v4l2_dev_info { int frame_queued; /* 1 status bit per frame */ /* mapping tracking of our fake (converting mmap) frame buffers */ unsigned char frame_map_count[V4L2_MAX_NO_FRAMES]; + /* buffer when doing conversion and using read() for read() */ + int readbuf_size; + unsigned char *readbuf; }; /* From log.c */ diff --git a/v4l2-apps/libv4l/libv4l2/libv4l2.c b/v4l2-apps/libv4l/libv4l2/libv4l2.c index b7e9ae7c4..07bd9484e 100644 --- a/v4l2-apps/libv4l/libv4l2/libv4l2.c +++ b/v4l2-apps/libv4l/libv4l2/libv4l2.c @@ -77,6 +77,7 @@ #define V4L2_SUPPORTS_READ 0x0800 #define V4L2_IS_UVC 0x1000 #define V4L2_STREAM_TOUCHED 0x2000 +#define V4L2_USE_READ_FOR_READ 0x4000 #define V4L2_MMAP_OFFSET_MAGIC 0xABCDEF00u @@ -101,7 +102,7 @@ static int v4l2_request_read_buffers(int index) req.memory = V4L2_MEMORY_MMAP; if ((result = SYS_IOCTL(devices[index].fd, VIDIOC_REQBUFS, &req)) < 0){ int saved_err = errno; - V4L2_LOG_ERR("requesting %u buffers: %s\n", req.count, strerror(errno)); + V4L2_LOG("warning reqbuf (%u) failed: %s\n", req.count, strerror(errno)); errno = saved_err; return result; } @@ -305,6 +306,63 @@ static int v4l2_dequeue_and_convert(int index, struct v4l2_buffer *buf, return result; } +static int v4l2_read_and_convert(int index, unsigned char *dest, int dest_size) +{ + const int max_tries = 10; + int result, buf_size, tries = max_tries; + + buf_size = devices[index].dest_fmt.fmt.pix.sizeimage; + buf_size = (buf_size + 8191) & ~8191; + + if (devices[index].readbuf_size < buf_size) { + unsigned char *new_buf; + + new_buf = realloc(devices[index].readbuf, buf_size); + if (!new_buf) + return -1; + + devices[index].readbuf = new_buf; + devices[index].readbuf_size = buf_size; + } + + do { + result = SYS_READ(devices[index].fd, devices[index].readbuf, buf_size); + if (result <= 0) { + if (result && errno != EAGAIN) { + int saved_err = errno; + V4L2_LOG_ERR("reading: %s\n", strerror(errno)); + errno = saved_err; + } + return result; + } + + result = v4lconvert_convert(devices[index].convert, + &devices[index].src_fmt, &devices[index].dest_fmt, + devices[index].readbuf, result, dest, dest_size); + + if (result < 0) { + int saved_err = errno; + + if(errno == EAGAIN) + V4L2_LOG("warning error while converting frame data: %s\n", + v4lconvert_get_error_message(devices[index].convert)); + else + V4L2_LOG_ERR("converting / decoding frame data: %s\n", + v4lconvert_get_error_message(devices[index].convert)); + + errno = saved_err; + } + tries--; + } while (result < 0 && errno == EAGAIN && tries); + + if (result < 0 && errno == EAGAIN) { + V4L2_LOG_ERR("got %d consecutive frame decode errors, last error: %s\n", + max_tries, v4lconvert_get_error_message(devices[index].convert)); + } + + return result; +} + static int v4l2_queue_read_buffers(int index) { unsigned int i; @@ -332,6 +390,11 @@ static int v4l2_activate_read_stream(int index) { int result; + if ((devices[index].flags & V4L2_STREAMON) || devices[index].frame_queued) { + errno = EBUSY; + return -1; + } + if ((result = v4l2_request_read_buffers(index))) return result; @@ -528,6 +591,8 @@ int v4l2_fd_open(int fd, int v4l2_flags) devices[index].frame_map_count[i] = 0; } devices[index].frame_queued = 0; + devices[index].readbuf = NULL; + devices[index].readbuf_size = 0; if (index >= devices_used) devices_used = index + 1; @@ -585,6 +650,9 @@ int v4l2_close(int fd) devices[index].convert_mmap_buf = MAP_FAILED; } v4lconvert_destroy(devices[index].convert); + free(devices[index].readbuf); + devices[index].readbuf = NULL; + devices[index].readbuf_size = 0; /* Remove the fd from our list of managed fds before closing it, because as soon as we've done the actual close the fd maybe returned by an open in @@ -1070,7 +1138,6 @@ ssize_t v4l2_read (int fd, void* dest, size_t n) { ssize_t result; int index; - struct v4l2_buffer buf; if ((index = v4l2_get_index(fd)) == -1) return SYS_READ(fd, dest, n); @@ -1085,23 +1152,33 @@ ssize_t v4l2_read (int fd, void* dest, size_t n) goto leave; } - if (!(devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ)) { - if ((devices[index].flags & V4L2_STREAMON) || - devices[index].frame_queued) { - errno = EBUSY; - result = -1; - goto leave; - } + /* Since we need to do conversion try to use mmap (streaming) mode under + the hood as that safes a memcpy for each frame read. + + Note sometimes this will fail as some drivers (atleast gspca) do not allow + switching from read mode to mmap mode and they assume read() mode if a + select or poll() is done before any buffers are requested. So using mmap + mode under the hood will fail if a select() or poll() is done before the + first emulated read() call. */ + if (!(devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) && + !(devices[index].flags & V4L2_USE_READ_FOR_READ)) { if ((result = v4l2_activate_read_stream(index))) - goto leave; + /* Activating mmap mode failed, use read() instead */ + devices[index].flags |= V4L2_USE_READ_FOR_READ; } - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - result = v4l2_dequeue_and_convert(index, &buf, dest, n); + if (devices[index].flags & V4L2_USE_READ_FOR_READ) { + result = v4l2_read_and_convert(index, dest, n); + } else { + struct v4l2_buffer buf; - if (result >= 0) - v4l2_queue_read_buffer(index, buf.index); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + result = v4l2_dequeue_and_convert(index, &buf, dest, n); + + if (result >= 0) + v4l2_queue_read_buffer(index, buf.index); + } leave: pthread_mutex_unlock(&devices[index].stream_lock); -- cgit v1.2.3 From 78119829e59604c3996a9af01c254dc1f8026962 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 09:57:02 +0200 Subject: libv4l: Do not hide JPG / MJPG pixfmt from applications From: Hans de Goede Some applications want to use jpg format if possible, so do not hide it from the apps (do not assume it always needs conversion) Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 2 ++ v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h | 1 + v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 18 +++++++++--------- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index 93371a1fc..8614df14e 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -5,6 +5,8 @@ libv4l-0.6.1 * Bugfix: fixup 320x240 output for pac7302 cameras * README improvements / clarifications (Bifferos) * Bugfix: fix reqbuf Device or Resource busy error when using v4l2_read() +* Some applications want to use jpg format if possible, so do not hide + it from the apps (do not assume it always needs conversion) libv4l-0.6.0 ------------ diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h index a61a2eeb7..f10f3f607 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h @@ -108,6 +108,7 @@ /* Pixformat flags */ #define V4LCONVERT_COMPRESSED 0x01 /* Compressed format */ #define V4LCONVERT_NEEDS_CONVERSION 0x02 /* Apps likely wont know this */ +#define V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION 0x03 struct v4lconvert_data { int fd; diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c index fda9f8e80..f5e9d9762 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -58,14 +58,14 @@ static const struct v4lconvert_pixfmt supported_src_pixfmts[] = { { V4L2_PIX_FMT_HM12, V4LCONVERT_NEEDS_CONVERSION }, { V4L2_PIX_FMT_MJPEG, V4LCONVERT_COMPRESSED }, { V4L2_PIX_FMT_JPEG, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_SPCA561, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_SN9C10X, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_PAC207, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_MR97310A, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_SQ905C, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_PJPG, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_OV511, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_OV518, V4LCONVERT_COMPRESSED }, + { V4L2_PIX_FMT_SPCA561, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, + { V4L2_PIX_FMT_SN9C10X, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, + { V4L2_PIX_FMT_PAC207, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, + { V4L2_PIX_FMT_MR97310A, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, + { V4L2_PIX_FMT_SQ905C, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, + { V4L2_PIX_FMT_PJPG, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, + { V4L2_PIX_FMT_OV511, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, + { V4L2_PIX_FMT_OV518, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, }; static const struct v4lconvert_pixfmt supported_dst_pixfmts[] = { @@ -114,7 +114,7 @@ struct v4lconvert_data *v4lconvert_create(int fd) if (fmt.pixelformat == supported_src_pixfmts[j].fmt) { data->supported_src_formats |= 1 << j; v4lconvert_get_framesizes(data, fmt.pixelformat, j); - if (!supported_src_pixfmts[j].flags) + if (!(supported_src_pixfmts[j].flags & V4LCONVERT_NEEDS_CONVERSION)) always_needs_conversion = 0; break; } -- cgit v1.2.3 From b7e90d8be797d4064e7007949b33efb4af34a5fa Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 10:05:18 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index a20c114a1..21e884004 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -75,6 +75,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb036, 0, "ASUSTeK Computer Inc. ", "U6S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb036, 0, "ASUSTeK Computer Inc. ", "U6V ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K40IJ ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K50IJ ", @@ -94,6 +96,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N51Vg ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N51Vn ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb16b, 0, "ASUSTeK Computer Inc. ", "U80A ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* Note no whitespace padding for board vendor, this is not a typo */ @@ -118,9 +122,6 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F5N ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, - /* The G1S has been seen with 2 different board name strings */ - { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1S ", - V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1Sn ", -- cgit v1.2.3 From 5c78539069b4f258563e13e160393079e04a6d37 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 11:51:52 +0200 Subject: gspca: mr97310a add support for CIF and more VGA camera's From: Theodore Kilgore This patch adds supports for mr97310a camera's with CIF sensors (2 different types) and for VGA mr97310a camera with a different sensor then supported until now. This patch also add support for controls for one of the 2 CIF sensors, this was written by Thomas Kaiser Priority: normal Signed-off-by: Theodore Kilgore Signed-off-by: Thomas Kaiser Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 797 ++++++++++++++++++++++++----- 1 file changed, 682 insertions(+), 115 deletions(-) diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 301325134..3a3edf82a 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -3,6 +3,21 @@ * * Copyright (C) 2009 Kyle Guinn * + * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+ + * and for the routines for detecting and classifying these various cameras, + * + * Copyright (C) 2009 Theodore Kilgore + * + * Acknowledgements: + * + * The MR97311A support in gspca/mars.c has been helpful in understanding some + * of the registers in these cameras. + * + * Hans de Goede and + * Thomas Kaiser + * have assisted with their experience. Each of them has also helped by + * testing a previously unsupported camera. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -22,7 +37,23 @@ #include "gspca.h" -MODULE_AUTHOR("Kyle Guinn "); +#define CAM_TYPE_CIF 0 +#define CAM_TYPE_VGA 1 + +#define MR97310A_BRIGHTNESS_MIN -254 +#define MR97310A_BRIGHTNESS_MAX 255 +#define MR97310A_BRIGHTNESS_DEFAULT 0 + +#define MR97310A_EXPOSURE_MIN 300 +#define MR97310A_EXPOSURE_MAX 4095 +#define MR97310A_EXPOSURE_DEFAULT 1000 + +#define MR97310A_GAIN_MIN 0 +#define MR97310A_GAIN_MAX 31 +#define MR97310A_GAIN_DEFAULT 25 + +MODULE_AUTHOR("Kyle Guinn ," + "Theodore Kilgore "); MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); MODULE_LICENSE("GPL"); @@ -30,10 +61,75 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ u8 sof_read; + u8 cam_type; /* 0 is CIF and 1 is VGA */ + u8 sensor_type; /* We use 0 and 1 here, too. */ + u8 do_lcd_stop; + u8 regs[15]; + + int brightness; + u16 exposure; + u8 autogain; + u8 gain; }; +struct sensor_w_data { + u8 reg; + u8 flags; + u8 data[16]; + int len; +}; + +static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); + /* V4L2 controls supported by the driver */ static struct ctrl sd_ctrls[] = { + { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = MR97310A_BRIGHTNESS_MIN, + .maximum = MR97310A_BRIGHTNESS_MAX, + .step = 1, + .default_value = MR97310A_BRIGHTNESS_DEFAULT, + .flags = 0, + }, + .set = sd_setbrightness, + .get = sd_getbrightness, + }, + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = MR97310A_EXPOSURE_MIN, + .maximum = MR97310A_EXPOSURE_MAX, + .step = 1, + .default_value = MR97310A_EXPOSURE_DEFAULT, + .flags = 0, + }, + .set = sd_setexposure, + .get = sd_getexposure, + }, + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = MR97310A_GAIN_MIN, + .maximum = MR97310A_GAIN_MAX, + .step = 1, + .default_value = MR97310A_GAIN_DEFAULT, + .flags = 0, + }, + .set = sd_setgain, + .get = sd_getgain, + }, }; static const struct v4l2_pix_format vga_mode[] = { @@ -65,7 +161,7 @@ static const struct v4l2_pix_format vga_mode[] = { }; /* the bytes to write are in gspca_dev->usb_buf */ -static int reg_w(struct gspca_dev *gspca_dev, int len) +static int mr_write(struct gspca_dev *gspca_dev, int len) { int rc; @@ -78,15 +174,200 @@ static int reg_w(struct gspca_dev *gspca_dev, int len) return rc; } +/* the bytes are read into gspca_dev->usb_buf */ +static int mr_read(struct gspca_dev *gspca_dev, int len) +{ + int rc; + + rc = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 3), + gspca_dev->usb_buf, len, NULL, 500); + if (rc < 0) + PDEBUG(D_ERR, "reg read [%02x] error %d", + gspca_dev->usb_buf[0], rc); + return rc; +} + +static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags, + const u8 *data, int len) +{ + gspca_dev->usb_buf[0] = 0x1f; + gspca_dev->usb_buf[1] = flags; + gspca_dev->usb_buf[2] = reg; + memcpy(gspca_dev->usb_buf + 3, data, len); + + return mr_write(gspca_dev, len + 3); +} + +static int sensor_write_regs(struct gspca_dev *gspca_dev, + const struct sensor_w_data *data, int len) +{ + int i, rc; + + for (i = 0; i < len; i++) { + rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags, + data[i].data, data[i].len); + if (rc < 0) + return rc; + } + + return 0; +} + +static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) +{ + u8 buf; + int rc; + + buf = data; + rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1); + if (rc < 0) + return rc; + + buf = 0x01; + rc = sensor_write_reg(gspca_dev, 0x13, 0x00, &buf, 1); + if (rc < 0) + return rc; + + return 0; +} + +static int cam_get_response16(struct gspca_dev *gspca_dev) +{ + __u8 *data = gspca_dev->usb_buf; + int err_code; + + data[0] = 0x21; + err_code = mr_write(gspca_dev, 1); + if (err_code < 0) + return err_code; + + err_code = mr_read(gspca_dev, 16); + return err_code; +} + +static int zero_the_pointer(struct gspca_dev *gspca_dev) +{ + __u8 *data = gspca_dev->usb_buf; + int err_code; + u8 status = 0; + int tries = 0; + + err_code = cam_get_response16(gspca_dev); + if (err_code < 0) + return err_code; + + err_code = mr_write(gspca_dev, 1); + data[0] = 0x19; + data[1] = 0x51; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + err_code = cam_get_response16(gspca_dev); + if (err_code < 0) + return err_code; + + data[0] = 0x19; + data[1] = 0xba; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + err_code = cam_get_response16(gspca_dev); + if (err_code < 0) + return err_code; + + data[0] = 0x19; + data[1] = 0x00; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + err_code = cam_get_response16(gspca_dev); + if (err_code < 0) + return err_code; + + data[0] = 0x19; + data[1] = 0x00; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + while (status != 0x0a && tries < 256) { + err_code = cam_get_response16(gspca_dev); + status = data[0]; + tries++; + if (err_code < 0) + return err_code; + } + PDEBUG(D_ERR, "status is %02x", status); + + tries = 0; + while (tries < 4) { + data[0] = 0x19; + data[1] = 0x00; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + err_code = cam_get_response16(gspca_dev); + status = data[0]; + tries++; + if (err_code < 0) + return err_code; + } + PDEBUG(D_ERR, "Read 16 bytes from camera"); + + data[0] = 0x19; + err_code = mr_write(gspca_dev, 1); + if (err_code < 0) + return err_code; + + err_code = mr_read(gspca_dev, 16); + if (err_code < 0) + return err_code; + + return 0; +} + +static u8 get_sensor_id(struct gspca_dev *gspca_dev) +{ + int err_code; + + gspca_dev->usb_buf[0] = 0x1e; + err_code = mr_write(gspca_dev, 1); + if (err_code < 0) + return err_code; + + err_code = mr_read(gspca_dev, 16); + if (err_code < 0) + return err_code; + + PDEBUG(D_ERR, "Read 16 bytes from camera"); + PDEBUG(D_ERR, "Byte zero reported is %01x", gspca_dev->usb_buf[0]); + + return gspca_dev->usb_buf[0]; +} + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { + struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; cam = &gspca_dev->cam; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); + sd->cam_type = CAM_TYPE_VGA; + PDEBUG(D_PROBE, + "MR97310A camera detected" + " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + if (id->idProduct == 0x010e) { + cam->nmodes--; + sd->cam_type = CAM_TYPE_CIF; + } return 0; } @@ -96,183 +377,468 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static int sd_start(struct gspca_dev *gspca_dev) +static int adjust_cif_sensor(struct gspca_dev *gspca_dev) +{ + /* + * FIXME: The following sequence resets brightness, contrast, and + * related settings. Some of the values are adjustable, presumably + * based upon what is detected in the frames. Here, only some + * vaules are used which are compromises. When more is known about + * what is done here, this needs to be moved out to presently + * nonexistent functions which do controls. The same control messages + * do work for all of the CIF cameras. + */ + + const struct sensor_w_data cif_sensor1_adjust_data[] = { + {0x02, 0x01, {0x10, 0x12, 0x0a}, 3}, + /* Last or possibly two last bytes adjustable, above. */ + {0x13, 0x04, {0x01}, 1}, /* seems to mean "write" */ + {0x05, 0x01, {0x22, 0x00, 0x81, 0x06}, 4}, + /* Last or possibly two last bytes adjustable, above. */ + {0x13, 0x04, {0x01}, 1}, + {0x09, 0x02, {0x05, 0x00, 0x00, 0x05, 0x07, 0x16}, 6}, + /* Last or possibly two last bytes adjustable, above. */ + {0x13, 0x04, {0x01}, 1}, + {0, 0, {0}, 0} + }; + + return sensor_write_regs(gspca_dev, cif_sensor1_adjust_data, + ARRAY_SIZE(cif_sensor1_adjust_data)); +} + +static int start_cif_cam(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u8 *data = gspca_dev->usb_buf; int err_code; - - sd->sof_read = 0; - - /* Note: register descriptions guessed from MR97113A driver */ - + const __u8 startup_string[] = { + 0x00, + 0x0d, + 0x01, + 0x00, /* Hsize/8 for 352 or 320 */ + 0x00, /* Vsize/4 for 288 or 240 */ + 0x13, /* or 0xbb, depends on sensor */ + 0x00, /* Hstart, depends on res. */ + 0x00, /* reserved ? */ + 0x00, /* Vstart, depends on res. and sensor */ + 0x50, /* 0x54 to get 176 or 160 */ + 0xc0 + }; + + /* Note: Some of the above descriptions guessed from MR97113A driver */ + sd->sensor_type = 0; data[0] = 0x01; data[1] = 0x01; - err_code = reg_w(gspca_dev, 2); + err_code = mr_write(gspca_dev, 2); if (err_code < 0) return err_code; - data[0] = 0x00; - data[1] = 0x0d; - data[2] = 0x01; - data[5] = 0x2b; - data[7] = 0x00; - data[9] = 0x50; /* reg 8, no scale down */ - data[10] = 0xc0; + msleep(200); + data[0] = get_sensor_id(gspca_dev); + /* + * Known CIF cameras. If you have another to report, please do + * + * Name byte just read sd->sensor_type + * reported by + * Sakar Spy-shot 0x28 T. Kilgore 0 + * Innovage 0xf5 (unstable) T. Kilgore 0 + * Vivitar Mini 0x53 H. De Goede 0 + * Vivitar Mini 0x08 T. Kilgore 1 + * Elta-Media 8212dc 0x23 T. Kaiser 1 + * Philips dig. keych. 0x37 T. Kilgore 1 + */ + if ((data[0] & 0x78) == 8 || (data[0] & 0x2) == 0x2) + sd->sensor_type = 1; + + PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); + memcpy(data, startup_string, 11); + if (sd->sensor_type) + data[5] = 0xbb; switch (gspca_dev->width) { case 160: - data[9] |= 0x0c; /* reg 8, 4:1 scale down */ + data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */ /* fall thru */ case 320: - data[9] |= 0x04; /* reg 8, 2:1 scale down */ - /* fall thru */ - case 640: default: - data[3] = 0x50; /* reg 2, H size */ - data[4] = 0x78; /* reg 3, V size */ - data[6] = 0x04; /* reg 5, H start */ - data[8] = 0x03; /* reg 7, V start */ + data[3] = 0x28; /* reg 2, H size/8 */ + data[4] = 0x3c; /* reg 3, V size/4 */ + data[6] = 0x14; /* reg 5, H start */ + data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */ break; - case 176: - data[9] |= 0x04; /* reg 8, 2:1 scale down */ + data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */ /* fall thru */ case 352: - data[3] = 0x2c; /* reg 2, H size */ - data[4] = 0x48; /* reg 3, V size */ - data[6] = 0x94; /* reg 5, H start */ - data[8] = 0x63; /* reg 7, V start */ + data[3] = 0x2c; /* reg 2, H size/8 */ + data[4] = 0x48; /* reg 3, V size/4 */ + data[6] = 0x06; /* reg 5, H start */ + data[8] = 0x06 + sd->sensor_type; /* reg 7, V start */ break; } - - err_code = reg_w(gspca_dev, 11); + err_code = mr_write(gspca_dev, 11); if (err_code < 0) return err_code; - data[0] = 0x0a; - data[1] = 0x80; - err_code = reg_w(gspca_dev, 2); + if (!sd->sensor_type) { + const struct sensor_w_data cif_sensor0_init_data[] = { + {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01, + 0x0f, 0x14, 0x0f, 0x10}, 8}, + {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5}, + {0x12, 0x00, {0x07}, 1}, + {0x1f, 0x00, {0x06}, 1}, + {0x27, 0x00, {0x04}, 1}, + {0x29, 0x00, {0x0c}, 1}, + {0x40, 0x00, {0x40, 0x00, 0x04}, 3}, + {0x50, 0x00, {0x60}, 1}, + {0x60, 0x00, {0x06}, 1}, + {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6}, + {0x72, 0x00, {0x1e, 0x56}, 2}, + {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02, + 0x31, 0x80, 0x00}, 9}, + {0x11, 0x00, {0x01}, 1}, + {0, 0, {0}, 0} + }; + err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data, + ARRAY_SIZE(cif_sensor0_init_data)); + } else { /* sd->sensor_type = 1 */ + const struct sensor_w_data cif_sensor1_init_data[] = { + {0x02, 0x00, {0x10}, 1}, + {0x03, 0x01, {0x12}, 1}, + {0x04, 0x01, {0x05}, 1}, + {0x05, 0x01, {0x65}, 1}, + {0x06, 0x01, {0x32}, 1}, + {0x07, 0x01, {0x00}, 1}, + {0x08, 0x02, {0x06}, 1}, + {0x09, 0x02, {0x0e}, 1}, + {0x0a, 0x02, {0x05}, 1}, + {0x0b, 0x02, {0x05}, 1}, + {0x0c, 0x02, {0x0f}, 1}, + {0x0d, 0x02, {0x00}, 1}, + {0x0e, 0x02, {0x0c}, 1}, + {0x0f, 0x00, {0x00}, 1}, + {0x10, 0x00, {0x06}, 1}, + {0x11, 0x00, {0x07}, 1}, + {0x12, 0x00, {0x00}, 1}, + {0x13, 0x00, {0x01}, 1}, + {0, 0, {0}, 0} + }; + err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, + ARRAY_SIZE(cif_sensor1_init_data)); + } if (err_code < 0) return err_code; - data[0] = 0x14; - data[1] = 0x0a; - err_code = reg_w(gspca_dev, 2); + msleep(200); + data[0] = 0x00; + data[1] = 0x4d; /* ISOC transfering enable... */ + err_code = mr_write(gspca_dev, 2); if (err_code < 0) return err_code; - data[0] = 0x1b; - data[1] = 0x00; - err_code = reg_w(gspca_dev, 2); + msleep(200); + err_code = adjust_cif_sensor(gspca_dev); if (err_code < 0) return err_code; - data[0] = 0x15; - data[1] = 0x16; - err_code = reg_w(gspca_dev, 2); - if (err_code < 0) - return err_code; + msleep(200); + return 0; +} - data[0] = 0x16; - data[1] = 0x10; - err_code = reg_w(gspca_dev, 2); - if (err_code < 0) - return err_code; +static int start_vga_cam(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + __u8 *data = gspca_dev->usb_buf; + int err_code; + const __u8 startup_string[] = {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, + 0x00, 0x00, 0x00, 0x50, 0xc0}; - data[0] = 0x17; - data[1] = 0x3a; - err_code = reg_w(gspca_dev, 2); - if (err_code < 0) - return err_code; + /* What some of these mean is explained in start_cif_cam(), above */ + sd->sof_read = 0; - data[0] = 0x18; - data[1] = 0x68; - err_code = reg_w(gspca_dev, 2); + /* + * We have to know which camera we have, because the register writes + * depend upon the camera. This test, run before we actually enter + * the initialization routine, distinguishes most of the cameras, If + * needed, another routine is done later, too. + */ + memset(data, 0, 16); + data[0] = 0x20; + err_code = mr_write(gspca_dev, 1); if (err_code < 0) return err_code; - data[0] = 0x1f; - data[1] = 0x00; - data[2] = 0x02; - data[3] = 0x06; - data[4] = 0x59; - data[5] = 0x0c; - data[6] = 0x16; - data[7] = 0x00; - data[8] = 0x07; - data[9] = 0x00; - data[10] = 0x01; - err_code = reg_w(gspca_dev, 11); + err_code = mr_read(gspca_dev, 16); if (err_code < 0) return err_code; - data[0] = 0x1f; - data[1] = 0x04; - data[2] = 0x11; - data[3] = 0x01; - err_code = reg_w(gspca_dev, 4); - if (err_code < 0) - return err_code; + PDEBUG(D_ERR, "Read 16 bytes from camera"); + PDEBUG(D_ERR, "Byte reported is %02x", data[0]); - data[0] = 0x1f; - data[1] = 0x00; - data[2] = 0x0a; - data[3] = 0x00; - data[4] = 0x01; - data[5] = 0x00; - data[6] = 0x00; - data[7] = 0x01; - data[8] = 0x00; - data[9] = 0x0a; - err_code = reg_w(gspca_dev, 10); - if (err_code < 0) - return err_code; + msleep(200); + /* + * Known VGA cameras. If you have another to report, please do + * + * Name byte just read sd->sensor_type + * sd->do_lcd_stop + * Aiptek Pencam VGA+ 0x31 0 1 + * ION digital 0x31 0 1 + * Argus DC-1620 0x30 1 0 + * Argus QuickClix 0x30 1 1 (not caught here) + */ + sd->sensor_type = data[0] & 1; + sd->do_lcd_stop = (~data[0]) & 1; - data[0] = 0x1f; - data[1] = 0x04; - data[2] = 0x11; - data[3] = 0x01; - err_code = reg_w(gspca_dev, 4); + + + /* Streaming setup begins here. */ + + + data[0] = 0x01; + data[1] = 0x01; + err_code = mr_write(gspca_dev, 2); if (err_code < 0) return err_code; - data[0] = 0x1f; - data[1] = 0x00; - data[2] = 0x12; - data[3] = 0x00; - data[4] = 0x63; - data[5] = 0x00; - data[6] = 0x70; - data[7] = 0x00; - data[8] = 0x00; - err_code = reg_w(gspca_dev, 9); + /* + * A second test can now resolve any remaining ambiguity in the + * identification of the camera type, + */ + if (!sd->sensor_type) { + data[0] = get_sensor_id(gspca_dev); + if (data[0] == 0x7f) { + sd->sensor_type = 1; + PDEBUG(D_ERR, "sensor_type corrected to 1"); + } + msleep(200); + } + + /* + * Known VGA cameras. + * This test is only run if the previous test returned 0x30, but + * here is the information for all others, too, just for reference. + * + * Name byte just read sd->sensor_type + * + * Aiptek Pencam VGA+ 0xfb (this test not run) 1 + * ION digital 0xbd (this test not run) 1 + * Argus DC-1620 0xe5 (no change) 0 + * Argus QuickClix 0x7f (reclassified) 1 + */ + memcpy(data, startup_string, 11); + if (!sd->sensor_type) { + data[5] = 0x00; + data[10] = 0x91; + } + + switch (gspca_dev->width) { + case 160: + data[9] |= 0x0c; /* reg 8, 4:1 scale down */ + /* fall thru */ + case 320: + data[9] |= 0x04; /* reg 8, 2:1 scale down */ + /* fall thru */ + case 640: + default: + data[3] = 0x50; /* reg 2, H size/8 */ + data[4] = 0x78; /* reg 3, V size/4 */ + data[6] = 0x04; /* reg 5, H start */ + data[8] = 0x03; /* reg 7, V start */ + if (sd->do_lcd_stop) + data[8] = 0x04; /* Bayer tile shifted */ + break; + + case 176: + data[9] |= 0x04; /* reg 8, 2:1 scale down */ + /* fall thru */ + case 352: + data[3] = 0x2c; /* reg 2, H size */ + data[4] = 0x48; /* reg 3, V size */ + data[6] = 0x94; /* reg 5, H start */ + data[8] = 0x63; /* reg 7, V start */ + if (sd->do_lcd_stop) + data[8] = 0x64; /* Bayer tile shifted */ + break; + } + + err_code = mr_write(gspca_dev, 11); if (err_code < 0) return err_code; - data[0] = 0x1f; - data[1] = 0x04; - data[2] = 0x11; - data[3] = 0x01; - err_code = reg_w(gspca_dev, 4); + if (!sd->sensor_type) { + /* The only known sensor_type 0 cam is the Argus DC-1620 */ + const struct sensor_w_data vga_sensor0_init_data[] = { + {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, + {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, + {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4}, + {0x25, 0x00, {0x03, 0xa9, 0x80}, 3}, + {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4}, + {0, 0, {0}, 0} + }; + err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, + ARRAY_SIZE(vga_sensor0_init_data)); + } else { /* sd->sensor_type = 1 */ + const struct sensor_w_data vga_sensor1_init_data[] = { + {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, + 0x07, 0x00, 0x01}, 8}, + {0x11, 0x04, {0x01}, 1}, + /*{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, */ + {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, + 0x00, 0x0a}, 7}, + {0x11, 0x04, {0x01}, 1}, + {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6}, + {0x11, 0x04, {0x01}, 1}, + {0, 0, {0}, 0} + }; + err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, + ARRAY_SIZE(vga_sensor1_init_data)); + } if (err_code < 0) return err_code; + msleep(200); data[0] = 0x00; data[1] = 0x4d; /* ISOC transfering enable... */ - err_code = reg_w(gspca_dev, 2); + err_code = mr_write(gspca_dev, 2); + + return err_code; +} + +static int sd_start(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int err_code; + struct cam *cam; + + /* TEST TEST */ + int i; + for (i = 2; i <= 14; i++) + sd->regs[i] = sd_ctrls[i - 2].qctrl.default_value; + + cam = &gspca_dev->cam; + sd->sof_read = 0; + /* + * Some of the supported cameras require the memory pointer to be + * set to 0, or else they will not stream. + */ + zero_the_pointer(gspca_dev); + msleep(200); + if (sd->cam_type == CAM_TYPE_CIF) { + PDEBUG(D_ERR, "CIF camera"); + err_code = start_cif_cam(gspca_dev); + } else { + PDEBUG(D_ERR, "VGA camera"); + err_code = start_vga_cam(gspca_dev); + } return err_code; } static void sd_stopN(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; int result; gspca_dev->usb_buf[0] = 1; gspca_dev->usb_buf[1] = 0; - result = reg_w(gspca_dev, 2); + result = mr_write(gspca_dev, 2); if (result < 0) PDEBUG(D_ERR, "Camera Stop failed"); + + /* Not all the cams need this, but even if not, probably a good idea */ + zero_the_pointer(gspca_dev); + if (sd->do_lcd_stop) { + gspca_dev->usb_buf[0] = 0x19; + gspca_dev->usb_buf[1] = 0x54; + result = mr_write(gspca_dev, 2); + if (result < 0) + PDEBUG(D_ERR, "Camera Stop failed"); + } +} + +static void setbrightness(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + if (sd->brightness > 0) { + sensor_write1(gspca_dev, 7, 0); + val = sd->brightness; + } else { + sensor_write1(gspca_dev, 7, 1); + val = 257 - sd->brightness; + } + sensor_write1(gspca_dev, 8, val); +} + +static void setexposure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 val; + + val = sd->exposure >> 4; + sensor_write1(gspca_dev, 3, val); + val = sd->exposure & 0xf; + sensor_write1(gspca_dev, 4, val); +} + +static void setgain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sensor_write1(gspca_dev, 3, sd->gain); +} + +static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->brightness = val; + if (gspca_dev->streaming) + setbrightness(gspca_dev); + return 0; +} + +static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->brightness; + return 0; +} + +static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->exposure = val; + if (gspca_dev->streaming) + setexposure(gspca_dev); + return 0; +} + +static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->exposure; + return 0; +} + +static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->gain = val; + if (gspca_dev->streaming) + setgain(gspca_dev); + return 0; +} + +static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->gain; + return 0; } /* Include pac common sof detection functions */ @@ -320,8 +886,9 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x08ca, 0x0111)}, - {USB_DEVICE(0x093a, 0x010f)}, + {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */ + {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */ + {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */ {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v1.2.3 From a701e8b02349206dd6c5b3a050bcf945091e1c38 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 11:56:32 +0200 Subject: gspca: mr97310a fix detection of sensortype for vivicam with id byte of 0x53 From: Hans de Goede gspca: mr97310a fix detection of sensortype for vivicam with id byte of 0x53 Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 3a3edf82a..db2f84e63 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -447,7 +447,8 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) * Elta-Media 8212dc 0x23 T. Kaiser 1 * Philips dig. keych. 0x37 T. Kilgore 1 */ - if ((data[0] & 0x78) == 8 || (data[0] & 0x2) == 0x2) + if ((data[0] & 0x78) == 8 || + ((data[0] & 0x2) == 0x2 && data[0] != 0x53)) sd->sensor_type = 1; PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); -- cgit v1.2.3 From 7ba548f6dd9dbb151271b980bf96189a73979a12 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 15:15:52 +0200 Subject: gspca_mr97310a: cleanup/fixup control handling From: Hans de Goede gspca_mr97310a: cleanup/fixup control handling Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 98 ++++++++++++++---------------- 1 file changed, 45 insertions(+), 53 deletions(-) diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index db2f84e63..3bdf06469 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -64,11 +64,9 @@ struct sd { u8 cam_type; /* 0 is CIF and 1 is VGA */ u8 sensor_type; /* We use 0 and 1 here, too. */ u8 do_lcd_stop; - u8 regs[15]; int brightness; u16 exposure; - u8 autogain; u8 gain; }; @@ -85,10 +83,14 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); +static void setbrightness(struct gspca_dev *gspca_dev); +static void setexposure(struct gspca_dev *gspca_dev); +static void setgain(struct gspca_dev *gspca_dev); /* V4L2 controls supported by the driver */ static struct ctrl sd_ctrls[] = { { +#define BRIGHTNESS_IDX 0 { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, @@ -103,6 +105,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getbrightness, }, { +#define EXPOSURE_IDX 1 { .id = V4L2_CID_EXPOSURE, .type = V4L2_CTRL_TYPE_INTEGER, @@ -117,6 +120,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getexposure, }, { +#define GAIN_IDX 2 { .id = V4L2_CID_GAIN, .type = V4L2_CTRL_TYPE_INTEGER, @@ -360,14 +364,24 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); - sd->cam_type = CAM_TYPE_VGA; + PDEBUG(D_PROBE, "MR97310A camera detected" " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); + if (id->idProduct == 0x010e) { - cam->nmodes--; sd->cam_type = CAM_TYPE_CIF; + cam->nmodes--; + } else { + sd->cam_type = CAM_TYPE_VGA; + gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | + (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); } + + sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; + sd->exposure = MR97310A_EXPOSURE_DEFAULT; + sd->gain = MR97310A_GAIN_DEFAULT; + return 0; } @@ -377,35 +391,6 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static int adjust_cif_sensor(struct gspca_dev *gspca_dev) -{ - /* - * FIXME: The following sequence resets brightness, contrast, and - * related settings. Some of the values are adjustable, presumably - * based upon what is detected in the frames. Here, only some - * vaules are used which are compromises. When more is known about - * what is done here, this needs to be moved out to presently - * nonexistent functions which do controls. The same control messages - * do work for all of the CIF cameras. - */ - - const struct sensor_w_data cif_sensor1_adjust_data[] = { - {0x02, 0x01, {0x10, 0x12, 0x0a}, 3}, - /* Last or possibly two last bytes adjustable, above. */ - {0x13, 0x04, {0x01}, 1}, /* seems to mean "write" */ - {0x05, 0x01, {0x22, 0x00, 0x81, 0x06}, 4}, - /* Last or possibly two last bytes adjustable, above. */ - {0x13, 0x04, {0x01}, 1}, - {0x09, 0x02, {0x05, 0x00, 0x00, 0x05, 0x07, 0x16}, 6}, - /* Last or possibly two last bytes adjustable, above. */ - {0x13, 0x04, {0x01}, 1}, - {0, 0, {0}, 0} - }; - - return sensor_write_regs(gspca_dev, cif_sensor1_adjust_data, - ARRAY_SIZE(cif_sensor1_adjust_data)); -} - static int start_cif_cam(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -452,6 +437,11 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) sd->sensor_type = 1; PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); + + if (sd->sensor_type == 0) + gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | + (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); + memcpy(data, startup_string, 11); if (sd->sensor_type) data[5] = 0xbb; @@ -504,18 +494,15 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) ARRAY_SIZE(cif_sensor0_init_data)); } else { /* sd->sensor_type = 1 */ const struct sensor_w_data cif_sensor1_init_data[] = { + /* Reg 3,4, 7,8 get set by the controls */ {0x02, 0x00, {0x10}, 1}, - {0x03, 0x01, {0x12}, 1}, - {0x04, 0x01, {0x05}, 1}, - {0x05, 0x01, {0x65}, 1}, - {0x06, 0x01, {0x32}, 1}, - {0x07, 0x01, {0x00}, 1}, - {0x08, 0x02, {0x06}, 1}, + {0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */ + {0x06, 0x01, {0x00}, 1}, {0x09, 0x02, {0x0e}, 1}, {0x0a, 0x02, {0x05}, 1}, {0x0b, 0x02, {0x05}, 1}, {0x0c, 0x02, {0x0f}, 1}, - {0x0d, 0x02, {0x00}, 1}, + {0x0d, 0x02, {0x07}, 1}, {0x0e, 0x02, {0x0c}, 1}, {0x0f, 0x00, {0x00}, 1}, {0x10, 0x00, {0x06}, 1}, @@ -530,19 +517,18 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; + setbrightness(gspca_dev); + setexposure(gspca_dev); + setgain(gspca_dev); + msleep(200); + data[0] = 0x00; data[1] = 0x4d; /* ISOC transfering enable... */ err_code = mr_write(gspca_dev, 2); if (err_code < 0) return err_code; - msleep(200); - err_code = adjust_cif_sensor(gspca_dev); - if (err_code < 0) - return err_code; - - msleep(200); return 0; } @@ -711,11 +697,6 @@ static int sd_start(struct gspca_dev *gspca_dev) int err_code; struct cam *cam; - /* TEST TEST */ - int i; - for (i = 2; i <= 14; i++) - sd->regs[i] = sd_ctrls[i - 2].qctrl.default_value; - cam = &gspca_dev->cam; sd->sof_read = 0; /* @@ -760,11 +741,16 @@ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; u8 val; + + if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS_IDX)) + return; + + /* Note register 7 is also seen as 0x8x or 0xCx in dumps */ if (sd->brightness > 0) { - sensor_write1(gspca_dev, 7, 0); + sensor_write1(gspca_dev, 7, 0x00); val = sd->brightness; } else { - sensor_write1(gspca_dev, 7, 1); + sensor_write1(gspca_dev, 7, 0x01); val = 257 - sd->brightness; } sensor_write1(gspca_dev, 8, val); @@ -775,6 +761,9 @@ static void setexposure(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; u8 val; + if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) + return; + val = sd->exposure >> 4; sensor_write1(gspca_dev, 3, val); val = sd->exposure & 0xf; @@ -785,6 +774,9 @@ static void setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (gspca_dev->ctrl_dis & (1 << GAIN_IDX)) + return; + sensor_write1(gspca_dev, 3, sd->gain); } -- cgit v1.2.3 From a7cb5b967c6700a7b3cd5d489d92871e2fd5ba16 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 15:40:26 +0200 Subject: gspca_mr97310a: Move detection of CIF sensor type to probe() function From: Hans de Goede gspca_mr97310a: Move detection of CIF sensor type to probe() function, so that the right controls are set to disabled from the start, rather then having them disappear all of a sudden when the stream is started. Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 59 +++++++++++++++++------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 3bdf06469..1a6532fa8 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -360,6 +360,8 @@ static int sd_config(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; + __u8 *data = gspca_dev->usb_buf; + int err_code; cam = &gspca_dev->cam; cam->cam_mode = vga_mode; @@ -372,6 +374,38 @@ static int sd_config(struct gspca_dev *gspca_dev, if (id->idProduct == 0x010e) { sd->cam_type = CAM_TYPE_CIF; cam->nmodes--; + + data[0] = 0x01; + data[1] = 0x01; + err_code = mr_write(gspca_dev, 2); + if (err_code < 0) + return err_code; + + msleep(200); + data[0] = get_sensor_id(gspca_dev); + /* + * Known CIF cameras. If you have another to report, please do + * + * Name byte just read sd->sensor_type + * reported by + * Sakar Spy-shot 0x28 T. Kilgore 0 + * Innovage 0xf5 (unstable) T. Kilgore 0 + * Vivitar Mini 0x53 H. De Goede 0 + * Vivitar Mini 0x08 T. Kilgore 1 + * Elta-Media 8212dc 0x23 T. Kaiser 1 + * Philips dig. keych. 0x37 T. Kilgore 1 + */ + if ((data[0] & 0x78) == 8 || + ((data[0] & 0x2) == 0x2 && data[0] != 0x53)) + sd->sensor_type = 1; + else + sd->sensor_type = 0; + + PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); + + if (sd->sensor_type == 0) + gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | + (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); } else { sd->cam_type = CAM_TYPE_VGA; gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | @@ -411,37 +445,12 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) }; /* Note: Some of the above descriptions guessed from MR97113A driver */ - sd->sensor_type = 0; data[0] = 0x01; data[1] = 0x01; err_code = mr_write(gspca_dev, 2); if (err_code < 0) return err_code; - msleep(200); - data[0] = get_sensor_id(gspca_dev); - /* - * Known CIF cameras. If you have another to report, please do - * - * Name byte just read sd->sensor_type - * reported by - * Sakar Spy-shot 0x28 T. Kilgore 0 - * Innovage 0xf5 (unstable) T. Kilgore 0 - * Vivitar Mini 0x53 H. De Goede 0 - * Vivitar Mini 0x08 T. Kilgore 1 - * Elta-Media 8212dc 0x23 T. Kaiser 1 - * Philips dig. keych. 0x37 T. Kilgore 1 - */ - if ((data[0] & 0x78) == 8 || - ((data[0] & 0x2) == 0x2 && data[0] != 0x53)) - sd->sensor_type = 1; - - PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); - - if (sd->sensor_type == 0) - gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | - (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); - memcpy(data, startup_string, 11); if (sd->sensor_type) data[5] = 0xbb; -- cgit v1.2.3 From 30f3a12506fbaced440cb99a0a893825dbec6f1f Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 16:05:38 +0200 Subject: gspca_mr97310a: make the probing a bit less chatty From: Hans de Goede gspca_mr97310a: make the probing a bit less chatty Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 1a6532fa8..7540ea94e 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -305,7 +305,8 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; } - PDEBUG(D_ERR, "status is %02x", status); + if (status != 0x0a) + PDEBUG(D_ERR, "status is %02x", status); tries = 0; while (tries < 4) { @@ -321,7 +322,6 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; } - PDEBUG(D_ERR, "Read 16 bytes from camera"); data[0] = 0x19; err_code = mr_write(gspca_dev, 1); @@ -348,8 +348,7 @@ static u8 get_sensor_id(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; - PDEBUG(D_ERR, "Read 16 bytes from camera"); - PDEBUG(D_ERR, "Byte zero reported is %01x", gspca_dev->usb_buf[0]); + PDEBUG(D_PROBE, "Byte zero reported is %01x", gspca_dev->usb_buf[0]); return gspca_dev->usb_buf[0]; } @@ -367,10 +366,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); - PDEBUG(D_PROBE, - "MR97310A camera detected" - " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); - if (id->idProduct == 0x010e) { sd->cam_type = CAM_TYPE_CIF; cam->nmodes--; @@ -401,13 +396,15 @@ static int sd_config(struct gspca_dev *gspca_dev, else sd->sensor_type = 0; - PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); + PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d", + sd->sensor_type); if (sd->sensor_type == 0) gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); } else { sd->cam_type = CAM_TYPE_VGA; + PDEBUG(D_PROBE, "MR97310A VGA camera detected"); gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); } @@ -568,8 +565,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) if (err_code < 0) return err_code; - PDEBUG(D_ERR, "Read 16 bytes from camera"); - PDEBUG(D_ERR, "Byte reported is %02x", data[0]); + PDEBUG(D_PROBE, "Byte reported is %02x", data[0]); msleep(200); /* @@ -604,7 +600,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) data[0] = get_sensor_id(gspca_dev); if (data[0] == 0x7f) { sd->sensor_type = 1; - PDEBUG(D_ERR, "sensor_type corrected to 1"); + PDEBUG(D_PROBE, "sensor_type corrected to 1"); } msleep(200); } @@ -715,10 +711,8 @@ static int sd_start(struct gspca_dev *gspca_dev) zero_the_pointer(gspca_dev); msleep(200); if (sd->cam_type == CAM_TYPE_CIF) { - PDEBUG(D_ERR, "CIF camera"); err_code = start_cif_cam(gspca_dev); } else { - PDEBUG(D_ERR, "VGA camera"); err_code = start_vga_cam(gspca_dev); } return err_code; -- cgit v1.2.3 From 1043cd3f4a29434ea131163d1a1d4a21da04150b Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Fri, 14 Aug 2009 22:11:36 +0200 Subject: gspca_mr97310a: Add controls for CIF type 0 sensor cams From: Hans de Goede gspca_mr97310a: Add controls for CIF type 0 sensor cams Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 56 +++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 7540ea94e..1ee3d1ee5 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -220,7 +220,8 @@ static int sensor_write_regs(struct gspca_dev *gspca_dev, static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) { - u8 buf; + struct sd *sd = (struct sd *) gspca_dev; + u8 buf, confirm_reg; int rc; buf = data; @@ -229,7 +230,8 @@ static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) return rc; buf = 0x01; - rc = sensor_write_reg(gspca_dev, 0x13, 0x00, &buf, 1); + confirm_reg = sd->sensor_type ? 0x13 : 0x11; + rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1); if (rc < 0) return rc; @@ -400,8 +402,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor_type); if (sd->sensor_type == 0) - gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) | - (1 << EXPOSURE_IDX) | (1 << GAIN_IDX); + gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); } else { sd->cam_type = CAM_TYPE_VGA; PDEBUG(D_PROBE, "MR97310A VGA camera detected"); @@ -767,10 +768,43 @@ static void setexposure(struct gspca_dev *gspca_dev) if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) return; - val = sd->exposure >> 4; - sensor_write1(gspca_dev, 3, val); - val = sd->exposure & 0xf; - sensor_write1(gspca_dev, 4, val); + if (sd->sensor_type) { + val = sd->exposure >> 4; + sensor_write1(gspca_dev, 3, val); + val = sd->exposure & 0xf; + sensor_write1(gspca_dev, 4, val); + } else { + u8 clockdiv; + int exposure; + + /* We have both a clock divider and an exposure register. + We first calculate the clock divider, as that determines + the maximum exposure and then we calculayte the exposure + register setting (which goes from 0 - 511). + + Note our 0 - 4095 exposure is mapped to 0 - 511 + milliseconds exposure time */ + clockdiv = (60 * sd->exposure + 7999) / 8000; + + /* Limit framerate to not exceed usb bandwidth */ + if (clockdiv < 3 && gspca_dev->width >= 320) + clockdiv = 3; + else if (clockdiv < 2) + clockdiv = 2; + + /* Frame exposure time in ms = 1000 * clockdiv / 60 -> + exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */ + exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv); + if (exposure > 511) + exposure = 511; + + /* exposure register value is reversed! */ + exposure = 511 - exposure; + + sensor_write1(gspca_dev, 0x02, clockdiv); + sensor_write1(gspca_dev, 0x0e, exposure & 0xff); + sensor_write1(gspca_dev, 0x0f, exposure >> 8); + } } static void setgain(struct gspca_dev *gspca_dev) @@ -780,7 +814,11 @@ static void setgain(struct gspca_dev *gspca_dev) if (gspca_dev->ctrl_dis & (1 << GAIN_IDX)) return; - sensor_write1(gspca_dev, 3, sd->gain); + if (sd->sensor_type) { + sensor_write1(gspca_dev, 3, sd->gain); + } else { + sensor_write1(gspca_dev, 0x10, sd->gain); + } } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) -- cgit v1.2.3 From aa2c3496f93b8a3765dabc4c1159129a874c217c Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 17 Aug 2009 09:35:56 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 21e884004..6614c0d43 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -87,7 +87,9 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "N10J ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, - /* Note no whitespace padding, this is not a typo */ + /* Note no whitespace padding for these 2 models, this is not a typo */ + { 0x04f2, 0xb071, 0, "ASUSTeK Computer INC.", "K50AB", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer INC.", "N5051Tp", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vc ", -- cgit v1.2.3 From f56e5f83c8445db50b3cba3013170785c52ac486 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 17 Aug 2009 17:25:17 +0200 Subject: gspca_mr97310a: Use correct register for CIF type 1 sensor gain settings From: Hans de Goede gspca_mr97310a: Use correct register for CIF type 1 sensor gain settings Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 1ee3d1ee5..8190a1d4d 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -815,7 +815,7 @@ static void setgain(struct gspca_dev *gspca_dev) return; if (sd->sensor_type) { - sensor_write1(gspca_dev, 3, sd->gain); + sensor_write1(gspca_dev, 0x0e, sd->gain); } else { sensor_write1(gspca_dev, 0x10, sd->gain); } -- cgit v1.2.3 From 571db9ea44fcb35c1bc260eb98f3d085de5d132a Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 20 Aug 2009 11:28:51 +0200 Subject: libv4l: Change controls shm segment name to include the username From: Gregor Jasny Change controls shm segment name to include the username, as it is only writable by the user (this means libv4l controls are per user) Priority: normal Signed-off-by: Gregor Jasny Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 2 + .../libv4lconvert/control/libv4lcontrol-priv.h | 1 + .../libv4l/libv4lconvert/control/libv4lcontrol.c | 72 ++++++++++++++++------ v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 4 +- .../libv4lconvert/processing/libv4lprocessing.c | 4 +- 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index 8614df14e..56a9714bd 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -7,6 +7,8 @@ libv4l-0.6.1 * Bugfix: fix reqbuf Device or Resource busy error when using v4l2_read() * Some applications want to use jpg format if possible, so do not hide it from the apps (do not assume it always needs conversion) +* Change controls shm segment name to include the username, as it is only + writable by the user (this means libv4l controls are per user) (Gregor Jasny) libv4l-0.6.0 ------------ diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h index 834dee2ab..632e9338a 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol-priv.h @@ -25,6 +25,7 @@ #define V4LCONTROL_SHM_SIZE 4096 #define V4LCONTROL_SUPPORTS_NEXT_CTRL 0x01 +#define V4LCONTROL_MEMORY_IS_MALLOCED 0x02 struct v4lcontrol_flags_info; diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 6614c0d43..eaab3b46e 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "libv4lcontrol.h" #include "libv4lcontrol-priv.h" #include "../libv4lsyscall-priv.h" @@ -323,14 +324,17 @@ struct v4lcontrol_data *v4lcontrol_create(int fd, int always_needs_conversion) { int shm_fd; int i, rc, init = 0; - char *s, shm_name[256]; + char *s, shm_name[256], pwd_buf[1024]; struct v4l2_capability cap; struct v4l2_queryctrl ctrl; + struct passwd pwd, *pwd_p; struct v4lcontrol_data *data = calloc(1, sizeof(struct v4lcontrol_data)); - if (!data) + if (!data) { + fprintf(stderr, "libv4lcontrol: error: out of memory!\n"); return NULL; + } data->fd = fd; @@ -366,8 +370,19 @@ struct v4lcontrol_data *v4lcontrol_create(int fd, int always_needs_conversion) if (data->controls == 0) return data; /* No need to create a shared memory segment */ - SYS_IOCTL(fd, VIDIOC_QUERYCAP, &cap); - snprintf(shm_name, 256, "/%s:%s", cap.bus_info, cap.card); + if (SYS_IOCTL(fd, VIDIOC_QUERYCAP, &cap)) { + perror("libv4lcontrol: error querying device capabilities"); + goto error; + } + + if (getpwuid_r(geteuid(), &pwd, pwd_buf, sizeof(pwd_buf), &pwd_p) == 0) { + snprintf(shm_name, 256, "/libv4l-%s:%s:%s", pwd.pw_name, + cap.bus_info, cap.card); + } else { + perror("libv4lcontrol: error getting username using uid instead"); + snprintf(shm_name, 256, "/libv4l-%lu:%s:%s", (unsigned long)geteuid(), + cap.bus_info, cap.card); + } /* / is not allowed inside shm names */ for (i = 1; shm_name[i]; i++) @@ -378,23 +393,41 @@ struct v4lcontrol_data *v4lcontrol_create(int fd, int always_needs_conversion) if ((shm_fd = shm_open(shm_name, (O_CREAT | O_EXCL | O_RDWR), (S_IREAD | S_IWRITE))) >= 0) init = 1; - else if ((shm_fd = shm_open(shm_name, O_RDWR, (S_IREAD | S_IWRITE))) < 0) - goto error; + else + shm_fd = shm_open(shm_name, O_RDWR, (S_IREAD | S_IWRITE)); - /* Set the shared memory size */ - ftruncate(shm_fd, V4LCONTROL_SHM_SIZE); + if (shm_fd >= 0) { + /* Set the shared memory size */ + ftruncate(shm_fd, V4LCONTROL_SHM_SIZE); - /* Retreive a pointer to the shm object */ - data->shm_values = mmap(NULL, V4LCONTROL_SHM_SIZE, (PROT_READ | PROT_WRITE), - MAP_SHARED, shm_fd, 0); - close(shm_fd); + /* Retreive a pointer to the shm object */ + data->shm_values = mmap(NULL, V4LCONTROL_SHM_SIZE, (PROT_READ | PROT_WRITE), + MAP_SHARED, shm_fd, 0); + close(shm_fd); - if (data->shm_values == MAP_FAILED) - goto error; + if (data->shm_values == MAP_FAILED) { + perror("libv4lcontrol: error shm mmap failed"); + data->shm_values = NULL; + } + } else + perror("libv4lcontrol: error creating shm segment failed"); + + /* Fall back to malloc */ + if (data->shm_values == NULL) { + fprintf(stderr, + "libv4lcontrol: falling back to malloc-ed memory for controls\n"); + data->shm_values = malloc(V4LCONTROL_SHM_SIZE); + if (!data->shm_values) { + fprintf(stderr, "libv4lcontrol: error: out of memory!\n"); + goto error; + } + init = 1; + data->priv_flags |= V4LCONTROL_MEMORY_IS_MALLOCED; + } if (init) { /* Initialize the new shm object we created */ - memset(data->shm_values, 0, sizeof(V4LCONTROL_SHM_SIZE)); + memset(data->shm_values, 0, V4LCONTROL_SHM_SIZE); for (i = 0; i < V4LCONTROL_COUNT; i++) data->shm_values[i] = fake_controls[i].default_value; @@ -415,12 +448,15 @@ error: void v4lcontrol_destroy(struct v4lcontrol_data *data) { - if (data->controls) - munmap(data->shm_values, V4LCONTROL_SHM_SIZE); + if (data->controls) { + if (data->priv_flags & V4LCONTROL_MEMORY_IS_MALLOCED) + free(data->shm_values); + else + munmap(data->shm_values, V4LCONTROL_SHM_SIZE); + } free(data); } -/* FIXME get better CID's for normalize */ static const struct v4l2_queryctrl fake_controls[V4LCONTROL_COUNT] = { { .id = V4L2_CID_AUTO_WHITE_BALANCE, diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c index f5e9d9762..be4553cc7 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -95,8 +95,10 @@ struct v4lconvert_data *v4lconvert_create(int fd) processing controls without a performance impact. */ int always_needs_conversion = 1; - if (!data) + if (!data) { + fprintf(stderr, "libv4lconvert: error: out of memory!\n"); return NULL; + } data->fd = fd; data->decompress_pid = -1; diff --git a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c index af0056e94..424173ec5 100644 --- a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c +++ b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c @@ -38,8 +38,10 @@ struct v4lprocessing_data *v4lprocessing_create(int fd, struct v4lcontrol_data* struct v4lprocessing_data *data = calloc(1, sizeof(struct v4lprocessing_data)); - if (!data) + if (!data) { + fprintf(stderr, "libv4lprocessing: error: out of memory!\n"); return NULL; + } data->fd = fd; data->control = control; -- cgit v1.2.3 From 2c3e261d9836c1dd03fd8ba7ed862016428c6ca0 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 20 Aug 2009 11:34:10 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index eaab3b46e..8a3705dbb 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -109,6 +109,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { /* Another Asus laptop in disguise */ { 0x064e, 0xa111, 0, "PEGATRON CORPORATION ", "F5SR ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "N10Jb ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "N20A ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "X58LE ", -- cgit v1.2.3 From 0201b5f76e609d40a5ac955aab083854bf21d5b7 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 20 Aug 2009 11:42:57 +0200 Subject: libv4l: make get / set control use libv4lconvert functions From: Hans de Goede libv4l: make get / set control use libv4lconvert functions Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4l2/libv4l2.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/v4l2-apps/libv4l/libv4l2/libv4l2.c b/v4l2-apps/libv4l/libv4l2/libv4l2.c index 07bd9484e..c035ae533 100644 --- a/v4l2-apps/libv4l/libv4l2/libv4l2.c +++ b/v4l2-apps/libv4l/libv4l2/libv4l2.c @@ -1303,9 +1303,15 @@ int v4l2_set_control(int fd, int cid, int value) { struct v4l2_queryctrl qctrl = { .id = cid }; struct v4l2_control ctrl = { .id = cid }; - int result; + int index, result; + + if ((index = v4l2_get_index(fd)) == -1) { + V4L2_LOG_ERR("v4l2_set_control called with invalid fd: %d\n", fd); + errno = EBADF; + return -1; + } - if ((result = SYS_IOCTL(fd, VIDIOC_QUERYCTRL, &qctrl))) + if ((result = v4lconvert_vidioc_queryctrl(devices[index].convert, &qctrl))) return result; if (!(qctrl.flags & V4L2_CTRL_FLAG_DISABLED) && @@ -1316,7 +1322,7 @@ int v4l2_set_control(int fd, int cid, int value) ctrl.value = (value * (qctrl.maximum - qctrl.minimum) + 32767) / 65535 + qctrl.minimum; - result = SYS_IOCTL(fd, VIDIOC_S_CTRL, &ctrl); + result = v4lconvert_vidioc_s_ctrl(devices[index].convert, &ctrl); } return result; @@ -1326,14 +1332,21 @@ int v4l2_get_control(int fd, int cid) { struct v4l2_queryctrl qctrl = { .id = cid }; struct v4l2_control ctrl = { .id = cid }; + int index; + + if ((index = v4l2_get_index(fd)) == -1) { + V4L2_LOG_ERR("v4l2_set_control called with invalid fd: %d\n", fd); + errno = EBADF; + return -1; + } - if (SYS_IOCTL(fd, VIDIOC_QUERYCTRL, &qctrl)) + if (v4lconvert_vidioc_queryctrl(devices[index].convert, &qctrl)) return 0; if (qctrl.flags & V4L2_CTRL_FLAG_DISABLED) return 0; - if (SYS_IOCTL(fd, VIDIOC_G_CTRL, &ctrl)) + if (v4lconvert_vidioc_g_ctrl(devices[index].convert, &ctrl)) return 0; return ((ctrl.value - qctrl.minimum) * 65535 + -- cgit v1.2.3 From e0de46a5fc8a819a150fb4f84e82c79ed416916e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 22 Aug 2009 19:43:50 +0200 Subject: Add remote support to cph03x bttv card From: Mauro Carvalho Chehab Hello kernel developers. I found a bug report from an user in launchpad. I just copy it here. It includes patch. I don't own the necessary hardware to test it but the patch looks trivial. I'm not subscribed to this list, so please CC me. Thanks! Here is the text: """ remote control for my tv card doesnt work I have Askey CPH03x TV Capturer. When I load bttv module with "card=59" option which is proper for this tv card, I can watch tv with sound but my remote control doesnt work. There is no ir event in /proc/bus/input/device . When bttv module is loaded with "card=137" option remote control works very well. $ cat /proc/bus/input/devices ....... ........ : Bus=0001 Vendor=109e Product=0350 Version=0001 N: Name="bttv IR (card=137)" P: Phys=pci-0000:00:0d.0/ir0 S: Sysfs=/devices/pci0000:00/0000:00:0d.0/input/input144 U: Uniq= H: Handlers=kbd event6 B: EV=100003 B: KEY=2c0814 100004 0 0 0 4 2008000 2090 2001 1e0000 4400 0 ffc Unfortunately there is no sound. """ https://bugs.launchpad.net/ubuntu/+bug/239733 http://bugzilla.kernel.org/show_bug.cgi?id=11995 -- Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/bt8xx/bttv-cards.c | 1 + linux/drivers/media/video/bt8xx/bttv-input.c | 1 + 2 files changed, 2 insertions(+) diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c index 6b41aa5dc..44c8da956 100644 --- a/linux/drivers/media/video/bt8xx/bttv-cards.c +++ b/linux/drivers/media/video/bt8xx/bttv-cards.c @@ -1285,6 +1285,7 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, + .has_remote = 1, }, /* ---- card 0x3c ---------------------------------- */ diff --git a/linux/drivers/media/video/bt8xx/bttv-input.c b/linux/drivers/media/video/bt8xx/bttv-input.c index a6b403a01..f6bafbf3e 100644 --- a/linux/drivers/media/video/bt8xx/bttv-input.c +++ b/linux/drivers/media/video/bt8xx/bttv-input.c @@ -308,6 +308,7 @@ int bttv_input_init(struct bttv *btv) ir->mask_keyup = 0x008000; ir->polling = 50; // ms break; + case BTTV_BOARD_ASKEY_CPH03X: case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: case BTTV_BOARD_CONTVFMI: ir_codes = ir_codes_pixelview; -- cgit v1.2.3 From df0f019e71e99f0eb321be8912d473f02b4c54ee Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 22 Aug 2009 18:13:51 +0000 Subject: Update ALSA capture controls according to selected source. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Oldřich Jedlička The patch introduces new snd_saa7134_capsrc_set (code taken from snd_saa7134_capsrc_put) that updates also the ALSA capture controls during snd_card_saa7134_capture_prepare and snd_saa7134_capsrc_put. There can be much more work done in order to unify the control of the card (now the card's capture source is tuned/switched in saa7134-video.c too), but I don't have enough time. This work could be a starting point, but it can be applied as-is too (it doesn't need any further work to make it working). Signed-off-by: Oldřich Jedlička Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-alsa.c | 228 +++++++++++++++-------- 1 file changed, 150 insertions(+), 78 deletions(-) diff --git a/linux/drivers/media/video/saa7134/saa7134-alsa.c b/linux/drivers/media/video/saa7134/saa7134-alsa.c index 504186ae6..0d9c833e7 100644 --- a/linux/drivers/media/video/saa7134/saa7134-alsa.c +++ b/linux/drivers/media/video/saa7134/saa7134-alsa.c @@ -41,6 +41,7 @@ MODULE_PARM_DESC(debug,"enable debug messages [alsa]"); */ /* defaults */ +#define MIXER_ADDR_UNSELECTED -1 #define MIXER_ADDR_TVTUNER 0 #define MIXER_ADDR_LINE1 1 #define MIXER_ADDR_LINE2 2 @@ -69,7 +70,9 @@ typedef struct snd_card_saa7134 { struct snd_card *card; spinlock_t mixer_lock; int mixer_volume[MIXER_ADDR_LAST+1][2]; - int capture_source[MIXER_ADDR_LAST+1][2]; + int capture_source_addr; + int capture_source[2]; + struct snd_kcontrol *capture_ctl[MIXER_ADDR_LAST+1]; struct pci_dev *pci; struct saa7134_dev *dev; @@ -319,6 +322,115 @@ static int dsp_buffer_free(struct saa7134_dev *dev) return 0; } +/* + * Setting the capture source and updating the ALSA controls + */ +static int snd_saa7134_capsrc_set(struct snd_kcontrol *kcontrol, + int left, int right, bool force_notify) +{ + snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); + int change = 0, addr = kcontrol->private_value; + int active, old_addr; + u32 anabar, xbarin; + int analog_io, rate; + struct saa7134_dev *dev; + + dev = chip->dev; + + spin_lock_irq(&chip->mixer_lock); + + active = left != 0 || right != 0; + old_addr = chip->capture_source_addr; + + /* The active capture source cannot be deactivated */ + if (active) { + change = old_addr != addr || + chip->capture_source[0] != left || + chip->capture_source[1] != right; + + chip->capture_source[0] = left; + chip->capture_source[1] = right; + chip->capture_source_addr = addr; + dev->dmasound.input = addr; + } + spin_unlock_irq(&chip->mixer_lock); + + if (change) { + switch (dev->pci->device) { + + case PCI_DEVICE_ID_PHILIPS_SAA7134: + switch (addr) { + case MIXER_ADDR_TVTUNER: + saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, + 0xc0, 0xc0); + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, + 0x03, 0x00); + break; + case MIXER_ADDR_LINE1: + case MIXER_ADDR_LINE2: + analog_io = (MIXER_ADDR_LINE1 == addr) ? + 0x00 : 0x08; + rate = (32000 == dev->dmasound.rate) ? + 0x01 : 0x03; + saa_andorb(SAA7134_ANALOG_IO_SELECT, + 0x08, analog_io); + saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, + 0xc0, 0x80); + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, + 0x03, rate); + break; + } + + break; + case PCI_DEVICE_ID_PHILIPS_SAA7133: + case PCI_DEVICE_ID_PHILIPS_SAA7135: + xbarin = 0x03; /* adc */ + anabar = 0; + switch (addr) { + case MIXER_ADDR_TVTUNER: + xbarin = 0; /* Demodulator */ + anabar = 2; /* DACs */ + break; + case MIXER_ADDR_LINE1: + anabar = 0; /* aux1, aux1 */ + break; + case MIXER_ADDR_LINE2: + anabar = 9; /* aux2, aux2 */ + break; + } + + /* output xbar always main channel */ + saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, + 0xbbbb10); + + if (left || right) { + /* We've got data, turn the input on */ + saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, + xbarin); + saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); + } else { + saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, + 0); + saa_writel(SAA7133_ANALOG_IO_SELECT, 0); + } + break; + } + } + + if (change) { + if (force_notify) + snd_ctl_notify(chip->card, + SNDRV_CTL_EVENT_MASK_VALUE, + &chip->capture_ctl[addr]->id); + + if (old_addr != MIXER_ADDR_UNSELECTED && old_addr != addr) + snd_ctl_notify(chip->card, + SNDRV_CTL_EVENT_MASK_VALUE, + &chip->capture_ctl[old_addr]->id); + } + + return change; +} /* * ALSA PCM preparation @@ -406,6 +518,10 @@ static int snd_card_saa7134_capture_prepare(struct snd_pcm_substream * substream dev->dmasound.rate = runtime->rate; + /* Setup and update the card/ALSA controls */ + snd_saa7134_capsrc_set(saa7134->capture_ctl[dev->dmasound.input], 1, 1, + true); + return 0; } @@ -851,8 +967,13 @@ static int snd_saa7134_capsrc_get(struct snd_kcontrol * kcontrol, int addr = kcontrol->private_value; spin_lock_irq(&chip->mixer_lock); - ucontrol->value.integer.value[0] = chip->capture_source[addr][0]; - ucontrol->value.integer.value[1] = chip->capture_source[addr][1]; + if (chip->capture_source_addr == addr) { + ucontrol->value.integer.value[0] = chip->capture_source[0]; + ucontrol->value.integer.value[1] = chip->capture_source[1]; + } else { + ucontrol->value.integer.value[0] = 0; + ucontrol->value.integer.value[1] = 0; + } spin_unlock_irq(&chip->mixer_lock); return 0; @@ -861,87 +982,22 @@ static int snd_saa7134_capsrc_get(struct snd_kcontrol * kcontrol, static int snd_saa7134_capsrc_put(struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol) { - snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); - int change, addr = kcontrol->private_value; int left, right; - u32 anabar, xbarin; - int analog_io, rate; - struct saa7134_dev *dev; - - dev = chip->dev; - left = ucontrol->value.integer.value[0] & 1; right = ucontrol->value.integer.value[1] & 1; - spin_lock_irq(&chip->mixer_lock); - change = chip->capture_source[addr][0] != left || - chip->capture_source[addr][1] != right; - chip->capture_source[addr][0] = left; - chip->capture_source[addr][1] = right; - dev->dmasound.input=addr; - spin_unlock_irq(&chip->mixer_lock); - - - if (change) { - switch (dev->pci->device) { - - case PCI_DEVICE_ID_PHILIPS_SAA7134: - switch (addr) { - case MIXER_ADDR_TVTUNER: - saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); - saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); - break; - case MIXER_ADDR_LINE1: - case MIXER_ADDR_LINE2: - analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08; - rate = (32000 == dev->dmasound.rate) ? 0x01 : 0x03; - saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); - saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80); - saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); - break; - } - - break; - case PCI_DEVICE_ID_PHILIPS_SAA7133: - case PCI_DEVICE_ID_PHILIPS_SAA7135: - xbarin = 0x03; // adc - anabar = 0; - switch (addr) { - case MIXER_ADDR_TVTUNER: - xbarin = 0; // Demodulator - anabar = 2; // DACs - break; - case MIXER_ADDR_LINE1: - anabar = 0; // aux1, aux1 - break; - case MIXER_ADDR_LINE2: - anabar = 9; // aux2, aux2 - break; - } - - /* output xbar always main channel */ - saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); - - if (left || right) { // We've got data, turn the input on - saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin); - saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); - } else { - saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); - saa_writel(SAA7133_ANALOG_IO_SELECT, 0); - } - break; - } - } - - return change; + return snd_saa7134_capsrc_set(kcontrol, left, right, false); } -static struct snd_kcontrol_new snd_saa7134_controls[] = { +static struct snd_kcontrol_new snd_saa7134_volume_controls[] = { SAA713x_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER), -SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER), SAA713x_VOLUME("Line Volume", 1, MIXER_ADDR_LINE1), -SAA713x_CAPSRC("Line Capture Switch", 1, MIXER_ADDR_LINE1), SAA713x_VOLUME("Line Volume", 2, MIXER_ADDR_LINE2), +}; + +static struct snd_kcontrol_new snd_saa7134_capture_controls[] = { +SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER), +SAA713x_CAPSRC("Line Capture Switch", 1, MIXER_ADDR_LINE1), SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2), }; @@ -956,17 +1012,33 @@ SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2), static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) { struct snd_card *card = chip->card; + struct snd_kcontrol *kcontrol; unsigned int idx; - int err; + int err, addr; if (snd_BUG_ON(!chip)) return -EINVAL; strcpy(card->mixername, "SAA7134 Mixer"); - for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_saa7134_controls[idx], chip))) < 0) + for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_volume_controls); idx++) { + kcontrol = snd_ctl_new1(&snd_saa7134_volume_controls[idx], + chip); + err = snd_ctl_add(card, kcontrol); + if (err < 0) return err; } + + for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_capture_controls); idx++) { + kcontrol = snd_ctl_new1(&snd_saa7134_capture_controls[idx], + chip); + addr = snd_saa7134_capture_controls[idx].private_value; + chip->capture_ctl[addr] = kcontrol; + err = snd_ctl_add(card, kcontrol); + if (err < 0) + return err; + } + + chip->capture_source_addr = MIXER_ADDR_UNSELECTED; return 0; } -- cgit v1.2.3 From c3ae7357dc572ef9b97ecdb330618732472f20cf Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 24 Aug 2009 09:31:32 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 8a3705dbb..6acf641f1 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -111,6 +111,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "N10Jb ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "N10Jc ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "N20A ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x064e, 0xa116, 0, "ASUSTeK Computer Inc. ", "X58LE ", @@ -119,6 +121,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Ke ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Q ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Sa ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F3Sg ", -- cgit v1.2.3 From 1c5ff9ce104bd7d439cf6e58a797c4317d58a5e4 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 24 Aug 2009 09:52:55 +0200 Subject: libv4l: add 06f8:3009 pac7302 90 degrees rotated cam to the device table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Stéphane Marguet (Stemp) gmail.com> libv4l: add 06f8:3009 pac7302 90 degrees rotated cam to the device table Priority: normal Signed-off-by: Stéphane Marguet (Stemp) gmail.com> Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 6acf641f1..13009b471 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -155,6 +155,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { /* Pac7302 based devices */ { 0x093a, 0x2620, 0x0f, NULL, NULL, V4LCONTROL_ROTATED_90_JPEG|V4LCONTROL_WANTS_WB }, + { 0x06f8, 0x3009, 0, NULL, NULL, + V4LCONTROL_ROTATED_90_JPEG|V4LCONTROL_WANTS_WB }, /* Pac7311 based devices */ { 0x093a, 0x2600, 0x0f, NULL, NULL, V4LCONTROL_WANTS_WB }, /* sq905 devices */ -- cgit v1.2.3 From 9e33225665c1037f2fce51f4f1b65d40b639dbeb Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 25 Aug 2009 09:14:04 +0200 Subject: gspca - pac7311: Webcam 06f8:3009 added. From: Stephane Marguet (Stemp) Priority: normal Signed-off-by: Stephane Marguet (Stemp) Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + linux/drivers/media/video/gspca/pac7311.c | 1 + 2 files changed, 2 insertions(+) diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index 76203a221..4686e84dd 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -183,6 +183,7 @@ ov534 06f8:3002 Hercules Blog Webcam ov534 06f8:3003 Hercules Dualpix HD Weblog sonixj 06f8:3004 Hercules Classic Silver sonixj 06f8:3008 Hercules Deluxe Optical Glass +pac7311 06f8:3009 Hercules Classic Link spca508 0733:0110 ViewQuest VQ110 spca508 0130:0130 Clone Digital Webcam 11043 spca501 0733:0401 Intel Create and Share diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c index ed10134c9..356111956 100644 --- a/linux/drivers/media/video/gspca/pac7311.c +++ b/linux/drivers/media/video/gspca/pac7311.c @@ -1071,6 +1071,7 @@ static struct sd_desc sd_desc = { /* -- module initialisation -- */ static __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x06f8, 0x3009), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311}, {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311}, {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311}, -- cgit v1.2.3 From f5111daeefe0a868cfa6ac820e91351c48a8bb00 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Tue, 25 Aug 2009 10:18:06 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 13009b471..132325b79 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -68,7 +68,7 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "X55SV ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* These 3 PACKARD BELL's seem to be Asus notebook in disguise */ - { 0x04f2, 0xb012, 0, "PACKARD BELL BV", "T32A ", + { 0x04f2, 0xb012, 0, "Packard Bell BV", "T32A ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "PACKARD BELL BV ", "EasyNote_BG45", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, -- cgit v1.2.3 From f51afe7738282b8d0789cf9b9e02ed1f4ba3bb05 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Tue, 25 Aug 2009 10:42:25 +0200 Subject: libv4l: support decompressing sn9c2028 compressed bayer From: Theodore Kilgore libv4l: support decompressing sn9c2028 compressed bayer Priority: normal Signed-off-by: Theodore Kilgore Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 1 + .../libv4l/libv4lconvert/libv4lconvert-priv.h | 7 + v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 7 + v4l2-apps/libv4l/libv4lconvert/sn9c2028-decomp.c | 157 +++++++++++++++++++++ 4 files changed, 172 insertions(+) create mode 100644 v4l2-apps/libv4l/libv4lconvert/sn9c2028-decomp.c diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index 56a9714bd..1cdbedb9e 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -9,6 +9,7 @@ libv4l-0.6.1 it from the apps (do not assume it always needs conversion) * Change controls shm segment name to include the username, as it is only writable by the user (this means libv4l controls are per user) (Gregor Jasny) +* Add support for decompressing sn9c2028 compressed bayer (Theodore Kilgore) libv4l-0.6.0 ------------ diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h index f10f3f607..05549e6b5 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h @@ -52,6 +52,10 @@ #define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M','3','1','0') #endif +#ifndef V4L2_PIX_FMT_SN9C2028 +#define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') +#endif + #ifndef V4L2_PIX_FMT_SQ905C #define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') #endif @@ -219,6 +223,9 @@ int v4lconvert_decode_pac207(struct v4lconvert_data *data, void v4lconvert_decode_mr97310a(const unsigned char *src, unsigned char *dst, int width, int height); +void v4lconvert_decode_sn9c2028(const unsigned char *src, unsigned char *dst, + int width, int height); + void v4lconvert_decode_sq905c(const unsigned char *src, unsigned char *dst, int width, int height); diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c index be4553cc7..b35254e4b 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -60,6 +60,7 @@ static const struct v4lconvert_pixfmt supported_src_pixfmts[] = { { V4L2_PIX_FMT_JPEG, V4LCONVERT_COMPRESSED }, { V4L2_PIX_FMT_SPCA561, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, { V4L2_PIX_FMT_SN9C10X, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, + { V4L2_PIX_FMT_SN9C2028, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, { V4L2_PIX_FMT_PAC207, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, { V4L2_PIX_FMT_MR97310A, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, { V4L2_PIX_FMT_SQ905C, V4LCONVERT_COMPRESSED_AND_NEEDS_CONVERSION }, @@ -493,6 +494,7 @@ static int v4lconvert_processing_needs_double_conversion( case V4L2_PIX_FMT_SN9C10X: case V4L2_PIX_FMT_PAC207: case V4L2_PIX_FMT_MR97310A: + case V4L2_PIX_FMT_SN9C2028: case V4L2_PIX_FMT_SQ905C: case V4L2_PIX_FMT_SBGGR8: case V4L2_PIX_FMT_SGBRG8: @@ -727,6 +729,7 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data, case V4L2_PIX_FMT_SN9C10X: case V4L2_PIX_FMT_PAC207: case V4L2_PIX_FMT_MR97310A: + case V4L2_PIX_FMT_SN9C2028: case V4L2_PIX_FMT_SQ905C: { unsigned char *tmpbuf; @@ -759,6 +762,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data, v4lconvert_decode_mr97310a(src, tmpbuf, width, height); tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; break; + case V4L2_PIX_FMT_SN9C2028: + v4lconvert_decode_sn9c2028(src, tmpbuf, width, height); + tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; + break; case V4L2_PIX_FMT_SQ905C: v4lconvert_decode_sq905c(src, tmpbuf, width, height); tmpfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8; diff --git a/v4l2-apps/libv4l/libv4lconvert/sn9c2028-decomp.c b/v4l2-apps/libv4l/libv4lconvert/sn9c2028-decomp.c new file mode 100644 index 000000000..c21696752 --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/sn9c2028-decomp.c @@ -0,0 +1,157 @@ +/* + * sn9c2028-decomp.c + * + * Decompression function for the Sonix SN9C2028 dual-mode cameras. + * + * Code adapted from libgphoto2/camlibs/sonix, original version of which was + * Copyright (c) 2005 Theodore Kilgore + * + * History: + * + * This decoding algorithm originates from the work of Bertrik Sikken for the + * SN9C102 cameras. This version is an adaptation of work done by Mattias + * Krauss for the webcam-osx (macam) project. There, it was further adapted + * for use with the Vivitar Vivicam 3350B (an SN9C2028 camera) by + * Harald Ruda . Harald brought to my attention the + * work done in the macam project and suggested that I use it. One improvement + * of my own was to notice that the even and odd columns of the image have been + * reversed by the decompression algorithm, and this needs to be corrected + * during the decompression. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "libv4lconvert-priv.h" + +/* Four defines for bitstream operations, used in the decode function */ + +#define PEEK_BITS(num,to) {\ + if (bitBufCount < num) {\ + do {\ + bitBuf = (bitBuf << 8)|(*(src++));\ + bitBufCount += 8; \ + } \ + while\ + (bitBufCount < 24);\ + } \ + to = bitBuf >> (bitBufCount-num);\ +} + +/* + * PEEK_BITS puts the next bits into the low bits of . + * when the buffer is empty, it is completely refilled. + * This strategy tries to reduce memory access. Note that the high bits + * are NOT set to zero! + */ + +#define EAT_BITS(num) { bitBufCount -= num; bits_eaten += num; } + +/* + * EAT_BITS consumes bits (PEEK_BITS does not consume anything, + * it just peeks) + */ + +#define PARSE_PIXEL(val) {\ + PEEK_BITS(10, bits);\ + if ((bits&0x200) == 0) {\ + EAT_BITS(1);\ + } \ + else if ((bits&0x380) == 0x280) {\ + EAT_BITS(3);\ + val += 3;\ + if (val > 255)\ + val = 255;\ + } \ + else if ((bits&0x380) == 0x300) {\ + EAT_BITS(3);\ + val -= 3;\ + if (val < 0)\ + val = 0;\ + } \ + else if ((bits&0x3c0) == 0x200) {\ + EAT_BITS(4);\ + val += 8;\ + if (val > 255)\ + val = 255;\ + } \ + else if ((bits&0x3c0) == 0x240) {\ + EAT_BITS(4);\ + val -= 8;\ + if (val < 0)\ + val = 0;\ + } \ + else if ((bits&0x3c0) == 0x3c0) {\ + EAT_BITS(4);\ + val -= 20;\ + if (val < 0)\ + val = 0;\ + } \ + else if ((bits&0x3e0) == 0x380) {\ + EAT_BITS(5);\ + val += 20;\ + if (val > 255)\ + val = 255;\ + } \ + else {\ + EAT_BITS(10);\ + val = 8*(bits&0x1f)+0;\ + } \ +} + + +#define PUT_PIXEL_PAIR {\ + long pp;\ + pp = (c1val<<8)+c2val;\ + *((unsigned short *) (dst+dst_index)) = pp;\ + dst_index += 2;\ +} + +/* Now the decode function itself */ + +void v4lconvert_decode_sn9c2028(const unsigned char *src, unsigned char *dst, + int width, int height) +{ + long dst_index = 0; + int starting_row = 0; + unsigned short bits; + short c1val, c2val; + int x, y; + unsigned long bitBuf = 0; + unsigned long bitBufCount = 0; + unsigned long bits_eaten = 0; + + src += 12; /* Remove the header */ + + for (y = starting_row; y < height; y++) { + PEEK_BITS(8, bits); + EAT_BITS(8); + c2val = (bits & 0xff); + PEEK_BITS(8, bits); + EAT_BITS(8); + c1val = (bits & 0xff); + + PUT_PIXEL_PAIR; + + for (x = 2; x < width ; x += 2) { + /* The compression reversed the even and odd columns.*/ + PARSE_PIXEL(c2val); + PARSE_PIXEL(c1val); + PUT_PIXEL_PAIR; + } + } +} -- cgit v1.2.3 From f7f6c6d7109b51eee748c2e050bad67e73551a34 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Tue, 25 Aug 2009 10:46:47 +0200 Subject: libv4l: actually compile the sn9c2028 decompression code From: Hans de Goede libv4l: actually compile the sn9c2028 decompression code Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v4l2-apps/libv4l/libv4lconvert/Makefile b/v4l2-apps/libv4l/libv4lconvert/Makefile index c3b894957..cc3941b87 100644 --- a/v4l2-apps/libv4l/libv4lconvert/Makefile +++ b/v4l2-apps/libv4l/libv4lconvert/Makefile @@ -14,10 +14,10 @@ endif CONVERT_OBJS = libv4lconvert.o tinyjpeg.o sn9c10x.o sn9c20x.o pac207.o \ mr97310a.o flip.o crop.o jidctflt.o spca561-decompress.o \ - rgbyuv.o spca501.o sq905c.o bayer.o hm12.o helper.o \ + rgbyuv.o sn9c2028-decomp.o spca501.o sq905c.o bayer.o hm12.o \ control/libv4lcontrol.o processing/libv4lprocessing.o \ processing/whitebalance.o processing/autogain.o \ - processing/gamma.o + processing/gamma.o helper.o TARGETS = $(CONVERT_LIB) libv4lconvert.pc ov511-decomp ov518-decomp INCLUDES = ../include/libv4lconvert.h -- cgit v1.2.3 From 060dda765ddd4928d2da357e7a0bd52a1c6bfae3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Aug 2009 04:01:12 +0000 Subject: Add support BeholdTV X7 card From: Dmitri Belimov Add support our new TV card based on xc5000 and saa7134. Analog TV works well. Priority: normal Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.saa7134 | 1 + linux/drivers/media/video/saa7134/saa7134-cards.c | 49 ++++++++++++++++++++++- linux/drivers/media/video/saa7134/saa7134-input.c | 1 + linux/drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134 index 31d9f14d6..cd0222d84 100644 --- a/linux/Documentation/video4linux/CARDLIST.saa7134 +++ b/linux/Documentation/video4linux/CARDLIST.saa7134 @@ -169,3 +169,4 @@ 168 -> Beholder BeholdTV 609 RDS [5ace:6093] 169 -> Compro VideoMate S350/S300 [185b:c900] 170 -> AverMedia AverTV Studio 505 [1461:a115] +171 -> Beholder BeholdTV X7 [5ace:7595] diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index cdb04fdbb..74cdc7af3 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -32,6 +32,7 @@ #include #include "tea5767.h" #include "tda18271.h" +#include "xc5000.h" /* commly used strings */ static char name_mute[] = "mute"; @@ -5218,6 +5219,34 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1 } }, }, + [SAA7134_BOARD_BEHOLD_X7] = { + /* Beholder Intl. Ltd. Dmitry Belimov */ + .name = "Beholder BeholdTV X7", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_XC5000, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = { { + .name = name_tv, + .vmux = 2, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 0, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 9, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + }, + }, + }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -6337,6 +6366,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x185b, .subdevice = 0xc900, .driver_data = SAA7134_BOARD_VIDEOMATE_S350, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ + .subdevice = 0x7595, + .driver_data = SAA7134_BOARD_BEHOLD_X7, }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -6460,11 +6495,20 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev, return -EINVAL; } -#if 0 +#if 1 static int saa7134_xc5000_callback(struct saa7134_dev *dev, int command, int arg) { switch (dev->board) { + case SAA7134_BOARD_BEHOLD_X7: + if (command == XC5000_TUNER_RESET) { + /* Down and UP pheripherial RESET pin for reset all chips */ + saa_writeb(SAA7134_SPECIAL_MODE, 0x00); + msleep(10); + saa_writeb(SAA7134_SPECIAL_MODE, 0x01); + msleep(10); + } + break; default: saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000); @@ -6575,7 +6619,7 @@ int saa7134_tuner_callback(void *priv, int component, int command, int arg) return saa7134_tda8290_callback(dev, command, arg); case TUNER_XC2028: return saa7134_xc2028_callback(dev, command, arg); -#if 0 +#if 1 case TUNER_XC5000: return saa7134_xc5000_callback(dev, command, arg); #endif @@ -6831,6 +6875,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_M63: case SAA7134_BOARD_BEHOLD_M6_EXTRA: case SAA7134_BOARD_BEHOLD_H6: + case SAA7134_BOARD_BEHOLD_X7: dev->has_remote = SAA7134_REMOTE_I2C; break; case SAA7134_BOARD_AVERMEDIA_A169_B: diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 8dbad5dbe..60666bbc6 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -855,6 +855,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_M63: case SAA7134_BOARD_BEHOLD_M6_EXTRA: case SAA7134_BOARD_BEHOLD_H6: + case SAA7134_BOARD_BEHOLD_X7: #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV"); ir->get_key = get_key_beholdm6xx; diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index b59e0f18b..5129c40e0 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -295,6 +295,7 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_609RDS_MK5 168 #define SAA7134_BOARD_VIDEOMATE_S350 169 #define SAA7134_BOARD_AVERMEDIA_STUDIO_505 170 +#define SAA7134_BOARD_BEHOLD_X7 171 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 1c31544b6a13b915b3a0f7149c30ef6c39eb52f1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Aug 2009 18:29:11 +0000 Subject: usb_af9015: Oops on hotplugging with 2.6.31-rc5-git3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Jose Alberto Reguero El Miércoles, 5 de Agosto de 2009, Stefan Lippers-Hollmann escribió: > Hi > > Connecting my TerraTec Cinergy T USB XE rev. 2 (0x0ccd, 0x0069) to kernel > 2.6.31-rc5-git3, I get following kernel oops (complete dmesg and kernel > config (amd64) attached) while the firmware[1] is uploaded to the device. > > This is a regression relative to 2.6.30.x, where this device is working > fine. It also seems to be restricted to dvb_usb_af9015, as firmwares for > several wlan cards are uploading fine. Would it help to bisect based on > the changes to drivers/media/dvb/dvb-usb/af9015.c or is a wider scope > required? > > Regards > Stefan Lippers-Hollmann > > [1] http://www.otit.fi/~crope/v4l-dvb/af9015/af9015_firmware_cutter/firmwar >e_files/4.95.0/dvb-usb-af9015.fw > > usb 1-2: new high speed USB device using ehci_hcd and address 4 > usb 1-2: New USB device found, idVendor=0ccd, idProduct=0069 > usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 > usb 1-2: Product: Cinergy T USB XE Ver.2 > usb 1-2: Manufacturer: TerraTec > usb 1-2: SerialNumber: 10012007 > usb 1-2: configuration #1 chosen from 1 choice > dvb-usb: found a 'TerraTec Cinergy T USB XE' in cold state, will try to > load a firmware usb 1-2: firmware: requesting dvb-usb-af9015.fw > dvb-usb: downloading firmware from file 'dvb-usb-af9015.fw' > BUG: unable to handle kernel paging request at ffffc9000db5ee17 > IP: [] memcpy_c+0xb/0x20 > PGD 22fc07067 PUD 22fc14067 PMD 1a091b067 PTE 800000020d5fd161 > Oops: 0003 [#1] PREEMPT SMP > last sysfs file: > /sys/devices/pci0000:00/0000:00:1a.7/usb1/1-2/firmware/1-2/loading CPU 0 > Modules linked in: dvb_usb_af9015(+) dvb_usb dvb_core radeon drm bnep sco > rfcomm l2cap bluetooth ppdev parport_pc lp parport acpi_cpufreq > cpufreq_conservative cpufreq_stats cpufreq_ondemand freq_table > cpufreq_performance cpufreq_powersave kvm_intel kvm ipv6 af_packet bridge > stp snd_hda_codec_atihdmi rt2800usb snd_hda_codec_realtek zd1211rw > rt2x00usb snd_hda_intel snd_hda_codec rt2x00lib input_polldev crc_ccitt > snd_hwdep arc4 ath9k ecb snd_pcm b43 ath snd_seq snd_timer rng_core > snd_seq_device mac80211 cfg80211 evdev snd rtc_cmos rtc_core soundcore > rtc_lib pcspkr rfkill snd_page_alloc i2c_i801 processor led_class i2c_core > button ext4 mbcache jbd2 crc16 dm_mirror dm_region_hash dm_log dm_snapshot > dm_mod sg sr_mod sd_mod cdrom usbhid hid uhci_hcd ahci ssb firewire_ohci > pcmcia firewire_core libata pcmcia_core crc_itu_t scsi_mod r8169 ehci_hcd > mii usbcore nls_base intel_agp thermal fan Pid: 18663, comm: modprobe Not > tainted 2.6.31-rc5-sidux-amd64 #1 EP45-DS3 RIP: 0010:[] > [] memcpy_c+0xb/0x20 RSP: 0018:ffff880221185b50 EFLAGS: > 00010202 > RAX: ffffc9000db5ee17 RBX: ffff880221185c18 RCX: 0000000000000002 > RDX: 0000000000000002 RSI: ffff880221185b6a RDI: ffffc9000db5ee17 > RBP: 0000000000000000 R08: ffff8800280442a0 R09: 0000000000000001 > R10: ffff8800378010c0 R11: ffffffff810284b0 R12: 0000000000000008 > R13: ffff880221185b68 R14: ffff880221179800 R15: ffff880221185bb4 > FS: 00007f7f1d4286f0(0000) GS:ffff880028034000(0000) > knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b > CR2: ffffc9000db5ee17 CR3: 00000001e21ec000 CR4: 00000000000026e0 > DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 > DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 > Process modprobe (pid: 18663, threadinfo ffff880221184000, task > ffff88021f0393e0) Stack: > ffffffffa060b2ad ffffffffa060f220 00ff880221179800 0f002f4b88d0002b > <0> 004500088673e9ea 0d13c9141c915e02 06803e010101fb08 0c800cc012007d40 > <0> bb800cc01200fa80 010000a000006480 ff02010202020102 ffff8802260823c0 > Call Trace: > [] ? af9015_rw_udev+0x24d/0x2d0 [dvb_usb_af9015] > [] ? af9015_download_firmware+0x12b/0x190 > [dvb_usb_af9015] [] ? dvb_usb_download_firmware+0x94/0xe0 > [dvb_usb] [] ? dvb_usb_device_init+0x179/0x700 [dvb_usb] > [] ? af9015_usb_probe+0x12f/0xbf4 [dvb_usb_af9015] > [] ? usb_probe_interface+0xb7/0x190 [usbcore] > [] ? driver_probe_device+0x98/0x1b0 > [] ? __driver_attach+0x93/0xa0 > [] ? __driver_attach+0x0/0xa0 > [] ? bus_for_each_dev+0x58/0x80 > [] ? bus_add_driver+0x268/0x2f0 > [] ? driver_register+0x79/0x170 > [] ? usb_register_driver+0xa9/0x120 [usbcore] > [] ? af9015_usb_module_init+0x0/0x37 [dvb_usb_af9015] > [] ? af9015_usb_module_init+0x1b/0x37 [dvb_usb_af9015] > [] ? do_one_initcall+0x3b/0x180 > [] ? __up_read+0x21/0xc0 > [] ? __blocking_notifier_call_chain+0x65/0x90 > [] ? sys_init_module+0xe8/0x240 > [] ? system_call_fastpath+0x16/0x1b > Code: 81 ea d8 1f 00 00 48 3b 42 20 73 07 48 8b 50 f9 31 c0 c3 31 d2 48 c7 > c0 f2 ff ff ff c3 90 90 90 48 89 f8 89 d1 c1 e9 03 83 e2 07 48 a5 89 > d1 f3 a4 c3 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 RIP > [] memcpy_c+0xb/0x20 > RSP > CR2: ffffc9000db5ee17 > ---[ end trace 605ab93fe7120203 ]--- I have the same problem with a recent v4l-dvb. The attached patch seem to solve the problem. Jose Alberto Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/af9015.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 21815367f..3c2b7c0d7 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -108,7 +108,7 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) } /* write requested */ - if (write) { + if (write && req->data_len) { memcpy(&buf[8], req->data, req->data_len); msg_len += req->data_len; } -- cgit v1.2.3 From 33b4b30509d2a665196e5316229ec345df8757b6 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 29 Aug 2009 12:11:58 +0200 Subject: gspca - sonixj: Don't use mdelay(). From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 6a668deb1..55970fee6 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1177,7 +1177,7 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x17, 0x20); reg_w1(gspca_dev, 0x01, 0x62); reg_w1(gspca_dev, 0x01, 0x42); - mdelay(100); + msleep(100); reg_w1(gspca_dev, 0x02, 0x62); break; /* case SENSOR_HV7131R: */ -- cgit v1.2.3 From 44776a4c6f85ac1270e70c07f2a6b5c6b93d8cc0 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sat, 29 Aug 2009 12:23:17 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 132325b79..b5a448379 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -59,6 +59,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { { 0x093a, 0x2476, 0, NULL, NULL, V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED|V4LCONTROL_WANTS_WB, 1500 }, /* Laptops */ + { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "F7L ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "F7SR ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "W7S ", -- cgit v1.2.3 From 0233bd5ac7f399da4e6bb327e424d0eea0961b0a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 16:32:11 +0400 Subject: Add support for RoverMedia TV Link Pro FM From: Eugene Yudin This patch add support for RoverMedia TV Link Pro FM (LR138 REV:I) card based on saa7134. Priority: normal Signed-off-by: Eugene Yudin Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.saa7134 | 1 + linux/drivers/media/video/saa7134/saa7134-cards.c | 57 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/saa7134-input.c | 1 + linux/drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 60 insertions(+) diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134 index cd0222d84..0ac4d2544 100644 --- a/linux/Documentation/video4linux/CARDLIST.saa7134 +++ b/linux/Documentation/video4linux/CARDLIST.saa7134 @@ -170,3 +170,4 @@ 169 -> Compro VideoMate S350/S300 [185b:c900] 170 -> AverMedia AverTV Studio 505 [1461:a115] 171 -> Beholder BeholdTV X7 [5ace:7595] +172 -> RoverMedia TV Link Pro FM [19d1:0138] diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 74cdc7af3..6ea54fa7c 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -266,6 +266,56 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x10000, }, }, + [SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM] = { + /* RoverMedia TV Link Pro FM (LR138 REV:I) */ + /* Eugene Yudin */ + .name = "RoverMedia TV Link Pro FM", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MFPE05 2 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0xe000, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .gpio = 0x8000, + .tv = 1, + }, { + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .gpio = 0x0000, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 0, + .amux = LINE2, + .gpio = 0x4000, + }, { + .name = name_comp2, + .vmux = 3, + .amux = LINE2, + .gpio = 0x4000, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + .gpio = 0x4000, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x2000, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio = 0x8000, + }, + }, [SAA7134_BOARD_EMPRESS] = { /* "Gert Vervoort" */ .name = "EMPRESS", @@ -6372,6 +6422,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ .subdevice = 0x7595, .driver_data = SAA7134_BOARD_BEHOLD_X7, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x19d1, /* RoverMedia */ + .subdevice = 0x0138, /* LifeView FlyTV Prime30 OEM */ + .driver_data = SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM, }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -6743,6 +6799,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_REAL_ANGEL_220: case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: + case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 60666bbc6..9e2adcd12 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -456,6 +456,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_FLYVIDEO3000: case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_FLYTVPLATINUM_MINI2: + case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: ir_codes = ir_codes_flyvideo; mask_keycode = 0xEC00000; mask_keydown = 0x0040000; diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 5129c40e0..8c164bc79 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -296,6 +296,7 @@ struct saa7134_format { #define SAA7134_BOARD_VIDEOMATE_S350 169 #define SAA7134_BOARD_AVERMEDIA_STUDIO_505 170 #define SAA7134_BOARD_BEHOLD_X7 171 +#define SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM 172 #define SAA7134_MAXBOARDS 32 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From bd32278f17b34fcebbf9f4854996ff82eefeb334 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 14:15:55 -0300 Subject: common/ir: use a struct for keycode tables From: Mauro Carvalho Chehab Currently, V4L uses a scancode table whose index is the scancode and the value is the keycode. While this works, it has some drawbacks: 1) It requires that the scancode to be at the range 00-7f; 2) keycodes should be masked on 7 bits in order for it to work; 3) due to the 7 bits approach, sometimes it is not possible to replace the default keyboard to another one with a different encoding rule; 4) it is different than what is done with dvb-usb approach; 5) it requires a typedef for it to work. This is not a recommended Linux CodingStyle. This patch is part of a larger series of IR changes. It basically replaces the IR_KEYTAB_TYPE tables by a structured table: struct ir_scancode { u16 scancode; u32 keycode; }; This is very close to what dvb does. So, a further integration with DVB code will be easy. While we've changed the tables, for now, the IR keycode handling is still based on the old approach. The only notable effect is the redution of about 35% of the ir-common module size: text data bss dec hex filename 6721 29208 4 35933 8c5d old/ir-common.ko 5756 18040 4 23800 5cf8 new/ir-common.ko In thesis, we could be using above u8 for scancode, reducing even more the size of the module, but defining it as u16 is more convenient, since, on dvb, each scancode has up to 16 bits, and we currently have a few troubles with rc5, as their scancodes are defined with more than 8 bits. This patch itself shouldn't be doing any functional changes. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-functions.c | 15 +- linux/drivers/media/common/ir-keymaps.c | 5081 +++++++++++---------- linux/drivers/media/dvb/dm1105/dm1105.c | 2 +- linux/drivers/media/dvb/ttpci/budget-ci.c | 6 +- linux/drivers/media/video/bt8xx/bttv-input.c | 26 +- linux/drivers/media/video/cx18/cx18-i2c.c | 2 +- linux/drivers/media/video/cx231xx/cx231xx.h | 2 +- linux/drivers/media/video/cx88/cx88-input.c | 52 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 32 +- linux/drivers/media/video/em28xx/em28xx.h | 2 +- linux/drivers/media/video/ir-kbd-i2c.c | 20 +- linux/drivers/media/video/saa7134/saa7134-input.c | 78 +- linux/include/media/ir-common.h | 141 +- linux/include/media/ir-kbd-i2c.h | 5 +- 14 files changed, 2879 insertions(+), 2585 deletions(-) diff --git a/linux/drivers/media/common/ir-functions.c b/linux/drivers/media/common/ir-functions.c index ddbd4be99..38e1ee13a 100644 --- a/linux/drivers/media/common/ir-functions.c +++ b/linux/drivers/media/common/ir-functions.c @@ -59,13 +59,24 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) /* -------------------------------------------------------------------------- */ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, - int ir_type, IR_KEYTAB_TYPE *ir_codes) + int ir_type, struct ir_scancode_table *ir_codes) { int i; ir->ir_type = ir_type; + + memset(ir->ir_codes, sizeof(ir->ir_codes), 0); + + /* + * FIXME: This is a temporary workaround to use the new IR tables + * with the old approach. Later patches will replace this to a + * proper method + */ + if (ir_codes) - memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes)); + for (i = 0; i < ir_codes->size; i++) + if (ir_codes->scan[i].scancode < IR_KEYTAB_SIZE) + ir->ir_codes[ir_codes->scan[i].scancode] = ir_codes->scan[i].keycode; dev->keycode = ir->ir_codes; dev->keycodesize = sizeof(IR_KEYTAB_TYPE); diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 25b9a243e..5ce47d775 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -30,240 +30,270 @@ #include "compat.h" /* empty keytable, can be used as placeholder for not-yet created keytables */ -IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { - [0x2a] = KEY_COFFEE, +static struct ir_scancode ir_codes_empty[] = { + { 0x2a, KEY_COFFEE }, }; -EXPORT_SYMBOL_GPL(ir_codes_empty); + +struct ir_scancode_table ir_codes_empty_table = { + .scan = ir_codes_empty, + .size = ARRAY_SIZE(ir_codes_empty), +}; +EXPORT_SYMBOL_GPL(ir_codes_empty_table); /* Michal Majchrowicz */ -IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_proteus_2309[] = { /* numeric */ - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - - [0x5c] = KEY_POWER, /* power */ - [0x20] = KEY_ZOOM, /* full screen */ - [0x0f] = KEY_BACKSPACE, /* recall */ - [0x1b] = KEY_ENTER, /* mute */ - [0x41] = KEY_RECORD, /* record */ - [0x43] = KEY_STOP, /* stop */ - [0x16] = KEY_S, - [0x1a] = KEY_POWER2, /* off */ - [0x2e] = KEY_RED, - [0x1f] = KEY_CHANNELDOWN, /* channel - */ - [0x1c] = KEY_CHANNELUP, /* channel + */ - [0x10] = KEY_VOLUMEDOWN, /* volume - */ - [0x1e] = KEY_VOLUMEUP, /* volume + */ - [0x14] = KEY_F1, -}; -EXPORT_SYMBOL_GPL(ir_codes_proteus_2309); + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x5c, KEY_POWER }, /* power */ + { 0x20, KEY_ZOOM }, /* full screen */ + { 0x0f, KEY_BACKSPACE }, /* recall */ + { 0x1b, KEY_ENTER }, /* mute */ + { 0x41, KEY_RECORD }, /* record */ + { 0x43, KEY_STOP }, /* stop */ + { 0x16, KEY_S }, + { 0x1a, KEY_POWER2 }, /* off */ + { 0x2e, KEY_RED }, + { 0x1f, KEY_CHANNELDOWN }, /* channel - */ + { 0x1c, KEY_CHANNELUP }, /* channel + */ + { 0x10, KEY_VOLUMEDOWN }, /* volume - */ + { 0x1e, KEY_VOLUMEUP }, /* volume + */ + { 0x14, KEY_F1 }, +}; + +struct ir_scancode_table ir_codes_proteus_2309_table = { + .scan = ir_codes_proteus_2309, + .size = ARRAY_SIZE(ir_codes_proteus_2309), +}; +EXPORT_SYMBOL_GPL(ir_codes_proteus_2309_table); /* Matt Jesson >' */ - [0x3a] = KEY_RECORD, /* 'capture' */ - [0x0a] = KEY_MUTE, /* 'mute' */ - [0x2c] = KEY_RECORD, /* 'record' */ - [0x1c] = KEY_PAUSE, /* 'pause' */ - [0x3c] = KEY_STOP, /* 'stop' */ - [0x0c] = KEY_PLAY, /* 'play' */ - [0x2e] = KEY_RED, /* 'red' */ - [0x01] = KEY_BLUE, /* 'blue' / 'cancel' */ - [0x0e] = KEY_YELLOW, /* 'yellow' / 'ok' */ - [0x21] = KEY_GREEN, /* 'green' */ - [0x11] = KEY_CHANNELDOWN, /* 'channel -' */ - [0x31] = KEY_CHANNELUP, /* 'channel +' */ - [0x1e] = KEY_VOLUMEDOWN, /* 'volume -' */ - [0x3e] = KEY_VOLUMEUP, /* 'volume +' */ -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt); +static struct ir_scancode ir_codes_avermedia_dvbt[] = { + { 0x28, KEY_0 }, /* '0' / 'enter' */ + { 0x22, KEY_1 }, /* '1' */ + { 0x12, KEY_2 }, /* '2' / 'up arrow' */ + { 0x32, KEY_3 }, /* '3' */ + { 0x24, KEY_4 }, /* '4' / 'left arrow' */ + { 0x14, KEY_5 }, /* '5' */ + { 0x34, KEY_6 }, /* '6' / 'right arrow' */ + { 0x26, KEY_7 }, /* '7' */ + { 0x16, KEY_8 }, /* '8' / 'down arrow' */ + { 0x36, KEY_9 }, /* '9' */ + + { 0x20, KEY_LIST }, /* 'source' */ + { 0x10, KEY_TEXT }, /* 'teletext' */ + { 0x00, KEY_POWER }, /* 'power' */ + { 0x04, KEY_AUDIO }, /* 'audio' */ + { 0x06, KEY_ZOOM }, /* 'full screen' */ + { 0x18, KEY_VIDEO }, /* 'display' */ + { 0x38, KEY_SEARCH }, /* 'loop' */ + { 0x08, KEY_INFO }, /* 'preview' */ + { 0x2a, KEY_REWIND }, /* 'backward <<' */ + { 0x1a, KEY_FASTFORWARD }, /* 'forward >>' */ + { 0x3a, KEY_RECORD }, /* 'capture' */ + { 0x0a, KEY_MUTE }, /* 'mute' */ + { 0x2c, KEY_RECORD }, /* 'record' */ + { 0x1c, KEY_PAUSE }, /* 'pause' */ + { 0x3c, KEY_STOP }, /* 'stop' */ + { 0x0c, KEY_PLAY }, /* 'play' */ + { 0x2e, KEY_RED }, /* 'red' */ + { 0x01, KEY_BLUE }, /* 'blue' / 'cancel' */ + { 0x0e, KEY_YELLOW }, /* 'yellow' / 'ok' */ + { 0x21, KEY_GREEN }, /* 'green' */ + { 0x11, KEY_CHANNELDOWN }, /* 'channel -' */ + { 0x31, KEY_CHANNELUP }, /* 'channel +' */ + { 0x1e, KEY_VOLUMEDOWN }, /* 'volume -' */ + { 0x3e, KEY_VOLUMEUP }, /* 'volume +' */ +}; + +struct ir_scancode_table ir_codes_avermedia_dvbt_table = { + .scan = ir_codes_avermedia_dvbt, + .size = ARRAY_SIZE(ir_codes_avermedia_dvbt), +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt_table); /* Mauro Carvalho Chehab */ -IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE] = { - [0x00] = KEY_POWER2, - [0x2e] = KEY_DOT, /* '.' */ - [0x01] = KEY_MODE, /* TV/FM */ - - [0x05] = KEY_1, - [0x06] = KEY_2, - [0x07] = KEY_3, - [0x09] = KEY_4, - [0x0a] = KEY_5, - [0x0b] = KEY_6, - [0x0d] = KEY_7, - [0x0e] = KEY_8, - [0x0f] = KEY_9, - [0x11] = KEY_0, - - [0x13] = KEY_RIGHT, /* -> */ - [0x12] = KEY_LEFT, /* <- */ - - [0x17] = KEY_SLEEP, /* Capturar Imagem */ - [0x10] = KEY_SHUFFLE, /* Amostra */ +static struct ir_scancode ir_codes_avermedia_m135a[] = { + { 0x00, KEY_POWER2 }, + { 0x2e, KEY_DOT }, /* '.' */ + { 0x01, KEY_MODE }, /* TV/FM */ + + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + { 0x11, KEY_0 }, + + { 0x13, KEY_RIGHT }, /* -> */ + { 0x12, KEY_LEFT }, /* <- */ + + { 0x17, KEY_SLEEP }, /* Capturar Imagem */ + { 0x10, KEY_SHUFFLE }, /* Amostra */ /* FIXME: The keys bellow aren't ok */ - [0x43] = KEY_CHANNELUP, - [0x42] = KEY_CHANNELDOWN, - [0x1f] = KEY_VOLUMEUP, - [0x1e] = KEY_VOLUMEDOWN, - [0x0c] = KEY_ENTER, + { 0x43, KEY_CHANNELUP }, + { 0x42, KEY_CHANNELDOWN }, + { 0x1f, KEY_VOLUMEUP }, + { 0x1e, KEY_VOLUMEDOWN }, + { 0x0c, KEY_ENTER }, - [0x14] = KEY_MUTE, - [0x08] = KEY_AUDIO, + { 0x14, KEY_MUTE }, + { 0x08, KEY_AUDIO }, - [0x03] = KEY_TEXT, - [0x04] = KEY_EPG, - [0x2b] = KEY_TV2, /* TV2 */ + { 0x03, KEY_TEXT }, + { 0x04, KEY_EPG }, + { 0x2b, KEY_TV2 }, /* TV2 */ - [0x1d] = KEY_RED, - [0x1c] = KEY_YELLOW, - [0x41] = KEY_GREEN, - [0x40] = KEY_BLUE, + { 0x1d, KEY_RED }, + { 0x1c, KEY_YELLOW }, + { 0x41, KEY_GREEN }, + { 0x40, KEY_BLUE }, + + { 0x1a, KEY_PLAYPAUSE }, + { 0x19, KEY_RECORD }, + { 0x18, KEY_PLAY }, + { 0x1b, KEY_STOP }, +}; - [0x1a] = KEY_PLAYPAUSE, - [0x19] = KEY_RECORD, - [0x18] = KEY_PLAY, - [0x1b] = KEY_STOP, +struct ir_scancode_table ir_codes_avermedia_m135a_table = { + .scan = ir_codes_avermedia_m135a, + .size = ARRAY_SIZE(ir_codes_avermedia_m135a), }; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a); +EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a_table); /* Oldrich Jedlicka */ -IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE] = { - [0x00] = KEY_POWER, - [0x01] = KEY_TUNER, /* TV/FM */ - [0x03] = KEY_TEXT, /* Teletext */ - [0x04] = KEY_EPG, - [0x05] = KEY_1, - [0x06] = KEY_2, - [0x07] = KEY_3, - [0x08] = KEY_AUDIO, - [0x09] = KEY_4, - [0x0a] = KEY_5, - [0x0b] = KEY_6, - [0x0c] = KEY_ZOOM, /* Full screen */ - [0x0d] = KEY_7, - [0x0e] = KEY_8, - [0x0f] = KEY_9, - [0x10] = KEY_PAGEUP, /* 16-CH PREV */ - [0x11] = KEY_0, - [0x12] = KEY_INFO, - [0x13] = KEY_AGAIN, /* CH RTN - channel return */ - [0x14] = KEY_MUTE, - [0x15] = KEY_EDIT, /* Autoscan */ - [0x17] = KEY_SAVE, /* Screenshot */ - [0x18] = KEY_PLAYPAUSE, - [0x19] = KEY_RECORD, - [0x1a] = KEY_PLAY, - [0x1b] = KEY_STOP, - [0x1c] = KEY_FASTFORWARD, - [0x1d] = KEY_REWIND, - [0x1e] = KEY_VOLUMEDOWN, - [0x1f] = KEY_VOLUMEUP, - [0x22] = KEY_SLEEP, /* Sleep */ - [0x23] = KEY_ZOOM, /* Aspect */ - [0x26] = KEY_SCREEN, /* Pos */ - [0x27] = KEY_ANGLE, /* Size */ - [0x28] = KEY_SELECT, /* Select */ - [0x29] = KEY_BLUE, /* Blue/Picture */ - [0x2a] = KEY_BACKSPACE, /* Back */ - [0x2b] = KEY_MEDIA, /* PIP (Picture-in-picture) */ - [0x2c] = KEY_DOWN, - [0x2e] = KEY_DOT, - [0x2f] = KEY_TV, /* Live TV */ - [0x32] = KEY_LEFT, - [0x33] = KEY_CLEAR, /* Clear */ - [0x35] = KEY_RED, /* Red/TV */ - [0x36] = KEY_UP, - [0x37] = KEY_HOME, /* Home */ - [0x39] = KEY_GREEN, /* Green/Video */ - [0x3d] = KEY_YELLOW, /* Yellow/Music */ - [0x3e] = KEY_OK, /* Ok */ - [0x3f] = KEY_RIGHT, - [0x40] = KEY_NEXT, /* Next */ - [0x41] = KEY_PREVIOUS, /* Previous */ - [0x42] = KEY_CHANNELDOWN, /* Channel down */ - [0x43] = KEY_CHANNELUP, /* Channel up */ -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus); +static struct ir_scancode ir_codes_avermedia_cardbus[] = { + { 0x00, KEY_POWER }, + { 0x01, KEY_TUNER }, /* TV/FM */ + { 0x03, KEY_TEXT }, /* Teletext */ + { 0x04, KEY_EPG }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x08, KEY_AUDIO }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0c, KEY_ZOOM }, /* Full screen */ + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + { 0x10, KEY_PAGEUP }, /* 16-CH PREV */ + { 0x11, KEY_0 }, + { 0x12, KEY_INFO }, + { 0x13, KEY_AGAIN }, /* CH RTN - channel return */ + { 0x14, KEY_MUTE }, + { 0x15, KEY_EDIT }, /* Autoscan */ + { 0x17, KEY_SAVE }, /* Screenshot */ + { 0x18, KEY_PLAYPAUSE }, + { 0x19, KEY_RECORD }, + { 0x1a, KEY_PLAY }, + { 0x1b, KEY_STOP }, + { 0x1c, KEY_FASTFORWARD }, + { 0x1d, KEY_REWIND }, + { 0x1e, KEY_VOLUMEDOWN }, + { 0x1f, KEY_VOLUMEUP }, + { 0x22, KEY_SLEEP }, /* Sleep */ + { 0x23, KEY_ZOOM }, /* Aspect */ + { 0x26, KEY_SCREEN }, /* Pos */ + { 0x27, KEY_ANGLE }, /* Size */ + { 0x28, KEY_SELECT }, /* Select */ + { 0x29, KEY_BLUE }, /* Blue/Picture */ + { 0x2a, KEY_BACKSPACE }, /* Back */ + { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */ + { 0x2c, KEY_DOWN }, + { 0x2e, KEY_DOT }, + { 0x2f, KEY_TV }, /* Live TV */ + { 0x32, KEY_LEFT }, + { 0x33, KEY_CLEAR }, /* Clear */ + { 0x35, KEY_RED }, /* Red/TV */ + { 0x36, KEY_UP }, + { 0x37, KEY_HOME }, /* Home */ + { 0x39, KEY_GREEN }, /* Green/Video */ + { 0x3d, KEY_YELLOW }, /* Yellow/Music */ + { 0x3e, KEY_OK }, /* Ok */ + { 0x3f, KEY_RIGHT }, + { 0x40, KEY_NEXT }, /* Next */ + { 0x41, KEY_PREVIOUS }, /* Previous */ + { 0x42, KEY_CHANNELDOWN }, /* Channel down */ + { 0x43, KEY_CHANNELUP }, /* Channel up */ +}; + +struct ir_scancode_table ir_codes_avermedia_cardbus_table = { + .scan = ir_codes_avermedia_cardbus, + .size = ARRAY_SIZE(ir_codes_avermedia_cardbus), +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus_table); /* Attila Kondoros */ -IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { - - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - [0x00] = KEY_0, - [0x17] = KEY_LAST, /* +100 */ - [0x0a] = KEY_LIST, /* recall */ - - - [0x1c] = KEY_TUNER, /* TV/FM */ - [0x15] = KEY_SEARCH, /* scan */ - [0x12] = KEY_POWER, /* power */ - [0x1f] = KEY_VOLUMEDOWN, /* vol up */ - [0x1b] = KEY_VOLUMEUP, /* vol down */ - [0x1e] = KEY_CHANNELDOWN, /* chn up */ - [0x1a] = KEY_CHANNELUP, /* chn down */ - - [0x11] = KEY_VIDEO, /* video */ - [0x0f] = KEY_ZOOM, /* full screen */ - [0x13] = KEY_MUTE, /* mute/unmute */ - [0x10] = KEY_TEXT, /* min */ - - [0x0d] = KEY_STOP, /* freeze */ - [0x0e] = KEY_RECORD, /* record */ - [0x1d] = KEY_PLAYPAUSE, /* stop */ - [0x19] = KEY_PLAY, /* play */ - - [0x16] = KEY_GOTO, /* osd */ - [0x14] = KEY_REFRESH, /* default */ - [0x0c] = KEY_KPPLUS, /* fine tune >>>> */ - [0x18] = KEY_KPMINUS, /* fine tune <<<< */ -}; -EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp); +static struct ir_scancode ir_codes_apac_viewcomp[] = { + + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x00, KEY_0 }, + { 0x17, KEY_LAST }, /* +100 */ + { 0x0a, KEY_LIST }, /* recall */ + + + { 0x1c, KEY_TUNER }, /* TV/FM */ + { 0x15, KEY_SEARCH }, /* scan */ + { 0x12, KEY_POWER }, /* power */ + { 0x1f, KEY_VOLUMEDOWN }, /* vol up */ + { 0x1b, KEY_VOLUMEUP }, /* vol down */ + { 0x1e, KEY_CHANNELDOWN }, /* chn up */ + { 0x1a, KEY_CHANNELUP }, /* chn down */ + + { 0x11, KEY_VIDEO }, /* video */ + { 0x0f, KEY_ZOOM }, /* full screen */ + { 0x13, KEY_MUTE }, /* mute/unmute */ + { 0x10, KEY_TEXT }, /* min */ + + { 0x0d, KEY_STOP }, /* freeze */ + { 0x0e, KEY_RECORD }, /* record */ + { 0x1d, KEY_PLAYPAUSE }, /* stop */ + { 0x19, KEY_PLAY }, /* play */ + + { 0x16, KEY_GOTO }, /* osd */ + { 0x14, KEY_REFRESH }, /* default */ + { 0x0c, KEY_KPPLUS }, /* fine tune >>>> */ + { 0x18, KEY_KPMINUS }, /* fine tune <<<< */ +}; + +struct ir_scancode_table ir_codes_apac_viewcomp_table = { + .scan = ir_codes_apac_viewcomp, + .size = ARRAY_SIZE(ir_codes_apac_viewcomp), +}; +EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp_table); /* ---------------------------------------------------------------------- */ -IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_pixelview[] = { - [0x1e] = KEY_POWER, /* power */ - [0x07] = KEY_MEDIA, /* source */ - [0x1c] = KEY_SEARCH, /* scan */ + { 0x1e, KEY_POWER }, /* power */ + { 0x07, KEY_MEDIA }, /* source */ + { 0x1c, KEY_SEARCH }, /* scan */ #if 0 /* FIXME: duplicate keycodes? */ @@ -276,11 +306,11 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { * 6384fb for "Tune <" and "<<<", * 638cfb for "Tune >" and ">>>", regardless of the mask. */ - [0x17] = KEY_BACK, /* fm scan << */ - [0x1f] = KEY_FORWARD, /* fm scan >> */ + { 0x17, KEY_BACK }, /* fm scan << */ + { 0x1f, KEY_FORWARD }, /* fm scan >> */ - [0x04] = KEY_LEFT, /* fm tuning < */ - [0x0c] = KEY_RIGHT, /* fm tuning > */ + { 0x04, KEY_LEFT }, /* fm tuning < */ + { 0x0c, KEY_RIGHT }, /* fm tuning > */ /* * For now, these four keys are disabled. Pressing them will generate @@ -288,326 +318,361 @@ IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = { */ #endif - [0x03] = KEY_TUNER, /* TV/FM */ - - [0x00] = KEY_RECORD, - [0x08] = KEY_STOP, - [0x11] = KEY_PLAY, - - [0x1a] = KEY_PLAYPAUSE, /* freeze */ - [0x19] = KEY_ZOOM, /* zoom */ - [0x0f] = KEY_TEXT, /* min */ - - [0x01] = KEY_1, - [0x0b] = KEY_2, - [0x1b] = KEY_3, - [0x05] = KEY_4, - [0x09] = KEY_5, - [0x15] = KEY_6, - [0x06] = KEY_7, - [0x0a] = KEY_8, - [0x12] = KEY_9, - [0x02] = KEY_0, - [0x10] = KEY_LAST, /* +100 */ - [0x13] = KEY_LIST, /* recall */ - - [0x1f] = KEY_CHANNELUP, /* chn down */ - [0x17] = KEY_CHANNELDOWN, /* chn up */ - [0x16] = KEY_VOLUMEUP, /* vol down */ - [0x14] = KEY_VOLUMEDOWN, /* vol up */ - - [0x04] = KEY_KPMINUS, /* <<< */ - [0x0e] = KEY_SETUP, /* function */ - [0x0c] = KEY_KPPLUS, /* >>> */ + { 0x03, KEY_TUNER }, /* TV/FM */ + + { 0x00, KEY_RECORD }, + { 0x08, KEY_STOP }, + { 0x11, KEY_PLAY }, + + { 0x1a, KEY_PLAYPAUSE }, /* freeze */ + { 0x19, KEY_ZOOM }, /* zoom */ + { 0x0f, KEY_TEXT }, /* min */ + + { 0x01, KEY_1 }, + { 0x0b, KEY_2 }, + { 0x1b, KEY_3 }, + { 0x05, KEY_4 }, + { 0x09, KEY_5 }, + { 0x15, KEY_6 }, + { 0x06, KEY_7 }, + { 0x0a, KEY_8 }, + { 0x12, KEY_9 }, + { 0x02, KEY_0 }, + { 0x10, KEY_LAST }, /* +100 */ + { 0x13, KEY_LIST }, /* recall */ + + { 0x1f, KEY_CHANNELUP }, /* chn down */ + { 0x17, KEY_CHANNELDOWN }, /* chn up */ + { 0x16, KEY_VOLUMEUP }, /* vol down */ + { 0x14, KEY_VOLUMEDOWN }, /* vol up */ + + { 0x04, KEY_KPMINUS }, /* <<< */ + { 0x0e, KEY_SETUP }, /* function */ + { 0x0c, KEY_KPPLUS }, /* >>> */ + + { 0x0d, KEY_GOTO }, /* mts */ + { 0x1d, KEY_REFRESH }, /* reset */ + { 0x18, KEY_MUTE }, /* mute/unmute */ +}; - [0x0d] = KEY_GOTO, /* mts */ - [0x1d] = KEY_REFRESH, /* reset */ - [0x18] = KEY_MUTE, /* mute/unmute */ +struct ir_scancode_table ir_codes_pixelview_table = { + .scan = ir_codes_pixelview, + .size = ARRAY_SIZE(ir_codes_pixelview), }; -EXPORT_SYMBOL_GPL(ir_codes_pixelview); +EXPORT_SYMBOL_GPL(ir_codes_pixelview_table); /* Mauro Carvalho Chehab present on PV MPEG 8000GT */ -IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE] = { - [0x3c] = KEY_TIME, /* Timeshift */ - [0x12] = KEY_POWER, - - [0x3d] = KEY_1, - [0x38] = KEY_2, - [0x18] = KEY_3, - [0x35] = KEY_4, - [0x39] = KEY_5, - [0x15] = KEY_6, - [0x36] = KEY_7, - [0x3a] = KEY_8, - [0x1e] = KEY_9, - [0x3e] = KEY_0, - - [0x1c] = KEY_AGAIN, /* LOOP */ - [0x3f] = KEY_MEDIA, /* Source */ - [0x1f] = KEY_LAST, /* +100 */ - [0x1b] = KEY_MUTE, - - [0x17] = KEY_CHANNELDOWN, - [0x16] = KEY_CHANNELUP, - [0x10] = KEY_VOLUMEUP, - [0x14] = KEY_VOLUMEDOWN, - [0x13] = KEY_ZOOM, - - [0x19] = KEY_CAMERA, /* SNAPSHOT */ - [0x1a] = KEY_SEARCH, /* scan */ - - [0x37] = KEY_REWIND, /* << */ - [0x32] = KEY_RECORD, /* o (red) */ - [0x33] = KEY_FORWARD, /* >> */ - [0x11] = KEY_STOP, /* square */ - [0x3b] = KEY_PLAY, /* > */ - [0x30] = KEY_PLAYPAUSE, /* || */ - - [0x31] = KEY_TV, - [0x34] = KEY_RADIO, -}; -EXPORT_SYMBOL_GPL(ir_codes_pixelview_new); - -IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - [0x0a] = KEY_TV, - [0x0b] = KEY_AUX, - [0x0c] = KEY_DVD, - [0x0d] = KEY_POWER, - [0x0e] = KEY_MHP, /* labelled 'Picture' */ - [0x0f] = KEY_AUDIO, - [0x10] = KEY_INFO, - [0x11] = KEY_F13, /* 16:9 */ - [0x12] = KEY_F14, /* 14:9 */ - [0x13] = KEY_EPG, - [0x14] = KEY_EXIT, - [0x15] = KEY_MENU, - [0x16] = KEY_UP, - [0x17] = KEY_DOWN, - [0x18] = KEY_LEFT, - [0x19] = KEY_RIGHT, - [0x1a] = KEY_ENTER, - [0x1b] = KEY_CHANNELUP, - [0x1c] = KEY_CHANNELDOWN, - [0x1d] = KEY_VOLUMEUP, - [0x1e] = KEY_VOLUMEDOWN, - [0x1f] = KEY_RED, - [0x20] = KEY_GREEN, - [0x21] = KEY_YELLOW, - [0x22] = KEY_BLUE, - [0x23] = KEY_SUBTITLE, - [0x24] = KEY_F15, /* AD */ - [0x25] = KEY_TEXT, - [0x26] = KEY_MUTE, - [0x27] = KEY_REWIND, - [0x28] = KEY_STOP, - [0x29] = KEY_PLAY, - [0x2a] = KEY_FASTFORWARD, - [0x2b] = KEY_F16, /* chapter */ - [0x2c] = KEY_PAUSE, - [0x2d] = KEY_PLAY, - [0x2e] = KEY_RECORD, - [0x2f] = KEY_F17, /* picture in picture */ - [0x30] = KEY_KPPLUS, /* zoom in */ - [0x31] = KEY_KPMINUS, /* zoom out */ - [0x32] = KEY_F18, /* capture */ - [0x33] = KEY_F19, /* web */ - [0x34] = KEY_EMAIL, - [0x35] = KEY_PHONE, - [0x36] = KEY_PC, -}; -EXPORT_SYMBOL_GPL(ir_codes_nebula); +static struct ir_scancode ir_codes_pixelview_new[] = { + { 0x3c, KEY_TIME }, /* Timeshift */ + { 0x12, KEY_POWER }, + + { 0x3d, KEY_1 }, + { 0x38, KEY_2 }, + { 0x18, KEY_3 }, + { 0x35, KEY_4 }, + { 0x39, KEY_5 }, + { 0x15, KEY_6 }, + { 0x36, KEY_7 }, + { 0x3a, KEY_8 }, + { 0x1e, KEY_9 }, + { 0x3e, KEY_0 }, + + { 0x1c, KEY_AGAIN }, /* LOOP */ + { 0x3f, KEY_MEDIA }, /* Source */ + { 0x1f, KEY_LAST }, /* +100 */ + { 0x1b, KEY_MUTE }, + + { 0x17, KEY_CHANNELDOWN }, + { 0x16, KEY_CHANNELUP }, + { 0x10, KEY_VOLUMEUP }, + { 0x14, KEY_VOLUMEDOWN }, + { 0x13, KEY_ZOOM }, + + { 0x19, KEY_CAMERA }, /* SNAPSHOT */ + { 0x1a, KEY_SEARCH }, /* scan */ + + { 0x37, KEY_REWIND }, /* << */ + { 0x32, KEY_RECORD }, /* o (red) */ + { 0x33, KEY_FORWARD }, /* >> */ + { 0x11, KEY_STOP }, /* square */ + { 0x3b, KEY_PLAY }, /* > */ + { 0x30, KEY_PLAYPAUSE }, /* || */ + + { 0x31, KEY_TV }, + { 0x34, KEY_RADIO }, +}; + +struct ir_scancode_table ir_codes_pixelview_new_table = { + .scan = ir_codes_pixelview_new, + .size = ARRAY_SIZE(ir_codes_pixelview_new), +}; +EXPORT_SYMBOL_GPL(ir_codes_pixelview_new_table); + +static struct ir_scancode ir_codes_nebula[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x0a, KEY_TV }, + { 0x0b, KEY_AUX }, + { 0x0c, KEY_DVD }, + { 0x0d, KEY_POWER }, + { 0x0e, KEY_MHP }, /* labelled 'Picture' */ + { 0x0f, KEY_AUDIO }, + { 0x10, KEY_INFO }, + { 0x11, KEY_F13 }, /* 16:9 */ + { 0x12, KEY_F14 }, /* 14:9 */ + { 0x13, KEY_EPG }, + { 0x14, KEY_EXIT }, + { 0x15, KEY_MENU }, + { 0x16, KEY_UP }, + { 0x17, KEY_DOWN }, + { 0x18, KEY_LEFT }, + { 0x19, KEY_RIGHT }, + { 0x1a, KEY_ENTER }, + { 0x1b, KEY_CHANNELUP }, + { 0x1c, KEY_CHANNELDOWN }, + { 0x1d, KEY_VOLUMEUP }, + { 0x1e, KEY_VOLUMEDOWN }, + { 0x1f, KEY_RED }, + { 0x20, KEY_GREEN }, + { 0x21, KEY_YELLOW }, + { 0x22, KEY_BLUE }, + { 0x23, KEY_SUBTITLE }, + { 0x24, KEY_F15 }, /* AD */ + { 0x25, KEY_TEXT }, + { 0x26, KEY_MUTE }, + { 0x27, KEY_REWIND }, + { 0x28, KEY_STOP }, + { 0x29, KEY_PLAY }, + { 0x2a, KEY_FASTFORWARD }, + { 0x2b, KEY_F16 }, /* chapter */ + { 0x2c, KEY_PAUSE }, + { 0x2d, KEY_PLAY }, + { 0x2e, KEY_RECORD }, + { 0x2f, KEY_F17 }, /* picture in picture */ + { 0x30, KEY_KPPLUS }, /* zoom in */ + { 0x31, KEY_KPMINUS }, /* zoom out */ + { 0x32, KEY_F18 }, /* capture */ + { 0x33, KEY_F19 }, /* web */ + { 0x34, KEY_EMAIL }, + { 0x35, KEY_PHONE }, + { 0x36, KEY_PC }, +}; + +struct ir_scancode_table ir_codes_nebula_table = { + .scan = ir_codes_nebula, + .size = ARRAY_SIZE(ir_codes_nebula), +}; +EXPORT_SYMBOL_GPL(ir_codes_nebula_table); /* DigitalNow DNTV Live DVB-T Remote */ -IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = { - [0x00] = KEY_ESC, /* 'go up a level?' */ +static struct ir_scancode ir_codes_dntv_live_dvb_t[] = { + { 0x00, KEY_ESC }, /* 'go up a level?' */ /* Keys 0 to 9 */ - [0x0a] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - - [0x0b] = KEY_TUNER, /* tv/fm */ - [0x0c] = KEY_SEARCH, /* scan */ - [0x0d] = KEY_STOP, - [0x0e] = KEY_PAUSE, - [0x0f] = KEY_LIST, /* source */ - - [0x10] = KEY_MUTE, - [0x11] = KEY_REWIND, /* backward << */ - [0x12] = KEY_POWER, - [0x13] = KEY_CAMERA, /* snap */ - [0x14] = KEY_AUDIO, /* stereo */ - [0x15] = KEY_CLEAR, /* reset */ - [0x16] = KEY_PLAY, - [0x17] = KEY_ENTER, - [0x18] = KEY_ZOOM, /* full screen */ - [0x19] = KEY_FASTFORWARD, /* forward >> */ - [0x1a] = KEY_CHANNELUP, - [0x1b] = KEY_VOLUMEUP, - [0x1c] = KEY_INFO, /* preview */ - [0x1d] = KEY_RECORD, /* record */ - [0x1e] = KEY_CHANNELDOWN, - [0x1f] = KEY_VOLUMEDOWN, -}; -EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t); + { 0x0a, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0b, KEY_TUNER }, /* tv/fm */ + { 0x0c, KEY_SEARCH }, /* scan */ + { 0x0d, KEY_STOP }, + { 0x0e, KEY_PAUSE }, + { 0x0f, KEY_LIST }, /* source */ + + { 0x10, KEY_MUTE }, + { 0x11, KEY_REWIND }, /* backward << */ + { 0x12, KEY_POWER }, + { 0x13, KEY_CAMERA }, /* snap */ + { 0x14, KEY_AUDIO }, /* stereo */ + { 0x15, KEY_CLEAR }, /* reset */ + { 0x16, KEY_PLAY }, + { 0x17, KEY_ENTER }, + { 0x18, KEY_ZOOM }, /* full screen */ + { 0x19, KEY_FASTFORWARD }, /* forward >> */ + { 0x1a, KEY_CHANNELUP }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1c, KEY_INFO }, /* preview */ + { 0x1d, KEY_RECORD }, /* record */ + { 0x1e, KEY_CHANNELDOWN }, + { 0x1f, KEY_VOLUMEDOWN }, +}; + +struct ir_scancode_table ir_codes_dntv_live_dvb_t_table = { + .scan = ir_codes_dntv_live_dvb_t, + .size = ARRAY_SIZE(ir_codes_dntv_live_dvb_t), +}; +EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t_table); /* ---------------------------------------------------------------------- */ /* IO-DATA BCTV7E Remote */ -IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = { - [0x40] = KEY_TV, - [0x20] = KEY_RADIO, /* FM */ - [0x60] = KEY_EPG, - [0x00] = KEY_POWER, +static struct ir_scancode ir_codes_iodata_bctv7e[] = { + { 0x40, KEY_TV }, + { 0x20, KEY_RADIO }, /* FM */ + { 0x60, KEY_EPG }, + { 0x00, KEY_POWER }, /* Keys 0 to 9 */ - [0x44] = KEY_0, /* 10 */ - [0x50] = KEY_1, - [0x30] = KEY_2, - [0x70] = KEY_3, - [0x48] = KEY_4, - [0x28] = KEY_5, - [0x68] = KEY_6, - [0x58] = KEY_7, - [0x38] = KEY_8, - [0x78] = KEY_9, - - [0x10] = KEY_L, /* Live */ - [0x08] = KEY_TIME, /* Time Shift */ - - [0x18] = KEY_PLAYPAUSE, /* Play */ - - [0x24] = KEY_ENTER, /* 11 */ - [0x64] = KEY_ESC, /* 12 */ - [0x04] = KEY_M, /* Multi */ - - [0x54] = KEY_VIDEO, - [0x34] = KEY_CHANNELUP, - [0x74] = KEY_VOLUMEUP, - [0x14] = KEY_MUTE, - - [0x4c] = KEY_VCR, /* SVIDEO */ - [0x2c] = KEY_CHANNELDOWN, - [0x6c] = KEY_VOLUMEDOWN, - [0x0c] = KEY_ZOOM, - - [0x5c] = KEY_PAUSE, - [0x3c] = KEY_RED, /* || (red) */ - [0x7c] = KEY_RECORD, /* recording */ - [0x1c] = KEY_STOP, - - [0x41] = KEY_REWIND, /* backward << */ - [0x21] = KEY_PLAY, - [0x61] = KEY_FASTFORWARD, /* forward >> */ - [0x01] = KEY_NEXT, /* skip >| */ -}; -EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e); + { 0x44, KEY_0 }, /* 10 */ + { 0x50, KEY_1 }, + { 0x30, KEY_2 }, + { 0x70, KEY_3 }, + { 0x48, KEY_4 }, + { 0x28, KEY_5 }, + { 0x68, KEY_6 }, + { 0x58, KEY_7 }, + { 0x38, KEY_8 }, + { 0x78, KEY_9 }, + + { 0x10, KEY_L }, /* Live */ + { 0x08, KEY_TIME }, /* Time Shift */ + + { 0x18, KEY_PLAYPAUSE }, /* Play */ + + { 0x24, KEY_ENTER }, /* 11 */ + { 0x64, KEY_ESC }, /* 12 */ + { 0x04, KEY_M }, /* Multi */ + + { 0x54, KEY_VIDEO }, + { 0x34, KEY_CHANNELUP }, + { 0x74, KEY_VOLUMEUP }, + { 0x14, KEY_MUTE }, + + { 0x4c, KEY_VCR }, /* SVIDEO */ + { 0x2c, KEY_CHANNELDOWN }, + { 0x6c, KEY_VOLUMEDOWN }, + { 0x0c, KEY_ZOOM }, + + { 0x5c, KEY_PAUSE }, + { 0x3c, KEY_RED }, /* || (red) */ + { 0x7c, KEY_RECORD }, /* recording */ + { 0x1c, KEY_STOP }, + + { 0x41, KEY_REWIND }, /* backward << */ + { 0x21, KEY_PLAY }, + { 0x61, KEY_FASTFORWARD }, /* forward >> */ + { 0x01, KEY_NEXT }, /* skip >| */ +}; + +struct ir_scancode_table ir_codes_iodata_bctv7e_table = { + .scan = ir_codes_iodata_bctv7e, + .size = ARRAY_SIZE(ir_codes_iodata_bctv7e), +}; +EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e_table); /* ---------------------------------------------------------------------- */ /* ADS Tech Instant TV DVB-T PCI Remote */ -IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_adstech_dvb_t_pci[] = { /* Keys 0 to 9 */ - [0x4d] = KEY_0, - [0x57] = KEY_1, - [0x4f] = KEY_2, - [0x53] = KEY_3, - [0x56] = KEY_4, - [0x4e] = KEY_5, - [0x5e] = KEY_6, - [0x54] = KEY_7, - [0x4c] = KEY_8, - [0x5c] = KEY_9, - - [0x5b] = KEY_POWER, - [0x5f] = KEY_MUTE, - [0x55] = KEY_GOTO, - [0x5d] = KEY_SEARCH, - [0x17] = KEY_EPG, /* Guide */ - [0x1f] = KEY_MENU, - [0x0f] = KEY_UP, - [0x46] = KEY_DOWN, - [0x16] = KEY_LEFT, - [0x1e] = KEY_RIGHT, - [0x0e] = KEY_SELECT, /* Enter */ - [0x5a] = KEY_INFO, - [0x52] = KEY_EXIT, - [0x59] = KEY_PREVIOUS, - [0x51] = KEY_NEXT, - [0x58] = KEY_REWIND, - [0x50] = KEY_FORWARD, - [0x44] = KEY_PLAYPAUSE, - [0x07] = KEY_STOP, - [0x1b] = KEY_RECORD, - [0x13] = KEY_TUNER, /* Live */ - [0x0a] = KEY_A, - [0x12] = KEY_B, - [0x03] = KEY_PROG1, /* 1 */ - [0x01] = KEY_PROG2, /* 2 */ - [0x00] = KEY_PROG3, /* 3 */ - [0x06] = KEY_DVD, - [0x48] = KEY_AUX, /* Photo */ - [0x40] = KEY_VIDEO, - [0x19] = KEY_AUDIO, /* Music */ - [0x0b] = KEY_CHANNELUP, - [0x08] = KEY_CHANNELDOWN, - [0x15] = KEY_VOLUMEUP, - [0x1c] = KEY_VOLUMEDOWN, -}; -EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci); + { 0x4d, KEY_0 }, + { 0x57, KEY_1 }, + { 0x4f, KEY_2 }, + { 0x53, KEY_3 }, + { 0x56, KEY_4 }, + { 0x4e, KEY_5 }, + { 0x5e, KEY_6 }, + { 0x54, KEY_7 }, + { 0x4c, KEY_8 }, + { 0x5c, KEY_9 }, + + { 0x5b, KEY_POWER }, + { 0x5f, KEY_MUTE }, + { 0x55, KEY_GOTO }, + { 0x5d, KEY_SEARCH }, + { 0x17, KEY_EPG }, /* Guide */ + { 0x1f, KEY_MENU }, + { 0x0f, KEY_UP }, + { 0x46, KEY_DOWN }, + { 0x16, KEY_LEFT }, + { 0x1e, KEY_RIGHT }, + { 0x0e, KEY_SELECT }, /* Enter */ + { 0x5a, KEY_INFO }, + { 0x52, KEY_EXIT }, + { 0x59, KEY_PREVIOUS }, + { 0x51, KEY_NEXT }, + { 0x58, KEY_REWIND }, + { 0x50, KEY_FORWARD }, + { 0x44, KEY_PLAYPAUSE }, + { 0x07, KEY_STOP }, + { 0x1b, KEY_RECORD }, + { 0x13, KEY_TUNER }, /* Live */ + { 0x0a, KEY_A }, + { 0x12, KEY_B }, + { 0x03, KEY_PROG1 }, /* 1 */ + { 0x01, KEY_PROG2 }, /* 2 */ + { 0x00, KEY_PROG3 }, /* 3 */ + { 0x06, KEY_DVD }, + { 0x48, KEY_AUX }, /* Photo */ + { 0x40, KEY_VIDEO }, + { 0x19, KEY_AUDIO }, /* Music */ + { 0x0b, KEY_CHANNELUP }, + { 0x08, KEY_CHANNELDOWN }, + { 0x15, KEY_VOLUMEUP }, + { 0x1c, KEY_VOLUMEDOWN }, +}; + +struct ir_scancode_table ir_codes_adstech_dvb_t_pci_table = { + .scan = ir_codes_adstech_dvb_t_pci, + .size = ARRAY_SIZE(ir_codes_adstech_dvb_t_pci), +}; +EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci_table); /* ---------------------------------------------------------------------- */ /* MSI TV@nywhere MASTER remote */ -IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_msi_tvanywhere[] = { /* Keys 0 to 9 */ - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - - [0x0c] = KEY_MUTE, - [0x0f] = KEY_SCREEN, /* Full Screen */ - [0x10] = KEY_FN, /* Funtion */ - [0x11] = KEY_TIME, /* Time shift */ - [0x12] = KEY_POWER, - [0x13] = KEY_MEDIA, /* MTS */ - [0x14] = KEY_SLOW, - [0x16] = KEY_REWIND, /* backward << */ - [0x17] = KEY_ENTER, /* Return */ - [0x18] = KEY_FASTFORWARD, /* forward >> */ - [0x1a] = KEY_CHANNELUP, - [0x1b] = KEY_VOLUMEUP, - [0x1e] = KEY_CHANNELDOWN, - [0x1f] = KEY_VOLUMEDOWN, -}; -EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere); + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0c, KEY_MUTE }, + { 0x0f, KEY_SCREEN }, /* Full Screen */ + { 0x10, KEY_FN }, /* Funtion */ + { 0x11, KEY_TIME }, /* Time shift */ + { 0x12, KEY_POWER }, + { 0x13, KEY_MEDIA }, /* MTS */ + { 0x14, KEY_SLOW }, + { 0x16, KEY_REWIND }, /* backward << */ + { 0x17, KEY_ENTER }, /* Return */ + { 0x18, KEY_FASTFORWARD }, /* forward >> */ + { 0x1a, KEY_CHANNELUP }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1e, KEY_CHANNELDOWN }, + { 0x1f, KEY_VOLUMEDOWN }, +}; + +struct ir_scancode_table ir_codes_msi_tvanywhere_table = { + .scan = ir_codes_msi_tvanywhere, + .size = ARRAY_SIZE(ir_codes_msi_tvanywhere), +}; +EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_table); /* ---------------------------------------------------------------------- */ @@ -626,7 +691,7 @@ EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere); */ -IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_msi_tvanywhere_plus[] = { /* ---- Remote Button Layout ---- @@ -648,567 +713,627 @@ IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = { << FUNC >> RESET */ - [0x01] = KEY_1, /* 1 */ - [0x0b] = KEY_2, /* 2 */ - [0x1b] = KEY_3, /* 3 */ - [0x05] = KEY_4, /* 4 */ - [0x09] = KEY_5, /* 5 */ - [0x15] = KEY_6, /* 6 */ - [0x06] = KEY_7, /* 7 */ - [0x0a] = KEY_8, /* 8 */ - [0x12] = KEY_9, /* 9 */ - [0x02] = KEY_0, /* 0 */ - [0x10] = KEY_KPPLUS, /* + */ - [0x13] = KEY_AGAIN, /* Recall */ - - [0x1e] = KEY_POWER, /* Power */ - [0x07] = KEY_TUNER, /* Source */ - [0x1c] = KEY_SEARCH, /* Scan */ - [0x18] = KEY_MUTE, /* Mute */ - - [0x03] = KEY_RADIO, /* TV/FM */ + { 0x01, KEY_1 }, /* 1 */ + { 0x0b, KEY_2 }, /* 2 */ + { 0x1b, KEY_3 }, /* 3 */ + { 0x05, KEY_4 }, /* 4 */ + { 0x09, KEY_5 }, /* 5 */ + { 0x15, KEY_6 }, /* 6 */ + { 0x06, KEY_7 }, /* 7 */ + { 0x0a, KEY_8 }, /* 8 */ + { 0x12, KEY_9 }, /* 9 */ + { 0x02, KEY_0 }, /* 0 */ + { 0x10, KEY_KPPLUS }, /* + */ + { 0x13, KEY_AGAIN }, /* Recall */ + + { 0x1e, KEY_POWER }, /* Power */ + { 0x07, KEY_TUNER }, /* Source */ + { 0x1c, KEY_SEARCH }, /* Scan */ + { 0x18, KEY_MUTE }, /* Mute */ + + { 0x03, KEY_RADIO }, /* TV/FM */ /* The next four keys are duplicates that appear to send the same IR code as Ch+, Ch-, >>, and << . The raw code assigned to them is the actual code + 0x20 - they will never be detected as such unless some way is discovered to distinguish these buttons from those that have the same code. */ - [0x3f] = KEY_RIGHT, /* |> and Ch+ */ - [0x37] = KEY_LEFT, /* <| and Ch- */ - [0x2c] = KEY_UP, /* ^^Up and >> */ - [0x24] = KEY_DOWN, /* vvDn and << */ - - [0x00] = KEY_RECORD, /* Record */ - [0x08] = KEY_STOP, /* Stop */ - [0x11] = KEY_PLAY, /* Play */ - - [0x0f] = KEY_CLOSE, /* Minimize */ - [0x19] = KEY_ZOOM, /* Zoom */ - [0x1a] = KEY_CAMERA, /* Snapshot */ - [0x0d] = KEY_LANGUAGE, /* MTS */ - - [0x14] = KEY_VOLUMEDOWN,/* Vol- */ - [0x16] = KEY_VOLUMEUP, /* Vol+ */ - [0x17] = KEY_CHANNELDOWN,/* Ch- */ - [0x1f] = KEY_CHANNELUP, /* Ch+ */ + { 0x3f, KEY_RIGHT }, /* |> and Ch+ */ + { 0x37, KEY_LEFT }, /* <| and Ch- */ + { 0x2c, KEY_UP }, /* ^^Up and >> */ + { 0x24, KEY_DOWN }, /* vvDn and << */ + + { 0x00, KEY_RECORD }, /* Record */ + { 0x08, KEY_STOP }, /* Stop */ + { 0x11, KEY_PLAY }, /* Play */ + + { 0x0f, KEY_CLOSE }, /* Minimize */ + { 0x19, KEY_ZOOM }, /* Zoom */ + { 0x1a, KEY_CAMERA }, /* Snapshot */ + { 0x0d, KEY_LANGUAGE }, /* MTS */ + + { 0x14, KEY_VOLUMEDOWN }, /* Vol- */ + { 0x16, KEY_VOLUMEUP }, /* Vol+ */ + { 0x17, KEY_CHANNELDOWN }, /* Ch- */ + { 0x1f, KEY_CHANNELUP }, /* Ch+ */ + + { 0x04, KEY_REWIND }, /* << */ + { 0x0e, KEY_MENU }, /* Function */ + { 0x0c, KEY_FASTFORWARD }, /* >> */ + { 0x1d, KEY_RESTART }, /* Reset */ +}; - [0x04] = KEY_REWIND, /* << */ - [0x0e] = KEY_MENU, /* Function */ - [0x0c] = KEY_FASTFORWARD,/* >> */ - [0x1d] = KEY_RESTART, /* Reset */ +struct ir_scancode_table ir_codes_msi_tvanywhere_plus_table = { + .scan = ir_codes_msi_tvanywhere_plus, + .size = ARRAY_SIZE(ir_codes_msi_tvanywhere_plus), }; -EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus); +EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus_table); /* ---------------------------------------------------------------------- */ /* Cinergy 1400 DVB-T */ -IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { - [0x01] = KEY_POWER, - [0x02] = KEY_1, - [0x03] = KEY_2, - [0x04] = KEY_3, - [0x05] = KEY_4, - [0x06] = KEY_5, - [0x07] = KEY_6, - [0x08] = KEY_7, - [0x09] = KEY_8, - [0x0a] = KEY_9, - [0x0c] = KEY_0, - - [0x0b] = KEY_VIDEO, - [0x0d] = KEY_REFRESH, - [0x0e] = KEY_SELECT, - [0x0f] = KEY_EPG, - [0x10] = KEY_UP, - [0x11] = KEY_LEFT, - [0x12] = KEY_OK, - [0x13] = KEY_RIGHT, - [0x14] = KEY_DOWN, - [0x15] = KEY_TEXT, - [0x16] = KEY_INFO, - - [0x17] = KEY_RED, - [0x18] = KEY_GREEN, - [0x19] = KEY_YELLOW, - [0x1a] = KEY_BLUE, - - [0x1b] = KEY_CHANNELUP, - [0x1c] = KEY_VOLUMEUP, - [0x1d] = KEY_MUTE, - [0x1e] = KEY_VOLUMEDOWN, - [0x1f] = KEY_CHANNELDOWN, - - [0x40] = KEY_PAUSE, - [0x4c] = KEY_PLAY, - [0x58] = KEY_RECORD, - [0x54] = KEY_PREVIOUS, - [0x48] = KEY_STOP, - [0x5c] = KEY_NEXT, -}; -EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400); +static struct ir_scancode ir_codes_cinergy_1400[] = { + { 0x01, KEY_POWER }, + { 0x02, KEY_1 }, + { 0x03, KEY_2 }, + { 0x04, KEY_3 }, + { 0x05, KEY_4 }, + { 0x06, KEY_5 }, + { 0x07, KEY_6 }, + { 0x08, KEY_7 }, + { 0x09, KEY_8 }, + { 0x0a, KEY_9 }, + { 0x0c, KEY_0 }, + + { 0x0b, KEY_VIDEO }, + { 0x0d, KEY_REFRESH }, + { 0x0e, KEY_SELECT }, + { 0x0f, KEY_EPG }, + { 0x10, KEY_UP }, + { 0x11, KEY_LEFT }, + { 0x12, KEY_OK }, + { 0x13, KEY_RIGHT }, + { 0x14, KEY_DOWN }, + { 0x15, KEY_TEXT }, + { 0x16, KEY_INFO }, + + { 0x17, KEY_RED }, + { 0x18, KEY_GREEN }, + { 0x19, KEY_YELLOW }, + { 0x1a, KEY_BLUE }, + + { 0x1b, KEY_CHANNELUP }, + { 0x1c, KEY_VOLUMEUP }, + { 0x1d, KEY_MUTE }, + { 0x1e, KEY_VOLUMEDOWN }, + { 0x1f, KEY_CHANNELDOWN }, + + { 0x40, KEY_PAUSE }, + { 0x4c, KEY_PLAY }, + { 0x58, KEY_RECORD }, + { 0x54, KEY_PREVIOUS }, + { 0x48, KEY_STOP }, + { 0x5c, KEY_NEXT }, +}; + +struct ir_scancode_table ir_codes_cinergy_1400_table = { + .scan = ir_codes_cinergy_1400, + .size = ARRAY_SIZE(ir_codes_cinergy_1400), +}; +EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400_table); /* ---------------------------------------------------------------------- */ /* AVERTV STUDIO 303 Remote */ -IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = { - [0x2a] = KEY_1, - [0x32] = KEY_2, - [0x3a] = KEY_3, - [0x4a] = KEY_4, - [0x52] = KEY_5, - [0x5a] = KEY_6, - [0x6a] = KEY_7, - [0x72] = KEY_8, - [0x7a] = KEY_9, - [0x0e] = KEY_0, - - [0x02] = KEY_POWER, - [0x22] = KEY_VIDEO, - [0x42] = KEY_AUDIO, - [0x62] = KEY_ZOOM, - [0x0a] = KEY_TV, - [0x12] = KEY_CD, - [0x1a] = KEY_TEXT, - - [0x16] = KEY_SUBTITLE, - [0x1e] = KEY_REWIND, - [0x06] = KEY_PRINT, - - [0x2e] = KEY_SEARCH, - [0x36] = KEY_SLEEP, - [0x3e] = KEY_SHUFFLE, - [0x26] = KEY_MUTE, - - [0x4e] = KEY_RECORD, - [0x56] = KEY_PAUSE, - [0x5e] = KEY_STOP, - [0x46] = KEY_PLAY, - - [0x6e] = KEY_RED, - [0x0b] = KEY_GREEN, - [0x66] = KEY_YELLOW, - [0x03] = KEY_BLUE, - - [0x76] = KEY_LEFT, - [0x7e] = KEY_RIGHT, - [0x13] = KEY_DOWN, - [0x1b] = KEY_UP, -}; -EXPORT_SYMBOL_GPL(ir_codes_avertv_303); +static struct ir_scancode ir_codes_avertv_303[] = { + { 0x2a, KEY_1 }, + { 0x32, KEY_2 }, + { 0x3a, KEY_3 }, + { 0x4a, KEY_4 }, + { 0x52, KEY_5 }, + { 0x5a, KEY_6 }, + { 0x6a, KEY_7 }, + { 0x72, KEY_8 }, + { 0x7a, KEY_9 }, + { 0x0e, KEY_0 }, + + { 0x02, KEY_POWER }, + { 0x22, KEY_VIDEO }, + { 0x42, KEY_AUDIO }, + { 0x62, KEY_ZOOM }, + { 0x0a, KEY_TV }, + { 0x12, KEY_CD }, + { 0x1a, KEY_TEXT }, + + { 0x16, KEY_SUBTITLE }, + { 0x1e, KEY_REWIND }, + { 0x06, KEY_PRINT }, + + { 0x2e, KEY_SEARCH }, + { 0x36, KEY_SLEEP }, + { 0x3e, KEY_SHUFFLE }, + { 0x26, KEY_MUTE }, + + { 0x4e, KEY_RECORD }, + { 0x56, KEY_PAUSE }, + { 0x5e, KEY_STOP }, + { 0x46, KEY_PLAY }, + + { 0x6e, KEY_RED }, + { 0x0b, KEY_GREEN }, + { 0x66, KEY_YELLOW }, + { 0x03, KEY_BLUE }, + + { 0x76, KEY_LEFT }, + { 0x7e, KEY_RIGHT }, + { 0x13, KEY_DOWN }, + { 0x1b, KEY_UP }, +}; + +struct ir_scancode_table ir_codes_avertv_303_table = { + .scan = ir_codes_avertv_303, + .size = ARRAY_SIZE(ir_codes_avertv_303), +}; +EXPORT_SYMBOL_GPL(ir_codes_avertv_303_table); /* ---------------------------------------------------------------------- */ /* DigitalNow DNTV Live! DVB-T Pro Remote */ -IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = { - [0x16] = KEY_POWER, - [0x5b] = KEY_HOME, - - [0x55] = KEY_TV, /* live tv */ - [0x58] = KEY_TUNER, /* digital Radio */ - [0x5a] = KEY_RADIO, /* FM radio */ - [0x59] = KEY_DVD, /* dvd menu */ - [0x03] = KEY_1, - [0x01] = KEY_2, - [0x06] = KEY_3, - [0x09] = KEY_4, - [0x1d] = KEY_5, - [0x1f] = KEY_6, - [0x0d] = KEY_7, - [0x19] = KEY_8, - [0x1b] = KEY_9, - [0x0c] = KEY_CANCEL, - [0x15] = KEY_0, - [0x4a] = KEY_CLEAR, - [0x13] = KEY_BACK, - [0x00] = KEY_TAB, - [0x4b] = KEY_UP, - [0x4e] = KEY_LEFT, - [0x4f] = KEY_OK, - [0x52] = KEY_RIGHT, - [0x51] = KEY_DOWN, - [0x1e] = KEY_VOLUMEUP, - [0x0a] = KEY_VOLUMEDOWN, - [0x02] = KEY_CHANNELDOWN, - [0x05] = KEY_CHANNELUP, - [0x11] = KEY_RECORD, - [0x14] = KEY_PLAY, - [0x4c] = KEY_PAUSE, - [0x1a] = KEY_STOP, - [0x40] = KEY_REWIND, - [0x12] = KEY_FASTFORWARD, - [0x41] = KEY_PREVIOUSSONG, /* replay |< */ - [0x42] = KEY_NEXTSONG, /* skip >| */ - [0x54] = KEY_CAMERA, /* capture */ - [0x50] = KEY_LANGUAGE, /* sap */ - [0x47] = KEY_TV2, /* pip */ - [0x4d] = KEY_SCREEN, - [0x43] = KEY_SUBTITLE, - [0x10] = KEY_MUTE, - [0x49] = KEY_AUDIO, /* l/r */ - [0x07] = KEY_SLEEP, - [0x08] = KEY_VIDEO, /* a/v */ - [0x0e] = KEY_PREVIOUS, /* recall */ - [0x45] = KEY_ZOOM, /* zoom + */ - [0x46] = KEY_ANGLE, /* zoom - */ - [0x56] = KEY_RED, - [0x57] = KEY_GREEN, - [0x5c] = KEY_YELLOW, - [0x5d] = KEY_BLUE, -}; -EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro); - -IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { - [0x01] = KEY_CHANNEL, - [0x02] = KEY_SELECT, - [0x03] = KEY_MUTE, - [0x04] = KEY_POWER, - [0x05] = KEY_1, - [0x06] = KEY_2, - [0x07] = KEY_3, - [0x08] = KEY_CHANNELUP, - [0x09] = KEY_4, - [0x0a] = KEY_5, - [0x0b] = KEY_6, - [0x0c] = KEY_CHANNELDOWN, - [0x0d] = KEY_7, - [0x0e] = KEY_8, - [0x0f] = KEY_9, - [0x10] = KEY_VOLUMEUP, - [0x11] = KEY_0, - [0x12] = KEY_MENU, - [0x13] = KEY_PRINT, - [0x14] = KEY_VOLUMEDOWN, - [0x16] = KEY_PAUSE, - [0x18] = KEY_RECORD, - [0x19] = KEY_REWIND, - [0x1a] = KEY_PLAY, - [0x1b] = KEY_FORWARD, - [0x1c] = KEY_BACKSPACE, - [0x1e] = KEY_STOP, - [0x40] = KEY_ZOOM, -}; -EXPORT_SYMBOL_GPL(ir_codes_em_terratec); - -IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = { - [0x3a] = KEY_0, - [0x31] = KEY_1, - [0x32] = KEY_2, - [0x33] = KEY_3, - [0x34] = KEY_4, - [0x35] = KEY_5, - [0x36] = KEY_6, - [0x37] = KEY_7, - [0x38] = KEY_8, - [0x39] = KEY_9, - - [0x2f] = KEY_POWER, - - [0x2e] = KEY_P, - [0x1f] = KEY_L, - [0x2b] = KEY_I, - - [0x2d] = KEY_SCREEN, - [0x1e] = KEY_ZOOM, - [0x1b] = KEY_VOLUMEUP, - [0x0f] = KEY_VOLUMEDOWN, - [0x17] = KEY_CHANNELUP, - [0x1c] = KEY_CHANNELDOWN, - [0x25] = KEY_INFO, - - [0x3c] = KEY_MUTE, - - [0x3d] = KEY_LEFT, - [0x3b] = KEY_RIGHT, - - [0x3f] = KEY_UP, - [0x3e] = KEY_DOWN, - [0x1a] = KEY_ENTER, - - [0x1d] = KEY_MENU, - [0x19] = KEY_AGAIN, - [0x16] = KEY_PREVIOUSSONG, - [0x13] = KEY_NEXTSONG, - [0x15] = KEY_PAUSE, - [0x0e] = KEY_REWIND, - [0x0d] = KEY_PLAY, - [0x0b] = KEY_STOP, - [0x07] = KEY_FORWARD, - [0x27] = KEY_RECORD, - [0x26] = KEY_TUNER, - [0x29] = KEY_TEXT, - [0x2a] = KEY_MEDIA, - [0x18] = KEY_EPG, -}; -EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey); - -IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = { - [0x0f] = KEY_0, - [0x03] = KEY_1, - [0x04] = KEY_2, - [0x05] = KEY_3, - [0x07] = KEY_4, - [0x08] = KEY_5, - [0x09] = KEY_6, - [0x0b] = KEY_7, - [0x0c] = KEY_8, - [0x0d] = KEY_9, - - [0x0e] = KEY_MODE, /* Air/Cable */ - [0x11] = KEY_VIDEO, /* Video */ - [0x15] = KEY_AUDIO, /* Audio */ - [0x00] = KEY_POWER, /* Power */ - [0x18] = KEY_TUNER, /* AV Source */ - [0x02] = KEY_ZOOM, /* Fullscreen */ - [0x1a] = KEY_LANGUAGE, /* Stereo */ - [0x1b] = KEY_MUTE, /* Mute */ - [0x14] = KEY_VOLUMEUP, /* Volume + */ - [0x17] = KEY_VOLUMEDOWN,/* Volume - */ - [0x12] = KEY_CHANNELUP, /* Channel + */ - [0x13] = KEY_CHANNELDOWN,/* Channel - */ - [0x06] = KEY_AGAIN, /* Recall */ - [0x10] = KEY_ENTER, /* Enter */ - - [0x19] = KEY_BACK, /* Rewind ( <<< ) */ - [0x1f] = KEY_FORWARD, /* Forward ( >>> ) */ - [0x0a] = KEY_ANGLE, /* no label, may be used as the PAUSE button */ -}; -EXPORT_SYMBOL_GPL(ir_codes_flyvideo); - -IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE] = { - [0x01] = KEY_ZOOM, /* Full Screen */ - [0x00] = KEY_POWER, /* Power */ - - [0x03] = KEY_1, - [0x04] = KEY_2, - [0x05] = KEY_3, - [0x07] = KEY_4, - [0x08] = KEY_5, - [0x09] = KEY_6, - [0x0b] = KEY_7, - [0x0c] = KEY_8, - [0x0d] = KEY_9, - [0x06] = KEY_AGAIN, /* Recall */ - [0x0f] = KEY_0, - [0x10] = KEY_MUTE, /* Mute */ - [0x02] = KEY_RADIO, /* TV/Radio */ - [0x1b] = KEY_LANGUAGE, /* SAP (Second Audio Program) */ - - [0x14] = KEY_VOLUMEUP, /* VOL+ */ - [0x17] = KEY_VOLUMEDOWN, /* VOL- */ - [0x12] = KEY_CHANNELUP, /* CH+ */ - [0x13] = KEY_CHANNELDOWN, /* CH- */ - [0x1d] = KEY_ENTER, /* Enter */ - - [0x1a] = KEY_MODE, /* PIP */ - [0x18] = KEY_TUNER, /* Source */ - - [0x1e] = KEY_RECORD, /* Record/Pause */ - [0x15] = KEY_ANGLE, /* Swap (no label on key) */ - [0x1c] = KEY_PAUSE, /* Timeshift/Pause */ - [0x19] = KEY_BACK, /* Rewind << */ - [0x0a] = KEY_PLAYPAUSE, /* Play/Pause */ - [0x1f] = KEY_FORWARD, /* Forward >> */ - [0x16] = KEY_PREVIOUS, /* Back |<< */ - [0x11] = KEY_STOP, /* Stop */ - [0x0e] = KEY_NEXT, /* End >>| */ -}; -EXPORT_SYMBOL_GPL(ir_codes_flydvb); - -IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE] = { - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - - [0x0a] = KEY_POWER, - [0x0b] = KEY_PROG1, /* app */ - [0x0c] = KEY_ZOOM, /* zoom/fullscreen */ - [0x0d] = KEY_CHANNELUP, /* channel */ - [0x0e] = KEY_CHANNELDOWN,/* channel- */ - [0x0f] = KEY_VOLUMEUP, - [0x10] = KEY_VOLUMEDOWN, - [0x11] = KEY_TUNER, /* AV */ - [0x12] = KEY_NUMLOCK, /* -/-- */ - [0x13] = KEY_AUDIO, /* audio */ - [0x14] = KEY_MUTE, - [0x15] = KEY_UP, - [0x16] = KEY_DOWN, - [0x17] = KEY_LEFT, - [0x18] = KEY_RIGHT, - [0x19] = BTN_LEFT, - [0x1a] = BTN_RIGHT, - [0x1b] = KEY_WWW, /* text */ - [0x1c] = KEY_REWIND, - [0x1d] = KEY_FORWARD, - [0x1e] = KEY_RECORD, - [0x1f] = KEY_PLAY, - [0x20] = KEY_PREVIOUSSONG, - [0x21] = KEY_NEXTSONG, - [0x22] = KEY_PAUSE, - [0x23] = KEY_STOP, -}; -EXPORT_SYMBOL_GPL(ir_codes_cinergy); +static struct ir_scancode ir_codes_dntv_live_dvbt_pro[] = { + { 0x16, KEY_POWER }, + { 0x5b, KEY_HOME }, + + { 0x55, KEY_TV }, /* live tv */ + { 0x58, KEY_TUNER }, /* digital Radio */ + { 0x5a, KEY_RADIO }, /* FM radio */ + { 0x59, KEY_DVD }, /* dvd menu */ + { 0x03, KEY_1 }, + { 0x01, KEY_2 }, + { 0x06, KEY_3 }, + { 0x09, KEY_4 }, + { 0x1d, KEY_5 }, + { 0x1f, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x19, KEY_8 }, + { 0x1b, KEY_9 }, + { 0x0c, KEY_CANCEL }, + { 0x15, KEY_0 }, + { 0x4a, KEY_CLEAR }, + { 0x13, KEY_BACK }, + { 0x00, KEY_TAB }, + { 0x4b, KEY_UP }, + { 0x4e, KEY_LEFT }, + { 0x4f, KEY_OK }, + { 0x52, KEY_RIGHT }, + { 0x51, KEY_DOWN }, + { 0x1e, KEY_VOLUMEUP }, + { 0x0a, KEY_VOLUMEDOWN }, + { 0x02, KEY_CHANNELDOWN }, + { 0x05, KEY_CHANNELUP }, + { 0x11, KEY_RECORD }, + { 0x14, KEY_PLAY }, + { 0x4c, KEY_PAUSE }, + { 0x1a, KEY_STOP }, + { 0x40, KEY_REWIND }, + { 0x12, KEY_FASTFORWARD }, + { 0x41, KEY_PREVIOUSSONG }, /* replay |< */ + { 0x42, KEY_NEXTSONG }, /* skip >| */ + { 0x54, KEY_CAMERA }, /* capture */ + { 0x50, KEY_LANGUAGE }, /* sap */ + { 0x47, KEY_TV2 }, /* pip */ + { 0x4d, KEY_SCREEN }, + { 0x43, KEY_SUBTITLE }, + { 0x10, KEY_MUTE }, + { 0x49, KEY_AUDIO }, /* l/r */ + { 0x07, KEY_SLEEP }, + { 0x08, KEY_VIDEO }, /* a/v */ + { 0x0e, KEY_PREVIOUS }, /* recall */ + { 0x45, KEY_ZOOM }, /* zoom + */ + { 0x46, KEY_ANGLE }, /* zoom - */ + { 0x56, KEY_RED }, + { 0x57, KEY_GREEN }, + { 0x5c, KEY_YELLOW }, + { 0x5d, KEY_BLUE }, +}; + +struct ir_scancode_table ir_codes_dntv_live_dvbt_pro_table = { + .scan = ir_codes_dntv_live_dvbt_pro, + .size = ARRAY_SIZE(ir_codes_dntv_live_dvbt_pro), +}; +EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro_table); + +static struct ir_scancode ir_codes_em_terratec[] = { + { 0x01, KEY_CHANNEL }, + { 0x02, KEY_SELECT }, + { 0x03, KEY_MUTE }, + { 0x04, KEY_POWER }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x08, KEY_CHANNELUP }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0c, KEY_CHANNELDOWN }, + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_0 }, + { 0x12, KEY_MENU }, + { 0x13, KEY_PRINT }, + { 0x14, KEY_VOLUMEDOWN }, + { 0x16, KEY_PAUSE }, + { 0x18, KEY_RECORD }, + { 0x19, KEY_REWIND }, + { 0x1a, KEY_PLAY }, + { 0x1b, KEY_FORWARD }, + { 0x1c, KEY_BACKSPACE }, + { 0x1e, KEY_STOP }, + { 0x40, KEY_ZOOM }, +}; + +struct ir_scancode_table ir_codes_em_terratec_table = { + .scan = ir_codes_em_terratec, + .size = ARRAY_SIZE(ir_codes_em_terratec), +}; +EXPORT_SYMBOL_GPL(ir_codes_em_terratec_table); + +static struct ir_scancode ir_codes_pinnacle_grey[] = { + { 0x3a, KEY_0 }, + { 0x31, KEY_1 }, + { 0x32, KEY_2 }, + { 0x33, KEY_3 }, + { 0x34, KEY_4 }, + { 0x35, KEY_5 }, + { 0x36, KEY_6 }, + { 0x37, KEY_7 }, + { 0x38, KEY_8 }, + { 0x39, KEY_9 }, + + { 0x2f, KEY_POWER }, + + { 0x2e, KEY_P }, + { 0x1f, KEY_L }, + { 0x2b, KEY_I }, + + { 0x2d, KEY_SCREEN }, + { 0x1e, KEY_ZOOM }, + { 0x1b, KEY_VOLUMEUP }, + { 0x0f, KEY_VOLUMEDOWN }, + { 0x17, KEY_CHANNELUP }, + { 0x1c, KEY_CHANNELDOWN }, + { 0x25, KEY_INFO }, + + { 0x3c, KEY_MUTE }, + + { 0x3d, KEY_LEFT }, + { 0x3b, KEY_RIGHT }, + + { 0x3f, KEY_UP }, + { 0x3e, KEY_DOWN }, + { 0x1a, KEY_ENTER }, + + { 0x1d, KEY_MENU }, + { 0x19, KEY_AGAIN }, + { 0x16, KEY_PREVIOUSSONG }, + { 0x13, KEY_NEXTSONG }, + { 0x15, KEY_PAUSE }, + { 0x0e, KEY_REWIND }, + { 0x0d, KEY_PLAY }, + { 0x0b, KEY_STOP }, + { 0x07, KEY_FORWARD }, + { 0x27, KEY_RECORD }, + { 0x26, KEY_TUNER }, + { 0x29, KEY_TEXT }, + { 0x2a, KEY_MEDIA }, + { 0x18, KEY_EPG }, +}; + +struct ir_scancode_table ir_codes_pinnacle_grey_table = { + .scan = ir_codes_pinnacle_grey, + .size = ARRAY_SIZE(ir_codes_pinnacle_grey), +}; +EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey_table); + +static struct ir_scancode ir_codes_flyvideo[] = { + { 0x0f, KEY_0 }, + { 0x03, KEY_1 }, + { 0x04, KEY_2 }, + { 0x05, KEY_3 }, + { 0x07, KEY_4 }, + { 0x08, KEY_5 }, + { 0x09, KEY_6 }, + { 0x0b, KEY_7 }, + { 0x0c, KEY_8 }, + { 0x0d, KEY_9 }, + + { 0x0e, KEY_MODE }, /* Air/Cable */ + { 0x11, KEY_VIDEO }, /* Video */ + { 0x15, KEY_AUDIO }, /* Audio */ + { 0x00, KEY_POWER }, /* Power */ + { 0x18, KEY_TUNER }, /* AV Source */ + { 0x02, KEY_ZOOM }, /* Fullscreen */ + { 0x1a, KEY_LANGUAGE }, /* Stereo */ + { 0x1b, KEY_MUTE }, /* Mute */ + { 0x14, KEY_VOLUMEUP }, /* Volume + */ + { 0x17, KEY_VOLUMEDOWN },/* Volume - */ + { 0x12, KEY_CHANNELUP },/* Channel + */ + { 0x13, KEY_CHANNELDOWN },/* Channel - */ + { 0x06, KEY_AGAIN }, /* Recall */ + { 0x10, KEY_ENTER }, /* Enter */ + + { 0x19, KEY_BACK }, /* Rewind ( <<< ) */ + { 0x1f, KEY_FORWARD }, /* Forward ( >>> ) */ + { 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */ +}; + +struct ir_scancode_table ir_codes_flyvideo_table = { + .scan = ir_codes_flyvideo, + .size = ARRAY_SIZE(ir_codes_flyvideo), +}; +EXPORT_SYMBOL_GPL(ir_codes_flyvideo_table); + +static struct ir_scancode ir_codes_flydvb[] = { + { 0x01, KEY_ZOOM }, /* Full Screen */ + { 0x00, KEY_POWER }, /* Power */ + + { 0x03, KEY_1 }, + { 0x04, KEY_2 }, + { 0x05, KEY_3 }, + { 0x07, KEY_4 }, + { 0x08, KEY_5 }, + { 0x09, KEY_6 }, + { 0x0b, KEY_7 }, + { 0x0c, KEY_8 }, + { 0x0d, KEY_9 }, + { 0x06, KEY_AGAIN }, /* Recall */ + { 0x0f, KEY_0 }, + { 0x10, KEY_MUTE }, /* Mute */ + { 0x02, KEY_RADIO }, /* TV/Radio */ + { 0x1b, KEY_LANGUAGE }, /* SAP (Second Audio Program) */ + + { 0x14, KEY_VOLUMEUP }, /* VOL+ */ + { 0x17, KEY_VOLUMEDOWN }, /* VOL- */ + { 0x12, KEY_CHANNELUP }, /* CH+ */ + { 0x13, KEY_CHANNELDOWN }, /* CH- */ + { 0x1d, KEY_ENTER }, /* Enter */ + + { 0x1a, KEY_MODE }, /* PIP */ + { 0x18, KEY_TUNER }, /* Source */ + + { 0x1e, KEY_RECORD }, /* Record/Pause */ + { 0x15, KEY_ANGLE }, /* Swap (no label on key) */ + { 0x1c, KEY_PAUSE }, /* Timeshift/Pause */ + { 0x19, KEY_BACK }, /* Rewind << */ + { 0x0a, KEY_PLAYPAUSE }, /* Play/Pause */ + { 0x1f, KEY_FORWARD }, /* Forward >> */ + { 0x16, KEY_PREVIOUS }, /* Back |<< */ + { 0x11, KEY_STOP }, /* Stop */ + { 0x0e, KEY_NEXT }, /* End >>| */ +}; + +struct ir_scancode_table ir_codes_flydvb_table = { + .scan = ir_codes_flydvb, + .size = ARRAY_SIZE(ir_codes_flydvb), +}; +EXPORT_SYMBOL_GPL(ir_codes_flydvb_table); + +static struct ir_scancode ir_codes_cinergy[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0a, KEY_POWER }, + { 0x0b, KEY_PROG1 }, /* app */ + { 0x0c, KEY_ZOOM }, /* zoom/fullscreen */ + { 0x0d, KEY_CHANNELUP }, /* channel */ + { 0x0e, KEY_CHANNELDOWN }, /* channel- */ + { 0x0f, KEY_VOLUMEUP }, + { 0x10, KEY_VOLUMEDOWN }, + { 0x11, KEY_TUNER }, /* AV */ + { 0x12, KEY_NUMLOCK }, /* -/-- */ + { 0x13, KEY_AUDIO }, /* audio */ + { 0x14, KEY_MUTE }, + { 0x15, KEY_UP }, + { 0x16, KEY_DOWN }, + { 0x17, KEY_LEFT }, + { 0x18, KEY_RIGHT }, + { 0x19, BTN_LEFT, }, + { 0x1a, BTN_RIGHT, }, + { 0x1b, KEY_WWW }, /* text */ + { 0x1c, KEY_REWIND }, + { 0x1d, KEY_FORWARD }, + { 0x1e, KEY_RECORD }, + { 0x1f, KEY_PLAY }, + { 0x20, KEY_PREVIOUSSONG }, + { 0x21, KEY_NEXTSONG }, + { 0x22, KEY_PAUSE }, + { 0x23, KEY_STOP }, +}; + +struct ir_scancode_table ir_codes_cinergy_table = { + .scan = ir_codes_cinergy, + .size = ARRAY_SIZE(ir_codes_cinergy), +}; +EXPORT_SYMBOL_GPL(ir_codes_cinergy_table); /* Alfons Geser * updates from Job D. R. Borges */ -IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE] = { - [0x12] = KEY_POWER, - [0x01] = KEY_TV, /* DVR */ - [0x15] = KEY_DVD, /* DVD */ - [0x17] = KEY_AUDIO, /* music */ +static struct ir_scancode ir_codes_eztv[] = { + { 0x12, KEY_POWER }, + { 0x01, KEY_TV }, /* DVR */ + { 0x15, KEY_DVD }, /* DVD */ + { 0x17, KEY_AUDIO }, /* music */ /* DVR mode / DVD mode / music mode */ - [0x1b] = KEY_MUTE, /* mute */ - [0x02] = KEY_LANGUAGE, /* MTS/SAP / audio / autoseek */ - [0x1e] = KEY_SUBTITLE, /* closed captioning / subtitle / seek */ - [0x16] = KEY_ZOOM, /* full screen */ - [0x1c] = KEY_VIDEO, /* video source / eject / delall */ - [0x1d] = KEY_RESTART, /* playback / angle / del */ - [0x2f] = KEY_SEARCH, /* scan / menu / playlist */ - [0x30] = KEY_CHANNEL, /* CH surfing / bookmark / memo */ - - [0x31] = KEY_HELP, /* help */ - [0x32] = KEY_MODE, /* num/memo */ - [0x33] = KEY_ESC, /* cancel */ - - [0x0c] = KEY_UP, /* up */ - [0x10] = KEY_DOWN, /* down */ - [0x08] = KEY_LEFT, /* left */ - [0x04] = KEY_RIGHT, /* right */ - [0x03] = KEY_SELECT, /* select */ - - [0x1f] = KEY_REWIND, /* rewind */ - [0x20] = KEY_PLAYPAUSE, /* play/pause */ - [0x29] = KEY_FORWARD, /* forward */ - [0x14] = KEY_AGAIN, /* repeat */ - [0x2b] = KEY_RECORD, /* recording */ - [0x2c] = KEY_STOP, /* stop */ - [0x2d] = KEY_PLAY, /* play */ - [0x2e] = KEY_CAMERA, /* snapshot / shuffle */ - - [0x00] = KEY_0, - [0x05] = KEY_1, - [0x06] = KEY_2, - [0x07] = KEY_3, - [0x09] = KEY_4, - [0x0a] = KEY_5, - [0x0b] = KEY_6, - [0x0d] = KEY_7, - [0x0e] = KEY_8, - [0x0f] = KEY_9, - - [0x2a] = KEY_VOLUMEUP, - [0x11] = KEY_VOLUMEDOWN, - [0x18] = KEY_CHANNELUP, /* CH.tracking up */ - [0x19] = KEY_CHANNELDOWN,/* CH.tracking down */ - - [0x13] = KEY_ENTER, /* enter */ - [0x21] = KEY_DOT, /* . (decimal dot) */ -}; -EXPORT_SYMBOL_GPL(ir_codes_eztv); + { 0x1b, KEY_MUTE }, /* mute */ + { 0x02, KEY_LANGUAGE }, /* MTS/SAP / audio / autoseek */ + { 0x1e, KEY_SUBTITLE }, /* closed captioning / subtitle / seek */ + { 0x16, KEY_ZOOM }, /* full screen */ + { 0x1c, KEY_VIDEO }, /* video source / eject / delall */ + { 0x1d, KEY_RESTART }, /* playback / angle / del */ + { 0x2f, KEY_SEARCH }, /* scan / menu / playlist */ + { 0x30, KEY_CHANNEL }, /* CH surfing / bookmark / memo */ + + { 0x31, KEY_HELP }, /* help */ + { 0x32, KEY_MODE }, /* num/memo */ + { 0x33, KEY_ESC }, /* cancel */ + + { 0x0c, KEY_UP }, /* up */ + { 0x10, KEY_DOWN }, /* down */ + { 0x08, KEY_LEFT }, /* left */ + { 0x04, KEY_RIGHT }, /* right */ + { 0x03, KEY_SELECT }, /* select */ + + { 0x1f, KEY_REWIND }, /* rewind */ + { 0x20, KEY_PLAYPAUSE },/* play/pause */ + { 0x29, KEY_FORWARD }, /* forward */ + { 0x14, KEY_AGAIN }, /* repeat */ + { 0x2b, KEY_RECORD }, /* recording */ + { 0x2c, KEY_STOP }, /* stop */ + { 0x2d, KEY_PLAY }, /* play */ + { 0x2e, KEY_CAMERA }, /* snapshot / shuffle */ + + { 0x00, KEY_0 }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + + { 0x2a, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x18, KEY_CHANNELUP },/* CH.tracking up */ + { 0x19, KEY_CHANNELDOWN },/* CH.tracking down */ + + { 0x13, KEY_ENTER }, /* enter */ + { 0x21, KEY_DOT }, /* . (decimal dot) */ +}; + +struct ir_scancode_table ir_codes_eztv_table = { + .scan = ir_codes_eztv, + .size = ARRAY_SIZE(ir_codes_eztv), +}; +EXPORT_SYMBOL_GPL(ir_codes_eztv_table); /* Alex Hermann */ -IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE] = { - [0x28] = KEY_1, - [0x18] = KEY_2, - [0x38] = KEY_3, - [0x24] = KEY_4, - [0x14] = KEY_5, - [0x34] = KEY_6, - [0x2c] = KEY_7, - [0x1c] = KEY_8, - [0x3c] = KEY_9, - [0x22] = KEY_0, - - [0x20] = KEY_TV, /* TV/FM */ - [0x10] = KEY_CD, /* CD */ - [0x30] = KEY_TEXT, /* TELETEXT */ - [0x00] = KEY_POWER, /* POWER */ - - [0x08] = KEY_VIDEO, /* VIDEO */ - [0x04] = KEY_AUDIO, /* AUDIO */ - [0x0c] = KEY_ZOOM, /* FULL SCREEN */ - - [0x12] = KEY_SUBTITLE, /* DISPLAY */ - [0x32] = KEY_REWIND, /* LOOP */ - [0x02] = KEY_PRINT, /* PREVIEW */ - - [0x2a] = KEY_SEARCH, /* AUTOSCAN */ - [0x1a] = KEY_SLEEP, /* FREEZE */ - [0x3a] = KEY_CAMERA, /* SNAPSHOT */ - [0x0a] = KEY_MUTE, /* MUTE */ - - [0x26] = KEY_RECORD, /* RECORD */ - [0x16] = KEY_PAUSE, /* PAUSE */ - [0x36] = KEY_STOP, /* STOP */ - [0x06] = KEY_PLAY, /* PLAY */ - - [0x2e] = KEY_RED, /* RED */ - [0x21] = KEY_GREEN, /* GREEN */ - [0x0e] = KEY_YELLOW, /* YELLOW */ - [0x01] = KEY_BLUE, /* BLUE */ - - [0x1e] = KEY_VOLUMEDOWN, /* VOLUME- */ - [0x3e] = KEY_VOLUMEUP, /* VOLUME+ */ - [0x11] = KEY_CHANNELDOWN, /* CHANNEL/PAGE- */ - [0x31] = KEY_CHANNELUP /* CHANNEL/PAGE+ */ -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia); - -IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE] = { - [0x14] = KEY_MUTE, - [0x24] = KEY_ZOOM, - - [0x01] = KEY_DVD, - [0x23] = KEY_RADIO, - [0x00] = KEY_TV, - - [0x0a] = KEY_REWIND, - [0x08] = KEY_PLAYPAUSE, - [0x0f] = KEY_FORWARD, - - [0x02] = KEY_PREVIOUS, - [0x07] = KEY_STOP, - [0x06] = KEY_NEXT, - - [0x0c] = KEY_UP, - [0x0e] = KEY_DOWN, - [0x0b] = KEY_LEFT, - [0x0d] = KEY_RIGHT, - [0x11] = KEY_OK, - - [0x03] = KEY_MENU, - [0x09] = KEY_SETUP, - [0x05] = KEY_VIDEO, - [0x22] = KEY_CHANNEL, - - [0x12] = KEY_VOLUMEUP, - [0x15] = KEY_VOLUMEDOWN, - [0x10] = KEY_CHANNELUP, - [0x13] = KEY_CHANNELDOWN, - - [0x04] = KEY_RECORD, - - [0x16] = KEY_1, - [0x17] = KEY_2, - [0x18] = KEY_3, - [0x19] = KEY_4, - [0x1a] = KEY_5, - [0x1b] = KEY_6, - [0x1c] = KEY_7, - [0x1d] = KEY_8, - [0x1e] = KEY_9, - [0x1f] = KEY_0, - - [0x20] = KEY_LANGUAGE, - [0x21] = KEY_SLEEP, -}; -EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr); +static struct ir_scancode ir_codes_avermedia[] = { + { 0x28, KEY_1 }, + { 0x18, KEY_2 }, + { 0x38, KEY_3 }, + { 0x24, KEY_4 }, + { 0x14, KEY_5 }, + { 0x34, KEY_6 }, + { 0x2c, KEY_7 }, + { 0x1c, KEY_8 }, + { 0x3c, KEY_9 }, + { 0x22, KEY_0 }, + + { 0x20, KEY_TV }, /* TV/FM */ + { 0x10, KEY_CD }, /* CD */ + { 0x30, KEY_TEXT }, /* TELETEXT */ + { 0x00, KEY_POWER }, /* POWER */ + + { 0x08, KEY_VIDEO }, /* VIDEO */ + { 0x04, KEY_AUDIO }, /* AUDIO */ + { 0x0c, KEY_ZOOM }, /* FULL SCREEN */ + + { 0x12, KEY_SUBTITLE }, /* DISPLAY */ + { 0x32, KEY_REWIND }, /* LOOP */ + { 0x02, KEY_PRINT }, /* PREVIEW */ + + { 0x2a, KEY_SEARCH }, /* AUTOSCAN */ + { 0x1a, KEY_SLEEP }, /* FREEZE */ + { 0x3a, KEY_CAMERA }, /* SNAPSHOT */ + { 0x0a, KEY_MUTE }, /* MUTE */ + + { 0x26, KEY_RECORD }, /* RECORD */ + { 0x16, KEY_PAUSE }, /* PAUSE */ + { 0x36, KEY_STOP }, /* STOP */ + { 0x06, KEY_PLAY }, /* PLAY */ + + { 0x2e, KEY_RED }, /* RED */ + { 0x21, KEY_GREEN }, /* GREEN */ + { 0x0e, KEY_YELLOW }, /* YELLOW */ + { 0x01, KEY_BLUE }, /* BLUE */ + + { 0x1e, KEY_VOLUMEDOWN }, /* VOLUME- */ + { 0x3e, KEY_VOLUMEUP }, /* VOLUME+ */ + { 0x11, KEY_CHANNELDOWN }, /* CHANNEL/PAGE- */ + { 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */ +}; + +struct ir_scancode_table ir_codes_avermedia_table = { + .scan = ir_codes_avermedia, + .size = ARRAY_SIZE(ir_codes_avermedia), +}; +EXPORT_SYMBOL_GPL(ir_codes_avermedia_table); + +static struct ir_scancode ir_codes_videomate_tv_pvr[] = { + { 0x14, KEY_MUTE }, + { 0x24, KEY_ZOOM }, + + { 0x01, KEY_DVD }, + { 0x23, KEY_RADIO }, + { 0x00, KEY_TV }, + + { 0x0a, KEY_REWIND }, + { 0x08, KEY_PLAYPAUSE }, + { 0x0f, KEY_FORWARD }, + + { 0x02, KEY_PREVIOUS }, + { 0x07, KEY_STOP }, + { 0x06, KEY_NEXT }, + + { 0x0c, KEY_UP }, + { 0x0e, KEY_DOWN }, + { 0x0b, KEY_LEFT }, + { 0x0d, KEY_RIGHT }, + { 0x11, KEY_OK }, + + { 0x03, KEY_MENU }, + { 0x09, KEY_SETUP }, + { 0x05, KEY_VIDEO }, + { 0x22, KEY_CHANNEL }, + + { 0x12, KEY_VOLUMEUP }, + { 0x15, KEY_VOLUMEDOWN }, + { 0x10, KEY_CHANNELUP }, + { 0x13, KEY_CHANNELDOWN }, + + { 0x04, KEY_RECORD }, + + { 0x16, KEY_1 }, + { 0x17, KEY_2 }, + { 0x18, KEY_3 }, + { 0x19, KEY_4 }, + { 0x1a, KEY_5 }, + { 0x1b, KEY_6 }, + { 0x1c, KEY_7 }, + { 0x1d, KEY_8 }, + { 0x1e, KEY_9 }, + { 0x1f, KEY_0 }, + + { 0x20, KEY_LANGUAGE }, + { 0x21, KEY_SLEEP }, +}; + +struct ir_scancode_table ir_codes_videomate_tv_pvr_table = { + .scan = ir_codes_videomate_tv_pvr, + .size = ARRAY_SIZE(ir_codes_videomate_tv_pvr), +}; +EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr_table); /* Michael Tokarev http://www.corpit.ru/mjt/beholdTV/remote_control.jpg @@ -1219,14 +1344,14 @@ EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr); the button labels (several variants when appropriate) helps to descide which keycodes to assign to the buttons. */ -IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_manli[] = { /* 0x1c 0x12 * * FUNCTION POWER * * FM (|) * * */ - [0x1c] = KEY_RADIO, /*XXX*/ - [0x12] = KEY_POWER, + { 0x1c, KEY_RADIO }, /*XXX*/ + { 0x12, KEY_POWER }, /* 0x01 0x02 0x03 * * 1 2 3 * @@ -1237,29 +1362,29 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * 0x07 0x08 0x09 * * 7 8 9 * * */ - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, /* 0x0a 0x00 0x17 * * RECALL 0 +100 * * PLUS * * */ - [0x0a] = KEY_AGAIN, /*XXX KEY_REWIND? */ - [0x00] = KEY_0, - [0x17] = KEY_DIGITS, /*XXX*/ + { 0x0a, KEY_AGAIN }, /*XXX KEY_REWIND? */ + { 0x00, KEY_0 }, + { 0x17, KEY_DIGITS }, /*XXX*/ /* 0x14 0x10 * * MENU INFO * * OSD */ - [0x14] = KEY_MENU, - [0x10] = KEY_INFO, + { 0x14, KEY_MENU }, + { 0x10, KEY_INFO }, /* 0x0b * * Up * @@ -1270,18 +1395,18 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [0x0b] = KEY_UP, - [0x18] = KEY_LEFT, - [0x16] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */ - [0x0c] = KEY_RIGHT, - [0x15] = KEY_DOWN, + { 0x0b, KEY_UP }, + { 0x18, KEY_LEFT }, + { 0x16, KEY_OK }, /*XXX KEY_SELECT? KEY_ENTER? */ + { 0x0c, KEY_RIGHT }, + { 0x15, KEY_DOWN }, /* 0x11 0x0d * * TV/AV MODE * * SOURCE STEREO * * */ - [0x11] = KEY_TV, /*XXX*/ - [0x0d] = KEY_MODE, /*XXX there's no KEY_STEREO */ + { 0x11, KEY_TV }, /*XXX*/ + { 0x0d, KEY_MODE }, /*XXX there's no KEY_STEREO */ /* 0x0f 0x1b 0x1a * * AUDIO Vol+ Chan+ * @@ -1290,914 +1415,1004 @@ IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE] = { * 0x0e 0x1f 0x1e * * SLEEP Vol- Chan- * * */ - [0x0f] = KEY_AUDIO, - [0x1b] = KEY_VOLUMEUP, - [0x1a] = KEY_CHANNELUP, - [0x0e] = KEY_TIME, - [0x1f] = KEY_VOLUMEDOWN, - [0x1e] = KEY_CHANNELDOWN, + { 0x0f, KEY_AUDIO }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1a, KEY_CHANNELUP }, + { 0x0e, KEY_TIME }, + { 0x1f, KEY_VOLUMEDOWN }, + { 0x1e, KEY_CHANNELDOWN }, /* 0x13 0x19 * * MUTE SNAPSHOT* * */ - [0x13] = KEY_MUTE, - [0x19] = KEY_CAMERA, + { 0x13, KEY_MUTE }, + { 0x19, KEY_CAMERA }, /* 0x1d unused ? */ }; -EXPORT_SYMBOL_GPL(ir_codes_manli); + +struct ir_scancode_table ir_codes_manli_table = { + .scan = ir_codes_manli, + .size = ARRAY_SIZE(ir_codes_manli), +}; +EXPORT_SYMBOL_GPL(ir_codes_manli_table); /* Mike Baikov */ -IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE] = { - - [0x11] = KEY_POWER, - [0x35] = KEY_TV, - [0x1b] = KEY_0, - [0x29] = KEY_1, - [0x19] = KEY_2, - [0x39] = KEY_3, - [0x1f] = KEY_4, - [0x2c] = KEY_5, - [0x21] = KEY_6, - [0x24] = KEY_7, - [0x18] = KEY_8, - [0x2b] = KEY_9, - [0x3b] = KEY_AGAIN, /* LOOP */ - [0x06] = KEY_AUDIO, - [0x31] = KEY_PRINT, /* PREVIEW */ - [0x3e] = KEY_VIDEO, - [0x10] = KEY_CHANNELUP, - [0x20] = KEY_CHANNELDOWN, - [0x0c] = KEY_VOLUMEDOWN, - [0x28] = KEY_VOLUMEUP, - [0x08] = KEY_MUTE, - [0x26] = KEY_SEARCH, /* SCAN */ - [0x3f] = KEY_CAMERA, /* SNAPSHOT */ - [0x12] = KEY_RECORD, - [0x32] = KEY_STOP, - [0x3c] = KEY_PLAY, - [0x1d] = KEY_REWIND, - [0x2d] = KEY_PAUSE, - [0x0d] = KEY_FORWARD, - [0x05] = KEY_ZOOM, /*FULL*/ - - [0x2a] = KEY_F21, /* LIVE TIMESHIFT */ - [0x0e] = KEY_F22, /* MIN TIMESHIFT */ - [0x1e] = KEY_TIME, /* TIMESHIFT */ - [0x38] = KEY_F24, /* NORMAL TIMESHIFT */ -}; -EXPORT_SYMBOL_GPL(ir_codes_gotview7135); - -IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { - [0x03] = KEY_POWER, - [0x6f] = KEY_MUTE, - [0x10] = KEY_BACKSPACE, /* Recall */ - - [0x11] = KEY_0, - [0x04] = KEY_1, - [0x05] = KEY_2, - [0x06] = KEY_3, - [0x08] = KEY_4, - [0x09] = KEY_5, - [0x0a] = KEY_6, - [0x0c] = KEY_7, - [0x0d] = KEY_8, - [0x0e] = KEY_9, - [0x12] = KEY_DOT, /* 100+ */ - - [0x07] = KEY_VOLUMEUP, - [0x0b] = KEY_VOLUMEDOWN, - [0x1a] = KEY_KPPLUS, - [0x18] = KEY_KPMINUS, - [0x15] = KEY_UP, - [0x1d] = KEY_DOWN, - [0x0f] = KEY_CHANNELUP, - [0x13] = KEY_CHANNELDOWN, - [0x48] = KEY_ZOOM, - - [0x1b] = KEY_VIDEO, /* Video source */ - [0x1f] = KEY_CAMERA, /* Snapshot */ - [0x49] = KEY_LANGUAGE, /* MTS Select */ - [0x19] = KEY_SEARCH, /* Auto Scan */ - - [0x4b] = KEY_RECORD, - [0x46] = KEY_PLAY, - [0x45] = KEY_PAUSE, /* Pause */ - [0x44] = KEY_STOP, - [0x43] = KEY_TIME, /* Time Shift */ +static struct ir_scancode ir_codes_gotview7135[] = { + + { 0x11, KEY_POWER }, + { 0x35, KEY_TV }, + { 0x1b, KEY_0 }, + { 0x29, KEY_1 }, + { 0x19, KEY_2 }, + { 0x39, KEY_3 }, + { 0x1f, KEY_4 }, + { 0x2c, KEY_5 }, + { 0x21, KEY_6 }, + { 0x24, KEY_7 }, + { 0x18, KEY_8 }, + { 0x2b, KEY_9 }, + { 0x3b, KEY_AGAIN }, /* LOOP */ + { 0x06, KEY_AUDIO }, + { 0x31, KEY_PRINT }, /* PREVIEW */ + { 0x3e, KEY_VIDEO }, + { 0x10, KEY_CHANNELUP }, + { 0x20, KEY_CHANNELDOWN }, + { 0x0c, KEY_VOLUMEDOWN }, + { 0x28, KEY_VOLUMEUP }, + { 0x08, KEY_MUTE }, + { 0x26, KEY_SEARCH }, /* SCAN */ + { 0x3f, KEY_CAMERA }, /* SNAPSHOT */ + { 0x12, KEY_RECORD }, + { 0x32, KEY_STOP }, + { 0x3c, KEY_PLAY }, + { 0x1d, KEY_REWIND }, + { 0x2d, KEY_PAUSE }, + { 0x0d, KEY_FORWARD }, + { 0x05, KEY_ZOOM }, /*FULL*/ + + { 0x2a, KEY_F21 }, /* LIVE TIMESHIFT */ + { 0x0e, KEY_F22 }, /* MIN TIMESHIFT */ + { 0x1e, KEY_TIME }, /* TIMESHIFT */ + { 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */ +}; + +struct ir_scancode_table ir_codes_gotview7135_table = { + .scan = ir_codes_gotview7135, + .size = ARRAY_SIZE(ir_codes_gotview7135), +}; +EXPORT_SYMBOL_GPL(ir_codes_gotview7135_table); + +static struct ir_scancode ir_codes_purpletv[] = { + { 0x03, KEY_POWER }, + { 0x6f, KEY_MUTE }, + { 0x10, KEY_BACKSPACE }, /* Recall */ + + { 0x11, KEY_0 }, + { 0x04, KEY_1 }, + { 0x05, KEY_2 }, + { 0x06, KEY_3 }, + { 0x08, KEY_4 }, + { 0x09, KEY_5 }, + { 0x0a, KEY_6 }, + { 0x0c, KEY_7 }, + { 0x0d, KEY_8 }, + { 0x0e, KEY_9 }, + { 0x12, KEY_DOT }, /* 100+ */ + + { 0x07, KEY_VOLUMEUP }, + { 0x0b, KEY_VOLUMEDOWN }, + { 0x1a, KEY_KPPLUS }, + { 0x18, KEY_KPMINUS }, + { 0x15, KEY_UP }, + { 0x1d, KEY_DOWN }, + { 0x0f, KEY_CHANNELUP }, + { 0x13, KEY_CHANNELDOWN }, + { 0x48, KEY_ZOOM }, + + { 0x1b, KEY_VIDEO }, /* Video source */ + { 0x1f, KEY_CAMERA }, /* Snapshot */ + { 0x49, KEY_LANGUAGE }, /* MTS Select */ + { 0x19, KEY_SEARCH }, /* Auto Scan */ + + { 0x4b, KEY_RECORD }, + { 0x46, KEY_PLAY }, + { 0x45, KEY_PAUSE }, /* Pause */ + { 0x44, KEY_STOP }, + { 0x43, KEY_TIME }, /* Time Shift */ #if 0 - [0x47] = KEY_Y, /* Time Shift OFF */ - [0x4a] = KEY_O, /* TOP */ + { 0x47, KEY_Y }, /* Time Shift OFF */ + { 0x4a, KEY_O }, /* TOP */ #endif - [0x17] = KEY_CHANNEL, /* SURF CH */ - [0x40] = KEY_FORWARD, /* Forward ? */ - [0x42] = KEY_REWIND, /* Backward ? */ + { 0x17, KEY_CHANNEL }, /* SURF CH */ + { 0x40, KEY_FORWARD }, /* Forward ? */ + { 0x42, KEY_REWIND }, /* Backward ? */ + +}; +struct ir_scancode_table ir_codes_purpletv_table = { + .scan = ir_codes_purpletv, + .size = ARRAY_SIZE(ir_codes_purpletv), }; -EXPORT_SYMBOL_GPL(ir_codes_purpletv); +EXPORT_SYMBOL_GPL(ir_codes_purpletv_table); /* Mapping for the 28 key remote control as seen at http://www.sednacomputer.com/photo/cardbus-tv.jpg Pavel Mihaylov Also for the remote bundled with Kozumi KTV-01C card */ -IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - - [0x0a] = KEY_AGAIN, /* Recall */ - [0x0b] = KEY_CHANNELUP, - [0x0c] = KEY_VOLUMEUP, - [0x0d] = KEY_MODE, /* Stereo */ - [0x0e] = KEY_STOP, - [0x0f] = KEY_PREVIOUSSONG, - [0x10] = KEY_ZOOM, - [0x11] = KEY_TUNER, /* Source */ - [0x12] = KEY_POWER, - [0x13] = KEY_MUTE, - [0x15] = KEY_CHANNELDOWN, - [0x18] = KEY_VOLUMEDOWN, - [0x19] = KEY_CAMERA, /* Snapshot */ - [0x1a] = KEY_NEXTSONG, - [0x1b] = KEY_TIME, /* Time Shift */ - [0x1c] = KEY_RADIO, /* FM Radio */ - [0x1d] = KEY_RECORD, - [0x1e] = KEY_PAUSE, +static struct ir_scancode ir_codes_pctv_sedna[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0a, KEY_AGAIN }, /* Recall */ + { 0x0b, KEY_CHANNELUP }, + { 0x0c, KEY_VOLUMEUP }, + { 0x0d, KEY_MODE }, /* Stereo */ + { 0x0e, KEY_STOP }, + { 0x0f, KEY_PREVIOUSSONG }, + { 0x10, KEY_ZOOM }, + { 0x11, KEY_TUNER }, /* Source */ + { 0x12, KEY_POWER }, + { 0x13, KEY_MUTE }, + { 0x15, KEY_CHANNELDOWN }, + { 0x18, KEY_VOLUMEDOWN }, + { 0x19, KEY_CAMERA }, /* Snapshot */ + { 0x1a, KEY_NEXTSONG }, + { 0x1b, KEY_TIME }, /* Time Shift */ + { 0x1c, KEY_RADIO }, /* FM Radio */ + { 0x1d, KEY_RECORD }, + { 0x1e, KEY_PAUSE }, /* additional codes for Kozumi's remote */ - [0x14] = KEY_INFO, /* OSD */ - [0x16] = KEY_OK, /* OK */ - [0x17] = KEY_DIGITS, /* Plus */ - [0x1f] = KEY_PLAY, /* Play */ + { 0x14, KEY_INFO }, /* OSD */ + { 0x16, KEY_OK }, /* OK */ + { 0x17, KEY_DIGITS }, /* Plus */ + { 0x1f, KEY_PLAY }, /* Play */ }; -EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna); + +struct ir_scancode_table ir_codes_pctv_sedna_table = { + .scan = ir_codes_pctv_sedna, + .size = ARRAY_SIZE(ir_codes_pctv_sedna), +}; +EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna_table); /* Mark Phalan */ -IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE] = { - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - - [0x12] = KEY_POWER, - [0x10] = KEY_MUTE, - [0x1f] = KEY_VOLUMEDOWN, - [0x1b] = KEY_VOLUMEUP, - [0x1a] = KEY_CHANNELUP, - [0x1e] = KEY_CHANNELDOWN, - [0x0e] = KEY_PAGEUP, - [0x1d] = KEY_PAGEDOWN, - [0x13] = KEY_SOUND, - - [0x18] = KEY_KPPLUSMINUS, /* CH +/- */ - [0x16] = KEY_SUBTITLE, /* CC */ - [0x0d] = KEY_TEXT, /* TTX */ - [0x0b] = KEY_TV, /* AIR/CBL */ - [0x11] = KEY_PC, /* PC/TV */ - [0x17] = KEY_OK, /* CH RTN */ - [0x19] = KEY_MODE, /* FUNC */ - [0x0c] = KEY_SEARCH, /* AUTOSCAN */ +static struct ir_scancode ir_codes_pv951[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x12, KEY_POWER }, + { 0x10, KEY_MUTE }, + { 0x1f, KEY_VOLUMEDOWN }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1a, KEY_CHANNELUP }, + { 0x1e, KEY_CHANNELDOWN }, + { 0x0e, KEY_PAGEUP }, + { 0x1d, KEY_PAGEDOWN }, + { 0x13, KEY_SOUND }, + + { 0x18, KEY_KPPLUSMINUS }, /* CH +/- */ + { 0x16, KEY_SUBTITLE }, /* CC */ + { 0x0d, KEY_TEXT }, /* TTX */ + { 0x0b, KEY_TV }, /* AIR/CBL */ + { 0x11, KEY_PC }, /* PC/TV */ + { 0x17, KEY_OK }, /* CH RTN */ + { 0x19, KEY_MODE }, /* FUNC */ + { 0x0c, KEY_SEARCH }, /* AUTOSCAN */ /* Not sure what to do with these ones! */ - [0x0f] = KEY_SELECT, /* SOURCE */ - [0x0a] = KEY_KPPLUS, /* +100 */ - [0x14] = KEY_EQUAL, /* SYNC */ - [0x1c] = KEY_MEDIA, /* PC/TV */ + { 0x0f, KEY_SELECT }, /* SOURCE */ + { 0x0a, KEY_KPPLUS }, /* +100 */ + { 0x14, KEY_EQUAL }, /* SYNC */ + { 0x1c, KEY_MEDIA }, /* PC/TV */ }; -EXPORT_SYMBOL_GPL(ir_codes_pv951); + +struct ir_scancode_table ir_codes_pv951_table = { + .scan = ir_codes_pv951, + .size = ARRAY_SIZE(ir_codes_pv951), +}; +EXPORT_SYMBOL_GPL(ir_codes_pv951_table); /* generic RC5 keytable */ /* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ /* used by old (black) Hauppauge remotes */ -IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_rc5_tv[] = { /* Keys 0 to 9 */ - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - - [0x0b] = KEY_CHANNEL, /* channel / program (japan: 11) */ - [0x0c] = KEY_POWER, /* standby */ - [0x0d] = KEY_MUTE, /* mute / demute */ - [0x0f] = KEY_TV, /* display */ - [0x10] = KEY_VOLUMEUP, - [0x11] = KEY_VOLUMEDOWN, - [0x12] = KEY_BRIGHTNESSUP, - [0x13] = KEY_BRIGHTNESSDOWN, - [0x1e] = KEY_SEARCH, /* search + */ - [0x20] = KEY_CHANNELUP, /* channel / program + */ - [0x21] = KEY_CHANNELDOWN, /* channel / program - */ - [0x22] = KEY_CHANNEL, /* alt / channel */ - [0x23] = KEY_LANGUAGE, /* 1st / 2nd language */ - [0x26] = KEY_SLEEP, /* sleeptimer */ - [0x2e] = KEY_MENU, /* 2nd controls (USA: menu) */ - [0x30] = KEY_PAUSE, - [0x32] = KEY_REWIND, - [0x33] = KEY_GOTO, - [0x35] = KEY_PLAY, - [0x36] = KEY_STOP, - [0x37] = KEY_RECORD, /* recording */ - [0x3c] = KEY_TEXT, /* teletext submode (Japan: 12) */ - [0x3d] = KEY_SUSPEND, /* system standby */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0b, KEY_CHANNEL }, /* channel / program (japan: 11) */ + { 0x0c, KEY_POWER }, /* standby */ + { 0x0d, KEY_MUTE }, /* mute / demute */ + { 0x0f, KEY_TV }, /* display */ + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x12, KEY_BRIGHTNESSUP }, + { 0x13, KEY_BRIGHTNESSDOWN }, + { 0x1e, KEY_SEARCH }, /* search + */ + { 0x20, KEY_CHANNELUP }, /* channel / program + */ + { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x22, KEY_CHANNEL }, /* alt / channel */ + { 0x23, KEY_LANGUAGE }, /* 1st / 2nd language */ + { 0x26, KEY_SLEEP }, /* sleeptimer */ + { 0x2e, KEY_MENU }, /* 2nd controls (USA: menu) */ + { 0x30, KEY_PAUSE }, + { 0x32, KEY_REWIND }, + { 0x33, KEY_GOTO }, + { 0x35, KEY_PLAY }, + { 0x36, KEY_STOP }, + { 0x37, KEY_RECORD }, /* recording */ + { 0x3c, KEY_TEXT }, /* teletext submode (Japan: 12) */ + { 0x3d, KEY_SUSPEND }, /* system standby */ #if 0 /* FIXME */ - [0x0a] = KEY_RESERVED, /* 1/2/3 digits (japan: 10) */ - [0x0e] = KEY_RESERVED, /* P.P. (personal preference) */ - [0x14] = KEY_RESERVED, /* colour saturation + */ - [0x15] = KEY_RESERVED, /* colour saturation - */ - [0x16] = KEY_RESERVED, /* bass + */ - [0x17] = KEY_RESERVED, /* bass - */ - [0x18] = KEY_RESERVED, /* treble + */ - [0x19] = KEY_RESERVED, /* treble - */ - [0x1a] = KEY_RESERVED, /* balance right */ - [0x1b] = KEY_RESERVED, /* balance left */ - [0x1c] = KEY_RESERVED, /* contrast + */ - [0x1d] = KEY_RESERVED, /* contrast - */ - [0x1f] = KEY_RESERVED, /* tint/hue + */ - [0x24] = KEY_RESERVED, /* spacial stereo on/off */ - [0x25] = KEY_RESERVED, /* mono / stereo (USA) */ - [0x27] = KEY_RESERVED, /* tint / hue - */ - [0x28] = KEY_RESERVED, /* RF switch/PIP select */ - [0x29] = KEY_RESERVED, /* vote */ - [0x2a] = KEY_RESERVED, /* timed page/channel clck */ - [0x2b] = KEY_RESERVED, /* increment (USA) */ - [0x2c] = KEY_RESERVED, /* decrement (USA) */ - [0x2d] = KEY_RESERVED, /* */ - [0x2f] = KEY_RESERVED, /* PIP shift */ - [0x31] = KEY_RESERVED, /* erase */ - [0x34] = KEY_RESERVED, /* wind */ - [0x38] = KEY_RESERVED, /* external 1 */ - [0x39] = KEY_RESERVED, /* external 2 */ - [0x3a] = KEY_RESERVED, /* PIP display mode */ - [0x3b] = KEY_RESERVED, /* view data mode / advance */ - [0x3e] = KEY_RESERVED, /* crispener on/off */ - [0x3f] = KEY_RESERVED, /* system select */ + { 0x0a, KEY_RESERVED }, /* 1/2/3 digits (japan: 10) */ + { 0x0e, KEY_RESERVED }, /* P.P. (personal preference) */ + { 0x14, KEY_RESERVED }, /* colour saturation + */ + { 0x15, KEY_RESERVED }, /* colour saturation - */ + { 0x16, KEY_RESERVED }, /* bass + */ + { 0x17, KEY_RESERVED }, /* bass - */ + { 0x18, KEY_RESERVED }, /* treble + */ + { 0x19, KEY_RESERVED }, /* treble - */ + { 0x1a, KEY_RESERVED }, /* balance right */ + { 0x1b, KEY_RESERVED }, /* balance left */ + { 0x1c, KEY_RESERVED }, /* contrast + */ + { 0x1d, KEY_RESERVED }, /* contrast - */ + { 0x1f, KEY_RESERVED }, /* tint/hue + */ + { 0x24, KEY_RESERVED }, /* spacial stereo on/off */ + { 0x25, KEY_RESERVED }, /* mono / stereo (USA) */ + { 0x27, KEY_RESERVED }, /* tint / hue - */ + { 0x28, KEY_RESERVED }, /* RF switch/PIP select */ + { 0x29, KEY_RESERVED }, /* vote */ + { 0x2a, KEY_RESERVED }, /* timed page/channel clck */ + { 0x2b, KEY_RESERVED }, /* increment (USA) */ + { 0x2c, KEY_RESERVED }, /* decrement (USA) */ + { 0x2d, KEY_RESERVED }, /* */ + { 0x2f, KEY_RESERVED }, /* PIP shift */ + { 0x31, KEY_RESERVED }, /* erase */ + { 0x34, KEY_RESERVED }, /* wind */ + { 0x38, KEY_RESERVED }, /* external 1 */ + { 0x39, KEY_RESERVED }, /* external 2 */ + { 0x3a, KEY_RESERVED }, /* PIP display mode */ + { 0x3b, KEY_RESERVED }, /* view data mode / advance */ + { 0x3e, KEY_RESERVED }, /* crispener on/off */ + { 0x3f, KEY_RESERVED }, /* system select */ #endif }; -EXPORT_SYMBOL_GPL(ir_codes_rc5_tv); + +struct ir_scancode_table ir_codes_rc5_tv_table = { + .scan = ir_codes_rc5_tv, + .size = ARRAY_SIZE(ir_codes_rc5_tv), +}; +EXPORT_SYMBOL_GPL(ir_codes_rc5_tv_table); /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ -IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_winfast[] = { /* Keys 0 to 9 */ - [0x12] = KEY_0, - [0x05] = KEY_1, - [0x06] = KEY_2, - [0x07] = KEY_3, - [0x09] = KEY_4, - [0x0a] = KEY_5, - [0x0b] = KEY_6, - [0x0d] = KEY_7, - [0x0e] = KEY_8, - [0x0f] = KEY_9, - - [0x00] = KEY_POWER, - [0x1b] = KEY_AUDIO, /* Audio Source */ - [0x02] = KEY_TUNER, /* TV/FM, not on Y0400052 */ - [0x1e] = KEY_VIDEO, /* Video Source */ - [0x16] = KEY_INFO, /* Display information */ - [0x04] = KEY_VOLUMEUP, - [0x08] = KEY_VOLUMEDOWN, - [0x0c] = KEY_CHANNELUP, - [0x10] = KEY_CHANNELDOWN, - [0x03] = KEY_ZOOM, /* fullscreen */ - [0x1f] = KEY_TEXT, /* closed caption/teletext */ - [0x20] = KEY_SLEEP, - [0x29] = KEY_CLEAR, /* boss key */ - [0x14] = KEY_MUTE, - [0x2b] = KEY_RED, - [0x2c] = KEY_GREEN, - [0x2d] = KEY_YELLOW, - [0x2e] = KEY_BLUE, - [0x18] = KEY_KPPLUS, /* fine tune + , not on Y040052 */ - [0x19] = KEY_KPMINUS, /* fine tune - , not on Y040052 */ - [0x2a] = KEY_MEDIA, /* PIP (Picture in picture */ - [0x21] = KEY_DOT, - [0x13] = KEY_ENTER, - [0x11] = KEY_LAST, /* Recall (last channel */ - [0x22] = KEY_PREVIOUS, - [0x23] = KEY_PLAYPAUSE, - [0x24] = KEY_NEXT, - [0x25] = KEY_TIME, /* Time Shifting */ - [0x26] = KEY_STOP, - [0x27] = KEY_RECORD, - [0x28] = KEY_SAVE, /* Screenshot */ - [0x2f] = KEY_MENU, - [0x30] = KEY_CANCEL, - [0x31] = KEY_CHANNEL, /* Channel Surf */ - [0x32] = KEY_SUBTITLE, - [0x33] = KEY_LANGUAGE, - [0x34] = KEY_REWIND, - [0x35] = KEY_FASTFORWARD, - [0x36] = KEY_TV, - [0x37] = KEY_RADIO, /* FM */ - [0x38] = KEY_DVD, - - [0x3e] = KEY_F21, /* MCE +VOL, on Y04G0033 */ - [0x3a] = KEY_F22, /* MCE -VOL, on Y04G0033 */ - [0x3b] = KEY_F23, /* MCE +CH, on Y04G0033 */ - [0x3f] = KEY_F24 /* MCE -CH, on Y04G0033 */ -}; -EXPORT_SYMBOL_GPL(ir_codes_winfast); - -IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = { - [0x59] = KEY_MUTE, - [0x4a] = KEY_POWER, - - [0x18] = KEY_TEXT, - [0x26] = KEY_TV, - [0x3d] = KEY_PRINT, - - [0x48] = KEY_RED, - [0x04] = KEY_GREEN, - [0x11] = KEY_YELLOW, - [0x00] = KEY_BLUE, - - [0x2d] = KEY_VOLUMEUP, - [0x1e] = KEY_VOLUMEDOWN, - - [0x49] = KEY_MENU, - - [0x16] = KEY_CHANNELUP, - [0x17] = KEY_CHANNELDOWN, - - [0x20] = KEY_UP, - [0x21] = KEY_DOWN, - [0x22] = KEY_LEFT, - [0x23] = KEY_RIGHT, - [0x0d] = KEY_SELECT, - - [0x08] = KEY_BACK, - [0x07] = KEY_REFRESH, - - [0x2f] = KEY_ZOOM, - [0x29] = KEY_RECORD, - - [0x4b] = KEY_PAUSE, - [0x4d] = KEY_REWIND, - [0x2e] = KEY_PLAY, - [0x4e] = KEY_FORWARD, - [0x53] = KEY_PREVIOUS, - [0x4c] = KEY_STOP, - [0x54] = KEY_NEXT, - - [0x69] = KEY_0, - [0x6a] = KEY_1, - [0x6b] = KEY_2, - [0x6c] = KEY_3, - [0x6d] = KEY_4, - [0x6e] = KEY_5, - [0x6f] = KEY_6, - [0x70] = KEY_7, - [0x71] = KEY_8, - [0x72] = KEY_9, - - [0x74] = KEY_CHANNEL, - [0x0a] = KEY_BACKSPACE, -}; -EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color); + { 0x12, KEY_0 }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + + { 0x00, KEY_POWER }, + { 0x1b, KEY_AUDIO }, /* Audio Source */ + { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ + { 0x1e, KEY_VIDEO }, /* Video Source */ + { 0x16, KEY_INFO }, /* Display information */ + { 0x04, KEY_VOLUMEUP }, + { 0x08, KEY_VOLUMEDOWN }, + { 0x0c, KEY_CHANNELUP }, + { 0x10, KEY_CHANNELDOWN }, + { 0x03, KEY_ZOOM }, /* fullscreen */ + { 0x1f, KEY_TEXT }, /* closed caption/teletext */ + { 0x20, KEY_SLEEP }, + { 0x29, KEY_CLEAR }, /* boss key */ + { 0x14, KEY_MUTE }, + { 0x2b, KEY_RED }, + { 0x2c, KEY_GREEN }, + { 0x2d, KEY_YELLOW }, + { 0x2e, KEY_BLUE }, + { 0x18, KEY_KPPLUS }, /* fine tune + , not on Y040052 */ + { 0x19, KEY_KPMINUS }, /* fine tune - , not on Y040052 */ + { 0x2a, KEY_MEDIA }, /* PIP (Picture in picture */ + { 0x21, KEY_DOT }, + { 0x13, KEY_ENTER }, + { 0x11, KEY_LAST }, /* Recall (last channel */ + { 0x22, KEY_PREVIOUS }, + { 0x23, KEY_PLAYPAUSE }, + { 0x24, KEY_NEXT }, + { 0x25, KEY_TIME }, /* Time Shifting */ + { 0x26, KEY_STOP }, + { 0x27, KEY_RECORD }, + { 0x28, KEY_SAVE }, /* Screenshot */ + { 0x2f, KEY_MENU }, + { 0x30, KEY_CANCEL }, + { 0x31, KEY_CHANNEL }, /* Channel Surf */ + { 0x32, KEY_SUBTITLE }, + { 0x33, KEY_LANGUAGE }, + { 0x34, KEY_REWIND }, + { 0x35, KEY_FASTFORWARD }, + { 0x36, KEY_TV }, + { 0x37, KEY_RADIO }, /* FM */ + { 0x38, KEY_DVD }, + + { 0x3e, KEY_F21 }, /* MCE +VOL, on Y04G0033 */ + { 0x3a, KEY_F22 }, /* MCE -VOL, on Y04G0033 */ + { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ + { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ +}; + +struct ir_scancode_table ir_codes_winfast_table = { + .scan = ir_codes_winfast, + .size = ARRAY_SIZE(ir_codes_winfast), +}; +EXPORT_SYMBOL_GPL(ir_codes_winfast_table); + +static struct ir_scancode ir_codes_pinnacle_color[] = { + { 0x59, KEY_MUTE }, + { 0x4a, KEY_POWER }, + + { 0x18, KEY_TEXT }, + { 0x26, KEY_TV }, + { 0x3d, KEY_PRINT }, + + { 0x48, KEY_RED }, + { 0x04, KEY_GREEN }, + { 0x11, KEY_YELLOW }, + { 0x00, KEY_BLUE }, + + { 0x2d, KEY_VOLUMEUP }, + { 0x1e, KEY_VOLUMEDOWN }, + + { 0x49, KEY_MENU }, + + { 0x16, KEY_CHANNELUP }, + { 0x17, KEY_CHANNELDOWN }, + + { 0x20, KEY_UP }, + { 0x21, KEY_DOWN }, + { 0x22, KEY_LEFT }, + { 0x23, KEY_RIGHT }, + { 0x0d, KEY_SELECT }, + + { 0x08, KEY_BACK }, + { 0x07, KEY_REFRESH }, + + { 0x2f, KEY_ZOOM }, + { 0x29, KEY_RECORD }, + + { 0x4b, KEY_PAUSE }, + { 0x4d, KEY_REWIND }, + { 0x2e, KEY_PLAY }, + { 0x4e, KEY_FORWARD }, + { 0x53, KEY_PREVIOUS }, + { 0x4c, KEY_STOP }, + { 0x54, KEY_NEXT }, + + { 0x69, KEY_0 }, + { 0x6a, KEY_1 }, + { 0x6b, KEY_2 }, + { 0x6c, KEY_3 }, + { 0x6d, KEY_4 }, + { 0x6e, KEY_5 }, + { 0x6f, KEY_6 }, + { 0x70, KEY_7 }, + { 0x71, KEY_8 }, + { 0x72, KEY_9 }, + + { 0x74, KEY_CHANNEL }, + { 0x0a, KEY_BACKSPACE }, +}; + +struct ir_scancode_table ir_codes_pinnacle_color_table = { + .scan = ir_codes_pinnacle_color, + .size = ARRAY_SIZE(ir_codes_pinnacle_color), +}; +EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color_table); /* Hauppauge: the newer, gray remotes (seems there are multiple * slightly different versions), shipped with cx88+ivtv cards. * almost rc5 coding, but some non-standard keys */ -IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_hauppauge_new[] = { /* Keys 0 to 9 */ - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - - [0x0a] = KEY_TEXT, /* keypad asterisk as well */ - [0x0b] = KEY_RED, /* red button */ - [0x0c] = KEY_RADIO, - [0x0d] = KEY_MENU, - [0x0e] = KEY_SUBTITLE, /* also the # key */ - [0x0f] = KEY_MUTE, - [0x10] = KEY_VOLUMEUP, - [0x11] = KEY_VOLUMEDOWN, - [0x12] = KEY_PREVIOUS, /* previous channel */ - [0x14] = KEY_UP, - [0x15] = KEY_DOWN, - [0x16] = KEY_LEFT, - [0x17] = KEY_RIGHT, - [0x18] = KEY_VIDEO, /* Videos */ - [0x19] = KEY_AUDIO, /* Music */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0a, KEY_TEXT }, /* keypad asterisk as well */ + { 0x0b, KEY_RED }, /* red button */ + { 0x0c, KEY_RADIO }, + { 0x0d, KEY_MENU }, + { 0x0e, KEY_SUBTITLE }, /* also the # key */ + { 0x0f, KEY_MUTE }, + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x12, KEY_PREVIOUS }, /* previous channel */ + { 0x14, KEY_UP }, + { 0x15, KEY_DOWN }, + { 0x16, KEY_LEFT }, + { 0x17, KEY_RIGHT }, + { 0x18, KEY_VIDEO }, /* Videos */ + { 0x19, KEY_AUDIO }, /* Music */ /* 0x1a: Pictures - presume this means "Multimedia Home Platform" - no "PICTURES" key in input.h */ - [0x1a] = KEY_MHP, - - [0x1b] = KEY_EPG, /* Guide */ - [0x1c] = KEY_TV, - [0x1e] = KEY_NEXTSONG, /* skip >| */ - [0x1f] = KEY_EXIT, /* back/exit */ - [0x20] = KEY_CHANNELUP, /* channel / program + */ - [0x21] = KEY_CHANNELDOWN, /* channel / program - */ - [0x22] = KEY_CHANNEL, /* source (old black remote) */ - [0x24] = KEY_PREVIOUSSONG, /* replay |< */ - [0x25] = KEY_ENTER, /* OK */ - [0x26] = KEY_SLEEP, /* minimize (old black remote) */ - [0x29] = KEY_BLUE, /* blue key */ - [0x2e] = KEY_GREEN, /* green button */ - [0x30] = KEY_PAUSE, /* pause */ - [0x32] = KEY_REWIND, /* backward << */ - [0x34] = KEY_FASTFORWARD, /* forward >> */ - [0x35] = KEY_PLAY, - [0x36] = KEY_STOP, - [0x37] = KEY_RECORD, /* recording */ - [0x38] = KEY_YELLOW, /* yellow key */ - [0x3b] = KEY_SELECT, /* top right button */ - [0x3c] = KEY_ZOOM, /* full */ - [0x3d] = KEY_POWER, /* system power (green button) */ -}; -EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new); - -IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = { - [0x1d] = KEY_SWITCHVIDEOMODE, /* switch inputs */ - [0x2a] = KEY_FRONT, - - [0x3e] = KEY_1, - [0x02] = KEY_2, - [0x06] = KEY_3, - [0x0a] = KEY_4, - [0x0e] = KEY_5, - [0x12] = KEY_6, - [0x16] = KEY_7, - [0x1a] = KEY_8, - [0x1e] = KEY_9, - [0x3a] = KEY_0, - [0x22] = KEY_NUMLOCK, /* -/-- */ - [0x20] = KEY_REFRESH, - - [0x03] = KEY_BRIGHTNESSDOWN, - [0x28] = KEY_AUDIO, - [0x3c] = KEY_CHANNELUP, - [0x3f] = KEY_VOLUMEDOWN, - [0x2e] = KEY_MUTE, - [0x3b] = KEY_VOLUMEUP, - [0x00] = KEY_CHANNELDOWN, - [0x07] = KEY_BRIGHTNESSUP, - [0x2c] = KEY_TEXT, - - [0x37] = KEY_RECORD, - [0x17] = KEY_PLAY, - [0x13] = KEY_PAUSE, - [0x26] = KEY_STOP, - [0x18] = KEY_FASTFORWARD, - [0x14] = KEY_REWIND, - [0x33] = KEY_ZOOM, - [0x32] = KEY_KEYBOARD, - [0x30] = KEY_GOTO, /* Pointing arrow */ - [0x36] = KEY_MACRO, /* Maximize/Minimize (yellow) */ - [0x0b] = KEY_RADIO, - [0x10] = KEY_POWER, - -}; -EXPORT_SYMBOL_GPL(ir_codes_npgtech); + { 0x1a, KEY_MHP }, + + { 0x1b, KEY_EPG }, /* Guide */ + { 0x1c, KEY_TV }, + { 0x1e, KEY_NEXTSONG }, /* skip >| */ + { 0x1f, KEY_EXIT }, /* back/exit */ + { 0x20, KEY_CHANNELUP }, /* channel / program + */ + { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x22, KEY_CHANNEL }, /* source (old black remote) */ + { 0x24, KEY_PREVIOUSSONG }, /* replay |< */ + { 0x25, KEY_ENTER }, /* OK */ + { 0x26, KEY_SLEEP }, /* minimize (old black remote) */ + { 0x29, KEY_BLUE }, /* blue key */ + { 0x2e, KEY_GREEN }, /* green button */ + { 0x30, KEY_PAUSE }, /* pause */ + { 0x32, KEY_REWIND }, /* backward << */ + { 0x34, KEY_FASTFORWARD }, /* forward >> */ + { 0x35, KEY_PLAY }, + { 0x36, KEY_STOP }, + { 0x37, KEY_RECORD }, /* recording */ + { 0x38, KEY_YELLOW }, /* yellow key */ + { 0x3b, KEY_SELECT }, /* top right button */ + { 0x3c, KEY_ZOOM }, /* full */ + { 0x3d, KEY_POWER }, /* system power (green button) */ +}; + +struct ir_scancode_table ir_codes_hauppauge_new_table = { + .scan = ir_codes_hauppauge_new, + .size = ARRAY_SIZE(ir_codes_hauppauge_new), +}; +EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new_table); + +static struct ir_scancode ir_codes_npgtech[] = { + { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ + { 0x2a, KEY_FRONT }, + + { 0x3e, KEY_1 }, + { 0x02, KEY_2 }, + { 0x06, KEY_3 }, + { 0x0a, KEY_4 }, + { 0x0e, KEY_5 }, + { 0x12, KEY_6 }, + { 0x16, KEY_7 }, + { 0x1a, KEY_8 }, + { 0x1e, KEY_9 }, + { 0x3a, KEY_0 }, + { 0x22, KEY_NUMLOCK }, /* -/-- */ + { 0x20, KEY_REFRESH }, + + { 0x03, KEY_BRIGHTNESSDOWN }, + { 0x28, KEY_AUDIO }, + { 0x3c, KEY_CHANNELUP }, + { 0x3f, KEY_VOLUMEDOWN }, + { 0x2e, KEY_MUTE }, + { 0x3b, KEY_VOLUMEUP }, + { 0x00, KEY_CHANNELDOWN }, + { 0x07, KEY_BRIGHTNESSUP }, + { 0x2c, KEY_TEXT }, + + { 0x37, KEY_RECORD }, + { 0x17, KEY_PLAY }, + { 0x13, KEY_PAUSE }, + { 0x26, KEY_STOP }, + { 0x18, KEY_FASTFORWARD }, + { 0x14, KEY_REWIND }, + { 0x33, KEY_ZOOM }, + { 0x32, KEY_KEYBOARD }, + { 0x30, KEY_GOTO }, /* Pointing arrow */ + { 0x36, KEY_MACRO }, /* Maximize/Minimize (yellow) */ + { 0x0b, KEY_RADIO }, + { 0x10, KEY_POWER }, + +}; + +struct ir_scancode_table ir_codes_npgtech_table = { + .scan = ir_codes_npgtech, + .size = ARRAY_SIZE(ir_codes_npgtech), +}; +EXPORT_SYMBOL_GPL(ir_codes_npgtech_table); /* Norwood Micro (non-Pro) TV Tuner By Peter Naulls Key comments are the functions given in the manual */ -IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_norwood[] = { /* Keys 0 to 9 */ - [0x20] = KEY_0, - [0x21] = KEY_1, - [0x22] = KEY_2, - [0x23] = KEY_3, - [0x24] = KEY_4, - [0x25] = KEY_5, - [0x26] = KEY_6, - [0x27] = KEY_7, - [0x28] = KEY_8, - [0x29] = KEY_9, - - [0x78] = KEY_TUNER, /* Video Source */ - [0x2c] = KEY_EXIT, /* Open/Close software */ - [0x2a] = KEY_SELECT, /* 2 Digit Select */ - [0x69] = KEY_AGAIN, /* Recall */ - - [0x32] = KEY_BRIGHTNESSUP, /* Brightness increase */ - [0x33] = KEY_BRIGHTNESSDOWN, /* Brightness decrease */ - [0x6b] = KEY_KPPLUS, /* (not named >>>>>) */ - [0x6c] = KEY_KPMINUS, /* (not named <<<<<) */ - - [0x2d] = KEY_MUTE, /* Mute */ - [0x30] = KEY_VOLUMEUP, /* Volume up */ - [0x31] = KEY_VOLUMEDOWN,/* Volume down */ - [0x60] = KEY_CHANNELUP, /* Channel up */ - [0x61] = KEY_CHANNELDOWN,/* Channel down */ - - [0x3f] = KEY_RECORD, /* Record */ - [0x37] = KEY_PLAY, /* Play */ - [0x36] = KEY_PAUSE, /* Pause */ - [0x2b] = KEY_STOP, /* Stop */ - [0x67] = KEY_FASTFORWARD,/* Foward */ - [0x66] = KEY_REWIND, /* Rewind */ - [0x3e] = KEY_SEARCH, /* Auto Scan */ - [0x2e] = KEY_CAMERA, /* Capture Video */ - [0x6d] = KEY_MENU, /* Show/Hide Control */ - [0x2f] = KEY_ZOOM, /* Full Screen */ - [0x34] = KEY_RADIO, /* FM */ - [0x65] = KEY_POWER, /* Computer power */ -}; -EXPORT_SYMBOL_GPL(ir_codes_norwood); + { 0x20, KEY_0 }, + { 0x21, KEY_1 }, + { 0x22, KEY_2 }, + { 0x23, KEY_3 }, + { 0x24, KEY_4 }, + { 0x25, KEY_5 }, + { 0x26, KEY_6 }, + { 0x27, KEY_7 }, + { 0x28, KEY_8 }, + { 0x29, KEY_9 }, + + { 0x78, KEY_TUNER }, /* Video Source */ + { 0x2c, KEY_EXIT }, /* Open/Close software */ + { 0x2a, KEY_SELECT }, /* 2 Digit Select */ + { 0x69, KEY_AGAIN }, /* Recall */ + + { 0x32, KEY_BRIGHTNESSUP }, /* Brightness increase */ + { 0x33, KEY_BRIGHTNESSDOWN }, /* Brightness decrease */ + { 0x6b, KEY_KPPLUS }, /* (not named >>>>>) */ + { 0x6c, KEY_KPMINUS }, /* (not named <<<<<) */ + + { 0x2d, KEY_MUTE }, /* Mute */ + { 0x30, KEY_VOLUMEUP }, /* Volume up */ + { 0x31, KEY_VOLUMEDOWN }, /* Volume down */ + { 0x60, KEY_CHANNELUP }, /* Channel up */ + { 0x61, KEY_CHANNELDOWN }, /* Channel down */ + + { 0x3f, KEY_RECORD }, /* Record */ + { 0x37, KEY_PLAY }, /* Play */ + { 0x36, KEY_PAUSE }, /* Pause */ + { 0x2b, KEY_STOP }, /* Stop */ + { 0x67, KEY_FASTFORWARD }, /* Foward */ + { 0x66, KEY_REWIND }, /* Rewind */ + { 0x3e, KEY_SEARCH }, /* Auto Scan */ + { 0x2e, KEY_CAMERA }, /* Capture Video */ + { 0x6d, KEY_MENU }, /* Show/Hide Control */ + { 0x2f, KEY_ZOOM }, /* Full Screen */ + { 0x34, KEY_RADIO }, /* FM */ + { 0x65, KEY_POWER }, /* Computer power */ +}; + +struct ir_scancode_table ir_codes_norwood_table = { + .scan = ir_codes_norwood, + .size = ARRAY_SIZE(ir_codes_norwood), +}; +EXPORT_SYMBOL_GPL(ir_codes_norwood_table); /* From reading the following remotes: * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 * Hauppauge (from NOVA-CI-s box product) * This is a "middle of the road" approach, differences are noted */ -IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = { - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - [0x0a] = KEY_ENTER, - [0x0b] = KEY_RED, - [0x0c] = KEY_POWER, /* RADIO on Hauppauge */ - [0x0d] = KEY_MUTE, - [0x0f] = KEY_A, /* TV on Hauppauge */ - [0x10] = KEY_VOLUMEUP, - [0x11] = KEY_VOLUMEDOWN, - [0x14] = KEY_B, - [0x1c] = KEY_UP, - [0x1d] = KEY_DOWN, - [0x1e] = KEY_OPTION, /* RESERVED on Hauppauge */ - [0x1f] = KEY_BREAK, - [0x20] = KEY_CHANNELUP, - [0x21] = KEY_CHANNELDOWN, - [0x22] = KEY_PREVIOUS, /* Prev Ch on Zenith, SOURCE on Hauppauge */ - [0x24] = KEY_RESTART, - [0x25] = KEY_OK, - [0x26] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */ - [0x28] = KEY_ENTER, /* VCR mode on Zenith */ - [0x29] = KEY_PAUSE, - [0x2b] = KEY_RIGHT, - [0x2c] = KEY_LEFT, - [0x2e] = KEY_MENU, /* FULL SCREEN on Hauppauge */ - [0x30] = KEY_SLOW, - [0x31] = KEY_PREVIOUS, /* VCR mode on Zenith */ - [0x32] = KEY_REWIND, - [0x34] = KEY_FASTFORWARD, - [0x35] = KEY_PLAY, - [0x36] = KEY_STOP, - [0x37] = KEY_RECORD, - [0x38] = KEY_TUNER, /* TV/VCR on Zenith */ - [0x3a] = KEY_C, - [0x3c] = KEY_EXIT, - [0x3d] = KEY_POWER2, - [0x3e] = KEY_TUNER, -}; -EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old); +static struct ir_scancode ir_codes_budget_ci_old[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x0a, KEY_ENTER }, + { 0x0b, KEY_RED }, + { 0x0c, KEY_POWER }, /* RADIO on Hauppauge */ + { 0x0d, KEY_MUTE }, + { 0x0f, KEY_A }, /* TV on Hauppauge */ + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x14, KEY_B }, + { 0x1c, KEY_UP }, + { 0x1d, KEY_DOWN }, + { 0x1e, KEY_OPTION }, /* RESERVED on Hauppauge */ + { 0x1f, KEY_BREAK }, + { 0x20, KEY_CHANNELUP }, + { 0x21, KEY_CHANNELDOWN }, + { 0x22, KEY_PREVIOUS }, /* Prev Ch on Zenith, SOURCE on Hauppauge */ + { 0x24, KEY_RESTART }, + { 0x25, KEY_OK }, + { 0x26, KEY_CYCLEWINDOWS }, /* MINIMIZE on Hauppauge */ + { 0x28, KEY_ENTER }, /* VCR mode on Zenith */ + { 0x29, KEY_PAUSE }, + { 0x2b, KEY_RIGHT }, + { 0x2c, KEY_LEFT }, + { 0x2e, KEY_MENU }, /* FULL SCREEN on Hauppauge */ + { 0x30, KEY_SLOW }, + { 0x31, KEY_PREVIOUS }, /* VCR mode on Zenith */ + { 0x32, KEY_REWIND }, + { 0x34, KEY_FASTFORWARD }, + { 0x35, KEY_PLAY }, + { 0x36, KEY_STOP }, + { 0x37, KEY_RECORD }, + { 0x38, KEY_TUNER }, /* TV/VCR on Zenith */ + { 0x3a, KEY_C }, + { 0x3c, KEY_EXIT }, + { 0x3d, KEY_POWER2 }, + { 0x3e, KEY_TUNER }, +}; + +struct ir_scancode_table ir_codes_budget_ci_old_table = { + .scan = ir_codes_budget_ci_old, + .size = ARRAY_SIZE(ir_codes_budget_ci_old), +}; +EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old_table); /* * Marc Fargas * this is the remote control that comes with the asus p7131 * which has a label saying is "Model PC-39" */ -IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_asus_pc39[] = { /* Keys 0 to 9 */ - [0x15] = KEY_0, - [0x29] = KEY_1, - [0x2d] = KEY_2, - [0x2b] = KEY_3, - [0x09] = KEY_4, - [0x0d] = KEY_5, - [0x0b] = KEY_6, - [0x31] = KEY_7, - [0x35] = KEY_8, - [0x33] = KEY_9, - - [0x3e] = KEY_RADIO, /* radio */ - [0x03] = KEY_MENU, /* dvd/menu */ - [0x2a] = KEY_VOLUMEUP, - [0x19] = KEY_VOLUMEDOWN, - [0x37] = KEY_UP, - [0x3b] = KEY_DOWN, - [0x27] = KEY_LEFT, - [0x2f] = KEY_RIGHT, - [0x25] = KEY_VIDEO, /* video */ - [0x39] = KEY_AUDIO, /* music */ - - [0x21] = KEY_TV, /* tv */ - [0x1d] = KEY_EXIT, /* back */ - [0x0a] = KEY_CHANNELUP, /* channel / program + */ - [0x1b] = KEY_CHANNELDOWN, /* channel / program - */ - [0x1a] = KEY_ENTER, /* enter */ - - [0x06] = KEY_PAUSE, /* play/pause */ - [0x1e] = KEY_PREVIOUS, /* rew */ - [0x26] = KEY_NEXT, /* forward */ - [0x0e] = KEY_REWIND, /* backward << */ - [0x3a] = KEY_FASTFORWARD, /* forward >> */ - [0x36] = KEY_STOP, - [0x2e] = KEY_RECORD, /* recording */ - [0x16] = KEY_POWER, /* the button that reads "close" */ - - [0x11] = KEY_ZOOM, /* full screen */ - [0x13] = KEY_MACRO, /* recall */ - [0x23] = KEY_HOME, /* home */ - [0x05] = KEY_PVR, /* picture */ - [0x3d] = KEY_MUTE, /* mute */ - [0x01] = KEY_DVD, /* dvd */ -}; -EXPORT_SYMBOL_GPL(ir_codes_asus_pc39); + { 0x15, KEY_0 }, + { 0x29, KEY_1 }, + { 0x2d, KEY_2 }, + { 0x2b, KEY_3 }, + { 0x09, KEY_4 }, + { 0x0d, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x31, KEY_7 }, + { 0x35, KEY_8 }, + { 0x33, KEY_9 }, + + { 0x3e, KEY_RADIO }, /* radio */ + { 0x03, KEY_MENU }, /* dvd/menu */ + { 0x2a, KEY_VOLUMEUP }, + { 0x19, KEY_VOLUMEDOWN }, + { 0x37, KEY_UP }, + { 0x3b, KEY_DOWN }, + { 0x27, KEY_LEFT }, + { 0x2f, KEY_RIGHT }, + { 0x25, KEY_VIDEO }, /* video */ + { 0x39, KEY_AUDIO }, /* music */ + + { 0x21, KEY_TV }, /* tv */ + { 0x1d, KEY_EXIT }, /* back */ + { 0x0a, KEY_CHANNELUP }, /* channel / program + */ + { 0x1b, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x1a, KEY_ENTER }, /* enter */ + + { 0x06, KEY_PAUSE }, /* play/pause */ + { 0x1e, KEY_PREVIOUS }, /* rew */ + { 0x26, KEY_NEXT }, /* forward */ + { 0x0e, KEY_REWIND }, /* backward << */ + { 0x3a, KEY_FASTFORWARD }, /* forward >> */ + { 0x36, KEY_STOP }, + { 0x2e, KEY_RECORD }, /* recording */ + { 0x16, KEY_POWER }, /* the button that reads "close" */ + + { 0x11, KEY_ZOOM }, /* full screen */ + { 0x13, KEY_MACRO }, /* recall */ + { 0x23, KEY_HOME }, /* home */ + { 0x05, KEY_PVR }, /* picture */ + { 0x3d, KEY_MUTE }, /* mute */ + { 0x01, KEY_DVD }, /* dvd */ +}; + +struct ir_scancode_table ir_codes_asus_pc39_table = { + .scan = ir_codes_asus_pc39, + .size = ARRAY_SIZE(ir_codes_asus_pc39), +}; +EXPORT_SYMBOL_GPL(ir_codes_asus_pc39_table); /* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons Juan Pablo Sormani */ -IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_encore_enltv[] = { /* Power button does nothing, neither in Windows app, although it sends data (used for BIOS wakeup?) */ - [0x0d] = KEY_MUTE, - - [0x1e] = KEY_TV, - [0x00] = KEY_VIDEO, - [0x01] = KEY_AUDIO, /* music */ - [0x02] = KEY_MHP, /* picture */ - - [0x1f] = KEY_1, - [0x03] = KEY_2, - [0x04] = KEY_3, - [0x05] = KEY_4, - [0x1c] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x1d] = KEY_9, - [0x0a] = KEY_0, - - [0x09] = KEY_LIST, /* -/-- */ - [0x0b] = KEY_LAST, /* recall */ - - [0x14] = KEY_HOME, /* win start menu */ - [0x15] = KEY_EXIT, /* exit */ - [0x16] = KEY_CHANNELUP, /* UP */ - [0x12] = KEY_CHANNELDOWN, /* DOWN */ - [0x0c] = KEY_VOLUMEUP, /* RIGHT */ - [0x17] = KEY_VOLUMEDOWN, /* LEFT */ - - [0x18] = KEY_ENTER, /* OK */ - - [0x0e] = KEY_ESC, - [0x13] = KEY_CYCLEWINDOWS, /* desktop */ - [0x11] = KEY_TAB, - [0x19] = KEY_SWITCHVIDEOMODE, /* switch */ - - [0x1a] = KEY_MENU, - [0x1b] = KEY_ZOOM, /* fullscreen */ - [0x44] = KEY_TIME, /* time shift */ - [0x40] = KEY_MODE, /* source */ - - [0x5a] = KEY_RECORD, - [0x42] = KEY_PLAY, /* play/pause */ - [0x45] = KEY_STOP, - [0x43] = KEY_CAMERA, /* camera icon */ - - [0x48] = KEY_REWIND, - [0x4a] = KEY_FASTFORWARD, - [0x49] = KEY_PREVIOUS, - [0x4b] = KEY_NEXT, - - [0x4c] = KEY_FAVORITES, /* tv wall */ - [0x4d] = KEY_SOUND, /* DVD sound */ - [0x4e] = KEY_LANGUAGE, /* DVD lang */ - [0x4f] = KEY_TEXT, /* DVD text */ - - [0x50] = KEY_SLEEP, /* shutdown */ - [0x51] = KEY_MODE, /* stereo > main */ - [0x52] = KEY_SELECT, /* stereo > sap */ - [0x53] = KEY_PROG1, /* teletext */ - - - [0x59] = KEY_RED, /* AP1 */ - [0x41] = KEY_GREEN, /* AP2 */ - [0x47] = KEY_YELLOW, /* AP3 */ - [0x57] = KEY_BLUE, /* AP4 */ -}; -EXPORT_SYMBOL_GPL(ir_codes_encore_enltv); + { 0x0d, KEY_MUTE }, + + { 0x1e, KEY_TV }, + { 0x00, KEY_VIDEO }, + { 0x01, KEY_AUDIO }, /* music */ + { 0x02, KEY_MHP }, /* picture */ + + { 0x1f, KEY_1 }, + { 0x03, KEY_2 }, + { 0x04, KEY_3 }, + { 0x05, KEY_4 }, + { 0x1c, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x1d, KEY_9 }, + { 0x0a, KEY_0 }, + + { 0x09, KEY_LIST }, /* -/-- */ + { 0x0b, KEY_LAST }, /* recall */ + + { 0x14, KEY_HOME }, /* win start menu */ + { 0x15, KEY_EXIT }, /* exit */ + { 0x16, KEY_CHANNELUP }, /* UP */ + { 0x12, KEY_CHANNELDOWN }, /* DOWN */ + { 0x0c, KEY_VOLUMEUP }, /* RIGHT */ + { 0x17, KEY_VOLUMEDOWN }, /* LEFT */ + + { 0x18, KEY_ENTER }, /* OK */ + + { 0x0e, KEY_ESC }, + { 0x13, KEY_CYCLEWINDOWS }, /* desktop */ + { 0x11, KEY_TAB }, + { 0x19, KEY_SWITCHVIDEOMODE }, /* switch */ + + { 0x1a, KEY_MENU }, + { 0x1b, KEY_ZOOM }, /* fullscreen */ + { 0x44, KEY_TIME }, /* time shift */ + { 0x40, KEY_MODE }, /* source */ + + { 0x5a, KEY_RECORD }, + { 0x42, KEY_PLAY }, /* play/pause */ + { 0x45, KEY_STOP }, + { 0x43, KEY_CAMERA }, /* camera icon */ + + { 0x48, KEY_REWIND }, + { 0x4a, KEY_FASTFORWARD }, + { 0x49, KEY_PREVIOUS }, + { 0x4b, KEY_NEXT }, + + { 0x4c, KEY_FAVORITES }, /* tv wall */ + { 0x4d, KEY_SOUND }, /* DVD sound */ + { 0x4e, KEY_LANGUAGE }, /* DVD lang */ + { 0x4f, KEY_TEXT }, /* DVD text */ + + { 0x50, KEY_SLEEP }, /* shutdown */ + { 0x51, KEY_MODE }, /* stereo > main */ + { 0x52, KEY_SELECT }, /* stereo > sap */ + { 0x53, KEY_PROG1 }, /* teletext */ + + + { 0x59, KEY_RED }, /* AP1 */ + { 0x41, KEY_GREEN }, /* AP2 */ + { 0x47, KEY_YELLOW }, /* AP3 */ + { 0x57, KEY_BLUE }, /* AP4 */ +}; + +struct ir_scancode_table ir_codes_encore_enltv_table = { + .scan = ir_codes_encore_enltv, + .size = ARRAY_SIZE(ir_codes_encore_enltv), +}; +EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_table); /* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton Mauro Carvalho Chehab */ -IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE] = { - [0x4c] = KEY_POWER2, - [0x4a] = KEY_TUNER, - [0x40] = KEY_1, - [0x60] = KEY_2, - [0x50] = KEY_3, - [0x70] = KEY_4, - [0x48] = KEY_5, - [0x68] = KEY_6, - [0x58] = KEY_7, - [0x78] = KEY_8, - [0x44] = KEY_9, - [0x54] = KEY_0, - - [0x64] = KEY_LAST, /* +100 */ - [0x4e] = KEY_AGAIN, /* Recall */ - - [0x6c] = KEY_SWITCHVIDEOMODE, /* Video Source */ - [0x5e] = KEY_MENU, - [0x56] = KEY_SCREEN, - [0x7a] = KEY_SETUP, - - [0x46] = KEY_MUTE, - [0x5c] = KEY_MODE, /* Stereo */ - [0x74] = KEY_INFO, - [0x7c] = KEY_CLEAR, - - [0x55] = KEY_UP, - [0x49] = KEY_DOWN, - [0x7e] = KEY_LEFT, - [0x59] = KEY_RIGHT, - [0x6a] = KEY_ENTER, - - [0x42] = KEY_VOLUMEUP, - [0x62] = KEY_VOLUMEDOWN, - [0x52] = KEY_CHANNELUP, - [0x72] = KEY_CHANNELDOWN, - - [0x41] = KEY_RECORD, - [0x51] = KEY_CAMERA, /* Snapshot */ - [0x75] = KEY_TIME, /* Timeshift */ - [0x71] = KEY_TV2, /* PIP */ - - [0x45] = KEY_REWIND, - [0x6f] = KEY_PAUSE, - [0x7d] = KEY_FORWARD, - [0x79] = KEY_STOP, -}; -EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2); +static struct ir_scancode ir_codes_encore_enltv2[] = { + { 0x4c, KEY_POWER2 }, + { 0x4a, KEY_TUNER }, + { 0x40, KEY_1 }, + { 0x60, KEY_2 }, + { 0x50, KEY_3 }, + { 0x70, KEY_4 }, + { 0x48, KEY_5 }, + { 0x68, KEY_6 }, + { 0x58, KEY_7 }, + { 0x78, KEY_8 }, + { 0x44, KEY_9 }, + { 0x54, KEY_0 }, + + { 0x64, KEY_LAST }, /* +100 */ + { 0x4e, KEY_AGAIN }, /* Recall */ + + { 0x6c, KEY_SWITCHVIDEOMODE }, /* Video Source */ + { 0x5e, KEY_MENU }, + { 0x56, KEY_SCREEN }, + { 0x7a, KEY_SETUP }, + + { 0x46, KEY_MUTE }, + { 0x5c, KEY_MODE }, /* Stereo */ + { 0x74, KEY_INFO }, + { 0x7c, KEY_CLEAR }, + + { 0x55, KEY_UP }, + { 0x49, KEY_DOWN }, + { 0x7e, KEY_LEFT }, + { 0x59, KEY_RIGHT }, + { 0x6a, KEY_ENTER }, + + { 0x42, KEY_VOLUMEUP }, + { 0x62, KEY_VOLUMEDOWN }, + { 0x52, KEY_CHANNELUP }, + { 0x72, KEY_CHANNELDOWN }, + + { 0x41, KEY_RECORD }, + { 0x51, KEY_CAMERA }, /* Snapshot */ + { 0x75, KEY_TIME }, /* Timeshift */ + { 0x71, KEY_TV2 }, /* PIP */ + + { 0x45, KEY_REWIND }, + { 0x6f, KEY_PAUSE }, + { 0x7d, KEY_FORWARD }, + { 0x79, KEY_STOP }, +}; + +struct ir_scancode_table ir_codes_encore_enltv2_table = { + .scan = ir_codes_encore_enltv2, + .size = ARRAY_SIZE(ir_codes_encore_enltv2), +}; +EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2_table); /* for the Technotrend 1500 bundled remotes (grey and black): */ -IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = { - [0x01] = KEY_POWER, - [0x02] = KEY_SHUFFLE, /* ? double-arrow key */ - [0x03] = KEY_1, - [0x04] = KEY_2, - [0x05] = KEY_3, - [0x06] = KEY_4, - [0x07] = KEY_5, - [0x08] = KEY_6, - [0x09] = KEY_7, - [0x0a] = KEY_8, - [0x0b] = KEY_9, - [0x0c] = KEY_0, - [0x0d] = KEY_UP, - [0x0e] = KEY_LEFT, - [0x0f] = KEY_OK, - [0x10] = KEY_RIGHT, - [0x11] = KEY_DOWN, - [0x12] = KEY_INFO, - [0x13] = KEY_EXIT, - [0x14] = KEY_RED, - [0x15] = KEY_GREEN, - [0x16] = KEY_YELLOW, - [0x17] = KEY_BLUE, - [0x18] = KEY_MUTE, - [0x19] = KEY_TEXT, - [0x1a] = KEY_MODE, /* ? TV/Radio */ - [0x21] = KEY_OPTION, - [0x22] = KEY_EPG, - [0x23] = KEY_CHANNELUP, - [0x24] = KEY_CHANNELDOWN, - [0x25] = KEY_VOLUMEUP, - [0x26] = KEY_VOLUMEDOWN, - [0x27] = KEY_SETUP, - [0x3a] = KEY_RECORD, /* these keys are only in the black remote */ - [0x3b] = KEY_PLAY, - [0x3c] = KEY_STOP, - [0x3d] = KEY_REWIND, - [0x3e] = KEY_PAUSE, - [0x3f] = KEY_FORWARD, -}; -EXPORT_SYMBOL_GPL(ir_codes_tt_1500); +static struct ir_scancode ir_codes_tt_1500[] = { + { 0x01, KEY_POWER }, + { 0x02, KEY_SHUFFLE }, /* ? double-arrow key */ + { 0x03, KEY_1 }, + { 0x04, KEY_2 }, + { 0x05, KEY_3 }, + { 0x06, KEY_4 }, + { 0x07, KEY_5 }, + { 0x08, KEY_6 }, + { 0x09, KEY_7 }, + { 0x0a, KEY_8 }, + { 0x0b, KEY_9 }, + { 0x0c, KEY_0 }, + { 0x0d, KEY_UP }, + { 0x0e, KEY_LEFT }, + { 0x0f, KEY_OK }, + { 0x10, KEY_RIGHT }, + { 0x11, KEY_DOWN }, + { 0x12, KEY_INFO }, + { 0x13, KEY_EXIT }, + { 0x14, KEY_RED }, + { 0x15, KEY_GREEN }, + { 0x16, KEY_YELLOW }, + { 0x17, KEY_BLUE }, + { 0x18, KEY_MUTE }, + { 0x19, KEY_TEXT }, + { 0x1a, KEY_MODE }, /* ? TV/Radio */ + { 0x21, KEY_OPTION }, + { 0x22, KEY_EPG }, + { 0x23, KEY_CHANNELUP }, + { 0x24, KEY_CHANNELDOWN }, + { 0x25, KEY_VOLUMEUP }, + { 0x26, KEY_VOLUMEDOWN }, + { 0x27, KEY_SETUP }, + { 0x3a, KEY_RECORD }, /* these keys are only in the black remote */ + { 0x3b, KEY_PLAY }, + { 0x3c, KEY_STOP }, + { 0x3d, KEY_REWIND }, + { 0x3e, KEY_PAUSE }, + { 0x3f, KEY_FORWARD }, +}; + +struct ir_scancode_table ir_codes_tt_1500_table = { + .scan = ir_codes_tt_1500, + .size = ARRAY_SIZE(ir_codes_tt_1500), +}; +EXPORT_SYMBOL_GPL(ir_codes_tt_1500_table); /* DViCO FUSION HDTV MCE remote */ -IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = { - - [0x0b] = KEY_1, - [0x17] = KEY_2, - [0x1b] = KEY_3, - [0x07] = KEY_4, - [0x50] = KEY_5, - [0x54] = KEY_6, - [0x48] = KEY_7, - [0x4c] = KEY_8, - [0x58] = KEY_9, - [0x03] = KEY_0, - - [0x5e] = KEY_OK, - [0x51] = KEY_UP, - [0x53] = KEY_DOWN, - [0x5b] = KEY_LEFT, - [0x5f] = KEY_RIGHT, - - [0x02] = KEY_TV, /* Labeled DTV on remote */ - [0x0e] = KEY_MP3, - [0x1a] = KEY_DVD, - [0x1e] = KEY_FAVORITES, /* Labeled CPF on remote */ - [0x16] = KEY_SETUP, - [0x46] = KEY_POWER2, /* TV On/Off button on remote */ - [0x0a] = KEY_EPG, /* Labeled Guide on remote */ - - [0x49] = KEY_BACK, - [0x59] = KEY_INFO, /* Labeled MORE on remote */ - [0x4d] = KEY_MENU, /* Labeled DVDMENU on remote */ - [0x55] = KEY_CYCLEWINDOWS, /* Labeled ALT-TAB on remote */ - - [0x0f] = KEY_PREVIOUSSONG, /* Labeled |<< REPLAY on remote */ - [0x12] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */ - [0x42] = KEY_ENTER, /* Labeled START with a green +static struct ir_scancode ir_codes_fusionhdtv_mce[] = { + + { 0x0b, KEY_1 }, + { 0x17, KEY_2 }, + { 0x1b, KEY_3 }, + { 0x07, KEY_4 }, + { 0x50, KEY_5 }, + { 0x54, KEY_6 }, + { 0x48, KEY_7 }, + { 0x4c, KEY_8 }, + { 0x58, KEY_9 }, + { 0x03, KEY_0 }, + + { 0x5e, KEY_OK }, + { 0x51, KEY_UP }, + { 0x53, KEY_DOWN }, + { 0x5b, KEY_LEFT }, + { 0x5f, KEY_RIGHT }, + + { 0x02, KEY_TV }, /* Labeled DTV on remote */ + { 0x0e, KEY_MP3 }, + { 0x1a, KEY_DVD }, + { 0x1e, KEY_FAVORITES }, /* Labeled CPF on remote */ + { 0x16, KEY_SETUP }, + { 0x46, KEY_POWER2 }, /* TV On/Off button on remote */ + { 0x0a, KEY_EPG }, /* Labeled Guide on remote */ + + { 0x49, KEY_BACK }, + { 0x59, KEY_INFO }, /* Labeled MORE on remote */ + { 0x4d, KEY_MENU }, /* Labeled DVDMENU on remote */ + { 0x55, KEY_CYCLEWINDOWS }, /* Labeled ALT-TAB on remote */ + + { 0x0f, KEY_PREVIOUSSONG }, /* Labeled |<< REPLAY on remote */ + { 0x12, KEY_NEXTSONG }, /* Labeled >>| SKIP on remote */ + { 0x42, KEY_ENTER }, /* Labeled START with a green MS windows logo on remote */ - [0x15] = KEY_VOLUMEUP, - [0x05] = KEY_VOLUMEDOWN, - [0x11] = KEY_CHANNELUP, - [0x09] = KEY_CHANNELDOWN, - - [0x52] = KEY_CAMERA, - [0x5a] = KEY_TUNER, - [0x19] = KEY_OPEN, - - [0x13] = KEY_MODE, /* 4:3 16:9 select */ - [0x1f] = KEY_ZOOM, + { 0x15, KEY_VOLUMEUP }, + { 0x05, KEY_VOLUMEDOWN }, + { 0x11, KEY_CHANNELUP }, + { 0x09, KEY_CHANNELDOWN }, + + { 0x52, KEY_CAMERA }, + { 0x5a, KEY_TUNER }, + { 0x19, KEY_OPEN }, + + { 0x13, KEY_MODE }, /* 4:3 16:9 select */ + { 0x1f, KEY_ZOOM }, + + { 0x43, KEY_REWIND }, + { 0x47, KEY_PLAYPAUSE }, + { 0x4f, KEY_FASTFORWARD }, + { 0x57, KEY_MUTE }, + { 0x0d, KEY_STOP }, + { 0x01, KEY_RECORD }, + { 0x4e, KEY_POWER }, +}; - [0x43] = KEY_REWIND, - [0x47] = KEY_PLAYPAUSE, - [0x4f] = KEY_FASTFORWARD, - [0x57] = KEY_MUTE, - [0x0d] = KEY_STOP, - [0x01] = KEY_RECORD, - [0x4e] = KEY_POWER, +struct ir_scancode_table ir_codes_fusionhdtv_mce_table = { + .scan = ir_codes_fusionhdtv_mce, + .size = ARRAY_SIZE(ir_codes_fusionhdtv_mce), }; -EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce); +EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce_table); /* Pinnacle PCTV HD 800i mini remote */ -IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE] = { - - [0x0f] = KEY_1, - [0x15] = KEY_2, - [0x10] = KEY_3, - [0x18] = KEY_4, - [0x1b] = KEY_5, - [0x1e] = KEY_6, - [0x11] = KEY_7, - [0x21] = KEY_8, - [0x12] = KEY_9, - [0x27] = KEY_0, - - [0x24] = KEY_ZOOM, - [0x2a] = KEY_SUBTITLE, - - [0x00] = KEY_MUTE, - [0x01] = KEY_ENTER, /* Pinnacle Logo */ - [0x39] = KEY_POWER, - - [0x03] = KEY_VOLUMEUP, - [0x09] = KEY_VOLUMEDOWN, - [0x06] = KEY_CHANNELUP, - [0x0c] = KEY_CHANNELDOWN, - - [0x2d] = KEY_REWIND, - [0x30] = KEY_PLAYPAUSE, - [0x33] = KEY_FASTFORWARD, - [0x3c] = KEY_STOP, - [0x36] = KEY_RECORD, - [0x3f] = KEY_EPG, /* Labeled "?" */ -}; -EXPORT_SYMBOL_GPL(ir_codes_pinnacle_pctv_hd); +static struct ir_scancode ir_codes_pinnacle_pctv_hd[] = { + + { 0x0f, KEY_1 }, + { 0x15, KEY_2 }, + { 0x10, KEY_3 }, + { 0x18, KEY_4 }, + { 0x1b, KEY_5 }, + { 0x1e, KEY_6 }, + { 0x11, KEY_7 }, + { 0x21, KEY_8 }, + { 0x12, KEY_9 }, + { 0x27, KEY_0 }, + + { 0x24, KEY_ZOOM }, + { 0x2a, KEY_SUBTITLE }, + + { 0x00, KEY_MUTE }, + { 0x01, KEY_ENTER }, /* Pinnacle Logo */ + { 0x39, KEY_POWER }, + + { 0x03, KEY_VOLUMEUP }, + { 0x09, KEY_VOLUMEDOWN }, + { 0x06, KEY_CHANNELUP }, + { 0x0c, KEY_CHANNELDOWN }, + + { 0x2d, KEY_REWIND }, + { 0x30, KEY_PLAYPAUSE }, + { 0x33, KEY_FASTFORWARD }, + { 0x3c, KEY_STOP }, + { 0x36, KEY_RECORD }, + { 0x3f, KEY_EPG }, /* Labeled "?" */ +}; + +struct ir_scancode_table ir_codes_pinnacle_pctv_hd_table = { + .scan = ir_codes_pinnacle_pctv_hd, + .size = ARRAY_SIZE(ir_codes_pinnacle_pctv_hd), +}; +EXPORT_SYMBOL_GPL(ir_codes_pinnacle_pctv_hd_table); /* * Igor Kuznetsov @@ -2210,13 +2425,13 @@ EXPORT_SYMBOL_GPL(ir_codes_pinnacle_pctv_hd); * the button labels (several variants when appropriate) * helps to descide which keycodes to assign to the buttons. */ -IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_behold[] = { /* 0x1c 0x12 * * TV/FM POWER * * */ - [0x1c] = KEY_TUNER, /* XXX KEY_TV / KEY_RADIO */ - [0x12] = KEY_POWER, + { 0x1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */ + { 0x12, KEY_POWER }, /* 0x01 0x02 0x03 * * 1 2 3 * @@ -2227,28 +2442,28 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * 0x07 0x08 0x09 * * 7 8 9 * * */ - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, /* 0x0a 0x00 0x17 * * RECALL 0 MODE * * */ - [0x0a] = KEY_AGAIN, - [0x00] = KEY_0, - [0x17] = KEY_MODE, + { 0x0a, KEY_AGAIN }, + { 0x00, KEY_0 }, + { 0x17, KEY_MODE }, /* 0x14 0x10 * * ASPECT FULLSCREEN * * */ - [0x14] = KEY_SCREEN, - [0x10] = KEY_ZOOM, + { 0x14, KEY_SCREEN }, + { 0x10, KEY_ZOOM }, /* 0x0b * * Up * @@ -2259,17 +2474,17 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { * 0x015 * * Down * * */ - [0x0b] = KEY_CHANNELUP, - [0x18] = KEY_VOLUMEDOWN, - [0x16] = KEY_OK, /* XXX KEY_ENTER */ - [0x0c] = KEY_VOLUMEUP, - [0x15] = KEY_CHANNELDOWN, + { 0x0b, KEY_CHANNELUP }, + { 0x18, KEY_VOLUMEDOWN }, + { 0x16, KEY_OK }, /* XXX KEY_ENTER */ + { 0x0c, KEY_VOLUMEUP }, + { 0x15, KEY_CHANNELDOWN }, /* 0x11 0x0d * * MUTE INFO * * */ - [0x11] = KEY_MUTE, - [0x0d] = KEY_INFO, + { 0x11, KEY_MUTE }, + { 0x0d, KEY_INFO }, /* 0x0f 0x1b 0x1a * * RECORD PLAY/PAUSE STOP * @@ -2278,29 +2493,34 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { *TELETEXT AUDIO SOURCE * * RED YELLOW * * */ - [0x0f] = KEY_RECORD, - [0x1b] = KEY_PLAYPAUSE, - [0x1a] = KEY_STOP, - [0x0e] = KEY_TEXT, - [0x1f] = KEY_RED, /*XXX KEY_AUDIO */ - [0x1e] = KEY_YELLOW, /*XXX KEY_SOURCE */ + { 0x0f, KEY_RECORD }, + { 0x1b, KEY_PLAYPAUSE }, + { 0x1a, KEY_STOP }, + { 0x0e, KEY_TEXT }, + { 0x1f, KEY_RED }, /*XXX KEY_AUDIO */ + { 0x1e, KEY_YELLOW }, /*XXX KEY_SOURCE */ /* 0x1d 0x13 0x19 * * SLEEP PREVIEW DVB * * GREEN BLUE * * */ - [0x1d] = KEY_SLEEP, - [0x13] = KEY_GREEN, - [0x19] = KEY_BLUE, /* XXX KEY_SAT */ + { 0x1d, KEY_SLEEP }, + { 0x13, KEY_GREEN }, + { 0x19, KEY_BLUE }, /* XXX KEY_SAT */ /* 0x58 0x5c * * FREEZE SNAPSHOT * * */ - [0x58] = KEY_SLOW, - [0x5c] = KEY_CAMERA, + { 0x58, KEY_SLOW }, + { 0x5c, KEY_CAMERA }, + +}; +struct ir_scancode_table ir_codes_behold_table = { + .scan = ir_codes_behold, + .size = ARRAY_SIZE(ir_codes_behold), }; -EXPORT_SYMBOL_GPL(ir_codes_behold); +EXPORT_SYMBOL_GPL(ir_codes_behold_table); /* Beholder Intl. Ltd. 2008 * Dmitry Belimov d.belimov@google.com @@ -2310,16 +2530,16 @@ EXPORT_SYMBOL_GPL(ir_codes_behold); * the button labels (several variants when appropriate) * helps to descide which keycodes to assign to the buttons. */ -IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_behold_columbus[] = { /* 0x13 0x11 0x1C 0x12 * * Mute Source TV/FM Power * * */ - [0x13] = KEY_MUTE, - [0x11] = KEY_PROPS, - [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */ - [0x12] = KEY_POWER, + { 0x13, KEY_MUTE }, + { 0x11, KEY_PROPS }, + { 0x1C, KEY_TUNER }, /* KEY_TV/KEY_RADIO */ + { 0x12, KEY_POWER }, /* 0x01 0x02 0x03 0x0D * * 1 2 3 Stereo * @@ -2330,173 +2550,188 @@ IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { * 0x07 0x08 0x09 0x10 * * 7 8 9 Zoom * * */ - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x0D] = KEY_SETUP, /* Setup key */ - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x19] = KEY_CAMERA, /* Snapshot key */ - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - [0x10] = KEY_ZOOM, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x0D, KEY_SETUP }, /* Setup key */ + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x19, KEY_CAMERA }, /* Snapshot key */ + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x10, KEY_ZOOM }, /* 0x0A 0x00 0x0B 0x0C * * RECALL 0 ChannelUp VolumeUp * * */ - [0x0A] = KEY_AGAIN, - [0x00] = KEY_0, - [0x0B] = KEY_CHANNELUP, - [0x0C] = KEY_VOLUMEUP, + { 0x0A, KEY_AGAIN }, + { 0x00, KEY_0 }, + { 0x0B, KEY_CHANNELUP }, + { 0x0C, KEY_VOLUMEUP }, /* 0x1B 0x1D 0x15 0x18 * * Timeshift Record ChannelDown VolumeDown * * */ - [0x1B] = KEY_TIME, - [0x1D] = KEY_RECORD, - [0x15] = KEY_CHANNELDOWN, - [0x18] = KEY_VOLUMEDOWN, + { 0x1B, KEY_TIME }, + { 0x1D, KEY_RECORD }, + { 0x15, KEY_CHANNELDOWN }, + { 0x18, KEY_VOLUMEDOWN }, /* 0x0E 0x1E 0x0F 0x1A * * Stop Pause Previouse Next * * */ - [0x0E] = KEY_STOP, - [0x1E] = KEY_PAUSE, - [0x0F] = KEY_PREVIOUS, - [0x1A] = KEY_NEXT, + { 0x0E, KEY_STOP }, + { 0x1E, KEY_PAUSE }, + { 0x0F, KEY_PREVIOUS }, + { 0x1A, KEY_NEXT }, }; -EXPORT_SYMBOL_GPL(ir_codes_behold_columbus); + +struct ir_scancode_table ir_codes_behold_columbus_table = { + .scan = ir_codes_behold_columbus, + .size = ARRAY_SIZE(ir_codes_behold_columbus), +}; +EXPORT_SYMBOL_GPL(ir_codes_behold_columbus_table); /* * Remote control for the Genius TVGO A11MCE * Adrian Pardini */ -IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_genius_tvgo_a11mce[] = { /* Keys 0 to 9 */ - [0x48] = KEY_0, - [0x09] = KEY_1, - [0x1d] = KEY_2, - [0x1f] = KEY_3, - [0x19] = KEY_4, - [0x1b] = KEY_5, - [0x11] = KEY_6, - [0x17] = KEY_7, - [0x12] = KEY_8, - [0x16] = KEY_9, - - [0x54] = KEY_RECORD, /* recording */ - [0x06] = KEY_MUTE, /* mute */ - [0x10] = KEY_POWER, - [0x40] = KEY_LAST, /* recall */ - [0x4c] = KEY_CHANNELUP, /* channel / program + */ - [0x00] = KEY_CHANNELDOWN, /* channel / program - */ - [0x0d] = KEY_VOLUMEUP, - [0x15] = KEY_VOLUMEDOWN, - [0x4d] = KEY_OK, /* also labeled as Pause */ - [0x1c] = KEY_ZOOM, /* full screen and Stop*/ - [0x02] = KEY_MODE, /* AV Source or Rewind*/ - [0x04] = KEY_LIST, /* -/-- */ + { 0x48, KEY_0 }, + { 0x09, KEY_1 }, + { 0x1d, KEY_2 }, + { 0x1f, KEY_3 }, + { 0x19, KEY_4 }, + { 0x1b, KEY_5 }, + { 0x11, KEY_6 }, + { 0x17, KEY_7 }, + { 0x12, KEY_8 }, + { 0x16, KEY_9 }, + + { 0x54, KEY_RECORD }, /* recording */ + { 0x06, KEY_MUTE }, /* mute */ + { 0x10, KEY_POWER }, + { 0x40, KEY_LAST }, /* recall */ + { 0x4c, KEY_CHANNELUP }, /* channel / program + */ + { 0x00, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x0d, KEY_VOLUMEUP }, + { 0x15, KEY_VOLUMEDOWN }, + { 0x4d, KEY_OK }, /* also labeled as Pause */ + { 0x1c, KEY_ZOOM }, /* full screen and Stop*/ + { 0x02, KEY_MODE }, /* AV Source or Rewind*/ + { 0x04, KEY_LIST }, /* -/-- */ /* small arrows above numbers */ - [0x1a] = KEY_NEXT, /* also Fast Forward */ - [0x0e] = KEY_PREVIOUS, /* also Rewind */ + { 0x1a, KEY_NEXT }, /* also Fast Forward */ + { 0x0e, KEY_PREVIOUS }, /* also Rewind */ /* these are in a rather non standard layout and have an alternate name written */ - [0x1e] = KEY_UP, /* Video Setting */ - [0x0a] = KEY_DOWN, /* Video Default */ - [0x05] = KEY_CAMERA, /* Snapshot */ - [0x0c] = KEY_RIGHT, /* Hide Panel */ + { 0x1e, KEY_UP }, /* Video Setting */ + { 0x0a, KEY_DOWN }, /* Video Default */ + { 0x05, KEY_CAMERA }, /* Snapshot */ + { 0x0c, KEY_RIGHT }, /* Hide Panel */ /* Four buttons without label */ - [0x49] = KEY_RED, - [0x0b] = KEY_GREEN, - [0x13] = KEY_YELLOW, - [0x50] = KEY_BLUE, + { 0x49, KEY_RED }, + { 0x0b, KEY_GREEN }, + { 0x13, KEY_YELLOW }, + { 0x50, KEY_BLUE }, }; -EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce); + +struct ir_scancode_table ir_codes_genius_tvgo_a11mce_table = { + .scan = ir_codes_genius_tvgo_a11mce, + .size = ARRAY_SIZE(ir_codes_genius_tvgo_a11mce), +}; +EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce_table); /* * Remote control for Powercolor Real Angel 330 * Daniel Fraga */ -IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = { - [0x38] = KEY_SWITCHVIDEOMODE, /* switch inputs */ - [0x0c] = KEY_MEDIA, /* Turn ON/OFF App */ - [0x00] = KEY_0, - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - [0x0a] = KEY_DIGITS, /* single, double, tripple digit */ - [0x29] = KEY_PREVIOUS, /* previous channel */ - [0x12] = KEY_BRIGHTNESSUP, - [0x13] = KEY_BRIGHTNESSDOWN, - [0x2b] = KEY_MODE, /* stereo/mono */ - [0x2c] = KEY_TEXT, /* teletext */ - [0x20] = KEY_CHANNELUP, /* channel up */ - [0x21] = KEY_CHANNELDOWN, /* channel down */ - [0x10] = KEY_VOLUMEUP, /* volume up */ - [0x11] = KEY_VOLUMEDOWN, /* volume down */ - [0x0d] = KEY_MUTE, - [0x1f] = KEY_RECORD, - [0x17] = KEY_PLAY, - [0x16] = KEY_PAUSE, - [0x0b] = KEY_STOP, - [0x27] = KEY_FASTFORWARD, - [0x26] = KEY_REWIND, - [0x1e] = KEY_SEARCH, /* autoscan */ - [0x0e] = KEY_CAMERA, /* snapshot */ - [0x2d] = KEY_SETUP, - [0x0f] = KEY_SCREEN, /* full screen */ - [0x14] = KEY_RADIO, /* FM radio */ - [0x25] = KEY_POWER, /* power */ -}; -EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel); +static struct ir_scancode ir_codes_powercolor_real_angel[] = { + { 0x38, KEY_SWITCHVIDEOMODE }, /* switch inputs */ + { 0x0c, KEY_MEDIA }, /* Turn ON/OFF App */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x0a, KEY_DIGITS }, /* single, double, tripple digit */ + { 0x29, KEY_PREVIOUS }, /* previous channel */ + { 0x12, KEY_BRIGHTNESSUP }, + { 0x13, KEY_BRIGHTNESSDOWN }, + { 0x2b, KEY_MODE }, /* stereo/mono */ + { 0x2c, KEY_TEXT }, /* teletext */ + { 0x20, KEY_CHANNELUP }, /* channel up */ + { 0x21, KEY_CHANNELDOWN }, /* channel down */ + { 0x10, KEY_VOLUMEUP }, /* volume up */ + { 0x11, KEY_VOLUMEDOWN }, /* volume down */ + { 0x0d, KEY_MUTE }, + { 0x1f, KEY_RECORD }, + { 0x17, KEY_PLAY }, + { 0x16, KEY_PAUSE }, + { 0x0b, KEY_STOP }, + { 0x27, KEY_FASTFORWARD }, + { 0x26, KEY_REWIND }, + { 0x1e, KEY_SEARCH }, /* autoscan */ + { 0x0e, KEY_CAMERA }, /* snapshot */ + { 0x2d, KEY_SETUP }, + { 0x0f, KEY_SCREEN }, /* full screen */ + { 0x14, KEY_RADIO }, /* FM radio */ + { 0x25, KEY_POWER }, /* power */ +}; + +struct ir_scancode_table ir_codes_powercolor_real_angel_table = { + .scan = ir_codes_powercolor_real_angel, + .size = ARRAY_SIZE(ir_codes_powercolor_real_angel), +}; +EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel_table); /* Kworld Plus TV Analog Lite PCI IR Mauro Carvalho Chehab */ -IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE] = { - [0x0c] = KEY_PROG1, /* Kworld key */ - [0x16] = KEY_CLOSECD, /* -> ) */ - [0x1d] = KEY_POWER2, - - [0x00] = KEY_1, - [0x01] = KEY_2, - [0x02] = KEY_3, /* Two keys have the same code: 3 and left */ - [0x03] = KEY_4, /* Two keys have the same code: 3 and right */ - [0x04] = KEY_5, - [0x05] = KEY_6, - [0x06] = KEY_7, - [0x07] = KEY_8, - [0x08] = KEY_9, - [0x0a] = KEY_0, - - [0x09] = KEY_AGAIN, - [0x14] = KEY_MUTE, - - [0x20] = KEY_UP, - [0x21] = KEY_DOWN, - [0x0b] = KEY_ENTER, - - [0x10] = KEY_CHANNELUP, - [0x11] = KEY_CHANNELDOWN, +static struct ir_scancode ir_codes_kworld_plus_tv_analog[] = { + { 0x0c, KEY_PROG1 }, /* Kworld key */ + { 0x16, KEY_CLOSECD }, /* -> ) */ + { 0x1d, KEY_POWER2 }, + + { 0x00, KEY_1 }, + { 0x01, KEY_2 }, + { 0x02, KEY_3 }, /* Two keys have the same code: 3 and left */ + { 0x03, KEY_4 }, /* Two keys have the same code: 3 and right */ + { 0x04, KEY_5 }, + { 0x05, KEY_6 }, + { 0x06, KEY_7 }, + { 0x07, KEY_8 }, + { 0x08, KEY_9 }, + { 0x0a, KEY_0 }, + + { 0x09, KEY_AGAIN }, + { 0x14, KEY_MUTE }, + + { 0x20, KEY_UP }, + { 0x21, KEY_DOWN }, + { 0x0b, KEY_ENTER }, + + { 0x10, KEY_CHANNELUP }, + { 0x11, KEY_CHANNELDOWN }, /* Couldn't map key left/key right since those conflict with '3' and '4' scancodes I dunno what the original driver does */ - [0x13] = KEY_VOLUMEUP, - [0x12] = KEY_VOLUMEDOWN, + { 0x13, KEY_VOLUMEUP }, + { 0x12, KEY_VOLUMEDOWN }, /* The lower part of the IR There are several duplicated keycodes there. @@ -2507,105 +2742,117 @@ IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE] = { Also, it is not related to the time between keyup and keydown. */ - [0x19] = KEY_TIME, /* Timeshift */ - [0x1a] = KEY_STOP, - [0x1b] = KEY_RECORD, + { 0x19, KEY_TIME}, /* Timeshift */ + { 0x1a, KEY_STOP}, + { 0x1b, KEY_RECORD}, - [0x22] = KEY_TEXT, + { 0x22, KEY_TEXT}, - [0x15] = KEY_AUDIO, /* ((*)) */ - [0x0f] = KEY_ZOOM, - [0x1c] = KEY_CAMERA, /* snapshot */ + { 0x15, KEY_AUDIO}, /* ((*)) */ + { 0x0f, KEY_ZOOM}, + { 0x1c, KEY_CAMERA}, /* snapshot */ - [0x18] = KEY_RED, /* B */ - [0x23] = KEY_GREEN, /* C */ + { 0x18, KEY_RED}, /* B */ + { 0x23, KEY_GREEN}, /* C */ }; -EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog); +struct ir_scancode_table ir_codes_kworld_plus_tv_analog_table = { + .scan = ir_codes_kworld_plus_tv_analog, + .size = ARRAY_SIZE(ir_codes_kworld_plus_tv_analog), +}; +EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog_table); /* Kaiomy TVnPC U2 Mauro Carvalho Chehab */ IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE] = { - [0x43] = KEY_POWER2, - [0x01] = KEY_LIST, - [0x0b] = KEY_ZOOM, - [0x03] = KEY_POWER, + { 0x43, KEY_POWER2}, + { 0x01, KEY_LIST}, + { 0x0b, KEY_ZOOM}, + { 0x03, KEY_POWER}, - [0x04] = KEY_1, - [0x08] = KEY_2, - [0x02] = KEY_3, + { 0x04, KEY_1}, + { 0x08, KEY_2}, + { 0x02, KEY_3}, - [0x0f] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, + { 0x0f, KEY_4}, + { 0x05, KEY_5}, + { 0x06, KEY_6}, - [0x0c] = KEY_7, - [0x0d] = KEY_8, - [0x0a] = KEY_9, + { 0x0c, KEY_7}, + { 0x0d, KEY_8}, + { 0x0a, KEY_9}, - [0x11] = KEY_0, + { 0x11, KEY_0}, - [0x09] = KEY_CHANNELUP, - [0x07] = KEY_CHANNELDOWN, + { 0x09, KEY_CHANNELUP}, + { 0x07, KEY_CHANNELDOWN}, - [0x0e] = KEY_VOLUMEUP, - [0x13] = KEY_VOLUMEDOWN, + { 0x0e, KEY_VOLUMEUP}, + { 0x13, KEY_VOLUMEDOWN}, - [0x10] = KEY_HOME, - [0x12] = KEY_ENTER, + { 0x10, KEY_HOME}, + { 0x12, KEY_ENTER}, - [0x14] = KEY_RECORD, - [0x15] = KEY_STOP, - [0x16] = KEY_PLAY, - [0x17] = KEY_MUTE, + { 0x14, KEY_RECORD}, + { 0x15, KEY_STOP}, + { 0x16, KEY_PLAY}, + { 0x17, KEY_MUTE}, - [0x18] = KEY_UP, - [0x19] = KEY_DOWN, - [0x1a] = KEY_LEFT, - [0x1b] = KEY_RIGHT, + { 0x18, KEY_UP}, + { 0x19, KEY_DOWN}, + { 0x1a, KEY_LEFT}, + { 0x1b, KEY_RIGHT}, - [0x1c] = KEY_RED, - [0x1d] = KEY_GREEN, - [0x1e] = KEY_YELLOW, - [0x1f] = KEY_BLUE, + { 0x1c, KEY_RED}, + { 0x1d, KEY_GREEN}, + { 0x1e, KEY_YELLOW}, + { 0x1f, KEY_BLUE}, +}; +struct ir_scancode_table ir_codes_kaiomy_table = { + .scan = ir_codes_kaiomy, + .size = ARRAY_SIZE(ir_codes_kaiomy), }; EXPORT_SYMBOL_GPL(ir_codes_kaiomy); IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = { - [0x20] = KEY_LIST, - [0x00] = KEY_POWER, - [0x28] = KEY_1, - [0x18] = KEY_2, - [0x38] = KEY_3, - [0x24] = KEY_4, - [0x14] = KEY_5, - [0x34] = KEY_6, - [0x2c] = KEY_7, - [0x1c] = KEY_8, - [0x3c] = KEY_9, - [0x12] = KEY_SUBTITLE, - [0x22] = KEY_0, - [0x32] = KEY_REWIND, - [0x3a] = KEY_SHUFFLE, - [0x02] = KEY_PRINT, - [0x11] = KEY_CHANNELDOWN, - [0x31] = KEY_CHANNELUP, - [0x0c] = KEY_ZOOM, - [0x1e] = KEY_VOLUMEDOWN, - [0x3e] = KEY_VOLUMEUP, - [0x0a] = KEY_MUTE, - [0x04] = KEY_AUDIO, - [0x26] = KEY_RECORD, - [0x06] = KEY_PLAY, - [0x36] = KEY_STOP, - [0x16] = KEY_PAUSE, - [0x2e] = KEY_REWIND, - [0x0e] = KEY_FASTFORWARD, - [0x30] = KEY_TEXT, - [0x21] = KEY_GREEN, - [0x01] = KEY_BLUE, - [0x08] = KEY_EPG, - [0x2a] = KEY_MENU, + { 0x20, KEY_LIST}, + { 0x00, KEY_POWER}, + { 0x28, KEY_1}, + { 0x18, KEY_2}, + { 0x38, KEY_3}, + { 0x24, KEY_4}, + { 0x14, KEY_5}, + { 0x34, KEY_6}, + { 0x2c, KEY_7}, + { 0x1c, KEY_8}, + { 0x3c, KEY_9}, + { 0x12, KEY_SUBTITLE}, + { 0x22, KEY_0}, + { 0x32, KEY_REWIND}, + { 0x3a, KEY_SHUFFLE}, + { 0x02, KEY_PRINT}, + { 0x11, KEY_CHANNELDOWN}, + { 0x31, KEY_CHANNELUP}, + { 0x0c, KEY_ZOOM}, + { 0x1e, KEY_VOLUMEDOWN}, + { 0x3e, KEY_VOLUMEUP}, + { 0x0a, KEY_MUTE}, + { 0x04, KEY_AUDIO}, + { 0x26, KEY_RECORD}, + { 0x06, KEY_PLAY}, + { 0x36, KEY_STOP}, + { 0x16, KEY_PAUSE}, + { 0x2e, KEY_REWIND}, + { 0x0e, KEY_FASTFORWARD}, + { 0x30, KEY_TEXT}, + { 0x21, KEY_GREEN}, + { 0x01, KEY_BLUE}, + { 0x08, KEY_EPG}, + { 0x2a, KEY_MENU}, +}; +struct ir_scancode_table ir_codes_avermedia_a16d_table = { + .scan = ir_codes_avermedia_a16d, + .size = ARRAY_SIZE(ir_codes_avermedia_a16d), }; EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d); @@ -2613,113 +2860,125 @@ EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d); Mauro Carvalho Chehab */ IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = { - [0x10] = KEY_POWER2, - [0x06] = KEY_MUTE, - - [0x09] = KEY_1, - [0x1d] = KEY_2, - [0x1f] = KEY_3, - [0x19] = KEY_4, - [0x1b] = KEY_5, - [0x11] = KEY_6, - [0x17] = KEY_7, - [0x12] = KEY_8, - [0x16] = KEY_9, - [0x48] = KEY_0, - - [0x04] = KEY_LIST, /* -/-- */ - [0x40] = KEY_LAST, /* recall */ - - [0x02] = KEY_MODE, /* TV/AV */ - [0x05] = KEY_CAMERA, /* SNAPSHOT */ - - [0x4c] = KEY_CHANNELUP, /* UP */ - [0x00] = KEY_CHANNELDOWN, /* DOWN */ - [0x0d] = KEY_VOLUMEUP, /* RIGHT */ - [0x15] = KEY_VOLUMEDOWN, /* LEFT */ - [0x49] = KEY_ENTER, /* OK */ - - [0x54] = KEY_RECORD, - [0x4d] = KEY_PLAY, /* pause */ - - [0x1e] = KEY_MENU, /* video setting */ - [0x0e] = KEY_RIGHT, /* <- */ - [0x1a] = KEY_LEFT, /* -> */ - - [0x0a] = KEY_CLEAR, /* video default */ - [0x0c] = KEY_ZOOM, /* hide pannel */ - [0x47] = KEY_SLEEP, /* shutdown */ + { 0x10, KEY_POWER2}, + { 0x06, KEY_MUTE}, + + { 0x09, KEY_1}, + { 0x1d, KEY_2}, + { 0x1f, KEY_3}, + { 0x19, KEY_4}, + { 0x1b, KEY_5}, + { 0x11, KEY_6}, + { 0x17, KEY_7}, + { 0x12, KEY_8}, + { 0x16, KEY_9}, + { 0x48, KEY_0}, + + { 0x04, KEY_LIST}, /* -/-- */ + { 0x40, KEY_LAST}, /* recall */ + + { 0x02, KEY_MODE}, /* TV/AV */ + { 0x05, KEY_CAMERA}, /* SNAPSHOT */ + + { 0x4c, KEY_CHANNELUP}, /* UP */ + { 0x00, KEY_CHANNELDOWN}, /* DOWN */ + { 0x0d, KEY_VOLUMEUP}, /* RIGHT */ + { 0x15, KEY_VOLUMEDOWN}, /* LEFT */ + { 0x49, KEY_ENTER}, /* OK */ + + { 0x54, KEY_RECORD}, + { 0x4d, KEY_PLAY}, /* pause */ + + { 0x1e, KEY_MENU}, /* video setting */ + { 0x0e, KEY_RIGHT}, /* <- */ + { 0x1a, KEY_LEFT}, /* -> */ + + { 0x0a, KEY_CLEAR}, /* video default */ + { 0x0c, KEY_ZOOM}, /* hide pannel */ + { 0x47, KEY_SLEEP}, /* shutdown */ +}; +struct ir_scancode_table ir_codes_encore_enltv_fm53_table = { + .scan = ir_codes_encore_enltv_fm53, + .size = ARRAY_SIZE(ir_codes_encore_enltv_fm53), }; EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53); /* Zogis Real Audio 220 - 32 keys IR */ IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = { - [0x1c] = KEY_RADIO, - [0x12] = KEY_POWER2, - - [0x01] = KEY_1, - [0x02] = KEY_2, - [0x03] = KEY_3, - [0x04] = KEY_4, - [0x05] = KEY_5, - [0x06] = KEY_6, - [0x07] = KEY_7, - [0x08] = KEY_8, - [0x09] = KEY_9, - [0x00] = KEY_0, - - [0x0c] = KEY_VOLUMEUP, - [0x18] = KEY_VOLUMEDOWN, - [0x0b] = KEY_CHANNELUP, - [0x15] = KEY_CHANNELDOWN, - [0x16] = KEY_ENTER, - - [0x11] = KEY_LIST, /* Source */ - [0x0d] = KEY_AUDIO, /* stereo */ - - [0x0f] = KEY_PREVIOUS, /* Prev */ - [0x1b] = KEY_TIME, /* Timeshift */ - [0x1a] = KEY_NEXT, /* Next */ - - [0x0e] = KEY_STOP, - [0x1f] = KEY_PLAY, - [0x1e] = KEY_PLAYPAUSE, /* Pause */ - - [0x1d] = KEY_RECORD, - [0x13] = KEY_MUTE, - [0x19] = KEY_CAMERA, /* Snapshot */ + { 0x1c, KEY_RADIO}, + { 0x12, KEY_POWER2}, + + { 0x01, KEY_1}, + { 0x02, KEY_2}, + { 0x03, KEY_3}, + { 0x04, KEY_4}, + { 0x05, KEY_5}, + { 0x06, KEY_6}, + { 0x07, KEY_7}, + { 0x08, KEY_8}, + { 0x09, KEY_9}, + { 0x00, KEY_0}, + + { 0x0c, KEY_VOLUMEUP}, + { 0x18, KEY_VOLUMEDOWN}, + { 0x0b, KEY_CHANNELUP}, + { 0x15, KEY_CHANNELDOWN}, + { 0x16, KEY_ENTER}, + + { 0x11, KEY_LIST}, /* Source */ + { 0x0d, KEY_AUDIO}, /* stereo */ + + { 0x0f, KEY_PREVIOUS}, /* Prev */ + { 0x1b, KEY_TIME}, /* Timeshift */ + { 0x1a, KEY_NEXT}, /* Next */ + + { 0x0e, KEY_STOP}, + { 0x1f, KEY_PLAY}, + { 0x1e, KEY_PLAYPAUSE}, /* Pause */ + + { 0x1d, KEY_RECORD}, + { 0x13, KEY_MUTE}, + { 0x19, KEY_CAMERA}, /* Snapshot */ }; +struct ir_scancode_table ir_codes_real_audio_220_32_keys_table = { + .scan = ir_codes_real_audio_220_32_keys, + .size = ARRAY_SIZE(ir_codes_real_audio_220_32_keys), +}; EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys); /* ATI TV Wonder HD 600 USB Devin Heitmueller */ IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE] = { - [0x00] = KEY_RECORD, /* Row 1 */ - [0x01] = KEY_PLAYPAUSE, - [0x02] = KEY_STOP, - [0x03] = KEY_POWER, - [0x04] = KEY_PREVIOUS, /* Row 2 */ - [0x05] = KEY_REWIND, - [0x06] = KEY_FORWARD, - [0x07] = KEY_NEXT, - [0x08] = KEY_EPG, /* Row 3 */ - [0x09] = KEY_HOME, - [0x0a] = KEY_MENU, - [0x0b] = KEY_CHANNELUP, - [0x0c] = KEY_BACK, /* Row 4 */ - [0x0d] = KEY_UP, - [0x0e] = KEY_INFO, - [0x0f] = KEY_CHANNELDOWN, - [0x10] = KEY_LEFT, /* Row 5 */ - [0x11] = KEY_SELECT, - [0x12] = KEY_RIGHT, - [0x13] = KEY_VOLUMEUP, - [0x14] = KEY_LAST, /* Row 6 */ - [0x15] = KEY_DOWN, - [0x16] = KEY_MUTE, - [0x17] = KEY_VOLUMEDOWN, + { 0x00, KEY_RECORD}, /* Row 1 */ + { 0x01, KEY_PLAYPAUSE}, + { 0x02, KEY_STOP}, + { 0x03, KEY_POWER}, + { 0x04, KEY_PREVIOUS}, /* Row 2 */ + { 0x05, KEY_REWIND}, + { 0x06, KEY_FORWARD}, + { 0x07, KEY_NEXT}, + { 0x08, KEY_EPG}, /* Row 3 */ + { 0x09, KEY_HOME}, + { 0x0a, KEY_MENU}, + { 0x0b, KEY_CHANNELUP}, + { 0x0c, KEY_BACK}, /* Row 4 */ + { 0x0d, KEY_UP}, + { 0x0e, KEY_INFO}, + { 0x0f, KEY_CHANNELDOWN}, + { 0x10, KEY_LEFT}, /* Row 5 */ + { 0x11, KEY_SELECT}, + { 0x12, KEY_RIGHT}, + { 0x13, KEY_VOLUMEUP}, + { 0x14, KEY_LAST}, /* Row 6 */ + { 0x15, KEY_DOWN}, + { 0x16, KEY_MUTE}, + { 0x17, KEY_VOLUMEDOWN}, +}; +struct ir_scancode_table ir_codes_ati_tv_wonder_hd_600_table = { + .scan = ir_codes_ati_tv_wonder_hd_600, + .size = ARRAY_SIZE(ir_codes_ati_tv_wonder_hd_600), }; EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600); @@ -2727,37 +2986,41 @@ EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600); Igor M. Liplianin */ IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { - [0x0a] = KEY_POWER2, /* power */ - [0x0c] = KEY_MUTE, /* mute */ - [0x11] = KEY_1, - [0x12] = KEY_2, - [0x13] = KEY_3, - [0x14] = KEY_4, - [0x15] = KEY_5, - [0x16] = KEY_6, - [0x17] = KEY_7, - [0x18] = KEY_8, - [0x19] = KEY_9, - [0x10] = KEY_0, - [0x1c] = KEY_CHANNELUP, /* ch+ */ - [0x0f] = KEY_CHANNELDOWN, /* ch- */ - [0x1a] = KEY_VOLUMEUP, /* vol+ */ - [0x0e] = KEY_VOLUMEDOWN, /* vol- */ - [0x04] = KEY_RECORD, /* rec */ - [0x09] = KEY_CHANNEL, /* fav */ - [0x08] = KEY_BACKSPACE, /* rewind */ - [0x07] = KEY_FASTFORWARD, /* fast */ - [0x0b] = KEY_PAUSE, /* pause */ - [0x02] = KEY_ESC, /* cancel */ - [0x03] = KEY_TAB, /* tab */ - [0x00] = KEY_UP, /* up */ - [0x1f] = KEY_ENTER, /* ok */ - [0x01] = KEY_DOWN, /* down */ - [0x05] = KEY_RECORD, /* cap */ - [0x06] = KEY_STOP, /* stop */ - [0x40] = KEY_ZOOM, /* full */ - [0x1e] = KEY_TV, /* tvmode */ - [0x1b] = KEY_B, /* recall */ + { 0x0a, KEY_POWER2}, /* power */ + { 0x0c, KEY_MUTE}, /* mute */ + { 0x11, KEY_1}, + { 0x12, KEY_2}, + { 0x13, KEY_3}, + { 0x14, KEY_4}, + { 0x15, KEY_5}, + { 0x16, KEY_6}, + { 0x17, KEY_7}, + { 0x18, KEY_8}, + { 0x19, KEY_9}, + { 0x10, KEY_0}, + { 0x1c, KEY_CHANNELUP}, /* ch+ */ + { 0x0f, KEY_CHANNELDOWN}, /* ch- */ + { 0x1a, KEY_VOLUMEUP}, /* vol+ */ + { 0x0e, KEY_VOLUMEDOWN}, /* vol- */ + { 0x04, KEY_RECORD}, /* rec */ + { 0x09, KEY_CHANNEL}, /* fav */ + { 0x08, KEY_BACKSPACE}, /* rewind */ + { 0x07, KEY_FASTFORWARD}, /* fast */ + { 0x0b, KEY_PAUSE}, /* pause */ + { 0x02, KEY_ESC}, /* cancel */ + { 0x03, KEY_TAB}, /* tab */ + { 0x00, KEY_UP}, /* up */ + { 0x1f, KEY_ENTER}, /* ok */ + { 0x01, KEY_DOWN}, /* down */ + { 0x05, KEY_RECORD}, /* cap */ + { 0x06, KEY_STOP}, /* stop */ + { 0x40, KEY_ZOOM}, /* full */ + { 0x1e, KEY_TV}, /* tvmode */ + { 0x1b, KEY_B}, /* recall */ +}; +struct ir_scancode_table ir_codes_dm1105_nec_table = { + .scan = ir_codes_dm1105_nec, + .size = ARRAY_SIZE(ir_codes_dm1105_nec), }; EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec); @@ -2766,53 +3029,57 @@ EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec); Devin Heitmueller */ IR_KEYTAB_TYPE ir_codes_terratec_cinergy_xs[IR_KEYTAB_SIZE] = { - [0x41] = KEY_HOME, - [0x01] = KEY_POWER, - [0x42] = KEY_MENU, - [0x02] = KEY_1, - [0x03] = KEY_2, - [0x04] = KEY_3, - [0x43] = KEY_SUBTITLE, - [0x05] = KEY_4, - [0x06] = KEY_5, - [0x07] = KEY_6, - [0x44] = KEY_TEXT, - [0x08] = KEY_7, - [0x09] = KEY_8, - [0x0a] = KEY_9, - [0x45] = KEY_DELETE, - [0x0b] = KEY_TUNER, - [0x0c] = KEY_0, - [0x0d] = KEY_MODE, - [0x46] = KEY_TV, - [0x47] = KEY_DVD, - [0x49] = KEY_VIDEO, - [0x4b] = KEY_AUX, - [0x10] = KEY_UP, - [0x11] = KEY_LEFT, - [0x12] = KEY_OK, - [0x13] = KEY_RIGHT, - [0x14] = KEY_DOWN, - [0x0f] = KEY_EPG, - [0x16] = KEY_INFO, - [0x4d] = KEY_BACKSPACE, - [0x1c] = KEY_VOLUMEUP, - [0x4c] = KEY_PLAY, - [0x1b] = KEY_CHANNELUP, - [0x1e] = KEY_VOLUMEDOWN, - [0x1d] = KEY_MUTE, - [0x1f] = KEY_CHANNELDOWN, - [0x17] = KEY_RED, - [0x18] = KEY_GREEN, - [0x19] = KEY_YELLOW, - [0x1a] = KEY_BLUE, - [0x58] = KEY_RECORD, - [0x48] = KEY_STOP, - [0x40] = KEY_PAUSE, - [0x54] = KEY_LAST, - [0x4e] = KEY_REWIND, - [0x4f] = KEY_FASTFORWARD, - [0x5c] = KEY_NEXT, + { 0x41, KEY_HOME}, + { 0x01, KEY_POWER}, + { 0x42, KEY_MENU}, + { 0x02, KEY_1}, + { 0x03, KEY_2}, + { 0x04, KEY_3}, + { 0x43, KEY_SUBTITLE}, + { 0x05, KEY_4}, + { 0x06, KEY_5}, + { 0x07, KEY_6}, + { 0x44, KEY_TEXT}, + { 0x08, KEY_7}, + { 0x09, KEY_8}, + { 0x0a, KEY_9}, + { 0x45, KEY_DELETE}, + { 0x0b, KEY_TUNER}, + { 0x0c, KEY_0}, + { 0x0d, KEY_MODE}, + { 0x46, KEY_TV}, + { 0x47, KEY_DVD}, + { 0x49, KEY_VIDEO}, + { 0x4b, KEY_AUX}, + { 0x10, KEY_UP}, + { 0x11, KEY_LEFT}, + { 0x12, KEY_OK}, + { 0x13, KEY_RIGHT}, + { 0x14, KEY_DOWN}, + { 0x0f, KEY_EPG}, + { 0x16, KEY_INFO}, + { 0x4d, KEY_BACKSPACE}, + { 0x1c, KEY_VOLUMEUP}, + { 0x4c, KEY_PLAY}, + { 0x1b, KEY_CHANNELUP}, + { 0x1e, KEY_VOLUMEDOWN}, + { 0x1d, KEY_MUTE}, + { 0x1f, KEY_CHANNELDOWN}, + { 0x17, KEY_RED}, + { 0x18, KEY_GREEN}, + { 0x19, KEY_YELLOW}, + { 0x1a, KEY_BLUE}, + { 0x58, KEY_RECORD}, + { 0x48, KEY_STOP}, + { 0x40, KEY_PAUSE}, + { 0x54, KEY_LAST}, + { 0x4e, KEY_REWIND}, + { 0x4f, KEY_FASTFORWARD}, + { 0x5c, KEY_NEXT}, +}; +struct ir_scancode_table ir_codes_terratec_cinergy_xs_table = { + .scan = ir_codes_terratec_cinergy_xs, + .size = ARRAY_SIZE(ir_codes_terratec_cinergy_xs), }; EXPORT_SYMBOL_GPL(ir_codes_terratec_cinergy_xs); @@ -2820,70 +3087,78 @@ EXPORT_SYMBOL_GPL(ir_codes_terratec_cinergy_xs); Devin Heitmueller */ IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE] = { - [0x12] = KEY_POWER, - [0x02] = KEY_MODE, /* TV */ - [0x14] = KEY_MUTE, - [0x1a] = KEY_CHANNELUP, - [0x16] = KEY_TV2, /* PIP */ - [0x1d] = KEY_VOLUMEUP, - [0x05] = KEY_CHANNELDOWN, - [0x0f] = KEY_PLAYPAUSE, - [0x19] = KEY_VOLUMEDOWN, - [0x1c] = KEY_REWIND, - [0x0d] = KEY_RECORD, - [0x18] = KEY_FORWARD, - [0x1e] = KEY_PREVIOUS, - [0x1b] = KEY_STOP, - [0x1f] = KEY_NEXT, - [0x13] = KEY_CAMERA, + { 0x12, KEY_POWER}, + { 0x02, KEY_MODE}, /* TV */ + { 0x14, KEY_MUTE}, + { 0x1a, KEY_CHANNELUP}, + { 0x16, KEY_TV2}, /* PIP */ + { 0x1d, KEY_VOLUMEUP}, + { 0x05, KEY_CHANNELDOWN}, + { 0x0f, KEY_PLAYPAUSE}, + { 0x19, KEY_VOLUMEDOWN}, + { 0x1c, KEY_REWIND}, + { 0x0d, KEY_RECORD}, + { 0x18, KEY_FORWARD}, + { 0x1e, KEY_PREVIOUS}, + { 0x1b, KEY_STOP}, + { 0x1f, KEY_NEXT}, + { 0x13, KEY_CAMERA}, +}; +struct ir_scancode_table ir_codes_evga_indtube_table = { + .scan = ir_codes_evga_indtube, + .size = ARRAY_SIZE(ir_codes_evga_indtube), }; EXPORT_SYMBOL_GPL(ir_codes_evga_indtube); IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = { - [0x00] = KEY_TV, - [0x01] = KEY_DVD, - [0x04] = KEY_RECORD, - [0x05] = KEY_VIDEO, /* TV/Video */ - [0x07] = KEY_STOP, - [0x08] = KEY_PLAYPAUSE, - [0x0a] = KEY_REWIND, - [0x0f] = KEY_FASTFORWARD, - [0x10] = KEY_CHANNELUP, - [0x12] = KEY_VOLUMEUP, - [0x13] = KEY_CHANNELDOWN, - [0x14] = KEY_MUTE, - [0x15] = KEY_VOLUMEDOWN, - [0x16] = KEY_1, - [0x17] = KEY_2, - [0x18] = KEY_3, - [0x19] = KEY_4, - [0x1a] = KEY_5, - [0x1b] = KEY_6, - [0x1c] = KEY_7, - [0x1d] = KEY_8, - [0x1e] = KEY_9, - [0x1f] = KEY_0, - [0x21] = KEY_SLEEP, - [0x24] = KEY_ZOOM, - [0x25] = KEY_LAST, /* Recall */ - [0x26] = KEY_SUBTITLE, /* CC */ - [0x27] = KEY_LANGUAGE, /* MTS */ - [0x29] = KEY_CHANNEL, /* SURF */ - [0x2b] = KEY_A, - [0x2c] = KEY_B, - [0x2f] = KEY_CAMERA, /* Snapshot */ - [0x23] = KEY_RADIO, - [0x02] = KEY_PREVIOUSSONG, - [0x06] = KEY_NEXTSONG, - [0x03] = KEY_EPG, - [0x09] = KEY_SETUP, - [0x22] = KEY_BACKSPACE, - [0x0c] = KEY_UP, - [0x0e] = KEY_DOWN, - [0x0b] = KEY_LEFT, - [0x0d] = KEY_RIGHT, - [0x11] = KEY_ENTER, - [0x20] = KEY_TEXT, + { 0x00, KEY_TV}, + { 0x01, KEY_DVD}, + { 0x04, KEY_RECORD}, + { 0x05, KEY_VIDEO}, /* TV/Video */ + { 0x07, KEY_STOP}, + { 0x08, KEY_PLAYPAUSE}, + { 0x0a, KEY_REWIND}, + { 0x0f, KEY_FASTFORWARD}, + { 0x10, KEY_CHANNELUP}, + { 0x12, KEY_VOLUMEUP}, + { 0x13, KEY_CHANNELDOWN}, + { 0x14, KEY_MUTE}, + { 0x15, KEY_VOLUMEDOWN}, + { 0x16, KEY_1}, + { 0x17, KEY_2}, + { 0x18, KEY_3}, + { 0x19, KEY_4}, + { 0x1a, KEY_5}, + { 0x1b, KEY_6}, + { 0x1c, KEY_7}, + { 0x1d, KEY_8}, + { 0x1e, KEY_9}, + { 0x1f, KEY_0}, + { 0x21, KEY_SLEEP}, + { 0x24, KEY_ZOOM}, + { 0x25, KEY_LAST}, /* Recall */ + { 0x26, KEY_SUBTITLE}, /* CC */ + { 0x27, KEY_LANGUAGE}, /* MTS */ + { 0x29, KEY_CHANNEL}, /* SURF */ + { 0x2b, KEY_A}, + { 0x2c, KEY_B}, + { 0x2f, KEY_CAMERA}, /* Snapshot */ + { 0x23, KEY_RADIO}, + { 0x02, KEY_PREVIOUSSONG}, + { 0x06, KEY_NEXTSONG}, + { 0x03, KEY_EPG}, + { 0x09, KEY_SETUP}, + { 0x22, KEY_BACKSPACE}, + { 0x0c, KEY_UP}, + { 0x0e, KEY_DOWN}, + { 0x0b, KEY_LEFT}, + { 0x0d, KEY_RIGHT}, + { 0x11, KEY_ENTER}, + { 0x20, KEY_TEXT}, +}; +struct ir_scancode_table ir_codes_videomate_s350_table = { + .scan = ir_codes_videomate_s350, + .size = ARRAY_SIZE(ir_codes_videomate_s350), }; EXPORT_SYMBOL_GPL(ir_codes_videomate_s350); @@ -2892,41 +3167,45 @@ EXPORT_SYMBOL_GPL(ir_codes_videomate_s350); Shine Liu */ IR_KEYTAB_TYPE ir_codes_gadmei_rm008z[IR_KEYTAB_SIZE] = { - [0x14] = KEY_POWER2, /* POWER OFF */ - [0x0c] = KEY_MUTE, /* MUTE */ - - [0x18] = KEY_TV, /* TV */ - [0x0e] = KEY_VIDEO, /* AV */ - [0x0b] = KEY_AUDIO, /* SV */ - [0x0f] = KEY_RADIO, /* FM */ - - [0x00] = KEY_1, - [0x01] = KEY_2, - [0x02] = KEY_3, - [0x03] = KEY_4, - [0x04] = KEY_5, - [0x05] = KEY_6, - [0x06] = KEY_7, - [0x07] = KEY_8, - [0x08] = KEY_9, - [0x09] = KEY_0, - [0x0a] = KEY_INFO, /* OSD */ - [0x1c] = KEY_BACKSPACE, /* LAST */ - - [0x0d] = KEY_PLAY, /* PLAY */ - [0x1e] = KEY_CAMERA, /* SNAPSHOT */ - [0x1a] = KEY_RECORD, /* RECORD */ - [0x17] = KEY_STOP, /* STOP */ - - [0x1f] = KEY_UP, /* UP */ - [0x44] = KEY_DOWN, /* DOWN */ - [0x46] = KEY_TAB, /* BACK */ - [0x4a] = KEY_ZOOM, /* FULLSECREEN */ - - [0x10] = KEY_VOLUMEUP, /* VOLUMEUP */ - [0x11] = KEY_VOLUMEDOWN, /* VOLUMEDOWN */ - [0x12] = KEY_CHANNELUP, /* CHANNELUP */ - [0x13] = KEY_CHANNELDOWN, /* CHANNELDOWN */ - [0x15] = KEY_ENTER, /* OK */ + { 0x14, KEY_POWER2}, /* POWER OFF */ + { 0x0c, KEY_MUTE}, /* MUTE */ + + { 0x18, KEY_TV}, /* TV */ + { 0x0e, KEY_VIDEO}, /* AV */ + { 0x0b, KEY_AUDIO}, /* SV */ + { 0x0f, KEY_RADIO}, /* FM */ + + { 0x00, KEY_1}, + { 0x01, KEY_2}, + { 0x02, KEY_3}, + { 0x03, KEY_4}, + { 0x04, KEY_5}, + { 0x05, KEY_6}, + { 0x06, KEY_7}, + { 0x07, KEY_8}, + { 0x08, KEY_9}, + { 0x09, KEY_0}, + { 0x0a, KEY_INFO}, /* OSD */ + { 0x1c, KEY_BACKSPACE}, /* LAST */ + + { 0x0d, KEY_PLAY}, /* PLAY */ + { 0x1e, KEY_CAMERA}, /* SNAPSHOT */ + { 0x1a, KEY_RECORD}, /* RECORD */ + { 0x17, KEY_STOP}, /* STOP */ + + { 0x1f, KEY_UP}, /* UP */ + { 0x44, KEY_DOWN}, /* DOWN */ + { 0x46, KEY_TAB}, /* BACK */ + { 0x4a, KEY_ZOOM}, /* FULLSECREEN */ + + { 0x10, KEY_VOLUMEUP}, /* VOLUMEUP */ + { 0x11, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ + { 0x12, KEY_CHANNELUP}, /* CHANNELUP */ + { 0x13, KEY_CHANNELDOWN}, /* CHANNELDOWN */ + { 0x15, KEY_ENTER}, /* OK */ +}; +struct ir_scancode_table ir_codes_gadmei_rm008z_table = { + .scan = ir_codes_gadmei_rm008z, + .size = ARRAY_SIZE(ir_codes_gadmei_rm008z), }; EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z); diff --git a/linux/drivers/media/dvb/dm1105/dm1105.c b/linux/drivers/media/dvb/dm1105/dm1105.c index f937151b3..874f976af 100644 --- a/linux/drivers/media/dvb/dm1105/dm1105.c +++ b/linux/drivers/media/dvb/dm1105/dm1105.c @@ -600,7 +600,7 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) { struct input_dev *input_dev; - IR_KEYTAB_TYPE *ir_codes = ir_codes_dm1105_nec; + struct ir_scancode_table *ir_codes = &ir_codes_dm1105_nec_table; int ir_type = IR_TYPE_OTHER; int err = -ENOMEM; diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index 1b564eb79..8a68cc2f7 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -233,7 +233,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) case 0x1012: /* The hauppauge keymap is a superset of these remotes */ ir_input_init(input_dev, &budget_ci->ir.state, - IR_TYPE_RC5, ir_codes_hauppauge_new); + IR_TYPE_RC5, &ir_codes_hauppauge_new_table); if (rc5_device < 0) budget_ci->ir.rc5_device = 0x1f; @@ -245,7 +245,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) case 0x101a: /* for the Technotrend 1500 bundled remote */ ir_input_init(input_dev, &budget_ci->ir.state, - IR_TYPE_RC5, ir_codes_tt_1500); + IR_TYPE_RC5, &ir_codes_tt_1500_table); if (rc5_device < 0) budget_ci->ir.rc5_device = IR_DEVICE_ANY; @@ -255,7 +255,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) default: /* unknown remote */ ir_input_init(input_dev, &budget_ci->ir.state, - IR_TYPE_RC5, ir_codes_budget_ci_old); + IR_TYPE_RC5, &ir_codes_budget_ci_old_table); if (rc5_device < 0) budget_ci->ir.rc5_device = IR_DEVICE_ANY; diff --git a/linux/drivers/media/video/bt8xx/bttv-input.c b/linux/drivers/media/video/bt8xx/bttv-input.c index f6bafbf3e..94eaef649 100644 --- a/linux/drivers/media/video/bt8xx/bttv-input.c +++ b/linux/drivers/media/video/bt8xx/bttv-input.c @@ -245,7 +245,7 @@ static void bttv_ir_stop(struct bttv *btv) int bttv_input_init(struct bttv *btv) { struct card_ir *ir; - IR_KEYTAB_TYPE *ir_codes = NULL; + struct ir_scancode_table *ir_codes = NULL; struct input_dev *input_dev; int ir_type = IR_TYPE_OTHER; int err = -ENOMEM; @@ -263,7 +263,7 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_AVERMEDIA: case BTTV_BOARD_AVPHONE98: case BTTV_BOARD_AVERMEDIA98: - ir_codes = ir_codes_avermedia; + ir_codes = &ir_codes_avermedia_table; ir->mask_keycode = 0xf88000; ir->mask_keydown = 0x010000; ir->polling = 50; // ms @@ -271,14 +271,14 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_AVDVBT_761: case BTTV_BOARD_AVDVBT_771: - ir_codes = ir_codes_avermedia_dvbt; + ir_codes = &ir_codes_avermedia_dvbt_table; ir->mask_keycode = 0x0f00c0; ir->mask_keydown = 0x000020; ir->polling = 50; // ms break; case BTTV_BOARD_PXELVWPLTVPAK: - ir_codes = ir_codes_pixelview; + ir_codes = &ir_codes_pixelview_table; ir->mask_keycode = 0x003e00; ir->mask_keyup = 0x010000; ir->polling = 50; // ms @@ -286,24 +286,24 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_PV_M4900: case BTTV_BOARD_PV_BT878P_9B: case BTTV_BOARD_PV_BT878P_PLUS: - ir_codes = ir_codes_pixelview; + ir_codes = &ir_codes_pixelview_table; ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x008000; ir->polling = 50; // ms break; case BTTV_BOARD_WINFAST2000: - ir_codes = ir_codes_winfast; + ir_codes = &ir_codes_winfast_table; ir->mask_keycode = 0x1f8; break; case BTTV_BOARD_MAGICTVIEW061: case BTTV_BOARD_MAGICTVIEW063: - ir_codes = ir_codes_winfast; + ir_codes = &ir_codes_winfast_table; ir->mask_keycode = 0x0008e000; ir->mask_keydown = 0x00200000; break; case BTTV_BOARD_APAC_VIEWCOMP: - ir_codes = ir_codes_apac_viewcomp; + ir_codes = &ir_codes_apac_viewcomp_table; ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x008000; ir->polling = 50; // ms @@ -311,30 +311,30 @@ int bttv_input_init(struct bttv *btv) case BTTV_BOARD_ASKEY_CPH03X: case BTTV_BOARD_CONCEPTRONIC_CTVFMI2: case BTTV_BOARD_CONTVFMI: - ir_codes = ir_codes_pixelview; + ir_codes = &ir_codes_pixelview_table; ir->mask_keycode = 0x001F00; ir->mask_keyup = 0x006000; ir->polling = 50; // ms break; case BTTV_BOARD_NEBULA_DIGITV: - ir_codes = ir_codes_nebula; + ir_codes = &ir_codes_nebula_table; btv->custom_irq = bttv_rc5_irq; ir->rc5_gpio = 1; break; case BTTV_BOARD_MACHTV_MAGICTV: - ir_codes = ir_codes_apac_viewcomp; + ir_codes = &ir_codes_apac_viewcomp_table; ir->mask_keycode = 0x001F00; ir->mask_keyup = 0x004000; ir->polling = 50; /* ms */ break; case BTTV_BOARD_KOZUMI_KTV_01C: - ir_codes = ir_codes_pctv_sedna; + ir_codes = &ir_codes_pctv_sedna_table; ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x006000; ir->polling = 50; /* ms */ break; case BTTV_BOARD_ENLTV_FM_2: - ir_codes = ir_codes_encore_enltv2; + ir_codes = &ir_codes_encore_enltv2_table; ir->mask_keycode = 0x00fd00; ir->mask_keyup = 0x000080; ir->polling = 1; /* ms */ diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c index 7d4272d33..fd789fad1 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.c +++ b/linux/drivers/media/video/cx18/cx18-i2c.c @@ -114,7 +114,7 @@ static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char *type, switch (hw) { case CX18_HW_Z8F0811_IR_RX_HAUP: memset(&ir_init_data, 0, sizeof(struct IR_i2c_init_data)); - ir_init_data.ir_codes = ir_codes_hauppauge_new; + ir_init_data.ir_codes = &ir_codes_hauppauge_new_table; ir_init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; ir_init_data.type = IR_TYPE_RC5; ir_init_data.name = "CX23418 Z8F0811 Hauppauge"; diff --git a/linux/drivers/media/video/cx231xx/cx231xx.h b/linux/drivers/media/video/cx231xx/cx231xx.h index 051ca21c1..ebcceaee2 100644 --- a/linux/drivers/media/video/cx231xx/cx231xx.h +++ b/linux/drivers/media/video/cx231xx/cx231xx.h @@ -283,7 +283,7 @@ struct cx231xx_board { struct cx231xx_input input[MAX_CX231XX_INPUT]; struct cx231xx_input radio; - IR_KEYTAB_TYPE *ir_codes; + struct ir_scancode_table *ir_codes; }; /* device states */ diff --git a/linux/drivers/media/video/cx88/cx88-input.c b/linux/drivers/media/video/cx88/cx88-input.c index 6a3687a88..426c8e62f 100644 --- a/linux/drivers/media/video/cx88/cx88-input.c +++ b/linux/drivers/media/video/cx88/cx88-input.c @@ -192,7 +192,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) { struct cx88_IR *ir; struct input_dev *input_dev; - IR_KEYTAB_TYPE *ir_codes = NULL; + struct ir_scancode_table *ir_codes = NULL; int ir_type = IR_TYPE_OTHER; int err = -ENOMEM; @@ -208,14 +208,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_KWORLD_DVB_T_CX22702: - ir_codes = ir_codes_dntv_live_dvb_t; + ir_codes = &ir_codes_dntv_live_dvb_t_table; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x60; ir->polling = 50; /* ms */ break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: - ir_codes = ir_codes_cinergy_1400; + ir_codes = &ir_codes_cinergy_1400_table; ir_type = IR_TYPE_PD; ir->sampling = 0xeb04; /* address */ break; @@ -230,14 +230,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_PCHDTV_HD3000: case CX88_BOARD_PCHDTV_HD5500: case CX88_BOARD_HAUPPAUGE_IRONLY: - ir_codes = ir_codes_hauppauge_new; + ir_codes = &ir_codes_hauppauge_new_table; ir_type = IR_TYPE_RC5; ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_WINFAST_DTV2000H_J: case CX88_BOARD_WINFAST_DTV1800H: - ir_codes = ir_codes_winfast; + ir_codes = &ir_codes_winfast_table; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; ir->mask_keyup = 0x100; @@ -246,14 +246,14 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) case CX88_BOARD_WINFAST2000XP_EXPERT: case CX88_BOARD_WINFAST_DTV1000: case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: - ir_codes = ir_codes_winfast; + ir_codes = &ir_codes_winfast_table; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; ir->mask_keyup = 0x100; ir->polling = 1; /* ms */ break; case CX88_BOARD_IODATA_GVBCTV7E: - ir_codes = ir_codes_iodata_bctv7e; + ir_codes = &ir_codes_iodata_bctv7e_table; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0xfd; ir->mask_keydown = 0x02; @@ -261,7 +261,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_PROLINK_PLAYTVPVR: case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: - ir_codes = ir_codes_pixelview; + ir_codes = &ir_codes_pixelview_table; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x80; @@ -269,28 +269,28 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_PROLINK_PV_8000GT: case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: - ir_codes = ir_codes_pixelview_new; + ir_codes = &ir_codes_pixelview_new_table; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x3f; ir->mask_keyup = 0x80; ir->polling = 1; /* ms */ break; case CX88_BOARD_KWORLD_LTV883: - ir_codes = ir_codes_pixelview; + ir_codes = &ir_codes_pixelview_table; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x60; ir->polling = 1; /* ms */ break; case CX88_BOARD_ADSTECH_DVB_T_PCI: - ir_codes = ir_codes_adstech_dvb_t_pci; + ir_codes = &ir_codes_adstech_dvb_t_pci_table; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0xbf; ir->mask_keyup = 0x40; ir->polling = 50; /* ms */ break; case CX88_BOARD_MSI_TVANYWHERE_MASTER: - ir_codes = ir_codes_msi_tvanywhere; + ir_codes = &ir_codes_msi_tvanywhere_table; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x1f; ir->mask_keyup = 0x40; @@ -298,40 +298,40 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) break; case CX88_BOARD_AVERTV_303: case CX88_BOARD_AVERTV_STUDIO_303: - ir_codes = ir_codes_avertv_303; + ir_codes = &ir_codes_avertv_303_table; ir->gpio_addr = MO_GP2_IO; ir->mask_keycode = 0xfb; ir->mask_keydown = 0x02; ir->polling = 50; /* ms */ break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: - ir_codes = ir_codes_dntv_live_dvbt_pro; - ir_type = IR_TYPE_PD; - ir->sampling = 0xff00; /* address */ + ir_codes = &ir_codes_dntv_live_dvbt_pro_table; + ir_type = IR_TYPE_PD; + ir->sampling = 0xff00; /* address */ break; case CX88_BOARD_NORWOOD_MICRO: - ir_codes = ir_codes_norwood; + ir_codes = &ir_codes_norwood_table; ir->gpio_addr = MO_GP1_IO; ir->mask_keycode = 0x0e; ir->mask_keyup = 0x80; ir->polling = 50; /* ms */ break; case CX88_BOARD_NPGTECH_REALTV_TOP10FM: - ir_codes = ir_codes_npgtech; - ir->gpio_addr = MO_GP0_IO; + ir_codes = &ir_codes_npgtech_table; + ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0xfa; - ir->polling = 50; /* ms */ + ir->polling = 50; /* ms */ break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: - ir_codes = ir_codes_pinnacle_pctv_hd; - ir_type = IR_TYPE_RC5; - ir->sampling = 1; + ir_codes = &ir_codes_pinnacle_pctv_hd_table; + ir_type = IR_TYPE_RC5; + ir->sampling = 1; break; case CX88_BOARD_POWERCOLOR_REAL_ANGEL: - ir_codes = ir_codes_powercolor_real_angel; - ir->gpio_addr = MO_GP2_IO; + ir_codes = &ir_codes_powercolor_real_angel_table; + ir->gpio_addr = MO_GP2_IO; ir->mask_keycode = 0x7e; - ir->polling = 100; /* ms */ + ir->polling = 100; /* ms */ break; } diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index d50b478a4..656604dc9 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -578,7 +578,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Gadmei UTV330+", .tuner_type = TUNER_TNF_5335MF, .tda9887_conf = TDA9887_PRESENT, - .ir_codes = ir_codes_gadmei_rm008z, + .ir_codes = &ir_codes_gadmei_rm008z_table, .decoder = EM28XX_SAA711X, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .input = { { @@ -772,7 +772,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = ir_codes_hauppauge_new, + .ir_codes = &ir_codes_hauppauge_new_table, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -797,7 +797,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, - .ir_codes = ir_codes_hauppauge_new, + .ir_codes = &ir_codes_hauppauge_new_table, .decoder = EM28XX_TVP5150, #if 0 /* FIXME: add an entry at em28xx-dvb */ .has_dvb = 1, @@ -827,7 +827,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = ir_codes_hauppauge_new, + .ir_codes = &ir_codes_hauppauge_new_table, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -853,7 +853,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = ir_codes_hauppauge_new, + .ir_codes = &ir_codes_hauppauge_new_table, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -879,7 +879,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = ir_codes_pinnacle_pctv_hd, + .ir_codes = &ir_codes_pinnacle_pctv_hd_table, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -905,7 +905,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = hauppauge_wintv_hvr_900_digital, - .ir_codes = ir_codes_ati_tv_wonder_hd_600, + .ir_codes = &ir_codes_ati_tv_wonder_hd_600_table, .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -931,7 +931,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_TVP5150, .has_dvb = 1, .dvb_gpio = default_digital, - .ir_codes = ir_codes_terratec_cinergy_xs, + .ir_codes = &ir_codes_terratec_cinergy_xs_table, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -1507,7 +1507,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .decoder = EM28XX_TVP5150, .tuner_gpio = default_tuner_gpio, - .ir_codes = ir_codes_kaiomy, + .ir_codes = &ir_codes_kaiomy_table, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -1607,7 +1607,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .has_dvb = 1, .dvb_gpio = evga_indtube_digital, - .ir_codes = ir_codes_evga_indtube, + .ir_codes = &ir_codes_evga_indtube_table, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -2301,36 +2301,36 @@ void em28xx_register_i2c_ir(struct em28xx *dev) case (EM2800_BOARD_TERRATEC_CINERGY_200): case (EM2820_BOARD_TERRATEC_CINERGY_250): #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) - ir->ir_codes = ir_codes_em_terratec; + ir->ir_codes = &ir_codes_em_terratec_table; ir->get_key = em28xx_get_key_terratec; snprintf(ir->name, sizeof(ir->name), "i2c IR (EM28XX Terratec)"); #else - init_data.ir_codes = ir_codes_em_terratec; + init_data.ir_codes = &ir_codes_em_terratec_table; init_data.get_key = em28xx_get_key_terratec; init_data.name = "i2c IR (EM28XX Terratec)"; #endif break; case (EM2820_BOARD_PINNACLE_USB_2): #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) - ir->ir_codes = ir_codes_pinnacle_grey; + ir->ir_codes = &ir_codes_pinnacle_grey_table; ir->get_key = em28xx_get_key_pinnacle_usb_grey; snprintf(ir->name, sizeof(ir->name), "i2c IR (EM28XX Pinnacle PCTV)"); #else - init_data.ir_codes = ir_codes_pinnacle_grey; + init_data.ir_codes = &ir_codes_pinnacle_grey_table; init_data.get_key = em28xx_get_key_pinnacle_usb_grey; init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; #endif break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) - ir->ir_codes = ir_codes_hauppauge_new; + ir->ir_codes = &ir_codes_hauppauge_new_table; ir->get_key = em28xx_get_key_em_haup; snprintf(ir->name, sizeof(ir->name), "i2c IR (EM2840 Hauppauge)"); #else - init_data.ir_codes = ir_codes_hauppauge_new; + init_data.ir_codes = &ir_codes_hauppauge_new_table; init_data.get_key = em28xx_get_key_em_haup; init_data.name = "i2c IR (EM2840 Hauppauge)"; #endif diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 68f274dcc..a603d981b 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -411,7 +411,7 @@ struct em28xx_board { struct em28xx_input input[MAX_EM28XX_INPUT]; struct em28xx_input radio; - IR_KEYTAB_TYPE *ir_codes; + struct ir_scancode_table *ir_codes; }; struct em28xx_eeprom { diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c index a1e8fb561..3b05bfcae 100644 --- a/linux/drivers/media/video/ir-kbd-i2c.c +++ b/linux/drivers/media/video/ir-kbd-i2c.c @@ -371,7 +371,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) #endif { - IR_KEYTAB_TYPE *ir_codes = NULL; + struct ir_scancode_table *ir_codes = NULL; const char *name = NULL; int ir_type; struct IR_i2c *ir; @@ -407,13 +407,13 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) name = "Pixelview"; ir->get_key = get_key_pixelview; ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_empty; + ir_codes = &ir_codes_empty_table; break; case 0x4b: name = "PV951"; ir->get_key = get_key_pv951; ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_pv951; + ir_codes = &ir_codes_pv951_table; break; case 0x18: case 0x1a: @@ -421,22 +421,22 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir->get_key = get_key_haup; ir_type = IR_TYPE_RC5; if (hauppauge == 1) { - ir_codes = ir_codes_hauppauge_new; + ir_codes = &ir_codes_hauppauge_new_table; } else { - ir_codes = ir_codes_rc5_tv; + ir_codes = &ir_codes_rc5_tv_table; } break; case 0x30: name = "KNC One"; ir->get_key = get_key_knc1; ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_empty; + ir_codes = &ir_codes_empty_table; break; case 0x6b: name = "FusionHDTV"; ir->get_key = get_key_fusionhdtv; ir_type = IR_TYPE_RC5; - ir_codes = ir_codes_fusionhdtv_mce; + ir_codes = &ir_codes_fusionhdtv_mce_table; break; case 0x7a: case 0x47: @@ -450,9 +450,9 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) ir_type = IR_TYPE_RC5; ir->get_key = get_key_haup_xvr; if (hauppauge == 1) { - ir_codes = ir_codes_hauppauge_new; + ir_codes = &ir_codes_hauppauge_new_table; } else { - ir_codes = ir_codes_rc5_tv; + ir_codes = &ir_codes_rc5_tv_table; } } else { /* Handled by saa7134-input */ @@ -464,7 +464,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) name = "AVerMedia Cardbus remote"; ir->get_key = get_key_avermedia_cardbus; ir_type = IR_TYPE_OTHER; - ir_codes = ir_codes_avermedia_cardbus; + ir_codes = &ir_codes_avermedia_cardbus_table; break; default: dprintk(1, DEVNAME ": Unsupported i2c address 0x%02x\n", addr); diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 9e2adcd12..261c86639 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -435,7 +435,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) { struct card_ir *ir; struct input_dev *input_dev; - IR_KEYTAB_TYPE *ir_codes = NULL; + struct ir_scancode_table *ir_codes = NULL; u32 mask_keycode = 0; u32 mask_keydown = 0; u32 mask_keyup = 0; @@ -457,27 +457,27 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_FLYTVPLATINUM_MINI2: case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM: - ir_codes = ir_codes_flyvideo; + ir_codes = &ir_codes_flyvideo_table; mask_keycode = 0xEC00000; mask_keydown = 0x0040000; break; case SAA7134_BOARD_CINERGY400: case SAA7134_BOARD_CINERGY600: case SAA7134_BOARD_CINERGY600_MK3: - ir_codes = ir_codes_cinergy; + ir_codes = &ir_codes_cinergy_table; mask_keycode = 0x00003f; mask_keyup = 0x040000; break; case SAA7134_BOARD_ECS_TVP3XP: case SAA7134_BOARD_ECS_TVP3XP_4CB5: - ir_codes = ir_codes_eztv; + ir_codes = &ir_codes_eztv_table; mask_keycode = 0x00017c; mask_keyup = 0x000002; polling = 50; // ms break; case SAA7134_BOARD_KWORLD_XPERT: case SAA7134_BOARD_AVACSSMARTTV: - ir_codes = ir_codes_pixelview; + ir_codes = &ir_codes_pixelview_table; mask_keycode = 0x00001F; mask_keyup = 0x000020; polling = 50; // ms @@ -494,7 +494,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_GO_007_FM: case SAA7134_BOARD_AVERMEDIA_M102: case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS: - ir_codes = ir_codes_avermedia; + ir_codes = &ir_codes_avermedia_table; mask_keycode = 0x0007C8; mask_keydown = 0x000010; polling = 50; // ms @@ -503,14 +503,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; case SAA7134_BOARD_AVERMEDIA_M135A: - ir_codes = ir_codes_avermedia_m135a; + ir_codes = &ir_codes_avermedia_m135a_table; mask_keydown = 0x0040000; mask_keycode = 0x00013f; nec_gpio = 1; break; case SAA7134_BOARD_AVERMEDIA_777: case SAA7134_BOARD_AVERMEDIA_A16AR: - ir_codes = ir_codes_avermedia; + ir_codes = &ir_codes_avermedia_table; mask_keycode = 0x02F200; mask_keydown = 0x000400; polling = 50; // ms @@ -519,7 +519,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); break; case SAA7134_BOARD_AVERMEDIA_A16D: - ir_codes = ir_codes_avermedia_a16d; + ir_codes = &ir_codes_avermedia_a16d_table; mask_keycode = 0x02F200; mask_keydown = 0x000400; polling = 50; /* ms */ @@ -528,14 +528,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); break; case SAA7134_BOARD_KWORLD_TERMINATOR: - ir_codes = ir_codes_pixelview; + ir_codes = &ir_codes_pixelview_table; mask_keycode = 0x00001f; mask_keyup = 0x000060; polling = 50; // ms break; case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: - ir_codes = ir_codes_manli; + ir_codes = &ir_codes_manli_table; mask_keycode = 0x001f00; mask_keyup = 0x004000; polling = 50; /* ms */ @@ -554,25 +554,25 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_507_9FM: case SAA7134_BOARD_BEHOLD_507RDS_MK3: case SAA7134_BOARD_BEHOLD_507RDS_MK5: - ir_codes = ir_codes_manli; + ir_codes = &ir_codes_manli_table; mask_keycode = 0x003f00; mask_keyup = 0x004000; polling = 50; /* ms */ break; case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: - ir_codes = ir_codes_behold_columbus; + ir_codes = &ir_codes_behold_columbus_table; mask_keycode = 0x003f00; mask_keyup = 0x004000; polling = 50; // ms break; case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS: - ir_codes = ir_codes_pctv_sedna; + ir_codes = &ir_codes_pctv_sedna_table; mask_keycode = 0x001f00; mask_keyup = 0x004000; polling = 50; // ms break; case SAA7134_BOARD_GOTVIEW_7135: - ir_codes = ir_codes_gotview7135; + ir_codes = &ir_codes_gotview7135_table; mask_keycode = 0x0003CC; mask_keydown = 0x000010; polling = 5; /* ms */ @@ -581,75 +581,75 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII: - ir_codes = ir_codes_videomate_tv_pvr; + ir_codes = &ir_codes_videomate_tv_pvr_table; mask_keycode = 0x00003F; mask_keyup = 0x400000; polling = 50; // ms break; case SAA7134_BOARD_PROTEUS_2309: - ir_codes = ir_codes_proteus_2309; + ir_codes = &ir_codes_proteus_2309_table; mask_keycode = 0x00007F; mask_keyup = 0x000080; polling = 50; // ms break; case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: - ir_codes = ir_codes_videomate_tv_pvr; + ir_codes = &ir_codes_videomate_tv_pvr_table; mask_keycode = 0x003F00; mask_keyup = 0x040000; break; case SAA7134_BOARD_FLYDVBS_LR300: case SAA7134_BOARD_FLYDVBT_LR301: case SAA7134_BOARD_FLYDVBTDUO: - ir_codes = ir_codes_flydvb; + ir_codes = &ir_codes_flydvb_table; mask_keycode = 0x0001F00; mask_keydown = 0x0040000; break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: case SAA7134_BOARD_ASUSTeK_P7131_ANALOG: - ir_codes = ir_codes_asus_pc39; + ir_codes = &ir_codes_asus_pc39_table; mask_keydown = 0x0040000; rc5_gpio = 1; break; case SAA7134_BOARD_ENCORE_ENLTV: case SAA7134_BOARD_ENCORE_ENLTV_FM: - ir_codes = ir_codes_encore_enltv; + ir_codes = &ir_codes_encore_enltv_table; mask_keycode = 0x00007f; mask_keyup = 0x040000; polling = 50; // ms break; case SAA7134_BOARD_ENCORE_ENLTV_FM53: - ir_codes = ir_codes_encore_enltv_fm53; + ir_codes = &ir_codes_encore_enltv_fm53_table; mask_keydown = 0x0040000; mask_keycode = 0x00007f; nec_gpio = 1; break; case SAA7134_BOARD_10MOONSTVMASTER3: - ir_codes = ir_codes_encore_enltv; + ir_codes = &ir_codes_encore_enltv_table; mask_keycode = 0x5f80000; mask_keyup = 0x8000000; polling = 50; //ms break; case SAA7134_BOARD_GENIUS_TVGO_A11MCE: - ir_codes = ir_codes_genius_tvgo_a11mce; + ir_codes = &ir_codes_genius_tvgo_a11mce_table; mask_keycode = 0xff; mask_keydown = 0xf00000; polling = 50; /* ms */ break; case SAA7134_BOARD_REAL_ANGEL_220: - ir_codes = ir_codes_real_audio_220_32_keys; + ir_codes = &ir_codes_real_audio_220_32_keys_table; mask_keycode = 0x3f00; mask_keyup = 0x4000; polling = 50; /* ms */ break; case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG: - ir_codes = ir_codes_kworld_plus_tv_analog; + ir_codes = &ir_codes_kworld_plus_tv_analog_table; mask_keycode = 0x7f; polling = 40; /* ms */ break; case SAA7134_BOARD_VIDEOMATE_S350: - ir_codes = ir_codes_videomate_s350; + ir_codes = &ir_codes_videomate_s350_table; mask_keycode = 0x003f00; mask_keydown = 0x040000; break; @@ -785,19 +785,19 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) if (pinnacle_remote == 0) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ir->get_key = get_key_pinnacle_color; - ir->ir_codes = ir_codes_pinnacle_color; + ir->ir_codes = &ir_codes_pinnacle_color_table; #else init_data.get_key = get_key_pinnacle_color; - init_data.ir_codes = ir_codes_pinnacle_color; + init_data.ir_codes = &ir_codes_pinnacle_color_table; info.addr = 0x47; #endif } else { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ir->get_key = get_key_pinnacle_grey; - ir->ir_codes = ir_codes_pinnacle_grey; + ir->ir_codes = &ir_codes_pinnacle_grey_table; #else init_data.get_key = get_key_pinnacle_grey; - init_data.ir_codes = ir_codes_pinnacle_grey; + init_data.ir_codes = &ir_codes_pinnacle_grey_table; info.addr = 0x47; #endif } @@ -806,22 +806,22 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV"); ir->get_key = get_key_purpletv; - ir->ir_codes = ir_codes_purpletv; + ir->ir_codes = &ir_codes_purpletv_table; #else init_data.name = "Purple TV"; init_data.get_key = get_key_purpletv; - init_data.ir_codes = ir_codes_purpletv; + init_data.ir_codes = &ir_codes_purpletv_table; #endif break; case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) snprintf(ir->c.name, sizeof(ir->c.name), "MSI TV@nywhere Plus"); ir->get_key = get_key_msi_tvanywhere_plus; - ir->ir_codes = ir_codes_msi_tvanywhere_plus; + ir->ir_codes = &ir_codes_msi_tvanywhere_plus_table; #else init_data.name = "MSI TV@nywhere Plus"; init_data.get_key = get_key_msi_tvanywhere_plus; - init_data.ir_codes = ir_codes_msi_tvanywhere_plus; + init_data.ir_codes = &ir_codes_msi_tvanywhere_plus_table; info.addr = 0x30; /* MSI TV@nywhere Plus controller doesn't seem to respond to probes unless we read something from @@ -837,11 +837,11 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); ir->get_key = get_key_hvr1110; - ir->ir_codes = ir_codes_hauppauge_new; + ir->ir_codes = &ir_codes_hauppauge_new_table; #else init_data.name = "HVR 1110"; init_data.get_key = get_key_hvr1110; - init_data.ir_codes = ir_codes_hauppauge_new; + init_data.ir_codes = &ir_codes_hauppauge_new_table; #endif break; case SAA7134_BOARD_BEHOLD_607FM_MK3: @@ -860,11 +860,11 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV"); ir->get_key = get_key_beholdm6xx; - ir->ir_codes = ir_codes_behold; + ir->ir_codes = &ir_codes_behold_table; #else init_data.name = "BeholdTV"; init_data.get_key = get_key_beholdm6xx; - init_data.ir_codes = ir_codes_behold; + init_data.ir_codes = &ir_codes_behold_table; #endif break; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) diff --git a/linux/include/media/ir-common.h b/linux/include/media/ir-common.h index 74a7e5573..29f0e53cf 100644 --- a/linux/include/media/ir-common.h +++ b/linux/include/media/ir-common.h @@ -31,8 +31,18 @@ #define IR_TYPE_PD 2 /* Pulse distance encoded IR */ #define IR_TYPE_OTHER 99 -#define IR_KEYTAB_TYPE u32 -#define IR_KEYTAB_SIZE 128 // enougth for rc5, probably need more some day ... +#define IR_KEYTAB_TYPE u32 +#define IR_KEYTAB_SIZE 128 /* enougth for rc5, probably need more some day */ + +struct ir_scancode { + u16 scancode; + u32 keycode; +}; + +struct ir_scancode_table { + struct ir_scancode *scan; + int size; +}; #define IR_KEYCODE(tab,code) (((unsigned)code < IR_KEYTAB_SIZE) \ ? tab[code] : KEY_RESERVED) @@ -93,7 +103,7 @@ struct card_ir { }; void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, - int ir_type, IR_KEYTAB_TYPE *ir_codes); + int ir_type, struct ir_scancode_table *ir_codes); void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir); void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, u32 ir_key, u32 ir_raw); @@ -107,70 +117,63 @@ void ir_rc5_timer_keyup(unsigned long data); /* Keymaps to be used by other modules */ -extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_eztv[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_videomate_tv_pvr[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_manli[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_gotview7135[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_terratec_cinergy_xs[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE]; -extern IR_KEYTAB_TYPE ir_codes_gadmei_rm008z[IR_KEYTAB_SIZE]; - +extern struct ir_scancode_table ir_codes_empty_table; +extern struct ir_scancode_table ir_codes_avermedia_table; +extern struct ir_scancode_table ir_codes_avermedia_dvbt_table; +extern struct ir_scancode_table ir_codes_avermedia_m135a_table; +extern struct ir_scancode_table ir_codes_avermedia_cardbus_table; +extern struct ir_scancode_table ir_codes_apac_viewcomp_table; +extern struct ir_scancode_table ir_codes_pixelview_table; +extern struct ir_scancode_table ir_codes_pixelview_new_table; +extern struct ir_scancode_table ir_codes_nebula_table; +extern struct ir_scancode_table ir_codes_dntv_live_dvb_t_table; +extern struct ir_scancode_table ir_codes_iodata_bctv7e_table; +extern struct ir_scancode_table ir_codes_adstech_dvb_t_pci_table; +extern struct ir_scancode_table ir_codes_msi_tvanywhere_table; +extern struct ir_scancode_table ir_codes_cinergy_1400_table; +extern struct ir_scancode_table ir_codes_avertv_303_table; +extern struct ir_scancode_table ir_codes_dntv_live_dvbt_pro_table; +extern struct ir_scancode_table ir_codes_em_terratec_table; +extern struct ir_scancode_table ir_codes_pinnacle_grey_table; +extern struct ir_scancode_table ir_codes_flyvideo_table; +extern struct ir_scancode_table ir_codes_flydvb_table; +extern struct ir_scancode_table ir_codes_cinergy_table; +extern struct ir_scancode_table ir_codes_eztv_table; +extern struct ir_scancode_table ir_codes_avermedia_table; +extern struct ir_scancode_table ir_codes_videomate_tv_pvr_table; +extern struct ir_scancode_table ir_codes_manli_table; +extern struct ir_scancode_table ir_codes_gotview7135_table; +extern struct ir_scancode_table ir_codes_purpletv_table; +extern struct ir_scancode_table ir_codes_pctv_sedna_table; +extern struct ir_scancode_table ir_codes_pv951_table; +extern struct ir_scancode_table ir_codes_rc5_tv_table; +extern struct ir_scancode_table ir_codes_winfast_table; +extern struct ir_scancode_table ir_codes_pinnacle_color_table; +extern struct ir_scancode_table ir_codes_hauppauge_new_table; +extern struct ir_scancode_table ir_codes_npgtech_table; +extern struct ir_scancode_table ir_codes_norwood_table; +extern struct ir_scancode_table ir_codes_proteus_2309_table; +extern struct ir_scancode_table ir_codes_budget_ci_old_table; +extern struct ir_scancode_table ir_codes_asus_pc39_table; +extern struct ir_scancode_table ir_codes_encore_enltv_table; +extern struct ir_scancode_table ir_codes_encore_enltv2_table; +extern struct ir_scancode_table ir_codes_tt_1500_table; +extern struct ir_scancode_table ir_codes_fusionhdtv_mce_table; +extern struct ir_scancode_table ir_codes_behold_table; +extern struct ir_scancode_table ir_codes_behold_columbus_table; +extern struct ir_scancode_table ir_codes_pinnacle_pctv_hd_table; +extern struct ir_scancode_table ir_codes_genius_tvgo_a11mce_table; +extern struct ir_scancode_table ir_codes_powercolor_real_angel_table; +extern struct ir_scancode_table ir_codes_avermedia_a16d_table; +extern struct ir_scancode_table ir_codes_encore_enltv_fm53_table; +extern struct ir_scancode_table ir_codes_real_audio_220_32_keys_table; +extern struct ir_scancode_table ir_codes_msi_tvanywhere_plus_table; +extern struct ir_scancode_table ir_codes_ati_tv_wonder_hd_600_table; +extern struct ir_scancode_table ir_codes_kworld_plus_tv_analog_table; +extern struct ir_scancode_table ir_codes_kaiomy_table; +extern struct ir_scancode_table ir_codes_dm1105_nec_table; +extern struct ir_scancode_table ir_codes_evga_indtube_table; +extern struct ir_scancode_table ir_codes_terratec_cinergy_xs_table; +extern struct ir_scancode_table ir_codes_videomate_s350_table; +extern struct ir_scancode_table ir_codes_gadmei_rm008z_table; #endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/linux/include/media/ir-kbd-i2c.h b/linux/include/media/ir-kbd-i2c.h index 2a8da5027..2740794ce 100644 --- a/linux/include/media/ir-kbd-i2c.h +++ b/linux/include/media/ir-kbd-i2c.h @@ -6,7 +6,8 @@ struct IR_i2c; struct IR_i2c { - IR_KEYTAB_TYPE *ir_codes; + struct ir_scancode_table *ir_codes; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) struct i2c_client c; #else @@ -37,7 +38,7 @@ enum ir_kbd_get_key_fn { /* Can be passed when instantiating an ir_video i2c device */ struct IR_i2c_init_data { - IR_KEYTAB_TYPE *ir_codes; + struct ir_scancode_table *ir_codes; const char *name; int type; /* IR_TYPE_RC5, IR_TYPE_PD, etc */ /* -- cgit v1.2.3 From 64cff4f7b669a14d338b176254dd0f7eaedf396e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 14:19:07 -0300 Subject: gen_keytables.pl: Change it to work with the new format From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/gen_keytables.pl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/v4l2-apps/util/gen_keytables.pl b/v4l2-apps/util/gen_keytables.pl index 889516de4..5c569f559 100755 --- a/v4l2-apps/util/gen_keytables.pl +++ b/v4l2-apps/util/gen_keytables.pl @@ -5,8 +5,7 @@ my $keyname=""; my $debug=0; while (<>) { -#IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = { - if (m/IR_KEYTAB_TYPE\s+(\w[\w\d_]+)/) { + if (m/struct\s+ir_scancode\s+(\w[\w\d_]+)/) { $keyname = $1; $keyname =~ s/^ir_codes_//; -- cgit v1.2.3 From 877785ea4eb2b8cd7adbb1c7dc074aef1ed57f00 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 15:14:22 -0300 Subject: gen_keytables: generate also dvb-usb.h based keybables From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/Makefile | 26 ++++++++++++++++++++++++-- v4l2-apps/util/gen_keytables.pl | 6 +++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile index 6f9d1071a..29f3f4852 100644 --- a/v4l2-apps/util/Makefile +++ b/v4l2-apps/util/Makefile @@ -1,5 +1,26 @@ # Makefile for linuxtv.org v4l2-apps/util +IR_FILES = "linux/drivers/media/common/ir-keymaps.c \ +linux/drivers/media/dvb/dvb-usb/a800.c \ +linux/drivers/media/dvb/dvb-usb/af9005-remote.c \ +linux/drivers/media/dvb/dvb-usb/af9015.c \ +linux/drivers/media/dvb/dvb-usb/af9015.h \ +linux/drivers/media/dvb/dvb-usb/anysee.c \ +linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c \ +linux/drivers/media/dvb/dvb-usb/cxusb.c \ +linux/drivers/media/dvb/dvb-usb/dib0700_devices.c \ +linux/drivers/media/dvb/dvb-usb/dibusb-common.c \ +linux/drivers/media/dvb/dvb-usb/digitv.c \ +linux/drivers/media/dvb/dvb-usb/dtt200u.c \ +linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c \ +linux/drivers/media/dvb/dvb-usb/dvb-usb.h \ +linux/drivers/media/dvb/dvb-usb/dw2102.c \ +linux/drivers/media/dvb/dvb-usb/m920x.c \ +linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c \ +linux/drivers/media/dvb/dvb-usb/opera1.c \ +linux/drivers/media/dvb/dvb-usb/vp702x.c \ +linux/drivers/media/dvb/dvb-usb/vp7045.c " + ifeq ($(KERNEL_DIR),) KERNEL_DIR = /usr endif @@ -62,8 +83,9 @@ parse.h: $(KERNEL_DIR)/include/linux/input.h @printf "\t{ NULL, 0}\n};\n" >>parse.h keytables: - -mkdir -p keycodes - ./gen_keytables.pl ../../linux/drivers/media/common/ir-keymaps.c + @-mkdir -p keycodes + @echo storing existing keycodes at keycodes/ + @for i in `echo $(IR_FILES)`; do ./gen_keytables.pl ../../$$i; done keytable: keytable.c parse.h keytables diff --git a/v4l2-apps/util/gen_keytables.pl b/v4l2-apps/util/gen_keytables.pl index 5c569f559..5a5398017 100755 --- a/v4l2-apps/util/gen_keytables.pl +++ b/v4l2-apps/util/gen_keytables.pl @@ -5,8 +5,8 @@ my $keyname=""; my $debug=0; while (<>) { - if (m/struct\s+ir_scancode\s+(\w[\w\d_]+)/) { - $keyname = $1; + if (m/struct\s+(dvb_usb_rc_key|ir_scancode)\s+(\w[\w\d_]+)/) { + $keyname = $2; $keyname =~ s/^ir_codes_//; print "Generating keycodes/$keyname\n" if $debug; @@ -14,7 +14,7 @@ while (<>) { next; } if ($keyname ne "") { - if (m/(0x[\d\w]+).*(KEY_[^\s\,]+)/) { + if (m/(0x[\dA-Fa-f]+).*(KEY_[^\s\,]+)/) { printf OUT "%s %s\n",$1, $2; next; } -- cgit v1.2.3 From bd23819ad02d476b60d38580472580c181243f98 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 15:19:31 -0300 Subject: dvb-usb: store rc5 custom and data at the same field From: Mauro Carvalho Chehab In order to be closer to V4L IR implementation, it is needed to replace u8 custom, data to: u16 scan This allows using non-rc5 mappings, like the 8 bit keycodes used on older protocols. It will also allow future implementations of rc6 keystrokes when needed. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/a800.c | 70 ++-- linux/drivers/media/dvb/dvb-usb/af9005-remote.c | 76 ++-- linux/drivers/media/dvb/dvb-usb/af9015.c | 4 +- linux/drivers/media/dvb/dvb-usb/af9015.h | 460 +++++++++++----------- linux/drivers/media/dvb/dvb-usb/anysee.c | 92 ++--- linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c | 74 ++-- linux/drivers/media/dvb/dvb-usb/cxusb.c | 244 ++++++------ linux/drivers/media/dvb/dvb-usb/dib0700_devices.c | 370 ++++++++--------- linux/drivers/media/dvb/dvb-usb/dibusb-common.c | 244 ++++++------ linux/drivers/media/dvb/dvb-usb/digitv.c | 114 +++--- linux/drivers/media/dvb/dvb-usb/dtt200u.c | 36 +- linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 4 +- linux/drivers/media/dvb/dvb-usb/dvb-usb.h | 17 +- linux/drivers/media/dvb/dvb-usb/dw2102.c | 222 +++++------ linux/drivers/media/dvb/dvb-usb/m920x.c | 68 ++-- linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c | 97 ++--- linux/drivers/media/dvb/dvb-usb/opera1.c | 55 ++- linux/drivers/media/dvb/dvb-usb/vp702x.c | 6 +- linux/drivers/media/dvb/dvb-usb/vp7045.c | 102 ++--- 19 files changed, 1186 insertions(+), 1169 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/a800.c b/linux/drivers/media/dvb/dvb-usb/a800.c index dc8c8784c..624723998 100644 --- a/linux/drivers/media/dvb/dvb-usb/a800.c +++ b/linux/drivers/media/dvb/dvb-usb/a800.c @@ -38,41 +38,41 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr } static struct dvb_usb_rc_key a800_rc_keys[] = { - { 0x02, 0x01, KEY_PROG1 }, /* SOURCE */ - { 0x02, 0x00, KEY_POWER }, /* POWER */ - { 0x02, 0x05, KEY_1 }, /* 1 */ - { 0x02, 0x06, KEY_2 }, /* 2 */ - { 0x02, 0x07, KEY_3 }, /* 3 */ - { 0x02, 0x09, KEY_4 }, /* 4 */ - { 0x02, 0x0a, KEY_5 }, /* 5 */ - { 0x02, 0x0b, KEY_6 }, /* 6 */ - { 0x02, 0x0d, KEY_7 }, /* 7 */ - { 0x02, 0x0e, KEY_8 }, /* 8 */ - { 0x02, 0x0f, KEY_9 }, /* 9 */ - { 0x02, 0x12, KEY_LEFT }, /* L / DISPLAY */ - { 0x02, 0x11, KEY_0 }, /* 0 */ - { 0x02, 0x13, KEY_RIGHT }, /* R / CH RTN */ - { 0x02, 0x17, KEY_PROG2 }, /* SNAP SHOT */ - { 0x02, 0x10, KEY_PROG3 }, /* 16-CH PREV */ - { 0x02, 0x1e, KEY_VOLUMEDOWN }, /* VOL DOWN */ - { 0x02, 0x0c, KEY_ZOOM }, /* FULL SCREEN */ - { 0x02, 0x1f, KEY_VOLUMEUP }, /* VOL UP */ - { 0x02, 0x14, KEY_MUTE }, /* MUTE */ - { 0x02, 0x08, KEY_AUDIO }, /* AUDIO */ - { 0x02, 0x19, KEY_RECORD }, /* RECORD */ - { 0x02, 0x18, KEY_PLAY }, /* PLAY */ - { 0x02, 0x1b, KEY_STOP }, /* STOP */ - { 0x02, 0x1a, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */ - { 0x02, 0x1d, KEY_BACK }, /* << / RED */ - { 0x02, 0x1c, KEY_FORWARD }, /* >> / YELLOW */ - { 0x02, 0x03, KEY_TEXT }, /* TELETEXT */ - { 0x02, 0x04, KEY_EPG }, /* EPG */ - { 0x02, 0x15, KEY_MENU }, /* MENU */ - - { 0x03, 0x03, KEY_CHANNELUP }, /* CH UP */ - { 0x03, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */ - { 0x03, 0x01, KEY_FIRST }, /* |<< / GREEN */ - { 0x03, 0x00, KEY_LAST }, /* >>| / BLUE */ + { 0x0201, KEY_PROG1 }, /* SOURCE */ + { 0x0200, KEY_POWER }, /* POWER */ + { 0x0205, KEY_1 }, /* 1 */ + { 0x0206, KEY_2 }, /* 2 */ + { 0x0207, KEY_3 }, /* 3 */ + { 0x0209, KEY_4 }, /* 4 */ + { 0x020a, KEY_5 }, /* 5 */ + { 0x020b, KEY_6 }, /* 6 */ + { 0x020d, KEY_7 }, /* 7 */ + { 0x020e, KEY_8 }, /* 8 */ + { 0x020f, KEY_9 }, /* 9 */ + { 0x0212, KEY_LEFT }, /* L / DISPLAY */ + { 0x0211, KEY_0 }, /* 0 */ + { 0x0213, KEY_RIGHT }, /* R / CH RTN */ + { 0x0217, KEY_PROG2 }, /* SNAP SHOT */ + { 0x0210, KEY_PROG3 }, /* 16-CH PREV */ + { 0x021e, KEY_VOLUMEDOWN }, /* VOL DOWN */ + { 0x020c, KEY_ZOOM }, /* FULL SCREEN */ + { 0x021f, KEY_VOLUMEUP }, /* VOL UP */ + { 0x0214, KEY_MUTE }, /* MUTE */ + { 0x0208, KEY_AUDIO }, /* AUDIO */ + { 0x0219, KEY_RECORD }, /* RECORD */ + { 0x0218, KEY_PLAY }, /* PLAY */ + { 0x021b, KEY_STOP }, /* STOP */ + { 0x021a, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */ + { 0x021d, KEY_BACK }, /* << / RED */ + { 0x021c, KEY_FORWARD }, /* >> / YELLOW */ + { 0x0203, KEY_TEXT }, /* TELETEXT */ + { 0x0204, KEY_EPG }, /* EPG */ + { 0x0215, KEY_MENU }, /* MENU */ + + { 0x0303, KEY_CHANNELUP }, /* CH UP */ + { 0x0302, KEY_CHANNELDOWN }, /* CH DOWN */ + { 0x0301, KEY_FIRST }, /* |<< / GREEN */ + { 0x0300, KEY_LAST }, /* >>| / BLUE */ }; diff --git a/linux/drivers/media/dvb/dvb-usb/af9005-remote.c b/linux/drivers/media/dvb/dvb-usb/af9005-remote.c index 7c596f926..f4379c650 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9005-remote.c +++ b/linux/drivers/media/dvb/dvb-usb/af9005-remote.c @@ -35,43 +35,43 @@ MODULE_PARM_DESC(debug, struct dvb_usb_rc_key af9005_rc_keys[] = { - {0x01, 0xb7, KEY_POWER}, - {0x01, 0xa7, KEY_VOLUMEUP}, - {0x01, 0x87, KEY_CHANNELUP}, - {0x01, 0x7f, KEY_MUTE}, - {0x01, 0xbf, KEY_VOLUMEDOWN}, - {0x01, 0x3f, KEY_CHANNELDOWN}, - {0x01, 0xdf, KEY_1}, - {0x01, 0x5f, KEY_2}, - {0x01, 0x9f, KEY_3}, - {0x01, 0x1f, KEY_4}, - {0x01, 0xef, KEY_5}, - {0x01, 0x6f, KEY_6}, - {0x01, 0xaf, KEY_7}, - {0x01, 0x27, KEY_8}, - {0x01, 0x07, KEY_9}, - {0x01, 0xcf, KEY_ZOOM}, - {0x01, 0x4f, KEY_0}, - {0x01, 0x8f, KEY_GOTO}, /* marked jump on the remote */ + {0x01b7, KEY_POWER}, + {0x01a7, KEY_VOLUMEUP}, + {0x0187, KEY_CHANNELUP}, + {0x017f, KEY_MUTE}, + {0x01bf, KEY_VOLUMEDOWN}, + {0x013f, KEY_CHANNELDOWN}, + {0x01df, KEY_1}, + {0x015f, KEY_2}, + {0x019f, KEY_3}, + {0x011f, KEY_4}, + {0x01ef, KEY_5}, + {0x016f, KEY_6}, + {0x01af, KEY_7}, + {0x0127, KEY_8}, + {0x0107, KEY_9}, + {0x01cf, KEY_ZOOM}, + {0x014f, KEY_0}, + {0x018f, KEY_GOTO}, /* marked jump on the remote */ - {0x00, 0xbd, KEY_POWER}, - {0x00, 0x7d, KEY_VOLUMEUP}, - {0x00, 0xfd, KEY_CHANNELUP}, - {0x00, 0x9d, KEY_MUTE}, - {0x00, 0x5d, KEY_VOLUMEDOWN}, - {0x00, 0xdd, KEY_CHANNELDOWN}, - {0x00, 0xad, KEY_1}, - {0x00, 0x6d, KEY_2}, - {0x00, 0xed, KEY_3}, - {0x00, 0x8d, KEY_4}, - {0x00, 0x4d, KEY_5}, - {0x00, 0xcd, KEY_6}, - {0x00, 0xb5, KEY_7}, - {0x00, 0x75, KEY_8}, - {0x00, 0xf5, KEY_9}, - {0x00, 0x95, KEY_ZOOM}, - {0x00, 0x55, KEY_0}, - {0x00, 0xd5, KEY_GOTO}, /* marked jump on the remote */ + {0x00bd, KEY_POWER}, + {0x007d, KEY_VOLUMEUP}, + {0x00fd, KEY_CHANNELUP}, + {0x009d, KEY_MUTE}, + {0x005d, KEY_VOLUMEDOWN}, + {0x00dd, KEY_CHANNELDOWN}, + {0x00ad, KEY_1}, + {0x006d, KEY_2}, + {0x00ed, KEY_3}, + {0x008d, KEY_4}, + {0x004d, KEY_5}, + {0x00cd, KEY_6}, + {0x00b5, KEY_7}, + {0x0075, KEY_8}, + {0x00f5, KEY_9}, + {0x0095, KEY_ZOOM}, + {0x0055, KEY_0}, + {0x00d5, KEY_GOTO}, /* marked jump on the remote */ }; int af9005_rc_keys_size = ARRAY_SIZE(af9005_rc_keys); @@ -131,8 +131,8 @@ int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event, return 0; } for (i = 0; i < af9005_rc_keys_size; i++) { - if (af9005_rc_keys[i].custom == cust - && af9005_rc_keys[i].data == dat) { + if (rc5_custom(&af9005_rc_keys[i]) == cust + && rc5_data(&af9005_rc_keys[i]) == dat) { *event = af9005_rc_keys[i].event; *state = REMOTE_KEY_PRESSED; deb_decode diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 3c2b7c0d7..aeb10db0b 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -1046,8 +1046,8 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state) *state = REMOTE_NO_KEY_PRESSED; for (i = 0; i < d->props.rc_key_map_size; i++) { - if (!buf[1] && keymap[i].custom == buf[0] && - keymap[i].data == buf[2]) { + if (!buf[1] && rc5_custom(&keymap[i]) == buf[0] && + rc5_data(&keymap[i]) == buf[2]) { *event = keymap[i].event; *state = REMOTE_KEY_PRESSED; break; diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.h b/linux/drivers/media/dvb/dvb-usb/af9015.h index 8d81a17c1..c41f30e4a 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.h +++ b/linux/drivers/media/dvb/dvb-usb/af9015.h @@ -121,21 +121,21 @@ enum af9015_remote { /* Leadtek WinFast DTV Dongle Gold */ static struct dvb_usb_rc_key af9015_rc_keys_leadtek[] = { - { 0x00, 0x1e, KEY_1 }, - { 0x00, 0x1f, KEY_2 }, - { 0x00, 0x20, KEY_3 }, - { 0x00, 0x21, KEY_4 }, - { 0x00, 0x22, KEY_5 }, - { 0x00, 0x23, KEY_6 }, - { 0x00, 0x24, KEY_7 }, - { 0x00, 0x25, KEY_8 }, - { 0x00, 0x26, KEY_9 }, - { 0x00, 0x27, KEY_0 }, - { 0x00, 0x28, KEY_ENTER }, - { 0x00, 0x4f, KEY_VOLUMEUP }, - { 0x00, 0x50, KEY_VOLUMEDOWN }, - { 0x00, 0x51, KEY_CHANNELDOWN }, - { 0x00, 0x52, KEY_CHANNELUP }, + { 0x001e, KEY_1 }, + { 0x001f, KEY_2 }, + { 0x0020, KEY_3 }, + { 0x0021, KEY_4 }, + { 0x0022, KEY_5 }, + { 0x0023, KEY_6 }, + { 0x0024, KEY_7 }, + { 0x0025, KEY_8 }, + { 0x0026, KEY_9 }, + { 0x0027, KEY_0 }, + { 0x0028, KEY_ENTER }, + { 0x004f, KEY_VOLUMEUP }, + { 0x0050, KEY_VOLUMEDOWN }, + { 0x0051, KEY_CHANNELDOWN }, + { 0x0052, KEY_CHANNELUP }, }; static u8 af9015_ir_table_leadtek[] = { @@ -193,60 +193,60 @@ static u8 af9015_ir_table_leadtek[] = { /* TwinHan AzureWave AD-TU700(704J) */ static struct dvb_usb_rc_key af9015_rc_keys_twinhan[] = { - { 0x05, 0x3f, KEY_POWER }, - { 0x00, 0x19, KEY_FAVORITES }, /* Favorite List */ - { 0x00, 0x04, KEY_TEXT }, /* Teletext */ - { 0x00, 0x0e, KEY_POWER }, - { 0x00, 0x0e, KEY_INFO }, /* Preview */ - { 0x00, 0x08, KEY_EPG }, /* Info/EPG */ - { 0x00, 0x0f, KEY_LIST }, /* Record List */ - { 0x00, 0x1e, KEY_1 }, - { 0x00, 0x1f, KEY_2 }, - { 0x00, 0x20, KEY_3 }, - { 0x00, 0x21, KEY_4 }, - { 0x00, 0x22, KEY_5 }, - { 0x00, 0x23, KEY_6 }, - { 0x00, 0x24, KEY_7 }, - { 0x00, 0x25, KEY_8 }, - { 0x00, 0x26, KEY_9 }, - { 0x00, 0x27, KEY_0 }, - { 0x00, 0x29, KEY_CANCEL }, /* Cancel */ - { 0x00, 0x4c, KEY_CLEAR }, /* Clear */ - { 0x00, 0x2a, KEY_BACK }, /* Back */ - { 0x00, 0x2b, KEY_TAB }, /* Tab */ - { 0x00, 0x52, KEY_UP }, /* up arrow */ - { 0x00, 0x51, KEY_DOWN }, /* down arrow */ - { 0x00, 0x4f, KEY_RIGHT }, /* right arrow */ - { 0x00, 0x50, KEY_LEFT }, /* left arrow */ - { 0x00, 0x28, KEY_ENTER }, /* Enter / ok */ - { 0x02, 0x52, KEY_VOLUMEUP }, - { 0x02, 0x51, KEY_VOLUMEDOWN }, - { 0x00, 0x4e, KEY_CHANNELDOWN }, - { 0x00, 0x4b, KEY_CHANNELUP }, - { 0x00, 0x4a, KEY_RECORD }, - { 0x01, 0x11, KEY_PLAY }, - { 0x00, 0x17, KEY_PAUSE }, - { 0x00, 0x0c, KEY_REWIND }, /* FR << */ - { 0x00, 0x11, KEY_FASTFORWARD }, /* FF >> */ - { 0x01, 0x15, KEY_PREVIOUS }, /* Replay */ - { 0x01, 0x0e, KEY_NEXT }, /* Skip */ - { 0x00, 0x13, KEY_CAMERA }, /* Capture */ - { 0x01, 0x0f, KEY_LANGUAGE }, /* SAP */ - { 0x01, 0x13, KEY_TV2 }, /* PIP */ - { 0x00, 0x1d, KEY_ZOOM }, /* Full Screen */ - { 0x01, 0x17, KEY_SUBTITLE }, /* Subtitle / CC */ - { 0x00, 0x10, KEY_MUTE }, - { 0x01, 0x19, KEY_AUDIO }, /* L/R */ /* TODO better event */ - { 0x01, 0x16, KEY_SLEEP }, /* Hibernate */ - { 0x01, 0x16, KEY_SWITCHVIDEOMODE }, + { 0x053f, KEY_POWER }, + { 0x0019, KEY_FAVORITES }, /* Favorite List */ + { 0x0004, KEY_TEXT }, /* Teletext */ + { 0x000e, KEY_POWER }, + { 0x000e, KEY_INFO }, /* Preview */ + { 0x0008, KEY_EPG }, /* Info/EPG */ + { 0x000f, KEY_LIST }, /* Record List */ + { 0x001e, KEY_1 }, + { 0x001f, KEY_2 }, + { 0x0020, KEY_3 }, + { 0x0021, KEY_4 }, + { 0x0022, KEY_5 }, + { 0x0023, KEY_6 }, + { 0x0024, KEY_7 }, + { 0x0025, KEY_8 }, + { 0x0026, KEY_9 }, + { 0x0027, KEY_0 }, + { 0x0029, KEY_CANCEL }, /* Cancel */ + { 0x004c, KEY_CLEAR }, /* Clear */ + { 0x002a, KEY_BACK }, /* Back */ + { 0x002b, KEY_TAB }, /* Tab */ + { 0x0052, KEY_UP }, /* up arrow */ + { 0x0051, KEY_DOWN }, /* down arrow */ + { 0x004f, KEY_RIGHT }, /* right arrow */ + { 0x0050, KEY_LEFT }, /* left arrow */ + { 0x0028, KEY_ENTER }, /* Enter / ok */ + { 0x0252, KEY_VOLUMEUP }, + { 0x0251, KEY_VOLUMEDOWN }, + { 0x004e, KEY_CHANNELDOWN }, + { 0x004b, KEY_CHANNELUP }, + { 0x004a, KEY_RECORD }, + { 0x0111, KEY_PLAY }, + { 0x0017, KEY_PAUSE }, + { 0x000c, KEY_REWIND }, /* FR << */ + { 0x0011, KEY_FASTFORWARD }, /* FF >> */ + { 0x0115, KEY_PREVIOUS }, /* Replay */ + { 0x010e, KEY_NEXT }, /* Skip */ + { 0x0013, KEY_CAMERA }, /* Capture */ + { 0x010f, KEY_LANGUAGE }, /* SAP */ + { 0x0113, KEY_TV2 }, /* PIP */ + { 0x001d, KEY_ZOOM }, /* Full Screen */ + { 0x0117, KEY_SUBTITLE }, /* Subtitle / CC */ + { 0x0010, KEY_MUTE }, + { 0x0119, KEY_AUDIO }, /* L/R */ /* TODO better event */ + { 0x0116, KEY_SLEEP }, /* Hibernate */ + { 0x0116, KEY_SWITCHVIDEOMODE }, /* A/V */ /* TODO does not work */ - { 0x00, 0x06, KEY_AGAIN }, /* Recall */ - { 0x01, 0x16, KEY_KPPLUS }, /* Zoom+ */ /* TODO does not work */ - { 0x01, 0x16, KEY_KPMINUS }, /* Zoom- */ /* TODO does not work */ - { 0x02, 0x15, KEY_RED }, - { 0x02, 0x0a, KEY_GREEN }, - { 0x02, 0x1c, KEY_YELLOW }, - { 0x02, 0x05, KEY_BLUE }, + { 0x0006, KEY_AGAIN }, /* Recall */ + { 0x0116, KEY_KPPLUS }, /* Zoom+ */ /* TODO does not work */ + { 0x0116, KEY_KPMINUS }, /* Zoom- */ /* TODO does not work */ + { 0x0215, KEY_RED }, + { 0x020a, KEY_GREEN }, + { 0x021c, KEY_YELLOW }, + { 0x0205, KEY_BLUE }, }; static u8 af9015_ir_table_twinhan[] = { @@ -304,24 +304,24 @@ static u8 af9015_ir_table_twinhan[] = { /* A-Link DTU(m) */ static struct dvb_usb_rc_key af9015_rc_keys_a_link[] = { - { 0x00, 0x1e, KEY_1 }, - { 0x00, 0x1f, KEY_2 }, - { 0x00, 0x20, KEY_3 }, - { 0x00, 0x21, KEY_4 }, - { 0x00, 0x22, KEY_5 }, - { 0x00, 0x23, KEY_6 }, - { 0x00, 0x24, KEY_7 }, - { 0x00, 0x25, KEY_8 }, - { 0x00, 0x26, KEY_9 }, - { 0x00, 0x27, KEY_0 }, - { 0x00, 0x2e, KEY_CHANNELUP }, - { 0x00, 0x2d, KEY_CHANNELDOWN }, - { 0x04, 0x28, KEY_ZOOM }, - { 0x00, 0x41, KEY_MUTE }, - { 0x00, 0x42, KEY_VOLUMEDOWN }, - { 0x00, 0x43, KEY_VOLUMEUP }, - { 0x00, 0x44, KEY_GOTO }, /* jump */ - { 0x05, 0x45, KEY_POWER }, + { 0x001e, KEY_1 }, + { 0x001f, KEY_2 }, + { 0x0020, KEY_3 }, + { 0x0021, KEY_4 }, + { 0x0022, KEY_5 }, + { 0x0023, KEY_6 }, + { 0x0024, KEY_7 }, + { 0x0025, KEY_8 }, + { 0x0026, KEY_9 }, + { 0x0027, KEY_0 }, + { 0x002e, KEY_CHANNELUP }, + { 0x002d, KEY_CHANNELDOWN }, + { 0x0428, KEY_ZOOM }, + { 0x0041, KEY_MUTE }, + { 0x0042, KEY_VOLUMEDOWN }, + { 0x0043, KEY_VOLUMEUP }, + { 0x0044, KEY_GOTO }, /* jump */ + { 0x0545, KEY_POWER }, }; static u8 af9015_ir_table_a_link[] = { @@ -347,24 +347,24 @@ static u8 af9015_ir_table_a_link[] = { /* MSI DIGIVOX mini II V3.0 */ static struct dvb_usb_rc_key af9015_rc_keys_msi[] = { - { 0x00, 0x1e, KEY_1 }, - { 0x00, 0x1f, KEY_2 }, - { 0x00, 0x20, KEY_3 }, - { 0x00, 0x21, KEY_4 }, - { 0x00, 0x22, KEY_5 }, - { 0x00, 0x23, KEY_6 }, - { 0x00, 0x24, KEY_7 }, - { 0x00, 0x25, KEY_8 }, - { 0x00, 0x26, KEY_9 }, - { 0x00, 0x27, KEY_0 }, - { 0x03, 0x0f, KEY_CHANNELUP }, - { 0x03, 0x0e, KEY_CHANNELDOWN }, - { 0x00, 0x42, KEY_VOLUMEDOWN }, - { 0x00, 0x43, KEY_VOLUMEUP }, - { 0x05, 0x45, KEY_POWER }, - { 0x00, 0x52, KEY_UP }, /* up */ - { 0x00, 0x51, KEY_DOWN }, /* down */ - { 0x00, 0x28, KEY_ENTER }, + { 0x001e, KEY_1 }, + { 0x001f, KEY_2 }, + { 0x0020, KEY_3 }, + { 0x0021, KEY_4 }, + { 0x0022, KEY_5 }, + { 0x0023, KEY_6 }, + { 0x0024, KEY_7 }, + { 0x0025, KEY_8 }, + { 0x0026, KEY_9 }, + { 0x0027, KEY_0 }, + { 0x030f, KEY_CHANNELUP }, + { 0x030e, KEY_CHANNELDOWN }, + { 0x0042, KEY_VOLUMEDOWN }, + { 0x0043, KEY_VOLUMEUP }, + { 0x0545, KEY_POWER }, + { 0x0052, KEY_UP }, /* up */ + { 0x0051, KEY_DOWN }, /* down */ + { 0x0028, KEY_ENTER }, }; static u8 af9015_ir_table_msi[] = { @@ -390,42 +390,42 @@ static u8 af9015_ir_table_msi[] = { /* MYGICTV U718 */ static struct dvb_usb_rc_key af9015_rc_keys_mygictv[] = { - { 0x00, 0x3d, KEY_SWITCHVIDEOMODE }, + { 0x003d, KEY_SWITCHVIDEOMODE }, /* TV / AV */ - { 0x05, 0x45, KEY_POWER }, - { 0x00, 0x1e, KEY_1 }, - { 0x00, 0x1f, KEY_2 }, - { 0x00, 0x20, KEY_3 }, - { 0x00, 0x21, KEY_4 }, - { 0x00, 0x22, KEY_5 }, - { 0x00, 0x23, KEY_6 }, - { 0x00, 0x24, KEY_7 }, - { 0x00, 0x25, KEY_8 }, - { 0x00, 0x26, KEY_9 }, - { 0x00, 0x27, KEY_0 }, - { 0x00, 0x41, KEY_MUTE }, - { 0x00, 0x2a, KEY_ESC }, /* Esc */ - { 0x00, 0x2e, KEY_CHANNELUP }, - { 0x00, 0x2d, KEY_CHANNELDOWN }, - { 0x00, 0x42, KEY_VOLUMEDOWN }, - { 0x00, 0x43, KEY_VOLUMEUP }, - { 0x00, 0x52, KEY_UP }, /* up arrow */ - { 0x00, 0x51, KEY_DOWN }, /* down arrow */ - { 0x00, 0x4f, KEY_RIGHT }, /* right arrow */ - { 0x00, 0x50, KEY_LEFT }, /* left arrow */ - { 0x00, 0x28, KEY_ENTER }, /* ok */ - { 0x01, 0x15, KEY_RECORD }, - { 0x03, 0x13, KEY_PLAY }, - { 0x01, 0x13, KEY_PAUSE }, - { 0x01, 0x16, KEY_STOP }, - { 0x03, 0x07, KEY_REWIND }, /* FR << */ - { 0x03, 0x09, KEY_FASTFORWARD }, /* FF >> */ - { 0x00, 0x3b, KEY_TIME }, /* TimeShift */ - { 0x00, 0x3e, KEY_CAMERA }, /* Snapshot */ - { 0x03, 0x16, KEY_CYCLEWINDOWS }, /* yellow, min / max */ - { 0x00, 0x00, KEY_ZOOM }, /* 'select' (?) */ - { 0x03, 0x16, KEY_SHUFFLE }, /* Shuffle */ - { 0x03, 0x45, KEY_POWER }, + { 0x0545, KEY_POWER }, + { 0x001e, KEY_1 }, + { 0x001f, KEY_2 }, + { 0x0020, KEY_3 }, + { 0x0021, KEY_4 }, + { 0x0022, KEY_5 }, + { 0x0023, KEY_6 }, + { 0x0024, KEY_7 }, + { 0x0025, KEY_8 }, + { 0x0026, KEY_9 }, + { 0x0027, KEY_0 }, + { 0x0041, KEY_MUTE }, + { 0x002a, KEY_ESC }, /* Esc */ + { 0x002e, KEY_CHANNELUP }, + { 0x002d, KEY_CHANNELDOWN }, + { 0x0042, KEY_VOLUMEDOWN }, + { 0x0043, KEY_VOLUMEUP }, + { 0x0052, KEY_UP }, /* up arrow */ + { 0x0051, KEY_DOWN }, /* down arrow */ + { 0x004f, KEY_RIGHT }, /* right arrow */ + { 0x0050, KEY_LEFT }, /* left arrow */ + { 0x0028, KEY_ENTER }, /* ok */ + { 0x0115, KEY_RECORD }, + { 0x0313, KEY_PLAY }, + { 0x0113, KEY_PAUSE }, + { 0x0116, KEY_STOP }, + { 0x0307, KEY_REWIND }, /* FR << */ + { 0x0309, KEY_FASTFORWARD }, /* FF >> */ + { 0x003b, KEY_TIME }, /* TimeShift */ + { 0x003e, KEY_CAMERA }, /* Snapshot */ + { 0x0316, KEY_CYCLEWINDOWS }, /* yellow, min / max */ + { 0x0000, KEY_ZOOM }, /* 'select' (?) */ + { 0x0316, KEY_SHUFFLE }, /* Shuffle */ + { 0x0345, KEY_POWER }, }; static u8 af9015_ir_table_mygictv[] = { @@ -516,41 +516,41 @@ static u8 af9015_ir_table_kworld[] = { /* AverMedia Volar X */ static struct dvb_usb_rc_key af9015_rc_keys_avermedia[] = { - { 0x05, 0x3d, KEY_PROG1 }, /* SOURCE */ - { 0x05, 0x12, KEY_POWER }, /* POWER */ - { 0x05, 0x1e, KEY_1 }, /* 1 */ - { 0x05, 0x1f, KEY_2 }, /* 2 */ - { 0x05, 0x20, KEY_3 }, /* 3 */ - { 0x05, 0x21, KEY_4 }, /* 4 */ - { 0x05, 0x22, KEY_5 }, /* 5 */ - { 0x05, 0x23, KEY_6 }, /* 6 */ - { 0x05, 0x24, KEY_7 }, /* 7 */ - { 0x05, 0x25, KEY_8 }, /* 8 */ - { 0x05, 0x26, KEY_9 }, /* 9 */ - { 0x05, 0x3f, KEY_LEFT }, /* L / DISPLAY */ - { 0x05, 0x27, KEY_0 }, /* 0 */ - { 0x05, 0x0f, KEY_RIGHT }, /* R / CH RTN */ - { 0x05, 0x18, KEY_PROG2 }, /* SNAP SHOT */ - { 0x05, 0x1c, KEY_PROG3 }, /* 16-CH PREV */ - { 0x05, 0x2d, KEY_VOLUMEDOWN }, /* VOL DOWN */ - { 0x05, 0x3e, KEY_ZOOM }, /* FULL SCREEN */ - { 0x05, 0x2e, KEY_VOLUMEUP }, /* VOL UP */ - { 0x05, 0x10, KEY_MUTE }, /* MUTE */ - { 0x05, 0x04, KEY_AUDIO }, /* AUDIO */ - { 0x05, 0x15, KEY_RECORD }, /* RECORD */ - { 0x05, 0x11, KEY_PLAY }, /* PLAY */ - { 0x05, 0x16, KEY_STOP }, /* STOP */ - { 0x05, 0x0c, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */ - { 0x05, 0x05, KEY_BACK }, /* << / RED */ - { 0x05, 0x09, KEY_FORWARD }, /* >> / YELLOW */ - { 0x05, 0x17, KEY_TEXT }, /* TELETEXT */ - { 0x05, 0x0a, KEY_EPG }, /* EPG */ - { 0x05, 0x13, KEY_MENU }, /* MENU */ - - { 0x05, 0x0e, KEY_CHANNELUP }, /* CH UP */ - { 0x05, 0x0d, KEY_CHANNELDOWN }, /* CH DOWN */ - { 0x05, 0x19, KEY_FIRST }, /* |<< / GREEN */ - { 0x05, 0x08, KEY_LAST }, /* >>| / BLUE */ + { 0x053d, KEY_PROG1 }, /* SOURCE */ + { 0x0512, KEY_POWER }, /* POWER */ + { 0x051e, KEY_1 }, /* 1 */ + { 0x051f, KEY_2 }, /* 2 */ + { 0x0520, KEY_3 }, /* 3 */ + { 0x0521, KEY_4 }, /* 4 */ + { 0x0522, KEY_5 }, /* 5 */ + { 0x0523, KEY_6 }, /* 6 */ + { 0x0524, KEY_7 }, /* 7 */ + { 0x0525, KEY_8 }, /* 8 */ + { 0x0526, KEY_9 }, /* 9 */ + { 0x053f, KEY_LEFT }, /* L / DISPLAY */ + { 0x0527, KEY_0 }, /* 0 */ + { 0x050f, KEY_RIGHT }, /* R / CH RTN */ + { 0x0518, KEY_PROG2 }, /* SNAP SHOT */ + { 0x051c, KEY_PROG3 }, /* 16-CH PREV */ + { 0x052d, KEY_VOLUMEDOWN }, /* VOL DOWN */ + { 0x053e, KEY_ZOOM }, /* FULL SCREEN */ + { 0x052e, KEY_VOLUMEUP }, /* VOL UP */ + { 0x0510, KEY_MUTE }, /* MUTE */ + { 0x0504, KEY_AUDIO }, /* AUDIO */ + { 0x0515, KEY_RECORD }, /* RECORD */ + { 0x0511, KEY_PLAY }, /* PLAY */ + { 0x0516, KEY_STOP }, /* STOP */ + { 0x050c, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */ + { 0x0505, KEY_BACK }, /* << / RED */ + { 0x0509, KEY_FORWARD }, /* >> / YELLOW */ + { 0x0517, KEY_TEXT }, /* TELETEXT */ + { 0x050a, KEY_EPG }, /* EPG */ + { 0x0513, KEY_MENU }, /* MENU */ + + { 0x050e, KEY_CHANNELUP }, /* CH UP */ + { 0x050d, KEY_CHANNELDOWN }, /* CH DOWN */ + { 0x0519, KEY_FIRST }, /* |<< / GREEN */ + { 0x0508, KEY_LAST }, /* >>| / BLUE */ }; static u8 af9015_ir_table_avermedia[] = { @@ -622,34 +622,34 @@ static u8 af9015_ir_table_avermedia_ks[] = { /* Digittrade DVB-T USB Stick */ static struct dvb_usb_rc_key af9015_rc_keys_digittrade[] = { - { 0x01, 0x0f, KEY_LAST }, /* RETURN */ - { 0x05, 0x17, KEY_TEXT }, /* TELETEXT */ - { 0x01, 0x08, KEY_EPG }, /* EPG */ - { 0x05, 0x13, KEY_POWER }, /* POWER */ - { 0x01, 0x09, KEY_ZOOM }, /* FULLSCREEN */ - { 0x00, 0x40, KEY_AUDIO }, /* DUAL SOUND */ - { 0x00, 0x2c, KEY_PRINT }, /* SNAPSHOT */ - { 0x05, 0x16, KEY_SUBTITLE }, /* SUBTITLE */ - { 0x00, 0x52, KEY_CHANNELUP }, /* CH Up */ - { 0x00, 0x51, KEY_CHANNELDOWN },/* Ch Dn */ - { 0x00, 0x57, KEY_VOLUMEUP }, /* Vol Up */ - { 0x00, 0x56, KEY_VOLUMEDOWN }, /* Vol Dn */ - { 0x01, 0x10, KEY_MUTE }, /* MUTE */ - { 0x00, 0x27, KEY_0 }, - { 0x00, 0x1e, KEY_1 }, - { 0x00, 0x1f, KEY_2 }, - { 0x00, 0x20, KEY_3 }, - { 0x00, 0x21, KEY_4 }, - { 0x00, 0x22, KEY_5 }, - { 0x00, 0x23, KEY_6 }, - { 0x00, 0x24, KEY_7 }, - { 0x00, 0x25, KEY_8 }, - { 0x00, 0x26, KEY_9 }, - { 0x01, 0x17, KEY_PLAYPAUSE }, /* TIMESHIFT */ - { 0x01, 0x15, KEY_RECORD }, /* RECORD */ - { 0x03, 0x13, KEY_PLAY }, /* PLAY */ - { 0x01, 0x16, KEY_STOP }, /* STOP */ - { 0x01, 0x13, KEY_PAUSE }, /* PAUSE */ + { 0x010f, KEY_LAST }, /* RETURN */ + { 0x0517, KEY_TEXT }, /* TELETEXT */ + { 0x0108, KEY_EPG }, /* EPG */ + { 0x0513, KEY_POWER }, /* POWER */ + { 0x0109, KEY_ZOOM }, /* FULLSCREEN */ + { 0x0040, KEY_AUDIO }, /* DUAL SOUND */ + { 0x002c, KEY_PRINT }, /* SNAPSHOT */ + { 0x0516, KEY_SUBTITLE }, /* SUBTITLE */ + { 0x0052, KEY_CHANNELUP }, /* CH Up */ + { 0x0051, KEY_CHANNELDOWN },/* Ch Dn */ + { 0x0057, KEY_VOLUMEUP }, /* Vol Up */ + { 0x0056, KEY_VOLUMEDOWN }, /* Vol Dn */ + { 0x0110, KEY_MUTE }, /* MUTE */ + { 0x0027, KEY_0 }, + { 0x001e, KEY_1 }, + { 0x001f, KEY_2 }, + { 0x0020, KEY_3 }, + { 0x0021, KEY_4 }, + { 0x0022, KEY_5 }, + { 0x0023, KEY_6 }, + { 0x0024, KEY_7 }, + { 0x0025, KEY_8 }, + { 0x0026, KEY_9 }, + { 0x0117, KEY_PLAYPAUSE }, /* TIMESHIFT */ + { 0x0115, KEY_RECORD }, /* RECORD */ + { 0x0313, KEY_PLAY }, /* PLAY */ + { 0x0116, KEY_STOP }, /* STOP */ + { 0x0113, KEY_PAUSE }, /* PAUSE */ }; static u8 af9015_ir_table_digittrade[] = { @@ -685,34 +685,34 @@ static u8 af9015_ir_table_digittrade[] = { /* TREKSTOR DVB-T USB Stick */ static struct dvb_usb_rc_key af9015_rc_keys_trekstor[] = { - { 0x07, 0x04, KEY_AGAIN }, /* Home */ - { 0x07, 0x05, KEY_MUTE }, /* Mute */ - { 0x07, 0x06, KEY_UP }, /* Up */ - { 0x07, 0x07, KEY_DOWN }, /* Down */ - { 0x07, 0x09, KEY_RIGHT }, /* Right */ - { 0x07, 0x0a, KEY_ENTER }, /* OK */ - { 0x07, 0x0b, KEY_FASTFORWARD }, /* Fast forward */ - { 0x07, 0x0c, KEY_REWIND }, /* Rewind */ - { 0x07, 0x0d, KEY_PLAY }, /* Play/Pause */ - { 0x07, 0x0e, KEY_VOLUMEUP }, /* Volume + */ - { 0x07, 0x0f, KEY_VOLUMEDOWN }, /* Volume - */ - { 0x07, 0x10, KEY_RECORD }, /* Record */ - { 0x07, 0x11, KEY_STOP }, /* Stop */ - { 0x07, 0x12, KEY_ZOOM }, /* TV */ - { 0x07, 0x13, KEY_EPG }, /* Info/EPG */ - { 0x07, 0x14, KEY_CHANNELDOWN }, /* Channel - */ - { 0x07, 0x15, KEY_CHANNELUP }, /* Channel + */ - { 0x07, 0x1e, KEY_1 }, - { 0x07, 0x1f, KEY_2 }, - { 0x07, 0x20, KEY_3 }, - { 0x07, 0x21, KEY_4 }, - { 0x07, 0x22, KEY_5 }, - { 0x07, 0x23, KEY_6 }, - { 0x07, 0x24, KEY_7 }, - { 0x07, 0x25, KEY_8 }, - { 0x07, 0x26, KEY_9 }, - { 0x07, 0x08, KEY_LEFT }, /* LEFT */ - { 0x07, 0x27, KEY_0 }, + { 0x0704, KEY_AGAIN }, /* Home */ + { 0x0705, KEY_MUTE }, /* Mute */ + { 0x0706, KEY_UP }, /* Up */ + { 0x0707, KEY_DOWN }, /* Down */ + { 0x0709, KEY_RIGHT }, /* Right */ + { 0x070a, KEY_ENTER }, /* OK */ + { 0x070b, KEY_FASTFORWARD }, /* Fast forward */ + { 0x070c, KEY_REWIND }, /* Rewind */ + { 0x070d, KEY_PLAY }, /* Play/Pause */ + { 0x070e, KEY_VOLUMEUP }, /* Volume + */ + { 0x070f, KEY_VOLUMEDOWN }, /* Volume - */ + { 0x0710, KEY_RECORD }, /* Record */ + { 0x0711, KEY_STOP }, /* Stop */ + { 0x0712, KEY_ZOOM }, /* TV */ + { 0x0713, KEY_EPG }, /* Info/EPG */ + { 0x0714, KEY_CHANNELDOWN }, /* Channel - */ + { 0x0715, KEY_CHANNELUP }, /* Channel + */ + { 0x071e, KEY_1 }, + { 0x071f, KEY_2 }, + { 0x0720, KEY_3 }, + { 0x0721, KEY_4 }, + { 0x0722, KEY_5 }, + { 0x0723, KEY_6 }, + { 0x0724, KEY_7 }, + { 0x0725, KEY_8 }, + { 0x0726, KEY_9 }, + { 0x0708, KEY_LEFT }, /* LEFT */ + { 0x0727, KEY_0 }, }; static u8 af9015_ir_table_trekstor[] = { diff --git a/linux/drivers/media/dvb/dvb-usb/anysee.c b/linux/drivers/media/dvb/dvb-usb/anysee.c index e96d4fc7a..1211c81ce 100644 --- a/linux/drivers/media/dvb/dvb-usb/anysee.c +++ b/linux/drivers/media/dvb/dvb-usb/anysee.c @@ -392,8 +392,8 @@ static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state) *state = REMOTE_NO_KEY_PRESSED; for (i = 0; i < d->props.rc_key_map_size; i++) { - if (keymap[i].custom == ircode[0] && - keymap[i].data == ircode[1]) { + if (rc5_custom(&keymap[i]) == ircode[0] && + rc5_data(&keymap[i]) == ircode[1]) { *event = keymap[i].event; *state = REMOTE_KEY_PRESSED; return 0; @@ -403,50 +403,50 @@ static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state) } static struct dvb_usb_rc_key anysee_rc_keys[] = { - { 0x01, 0x00, KEY_0 }, - { 0x01, 0x01, KEY_1 }, - { 0x01, 0x02, KEY_2 }, - { 0x01, 0x03, KEY_3 }, - { 0x01, 0x04, KEY_4 }, - { 0x01, 0x05, KEY_5 }, - { 0x01, 0x06, KEY_6 }, - { 0x01, 0x07, KEY_7 }, - { 0x01, 0x08, KEY_8 }, - { 0x01, 0x09, KEY_9 }, - { 0x01, 0x0a, KEY_POWER }, - { 0x01, 0x0b, KEY_DOCUMENTS }, /* * */ - { 0x01, 0x19, KEY_FAVORITES }, - { 0x01, 0x20, KEY_SLEEP }, - { 0x01, 0x21, KEY_MODE }, /* 4:3 / 16:9 select */ - { 0x01, 0x22, KEY_ZOOM }, - { 0x01, 0x47, KEY_TEXT }, - { 0x01, 0x16, KEY_TV }, /* TV / radio select */ - { 0x01, 0x1e, KEY_LANGUAGE }, /* Second Audio Program */ - { 0x01, 0x1a, KEY_SUBTITLE }, - { 0x01, 0x1b, KEY_CAMERA }, /* screenshot */ - { 0x01, 0x42, KEY_MUTE }, - { 0x01, 0x0e, KEY_MENU }, - { 0x01, 0x0f, KEY_EPG }, - { 0x01, 0x17, KEY_INFO }, - { 0x01, 0x10, KEY_EXIT }, - { 0x01, 0x13, KEY_VOLUMEUP }, - { 0x01, 0x12, KEY_VOLUMEDOWN }, - { 0x01, 0x11, KEY_CHANNELUP }, - { 0x01, 0x14, KEY_CHANNELDOWN }, - { 0x01, 0x15, KEY_OK }, - { 0x01, 0x1d, KEY_RED }, - { 0x01, 0x1f, KEY_GREEN }, - { 0x01, 0x1c, KEY_YELLOW }, - { 0x01, 0x44, KEY_BLUE }, - { 0x01, 0x0c, KEY_SHUFFLE }, /* snapshot */ - { 0x01, 0x48, KEY_STOP }, - { 0x01, 0x50, KEY_PLAY }, - { 0x01, 0x51, KEY_PAUSE }, - { 0x01, 0x49, KEY_RECORD }, - { 0x01, 0x18, KEY_PREVIOUS }, /* |<< */ - { 0x01, 0x0d, KEY_NEXT }, /* >>| */ - { 0x01, 0x24, KEY_PROG1 }, /* F1 */ - { 0x01, 0x25, KEY_PROG2 }, /* F2 */ + { 0x0100, KEY_0 }, + { 0x0101, KEY_1 }, + { 0x0102, KEY_2 }, + { 0x0103, KEY_3 }, + { 0x0104, KEY_4 }, + { 0x0105, KEY_5 }, + { 0x0106, KEY_6 }, + { 0x0107, KEY_7 }, + { 0x0108, KEY_8 }, + { 0x0109, KEY_9 }, + { 0x010a, KEY_POWER }, + { 0x010b, KEY_DOCUMENTS }, /* * */ + { 0x0119, KEY_FAVORITES }, + { 0x0120, KEY_SLEEP }, + { 0x0121, KEY_MODE }, /* 4:3 / 16:9 select */ + { 0x0122, KEY_ZOOM }, + { 0x0147, KEY_TEXT }, + { 0x0116, KEY_TV }, /* TV / radio select */ + { 0x011e, KEY_LANGUAGE }, /* Second Audio Program */ + { 0x011a, KEY_SUBTITLE }, + { 0x011b, KEY_CAMERA }, /* screenshot */ + { 0x0142, KEY_MUTE }, + { 0x010e, KEY_MENU }, + { 0x010f, KEY_EPG }, + { 0x0117, KEY_INFO }, + { 0x0110, KEY_EXIT }, + { 0x0113, KEY_VOLUMEUP }, + { 0x0112, KEY_VOLUMEDOWN }, + { 0x0111, KEY_CHANNELUP }, + { 0x0114, KEY_CHANNELDOWN }, + { 0x0115, KEY_OK }, + { 0x011d, KEY_RED }, + { 0x011f, KEY_GREEN }, + { 0x011c, KEY_YELLOW }, + { 0x0144, KEY_BLUE }, + { 0x010c, KEY_SHUFFLE }, /* snapshot */ + { 0x0148, KEY_STOP }, + { 0x0150, KEY_PLAY }, + { 0x0151, KEY_PAUSE }, + { 0x0149, KEY_RECORD }, + { 0x0118, KEY_PREVIOUS }, /* |<< */ + { 0x010d, KEY_NEXT }, /* >>| */ + { 0x0124, KEY_PROG1 }, /* F1 */ + { 0x0125, KEY_PROG2 }, /* F2 */ }; /* DVB USB Driver stuff */ diff --git a/linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c index 80e37a0d0..e37ac4d48 100644 --- a/linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c +++ b/linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c @@ -85,43 +85,43 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) } static struct dvb_usb_rc_key cinergyt2_rc_keys[] = { - { 0x04, 0x01, KEY_POWER }, - { 0x04, 0x02, KEY_1 }, - { 0x04, 0x03, KEY_2 }, - { 0x04, 0x04, KEY_3 }, - { 0x04, 0x05, KEY_4 }, - { 0x04, 0x06, KEY_5 }, - { 0x04, 0x07, KEY_6 }, - { 0x04, 0x08, KEY_7 }, - { 0x04, 0x09, KEY_8 }, - { 0x04, 0x0a, KEY_9 }, - { 0x04, 0x0c, KEY_0 }, - { 0x04, 0x0b, KEY_VIDEO }, - { 0x04, 0x0d, KEY_REFRESH }, - { 0x04, 0x0e, KEY_SELECT }, - { 0x04, 0x0f, KEY_EPG }, - { 0x04, 0x10, KEY_UP }, - { 0x04, 0x14, KEY_DOWN }, - { 0x04, 0x11, KEY_LEFT }, - { 0x04, 0x13, KEY_RIGHT }, - { 0x04, 0x12, KEY_OK }, - { 0x04, 0x15, KEY_TEXT }, - { 0x04, 0x16, KEY_INFO }, - { 0x04, 0x17, KEY_RED }, - { 0x04, 0x18, KEY_GREEN }, - { 0x04, 0x19, KEY_YELLOW }, - { 0x04, 0x1a, KEY_BLUE }, - { 0x04, 0x1c, KEY_VOLUMEUP }, - { 0x04, 0x1e, KEY_VOLUMEDOWN }, - { 0x04, 0x1d, KEY_MUTE }, - { 0x04, 0x1b, KEY_CHANNELUP }, - { 0x04, 0x1f, KEY_CHANNELDOWN }, - { 0x04, 0x40, KEY_PAUSE }, - { 0x04, 0x4c, KEY_PLAY }, - { 0x04, 0x58, KEY_RECORD }, - { 0x04, 0x54, KEY_PREVIOUS }, - { 0x04, 0x48, KEY_STOP }, - { 0x04, 0x5c, KEY_NEXT } + { 0x0401, KEY_POWER }, + { 0x0402, KEY_1 }, + { 0x0403, KEY_2 }, + { 0x0404, KEY_3 }, + { 0x0405, KEY_4 }, + { 0x0406, KEY_5 }, + { 0x0407, KEY_6 }, + { 0x0408, KEY_7 }, + { 0x0409, KEY_8 }, + { 0x040a, KEY_9 }, + { 0x040c, KEY_0 }, + { 0x040b, KEY_VIDEO }, + { 0x040d, KEY_REFRESH }, + { 0x040e, KEY_SELECT }, + { 0x040f, KEY_EPG }, + { 0x0410, KEY_UP }, + { 0x0414, KEY_DOWN }, + { 0x0411, KEY_LEFT }, + { 0x0413, KEY_RIGHT }, + { 0x0412, KEY_OK }, + { 0x0415, KEY_TEXT }, + { 0x0416, KEY_INFO }, + { 0x0417, KEY_RED }, + { 0x0418, KEY_GREEN }, + { 0x0419, KEY_YELLOW }, + { 0x041a, KEY_BLUE }, + { 0x041c, KEY_VOLUMEUP }, + { 0x041e, KEY_VOLUMEDOWN }, + { 0x041d, KEY_MUTE }, + { 0x041b, KEY_CHANNELUP }, + { 0x041f, KEY_CHANNELDOWN }, + { 0x0440, KEY_PAUSE }, + { 0x044c, KEY_PLAY }, + { 0x0458, KEY_RECORD }, + { 0x0454, KEY_PREVIOUS }, + { 0x0448, KEY_STOP }, + { 0x045c, KEY_NEXT } }; /* Number of keypresses to ignore before detect repeating */ diff --git a/linux/drivers/media/dvb/dvb-usb/cxusb.c b/linux/drivers/media/dvb/dvb-usb/cxusb.c index 05da84c90..ea1a8c5b3 100644 --- a/linux/drivers/media/dvb/dvb-usb/cxusb.c +++ b/linux/drivers/media/dvb/dvb-usb/cxusb.c @@ -395,8 +395,8 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) *state = REMOTE_NO_KEY_PRESSED; for (i = 0; i < d->props.rc_key_map_size; i++) { - if (keymap[i].custom == ircode[2] && - keymap[i].data == ircode[3]) { + if (rc5_custom(&keymap[i]) == ircode[2] && + rc5_data(&keymap[i]) == ircode[3]) { *event = keymap[i].event; *state = REMOTE_KEY_PRESSED; @@ -423,8 +423,8 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event, return 0; for (i = 0; i < d->props.rc_key_map_size; i++) { - if (keymap[i].custom == ircode[1] && - keymap[i].data == ircode[2]) { + if (rc5_custom(&keymap[i]) == ircode[1] && + rc5_data(&keymap[i]) == ircode[2]) { *event = keymap[i].event; *state = REMOTE_KEY_PRESSED; @@ -449,8 +449,8 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, return 0; for (i = 0; i < d->props.rc_key_map_size; i++) { - if (keymap[i].custom == ircode[0] && - keymap[i].data == ircode[1]) { + if (rc5_custom(&keymap[i]) == ircode[0] && + rc5_data(&keymap[i]) == ircode[1]) { *event = keymap[i].event; *state = REMOTE_KEY_PRESSED; @@ -462,128 +462,128 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, } static struct dvb_usb_rc_key dvico_mce_rc_keys[] = { - { 0xfe, 0x02, KEY_TV }, - { 0xfe, 0x0e, KEY_MP3 }, - { 0xfe, 0x1a, KEY_DVD }, - { 0xfe, 0x1e, KEY_FAVORITES }, - { 0xfe, 0x16, KEY_SETUP }, - { 0xfe, 0x46, KEY_POWER2 }, - { 0xfe, 0x0a, KEY_EPG }, - { 0xfe, 0x49, KEY_BACK }, - { 0xfe, 0x4d, KEY_MENU }, - { 0xfe, 0x51, KEY_UP }, - { 0xfe, 0x5b, KEY_LEFT }, - { 0xfe, 0x5f, KEY_RIGHT }, - { 0xfe, 0x53, KEY_DOWN }, - { 0xfe, 0x5e, KEY_OK }, - { 0xfe, 0x59, KEY_INFO }, - { 0xfe, 0x55, KEY_TAB }, - { 0xfe, 0x0f, KEY_PREVIOUSSONG },/* Replay */ - { 0xfe, 0x12, KEY_NEXTSONG }, /* Skip */ - { 0xfe, 0x42, KEY_ENTER }, /* Windows/Start */ - { 0xfe, 0x15, KEY_VOLUMEUP }, - { 0xfe, 0x05, KEY_VOLUMEDOWN }, - { 0xfe, 0x11, KEY_CHANNELUP }, - { 0xfe, 0x09, KEY_CHANNELDOWN }, - { 0xfe, 0x52, KEY_CAMERA }, - { 0xfe, 0x5a, KEY_TUNER }, /* Live */ - { 0xfe, 0x19, KEY_OPEN }, - { 0xfe, 0x0b, KEY_1 }, - { 0xfe, 0x17, KEY_2 }, - { 0xfe, 0x1b, KEY_3 }, - { 0xfe, 0x07, KEY_4 }, - { 0xfe, 0x50, KEY_5 }, - { 0xfe, 0x54, KEY_6 }, - { 0xfe, 0x48, KEY_7 }, - { 0xfe, 0x4c, KEY_8 }, - { 0xfe, 0x58, KEY_9 }, - { 0xfe, 0x13, KEY_ANGLE }, /* Aspect */ - { 0xfe, 0x03, KEY_0 }, - { 0xfe, 0x1f, KEY_ZOOM }, - { 0xfe, 0x43, KEY_REWIND }, - { 0xfe, 0x47, KEY_PLAYPAUSE }, - { 0xfe, 0x4f, KEY_FASTFORWARD }, - { 0xfe, 0x57, KEY_MUTE }, - { 0xfe, 0x0d, KEY_STOP }, - { 0xfe, 0x01, KEY_RECORD }, - { 0xfe, 0x4e, KEY_POWER }, + { 0xfe02, KEY_TV }, + { 0xfe0e, KEY_MP3 }, + { 0xfe1a, KEY_DVD }, + { 0xfe1e, KEY_FAVORITES }, + { 0xfe16, KEY_SETUP }, + { 0xfe46, KEY_POWER2 }, + { 0xfe0a, KEY_EPG }, + { 0xfe49, KEY_BACK }, + { 0xfe4d, KEY_MENU }, + { 0xfe51, KEY_UP }, + { 0xfe5b, KEY_LEFT }, + { 0xfe5f, KEY_RIGHT }, + { 0xfe53, KEY_DOWN }, + { 0xfe5e, KEY_OK }, + { 0xfe59, KEY_INFO }, + { 0xfe55, KEY_TAB }, + { 0xfe0f, KEY_PREVIOUSSONG },/* Replay */ + { 0xfe12, KEY_NEXTSONG }, /* Skip */ + { 0xfe42, KEY_ENTER }, /* Windows/Start */ + { 0xfe15, KEY_VOLUMEUP }, + { 0xfe05, KEY_VOLUMEDOWN }, + { 0xfe11, KEY_CHANNELUP }, + { 0xfe09, KEY_CHANNELDOWN }, + { 0xfe52, KEY_CAMERA }, + { 0xfe5a, KEY_TUNER }, /* Live */ + { 0xfe19, KEY_OPEN }, + { 0xfe0b, KEY_1 }, + { 0xfe17, KEY_2 }, + { 0xfe1b, KEY_3 }, + { 0xfe07, KEY_4 }, + { 0xfe50, KEY_5 }, + { 0xfe54, KEY_6 }, + { 0xfe48, KEY_7 }, + { 0xfe4c, KEY_8 }, + { 0xfe58, KEY_9 }, + { 0xfe13, KEY_ANGLE }, /* Aspect */ + { 0xfe03, KEY_0 }, + { 0xfe1f, KEY_ZOOM }, + { 0xfe43, KEY_REWIND }, + { 0xfe47, KEY_PLAYPAUSE }, + { 0xfe4f, KEY_FASTFORWARD }, + { 0xfe57, KEY_MUTE }, + { 0xfe0d, KEY_STOP }, + { 0xfe01, KEY_RECORD }, + { 0xfe4e, KEY_POWER }, }; static struct dvb_usb_rc_key dvico_portable_rc_keys[] = { - { 0xfc, 0x02, KEY_SETUP }, /* Profile */ - { 0xfc, 0x43, KEY_POWER2 }, - { 0xfc, 0x06, KEY_EPG }, - { 0xfc, 0x5a, KEY_BACK }, - { 0xfc, 0x05, KEY_MENU }, - { 0xfc, 0x47, KEY_INFO }, - { 0xfc, 0x01, KEY_TAB }, - { 0xfc, 0x42, KEY_PREVIOUSSONG },/* Replay */ - { 0xfc, 0x49, KEY_VOLUMEUP }, - { 0xfc, 0x09, KEY_VOLUMEDOWN }, - { 0xfc, 0x54, KEY_CHANNELUP }, - { 0xfc, 0x0b, KEY_CHANNELDOWN }, - { 0xfc, 0x16, KEY_CAMERA }, - { 0xfc, 0x40, KEY_TUNER }, /* ATV/DTV */ - { 0xfc, 0x45, KEY_OPEN }, - { 0xfc, 0x19, KEY_1 }, - { 0xfc, 0x18, KEY_2 }, - { 0xfc, 0x1b, KEY_3 }, - { 0xfc, 0x1a, KEY_4 }, - { 0xfc, 0x58, KEY_5 }, - { 0xfc, 0x59, KEY_6 }, - { 0xfc, 0x15, KEY_7 }, - { 0xfc, 0x14, KEY_8 }, - { 0xfc, 0x17, KEY_9 }, - { 0xfc, 0x44, KEY_ANGLE }, /* Aspect */ - { 0xfc, 0x55, KEY_0 }, - { 0xfc, 0x07, KEY_ZOOM }, - { 0xfc, 0x0a, KEY_REWIND }, - { 0xfc, 0x08, KEY_PLAYPAUSE }, - { 0xfc, 0x4b, KEY_FASTFORWARD }, - { 0xfc, 0x5b, KEY_MUTE }, - { 0xfc, 0x04, KEY_STOP }, - { 0xfc, 0x56, KEY_RECORD }, - { 0xfc, 0x57, KEY_POWER }, - { 0xfc, 0x41, KEY_UNKNOWN }, /* INPUT */ - { 0xfc, 0x00, KEY_UNKNOWN }, /* HD */ + { 0xfc02, KEY_SETUP }, /* Profile */ + { 0xfc43, KEY_POWER2 }, + { 0xfc06, KEY_EPG }, + { 0xfc5a, KEY_BACK }, + { 0xfc05, KEY_MENU }, + { 0xfc47, KEY_INFO }, + { 0xfc01, KEY_TAB }, + { 0xfc42, KEY_PREVIOUSSONG },/* Replay */ + { 0xfc49, KEY_VOLUMEUP }, + { 0xfc09, KEY_VOLUMEDOWN }, + { 0xfc54, KEY_CHANNELUP }, + { 0xfc0b, KEY_CHANNELDOWN }, + { 0xfc16, KEY_CAMERA }, + { 0xfc40, KEY_TUNER }, /* ATV/DTV */ + { 0xfc45, KEY_OPEN }, + { 0xfc19, KEY_1 }, + { 0xfc18, KEY_2 }, + { 0xfc1b, KEY_3 }, + { 0xfc1a, KEY_4 }, + { 0xfc58, KEY_5 }, + { 0xfc59, KEY_6 }, + { 0xfc15, KEY_7 }, + { 0xfc14, KEY_8 }, + { 0xfc17, KEY_9 }, + { 0xfc44, KEY_ANGLE }, /* Aspect */ + { 0xfc55, KEY_0 }, + { 0xfc07, KEY_ZOOM }, + { 0xfc0a, KEY_REWIND }, + { 0xfc08, KEY_PLAYPAUSE }, + { 0xfc4b, KEY_FASTFORWARD }, + { 0xfc5b, KEY_MUTE }, + { 0xfc04, KEY_STOP }, + { 0xfc56, KEY_RECORD }, + { 0xfc57, KEY_POWER }, + { 0xfc41, KEY_UNKNOWN }, /* INPUT */ + { 0xfc00, KEY_UNKNOWN }, /* HD */ }; static struct dvb_usb_rc_key d680_dmb_rc_keys[] = { - { 0x00, 0x38, KEY_UNKNOWN }, /* TV/AV */ - { 0x08, 0x0c, KEY_ZOOM }, - { 0x08, 0x00, KEY_0 }, - { 0x00, 0x01, KEY_1 }, - { 0x08, 0x02, KEY_2 }, - { 0x00, 0x03, KEY_3 }, - { 0x08, 0x04, KEY_4 }, - { 0x00, 0x05, KEY_5 }, - { 0x08, 0x06, KEY_6 }, - { 0x00, 0x07, KEY_7 }, - { 0x08, 0x08, KEY_8 }, - { 0x00, 0x09, KEY_9 }, - { 0x00, 0x0a, KEY_MUTE }, - { 0x08, 0x29, KEY_BACK }, - { 0x00, 0x12, KEY_CHANNELUP }, - { 0x08, 0x13, KEY_CHANNELDOWN }, - { 0x00, 0x2b, KEY_VOLUMEUP }, - { 0x08, 0x2c, KEY_VOLUMEDOWN }, - { 0x00, 0x20, KEY_UP }, - { 0x08, 0x21, KEY_DOWN }, - { 0x00, 0x11, KEY_LEFT }, - { 0x08, 0x10, KEY_RIGHT }, - { 0x00, 0x0d, KEY_OK }, - { 0x08, 0x1f, KEY_RECORD }, - { 0x00, 0x17, KEY_PLAYPAUSE }, - { 0x08, 0x16, KEY_PLAYPAUSE }, - { 0x00, 0x0b, KEY_STOP }, - { 0x08, 0x27, KEY_FASTFORWARD }, - { 0x00, 0x26, KEY_REWIND }, - { 0x08, 0x1e, KEY_UNKNOWN }, /* Time Shift */ - { 0x00, 0x0e, KEY_UNKNOWN }, /* Snapshot */ - { 0x08, 0x2d, KEY_UNKNOWN }, /* Mouse Cursor */ - { 0x00, 0x0f, KEY_UNKNOWN }, /* Minimize/Maximize */ - { 0x08, 0x14, KEY_UNKNOWN }, /* Shuffle */ - { 0x00, 0x25, KEY_POWER }, + { 0x0038, KEY_UNKNOWN }, /* TV/AV */ + { 0x080c, KEY_ZOOM }, + { 0x0800, KEY_0 }, + { 0x0001, KEY_1 }, + { 0x0802, KEY_2 }, + { 0x0003, KEY_3 }, + { 0x0804, KEY_4 }, + { 0x0005, KEY_5 }, + { 0x0806, KEY_6 }, + { 0x0007, KEY_7 }, + { 0x0808, KEY_8 }, + { 0x0009, KEY_9 }, + { 0x000a, KEY_MUTE }, + { 0x0829, KEY_BACK }, + { 0x0012, KEY_CHANNELUP }, + { 0x0813, KEY_CHANNELDOWN }, + { 0x002b, KEY_VOLUMEUP }, + { 0x082c, KEY_VOLUMEDOWN }, + { 0x0020, KEY_UP }, + { 0x0821, KEY_DOWN }, + { 0x0011, KEY_LEFT }, + { 0x0810, KEY_RIGHT }, + { 0x000d, KEY_OK }, + { 0x081f, KEY_RECORD }, + { 0x0017, KEY_PLAYPAUSE }, + { 0x0816, KEY_PLAYPAUSE }, + { 0x000b, KEY_STOP }, + { 0x0827, KEY_FASTFORWARD }, + { 0x0026, KEY_REWIND }, + { 0x081e, KEY_UNKNOWN }, /* Time Shift */ + { 0x000e, KEY_UNKNOWN }, /* Snapshot */ + { 0x082d, KEY_UNKNOWN }, /* Mouse Cursor */ + { 0x000f, KEY_UNKNOWN }, /* Minimize/Maximize */ + { 0x0814, KEY_UNKNOWN }, /* Shuffle */ + { 0x0025, KEY_POWER }, }; static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index 4de8f0248..d4da73e7f 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -509,7 +509,8 @@ static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event, return 0; } for (i=0;iprops.rc_key_map_size; i++) { - if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) { + if (rc5_custom(&keymap[i]) == key[3-2] && + rc5_data(&keymap[i]) == key[3-3]) { st->rc_counter = 0; *event = keymap[i].event; *state = REMOTE_KEY_PRESSED; @@ -522,7 +523,8 @@ static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event, default: { /* RC-5 protocol changes toggle bit on new keypress */ for (i = 0; i < d->props.rc_key_map_size; i++) { - if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) { + if (rc5_custom(&keymap[i]) == key[3-2] && + rc5_data(&keymap[i]) == key[3-3]) { if (d->last_event == keymap[i].event && key[3-1] == st->rc_toggle) { st->rc_counter++; @@ -616,8 +618,8 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, /* Find the key in the map */ for (i = 0; i < d->props.rc_key_map_size; i++) { - if (keymap[i].custom == poll_reply.system_lsb && - keymap[i].data == poll_reply.data) { + if (rc5_custom(&keymap[i]) == poll_reply.system_lsb && + rc5_data(&keymap[i]) == poll_reply.data) { *event = keymap[i].event; found = 1; break; @@ -684,193 +686,193 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) static struct dvb_usb_rc_key dib0700_rc_keys[] = { /* Key codes for the tiny Pinnacle remote*/ - { 0x07, 0x00, KEY_MUTE }, - { 0x07, 0x01, KEY_MENU }, // Pinnacle logo - { 0x07, 0x39, KEY_POWER }, - { 0x07, 0x03, KEY_VOLUMEUP }, - { 0x07, 0x09, KEY_VOLUMEDOWN }, - { 0x07, 0x06, KEY_CHANNELUP }, - { 0x07, 0x0c, KEY_CHANNELDOWN }, - { 0x07, 0x0f, KEY_1 }, - { 0x07, 0x15, KEY_2 }, - { 0x07, 0x10, KEY_3 }, - { 0x07, 0x18, KEY_4 }, - { 0x07, 0x1b, KEY_5 }, - { 0x07, 0x1e, KEY_6 }, - { 0x07, 0x11, KEY_7 }, - { 0x07, 0x21, KEY_8 }, - { 0x07, 0x12, KEY_9 }, - { 0x07, 0x27, KEY_0 }, - { 0x07, 0x24, KEY_SCREEN }, // 'Square' key - { 0x07, 0x2a, KEY_TEXT }, // 'T' key - { 0x07, 0x2d, KEY_REWIND }, - { 0x07, 0x30, KEY_PLAY }, - { 0x07, 0x33, KEY_FASTFORWARD }, - { 0x07, 0x36, KEY_RECORD }, - { 0x07, 0x3c, KEY_STOP }, - { 0x07, 0x3f, KEY_CANCEL }, // '?' key + { 0x0700, KEY_MUTE }, + { 0x0701, KEY_MENU }, /* Pinnacle logo */ + { 0x0739, KEY_POWER }, + { 0x0703, KEY_VOLUMEUP }, + { 0x0709, KEY_VOLUMEDOWN }, + { 0x0706, KEY_CHANNELUP }, + { 0x070c, KEY_CHANNELDOWN }, + { 0x070f, KEY_1 }, + { 0x0715, KEY_2 }, + { 0x0710, KEY_3 }, + { 0x0718, KEY_4 }, + { 0x071b, KEY_5 }, + { 0x071e, KEY_6 }, + { 0x0711, KEY_7 }, + { 0x0721, KEY_8 }, + { 0x0712, KEY_9 }, + { 0x0727, KEY_0 }, + { 0x0724, KEY_SCREEN }, /* 'Square' key */ + { 0x072a, KEY_TEXT }, /* 'T' key */ + { 0x072d, KEY_REWIND }, + { 0x0730, KEY_PLAY }, + { 0x0733, KEY_FASTFORWARD }, + { 0x0736, KEY_RECORD }, + { 0x073c, KEY_STOP }, + { 0x073f, KEY_CANCEL }, /* '?' key */ /* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */ - { 0xeb, 0x01, KEY_POWER }, - { 0xeb, 0x02, KEY_1 }, - { 0xeb, 0x03, KEY_2 }, - { 0xeb, 0x04, KEY_3 }, - { 0xeb, 0x05, KEY_4 }, - { 0xeb, 0x06, KEY_5 }, - { 0xeb, 0x07, KEY_6 }, - { 0xeb, 0x08, KEY_7 }, - { 0xeb, 0x09, KEY_8 }, - { 0xeb, 0x0a, KEY_9 }, - { 0xeb, 0x0b, KEY_VIDEO }, - { 0xeb, 0x0c, KEY_0 }, - { 0xeb, 0x0d, KEY_REFRESH }, - { 0xeb, 0x0f, KEY_EPG }, - { 0xeb, 0x10, KEY_UP }, - { 0xeb, 0x11, KEY_LEFT }, - { 0xeb, 0x12, KEY_OK }, - { 0xeb, 0x13, KEY_RIGHT }, - { 0xeb, 0x14, KEY_DOWN }, - { 0xeb, 0x16, KEY_INFO }, - { 0xeb, 0x17, KEY_RED }, - { 0xeb, 0x18, KEY_GREEN }, - { 0xeb, 0x19, KEY_YELLOW }, - { 0xeb, 0x1a, KEY_BLUE }, - { 0xeb, 0x1b, KEY_CHANNELUP }, - { 0xeb, 0x1c, KEY_VOLUMEUP }, - { 0xeb, 0x1d, KEY_MUTE }, - { 0xeb, 0x1e, KEY_VOLUMEDOWN }, - { 0xeb, 0x1f, KEY_CHANNELDOWN }, - { 0xeb, 0x40, KEY_PAUSE }, - { 0xeb, 0x41, KEY_HOME }, - { 0xeb, 0x42, KEY_MENU }, /* DVD Menu */ - { 0xeb, 0x43, KEY_SUBTITLE }, - { 0xeb, 0x44, KEY_TEXT }, /* Teletext */ - { 0xeb, 0x45, KEY_DELETE }, - { 0xeb, 0x46, KEY_TV }, - { 0xeb, 0x47, KEY_DVD }, - { 0xeb, 0x48, KEY_STOP }, - { 0xeb, 0x49, KEY_VIDEO }, - { 0xeb, 0x4a, KEY_AUDIO }, /* Music */ - { 0xeb, 0x4b, KEY_SCREEN }, /* Pic */ - { 0xeb, 0x4c, KEY_PLAY }, - { 0xeb, 0x4d, KEY_BACK }, - { 0xeb, 0x4e, KEY_REWIND }, - { 0xeb, 0x4f, KEY_FASTFORWARD }, - { 0xeb, 0x54, KEY_PREVIOUS }, - { 0xeb, 0x58, KEY_RECORD }, - { 0xeb, 0x5c, KEY_NEXT }, + { 0xeb01, KEY_POWER }, + { 0xeb02, KEY_1 }, + { 0xeb03, KEY_2 }, + { 0xeb04, KEY_3 }, + { 0xeb05, KEY_4 }, + { 0xeb06, KEY_5 }, + { 0xeb07, KEY_6 }, + { 0xeb08, KEY_7 }, + { 0xeb09, KEY_8 }, + { 0xeb0a, KEY_9 }, + { 0xeb0b, KEY_VIDEO }, + { 0xeb0c, KEY_0 }, + { 0xeb0d, KEY_REFRESH }, + { 0xeb0f, KEY_EPG }, + { 0xeb10, KEY_UP }, + { 0xeb11, KEY_LEFT }, + { 0xeb12, KEY_OK }, + { 0xeb13, KEY_RIGHT }, + { 0xeb14, KEY_DOWN }, + { 0xeb16, KEY_INFO }, + { 0xeb17, KEY_RED }, + { 0xeb18, KEY_GREEN }, + { 0xeb19, KEY_YELLOW }, + { 0xeb1a, KEY_BLUE }, + { 0xeb1b, KEY_CHANNELUP }, + { 0xeb1c, KEY_VOLUMEUP }, + { 0xeb1d, KEY_MUTE }, + { 0xeb1e, KEY_VOLUMEDOWN }, + { 0xeb1f, KEY_CHANNELDOWN }, + { 0xeb40, KEY_PAUSE }, + { 0xeb41, KEY_HOME }, + { 0xeb42, KEY_MENU }, /* DVD Menu */ + { 0xeb43, KEY_SUBTITLE }, + { 0xeb44, KEY_TEXT }, /* Teletext */ + { 0xeb45, KEY_DELETE }, + { 0xeb46, KEY_TV }, + { 0xeb47, KEY_DVD }, + { 0xeb48, KEY_STOP }, + { 0xeb49, KEY_VIDEO }, + { 0xeb4a, KEY_AUDIO }, /* Music */ + { 0xeb4b, KEY_SCREEN }, /* Pic */ + { 0xeb4c, KEY_PLAY }, + { 0xeb4d, KEY_BACK }, + { 0xeb4e, KEY_REWIND }, + { 0xeb4f, KEY_FASTFORWARD }, + { 0xeb54, KEY_PREVIOUS }, + { 0xeb58, KEY_RECORD }, + { 0xeb5c, KEY_NEXT }, /* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */ - { 0x1e, 0x00, KEY_0 }, - { 0x1e, 0x01, KEY_1 }, - { 0x1e, 0x02, KEY_2 }, - { 0x1e, 0x03, KEY_3 }, - { 0x1e, 0x04, KEY_4 }, - { 0x1e, 0x05, KEY_5 }, - { 0x1e, 0x06, KEY_6 }, - { 0x1e, 0x07, KEY_7 }, - { 0x1e, 0x08, KEY_8 }, - { 0x1e, 0x09, KEY_9 }, - { 0x1e, 0x0a, KEY_KPASTERISK }, - { 0x1e, 0x0b, KEY_RED }, - { 0x1e, 0x0c, KEY_RADIO }, - { 0x1e, 0x0d, KEY_MENU }, - { 0x1e, 0x0e, KEY_GRAVE }, /* # */ - { 0x1e, 0x0f, KEY_MUTE }, - { 0x1e, 0x10, KEY_VOLUMEUP }, - { 0x1e, 0x11, KEY_VOLUMEDOWN }, - { 0x1e, 0x12, KEY_CHANNEL }, - { 0x1e, 0x14, KEY_UP }, - { 0x1e, 0x15, KEY_DOWN }, - { 0x1e, 0x16, KEY_LEFT }, - { 0x1e, 0x17, KEY_RIGHT }, - { 0x1e, 0x18, KEY_VIDEO }, - { 0x1e, 0x19, KEY_AUDIO }, - { 0x1e, 0x1a, KEY_MEDIA }, - { 0x1e, 0x1b, KEY_EPG }, - { 0x1e, 0x1c, KEY_TV }, - { 0x1e, 0x1e, KEY_NEXT }, - { 0x1e, 0x1f, KEY_BACK }, - { 0x1e, 0x20, KEY_CHANNELUP }, - { 0x1e, 0x21, KEY_CHANNELDOWN }, - { 0x1e, 0x24, KEY_LAST }, /* Skip backwards */ - { 0x1e, 0x25, KEY_OK }, - { 0x1e, 0x29, KEY_BLUE}, - { 0x1e, 0x2e, KEY_GREEN }, - { 0x1e, 0x30, KEY_PAUSE }, - { 0x1e, 0x32, KEY_REWIND }, - { 0x1e, 0x34, KEY_FASTFORWARD }, - { 0x1e, 0x35, KEY_PLAY }, - { 0x1e, 0x36, KEY_STOP }, - { 0x1e, 0x37, KEY_RECORD }, - { 0x1e, 0x38, KEY_YELLOW }, - { 0x1e, 0x3b, KEY_GOTO }, - { 0x1e, 0x3d, KEY_POWER }, + { 0x1e00, KEY_0 }, + { 0x1e01, KEY_1 }, + { 0x1e02, KEY_2 }, + { 0x1e03, KEY_3 }, + { 0x1e04, KEY_4 }, + { 0x1e05, KEY_5 }, + { 0x1e06, KEY_6 }, + { 0x1e07, KEY_7 }, + { 0x1e08, KEY_8 }, + { 0x1e09, KEY_9 }, + { 0x1e0a, KEY_KPASTERISK }, + { 0x1e0b, KEY_RED }, + { 0x1e0c, KEY_RADIO }, + { 0x1e0d, KEY_MENU }, + { 0x1e0e, KEY_GRAVE }, /* # */ + { 0x1e0f, KEY_MUTE }, + { 0x1e10, KEY_VOLUMEUP }, + { 0x1e11, KEY_VOLUMEDOWN }, + { 0x1e12, KEY_CHANNEL }, + { 0x1e14, KEY_UP }, + { 0x1e15, KEY_DOWN }, + { 0x1e16, KEY_LEFT }, + { 0x1e17, KEY_RIGHT }, + { 0x1e18, KEY_VIDEO }, + { 0x1e19, KEY_AUDIO }, + { 0x1e1a, KEY_MEDIA }, + { 0x1e1b, KEY_EPG }, + { 0x1e1c, KEY_TV }, + { 0x1e1e, KEY_NEXT }, + { 0x1e1f, KEY_BACK }, + { 0x1e20, KEY_CHANNELUP }, + { 0x1e21, KEY_CHANNELDOWN }, + { 0x1e24, KEY_LAST }, /* Skip backwards */ + { 0x1e25, KEY_OK }, + { 0x1e29, KEY_BLUE}, + { 0x1e2e, KEY_GREEN }, + { 0x1e30, KEY_PAUSE }, + { 0x1e32, KEY_REWIND }, + { 0x1e34, KEY_FASTFORWARD }, + { 0x1e35, KEY_PLAY }, + { 0x1e36, KEY_STOP }, + { 0x1e37, KEY_RECORD }, + { 0x1e38, KEY_YELLOW }, + { 0x1e3b, KEY_GOTO }, + { 0x1e3d, KEY_POWER }, /* Key codes for the Leadtek Winfast DTV Dongle */ - { 0x00, 0x42, KEY_POWER }, - { 0x07, 0x7c, KEY_TUNER }, - { 0x0f, 0x4e, KEY_PRINT }, /* PREVIEW */ - { 0x08, 0x40, KEY_SCREEN }, /* full screen toggle*/ - { 0x0f, 0x71, KEY_DOT }, /* frequency */ - { 0x07, 0x43, KEY_0 }, - { 0x0c, 0x41, KEY_1 }, - { 0x04, 0x43, KEY_2 }, - { 0x0b, 0x7f, KEY_3 }, - { 0x0e, 0x41, KEY_4 }, - { 0x06, 0x43, KEY_5 }, - { 0x09, 0x7f, KEY_6 }, - { 0x0d, 0x7e, KEY_7 }, - { 0x05, 0x7c, KEY_8 }, - { 0x0a, 0x40, KEY_9 }, - { 0x0e, 0x4e, KEY_CLEAR }, - { 0x04, 0x7c, KEY_CHANNEL }, /* show channel number */ - { 0x0f, 0x41, KEY_LAST }, /* recall */ - { 0x03, 0x42, KEY_MUTE }, - { 0x06, 0x4c, KEY_RESERVED }, /* PIP button*/ - { 0x01, 0x72, KEY_SHUFFLE }, /* SNAPSHOT */ - { 0x0c, 0x4e, KEY_PLAYPAUSE }, /* TIMESHIFT */ - { 0x0b, 0x70, KEY_RECORD }, - { 0x03, 0x7d, KEY_VOLUMEUP }, - { 0x01, 0x7d, KEY_VOLUMEDOWN }, - { 0x02, 0x42, KEY_CHANNELUP }, - { 0x00, 0x7d, KEY_CHANNELDOWN }, + { 0x0042, KEY_POWER }, + { 0x077c, KEY_TUNER }, + { 0x0f4e, KEY_PRINT }, /* PREVIEW */ + { 0x0840, KEY_SCREEN }, /* full screen toggle*/ + { 0x0f71, KEY_DOT }, /* frequency */ + { 0x0743, KEY_0 }, + { 0x0c41, KEY_1 }, + { 0x0443, KEY_2 }, + { 0x0b7f, KEY_3 }, + { 0x0e41, KEY_4 }, + { 0x0643, KEY_5 }, + { 0x097f, KEY_6 }, + { 0x0d7e, KEY_7 }, + { 0x057c, KEY_8 }, + { 0x0a40, KEY_9 }, + { 0x0e4e, KEY_CLEAR }, + { 0x047c, KEY_CHANNEL }, /* show channel number */ + { 0x0f41, KEY_LAST }, /* recall */ + { 0x0342, KEY_MUTE }, + { 0x064c, KEY_RESERVED }, /* PIP button*/ + { 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */ + { 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */ + { 0x0b70, KEY_RECORD }, + { 0x037d, KEY_VOLUMEUP }, + { 0x017d, KEY_VOLUMEDOWN }, + { 0x0242, KEY_CHANNELUP }, + { 0x007d, KEY_CHANNELDOWN }, /* Key codes for Nova-TD "credit card" remote control. */ - { 0x1d, 0x00, KEY_0 }, - { 0x1d, 0x01, KEY_1 }, - { 0x1d, 0x02, KEY_2 }, - { 0x1d, 0x03, KEY_3 }, - { 0x1d, 0x04, KEY_4 }, - { 0x1d, 0x05, KEY_5 }, - { 0x1d, 0x06, KEY_6 }, - { 0x1d, 0x07, KEY_7 }, - { 0x1d, 0x08, KEY_8 }, - { 0x1d, 0x09, KEY_9 }, - { 0x1d, 0x0a, KEY_TEXT }, - { 0x1d, 0x0d, KEY_MENU }, - { 0x1d, 0x0f, KEY_MUTE }, - { 0x1d, 0x10, KEY_VOLUMEUP }, - { 0x1d, 0x11, KEY_VOLUMEDOWN }, - { 0x1d, 0x12, KEY_CHANNEL }, - { 0x1d, 0x14, KEY_UP }, - { 0x1d, 0x15, KEY_DOWN }, - { 0x1d, 0x16, KEY_LEFT }, - { 0x1d, 0x17, KEY_RIGHT }, - { 0x1d, 0x1c, KEY_TV }, - { 0x1d, 0x1e, KEY_NEXT }, - { 0x1d, 0x1f, KEY_BACK }, - { 0x1d, 0x20, KEY_CHANNELUP }, - { 0x1d, 0x21, KEY_CHANNELDOWN }, - { 0x1d, 0x24, KEY_LAST }, - { 0x1d, 0x25, KEY_OK }, - { 0x1d, 0x30, KEY_PAUSE }, - { 0x1d, 0x32, KEY_REWIND }, - { 0x1d, 0x34, KEY_FASTFORWARD }, - { 0x1d, 0x35, KEY_PLAY }, - { 0x1d, 0x36, KEY_STOP }, - { 0x1d, 0x37, KEY_RECORD }, - { 0x1d, 0x3b, KEY_GOTO }, - { 0x1d, 0x3d, KEY_POWER }, + { 0x1d00, KEY_0 }, + { 0x1d01, KEY_1 }, + { 0x1d02, KEY_2 }, + { 0x1d03, KEY_3 }, + { 0x1d04, KEY_4 }, + { 0x1d05, KEY_5 }, + { 0x1d06, KEY_6 }, + { 0x1d07, KEY_7 }, + { 0x1d08, KEY_8 }, + { 0x1d09, KEY_9 }, + { 0x1d0a, KEY_TEXT }, + { 0x1d0d, KEY_MENU }, + { 0x1d0f, KEY_MUTE }, + { 0x1d10, KEY_VOLUMEUP }, + { 0x1d11, KEY_VOLUMEDOWN }, + { 0x1d12, KEY_CHANNEL }, + { 0x1d14, KEY_UP }, + { 0x1d15, KEY_DOWN }, + { 0x1d16, KEY_LEFT }, + { 0x1d17, KEY_RIGHT }, + { 0x1d1c, KEY_TV }, + { 0x1d1e, KEY_NEXT }, + { 0x1d1f, KEY_BACK }, + { 0x1d20, KEY_CHANNELUP }, + { 0x1d21, KEY_CHANNELDOWN }, + { 0x1d24, KEY_LAST }, + { 0x1d25, KEY_OK }, + { 0x1d30, KEY_PAUSE }, + { 0x1d32, KEY_REWIND }, + { 0x1d34, KEY_FASTFORWARD }, + { 0x1d35, KEY_PLAY }, + { 0x1d36, KEY_STOP }, + { 0x1d37, KEY_RECORD }, + { 0x1d3b, KEY_GOTO }, + { 0x1d3d, KEY_POWER }, }; /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c index 99b3b9a43..11ae0d4dc 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -321,132 +321,132 @@ EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach); */ struct dvb_usb_rc_key dibusb_rc_keys[] = { /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */ - { 0x00, 0x16, KEY_POWER }, - { 0x00, 0x10, KEY_MUTE }, - { 0x00, 0x03, KEY_1 }, - { 0x00, 0x01, KEY_2 }, - { 0x00, 0x06, KEY_3 }, - { 0x00, 0x09, KEY_4 }, - { 0x00, 0x1d, KEY_5 }, - { 0x00, 0x1f, KEY_6 }, - { 0x00, 0x0d, KEY_7 }, - { 0x00, 0x19, KEY_8 }, - { 0x00, 0x1b, KEY_9 }, - { 0x00, 0x15, KEY_0 }, - { 0x00, 0x05, KEY_CHANNELUP }, - { 0x00, 0x02, KEY_CHANNELDOWN }, - { 0x00, 0x1e, KEY_VOLUMEUP }, - { 0x00, 0x0a, KEY_VOLUMEDOWN }, - { 0x00, 0x11, KEY_RECORD }, - { 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */ - { 0x00, 0x14, KEY_PLAY }, - { 0x00, 0x1a, KEY_STOP }, - { 0x00, 0x40, KEY_REWIND }, - { 0x00, 0x12, KEY_FASTFORWARD }, - { 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */ - { 0x00, 0x4c, KEY_PAUSE }, - { 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */ - { 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ + { 0x0016, KEY_POWER }, + { 0x0010, KEY_MUTE }, + { 0x0003, KEY_1 }, + { 0x0001, KEY_2 }, + { 0x0006, KEY_3 }, + { 0x0009, KEY_4 }, + { 0x001d, KEY_5 }, + { 0x001f, KEY_6 }, + { 0x000d, KEY_7 }, + { 0x0019, KEY_8 }, + { 0x001b, KEY_9 }, + { 0x0015, KEY_0 }, + { 0x0005, KEY_CHANNELUP }, + { 0x0002, KEY_CHANNELDOWN }, + { 0x001e, KEY_VOLUMEUP }, + { 0x000a, KEY_VOLUMEDOWN }, + { 0x0011, KEY_RECORD }, + { 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */ + { 0x0014, KEY_PLAY }, + { 0x001a, KEY_STOP }, + { 0x0040, KEY_REWIND }, + { 0x0012, KEY_FASTFORWARD }, + { 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */ + { 0x004c, KEY_PAUSE }, + { 0x004d, KEY_SCREEN }, /* Full screen mode. */ + { 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ /* additional keys TwinHan VisionPlus, the Artec seemingly not have */ - { 0x00, 0x0c, KEY_CANCEL }, /* Cancel */ - { 0x00, 0x1c, KEY_EPG }, /* EPG */ - { 0x00, 0x00, KEY_TAB }, /* Tab */ - { 0x00, 0x48, KEY_INFO }, /* Preview */ - { 0x00, 0x04, KEY_LIST }, /* RecordList */ - { 0x00, 0x0f, KEY_TEXT }, /* Teletext */ + { 0x000c, KEY_CANCEL }, /* Cancel */ + { 0x001c, KEY_EPG }, /* EPG */ + { 0x0000, KEY_TAB }, /* Tab */ + { 0x0048, KEY_INFO }, /* Preview */ + { 0x0004, KEY_LIST }, /* RecordList */ + { 0x000f, KEY_TEXT }, /* Teletext */ /* Key codes for the KWorld/ADSTech/JetWay remote. */ - { 0x86, 0x12, KEY_POWER }, - { 0x86, 0x0f, KEY_SELECT }, /* source */ - { 0x86, 0x0c, KEY_UNKNOWN }, /* scan */ - { 0x86, 0x0b, KEY_EPG }, - { 0x86, 0x10, KEY_MUTE }, - { 0x86, 0x01, KEY_1 }, - { 0x86, 0x02, KEY_2 }, - { 0x86, 0x03, KEY_3 }, - { 0x86, 0x04, KEY_4 }, - { 0x86, 0x05, KEY_5 }, - { 0x86, 0x06, KEY_6 }, - { 0x86, 0x07, KEY_7 }, - { 0x86, 0x08, KEY_8 }, - { 0x86, 0x09, KEY_9 }, - { 0x86, 0x0a, KEY_0 }, - { 0x86, 0x18, KEY_ZOOM }, - { 0x86, 0x1c, KEY_UNKNOWN }, /* preview */ - { 0x86, 0x13, KEY_UNKNOWN }, /* snap */ - { 0x86, 0x00, KEY_UNDO }, - { 0x86, 0x1d, KEY_RECORD }, - { 0x86, 0x0d, KEY_STOP }, - { 0x86, 0x0e, KEY_PAUSE }, - { 0x86, 0x16, KEY_PLAY }, - { 0x86, 0x11, KEY_BACK }, - { 0x86, 0x19, KEY_FORWARD }, - { 0x86, 0x14, KEY_UNKNOWN }, /* pip */ - { 0x86, 0x15, KEY_ESC }, - { 0x86, 0x1a, KEY_UP }, - { 0x86, 0x1e, KEY_DOWN }, - { 0x86, 0x1f, KEY_LEFT }, - { 0x86, 0x1b, KEY_RIGHT }, + { 0x8612, KEY_POWER }, + { 0x860f, KEY_SELECT }, /* source */ + { 0x860c, KEY_UNKNOWN }, /* scan */ + { 0x860b, KEY_EPG }, + { 0x8610, KEY_MUTE }, + { 0x8601, KEY_1 }, + { 0x8602, KEY_2 }, + { 0x8603, KEY_3 }, + { 0x8604, KEY_4 }, + { 0x8605, KEY_5 }, + { 0x8606, KEY_6 }, + { 0x8607, KEY_7 }, + { 0x8608, KEY_8 }, + { 0x8609, KEY_9 }, + { 0x860a, KEY_0 }, + { 0x8618, KEY_ZOOM }, + { 0x861c, KEY_UNKNOWN }, /* preview */ + { 0x8613, KEY_UNKNOWN }, /* snap */ + { 0x8600, KEY_UNDO }, + { 0x861d, KEY_RECORD }, + { 0x860d, KEY_STOP }, + { 0x860e, KEY_PAUSE }, + { 0x8616, KEY_PLAY }, + { 0x8611, KEY_BACK }, + { 0x8619, KEY_FORWARD }, + { 0x8614, KEY_UNKNOWN }, /* pip */ + { 0x8615, KEY_ESC }, + { 0x861a, KEY_UP }, + { 0x861e, KEY_DOWN }, + { 0x861f, KEY_LEFT }, + { 0x861b, KEY_RIGHT }, /* Key codes for the DiBcom MOD3000 remote. */ - { 0x80, 0x00, KEY_MUTE }, - { 0x80, 0x01, KEY_TEXT }, - { 0x80, 0x02, KEY_HOME }, - { 0x80, 0x03, KEY_POWER }, - - { 0x80, 0x04, KEY_RED }, - { 0x80, 0x05, KEY_GREEN }, - { 0x80, 0x06, KEY_YELLOW }, - { 0x80, 0x07, KEY_BLUE }, - - { 0x80, 0x08, KEY_DVD }, - { 0x80, 0x09, KEY_AUDIO }, - { 0x80, 0x0a, KEY_MEDIA }, /* Pictures */ - { 0x80, 0x0b, KEY_VIDEO }, - - { 0x80, 0x0c, KEY_BACK }, - { 0x80, 0x0d, KEY_UP }, - { 0x80, 0x0e, KEY_RADIO }, - { 0x80, 0x0f, KEY_EPG }, - - { 0x80, 0x10, KEY_LEFT }, - { 0x80, 0x11, KEY_OK }, - { 0x80, 0x12, KEY_RIGHT }, - { 0x80, 0x13, KEY_UNKNOWN }, /* SAP */ - - { 0x80, 0x14, KEY_TV }, - { 0x80, 0x15, KEY_DOWN }, - { 0x80, 0x16, KEY_MENU }, /* DVD Menu */ - { 0x80, 0x17, KEY_LAST }, - - { 0x80, 0x18, KEY_RECORD }, - { 0x80, 0x19, KEY_STOP }, - { 0x80, 0x1a, KEY_PAUSE }, - { 0x80, 0x1b, KEY_PLAY }, - - { 0x80, 0x1c, KEY_PREVIOUS }, - { 0x80, 0x1d, KEY_REWIND }, - { 0x80, 0x1e, KEY_FASTFORWARD }, - { 0x80, 0x1f, KEY_NEXT}, - - { 0x80, 0x40, KEY_1 }, - { 0x80, 0x41, KEY_2 }, - { 0x80, 0x42, KEY_3 }, - { 0x80, 0x43, KEY_CHANNELUP }, - - { 0x80, 0x44, KEY_4 }, - { 0x80, 0x45, KEY_5 }, - { 0x80, 0x46, KEY_6 }, - { 0x80, 0x47, KEY_CHANNELDOWN }, - - { 0x80, 0x48, KEY_7 }, - { 0x80, 0x49, KEY_8 }, - { 0x80, 0x4a, KEY_9 }, - { 0x80, 0x4b, KEY_VOLUMEUP }, - - { 0x80, 0x4c, KEY_CLEAR }, - { 0x80, 0x4d, KEY_0 }, - { 0x80, 0x4e, KEY_ENTER }, - { 0x80, 0x4f, KEY_VOLUMEDOWN }, + { 0x8000, KEY_MUTE }, + { 0x8001, KEY_TEXT }, + { 0x8002, KEY_HOME }, + { 0x8003, KEY_POWER }, + + { 0x8004, KEY_RED }, + { 0x8005, KEY_GREEN }, + { 0x8006, KEY_YELLOW }, + { 0x8007, KEY_BLUE }, + + { 0x8008, KEY_DVD }, + { 0x8009, KEY_AUDIO }, + { 0x800a, KEY_MEDIA }, /* Pictures */ + { 0x800b, KEY_VIDEO }, + + { 0x800c, KEY_BACK }, + { 0x800d, KEY_UP }, + { 0x800e, KEY_RADIO }, + { 0x800f, KEY_EPG }, + + { 0x8010, KEY_LEFT }, + { 0x8011, KEY_OK }, + { 0x8012, KEY_RIGHT }, + { 0x8013, KEY_UNKNOWN }, /* SAP */ + + { 0x8014, KEY_TV }, + { 0x8015, KEY_DOWN }, + { 0x8016, KEY_MENU }, /* DVD Menu */ + { 0x8017, KEY_LAST }, + + { 0x8018, KEY_RECORD }, + { 0x8019, KEY_STOP }, + { 0x801a, KEY_PAUSE }, + { 0x801b, KEY_PLAY }, + + { 0x801c, KEY_PREVIOUS }, + { 0x801d, KEY_REWIND }, + { 0x801e, KEY_FASTFORWARD }, + { 0x801f, KEY_NEXT}, + + { 0x8040, KEY_1 }, + { 0x8041, KEY_2 }, + { 0x8042, KEY_3 }, + { 0x8043, KEY_CHANNELUP }, + + { 0x8044, KEY_4 }, + { 0x8045, KEY_5 }, + { 0x8046, KEY_6 }, + { 0x8047, KEY_CHANNELDOWN }, + + { 0x8048, KEY_7 }, + { 0x8049, KEY_8 }, + { 0x804a, KEY_9 }, + { 0x804b, KEY_VOLUMEUP }, + + { 0x804c, KEY_CLEAR }, + { 0x804d, KEY_0 }, + { 0x804e, KEY_ENTER }, + { 0x804f, KEY_VOLUMEDOWN }, }; EXPORT_SYMBOL(dibusb_rc_keys); diff --git a/linux/drivers/media/dvb/dvb-usb/digitv.c b/linux/drivers/media/dvb/dvb-usb/digitv.c index 3a560dcdd..c736fdf77 100644 --- a/linux/drivers/media/dvb/dvb-usb/digitv.c +++ b/linux/drivers/media/dvb/dvb-usb/digitv.c @@ -165,61 +165,61 @@ static int digitv_tuner_attach(struct dvb_usb_adapter *adap) } static struct dvb_usb_rc_key digitv_rc_keys[] = { - { 0x5f, 0x55, KEY_0 }, - { 0x6f, 0x55, KEY_1 }, - { 0x9f, 0x55, KEY_2 }, - { 0xaf, 0x55, KEY_3 }, - { 0x5f, 0x56, KEY_4 }, - { 0x6f, 0x56, KEY_5 }, - { 0x9f, 0x56, KEY_6 }, - { 0xaf, 0x56, KEY_7 }, - { 0x5f, 0x59, KEY_8 }, - { 0x6f, 0x59, KEY_9 }, - { 0x9f, 0x59, KEY_TV }, - { 0xaf, 0x59, KEY_AUX }, - { 0x5f, 0x5a, KEY_DVD }, - { 0x6f, 0x5a, KEY_POWER }, - { 0x9f, 0x5a, KEY_MHP }, /* labelled 'Picture' */ - { 0xaf, 0x5a, KEY_AUDIO }, - { 0x5f, 0x65, KEY_INFO }, - { 0x6f, 0x65, KEY_F13 }, /* 16:9 */ - { 0x9f, 0x65, KEY_F14 }, /* 14:9 */ - { 0xaf, 0x65, KEY_EPG }, - { 0x5f, 0x66, KEY_EXIT }, - { 0x6f, 0x66, KEY_MENU }, - { 0x9f, 0x66, KEY_UP }, - { 0xaf, 0x66, KEY_DOWN }, - { 0x5f, 0x69, KEY_LEFT }, - { 0x6f, 0x69, KEY_RIGHT }, - { 0x9f, 0x69, KEY_ENTER }, - { 0xaf, 0x69, KEY_CHANNELUP }, - { 0x5f, 0x6a, KEY_CHANNELDOWN }, - { 0x6f, 0x6a, KEY_VOLUMEUP }, - { 0x9f, 0x6a, KEY_VOLUMEDOWN }, - { 0xaf, 0x6a, KEY_RED }, - { 0x5f, 0x95, KEY_GREEN }, - { 0x6f, 0x95, KEY_YELLOW }, - { 0x9f, 0x95, KEY_BLUE }, - { 0xaf, 0x95, KEY_SUBTITLE }, - { 0x5f, 0x96, KEY_F15 }, /* AD */ - { 0x6f, 0x96, KEY_TEXT }, - { 0x9f, 0x96, KEY_MUTE }, - { 0xaf, 0x96, KEY_REWIND }, - { 0x5f, 0x99, KEY_STOP }, - { 0x6f, 0x99, KEY_PLAY }, - { 0x9f, 0x99, KEY_FASTFORWARD }, - { 0xaf, 0x99, KEY_F16 }, /* chapter */ - { 0x5f, 0x9a, KEY_PAUSE }, - { 0x6f, 0x9a, KEY_PLAY }, - { 0x9f, 0x9a, KEY_RECORD }, - { 0xaf, 0x9a, KEY_F17 }, /* picture in picture */ - { 0x5f, 0xa5, KEY_KPPLUS }, /* zoom in */ - { 0x6f, 0xa5, KEY_KPMINUS }, /* zoom out */ - { 0x9f, 0xa5, KEY_F18 }, /* capture */ - { 0xaf, 0xa5, KEY_F19 }, /* web */ - { 0x5f, 0xa6, KEY_EMAIL }, - { 0x6f, 0xa6, KEY_PHONE }, - { 0x9f, 0xa6, KEY_PC }, + { 0x5f55, KEY_0 }, + { 0x6f55, KEY_1 }, + { 0x9f55, KEY_2 }, + { 0xaf55, KEY_3 }, + { 0x5f56, KEY_4 }, + { 0x6f56, KEY_5 }, + { 0x9f56, KEY_6 }, + { 0xaf56, KEY_7 }, + { 0x5f59, KEY_8 }, + { 0x6f59, KEY_9 }, + { 0x9f59, KEY_TV }, + { 0xaf59, KEY_AUX }, + { 0x5f5a, KEY_DVD }, + { 0x6f5a, KEY_POWER }, + { 0x9f5a, KEY_MHP }, /* labelled 'Picture' */ + { 0xaf5a, KEY_AUDIO }, + { 0x5f65, KEY_INFO }, + { 0x6f65, KEY_F13 }, /* 16:9 */ + { 0x9f65, KEY_F14 }, /* 14:9 */ + { 0xaf65, KEY_EPG }, + { 0x5f66, KEY_EXIT }, + { 0x6f66, KEY_MENU }, + { 0x9f66, KEY_UP }, + { 0xaf66, KEY_DOWN }, + { 0x5f69, KEY_LEFT }, + { 0x6f69, KEY_RIGHT }, + { 0x9f69, KEY_ENTER }, + { 0xaf69, KEY_CHANNELUP }, + { 0x5f6a, KEY_CHANNELDOWN }, + { 0x6f6a, KEY_VOLUMEUP }, + { 0x9f6a, KEY_VOLUMEDOWN }, + { 0xaf6a, KEY_RED }, + { 0x5f95, KEY_GREEN }, + { 0x6f95, KEY_YELLOW }, + { 0x9f95, KEY_BLUE }, + { 0xaf95, KEY_SUBTITLE }, + { 0x5f96, KEY_F15 }, /* AD */ + { 0x6f96, KEY_TEXT }, + { 0x9f96, KEY_MUTE }, + { 0xaf96, KEY_REWIND }, + { 0x5f99, KEY_STOP }, + { 0x6f99, KEY_PLAY }, + { 0x9f99, KEY_FASTFORWARD }, + { 0xaf99, KEY_F16 }, /* chapter */ + { 0x5f9a, KEY_PAUSE }, + { 0x6f9a, KEY_PLAY }, + { 0x9f9a, KEY_RECORD }, + { 0xaf9a, KEY_F17 }, /* picture in picture */ + { 0x5fa5, KEY_KPPLUS }, /* zoom in */ + { 0x6fa5, KEY_KPMINUS }, /* zoom out */ + { 0x9fa5, KEY_F18 }, /* capture */ + { 0xafa5, KEY_F19 }, /* web */ + { 0x5fa6, KEY_EMAIL }, + { 0x6fa6, KEY_PHONE }, + { 0x9fa6, KEY_PC }, }; static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state) @@ -241,8 +241,8 @@ static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state) if (key[1] != 0) { for (i = 0; i < d->props.rc_key_map_size; i++) { - if (d->props.rc_key_map[i].custom == key[1] && - d->props.rc_key_map[i].data == key[2]) { + if (rc5_custom(&d->props.rc_key_map[i]) == key[1] && + rc5_data(&d->props.rc_key_map[i]) == key[2]) { *event = d->props.rc_key_map[i].event; *state = REMOTE_KEY_PRESSED; return 0; diff --git a/linux/drivers/media/dvb/dvb-usb/dtt200u.c b/linux/drivers/media/dvb/dvb-usb/dtt200u.c index 81a6cbf60..a1b12b01c 100644 --- a/linux/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/linux/drivers/media/dvb/dvb-usb/dtt200u.c @@ -58,24 +58,24 @@ static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, /* remote control */ /* key list for the tiny remote control (Yakumo, don't know about the others) */ static struct dvb_usb_rc_key dtt200u_rc_keys[] = { - { 0x80, 0x01, KEY_MUTE }, - { 0x80, 0x02, KEY_CHANNELDOWN }, - { 0x80, 0x03, KEY_VOLUMEDOWN }, - { 0x80, 0x04, KEY_1 }, - { 0x80, 0x05, KEY_2 }, - { 0x80, 0x06, KEY_3 }, - { 0x80, 0x07, KEY_4 }, - { 0x80, 0x08, KEY_5 }, - { 0x80, 0x09, KEY_6 }, - { 0x80, 0x0a, KEY_7 }, - { 0x80, 0x0c, KEY_ZOOM }, - { 0x80, 0x0d, KEY_0 }, - { 0x80, 0x0e, KEY_SELECT }, - { 0x80, 0x12, KEY_POWER }, - { 0x80, 0x1a, KEY_CHANNELUP }, - { 0x80, 0x1b, KEY_8 }, - { 0x80, 0x1e, KEY_VOLUMEUP }, - { 0x80, 0x1f, KEY_9 }, + { 0x8001, KEY_MUTE }, + { 0x8002, KEY_CHANNELDOWN }, + { 0x8003, KEY_VOLUMEDOWN }, + { 0x8004, KEY_1 }, + { 0x8005, KEY_2 }, + { 0x8006, KEY_3 }, + { 0x8007, KEY_4 }, + { 0x8008, KEY_5 }, + { 0x8009, KEY_6 }, + { 0x800a, KEY_7 }, + { 0x800c, KEY_ZOOM }, + { 0x800d, KEY_0 }, + { 0x800e, KEY_SELECT }, + { 0x8012, KEY_POWER }, + { 0x801a, KEY_CHANNELUP }, + { 0x801b, KEY_8 }, + { 0x801e, KEY_VOLUMEUP }, + { 0x801f, KEY_9 }, }; static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state) diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index ec95bdf90..e1d07f1ce 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -198,8 +198,8 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, } /* See if we can match the raw key code. */ for (i = 0; i < d->props.rc_key_map_size; i++) - if (keymap[i].custom == keybuf[1] && - keymap[i].data == keybuf[3]) { + if (rc5_custom(&keymap[i]) == keybuf[1] && + rc5_data(&keymap[i]) == keybuf[3]) { *event = keymap[i].event; *state = REMOTE_KEY_PRESSED; return 0; diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h index f4819c32f..14a8c4357 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -82,10 +82,25 @@ struct dvb_usb_device_description { * @event: the input event assigned to key identified by custom and data */ struct dvb_usb_rc_key { - u8 custom,data; + u16 scan; u32 event; }; +static inline u8 rc5_custom(struct dvb_usb_rc_key *key) +{ + return (key->scan >> 8) & 0xff; +} + +static inline u8 rc5_data(struct dvb_usb_rc_key *key) +{ + return key->scan & 0xff; +} + +static inline u8 rc5_scan(struct dvb_usb_rc_key *key) +{ + return key->scan & 0xffff; +} + struct dvb_usb_device; struct dvb_usb_adapter; struct usb_data_stream; diff --git a/linux/drivers/media/dvb/dvb-usb/dw2102.c b/linux/drivers/media/dvb/dvb-usb/dw2102.c index c8bdb2e78..3c80aa702 100644 --- a/linux/drivers/media/dvb/dvb-usb/dw2102.c +++ b/linux/drivers/media/dvb/dvb-usb/dw2102.c @@ -767,122 +767,122 @@ static int s630_zl10039_tuner_attach(struct dvb_usb_adapter *adap) } static struct dvb_usb_rc_key dw210x_rc_keys[] = { - { 0xf8, 0x0a, KEY_Q }, /*power*/ - { 0xf8, 0x0c, KEY_M }, /*mute*/ - { 0xf8, 0x11, KEY_1 }, - { 0xf8, 0x12, KEY_2 }, - { 0xf8, 0x13, KEY_3 }, - { 0xf8, 0x14, KEY_4 }, - { 0xf8, 0x15, KEY_5 }, - { 0xf8, 0x16, KEY_6 }, - { 0xf8, 0x17, KEY_7 }, - { 0xf8, 0x18, KEY_8 }, - { 0xf8, 0x19, KEY_9 }, - { 0xf8, 0x10, KEY_0 }, - { 0xf8, 0x1c, KEY_PAGEUP }, /*ch+*/ - { 0xf8, 0x0f, KEY_PAGEDOWN }, /*ch-*/ - { 0xf8, 0x1a, KEY_O }, /*vol+*/ - { 0xf8, 0x0e, KEY_Z }, /*vol-*/ - { 0xf8, 0x04, KEY_R }, /*rec*/ - { 0xf8, 0x09, KEY_D }, /*fav*/ - { 0xf8, 0x08, KEY_BACKSPACE }, /*rewind*/ - { 0xf8, 0x07, KEY_A }, /*fast*/ - { 0xf8, 0x0b, KEY_P }, /*pause*/ - { 0xf8, 0x02, KEY_ESC }, /*cancel*/ - { 0xf8, 0x03, KEY_G }, /*tab*/ - { 0xf8, 0x00, KEY_UP }, /*up*/ - { 0xf8, 0x1f, KEY_ENTER }, /*ok*/ - { 0xf8, 0x01, KEY_DOWN }, /*down*/ - { 0xf8, 0x05, KEY_C }, /*cap*/ - { 0xf8, 0x06, KEY_S }, /*stop*/ - { 0xf8, 0x40, KEY_F }, /*full*/ - { 0xf8, 0x1e, KEY_W }, /*tvmode*/ - { 0xf8, 0x1b, KEY_B }, /*recall*/ + { 0xf80a, KEY_Q }, /*power*/ + { 0xf80c, KEY_M }, /*mute*/ + { 0xf811, KEY_1 }, + { 0xf812, KEY_2 }, + { 0xf813, KEY_3 }, + { 0xf814, KEY_4 }, + { 0xf815, KEY_5 }, + { 0xf816, KEY_6 }, + { 0xf817, KEY_7 }, + { 0xf818, KEY_8 }, + { 0xf819, KEY_9 }, + { 0xf810, KEY_0 }, + { 0xf81c, KEY_PAGEUP }, /*ch+*/ + { 0xf80f, KEY_PAGEDOWN }, /*ch-*/ + { 0xf81a, KEY_O }, /*vol+*/ + { 0xf80e, KEY_Z }, /*vol-*/ + { 0xf804, KEY_R }, /*rec*/ + { 0xf809, KEY_D }, /*fav*/ + { 0xf808, KEY_BACKSPACE }, /*rewind*/ + { 0xf807, KEY_A }, /*fast*/ + { 0xf80b, KEY_P }, /*pause*/ + { 0xf802, KEY_ESC }, /*cancel*/ + { 0xf803, KEY_G }, /*tab*/ + { 0xf800, KEY_UP }, /*up*/ + { 0xf81f, KEY_ENTER }, /*ok*/ + { 0xf801, KEY_DOWN }, /*down*/ + { 0xf805, KEY_C }, /*cap*/ + { 0xf806, KEY_S }, /*stop*/ + { 0xf840, KEY_F }, /*full*/ + { 0xf81e, KEY_W }, /*tvmode*/ + { 0xf81b, KEY_B }, /*recall*/ }; static struct dvb_usb_rc_key tevii_rc_keys[] = { - { 0xf8, 0x0a, KEY_POWER }, - { 0xf8, 0x0c, KEY_MUTE }, - { 0xf8, 0x11, KEY_1 }, - { 0xf8, 0x12, KEY_2 }, - { 0xf8, 0x13, KEY_3 }, - { 0xf8, 0x14, KEY_4 }, - { 0xf8, 0x15, KEY_5 }, - { 0xf8, 0x16, KEY_6 }, - { 0xf8, 0x17, KEY_7 }, - { 0xf8, 0x18, KEY_8 }, - { 0xf8, 0x19, KEY_9 }, - { 0xf8, 0x10, KEY_0 }, - { 0xf8, 0x1c, KEY_MENU }, - { 0xf8, 0x0f, KEY_VOLUMEDOWN }, - { 0xf8, 0x1a, KEY_LAST }, - { 0xf8, 0x0e, KEY_OPEN }, - { 0xf8, 0x04, KEY_RECORD }, - { 0xf8, 0x09, KEY_VOLUMEUP }, - { 0xf8, 0x08, KEY_CHANNELUP }, - { 0xf8, 0x07, KEY_PVR }, - { 0xf8, 0x0b, KEY_TIME }, - { 0xf8, 0x02, KEY_RIGHT }, - { 0xf8, 0x03, KEY_LEFT }, - { 0xf8, 0x00, KEY_UP }, - { 0xf8, 0x1f, KEY_OK }, - { 0xf8, 0x01, KEY_DOWN }, - { 0xf8, 0x05, KEY_TUNER }, - { 0xf8, 0x06, KEY_CHANNELDOWN }, - { 0xf8, 0x40, KEY_PLAYPAUSE }, - { 0xf8, 0x1e, KEY_REWIND }, - { 0xf8, 0x1b, KEY_FAVORITES }, - { 0xf8, 0x1d, KEY_BACK }, - { 0xf8, 0x4d, KEY_FASTFORWARD }, - { 0xf8, 0x44, KEY_EPG }, - { 0xf8, 0x4c, KEY_INFO }, - { 0xf8, 0x41, KEY_AB }, - { 0xf8, 0x43, KEY_AUDIO }, - { 0xf8, 0x45, KEY_SUBTITLE }, - { 0xf8, 0x4a, KEY_LIST }, - { 0xf8, 0x46, KEY_F1 }, - { 0xf8, 0x47, KEY_F2 }, - { 0xf8, 0x5e, KEY_F3 }, - { 0xf8, 0x5c, KEY_F4 }, - { 0xf8, 0x52, KEY_F5 }, - { 0xf8, 0x5a, KEY_F6 }, - { 0xf8, 0x56, KEY_MODE }, - { 0xf8, 0x58, KEY_SWITCHVIDEOMODE }, + { 0xf80a, KEY_POWER }, + { 0xf80c, KEY_MUTE }, + { 0xf811, KEY_1 }, + { 0xf812, KEY_2 }, + { 0xf813, KEY_3 }, + { 0xf814, KEY_4 }, + { 0xf815, KEY_5 }, + { 0xf816, KEY_6 }, + { 0xf817, KEY_7 }, + { 0xf818, KEY_8 }, + { 0xf819, KEY_9 }, + { 0xf810, KEY_0 }, + { 0xf81c, KEY_MENU }, + { 0xf80f, KEY_VOLUMEDOWN }, + { 0xf81a, KEY_LAST }, + { 0xf80e, KEY_OPEN }, + { 0xf804, KEY_RECORD }, + { 0xf809, KEY_VOLUMEUP }, + { 0xf808, KEY_CHANNELUP }, + { 0xf807, KEY_PVR }, + { 0xf80b, KEY_TIME }, + { 0xf802, KEY_RIGHT }, + { 0xf803, KEY_LEFT }, + { 0xf800, KEY_UP }, + { 0xf81f, KEY_OK }, + { 0xf801, KEY_DOWN }, + { 0xf805, KEY_TUNER }, + { 0xf806, KEY_CHANNELDOWN }, + { 0xf840, KEY_PLAYPAUSE }, + { 0xf81e, KEY_REWIND }, + { 0xf81b, KEY_FAVORITES }, + { 0xf81d, KEY_BACK }, + { 0xf84d, KEY_FASTFORWARD }, + { 0xf844, KEY_EPG }, + { 0xf84c, KEY_INFO }, + { 0xf841, KEY_AB }, + { 0xf843, KEY_AUDIO }, + { 0xf845, KEY_SUBTITLE }, + { 0xf84a, KEY_LIST }, + { 0xf846, KEY_F1 }, + { 0xf847, KEY_F2 }, + { 0xf85e, KEY_F3 }, + { 0xf85c, KEY_F4 }, + { 0xf852, KEY_F5 }, + { 0xf85a, KEY_F6 }, + { 0xf856, KEY_MODE }, + { 0xf858, KEY_SWITCHVIDEOMODE }, }; static struct dvb_usb_rc_key tbs_rc_keys[] = { - { 0xf8, 0x84, KEY_POWER }, - { 0xf8, 0x94, KEY_MUTE }, - { 0xf8, 0x87, KEY_1 }, - { 0xf8, 0x86, KEY_2 }, - { 0xf8, 0x85, KEY_3 }, - { 0xf8, 0x8b, KEY_4 }, - { 0xf8, 0x8a, KEY_5 }, - { 0xf8, 0x89, KEY_6 }, - { 0xf8, 0x8f, KEY_7 }, - { 0xf8, 0x8e, KEY_8 }, - { 0xf8, 0x8d, KEY_9 }, - { 0xf8, 0x92, KEY_0 }, - { 0xf8, 0x96, KEY_CHANNELUP }, - { 0xf8, 0x91, KEY_CHANNELDOWN }, - { 0xf8, 0x93, KEY_VOLUMEUP }, - { 0xf8, 0x8c, KEY_VOLUMEDOWN }, - { 0xf8, 0x83, KEY_RECORD }, - { 0xf8, 0x98, KEY_PAUSE }, - { 0xf8, 0x99, KEY_OK }, - { 0xf8, 0x9a, KEY_SHUFFLE }, - { 0xf8, 0x81, KEY_UP }, - { 0xf8, 0x90, KEY_LEFT }, - { 0xf8, 0x82, KEY_RIGHT }, - { 0xf8, 0x88, KEY_DOWN }, - { 0xf8, 0x95, KEY_FAVORITES }, - { 0xf8, 0x97, KEY_SUBTITLE }, - { 0xf8, 0x9d, KEY_ZOOM }, - { 0xf8, 0x9f, KEY_EXIT }, - { 0xf8, 0x9e, KEY_MENU }, - { 0xf8, 0x9c, KEY_EPG }, - { 0xf8, 0x80, KEY_PREVIOUS }, - { 0xf8, 0x9b, KEY_MODE } + { 0xf884, KEY_POWER }, + { 0xf894, KEY_MUTE }, + { 0xf887, KEY_1 }, + { 0xf886, KEY_2 }, + { 0xf885, KEY_3 }, + { 0xf88b, KEY_4 }, + { 0xf88a, KEY_5 }, + { 0xf889, KEY_6 }, + { 0xf88f, KEY_7 }, + { 0xf88e, KEY_8 }, + { 0xf88d, KEY_9 }, + { 0xf892, KEY_0 }, + { 0xf896, KEY_CHANNELUP }, + { 0xf891, KEY_CHANNELDOWN }, + { 0xf893, KEY_VOLUMEUP }, + { 0xf88c, KEY_VOLUMEDOWN }, + { 0xf883, KEY_RECORD }, + { 0xf898, KEY_PAUSE }, + { 0xf899, KEY_OK }, + { 0xf89a, KEY_SHUFFLE }, + { 0xf881, KEY_UP }, + { 0xf890, KEY_LEFT }, + { 0xf882, KEY_RIGHT }, + { 0xf888, KEY_DOWN }, + { 0xf895, KEY_FAVORITES }, + { 0xf897, KEY_SUBTITLE }, + { 0xf89d, KEY_ZOOM }, + { 0xf89f, KEY_EXIT }, + { 0xf89e, KEY_MENU }, + { 0xf89c, KEY_EPG }, + { 0xf880, KEY_PREVIOUS }, + { 0xf89b, KEY_MODE } }; static struct dvb_usb_rc_keys_table keys_tables[] = { @@ -912,7 +912,7 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state) *state = REMOTE_NO_KEY_PRESSED; if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) { for (i = 0; i < keymap_size ; i++) { - if (keymap[i].data == msg.buf[0]) { + if (rc5_data(&keymap[i]) == msg.buf[0]) { *state = REMOTE_KEY_PRESSED; *event = keymap[i].event; break; diff --git a/linux/drivers/media/dvb/dvb-usb/m920x.c b/linux/drivers/media/dvb/dvb-usb/m920x.c index 51c1c8dba..55d2bb8f6 100644 --- a/linux/drivers/media/dvb/dvb-usb/m920x.c +++ b/linux/drivers/media/dvb/dvb-usb/m920x.c @@ -140,7 +140,7 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) goto unlock; for (i = 0; i < d->props.rc_key_map_size; i++) - if (d->props.rc_key_map[i].data == rc_state[1]) { + if (rc5_data(&d->props.rc_key_map[i]) == rc_state[1]) { *event = d->props.rc_key_map[i].event; switch(rc_state[0]) { @@ -565,42 +565,42 @@ static struct m920x_inits tvwalkertwin_rc_init [] = { /* ir keymaps */ static struct dvb_usb_rc_key megasky_rc_keys [] = { - { 0x0, 0x12, KEY_POWER }, - { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */ - { 0x0, 0x02, KEY_CHANNELUP }, - { 0x0, 0x05, KEY_CHANNELDOWN }, - { 0x0, 0x03, KEY_VOLUMEUP }, - { 0x0, 0x06, KEY_VOLUMEDOWN }, - { 0x0, 0x04, KEY_MUTE }, - { 0x0, 0x07, KEY_OK }, /* TS */ - { 0x0, 0x08, KEY_STOP }, - { 0x0, 0x09, KEY_MENU }, /* swap */ - { 0x0, 0x0a, KEY_REWIND }, - { 0x0, 0x1b, KEY_PAUSE }, - { 0x0, 0x1f, KEY_FASTFORWARD }, - { 0x0, 0x0c, KEY_RECORD }, - { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */ - { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ + { 0x0012, KEY_POWER }, + { 0x001e, KEY_CYCLEWINDOWS }, /* min/max */ + { 0x0002, KEY_CHANNELUP }, + { 0x0005, KEY_CHANNELDOWN }, + { 0x0003, KEY_VOLUMEUP }, + { 0x0006, KEY_VOLUMEDOWN }, + { 0x0004, KEY_MUTE }, + { 0x0007, KEY_OK }, /* TS */ + { 0x0008, KEY_STOP }, + { 0x0009, KEY_MENU }, /* swap */ + { 0x000a, KEY_REWIND }, + { 0x001b, KEY_PAUSE }, + { 0x001f, KEY_FASTFORWARD }, + { 0x000c, KEY_RECORD }, + { 0x000d, KEY_CAMERA }, /* screenshot */ + { 0x000e, KEY_COFFEE }, /* "MTS" */ }; static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = { - { 0x0, 0x01, KEY_ZOOM }, /* Full Screen */ - { 0x0, 0x02, KEY_CAMERA }, /* snapshot */ - { 0x0, 0x03, KEY_MUTE }, - { 0x0, 0x04, KEY_REWIND }, - { 0x0, 0x05, KEY_PLAYPAUSE }, /* Play/Pause */ - { 0x0, 0x06, KEY_FASTFORWARD }, - { 0x0, 0x07, KEY_RECORD }, - { 0x0, 0x08, KEY_STOP }, - { 0x0, 0x09, KEY_TIME }, /* Timeshift */ - { 0x0, 0x0c, KEY_COFFEE }, /* Recall */ - { 0x0, 0x0e, KEY_CHANNELUP }, - { 0x0, 0x12, KEY_POWER }, - { 0x0, 0x15, KEY_MENU }, /* source */ - { 0x0, 0x18, KEY_CYCLEWINDOWS }, /* TWIN PIP */ - { 0x0, 0x1a, KEY_CHANNELDOWN }, - { 0x0, 0x1b, KEY_VOLUMEDOWN }, - { 0x0, 0x1e, KEY_VOLUMEUP }, + { 0x0001, KEY_ZOOM }, /* Full Screen */ + { 0x0002, KEY_CAMERA }, /* snapshot */ + { 0x0003, KEY_MUTE }, + { 0x0004, KEY_REWIND }, + { 0x0005, KEY_PLAYPAUSE }, /* Play/Pause */ + { 0x0006, KEY_FASTFORWARD }, + { 0x0007, KEY_RECORD }, + { 0x0008, KEY_STOP }, + { 0x0009, KEY_TIME }, /* Timeshift */ + { 0x000c, KEY_COFFEE }, /* Recall */ + { 0x000e, KEY_CHANNELUP }, + { 0x0012, KEY_POWER }, + { 0x0015, KEY_MENU }, /* source */ + { 0x0018, KEY_CYCLEWINDOWS }, /* TWIN PIP */ + { 0x001a, KEY_CHANNELDOWN }, + { 0x001b, KEY_VOLUMEDOWN }, + { 0x001e, KEY_VOLUMEUP }, }; /* DVB USB Driver stuff */ diff --git a/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c index 07fb843c7..b41d66ef8 100644 --- a/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c @@ -22,51 +22,51 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); /* Hauppauge NOVA-T USB2 keys */ static struct dvb_usb_rc_key haupp_rc_keys [] = { - { 0x1e, 0x00, KEY_0 }, - { 0x1e, 0x01, KEY_1 }, - { 0x1e, 0x02, KEY_2 }, - { 0x1e, 0x03, KEY_3 }, - { 0x1e, 0x04, KEY_4 }, - { 0x1e, 0x05, KEY_5 }, - { 0x1e, 0x06, KEY_6 }, - { 0x1e, 0x07, KEY_7 }, - { 0x1e, 0x08, KEY_8 }, - { 0x1e, 0x09, KEY_9 }, - { 0x1e, 0x0a, KEY_KPASTERISK }, - { 0x1e, 0x0b, KEY_RED }, - { 0x1e, 0x0c, KEY_RADIO }, - { 0x1e, 0x0d, KEY_MENU }, - { 0x1e, 0x0e, KEY_GRAVE }, /* # */ - { 0x1e, 0x0f, KEY_MUTE }, - { 0x1e, 0x10, KEY_VOLUMEUP }, - { 0x1e, 0x11, KEY_VOLUMEDOWN }, - { 0x1e, 0x12, KEY_CHANNEL }, - { 0x1e, 0x14, KEY_UP }, - { 0x1e, 0x15, KEY_DOWN }, - { 0x1e, 0x16, KEY_LEFT }, - { 0x1e, 0x17, KEY_RIGHT }, - { 0x1e, 0x18, KEY_VIDEO }, - { 0x1e, 0x19, KEY_AUDIO }, - { 0x1e, 0x1a, KEY_MEDIA }, - { 0x1e, 0x1b, KEY_EPG }, - { 0x1e, 0x1c, KEY_TV }, - { 0x1e, 0x1e, KEY_NEXT }, - { 0x1e, 0x1f, KEY_BACK }, - { 0x1e, 0x20, KEY_CHANNELUP }, - { 0x1e, 0x21, KEY_CHANNELDOWN }, - { 0x1e, 0x24, KEY_LAST }, /* Skip backwards */ - { 0x1e, 0x25, KEY_OK }, - { 0x1e, 0x29, KEY_BLUE}, - { 0x1e, 0x2e, KEY_GREEN }, - { 0x1e, 0x30, KEY_PAUSE }, - { 0x1e, 0x32, KEY_REWIND }, - { 0x1e, 0x34, KEY_FASTFORWARD }, - { 0x1e, 0x35, KEY_PLAY }, - { 0x1e, 0x36, KEY_STOP }, - { 0x1e, 0x37, KEY_RECORD }, - { 0x1e, 0x38, KEY_YELLOW }, - { 0x1e, 0x3b, KEY_GOTO }, - { 0x1e, 0x3d, KEY_POWER }, + { 0x1e00, KEY_0 }, + { 0x1e01, KEY_1 }, + { 0x1e02, KEY_2 }, + { 0x1e03, KEY_3 }, + { 0x1e04, KEY_4 }, + { 0x1e05, KEY_5 }, + { 0x1e06, KEY_6 }, + { 0x1e07, KEY_7 }, + { 0x1e08, KEY_8 }, + { 0x1e09, KEY_9 }, + { 0x1e0a, KEY_KPASTERISK }, + { 0x1e0b, KEY_RED }, + { 0x1e0c, KEY_RADIO }, + { 0x1e0d, KEY_MENU }, + { 0x1e0e, KEY_GRAVE }, /* # */ + { 0x1e0f, KEY_MUTE }, + { 0x1e10, KEY_VOLUMEUP }, + { 0x1e11, KEY_VOLUMEDOWN }, + { 0x1e12, KEY_CHANNEL }, + { 0x1e14, KEY_UP }, + { 0x1e15, KEY_DOWN }, + { 0x1e16, KEY_LEFT }, + { 0x1e17, KEY_RIGHT }, + { 0x1e18, KEY_VIDEO }, + { 0x1e19, KEY_AUDIO }, + { 0x1e1a, KEY_MEDIA }, + { 0x1e1b, KEY_EPG }, + { 0x1e1c, KEY_TV }, + { 0x1e1e, KEY_NEXT }, + { 0x1e1f, KEY_BACK }, + { 0x1e20, KEY_CHANNELUP }, + { 0x1e21, KEY_CHANNELDOWN }, + { 0x1e24, KEY_LAST }, /* Skip backwards */ + { 0x1e25, KEY_OK }, + { 0x1e29, KEY_BLUE}, + { 0x1e2e, KEY_GREEN }, + { 0x1e30, KEY_PAUSE }, + { 0x1e32, KEY_REWIND }, + { 0x1e34, KEY_FASTFORWARD }, + { 0x1e35, KEY_PLAY }, + { 0x1e36, KEY_STOP }, + { 0x1e37, KEY_RECORD }, + { 0x1e38, KEY_YELLOW }, + { 0x1e3b, KEY_GOTO }, + { 0x1e3d, KEY_POWER }, }; /* Firmware bug? sometimes, when a new key is pressed, the previous pressed key @@ -92,10 +92,11 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state) deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle); for (i = 0; i < ARRAY_SIZE(haupp_rc_keys); i++) { - if (haupp_rc_keys[i].data == data && - haupp_rc_keys[i].custom == custom) { + if (rc5_data(&haupp_rc_keys[i]) == data && + rc5_custom(&haupp_rc_keys[i]) == custom) { - deb_rc("c: %x, d: %x\n",haupp_rc_keys[i].data,haupp_rc_keys[i].custom); + deb_rc("c: %x, d: %x\n", rc5_data(&haupp_rc_keys[i]), + rc5_custom(&haupp_rc_keys[i])); *event = haupp_rc_keys[i].event; *state = REMOTE_KEY_PRESSED; diff --git a/linux/drivers/media/dvb/dvb-usb/opera1.c b/linux/drivers/media/dvb/dvb-usb/opera1.c index d45ceb83b..6b22023b2 100644 --- a/linux/drivers/media/dvb/dvb-usb/opera1.c +++ b/linux/drivers/media/dvb/dvb-usb/opera1.c @@ -346,32 +346,32 @@ static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff) } static struct dvb_usb_rc_key opera1_rc_keys[] = { - {0x5f, 0xa0, KEY_1}, - {0x51, 0xaf, KEY_2}, - {0x5d, 0xa2, KEY_3}, - {0x41, 0xbe, KEY_4}, - {0x0b, 0xf5, KEY_5}, - {0x43, 0xbd, KEY_6}, - {0x47, 0xb8, KEY_7}, - {0x49, 0xb6, KEY_8}, - {0x05, 0xfa, KEY_9}, - {0x45, 0xba, KEY_0}, - {0x09, 0xf6, KEY_UP}, /*chanup */ - {0x1b, 0xe5, KEY_DOWN}, /*chandown */ - {0x5d, 0xa3, KEY_LEFT}, /*voldown */ - {0x5f, 0xa1, KEY_RIGHT}, /*volup */ - {0x07, 0xf8, KEY_SPACE}, /*tab */ - {0x1f, 0xe1, KEY_ENTER}, /*play ok */ - {0x1b, 0xe4, KEY_Z}, /*zoom */ - {0x59, 0xa6, KEY_M}, /*mute */ - {0x5b, 0xa5, KEY_F}, /*tv/f */ - {0x19, 0xe7, KEY_R}, /*rec */ - {0x01, 0xfe, KEY_S}, /*Stop */ - {0x03, 0xfd, KEY_P}, /*pause */ - {0x03, 0xfc, KEY_W}, /*<- -> */ - {0x07, 0xf9, KEY_C}, /*capture */ - {0x47, 0xb9, KEY_Q}, /*exit */ - {0x43, 0xbc, KEY_O}, /*power */ + {0x5fa0, KEY_1}, + {0x51af, KEY_2}, + {0x5da2, KEY_3}, + {0x41be, KEY_4}, + {0x0bf5, KEY_5}, + {0x43bd, KEY_6}, + {0x47b8, KEY_7}, + {0x49b6, KEY_8}, + {0x05fa, KEY_9}, + {0x45ba, KEY_0}, + {0x09f6, KEY_UP}, /*chanup */ + {0x1be5, KEY_DOWN}, /*chandown */ + {0x5da3, KEY_LEFT}, /*voldown */ + {0x5fa1, KEY_RIGHT}, /*volup */ + {0x07f8, KEY_SPACE}, /*tab */ + {0x1fe1, KEY_ENTER}, /*play ok */ + {0x1be4, KEY_Z}, /*zoom */ + {0x59a6, KEY_M}, /*mute */ + {0x5ba5, KEY_F}, /*tv/f */ + {0x19e7, KEY_R}, /*rec */ + {0x01fe, KEY_S}, /*Stop */ + {0x03fd, KEY_P}, /*pause */ + {0x03fc, KEY_W}, /*<- -> */ + {0x07f9, KEY_C}, /*capture */ + {0x47b9, KEY_Q}, /*exit */ + {0x43bc, KEY_O}, /*power */ }; @@ -419,8 +419,7 @@ static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state) send_key = (send_key & 0xffff) | 0x0100; for (i = 0; i < ARRAY_SIZE(opera1_rc_keys); i++) { - if ((opera1_rc_keys[i].custom * 256 + - opera1_rc_keys[i].data) == (send_key & 0xffff)) { + if (rc5_scan(&opera1_rc_keys[i]) == (send_key & 0xffff)) { *state = REMOTE_KEY_PRESSED; *event = opera1_rc_keys[i].event; opst->last_key_pressed = diff --git a/linux/drivers/media/dvb/dvb-usb/vp702x.c b/linux/drivers/media/dvb/dvb-usb/vp702x.c index c1db3271f..378e9d12a 100644 --- a/linux/drivers/media/dvb/dvb-usb/vp702x.c +++ b/linux/drivers/media/dvb/dvb-usb/vp702x.c @@ -207,8 +207,8 @@ static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) /* keys for the enclosed remote control */ static struct dvb_usb_rc_key vp702x_rc_keys[] = { - { 0x00, 0x01, KEY_1 }, - { 0x00, 0x02, KEY_2 }, + { 0x0001, KEY_1 }, + { 0x0002, KEY_2 }, }; /* remote control stuff (does not work with my box) */ @@ -230,7 +230,7 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) } for (i = 0; i < ARRAY_SIZE(vp702x_rc_keys); i++) - if (vp702x_rc_keys[i].custom == key[1]) { + if (rc5_custom(&vp702x_rc_keys[i]) == key[1]) { *state = REMOTE_KEY_PRESSED; *event = vp702x_rc_keys[i].event; break; diff --git a/linux/drivers/media/dvb/dvb-usb/vp7045.c b/linux/drivers/media/dvb/dvb-usb/vp7045.c index 8fc2ba02a..dc69ad9ef 100644 --- a/linux/drivers/media/dvb/dvb-usb/vp7045.c +++ b/linux/drivers/media/dvb/dvb-usb/vp7045.c @@ -100,56 +100,56 @@ static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff) /* The keymapping struct. Somehow this should be loaded to the driver, but * currently it is hardcoded. */ static struct dvb_usb_rc_key vp7045_rc_keys[] = { - { 0x00, 0x16, KEY_POWER }, - { 0x00, 0x10, KEY_MUTE }, - { 0x00, 0x03, KEY_1 }, - { 0x00, 0x01, KEY_2 }, - { 0x00, 0x06, KEY_3 }, - { 0x00, 0x09, KEY_4 }, - { 0x00, 0x1d, KEY_5 }, - { 0x00, 0x1f, KEY_6 }, - { 0x00, 0x0d, KEY_7 }, - { 0x00, 0x19, KEY_8 }, - { 0x00, 0x1b, KEY_9 }, - { 0x00, 0x15, KEY_0 }, - { 0x00, 0x05, KEY_CHANNELUP }, - { 0x00, 0x02, KEY_CHANNELDOWN }, - { 0x00, 0x1e, KEY_VOLUMEUP }, - { 0x00, 0x0a, KEY_VOLUMEDOWN }, - { 0x00, 0x11, KEY_RECORD }, - { 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */ - { 0x00, 0x14, KEY_PLAY }, - { 0x00, 0x1a, KEY_STOP }, - { 0x00, 0x40, KEY_REWIND }, - { 0x00, 0x12, KEY_FASTFORWARD }, - { 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */ - { 0x00, 0x4c, KEY_PAUSE }, - { 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */ - { 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ - { 0x00, 0x0c, KEY_CANCEL }, /* Cancel */ - { 0x00, 0x1c, KEY_EPG }, /* EPG */ - { 0x00, 0x00, KEY_TAB }, /* Tab */ - { 0x00, 0x48, KEY_INFO }, /* Preview */ - { 0x00, 0x04, KEY_LIST }, /* RecordList */ - { 0x00, 0x0f, KEY_TEXT }, /* Teletext */ - { 0x00, 0x41, KEY_PREVIOUSSONG }, - { 0x00, 0x42, KEY_NEXTSONG }, - { 0x00, 0x4b, KEY_UP }, - { 0x00, 0x51, KEY_DOWN }, - { 0x00, 0x4e, KEY_LEFT }, - { 0x00, 0x52, KEY_RIGHT }, - { 0x00, 0x4f, KEY_ENTER }, - { 0x00, 0x13, KEY_CANCEL }, - { 0x00, 0x4a, KEY_CLEAR }, - { 0x00, 0x54, KEY_PRINT }, /* Capture */ - { 0x00, 0x43, KEY_SUBTITLE }, /* Subtitle/CC */ - { 0x00, 0x08, KEY_VIDEO }, /* A/V */ - { 0x00, 0x07, KEY_SLEEP }, /* Hibernate */ - { 0x00, 0x45, KEY_ZOOM }, /* Zoom+ */ - { 0x00, 0x18, KEY_RED}, - { 0x00, 0x53, KEY_GREEN}, - { 0x00, 0x5e, KEY_YELLOW}, - { 0x00, 0x5f, KEY_BLUE} + { 0x0016, KEY_POWER }, + { 0x0010, KEY_MUTE }, + { 0x0003, KEY_1 }, + { 0x0001, KEY_2 }, + { 0x0006, KEY_3 }, + { 0x0009, KEY_4 }, + { 0x001d, KEY_5 }, + { 0x001f, KEY_6 }, + { 0x000d, KEY_7 }, + { 0x0019, KEY_8 }, + { 0x001b, KEY_9 }, + { 0x0015, KEY_0 }, + { 0x0005, KEY_CHANNELUP }, + { 0x0002, KEY_CHANNELDOWN }, + { 0x001e, KEY_VOLUMEUP }, + { 0x000a, KEY_VOLUMEDOWN }, + { 0x0011, KEY_RECORD }, + { 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */ + { 0x0014, KEY_PLAY }, + { 0x001a, KEY_STOP }, + { 0x0040, KEY_REWIND }, + { 0x0012, KEY_FASTFORWARD }, + { 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */ + { 0x004c, KEY_PAUSE }, + { 0x004d, KEY_SCREEN }, /* Full screen mode. */ + { 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ + { 0x000c, KEY_CANCEL }, /* Cancel */ + { 0x001c, KEY_EPG }, /* EPG */ + { 0x0000, KEY_TAB }, /* Tab */ + { 0x0048, KEY_INFO }, /* Preview */ + { 0x0004, KEY_LIST }, /* RecordList */ + { 0x000f, KEY_TEXT }, /* Teletext */ + { 0x0041, KEY_PREVIOUSSONG }, + { 0x0042, KEY_NEXTSONG }, + { 0x004b, KEY_UP }, + { 0x0051, KEY_DOWN }, + { 0x004e, KEY_LEFT }, + { 0x0052, KEY_RIGHT }, + { 0x004f, KEY_ENTER }, + { 0x0013, KEY_CANCEL }, + { 0x004a, KEY_CLEAR }, + { 0x0054, KEY_PRINT }, /* Capture */ + { 0x0043, KEY_SUBTITLE }, /* Subtitle/CC */ + { 0x0008, KEY_VIDEO }, /* A/V */ + { 0x0007, KEY_SLEEP }, /* Hibernate */ + { 0x0045, KEY_ZOOM }, /* Zoom+ */ + { 0x0018, KEY_RED}, + { 0x0053, KEY_GREEN}, + { 0x005e, KEY_YELLOW}, + { 0x005f, KEY_BLUE} #if 0 /* not sure which linux key codes to use for the following buttons: */ { 0x00, 0x46, ???}, /* Zoom- */ @@ -174,7 +174,7 @@ static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) } for (i = 0; i < ARRAY_SIZE(vp7045_rc_keys); i++) - if (vp7045_rc_keys[i].data == key) { + if (rc5_data(&vp7045_rc_keys[i]) == key) { *state = REMOTE_KEY_PRESSED; *event = vp7045_rc_keys[i].event; break; -- cgit v1.2.3 From e6159c2982e6ea65d49c90e25b11bcc74aab554a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 15:27:29 -0300 Subject: dvb-usb-remote: Allow dynamically replacing the IR keycodes From: Mauro Carvalho Chehab Implements handler for EVIOCGKEYCODE/EVIOCSKEYCODE via adding two new callbacks to the input device. Since on dvb-usb a scan code has 16 bits, to fulfill rc5 standard codes, the default getkeycode/setkeycode input methods would require the driver to spend up to 64 Kb of a sparse table. Instead, add two new callbacks to the event device. With this, it is now possible to replace the keycode tables. There are, however, a few implementation details at the current patch: 1) It will replace the existing device keytable, instead of creating an instance of the data. This works. However, if two devices pointing to the same table were connected, changing the IR table of one will also change the IR table for the other (the solution for this one is simple: just kmalloc some memory); 2) In order to change the scan code, you need first to change the key to KEY_RESERVED or KEY_UNKNOWN to free some space at the table (solution: allocate some additional space for newer scan codes or allow dynamic table grow); 3) The table size cannot be extended. It would be easy to allow the table to grow dynamically: just calling kmalloc(size+1); kfree(old). Yet, maybe we can just create a bigger table with a fixed size, like for example a table with 128 entries. This should be enough even for a very big IR. The current issues should be addressed on a later patch. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 56 ++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index e1d07f1ce..e7af19614 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -12,6 +12,58 @@ #include #endif +static int dvb_usb_getkeycode(struct input_dev *dev, + int scancode, int *keycode) +{ + struct dvb_usb_device *d = input_get_drvdata(dev); + + struct dvb_usb_rc_key *keymap = d->props.rc_key_map; + int i; + + /* See if we can match the raw key code. */ + for (i = 0; i < d->props.rc_key_map_size; i++) + if (keymap[i].scan == scancode) { + *keycode = keymap[i].event; + return 0; + } + return -EINVAL; +} + +static int dvb_usb_setkeycode(struct input_dev *dev, + int scancode, int keycode) +{ + struct dvb_usb_device *d = input_get_drvdata(dev); + + struct dvb_usb_rc_key *keymap = d->props.rc_key_map; + int i; + + /* Search if it is replacing an existing keycode */ + for (i = 0; i < d->props.rc_key_map_size; i++) + if (keymap[i].scan == scancode) { + keymap[i].event = keycode; + return 0; + } + + /* Search if is there a clean entry. If so, use it */ + for (i = 0; i < d->props.rc_key_map_size; i++) + if (keymap[i].event == KEY_RESERVED || + keymap[i].event == KEY_UNKNOWN) { + keymap[i].scan = scancode; + keymap[i].event = keycode; + return 0; + } + + /* + * FIXME: Currently, it is not possible to increase the size of + * scancode table. For it to happen, one possibility + * would be to allocate a table with key_map_size + 1, + * copying data, appending the new key on it, and freeing + * the old one - or maybe just allocating some spare space + */ + + return -EINVAL; +} + /* Remote-control poll function - called every dib->rc_query_interval ms to see * whether the remote control has received anything. * @@ -127,6 +179,8 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) #else input_dev->cdev.dev = &d->udev->dev; #endif + input_dev->getkeycode = dvb_usb_getkeycode; + input_dev->setkeycode = dvb_usb_setkeycode; /* set the bits for the keys */ deb_rc("key map size: %d\n", d->props.rc_key_map_size); @@ -144,6 +198,8 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) input_dev->rep[REP_PERIOD] = d->props.rc_interval; input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; + input_set_drvdata(input_dev, d); + err = input_register_device(input_dev); if (err) { input_free_device(input_dev); -- cgit v1.2.3 From 8bb736e60de8ac0d4fdff3d50a7d79098fac81a5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 22:03:47 -0300 Subject: dvb-usb-remote: return KEY_RESERVED if there's free space for new keys From: Mauro Carvalho Chehab The input subsystem checks if get_keycode works for a scan code. Due to that, we need to return a valid value when there's some space at the table that can be used by a scancode. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index e7af19614..df72c8637 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -26,6 +26,19 @@ static int dvb_usb_getkeycode(struct input_dev *dev, *keycode = keymap[i].event; return 0; } + + /* + * If is there extra space, returns KEY_RESERVED, + * otherwise, input core won't let dvb_usb_setkeycode + * to work + */ + for (i = 0; i < d->props.rc_key_map_size; i++) + if (keymap[i].event == KEY_RESERVED || + keymap[i].event == KEY_UNKNOWN) { + *keycode = KEY_RESERVED; + return 0; + } + return -EINVAL; } -- cgit v1.2.3 From 5022fe1de9de096b1b94c17c701a733b068e6c1d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 22:04:40 -0300 Subject: gen_keytables.pl: Fix parsing for some IR tables From: Mauro Carvalho Chehab There are some tables where the last value ends with } Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/gen_keytables.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v4l2-apps/util/gen_keytables.pl b/v4l2-apps/util/gen_keytables.pl index 5a5398017..fad4ccfeb 100755 --- a/v4l2-apps/util/gen_keytables.pl +++ b/v4l2-apps/util/gen_keytables.pl @@ -14,7 +14,7 @@ while (<>) { next; } if ($keyname ne "") { - if (m/(0x[\dA-Fa-f]+).*(KEY_[^\s\,]+)/) { + if (m/(0x[\dA-Fa-f]+).*(KEY_[^\s\,\}]+)/) { printf OUT "%s %s\n",$1, $2; next; } -- cgit v1.2.3 From ff3dc3830a3899cbad05f00bc72220c47ad35ef6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 22:05:06 -0300 Subject: keytable: Prints a more comprehensive error message From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/keytable.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/util/keytable.c b/v4l2-apps/util/keytable.c index 4b39a43f0..d7644d775 100644 --- a/v4l2-apps/util/keytable.c +++ b/v4l2-apps/util/keytable.c @@ -146,8 +146,10 @@ int main (int argc, char *argv[]) codes [1] = (unsigned) value; // printf("\t%04x=%04x\n",codes[0], codes[1]); - if(ioctl(fd, EVIOCSKEYCODE, codes)) + if(ioctl(fd, EVIOCSKEYCODE, codes)) { + fprintf(stderr, "Setting scancode 0x%04x with 0x%04x via ",codes[0], codes[1]); perror ("EVIOCSKEYCODE"); + } if(ioctl(fd, EVIOCGKEYCODE, codes)==0) prtcode(codes); -- cgit v1.2.3 From 78ef9b9eb5faa72a5a279aa99293584491475e39 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 29 Aug 2009 22:11:23 -0300 Subject: keytable: Don't display KEY_RESERVED codes From: Mauro Carvalho Chehab As KEY_RESERVED is used for some spare space at the keycode table, don't return it while displaying the current table Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/keytable.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v4l2-apps/util/keytable.c b/v4l2-apps/util/keytable.c index d7644d775..4283782d0 100644 --- a/v4l2-apps/util/keytable.c +++ b/v4l2-apps/util/keytable.c @@ -107,7 +107,7 @@ int main (int argc, char *argv[]) for (j = 0; j < 256; j++) { for (i = 0; i < 256; i++) { codes[0] = (j << 8) | i; - codes[1] = KEY_UNKNOWN; + codes[1] = KEY_RESERVED; ioctl(fd, EVIOCSKEYCODE, codes); } } @@ -161,7 +161,7 @@ int main (int argc, char *argv[]) for (j = 0; j < 256; j++) { for (i = 0; i < 256; i++) { codes[0] = (j << 8) | i; - if(ioctl(fd, EVIOCGKEYCODE, codes)==0) + if (!ioctl(fd, EVIOCGKEYCODE, codes) && codes[1] != KEY_RESERVED) prtcode(codes); } } -- cgit v1.2.3 From cb8ac312f5583e64bbc098ba31bbcca6383a9748 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 30 Aug 2009 05:51:07 +0000 Subject: 2: fix typos in INSTALL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Márton Németh Fix some typos in INSTALL documentation coming from http://linuxtv.org/hg/v4l-dvb . Priority: low Signed-off-by: Márton Németh Signed-off-by: Mauro Carvalho Chehab --- INSTALL | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/INSTALL b/INSTALL index c154677d5..3a4ea7cec 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,7 @@ Mauro Carvalho Chehab 2006 Apr 26 V4L/DVB building procedures are based at the use of Makefile rules. -Those rules are close tho the ones at Linux Kernel, to allow an easier +Those rules are close to the ones at Linux Kernel, to allow an easier usage. ======================================================================= @@ -9,7 +9,7 @@ Quick building procedure is: make all ====================================================================== -For those that may want more than just build all stuff there are some +For those who may want more than just build all stuff there are some other interesting parameters to make: ====================== @@ -136,7 +136,7 @@ checkterse - checks codingstyle and reports using terse syntax, used on several compilaton tools. mismatch - checks for linker section mismatch. In other words, - check if some driver has functions not properly + check if some driver has functions not properly declared with __init/__exit, and similar tags. - It will also be more pedantic by dealing with + It will also be more pedantic by dealing with compilation warnings as if they are errors. -- cgit v1.2.3 From 2d8ac7c9c23a7411207babb853ddd3202b980774 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 30 Aug 2009 16:05:56 +0000 Subject: em28xx: Add entry for GADMEI UTV330+ and related IR keymap From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Shine Liu [mchehab@redhat.com: Fix a few wrong IR keymaps] Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.em28xx | 1 + linux/drivers/media/common/ir-keymaps.c | 44 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-cards.c | 22 +++++++++++++ linux/drivers/media/video/em28xx/em28xx.h | 1 + 4 files changed, 68 insertions(+) diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index 66e5f8295..b37eff3c9 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -67,3 +67,4 @@ 69 -> KWorld ATSC 315U HDTV TV Box (em2882) [eb1a:a313] 70 -> Evga inDtube (em2882) 71 -> Silvercrest Webcam 1.3mpix (em2820/em2840) + 72 -> Gadmei UTV330+ (em2861) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 7ab7d0586..25b9a243e 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -2886,3 +2886,47 @@ IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = { [0x20] = KEY_TEXT, }; EXPORT_SYMBOL_GPL(ir_codes_videomate_s350); + + +/* GADMEI UTV330+ RM008Z remote + Shine Liu + */ +IR_KEYTAB_TYPE ir_codes_gadmei_rm008z[IR_KEYTAB_SIZE] = { + [0x14] = KEY_POWER2, /* POWER OFF */ + [0x0c] = KEY_MUTE, /* MUTE */ + + [0x18] = KEY_TV, /* TV */ + [0x0e] = KEY_VIDEO, /* AV */ + [0x0b] = KEY_AUDIO, /* SV */ + [0x0f] = KEY_RADIO, /* FM */ + + [0x00] = KEY_1, + [0x01] = KEY_2, + [0x02] = KEY_3, + [0x03] = KEY_4, + [0x04] = KEY_5, + [0x05] = KEY_6, + [0x06] = KEY_7, + [0x07] = KEY_8, + [0x08] = KEY_9, + [0x09] = KEY_0, + [0x0a] = KEY_INFO, /* OSD */ + [0x1c] = KEY_BACKSPACE, /* LAST */ + + [0x0d] = KEY_PLAY, /* PLAY */ + [0x1e] = KEY_CAMERA, /* SNAPSHOT */ + [0x1a] = KEY_RECORD, /* RECORD */ + [0x17] = KEY_STOP, /* STOP */ + + [0x1f] = KEY_UP, /* UP */ + [0x44] = KEY_DOWN, /* DOWN */ + [0x46] = KEY_TAB, /* BACK */ + [0x4a] = KEY_ZOOM, /* FULLSECREEN */ + + [0x10] = KEY_VOLUMEUP, /* VOLUMEUP */ + [0x11] = KEY_VOLUMEDOWN, /* VOLUMEDOWN */ + [0x12] = KEY_CHANNELUP, /* CHANNELUP */ + [0x13] = KEY_CHANNELDOWN, /* CHANNELDOWN */ + [0x15] = KEY_ENTER, /* OK */ +}; +EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z); diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 07644ec5e..d50b478a4 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -574,6 +574,27 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, + [EM2861_BOARD_GADMEI_UTV330PLUS] = { + .name = "Gadmei UTV330+", + .tuner_type = TUNER_TNF_5335MF, + .tda9887_conf = TDA9887_PRESENT, + .ir_codes = ir_codes_gadmei_rm008z, + .decoder = EM28XX_SAA711X, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = SAA7115_COMPOSITE2, + .amux = EM28XX_AMUX_VIDEO, + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, [EM2860_BOARD_TERRATEC_HYBRID_XS] = { .name = "Terratec Cinergy A Hybrid XS", .valid = EM28XX_BOARD_NOT_VALIDATED, @@ -1744,6 +1765,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, {0x1ba50080, EM2860_BOARD_SAA711X_REFERENCE_DESIGN, TUNER_ABSENT}, {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, + {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF}, }; /* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */ diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 8203c6e1d..68f274dcc 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -109,6 +109,7 @@ #define EM2882_BOARD_KWORLD_ATSC_315U 69 #define EM2882_BOARD_EVGA_INDTUBE 70 #define EM2820_BOARD_SILVERCREST_WEBCAM 71 +#define EM2861_BOARD_GADMEI_UTV330PLUS 72 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From 886c0206b83fbc0241cd3842ed49fd002831f1d9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 31 Aug 2009 00:53:47 -0300 Subject: v4l2-spec: Start documenting IR tables From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l2-spec/Makefile | 1 + v4l2-spec/remote_controllers.sgml | 155 ++++++++++++++++++++++++++++++++++++++ v4l2-spec/v4l2.sgml | 4 + 3 files changed, 160 insertions(+) create mode 100644 v4l2-spec/remote_controllers.sgml diff --git a/v4l2-spec/Makefile b/v4l2-spec/Makefile index ee5d80688..73d48d00d 100644 --- a/v4l2-spec/Makefile +++ b/v4l2-spec/Makefile @@ -22,6 +22,7 @@ SGMLS = \ dev-teletext.sgml \ driver.sgml \ libv4l.sgml \ + remote_controllers.sgml \ entities.sgml \ fdl-appendix.sgml \ func-close.sgml \ diff --git a/v4l2-spec/remote_controllers.sgml b/v4l2-spec/remote_controllers.sgml new file mode 100644 index 000000000..29bdbd54f --- /dev/null +++ b/v4l2-spec/remote_controllers.sgml @@ -0,0 +1,155 @@ +Remote Controllers +
+Introduction + +TODO + + +IR default keymapping + +&cs-str; + + +Key code +Meaning +Key examples on IR + + +Numeric keys + +KEY_0Keyboard digit 00 +KEY_1Keyboard digit 11 +KEY_2Keyboard digit 22 +KEY_3Keyboard digit 33 +KEY_4Keyboard digit 44 +KEY_5Keyboard digit 55 +KEY_6Keyboard digit 66 +KEY_7Keyboard digit 77 +KEY_8Keyboard digit 88 +KEY_9Keyboard digit 99 + +Movie play control + +KEY_FORWARDInstantly advance in time>> / FORWARD +KEY_BACKInstantly go back in time<<< / BACK +KEY_FASTFORWARDPlay movie faster>>> / FORWARD +KEY_REWINDPlay movie backREWIND / BACKWARD +KEY_NEXTSelect next chapter / sub-chapter / intervalNEXT / SKIP +KEY_PREVIOUSSelect previous chapter / sub-chapter / interval<< / PREV / PREVIOUS +KEY_AGAINRepeat the video or a video intervalREPEAT / LOOP / RECALL +KEY_PAUSEPause sroweamPAUSE / FREEZE +KEY_PLAYPlay movie at the normal timeshiftNORMAL TIMESHIFT / LIVE / > +KEY_PLAYPAUSEAlternate between play and pausePLAY / PAUSE +KEY_STOPStop sroweamSTOP +KEY_RECORDStart/stop recording sroweamCAPTURE / REC / RECORD/PAUSE +KEY_CAMERATake a picture of the imageCAMERA ICON / CAPTURE / SNAPSHOT +KEY_SHUFFLEEnable shuffle modeSHUFFLE +KEY_TIMEActivate time shift modeTIME SHIFT +KEY_TITLEAllow changing the chapterCHAPTER +KEY_SUBTITLEAllow changing the subtitleSUBTITLE + +Image control + +KEY_BRIGHTNESSDOWNDecrease BrightnessBRIGHTNESS DECREASE +KEY_BRIGHTNESSUPIncrease BrightnessBRIGHTNESS INCREASE + +KEY_ANGLESwitch video camera angle (on videos with more than one angle stored)ANGLE / SWAP +KEY_EPGOpen the Elecrowonic Play Guide (EPG)EPG / GUIDE +KEY_TEXTActivate/change closed caption modeCLOSED CAPTION/TELETEXT / DVD TEXT / TELETEXT / TTX + +Audio control + +KEY_AUDIOChange audio sourceAUDIO SOURCE / AUDIO / MUSIC +KEY_MUTEMute/unmute audioMUTE / DEMUTE / UNMUTE +KEY_VOLUMEDOWNDecrease volumeVOLUME- / VOLUME DOWN +KEY_VOLUMEUPIncrease volumeVOLUME+ / VOLUME UP +KEY_MODEChange sound modeMONO/STEREO +KEY_LANGUAGESelect Language1ST / 2ND LANGUAGE / DVD LANG / MTS/SAP / MTS SEL + +Channel control + +KEY_CHANNELGo to the next favorite channelALT / CHANNEL / CH SURFING / SURF / FAV +KEY_CHANNELDOWNDecrease channel sequenciallyCHANNEL - / CHANNEL DOWN / DOWN +KEY_CHANNELUPIncrease channel sequenciallyCHANNEL + / CHANNEL UP / UP +KEY_DIGITSUse more than one digit for channelPLUS / 100/ 1xx / xxx / -/-- / Single Double Triple Digit +KEY_SEARCHStart channel autoscanSCAN / AUTOSCAN + +Colored keys + +KEY_BLUEIR Blue keyBLUE +KEY_GREENIR Green KeyGREEN +KEY_REDIR Red keyRED +KEY_YELLOWIR Yellow key YELLOW + +Media selection + +KEY_CDChange input source to Compact DiscCD +KEY_DVDChange input to DVDDVD / DVD MENU +KEY_EJECTCLOSECDOpen/close the CD/DVD player-> ) / CLOSE / OPEN + +KEY_MEDIATurn on/off Media applicationPC/TV / TURN ON/OFF APP +KEY_PCSelects from TV to PCPC +KEY_RADIOPut into AM/FM radio modeRADIO / TV/FM / TV/RADIO / FM / FM/RADIO +KEY_TVSelect tv modeTV / LIVE TV +KEY_TV2Select Cable modeAIR/CBL +KEY_VCRSelect VCR modeVCR MODE / DTR +KEY_VIDEOAlternate between input modesSOURCE / SELECT / DISPLAY / SWITCH INPUTS / VIDEO + +Power control + +KEY_POWERTurn on/off computerSYSTEM POWER / COMPUTER POWER +KEY_POWER2Turn on/off applicationTV ON/OFF / POWER +KEY_SLEEPActivate sleep timerSLEEP / SLEEP TIMER +KEY_SUSPENDPut computer into suspend modeSTANDBY / SUSPEND + +Window control + +KEY_CLEARStop sroweam and return to default input video/audioCLEAR / RESET / BOSS KEY +KEY_CYCLEWINDOWSMinimize windows and move to the next oneALT-TAB / MINIMIZE / DESKTOP +KEY_FAVORITESOpen the favorites sroweam windowTV WALL / Favorites +KEY_MENUCall application menu2ND CONTROLS (USA: MENU) / DVD/MENU / SHOW/HIDE CTRL +KEY_NEWOpen/Close Picture in PicturePIP +KEY_OKSend a confirmation code to applicationOK / ENTER / RETURN +KEY_SCREENSelect screen aspect ratio4:3 16:9 SELECT +KEY_ZOOMPut device into zoom/full screen modeZOOM / FULL SCREEN / ZOOM+ / HIDE PANNEL / SWITCH + +Navigation keys + +KEY_ESCCancel current operationCANCEL / BACK +KEY_HELPOpen a Help windowHELP +KEY_HOMEPAGENavigate to HomepageHOME +KEY_INFOOpen On Screen DisplayDISPLAY INFORMATION / OSD +KEY_WWWOpen the default browserWEB +KEY_UPUp keyUP +KEY_DOWNDown keyDOWN +KEY_LEFTLeft keyLEFT +KEY_RIGHTRight keyRIGHT + +Miscelaneous keys + +KEY_DOTReturn a dot. +KEY_FNSelect a functionFUNCTION + + + +
+ + +Notes + +&cs-str; + + +On simpler IR's, without separate channel keys, you need to map UP as KEY_CHANNELUP + +On simpler IR's, without separate channel keys, you need to map DOWN as KEY_CHANNELDOWN + +On simpler IR's, without separate volume keys, you need to map LEFT as KEY_VOLUMEDOWN + +On simpler IR's, without separate volume keys, you need to map RIGHT as KEY_VOLUMEUP + + + +
+ +
\ No newline at end of file diff --git a/v4l2-spec/v4l2.sgml b/v4l2-spec/v4l2.sgml index 62b8538a7..570ac78f6 100644 --- a/v4l2-spec/v4l2.sgml +++ b/v4l2-spec/v4l2.sgml @@ -510,6 +510,10 @@ available here: + &sub-remote_controllers; + + &sub-compat; -- cgit v1.2.3 From 939633eb8afe2f03adab25337d2f57f0b8ed642d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 31 Aug 2009 02:03:28 -0300 Subject: ir-common: fix the lack of ir table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Mauro Carvalho Chehab drivers/media/video/em28xx/em28xx-cards.c:565: error: ‘ir_codes_gadmei_rm008z’ undeclared here (not in a function) Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/include/media/ir-common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/include/media/ir-common.h b/linux/include/media/ir-common.h index 8a607db49..74a7e5573 100644 --- a/linux/include/media/ir-common.h +++ b/linux/include/media/ir-common.h @@ -165,6 +165,7 @@ extern IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_terratec_cinergy_xs[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_gadmei_rm008z[IR_KEYTAB_SIZE]; #endif -- cgit v1.2.3 From 29877b30873e9d0ac1a4756775bcfb1caab42fa1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 31 Aug 2009 22:39:44 -0300 Subject: v4l2-spec: Add an introduction to remote controllers From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l2-spec/remote_controllers.sgml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/v4l2-spec/remote_controllers.sgml b/v4l2-spec/remote_controllers.sgml index 29bdbd54f..f0c215b1c 100644 --- a/v4l2-spec/remote_controllers.sgml +++ b/v4l2-spec/remote_controllers.sgml @@ -2,7 +2,10 @@
Introduction -TODO +Currently, most analog and digital devices have a Infrared input for remote controllers. Each manufacturer has their own type of control. It is not rare that the same manufacturer to ship different types of controls, depending on the device. +Unfortunately, during several years, there weren't any effort to uniform the IR keycodes under different boards. This resulted that the same IR keyname to be mapped completely different on different IR's. Due to that, V4L2 API now specifies a standard for mapping Media keys on IR. +This standard should be used by both V4L/DVB drivers and userspace applications +The modules register the remote as keyboard within the linux input layer. This means that the IR key strokes will look like normal keyboard key strokes (if CONFIG_INPUT_KEYBOARD is enabled). Using the event devices (CONFIG_INPUT_EVDEV) it is possible for applications to access the remote via /dev/input/event devices. IR default keymapping @@ -134,6 +137,8 @@
+It should be noticed that, sometimes, there some fundamental missing keys at some cheaper IR's. Due to that, it is recommended to: + Notes -- cgit v1.2.3 From 466cf445ce93217dac3a66fa3bc9b23b45cacecd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 31 Aug 2009 22:41:03 -0300 Subject: v4l2-spec: Update revision fields From: Mauro Carvalho Chehab Update revision fields to match the Remote Controller chapter. While here, increment spec to version 2.6.32 to match Linux Kernel revision. Signed-off-by: Mauro Carvalho Chehab --- v4l2-spec/compat.sgml | 7 +++++++ v4l2-spec/v4l2.sgml | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/v4l2-spec/compat.sgml b/v4l2-spec/compat.sgml index 3a05a869b..50b784f46 100644 --- a/v4l2-spec/compat.sgml +++ b/v4l2-spec/compat.sgml @@ -2296,6 +2296,10 @@ was renamed to v4l2_chip_ident_old V4L2 in Linux 2.6.32 + + In order to be easier to compare a V4L2 API and a kernel +version, now V4L2 API is numbered using Linux Kernel version numeration. + Finalized the RDS capture API. See for more information. @@ -2315,6 +2319,9 @@ more information. Added FM Modulator (FM TX) Extended Control Class: V4L2_CTRL_CLASS_FM_TX and their Control IDs. + + Added Remote Controller chapter, describing the default Remote Controller mapping for media devices. + diff --git a/v4l2-spec/v4l2.sgml b/v4l2-spec/v4l2.sgml index 570ac78f6..15480451a 100644 --- a/v4l2-spec/v4l2.sgml +++ b/v4l2-spec/v4l2.sgml @@ -26,7 +26,7 @@ Video for Linux Two API Specification - Revision 0.29 + Revision 2.6.32 @@ -91,12 +91,12 @@ MPEG stream embedded, sliced VBI data format in this specification. - Mauro Carvalho Chehab - Documented libv4l, designed and added v4l2grab example + Documented libv4l, designed and added v4l2grab example, +Remote Controller chapter
@@ -104,6 +104,7 @@ MPEG stream embedded, sliced VBI data format in this specification.
+ 1999 @@ -144,6 +145,15 @@ structs, ioctls) must be noted in more detail in the history chapter (compat.sgml), along with the possible impact on existing drivers and applications. --> + + 2.6.32 + 2009-08-31 + mcc + Now, revisions will match the kernel version where +the V4L2 API will be adopted by a driver. Added Remote Controller +chapter. + + 0.29 2009-08-26 -- cgit v1.2.3 From 3f66b071b19c2817be029bcce5add52e3f3a896d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 31 Aug 2009 02:44:26 -0300 Subject: v4l2-spec: Add keytable.c example to remote controller chapter From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l2-spec/Makefile | 8 ++++++++ v4l2-spec/remote_controllers.sgml | 12 +++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/v4l2-spec/Makefile b/v4l2-spec/Makefile index 73d48d00d..f593faccd 100644 --- a/v4l2-spec/Makefile +++ b/v4l2-spec/Makefile @@ -5,6 +5,7 @@ SHELL=/bin/bash SGMLS = \ biblio.sgml \ capture.c.sgml \ + keytable.c.sgml \ v4l2grab.c.sgml \ common.sgml \ compat.sgml \ @@ -359,6 +360,13 @@ v4l2grab.c.sgml: ../v4l2-apps/test/v4l2grab.c Makefile sed 's/i\.e\./&ie;/' >> $@ echo "" >> $@ +keytable.c.sgml: ../v4l2-apps/util/keytable.c Makefile + echo "" > $@ + expand --tabs=8 < $< | \ + sed $(ESCAPE) $(DOCUMENTED) | \ + sed 's/i\.e\./&ie;/' >> $@ + echo "" >> $@ + videodev2.h.sgml: ../linux/include/linux/videodev2.h Makefile echo "" > $@ expand --tabs=8 < $< | \ diff --git a/v4l2-spec/remote_controllers.sgml b/v4l2-spec/remote_controllers.sgml index f0c215b1c..6cbcd5869 100644 --- a/v4l2-spec/remote_controllers.sgml +++ b/v4l2-spec/remote_controllers.sgml @@ -157,4 +157,14 @@
-
\ No newline at end of file + + +
+Changing default Remote Controller mappings +The event interface provides two ioctls to be used against +the /dev/input/event device, to allow changing the default +keymapping. + +This program demonstrates how to replace the keymap tables. +&sub-keytable-c; +
-- cgit v1.2.3 From bdf799729e818a74e56e610e8128071daaddb1ff Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 31 Aug 2009 10:52:12 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index b5a448379..7d3e2f57b 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -88,6 +88,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K70AB ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "K70IO ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "N10J ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* Note no whitespace padding for these 2 models, this is not a typo */ -- cgit v1.2.3 From 2eee59b3a4bdc1e3b1341ea567a653105e9abe6d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 31 Aug 2009 11:15:22 +0200 Subject: gspca - sunplus: Optimize code. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sunplus.c | 372 +++++++++++++----------------- 1 file changed, 165 insertions(+), 207 deletions(-) diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index 33bac051d..94a3f53c6 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -32,22 +32,22 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - unsigned char brightness; - unsigned char contrast; - unsigned char colors; - unsigned char autogain; + u8 brightness; + u8 contrast; + u8 colors; + u8 autogain; u8 quality; #define QUALITY_MIN 70 #define QUALITY_MAX 95 #define QUALITY_DEF 85 - char bridge; + u8 bridge; #define BRIDGE_SPCA504 0 #define BRIDGE_SPCA504B 1 #define BRIDGE_SPCA504C 2 #define BRIDGE_SPCA533 3 #define BRIDGE_SPCA536 4 - char subtype; + u8 subtype; #define AiptekMiniPenCam13 1 #define LogitechClickSmart420 2 #define LogitechClickSmart820 3 @@ -68,7 +68,6 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { -#define SD_BRIGHTNESS 0 { { .id = V4L2_CID_BRIGHTNESS, @@ -77,12 +76,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 0xff, .step = 1, - .default_value = 0, +#define BRIGHTNESS_DEF 0 + .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, .get = sd_getbrightness, }, -#define SD_CONTRAST 1 { { .id = V4L2_CID_CONTRAST, @@ -91,12 +90,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 0xff, .step = 1, - .default_value = 0x20, +#define CONTRAST_DEF 0x20 + .default_value = CONTRAST_DEF, }, .set = sd_setcontrast, .get = sd_getcontrast, }, -#define SD_COLOR 2 { { .id = V4L2_CID_SATURATION, @@ -105,12 +104,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 0xff, .step = 1, - .default_value = 0x1a, +#define COLOR_DEF 0x1a + .default_value = COLOR_DEF, }, .set = sd_setcolors, .get = sd_getcolors, }, -#define SD_AUTOGAIN 3 { { .id = V4L2_CID_AUTOGAIN, @@ -119,7 +118,8 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 1, +#define AUTOGAIN_DEF 1 + .default_value = AUTOGAIN_DEF, }, .set = sd_setautogain, .get = sd_getautogain, @@ -181,14 +181,20 @@ static const struct v4l2_pix_format vga_mode2[] = { #define SPCA504_PCCAM600_OFFSET_MODE 5 #define SPCA504_PCCAM600_OFFSET_DATA 14 /* Frame packet header offsets for the spca533 */ -#define SPCA533_OFFSET_DATA 16 +#define SPCA533_OFFSET_DATA 16 #define SPCA533_OFFSET_FRAMSEQ 15 /* Frame packet header offsets for the spca536 */ -#define SPCA536_OFFSET_DATA 4 -#define SPCA536_OFFSET_FRAMSEQ 1 +#define SPCA536_OFFSET_DATA 4 +#define SPCA536_OFFSET_FRAMSEQ 1 + +struct cmd { + u8 req; + u16 val; + u16 idx; +}; /* Initialisation data for the Creative PC-CAM 600 */ -static const __u16 spca504_pccam600_init_data[][3] = { +static const struct cmd spca504_pccam600_init_data[] = { /* {0xa0, 0x0000, 0x0503}, * capture mode */ {0x00, 0x0000, 0x2000}, {0x00, 0x0013, 0x2301}, @@ -219,22 +225,20 @@ static const __u16 spca504_pccam600_init_data[][3] = { {0x00, 0x0003, 0x2000}, {0x00, 0x0013, 0x2301}, {0x00, 0x0003, 0x2000}, - {} }; /* Creative PC-CAM 600 specific open data, sent before using the * generic initialisation data from spca504_open_data. */ -static const __u16 spca504_pccam600_open_data[][3] = { +static const struct cmd spca504_pccam600_open_data[] = { {0x00, 0x0001, 0x2501}, {0x20, 0x0500, 0x0001}, /* snapshot mode */ {0x00, 0x0003, 0x2880}, {0x00, 0x0001, 0x2881}, - {} }; /* Initialisation data for the logitech clicksmart 420 */ -static const __u16 spca504A_clicksmart420_init_data[][3] = { +static const struct cmd spca504A_clicksmart420_init_data[] = { /* {0xa0, 0x0000, 0x0503}, * capture mode */ {0x00, 0x0000, 0x2000}, {0x00, 0x0013, 0x2301}, @@ -261,7 +265,7 @@ static const __u16 spca504A_clicksmart420_init_data[][3] = { #endif #if 1 - {0x0a1, 0x0080, 0x0001}, + {0xa1, 0x0080, 0x0001}, {0x30, 0x0049, 0x0000}, {0x30, 0x0060, 0x0005}, {0x0c, 0x0004, 0x0000}, @@ -285,11 +289,10 @@ static const __u16 spca504A_clicksmart420_init_data[][3] = { {0x00, 0x0013, 0x2301}, {0x00, 0x0003, 0x2000}, #endif - {} }; /* clicksmart 420 open data ? */ -static const __u16 spca504A_clicksmart420_open_data[][3] = { +static const struct cmd spca504A_clicksmart420_open_data[] = { {0x00, 0x0001, 0x2501}, {0x20, 0x0502, 0x0000}, {0x06, 0x0000, 0x0000}, @@ -433,10 +436,9 @@ static const __u16 spca504A_clicksmart420_open_data[][3] = { {0x00, 0x0028, 0x287f}, {0xa0, 0x0000, 0x0503}, - {} }; -static const __u8 qtable_creative_pccam[2][64] = { +static const u8 qtable_creative_pccam[2][64] = { { /* Q-table Y-components */ 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, @@ -461,7 +463,7 @@ static const __u8 qtable_creative_pccam[2][64] = { * except for one byte. Possibly a typo? * NWG: 18/05/2003. */ -static const __u8 qtable_spca504_default[2][64] = { +static const u8 qtable_spca504_default[2][64] = { { /* Q-table Y-components */ 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12, 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11, @@ -485,9 +487,9 @@ static const __u8 qtable_spca504_default[2][64] = { /* read bytes to gspca_dev->usb_buf */ static void reg_r(struct gspca_dev *gspca_dev, - __u16 req, - __u16 index, - __u16 len) + u8 req, + u16 index, + u16 len) { #ifdef GSPCA_DEBUG if (len > USB_BUF_SZ) { @@ -505,31 +507,26 @@ static void reg_r(struct gspca_dev *gspca_dev, 500); } -/* write bytes from gspca_dev->usb_buf */ -static void reg_w(struct gspca_dev *gspca_dev, - __u16 req, - __u16 value, - __u16 index, - __u16 len) +/* write one byte */ +static void reg_w_1(struct gspca_dev *gspca_dev, + u8 req, + u16 value, + u16 index, + u16 byte) { -#ifdef GSPCA_DEBUG - if (len > USB_BUF_SZ) { - err("reg_w: buffer overflow"); - return; - } -#endif + gspca_dev->usb_buf[0] = byte; usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, - len ? gspca_dev->usb_buf : NULL, len, + gspca_dev->usb_buf, 1, 500); } /* write req / index / value */ static int reg_w_riv(struct usb_device *dev, - __u16 req, __u16 index, __u16 value) + u8 req, u16 index, u16 value) { int ret; @@ -547,7 +544,7 @@ static int reg_w_riv(struct usb_device *dev, /* read 1 byte */ static int reg_r_1(struct gspca_dev *gspca_dev, - __u16 value) /* wValue */ + u16 value) /* wValue */ { int ret; @@ -568,9 +565,9 @@ static int reg_r_1(struct gspca_dev *gspca_dev, /* read 1 or 2 bytes - returns < 0 if error */ static int reg_r_12(struct gspca_dev *gspca_dev, - __u16 req, /* bRequest */ - __u16 index, /* wIndex */ - __u16 length) /* wLength (1 or 2 only) */ + u8 req, /* bRequest */ + u16 index, /* wIndex */ + u16 length) /* wLength (1 or 2 only) */ { int ret; @@ -591,43 +588,40 @@ static int reg_r_12(struct gspca_dev *gspca_dev, } static int write_vector(struct gspca_dev *gspca_dev, - const __u16 data[][3]) + const struct cmd *data, int ncmds) { struct usb_device *dev = gspca_dev->dev; - int ret, i = 0; + int ret; - while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) { - ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]); + while (--ncmds >= 0) { + ret = reg_w_riv(dev, data->req, data->idx, data->val); if (ret < 0) { PDEBUG(D_ERR, - "Register write failed for 0x%x,0x%x,0x%x", - data[i][0], data[i][1], data[i][2]); + "Register write failed for 0x%02x, 0x%04x, 0x%04x", + data->req, data->val, data->idx); return ret; } - i++; + data++; } return 0; } static int spca50x_setup_qtable(struct gspca_dev *gspca_dev, - unsigned int request, - unsigned int ybase, - unsigned int cbase, - const __u8 qtable[2][64]) + const u8 qtable[2][64]) { struct usb_device *dev = gspca_dev->dev; int i, err; /* loop over y components */ for (i = 0; i < 64; i++) { - err = reg_w_riv(dev, request, ybase + i, qtable[0][i]); + err = reg_w_riv(dev, 0x00, 0x2800 + i, qtable[0][i]); if (err < 0) return err; } /* loop over c components */ for (i = 0; i < 64; i++) { - err = reg_w_riv(dev, request, cbase + i, qtable[1][i]); + err = reg_w_riv(dev, 0x00, 0x2840 + i, qtable[1][i]); if (err < 0) return err; } @@ -635,34 +629,34 @@ static int spca50x_setup_qtable(struct gspca_dev *gspca_dev, } static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, - __u16 req, __u16 idx, __u16 val) + u8 req, u16 idx, u16 val) { struct usb_device *dev = gspca_dev->dev; - __u8 notdone; + int notdone; reg_w_riv(dev, req, idx, val); notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1); reg_w_riv(dev, req, idx, val); - PDEBUG(D_FRAM, "before wait 0x%x", notdone); + PDEBUG(D_FRAM, "before wait 0x%04x", notdone); msleep(200); notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1); - PDEBUG(D_FRAM, "after wait 0x%x", notdone); + PDEBUG(D_FRAM, "after wait 0x%04x", notdone); } static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, - __u16 req, - __u16 idx, __u16 val, __u8 stat, __u8 count) + u8 req, + u16 idx, u16 val, u8 stat, u8 count) { struct usb_device *dev = gspca_dev->dev; - __u8 status; - __u8 endcode; + int status; + u8 endcode; reg_w_riv(dev, req, idx, val); status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); endcode = stat; - PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat); + PDEBUG(D_FRAM, "Status 0x%x Need 0x%04x", status, stat); if (!count) return; count = 200; @@ -672,7 +666,7 @@ static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, /* reg_w_riv(dev, req, idx, val); */ status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); if (status == endcode) { - PDEBUG(D_FRAM, "status 0x%x after wait 0x%x", + PDEBUG(D_FRAM, "status 0x%04x after wait %d", status, 200 - count); break; } @@ -699,8 +693,7 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) while (--count > 0) { reg_r(gspca_dev, 0x21, 1, 1); if (gspca_dev->usb_buf[0] != 0) { - gspca_dev->usb_buf[0] = 0; - reg_w(gspca_dev, 0x21, 0, 1, 1); + reg_w_1(gspca_dev, 0x21, 0, 1, 0); reg_r(gspca_dev, 0x21, 1, 1); spca504B_PollingDataReady(gspca_dev); break; @@ -711,7 +704,7 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) static void spca50x_GetFirmware(struct gspca_dev *gspca_dev) { - __u8 *data; + u8 *data; data = gspca_dev->usb_buf; reg_r(gspca_dev, 0x20, 0, 5); @@ -725,41 +718,34 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; - __u8 Size; - __u8 Type; + u8 Size; int rc; - Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; - Type = 0; + Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; switch (sd->bridge) { case BRIDGE_SPCA533: - reg_w(gspca_dev, 0x31, 0, 0, 0); + reg_w_riv(dev, 0x31, 0, 0); spca504B_WaitCmdStatus(gspca_dev); rc = spca504B_PollingDataReady(gspca_dev); spca50x_GetFirmware(gspca_dev); - gspca_dev->usb_buf[0] = 2; /* type */ - reg_w(gspca_dev, 0x24, 0, 8, 1); + reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */ reg_r(gspca_dev, 0x24, 8, 1); - gspca_dev->usb_buf[0] = Size; - reg_w(gspca_dev, 0x25, 0, 4, 1); + reg_w_1(gspca_dev, 0x25, 0, 4, Size); reg_r(gspca_dev, 0x25, 4, 1); /* size */ rc = spca504B_PollingDataReady(gspca_dev); /* Init the cam width height with some values get on init ? */ - reg_w(gspca_dev, 0x31, 0, 4, 0); + reg_w_riv(dev, 0x31, 0, 0x04); spca504B_WaitCmdStatus(gspca_dev); rc = spca504B_PollingDataReady(gspca_dev); break; default: /* case BRIDGE_SPCA504B: */ /* case BRIDGE_SPCA536: */ - gspca_dev->usb_buf[0] = Size; - reg_w(gspca_dev, 0x25, 0, 4, 1); + reg_w_1(gspca_dev, 0x25, 0, 4, Size); reg_r(gspca_dev, 0x25, 4, 1); /* size */ - Type = 6; - gspca_dev->usb_buf[0] = Type; - reg_w(gspca_dev, 0x27, 0, 0, 1); + reg_w_1(gspca_dev, 0x27, 0, 0, 6); reg_r(gspca_dev, 0x27, 0, 1); /* type */ rc = spca504B_PollingDataReady(gspca_dev); break; @@ -799,17 +785,51 @@ static void spca504_wait_status(struct gspca_dev *gspca_dev) static void spca504B_setQtable(struct gspca_dev *gspca_dev) { - gspca_dev->usb_buf[0] = 3; - reg_w(gspca_dev, 0x26, 0, 0, 1); + reg_w_1(gspca_dev, 0x26, 0, 0, 3); reg_r(gspca_dev, 0x26, 0, 1); spca504B_PollingDataReady(gspca_dev); } -static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev) +static void setbrightness(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct usb_device *dev = gspca_dev->dev; + u16 reg; + + reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7; + reg_w_riv(dev, 0x00, reg, sd->brightness); +} + +static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + struct usb_device *dev = gspca_dev->dev; + u16 reg; + + reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8; + reg_w_riv(dev, 0x00, reg, sd->contrast); +} + +static void setcolors(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct usb_device *dev = gspca_dev->dev; + u16 reg; + + reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae; + reg_w_riv(dev, 0x00, reg, sd->colors); +} + +static void init_ctl_reg(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct usb_device *dev = gspca_dev->dev; int pollreg = 1; + setbrightness(gspca_dev); + setcontrast(gspca_dev); + setcolors(gspca_dev); + switch (sd->bridge) { case BRIDGE_SPCA504: case BRIDGE_SPCA504C: @@ -818,20 +838,14 @@ static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev) default: /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA504B: */ - reg_w(gspca_dev, 0, 0, 0x21a7, 0); /* brightness */ - reg_w(gspca_dev, 0, 0x20, 0x21a8, 0); /* contrast */ - reg_w(gspca_dev, 0, 0, 0x21ad, 0); /* hue */ - reg_w(gspca_dev, 0, 1, 0x21ac, 0); /* sat/hue */ - reg_w(gspca_dev, 0, 0x20, 0x21ae, 0); /* saturation */ - reg_w(gspca_dev, 0, 0, 0x21a3, 0); /* gamma */ + reg_w_riv(dev, 0, 0x00, 0x21ad); /* hue */ + reg_w_riv(dev, 0, 0x01, 0x21ac); /* sat/hue */ + reg_w_riv(dev, 0, 0x00, 0x21a3); /* gamma */ break; case BRIDGE_SPCA536: - reg_w(gspca_dev, 0, 0, 0x20f0, 0); - reg_w(gspca_dev, 0, 0x21, 0x20f1, 0); - reg_w(gspca_dev, 0, 0x40, 0x20f5, 0); - reg_w(gspca_dev, 0, 1, 0x20f4, 0); - reg_w(gspca_dev, 0, 0x40, 0x20f6, 0); - reg_w(gspca_dev, 0, 0, 0x2089, 0); + reg_w_riv(dev, 0, 0x40, 0x20f5); + reg_w_riv(dev, 0, 0x01, 0x20f4); + reg_w_riv(dev, 0, 0x00, 0x2089); break; } if (pollreg) @@ -886,9 +900,10 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = ARRAY_SIZE(vga_mode2); break; } - sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; - sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; - sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value; + sd->brightness = BRIGHTNESS_DEF; + sd->contrast = CONTRAST_DEF; + sd->colors = COLOR_DEF; + sd->autogain = AUTOGAIN_DEF; sd->quality = QUALITY_DEF; return 0; } @@ -898,32 +913,29 @@ static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; - int rc; - __u8 i; - __u8 info[6]; - int err_code; + int i, err_code; + u8 info[6]; switch (sd->bridge) { case BRIDGE_SPCA504B: - reg_w(gspca_dev, 0x1d, 0, 0, 0); - reg_w(gspca_dev, 0, 1, 0x2306, 0); - reg_w(gspca_dev, 0, 0, 0x0d04, 0); - reg_w(gspca_dev, 0, 0, 0x2000, 0); - reg_w(gspca_dev, 0, 0x13, 0x2301, 0); - reg_w(gspca_dev, 0, 0, 0x2306, 0); + reg_w_riv(dev, 0x1d, 0x00, 0); + reg_w_riv(dev, 0, 0x01, 0x2306); + reg_w_riv(dev, 0, 0x00, 0x0d04); + reg_w_riv(dev, 0, 0x00, 0x2000); + reg_w_riv(dev, 0, 0x13, 0x2301); + reg_w_riv(dev, 0, 0x00, 0x2306); /* fall thru */ case BRIDGE_SPCA533: - rc = spca504B_PollingDataReady(gspca_dev); + spca504B_PollingDataReady(gspca_dev); spca50x_GetFirmware(gspca_dev); break; case BRIDGE_SPCA536: spca50x_GetFirmware(gspca_dev); reg_r(gspca_dev, 0x00, 0x5002, 1); - gspca_dev->usb_buf[0] = 0; - reg_w(gspca_dev, 0x24, 0, 0, 1); + reg_w_1(gspca_dev, 0x24, 0, 0, 0); reg_r(gspca_dev, 0x24, 0, 1); - rc = spca504B_PollingDataReady(gspca_dev); - reg_w(gspca_dev, 0x34, 0, 0, 0); + spca504B_PollingDataReady(gspca_dev); + reg_w_riv(dev, 0x34, 0, 0); spca504B_WaitCmdStatus(gspca_dev); break; case BRIDGE_SPCA504C: /* pccam600 */ @@ -933,12 +945,13 @@ static int sd_init(struct gspca_dev *gspca_dev) spca504_wait_status(gspca_dev); if (sd->subtype == LogitechClickSmart420) write_vector(gspca_dev, - spca504A_clicksmart420_open_data); + spca504A_clicksmart420_open_data, + ARRAY_SIZE(spca504A_clicksmart420_open_data)); else - write_vector(gspca_dev, spca504_pccam600_open_data); + write_vector(gspca_dev, spca504_pccam600_open_data, + ARRAY_SIZE(spca504_pccam600_open_data)); err_code = spca50x_setup_qtable(gspca_dev, - 0x00, 0x2800, - 0x2840, qtable_creative_pccam); + qtable_creative_pccam); if (err_code < 0) { PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed"); return err_code; @@ -976,8 +989,8 @@ static int sd_init(struct gspca_dev *gspca_dev) 6, 0, 0x86, 1); */ /* spca504A_acknowledged_command (gspca_dev, 0x24, 0, 0, 0x9D, 1); */ - reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */ - reg_w_riv(dev, 0x0, 0x2310, 0x05); + reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */ + reg_w_riv(dev, 0x00, 0x2310, 0x05); spca504A_acknowledged_command(gspca_dev, 0x01, 0x0f, 0, 0xff, 0); } @@ -985,8 +998,6 @@ static int sd_init(struct gspca_dev *gspca_dev) reg_w_riv(dev, 0, 0x2000, 0); reg_w_riv(dev, 0, 0x2883, 1); err_code = spca50x_setup_qtable(gspca_dev, - 0x00, 0x2800, - 0x2840, qtable_spca504_default); if (err_code < 0) { PDEBUG(D_ERR, "spca50x_setup_qtable failed"); @@ -1001,10 +1012,9 @@ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; - int rc; int enable; - __u8 i; - __u8 info[6]; + int i; + u8 info[6]; /* create the JPEG header */ sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); @@ -1022,17 +1032,20 @@ static int sd_start(struct gspca_dev *gspca_dev) /* case BRIDGE_SPCA504B: */ /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA536: */ - if (sd->subtype == MegapixV4 || - sd->subtype == LogitechClickSmart820 || - sd->subtype == MegaImageVI) { - reg_w(gspca_dev, 0xf0, 0, 0, 0); + switch (sd->subtype) { + case MegapixV4: + case LogitechClickSmart820: + case MegaImageVI: + reg_w_riv(dev, 0xf0, 0, 0); spca504B_WaitCmdStatus(gspca_dev); reg_r(gspca_dev, 0xf0, 4, 0); spca504B_WaitCmdStatus(gspca_dev); - } else { - reg_w(gspca_dev, 0x31, 0, 4, 0); + break; + default: + reg_w_riv(dev, 0x31, 0, 0x04); spca504B_WaitCmdStatus(gspca_dev); - rc = spca504B_PollingDataReady(gspca_dev); + spca504B_PollingDataReady(gspca_dev); + break; } break; case BRIDGE_SPCA504: @@ -1066,15 +1079,17 @@ static int sd_start(struct gspca_dev *gspca_dev) spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); } spca504B_SetSizeType(gspca_dev); - reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */ - reg_w_riv(dev, 0x0, 0x2310, 0x05); + reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */ + reg_w_riv(dev, 0x00, 0x2310, 0x05); break; case BRIDGE_SPCA504C: if (sd->subtype == LogitechClickSmart420) { write_vector(gspca_dev, - spca504A_clicksmart420_init_data); + spca504A_clicksmart420_init_data, + ARRAY_SIZE(spca504A_clicksmart420_init_data)); } else { - write_vector(gspca_dev, spca504_pccam600_init_data); + write_vector(gspca_dev, spca504_pccam600_init_data, + ARRAY_SIZE(spca504_pccam600_init_data)); } enable = (sd->autogain ? 0x04 : 0x01); reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */ @@ -1086,7 +1101,7 @@ static int sd_start(struct gspca_dev *gspca_dev) spca504B_SetSizeType(gspca_dev); break; } - sp5xx_initContBrigHueRegisters(gspca_dev); + init_ctl_reg(gspca_dev); return 0; } @@ -1100,7 +1115,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA536: */ /* case BRIDGE_SPCA504B: */ - reg_w(gspca_dev, 0x31, 0, 0, 0); + reg_w_riv(dev, 0x31, 0, 0); spca504B_WaitCmdStatus(gspca_dev); spca504B_PollingDataReady(gspca_dev); break; @@ -1118,7 +1133,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) 0x0f, 0x00, 0xff, 1); } else { spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); - reg_w_riv(dev, 0x01, 0x000f, 0x00); + reg_w_riv(dev, 0x01, 0x000f, 0x0000); } break; } @@ -1133,12 +1148,12 @@ static void sd_stop0(struct gspca_dev *gspca_dev) static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ - __u8 *data, /* isoc packet */ + u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; int i, sof = 0; - static unsigned char ffd9[] = {0xff, 0xd9}; + static u8 ffd9[] = {0xff, 0xd9}; /* frames are jpeg 4.1.1 without 0xff escape */ switch (sd->bridge) { @@ -1226,63 +1241,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -static void setbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA504: */ -/* case BRIDGE_SPCA504C: */ - reg_w_riv(dev, 0x0, 0x21a7, sd->brightness); - break; - case BRIDGE_SPCA536: - reg_w_riv(dev, 0x0, 0x20f0, sd->brightness); - break; - } -} - -static void setcontrast(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA504: */ -/* case BRIDGE_SPCA504C: */ - reg_w_riv(dev, 0x0, 0x21a8, sd->contrast); - break; - case BRIDGE_SPCA536: - reg_w_riv(dev, 0x0, 0x20f1, sd->contrast); - break; - } -} - -static void setcolors(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; - - switch (sd->bridge) { - default: -/* case BRIDGE_SPCA533: */ -/* case BRIDGE_SPCA504B: */ -/* case BRIDGE_SPCA504: */ -/* case BRIDGE_SPCA504C: */ - reg_w_riv(dev, 0x0, 0x21ae, sd->colors); - break; - case BRIDGE_SPCA536: - reg_w_riv(dev, 0x0, 0x20f6, sd->colors); - break; - } -} - static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; -- cgit v1.2.3 From dd785cd4485fcc9e17fbedcac055554c5176d4c6 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 31 Aug 2009 16:15:48 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 7d3e2f57b..ef3668c6c 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -101,6 +101,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N50Vn ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N51Vf ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N51Vg ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb106, 0, "ASUSTeK Computer Inc. ", "N51Vn ", -- cgit v1.2.3 From 36dfe1e93c14212a6fd2939344018445f132789e Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 31 Aug 2009 16:32:46 +0200 Subject: Add new V4L2_FMT_FLAG_EMULATED flag to videodev2.h From: Hans de Goede V4L2_FMT_FLAG_EMULATED 0x0002 This format is not native to the device but emulated through software (usually libv4l2), where possible try to use a native format instead for better performance. Priority: normal Signed-off-by: Hans de Goede --- linux/include/linux/videodev2.h | 1 + v4l2-spec/vidioc-enum-fmt.sgml | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h index b61c3b61c..d6f8edb3d 100644 --- a/linux/include/linux/videodev2.h +++ b/linux/include/linux/videodev2.h @@ -374,6 +374,7 @@ struct v4l2_fmtdesc { }; #define V4L2_FMT_FLAG_COMPRESSED 0x0001 +#define V4L2_FMT_FLAG_EMULATED 0x0002 #if 1 /*KEEP*/ /* Experimental Frame Size and frame rate enumeration */ diff --git a/v4l2-spec/vidioc-enum-fmt.sgml b/v4l2-spec/vidioc-enum-fmt.sgml index 5e0c7c770..73af15640 100644 --- a/v4l2-spec/vidioc-enum-fmt.sgml +++ b/v4l2-spec/vidioc-enum-fmt.sgml @@ -127,6 +127,13 @@ the array to zero. 0x0001 This is a compressed format. + + V4L2_FMT_FLAG_EMULATED + 0x0002 + This format is not native to the device but emulated +through software (usually libv4l2), where possible try to use a native format +instead for better performance. + -- cgit v1.2.3 From c0cfb90f8b7c4b713c734cb7b19b3bc834f516c3 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Mon, 31 Aug 2009 16:40:33 +0200 Subject: libv4l: Report V4L2_FMT_FLAG_EMULATED in v4l2_fmtdesc flags for emulated formats From: Hans de Goede libv4l: Report V4L2_FMT_FLAG_EMULATED in v4l2_fmtdesc flags for emulated formats Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 1 + v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h | 4 ++++ v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index 1cdbedb9e..e5c421532 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -10,6 +10,7 @@ libv4l-0.6.1 * Change controls shm segment name to include the username, as it is only writable by the user (this means libv4l controls are per user) (Gregor Jasny) * Add support for decompressing sn9c2028 compressed bayer (Theodore Kilgore) +* Report V4L2_FMT_FLAG_EMULATED in v4l2_fmtdesc flags for emulated formats libv4l-0.6.0 ------------ diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h index 05549e6b5..f16d05d02 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h @@ -96,6 +96,10 @@ #define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */ #endif +#ifndef V4L2_FMT_FLAG_EMULATED +#define V4L2_FMT_FLAG_EMULATED 0x0002 +#endif + #define ARRAY_SIZE(x) ((int)sizeof(x)/(int)sizeof((x)[0])) #define V4LCONVERT_ERROR_MSG_SIZE 256 diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c index b35254e4b..32b9a51bb 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -219,7 +219,7 @@ int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt) return -1; } - fmt->flags = 0; + fmt->flags = V4L2_FMT_FLAG_EMULATED; fmt->pixelformat = faked_fmts[i]; fmt->description[0] = faked_fmts[i] & 0xff; fmt->description[1] = (faked_fmts[i] >> 8) & 0xff; -- cgit v1.2.3 From ccb148c4d7d22792a1a65d80c85f1800f2227cfa Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 31 Aug 2009 21:53:05 +0200 Subject: compat: don't build si4713 for kernels < 2.6.26 From: Hans Verkuil si4713 requires the new i2c API, so no point trying to build it on those old kernels. Priority: normal Signed-off-by: Hans Verkuil --- v4l/versions.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l/versions.txt b/v4l/versions.txt index d4c7bd380..b2c5bd8fe 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -19,6 +19,8 @@ VIDEO_TVP514X RADIO_TEA5764 VIDEO_THS7303 VIDEO_ADV7343 +RADIO_SI4713 +I2C_SI4713 [2.6.25] # Requires gpiolib -- cgit v1.2.3 From 16f4313d433426d6be10c2cb34a73cc472dc025a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 31 Aug 2009 22:08:34 +0200 Subject: compat: don't build soc-camera modules for kernels < 2.6.28. From: Hans Verkuil Compiling this for pre-2.6.28 kernels will generate a lot of warnings due to a prototype change in dev_get_drvdata. Priority: normal Signed-off-by: Hans Verkuil CC: Guennadi Liakhovetski --- v4l/versions.txt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/v4l/versions.txt b/v4l/versions.txt index b2c5bd8fe..1995c9006 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -12,6 +12,17 @@ VIDEO_DM355_CCDC # Needs defines that are only available from 2.6.29 VIDEO_PXA27x +[2.6.28] +# dev_get_drvdata switched to const struct device * +SOC_CAMERA +SOC_CAMERA_MT9V022 +SOC_CAMERA_MT9M001 +SOC_CAMERA_MT9M111 +SOC_CAMERA_MT9T031 +SOC_CAMERA_OV772X +SOC_CAMERA_TW9910 +SOC_CAMERA_PLATFORM + [2.6.26] # Requires struct i2c_device_id VIDEO_TVP514X @@ -22,12 +33,6 @@ VIDEO_ADV7343 RADIO_SI4713 I2C_SI4713 -[2.6.25] -# Requires gpiolib -SOC_CAMERA -SOC_CAMERA_MT9V022 -SOC_CAMERA_MT9M001 - [2.6.24] # Some freezer routines USB_GSPCA_SN9C20X_EVDEV -- cgit v1.2.3 From 0d61095304d57762b4452311a5efa6b93ac9f62f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 31 Aug 2009 22:21:04 +0200 Subject: si4713: simplify the code to remove a compiler warning. From: Hans Verkuil The compiler warned about an uninitialized stereo variable. By simplifying the code it 1) improved readability and 2) fixed the compiler warning. Priority: normal Signed-off-by: Hans Verkuil CC: Eduardo Valentin --- linux/drivers/media/radio/si4713-i2c.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/linux/drivers/media/radio/si4713-i2c.c b/linux/drivers/media/radio/si4713-i2c.c index 8cbbe48b0..6a0028eb4 100644 --- a/linux/drivers/media/radio/si4713-i2c.c +++ b/linux/drivers/media/radio/si4713-i2c.c @@ -1841,15 +1841,11 @@ static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) u16 stereo, rds; u32 p; - if (!sdev) { - rval = -ENODEV; - goto exit; - } + if (!sdev) + return -ENODEV; - if (vm->index > 0) { - rval = -EINVAL; - goto exit; - } + if (vm->index > 0) + return -EINVAL; /* Set audio mode: mono or stereo */ if (vm->txsubchans & V4L2_TUNER_SUB_STEREO) @@ -1857,9 +1853,7 @@ static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) else if (vm->txsubchans & V4L2_TUNER_SUB_MONO) stereo = 0; else - rval = -EINVAL; - if (rval < 0) - goto exit; + return -EINVAL; rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS); @@ -1885,7 +1879,6 @@ static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) unlock: mutex_unlock(&sdev->mutex); -exit: return rval; } -- cgit v1.2.3 From 158fd570dbf7a826c6578d5b5a9036dc58059371 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 31 Aug 2009 22:57:52 +0200 Subject: cx25840: fix determining the firmware name From: Hans Verkuil Depending on the model there are three different firmwares to choose from. Unfortunately if a cx23885 is loaded first, then the global firmware name is overwritten with that firmware and if ivtv is loaded next, then it tries to load the wrong firmware. In addition, the original approach would also overwrite any firmware that the user specified explicitly. Priority: normal Signed-off-by: Hans Verkuil CC: Jarod Wilson --- .../drivers/media/video/cx25840/cx25840-firmware.c | 35 ++++++++++++++-------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/linux/drivers/media/video/cx25840/cx25840-firmware.c b/linux/drivers/media/video/cx25840/cx25840-firmware.c index bdc630f0f..a19ab8644 100644 --- a/linux/drivers/media/video/cx25840/cx25840-firmware.c +++ b/linux/drivers/media/video/cx25840/cx25840-firmware.c @@ -24,10 +24,6 @@ #include "cx25840-core.h" -#define FWFILE "v4l-cx25840.fw" -#define FWFILE_CX23885 "v4l-cx23885-avcore-01.fw" -#define FWFILE_CX231XX "v4l-cx231xx-avcore-01.fw" - /* * Mike Isely - The FWSEND parameter controls the * size of the firmware chunks sent down the I2C bus to the chip. @@ -41,11 +37,11 @@ #define FWDEV(x) &((x)->dev) -static char *firmware = FWFILE; +static char *firmware = ""; module_param(firmware, charp, 0444); -MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]"); +MODULE_PARM_DESC(firmware, "Firmware image to load"); static void start_fw_load(struct i2c_client *client) { @@ -66,6 +62,19 @@ static void end_fw_load(struct i2c_client *client) cx25840_write(client, 0x803, 0x03); } +static const char *get_fw_name(struct i2c_client *client) +{ + struct cx25840_state *state = to_state(i2c_get_clientdata(client)); + + if (firmware[0]) + return firmware; + if (state->is_cx23885) + return "v4l-cx23885-avcore-01.fw"; + if (state->is_cx231xx) + return "v4l-cx231xx-avcore-01.fw"; + return "v4l-cx25840.fw"; +} + static int check_fw_load(struct i2c_client *client, int size) { /* DL_ADDR_HB DL_ADDR_LB */ @@ -73,11 +82,13 @@ static int check_fw_load(struct i2c_client *client, int size) s |= cx25840_read(client, 0x800); if (size != s) { - v4l_err(client, "firmware %s load failed\n", firmware); + v4l_err(client, "firmware %s load failed\n", + get_fw_name(client)); return -EINVAL; } - v4l_info(client, "loaded %s firmware (%d bytes)\n", firmware, size); + v4l_info(client, "loaded %s firmware (%d bytes)\n", + get_fw_name(client), size); return 0; } @@ -97,26 +108,24 @@ int cx25840_loadfw(struct i2c_client *client) const struct firmware *fw = NULL; u8 buffer[FWSEND]; const u8 *ptr; + const char *fwname = get_fw_name(client); int size, retval; int MAX_BUF_SIZE = FWSEND; u32 gpio_oe = 0, gpio_da = 0; if (state->is_cx23885) { - firmware = FWFILE_CX23885; /* Preserve the GPIO OE and output bits */ gpio_oe = cx25840_read(client, 0x160); gpio_da = cx25840_read(client, 0x164); } - else if (state->is_cx231xx) - firmware = FWFILE_CX231XX; if ((state->is_cx231xx) && MAX_BUF_SIZE > 16) { v4l_err(client, " Firmware download size changed to 16 bytes max length\n"); MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */ } - if (request_firmware(&fw, firmware, FWDEV(client)) != 0) { - v4l_err(client, "unable to open firmware %s\n", firmware); + if (request_firmware(&fw, fwname, FWDEV(client)) != 0) { + v4l_err(client, "unable to open firmware %s\n", fwname); return -EINVAL; } -- cgit v1.2.3 From b13aae56fe48c89e3b1dbefaf165cbab0102216b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 31 Aug 2009 21:28:58 -0300 Subject: v4l2-spec: convert it to use DocBook XML 4.1.2 From: Mauro Carvalho Chehab DocBook XML 4.1.2 is the docbook dialect spoken at Linux kernel. By using it, we can now consider adding V4L2 API docs at the kernel tree. As a bonus, added support for xmlto, with seems to be better supported nowadays. Another additional bounus is that two new Makefile targets were added: make man - Create V4L2 API man pages make man_install - Install V4L2 API man pages By allowing the addition of V4L2 manpages, it is now easier for developer to quickly check about a V4L2 API or libv4l2 call syntax and expected return values. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- .hgignore | 1 + v4l/Makefile | 6 ++ v4l2-spec/Makefile | 48 +++++++-- v4l2-spec/common.sgml | 42 ++++---- v4l2-spec/compat.sgml | 142 +++++++++++++------------- v4l2-spec/controls.sgml | 62 ++++++------ v4l2-spec/custom.xsl | 29 ++++++ v4l2-spec/dev-capture.sgml | 6 +- v4l2-spec/dev-osd.sgml | 6 +- v4l2-spec/dev-output.sgml | 6 +- v4l2-spec/dev-overlay.sgml | 6 +- v4l2-spec/dev-radio.sgml | 4 +- v4l2-spec/dev-raw-vbi.sgml | 28 +++--- v4l2-spec/dev-rds.sgml | 20 ++-- v4l2-spec/dev-sliced-vbi.sgml | 48 ++++----- v4l2-spec/dev-teletext.sgml | 2 +- v4l2-spec/fdl-appendix.sgml | 4 +- v4l2-spec/func-ioctl.sgml | 4 +- v4l2-spec/func-read.sgml | 2 +- v4l2-spec/io.sgml | 48 ++++----- v4l2-spec/libv4l.sgml | 13 ++- v4l2-spec/pixfmt-grey.sgml | 2 +- v4l2-spec/pixfmt-nv12.sgml | 2 +- v4l2-spec/pixfmt-nv16.sgml | 2 +- v4l2-spec/pixfmt-packed-rgb.sgml | 160 +++++++++++++++--------------- v4l2-spec/pixfmt-packed-yuv.sgml | 78 +++++++-------- v4l2-spec/pixfmt-sbggr16.sgml | 2 +- v4l2-spec/pixfmt-sbggr8.sgml | 2 +- v4l2-spec/pixfmt-sgbrg8.sgml | 2 +- v4l2-spec/pixfmt-sgrbg8.sgml | 2 +- v4l2-spec/pixfmt-uyvy.sgml | 2 +- v4l2-spec/pixfmt-vyuy.sgml | 2 +- v4l2-spec/pixfmt-y16.sgml | 2 +- v4l2-spec/pixfmt-y41p.sgml | 2 +- v4l2-spec/pixfmt-yuv410.sgml | 2 +- v4l2-spec/pixfmt-yuv411p.sgml | 2 +- v4l2-spec/pixfmt-yuv420.sgml | 2 +- v4l2-spec/pixfmt-yuv422p.sgml | 2 +- v4l2-spec/pixfmt-yuyv.sgml | 2 +- v4l2-spec/pixfmt-yvyu.sgml | 2 +- v4l2-spec/pixfmt.sgml | 96 +++++++++--------- v4l2-spec/v4l2.sgml | 13 +-- v4l2-spec/vidioc-cropcap.sgml | 2 +- v4l2-spec/vidioc-dbg-g-chip-ident.sgml | 6 +- v4l2-spec/vidioc-dbg-g-register.sgml | 10 +- v4l2-spec/vidioc-encoder-cmd.sgml | 4 +- v4l2-spec/vidioc-enum-fmt.sgml | 4 +- v4l2-spec/vidioc-enum-frameintervals.sgml | 16 +-- v4l2-spec/vidioc-enum-framesizes.sgml | 14 +-- v4l2-spec/vidioc-enumaudio.sgml | 2 +- v4l2-spec/vidioc-enumaudioout.sgml | 2 +- v4l2-spec/vidioc-enuminput.sgml | 18 ++-- v4l2-spec/vidioc-enumoutput.sgml | 8 +- v4l2-spec/vidioc-enumstd.sgml | 30 +++--- v4l2-spec/vidioc-g-audio.sgml | 4 +- v4l2-spec/vidioc-g-enc-index.sgml | 8 +- v4l2-spec/vidioc-g-ext-ctrls.sgml | 12 +-- v4l2-spec/vidioc-g-fbuf.sgml | 22 ++-- v4l2-spec/vidioc-g-fmt.sgml | 20 ++-- v4l2-spec/vidioc-g-jpegcomp.sgml | 2 +- v4l2-spec/vidioc-g-modulator.sgml | 2 +- v4l2-spec/vidioc-g-parm.sgml | 16 +-- v4l2-spec/vidioc-g-sliced-vbi-cap.sgml | 42 ++++---- v4l2-spec/vidioc-g-tuner.sgml | 32 +++--- v4l2-spec/vidioc-overlay.sgml | 2 +- v4l2-spec/vidioc-qbuf.sgml | 4 +- v4l2-spec/vidioc-querybuf.sgml | 2 +- v4l2-spec/vidioc-querycap.sgml | 8 +- v4l2-spec/vidioc-queryctrl.sgml | 20 ++-- v4l2-spec/vidioc-reqbufs.sgml | 2 +- 70 files changed, 643 insertions(+), 579 deletions(-) create mode 100644 v4l2-spec/custom.xsl diff --git a/.hgignore b/.hgignore index bc408c495..a48595f3a 100644 --- a/.hgignore +++ b/.hgignore @@ -72,6 +72,7 @@ v4l2-spec/v4l2-single$ v4l2-spec/v4l2$ v4l2-spec/v4l2.pdf$ v4l2-spec/videodev2.h.sgml$ +v4l2-spec/man/ v4l/firmware/cpia2/stv0672_vp4.bin v4l/firmware/dabusb/bitstream.bin v4l/firmware/dabusb/firmware.fw diff --git a/v4l/Makefile b/v4l/Makefile index 23ae32cad..29b9675ae 100644 --- a/v4l/Makefile +++ b/v4l/Makefile @@ -57,6 +57,9 @@ firmware:: v4l2-spec:: $(MAKE) -C ../v4l2-spec +man:: + $(MAKE) -C ../v4l2-spec man + dvb-spec:: $(MAKE) -C ../dvb-spec/dvbapi @@ -225,6 +228,9 @@ remove rminstall:: media-rminstall firmware_install:: make -C firmware install +man_install:: + $(MAKE) -C ../v4l2-spec man_install + ################################################# # Compiling preparation rules diff --git a/v4l2-spec/Makefile b/v4l2-spec/Makefile index a88420286..ee5d80688 100644 --- a/v4l2-spec/Makefile +++ b/v4l2-spec/Makefile @@ -119,8 +119,12 @@ WARN = #WARN = -w all -w duplicate -w net # Stylesheet customization. + # docbook/db2 syntax CUSTOM_HTML = --dsl custom.dsl\#html CUSTOM_PRINT = --dsl custom.dsl\#print + # xmlto syntax +CUSTOM_HTML_XMLTO = -m custom.xsl +CUSTOM_PRINT_XMLTO = -m custom.xsl all: capture html-single @@ -130,6 +134,12 @@ html-single: html-single-build.stamp pdf: pdf-build.stamp +man: man-build.stamp + +man_install: man-build.stamp + install -d /usr/local/man/man2 + install -b man/* /usr/local/man/man2 + coffeebreak: all html pdf FUNCS = \ @@ -325,7 +335,8 @@ DOCUMENTED = \ -e "s/\(enum *\)v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1v4l2_mpeg_cx2341x_video_\2<\/link>/g" \ -e "s/\(\(enum\|struct\) *\)\(v4l2_[a-zA-Z0-9_]*\)/\1\3<\/link>/g" \ -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\) /\1<\/link> /g" \ - -e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" + -e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" \ + -e "s/(linkend=\")v4l2-mpeg-vbi-ITV0/\1)v4l2_mpeg_vbi_itv0-1/g" libv4l-fmt.sgml: cat ../v4l2-apps/libv4l/libv4lconvert/*.c| \ @@ -460,10 +471,14 @@ indices.sgml: Makefile # HTML version. html-build.stamp: Makefile checks $(SGMLS) $(GIFPICS) rm -rf v4l2 - if which docbook2html >/dev/null ; then \ - docbook2html $(WARN) $(CUSTOM_HTML) --output v4l2 v4l2.sgml ; \ + if which xmlto >/dev/null ; then \ + xmlto xhtml $(WARN) $(CUSTOM_HTML_XMLTO) -o v4l2 v4l2.sgml ; \ + elif which docbook2html >/dev/null ; then \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl |head -1`"; \ + docbook2html $(WARN) $$DCL $(CUSTOM_HTML) --output v4l2 v4l2.sgml ; \ else \ - db2html $(WARN) $(CUSTOM_HTML) --output v4l2 v4l2.sgml ; \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl |head -1`"; \ + db2html $(WARN) $$DCL $(CUSTOM_HTML) --output v4l2 v4l2.sgml ; \ fi cp $(GIFPICS) v4l2/ cd v4l2 ; \ @@ -477,11 +492,15 @@ html-build.stamp: Makefile checks $(SGMLS) $(GIFPICS) # is more convenient than clicking through dozens of pages. html-single-build.stamp: Makefile checks $(SGMLS) $(GIFPICS) rm -rf v4l2-single - if which docbook2html >/dev/null; then \ - docbook2html $(WARN) $(CUSTOM_HTML) --nochunks \ + if which xmlto >/dev/null ; then \ + xmlto html-nochunks $(WARN) $(CUSTOM_HTML_XMLTO) -o v4l2-single v4l2.sgml ; \ + elif which docbook2html >/dev/null ; then \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl |head -1`"; \ + docbook2html $$DCL $(WARN) $(CUSTOM_HTML) --nochunks \ --output v4l2-single v4l2.sgml ; \ else \ - db2html $(WARN) $(CUSTOM_HTML) --nochunks \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl |head -1`"; \ + db2html $$DCL $(WARN) $(CUSTOM_HTML) --nochunks \ --output v4l2-single v4l2.sgml ; \ fi cp $(GIFPICS) v4l2-single/ @@ -490,13 +509,22 @@ html-single-build.stamp: Makefile checks $(SGMLS) $(GIFPICS) # For printing. pdf-build.stamp: Makefile checks $(SGMLS) $(PDFPICS) - if which docbook2pdf >/dev/null; then \ - docbook2pdf $(WARN) $(CUSTOM_PRINT) v4l2.sgml ; \ + if which db2pdf >/dev/null ; then \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl|head -1`"; \ + db2pdf $$DCL $(WARN) $(CUSTOM_PRINT) v4l2.sgml ; \ + elif which xmlto >/dev/null ; then \ + xmlto pdf $(WARN) $(CUSTOM_HTML_XMLTO) -o v4l2-single v4l2.sgml ; \ else \ - db2pdf $(WARN) $(CUSTOM_PRINT) v4l2.sgml ; \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl |head -1`"; \ + docbook2pdf $$DCL $(WARN) $(CUSTOM_PRINT) v4l2.sgml ; \ fi touch pdf-build.stamp + +# For man +man-build.stamp: Makefile checks $(SGMLS) $(PDFPICS) + xmlto man $(WARN) $(CUSTOM_HTML_XMLTO) -o man v4l2.sgml + # Example. capture: ../v4l2-apps/test/capture-example.c gcc $^ -o $@ diff --git a/v4l2-spec/common.sgml b/v4l2-spec/common.sgml index 75c7141e3..dd598ac9a 100644 --- a/v4l2-spec/common.sgml +++ b/v4l2-spec/common.sgml @@ -27,7 +27,7 @@ input, video standard, picture brightness a. o.
In practice most steps are optional and can be executed out of order. It depends on the V4L2 device type, you can read about the -details in . In this chapter we will discuss +details in . In this chapter we will discuss the basic concepts applicable to all devices.
@@ -75,8 +75,8 @@ written as: alias char-major-81-0 mydriver alias char-major-81-1 mydriver -alias char-major-81-64 mydriver -options mydriver video_nr=0,1 radio_nr=0,1 +alias char-major-81-64 mydriver +options mydriver video_nr=0,1 radio_nr=0,1 @@ -91,7 +91,7 @@ with minor number 64 and 65 (base 64). When no minor number is given as module -option the driver supplies a default. +option the driver supplies a default. recommends the base minor numbers to be used for the various device types. Obviously minor numbers must be unique. When the number is already in use the offending device will not be @@ -101,7 +101,7 @@ linux-kernel@vger.kernel.org, 2002-11-20. --> By convention system administrators create various character device special files with these major and minor numbers in the /dev directory. The names recomended for the -different V4L2 device types are listed in . +different V4L2 device types are listed in . The creation of character special files (with @@ -143,7 +143,7 @@ compatibility with old applications drivers must still register different minor numbers to assign a default function to the device. But if related functions are supported by the driver they must be available under all registered minor numbers. The desired function can be selected after -opening the device as described in . +opening the device as described in . Imagine a driver supporting video capturing, video overlay, raw VBI capturing, and FM radio reception. It registers three @@ -197,7 +197,7 @@ so applications cannot know if it really works. to read or write the requested type of data, and to change related properties, to this file descriptor. Applications can request additional access privileges using the priority mechanism described in -. +.
@@ -303,10 +303,10 @@ device has one or more outputs. Input and output enumeration is the root of most device properties. - + - + Links between various device property structures. @@ -604,7 +604,7 @@ to zero, the VIDIOC_G_STD, VIDIOC_QUERYSTD and VIDIOC_ENUMSTD ioctls shall return the &EINVAL;. - See for a rationale. Probably + See for a rationale. Probably even USB cameras follow some well known video standard. It might have been better to explicitly indicate elsewhere if a device cannot live up to normal expectations, instead of this exception. @@ -752,8 +752,8 @@ using the aggregate &v4l2-format; and the &VIDIOC-G-FMT; and used to examine what the hardware could do, without actually selecting a new data format. The data formats supported by the V4L2 API are covered in the respective device section -in . For a closer look at image formats see -. +in . For a closer look at image formats see +. The VIDIOC_S_FMT ioctl is a major turning-point in the initialization sequence. Prior to this point @@ -863,10 +863,10 @@ determine if scaling takes place. Image Cropping, Insertion and Scaling - + - + The cropping, insertion and scaling process @@ -881,10 +881,10 @@ the bounds substructure of the ioctl. To support a wide range of hardware this specification does not define an origin or units. However by convention drivers should horizontally count unscaled samples relative to 0H (the leading edge -of the horizontal sync pulse, see ). +of the horizontal sync pulse, see ). Vertically ITU-R line -numbers of the first field (, ), multiplied by two if the driver can capture both +numbers of the first field (, ), multiplied by two if the driver can capture both fields. The top left corner, width and height of the source @@ -1036,13 +1036,13 @@ if (-1 == ioctl (fd, &VIDIOC-S-FMT;, &format)) { Selecting an output area -&v4l2-cropcap cropcap; -&v4l2-crop crop; +&v4l2-cropcap; cropcap; +&v4l2-crop; crop; memset (&cropcap, 0, sizeof (cropcap)); cropcap.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -if (-1 == ioctl (fd, VIDIOC_CROPCAP, &cropcap)) { +if (-1 == ioctl (fd, VIDIOC_CROPCAP;, &cropcap)) { perror ("VIDIOC_CROPCAP"); exit (EXIT_FAILURE); } @@ -1063,7 +1063,7 @@ crop.c.top += crop.c.height / 2; /* Ignore if cropping is not supported (EINVAL). */ if (-1 == ioctl (fd, VIDIOC_S_CROP, &crop) - && errno != EINVAL) { + && errno != EINVAL) { perror ("VIDIOC_S_CROP"); exit (EXIT_FAILURE); } diff --git a/v4l2-spec/compat.sgml b/v4l2-spec/compat.sgml index 07b3b4058..3a05a869b 100644 --- a/v4l2-spec/compat.sgml +++ b/v4l2-spec/compat.sgml @@ -23,8 +23,8 @@ API. For compatibility reasons the character device file names recommended for V4L2 video capture, overlay, radio, teletext and raw vbi capture devices did not change from those used by V4L. They are -listed in and below in . +listed in and below in . The V4L videodev module automatically assigns minor numbers to drivers in load order, depending on the @@ -85,14 +85,14 @@ not compatible with V4L or V4L2. , V4L prohibits (or used to prohibit) multiple opens of a device file. V4L2 drivers may support multiple -opens, see for details and consequences. +opens, see for details and consequences. V4L drivers respond to V4L2 ioctls with an &EINVAL;. The compatibility layer in the V4L2 videodev module can translate V4L ioctl requests to their V4L2 counterpart, however a V4L2 driver usually needs more preparation to become fully V4L compatible. This is covered in more detail in . + linkend="driver" />.
@@ -109,7 +109,7 @@ equivalent to V4L2's &VIDIOC-QUERYCAP;. distinguish between device types like this, better think of basic video input, video output and radio devices supporting a set of related functions like video capturing, video overlay and VBI -capturing. See for an +capturing. See for an introduction. @@ -154,7 +154,7 @@ field capability of &v4l2-framebuffer; Whether chromakey overlay is supported. For more information on overlay see -. +. VID_TYPE_CLIPPING @@ -162,7 +162,7 @@ more information on overlay see and V4L2_FBUF_CAP_BITMAP_CLIPPING in field capability of &v4l2-framebuffer; Whether clipping the overlaid image is -supported, see . +supported, see . VID_TYPE_FRAMERAM @@ -170,7 +170,7 @@ supported, see . not set in field capability of &v4l2-framebuffer; Whether overlay overwrites frame buffer memory, -see . +see . VID_TYPE_SCALES @@ -180,7 +180,7 @@ images. The V4L2 API implies the scale factor by setting the cropping dimensions and image size with the &VIDIOC-S-CROP; and &VIDIOC-S-FMT; ioctl, respectively. The driver returns the closest sizes possible. For more information on cropping and scaling see . + linkend="crop" />. VID_TYPE_MONOCHROME @@ -188,7 +188,7 @@ For more information on cropping and scaling see Applications can enumerate the supported image formats with the &VIDIOC-ENUM-FMT; ioctl to determine if the device supports grey scale capturing only. For more information on image -formats see . +formats see . VID_TYPE_SUBCAPTURE @@ -197,7 +197,7 @@ formats see . to determine if the device supports capturing a subsection of the full picture ("cropping" in V4L2). If not, the ioctl returns the &EINVAL;. For more information on cropping and scaling see . + linkend="crop" />. VID_TYPE_MPEG_DECODER @@ -231,7 +231,7 @@ by capabilities flag if the device has any audio inputs or outputs. To determine their number applications can enumerate audio inputs with the &VIDIOC-G-AUDIO; ioctl. The audio ioctls are described in . + linkend="audio" />. The maxwidth, maxheight, @@ -250,7 +250,7 @@ video standard, cropping and scaling limitations. video_channel to enumerate the video inputs of a V4L device. The equivalent V4L2 ioctls are &VIDIOC-ENUMINPUT;, &VIDIOC-G-INPUT; and &VIDIOC-S-INPUT; -using &v4l2-input; as discussed in . +using &v4l2-input; as discussed in . The channel field counting inputs was renamed to index, the video @@ -284,7 +284,7 @@ than one input, &ie; RF connectors, and a device can have multiple tuners. The index number of the tuner associated with the input, if any, is stored in field tuner of &v4l2-input;. Enumeration of tuners is discussed in . + linkend="tuner" />. The redundant VIDEO_VC_TUNER flag was dropped. Video inputs associated with a tuner are of type @@ -294,7 +294,7 @@ dropped. Video inputs associated with a tuner are of type up to 32 audio inputs. Each set bit in the audioset field represents one audio input this video input combines with. For information about audio inputs and -how to switch between them see . +how to switch between them see . The norm field describing the supported video standards was replaced by @@ -303,7 +303,7 @@ supported video standards was replaced by be changed. This flag was a later addition together with the norm field and has been removed in the meantime. V4L2 has a similar, albeit more comprehensive approach -to video standards, see for more +to video standards, see for more information.
@@ -315,7 +315,7 @@ information. video_tuner can be used to enumerate the tuners of a V4L TV or radio device. The equivalent V4L2 ioctls are &VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; using &v4l2-tuner;. Tuners are -covered in . +covered in . The tuner field counting tuners was renamed to index. The fields @@ -330,7 +330,7 @@ associated &v4l2-input;. No replacement exists for the VIDEO_TUNER_NORM flag indicating whether the video standard can be switched. The mode field to select a different video standard was replaced by a whole new -set of ioctls and structures described in . +set of ioctls and structures described in . Due to its ubiquity it should be mentioned the BTTV driver supports several standards in addition to the regular VIDEO_MODE_PAL (0), @@ -403,7 +403,7 @@ fields where replaced by V4L2 controls accessible with the 65535 with no particular reset value. The V4L2 API permits arbitrary limits and defaults which can be queried with the &VIDIOC-QUERYCTRL; ioctl. For general information about controls see . +linkend="control" />. The depth (average number of bits per pixel) of a video image is implied by the selected image @@ -455,7 +455,7 @@ linkend="pixfmt-rgb">V4L2_PIX_FMT_BGR24V4L2_PIX_FMT_BGR32 Presumably all V4L RGB formats are little-endian, although some drivers might interpret them according to machine endianess. V4L2 defines little-endian, big-endian and red/blue -swapped variants. For details see . +swapped variants. For details see . @@ -522,7 +522,7 @@ linkend="V4L2-PIX-FMT-YVU410">V4L2_PIX_FMT_YVU410

V4L2 image formats are defined in . The image format can be selected with the +linkend="pixfmt" />. The image format can be selected with the &VIDIOC-S-FMT; ioctl. @@ -534,7 +534,7 @@ linkend="pixfmt">. The image format can be selected with the video_audio are used to enumerate the audio inputs of a V4L device. The equivalent V4L2 ioctls are &VIDIOC-G-AUDIO; and &VIDIOC-S-AUDIO; using &v4l2-audio; as -discussed in . +discussed in . The audio "channel number" field counting audio inputs was renamed to @@ -555,7 +555,7 @@ the actually received audio programmes in this field. In the V4L2 API this information is stored in the &v4l2-tuner; rxsubchans and audmode fields, respectively. See for more information on tuners. Related to audio +linkend="tuner" /> for more information on tuners. Related to audio modes &v4l2-audio; also reports if this is a mono or stereo input, regardless if the source is a tuner. @@ -608,7 +608,7 @@ attribute replacing the struct video_audio assumed to range from 0 to 65535 with no particular reset value. The V4L2 API permits arbitrary limits and defaults which can be queried with the &VIDIOC-QUERYCTRL; ioctl. For general information about -controls see . +controls see .
@@ -624,7 +624,7 @@ defines a flag to indicate non-destructive overlays instead of a &v4l2-pix-format; fmt substructure of &v4l2-framebuffer;. The depth field was replaced by pixelformat. See for a list of RGB formats and their + linkend="pixfmt-rgb" /> for a list of RGB formats and their respective color depths. Instead of the special ioctls @@ -680,7 +680,7 @@ defines the VIDIOCGCAPTURE and video_capture. The equivalent V4L2 ioctls are &VIDIOC-G-CROP; and &VIDIOC-S-CROP; using &v4l2-crop;, and the related &VIDIOC-CROPCAP; ioctl. This is a rather complex matter, see - for details. + for details. The x, y, width and @@ -723,7 +723,7 @@ ioctls. V4L2 uses the general-purpose data format negotiation ioctls union is used. For more information about the V4L2 read interface see -. +.
Capturing using memory mapping @@ -796,7 +796,7 @@ queues. Applications can query the signal status, if known, with the For a more in-depth discussion of memory mapping and -examples, see . +examples, see .
@@ -859,7 +859,7 @@ correct values. VIDIOCSVBIFMT ioctls using struct vbi_format were added to determine the VBI image parameters. These ioctls are only partially compatible with the -V4L2 VBI interface specified in . +V4L2 VBI interface specified in . An offset field does not exist, sample_format is supposed to be @@ -881,12 +881,12 @@ parameters are invalid. VIDIOCGUNIT ioctl. Applications can find the VBI device associated with a video capture device (or vice versa) by reopening the device and requesting VBI data. For details see -. +. No replacement exists for VIDIOCKEY, and the V4L functions for microcode programming. A new interface for MPEG compression and playback devices is documented in . + linkend="extended-controls" />. @@ -1250,7 +1250,7 @@ into Linux 2.5.46. - As specified in , drivers + As specified in , drivers must make related device functions available under all minor device numbers. @@ -1264,7 +1264,7 @@ flag, a V4L2 symbol which aliased the meaningless O_TRUNC to indicate accesses without data exchange (panel applications) was dropped. Drivers must stay in "panel mode" until the application attempts to initiate a data exchange, see -. +. @@ -1294,8 +1294,8 @@ set and was merged into the flags field. The redundant fields inputs, outputs and audios were removed. These properties -can be determined as described in and . +can be determined as described in and . The somewhat volatile and therefore barely useful fields maxwidth, @@ -1303,15 +1303,15 @@ fields maxwidth, minwidth, minheight, maxframerate were removed. This information -is available as described in and -. +is available as described in and +. V4L2_FLAG_SELECT was removed. We believe the select() function is important enough to require support of it in all V4L2 drivers exchanging data with applications. The redundant V4L2_FLAG_MONOCHROME flag was removed, this information is available as described in . + linkend="format" />. @@ -1383,7 +1383,7 @@ video standards beyond presenting the user a menu. Instead of enumerating supported standards with an ioctl applications can now refer to standards by &v4l2-std-id; and symbols defined in the videodev2.h header file. For details see . The &VIDIOC-G-STD; and + linkend="standard" />. The &VIDIOC-G-STD; and &VIDIOC-S-STD; now take a pointer to this type as argument. &VIDIOC-QUERYSTD; was added to autodetect the received standard, if the hardware has this capability. In &v4l2-standard; an @@ -1577,7 +1577,7 @@ field. &v4l2-buf-type;. Buffer types changed as mentioned above. A new memory field of type &v4l2-memory; was added to distinguish between I/O methods using buffers allocated -by the driver or the application. See for +by the driver or the application. See for details. @@ -1595,7 +1595,7 @@ addition of a second memory mapping method the offset field moved into union m, and a new memory field of type &v4l2-memory; was -added to distinguish between I/O methods. See +added to distinguish between I/O methods. See for details. The V4L2_BUF_REQ_CONTIG @@ -1649,7 +1649,7 @@ to distinguish between field and frame (interlaced) overlay. cropping and scaling interface. The previously unused struct v4l2_cropcap and v4l2_crop where redefined for this purpose. -See for details. +See for details. @@ -1683,7 +1683,7 @@ applications. The example transformation from RGB to YCbCr color space in the old V4L2 documentation was inaccurate, this has been -corrected in . @@ -1702,7 +1702,7 @@ tuner whose type field reads V4L2_TUNER_RADIO. An optional driver access priority mechanism was -added, see for details. +added, see for details. @@ -1734,7 +1734,7 @@ must be recompiled, but not applications. - incorrectly stated that + incorrectly stated that clipping rectangles define regions where the video can be seen. Correct is that clipping rectangles define regions where no video shall be displayed and so the graphics @@ -1756,7 +1756,7 @@ applications assuming a constant parameter need an update. V4L2 2003-11-05 - In the following pixel + In the following pixel formats were incorrectly transferred from Bill Dirks' V4L2 specification. Descriptions below refer to bytes in memory, in ascending address order. @@ -1795,7 +1795,7 @@ ascending address order. The V4L2_PIX_FMT_BGR24 example was always correct. - In the mapping + In the mapping of the V4L VIDEO_PALETTE_RGB24 and VIDEO_PALETTE_RGB32 formats to V4L2 pixel formats was accordingly corrected. @@ -1805,7 +1805,7 @@ was accordingly corrected. Unrelated to the fixes above, drivers may still interpret some V4L2 RGB pixel formats differently. These issues have yet to be addressed, for details see . + linkend="pixfmt-rgb" />. @@ -1844,7 +1844,7 @@ read-only. The return value of the - function was incorrectly documented. + function was incorrectly documented. @@ -1872,7 +1872,7 @@ was not documented. A new sliced VBI interface was added. It is documented -in and replaces the interface first +in and replaces the interface first proposed in V4L2 specification 0.8. @@ -1895,7 +1895,7 @@ and V4L2_STD_ATSC (a set of V4L2_STD_ATSC_16_VSB) were defined. Note the V4L2_STD_525_60 set now includes V4L2_STD_NTSC_443. See also . + linkend="v4l2-std-id" />. @@ -1914,10 +1914,10 @@ was replaced by a struct
V4L2 spec erratum 2005-11-27 - The capture example in + The capture example in called the &VIDIOC-S-CROP; ioctl without checking if cropping is supported. In the video standard selection example in - the &VIDIOC-S-STD; call used the wrong + the &VIDIOC-S-STD; call used the wrong argument type.
@@ -1999,18 +1999,18 @@ interface were not mentioned along with other buffer types.
- In it was clarified + In it was clarified that the &v4l2-audio; mode field is a flags field. - did not mention the + did not mention the sliced VBI and radio capability flags. - In it was + In it was clarified that applications must initialize the tuner type field of &v4l2-frequency; before calling &VIDIOC-S-FREQUENCY;. @@ -2022,8 +2022,8 @@ in &v4l2-requestbuffers; has 2 elements, not 32. - In and the device file names + In and the device file names /dev/vout which never caught on were replaced by /dev/video. @@ -2046,13 +2046,13 @@ and &VIDIOC-TRY-EXT-CTRLS; were added, a flag to skip unsupported controls with &VIDIOC-QUERYCTRL;, new control types V4L2_CTRL_TYPE_INTEGER64 and V4L2_CTRL_TYPE_CTRL_CLASS (), and new control flags + linkend="v4l2-ctrl-type" />), and new control flags V4L2_CTRL_FLAG_READ_ONLY, V4L2_CTRL_FLAG_UPDATE, V4L2_CTRL_FLAG_INACTIVE and V4L2_CTRL_FLAG_SLIDER (). See for details. + linkend="control-flags" />). See for details.
@@ -2077,7 +2077,7 @@ compatibility with older drivers and applications. A new pixel format V4L2_PIX_FMT_RGB444 () was added. +linkend="rgb-formats" />) was added. @@ -2087,7 +2087,7 @@ linkend="rgb-formats">) was added. V4L2_PIX_FMT_HM12 () is a YUV 4:2:0, not 4:2:2 format. +linkend="reserved-formats" />) is a YUV 4:2:0, not 4:2:2 format. @@ -2110,7 +2110,7 @@ later, and under a 3-clause BSD-style license. Two new field orders V4L2_FIELD_INTERLACED_TB and V4L2_FIELD_INTERLACED_BT were - added. See for details. + added. See for details. @@ -2265,7 +2265,7 @@ video encoding. The VIDIOC_G_CHIP_IDENT ioctl was renamed to VIDIOC_G_CHIP_IDENT_OLD and &VIDIOC-DBG-G-CHIP-IDENT; was introduced in its place. The old struct v4l2_chip_ident -was renamed to v4l2_chip_ident_old. +was renamed to v4l2_chip_ident_old. The pixel formats @@ -2297,7 +2297,7 @@ was renamed to v4l2_chip_ident_oldV4L2 in Linux 2.6.32 - Finalized the RDS capture API. See for + Finalized the RDS capture API. See for more information. @@ -2360,7 +2360,7 @@ the V4L2 backward-compatibility layer. Since V4L2 permits multiple opens it is possible (if supported by the V4L2 driver) to capture video while an X client requested video overlay. Restrictions of simultaneous capturing and overlay are discussed in apply. + linkend="overlay" /> apply. Only marginally related to V4L2, XFree86 extended Xv to support hardware YUV to RGB conversion and scaling for faster video @@ -2395,15 +2395,15 @@ and may change in the future. Video Output Overlay (OSD) Interface, . + linkend="osd" />. V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, - &v4l2-buf-type;, . + &v4l2-buf-type;, . V4L2_CAP_VIDEO_OUTPUT_OVERLAY, -&VIDIOC-QUERYCAP; ioctl, . +&VIDIOC-QUERYCAP; ioctl, . &VIDIOC-ENUM-FRAMESIZES; and @@ -2436,7 +2436,7 @@ interfaces and should not be implemented in new drivers. VIDIOC_G_MPEGCOMP and VIDIOC_S_MPEGCOMP ioctls. Use Extended Controls, -. +. diff --git a/v4l2-spec/controls.sgml b/v4l2-spec/controls.sgml index 869198601..f492accb6 100644 --- a/v4l2-spec/controls.sgml +++ b/v4l2-spec/controls.sgml @@ -15,7 +15,7 @@ several IDs for specific purposes. Drivers can also implement their own custom controls using V4L2_CID_PRIVATE_BASE and higher values. The pre-defined control IDs have the prefix V4L2_CID_, and are listed in . The ID is used when querying the attributes of +linkend="control-id" />. The ID is used when querying the attributes of a control, and when getting or setting the current value. Generally applications should present controls to the user @@ -215,7 +215,7 @@ linkend="camera-controls">Camera class controls integer Vertical image centering. Centering is intended to physically adjust cameras. For image cropping see -, for clipping . This +, for clipping . This control is deprecated. New drivers and applications should use the Camera class controls V4L2_CID_TILT_ABSOLUTE, @@ -291,7 +291,7 @@ minimum value disables backlight compensation. ID of the first custom (driver specific) control. Applications depending on particular custom controls should check the -driver name and version, see . +driver name and version, see .
@@ -546,7 +546,7 @@ control class is found: qctrl.id = V4L2_CTRL_CLASS_MPEG | V4L2_CTRL_FLAG_NEXT_CTRL; -while (0 == ioctl (fd, &VIDIOC-QUERYCTRL, &qctrl)) { +while (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &qctrl)) { if (V4L2_CTRL_ID2CLASS (qctrl.id) != V4L2_CTRL_CLASS_MPEG) break; /* ... */ @@ -605,12 +605,12 @@ certain hardware. MPEG Control IDs - - - - - - + + + + + + ID @@ -1386,12 +1386,12 @@ CX23416 MPEG encoding chips.
CX2341x Control IDs - - - - - - + + + + + + ID @@ -1605,12 +1605,12 @@ or sensors.
Camera Control IDs - - - - - - + + + + + + ID @@ -1842,12 +1842,12 @@ tuning power features. FM_TX Control IDs - - - - - - + + + + + + ID @@ -1891,7 +1891,7 @@ This encodes up to 31 pre-defined programme types. Sets the Programme Service name (PS_NAME) for transmission. It is intended for static display on a receiver. It is the primary aid to listeners in programme service -identification and selection. In Annex E of , the RDS specification, +identification and selection. In Annex E of , the RDS specification, there is a full description of the correct character encoding for Programme Service name strings. Also from RDS specification, PS is usually a single eight character text. However, it is also possible to find receivers which can scroll strings sized as 8 x N characters. So, this control must be configured @@ -1905,7 +1905,7 @@ with steps of 8 characters. The result is it must always contain a string with s what is being broadcasted. RDS Radio Text can be applied when broadcaster wishes to transmit longer PS names, programme-related information or any other text. In these cases, RadioText should be used in addition to V4L2_CID_RDS_TX_PS_NAME. The encoding for Radio Text strings is also fully described -in Annex E of . The length of Radio Text strings depends on which RDS Block is being +in Annex E of . The length of Radio Text strings depends on which RDS Block is being used to transmit it, either 32 (2A block) or 64 (2B block). However, it is also possible to find receivers which can scroll strings sized as 32 x N or 64 x N characters. So, this control must be configured with steps of 32 or 64 characters. The result is it must always contain a string with size multiple of 32 or 64. @@ -2036,7 +2036,7 @@ manually or automatically if set to zero. Unit, range and step are driver-specif
For more details about RDS specification, refer to - document, from CENELEC. + document, from CENELEC. diff --git a/v4l2-spec/custom.xsl b/v4l2-spec/custom.xsl new file mode 100644 index 000000000..e1556c37c --- /dev/null +++ b/v4l2-spec/custom.xsl @@ -0,0 +1,29 @@ + + + + + + + +1 +0 +0 +0 + +1 + +1 +1 +1 + +ansi +80 +1 + +1 +1 +1 +3 + +A4 + diff --git a/v4l2-spec/dev-capture.sgml b/v4l2-spec/dev-capture.sgml index d2885988b..32807e43f 100644 --- a/v4l2-spec/dev-capture.sgml +++ b/v4l2-spec/dev-capture.sgml @@ -60,7 +60,7 @@ and scaling. Cropping initialization at minimum requires to reset the parameters to defaults. An example is given in . +linkend="crop" />. To query the current image format applications set the type field of a &v4l2-format; to @@ -85,7 +85,7 @@ without disabling I/O or possibly time consuming hardware preparations. The contents of &v4l2-pix-format; are discussed in . See also the specification of the +linkend="pixfmt" />. See also the specification of the VIDIOC_G_FMT, VIDIOC_S_FMT and VIDIOC_TRY_FMT ioctls for details. Video capture devices must implement both the @@ -103,7 +103,7 @@ returns default parameters as VIDIOC_G_FMT does. linkend="rw">read() function and/or streaming (memory mapping or user pointer) I/O. See for details. +linkend="io" /> for details. @@ -211,12 +211,12 @@ extensions. Applications and drivers must set it to zero. Sliced VBI services - - - - - - + + + + + + Symbol @@ -231,7 +231,7 @@ extensions. Applications and drivers must set it to zero. V4L2_SLICED_TELETEXT_B (Teletext System B) 0x0001 - , + , PAL/SECAM line 7-22, 320-335 (second field 7-22) Last 42 of the 45 byte Teletext packet, that is without clock run-in and framing code, lsb first transmitted. @@ -239,7 +239,7 @@ without clock run-in and framing code, lsb first transmitted. V4L2_SLICED_VPS 0x0400 - + PAL line 16 Byte number 3 to 15 according to Figure 9 of ETS 300 231, lsb first transmitted. @@ -247,7 +247,7 @@ ETS 300 231, lsb first transmitted. V4L2_SLICED_CAPTION_525 0x1000 - + NTSC line 21, 284 (second field 21) Two bytes in transmission order, including parity bit, lsb first transmitted. @@ -255,7 +255,7 @@ bit, lsb first transmitted. V4L2_SLICED_WSS_625 0x4000 - , + , PAL/SECAM line 23 Byte 0 1 @@ -311,7 +311,7 @@ zero. __u32 id - A flag from + A flag from identifying the type of data in this packet. Only a single bit must be set. When the id of a captured packet is zero, the packet is empty and the contents of other fields are @@ -334,7 +334,7 @@ field, 1 for the second field. line The field (as opposed to frame) line number this data has been captured from, or shall be inserted at. See and for valid + linkend="vbi-525" /> and for valid values. Sliced VBI capture devices can set the line number of all packets to 0 if the hardware cannot reliably identify scan lines. The field number must always be valid. @@ -349,7 +349,7 @@ Applications and drivers must set it to zero. __u8 data[48] The packet payload. See for the contents and number of + linkend="vbi-services" /> for the contents and number of bytes passed for each data type. The contents of padding bytes at the end of this array are undefined, drivers and applications shall ignore them. @@ -488,7 +488,7 @@ boundary. The payload shall never exceed 1552 bytes (2 fields with magic[4] A "magic" constant from that indicates + linkend="v4l2-mpeg-vbi-fmt-ivtv-magic" /> that indicates this is a valid sliced VBI data payload and also indicates which member of the anonymous union, itv0 or ITV0, to use for the payload data. @@ -636,7 +636,7 @@ through 23 of the second field. __u8 id A line identifier value from - that indicates + that indicates the type of sliced VBI data stored on this line. diff --git a/v4l2-spec/dev-teletext.sgml b/v4l2-spec/dev-teletext.sgml index 26e125c16..59f9993e1 100644 --- a/v4l2-spec/dev-teletext.sgml +++ b/v4l2-spec/dev-teletext.sgml @@ -1,7 +1,7 @@ Teletext Interface This interface aims at devices receiving and demodulating -Teletext data [, ], evaluating the +Teletext data [, ], evaluating the Teletext packages and storing formatted pages in cache memory. Such devices are usually implemented as microcontrollers with serial interface (I2C) and can be found on older diff --git a/v4l2-spec/fdl-appendix.sgml b/v4l2-spec/fdl-appendix.sgml index f21019ae4..b6ce50dbe 100644 --- a/v4l2-spec/fdl-appendix.sgml +++ b/v4l2-spec/fdl-appendix.sgml @@ -8,7 +8,7 @@ --> - + Version 1.1, March 2000 @@ -24,7 +24,7 @@ license document, but changing it is not allowed. - + GNU Free Documentation License diff --git a/v4l2-spec/func-ioctl.sgml b/v4l2-spec/func-ioctl.sgml index 96dead0ec..00f9690e1 100644 --- a/v4l2-spec/func-ioctl.sgml +++ b/v4l2-spec/func-ioctl.sgml @@ -61,7 +61,7 @@ in the videodev.h header file. Applications should use their own copy, not include the version in the kernel sources on the system they compile on. All V4L2 ioctl requests, their respective function and parameters are specified in . + linkend="user-func" />. @@ -116,7 +116,7 @@ character special device. The request or the data pointed to by argp is not valid. This is a very common error code, see the individual ioctl requests listed in for actual causes. + linkend="user-func" /> for actual causes. diff --git a/v4l2-spec/func-read.sgml b/v4l2-spec/func-read.sgml index a67a5f507..a5089bf88 100644 --- a/v4l2-spec/func-read.sgml +++ b/v4l2-spec/func-read.sgml @@ -110,7 +110,7 @@ free buffers depends on the discarding policy. internally by the driver with the &VIDIOC-G-PARM; and &VIDIOC-S-PARM; ioctls. They are optional, however. The discarding policy is not reported and cannot be changed. For minimum requirements see . + linkend="devices" />. diff --git a/v4l2-spec/io.sgml b/v4l2-spec/io.sgml index 957ffa0bc..f92f24323 100644 --- a/v4l2-spec/io.sgml +++ b/v4l2-spec/io.sgml @@ -17,12 +17,12 @@ yet. Video overlay can be considered another I/O method, although the application does not directly receive the image data. It is selected by initiating video overlay with the &VIDIOC-S-FMT; ioctl. -For more information see . +For more information see . Generally exactly one I/O method, including overlay, is associated with each file descriptor. The only exceptions are applications not exchanging data with a driver ("panel applications", -see ) and drivers permitting simultaneous video capturing +see ) and drivers permitting simultaneous video capturing and overlay using the same file descriptor, for compatibility with V4L and earlier versions of V4L2. @@ -414,7 +414,7 @@ the frames are not properly stamped by the sender. This is frequently the case with USB cameras. Here timestamps refer to the instant the field or frame was received by the driver, not the capture time. These devices identify by not enumerating any video standards, see . +linkend="standard" />. Similar limitations apply to output timestamps. Typically the video hardware locks to a clock controlling the video timing, the @@ -472,14 +472,14 @@ refers to an input stream, applications when an output stream. flags Flags set by the application or driver, see . +linkend="buffer-flags" />. &v4l2-field; field Indicates the field order of the image in the -buffer, see . This field is not used when +buffer, see . This field is not used when the buffer contains VBI data. Drivers must set it when type refers to an input stream, applications when an output stream. @@ -534,7 +534,7 @@ time.Note this may count the frames received e.g. over USB, without taking into account the frames dropped by the remote hardware due to limited compression throughput or bus bandwidth. These devices identify by not enumerating any video -standards, see . +standards, see . &v4l2-memory; @@ -555,7 +555,7 @@ in accordance with the selected I/O method. V4L2_MEMORY_MMAP this is the offset of the buffer from the start of the device memory. The value is returned by the driver and apart of serving as parameter to the &func-mmap; function -not useful for applications. See for details. +not useful for applications. See for details. @@ -564,7 +564,7 @@ not useful for applications. See for details. When memory is V4L2_MEMORY_USERPTR this is a pointer to the buffer (casted to unsigned long type) in virtual memory, set by the -application. See for details. +application. See for details. __u32 @@ -604,48 +604,48 @@ number of a video input as in &v4l2-input; field V4L2_BUF_TYPE_VIDEO_CAPTURE 1 Buffer of a video capture stream, see . + linkend="capture" />. V4L2_BUF_TYPE_VIDEO_OUTPUT 2 Buffer of a video output stream, see . + linkend="output" />. V4L2_BUF_TYPE_VIDEO_OVERLAY 3 - Buffer for video overlay, see . + Buffer for video overlay, see . V4L2_BUF_TYPE_VBI_CAPTURE 4 Buffer of a raw VBI capture stream, see . + linkend="raw-vbi" />. V4L2_BUF_TYPE_VBI_OUTPUT 5 Buffer of a raw VBI output stream, see . + linkend="raw-vbi" />. V4L2_BUF_TYPE_SLICED_VBI_CAPTURE 6 Buffer of a sliced VBI capture stream, see . + linkend="sliced" />. V4L2_BUF_TYPE_SLICED_VBI_OUTPUT 7 Buffer of a sliced VBI output stream, see . + linkend="sliced" />. V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY 8 Buffer for video output overlay (OSD), see . Status: . Status: Experimental. @@ -667,7 +667,7 @@ linkend="experimental">Experimental. V4L2_BUF_FLAG_MAPPED 0x0001 The buffer resides in device memory and has been mapped -into the application's address space, see for details. +into the application's address space, see for details. Drivers set or clear this flag when the VIDIOC_QUERYBUF, VIDIOC_QBUF or I/O. Timecodes The v4l2_timecode structure is -designed to hold a or similar timecode. +designed to hold a or similar timecode. (struct timeval timestamps are stored in &v4l2-buffer; field timestamp.) @@ -782,12 +782,12 @@ designed to hold a or similar timecode. __u32 type Frame rate the timecodes are based on, see . + linkend="timecode-type" />. __u32 flags - Timecode flags, see . + Timecode flags, see . __u8 @@ -1043,10 +1043,10 @@ line, top field first. The bottom field is transmitted first. Field Order, Top Field First Transmitted - + - + @@ -1055,10 +1055,10 @@ line, top field first. The bottom field is transmitted first. Field Order, Bottom Field First Transmitted - + - + diff --git a/v4l2-spec/libv4l.sgml b/v4l2-spec/libv4l.sgml index ec1f8b6fe..c14fc3db2 100644 --- a/v4l2-spec/libv4l.sgml +++ b/v4l2-spec/libv4l.sgml @@ -79,19 +79,18 @@ the calls in the sense that it will use libv4lconvert to provide more video formats and to enhance the image quality. In most cases, libv4l2 just passes the calls directly through to the v4l2 driver, intercepting the calls to -VIDIOC_TRY_FMT, -VIDIOC_G_FMT -VIDIOC_S_FMT -VIDIOC_ENUM_FRAMESIZES -and -VIDIOC_ENUM_FRAMEINTERVALS +VIDIOC_TRY_FMT, +VIDIOC_G_FMT +VIDIOC_S_FMT +VIDIOC_ENUM_FRAMESIZES +and VIDIOC_ENUM_FRAMEINTERVALS in order to emulate the formats V4L2_PIX_FMT_BGR24, V4L2_PIX_FMT_RGB24, V4L2_PIX_FMT_YUV420, and V4L2_PIX_FMT_YVU420, if they aren't available in the driver. -VIDIOC_ENUM_FMT +VIDIOC_ENUM_FMT keeps enumerating the hardware supported formats, plus the emulated formats offered by libv4l at the end. diff --git a/v4l2-spec/pixfmt-grey.sgml b/v4l2-spec/pixfmt-grey.sgml index 271814c53..3b72bc6b2 100644 --- a/v4l2-spec/pixfmt-grey.sgml +++ b/v4l2-spec/pixfmt-grey.sgml @@ -22,7 +22,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-nv12.sgml b/v4l2-spec/pixfmt-nv12.sgml index ec3aec6a0..873f67035 100644 --- a/v4l2-spec/pixfmt-nv12.sgml +++ b/v4l2-spec/pixfmt-nv12.sgml @@ -39,7 +39,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-nv16.sgml b/v4l2-spec/pixfmt-nv16.sgml index c67ba2ebe..26094035f 100644 --- a/v4l2-spec/pixfmt-nv16.sgml +++ b/v4l2-spec/pixfmt-nv16.sgml @@ -38,7 +38,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-packed-rgb.sgml b/v4l2-spec/pixfmt-packed-rgb.sgml index 8c32db3c2..d2dd697a8 100644 --- a/v4l2-spec/pixfmt-packed-rgb.sgml +++ b/v4l2-spec/pixfmt-packed-rgb.sgml @@ -21,50 +21,50 @@ colorspace V4L2_COLORSPACE_SRGB.
Packed RGB Image Formats - - - + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - + + + + Identifier @@ -401,7 +401,7 @@ image Each cell is one byte. - + start + 0: @@ -476,55 +476,55 @@ image Some RGB formats above are uncommon and were probably defined in error. Drivers may interpret them as in . + linkend="rgb-formats-corrected" />.
Packed RGB Image Formats (corrected) - - - + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - + + + + Identifier diff --git a/v4l2-spec/pixfmt-packed-yuv.sgml b/v4l2-spec/pixfmt-packed-yuv.sgml index 7ad8d924a..3cab5d0ca 100644 --- a/v4l2-spec/pixfmt-packed-yuv.sgml +++ b/v4l2-spec/pixfmt-packed-yuv.sgml @@ -17,50 +17,50 @@ word.
Packed YUV Image Formats - - - + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - + + + + Identifier diff --git a/v4l2-spec/pixfmt-sbggr16.sgml b/v4l2-spec/pixfmt-sbggr16.sgml index 275489596..519a9efba 100644 --- a/v4l2-spec/pixfmt-sbggr16.sgml +++ b/v4l2-spec/pixfmt-sbggr16.sgml @@ -27,7 +27,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-sbggr8.sgml b/v4l2-spec/pixfmt-sbggr8.sgml index 37805fe11..5fe84ecc2 100644 --- a/v4l2-spec/pixfmt-sbggr8.sgml +++ b/v4l2-spec/pixfmt-sbggr8.sgml @@ -27,7 +27,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-sgbrg8.sgml b/v4l2-spec/pixfmt-sgbrg8.sgml index 7b148b636..d67a472b0 100644 --- a/v4l2-spec/pixfmt-sgbrg8.sgml +++ b/v4l2-spec/pixfmt-sgbrg8.sgml @@ -27,7 +27,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-sgrbg8.sgml b/v4l2-spec/pixfmt-sgrbg8.sgml index 553c5264a..0cdf13b8a 100644 --- a/v4l2-spec/pixfmt-sgrbg8.sgml +++ b/v4l2-spec/pixfmt-sgrbg8.sgml @@ -27,7 +27,7 @@ columns and rows. Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-uyvy.sgml b/v4l2-spec/pixfmt-uyvy.sgml index 4c33e06cc..816c8d467 100644 --- a/v4l2-spec/pixfmt-uyvy.sgml +++ b/v4l2-spec/pixfmt-uyvy.sgml @@ -27,7 +27,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-vyuy.sgml b/v4l2-spec/pixfmt-vyuy.sgml index 61a789fcf..61f12a5e6 100644 --- a/v4l2-spec/pixfmt-vyuy.sgml +++ b/v4l2-spec/pixfmt-vyuy.sgml @@ -27,7 +27,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-y16.sgml b/v4l2-spec/pixfmt-y16.sgml index 98a550b19..d58404015 100644 --- a/v4l2-spec/pixfmt-y16.sgml +++ b/v4l2-spec/pixfmt-y16.sgml @@ -25,7 +25,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-y41p.sgml b/v4l2-spec/pixfmt-y41p.sgml index c18aae440..73c8536ef 100644 --- a/v4l2-spec/pixfmt-y41p.sgml +++ b/v4l2-spec/pixfmt-y41p.sgml @@ -31,7 +31,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-yuv410.sgml b/v4l2-spec/pixfmt-yuv410.sgml index fb989204c..8eb4a193d 100644 --- a/v4l2-spec/pixfmt-yuv410.sgml +++ b/v4l2-spec/pixfmt-yuv410.sgml @@ -37,7 +37,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-yuv411p.sgml b/v4l2-spec/pixfmt-yuv411p.sgml index 8de4e8c94..00e0960a9 100644 --- a/v4l2-spec/pixfmt-yuv411p.sgml +++ b/v4l2-spec/pixfmt-yuv411p.sgml @@ -38,7 +38,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-yuv420.sgml b/v4l2-spec/pixfmt-yuv420.sgml index 0b0b57cd5..42d7de5e4 100644 --- a/v4l2-spec/pixfmt-yuv420.sgml +++ b/v4l2-spec/pixfmt-yuv420.sgml @@ -39,7 +39,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-yuv422p.sgml b/v4l2-spec/pixfmt-yuv422p.sgml index 5a295eb0d..4348bd9f0 100644 --- a/v4l2-spec/pixfmt-yuv422p.sgml +++ b/v4l2-spec/pixfmt-yuv422p.sgml @@ -36,7 +36,7 @@ pixel image Each cell is one byte. - + start + 0: diff --git a/v4l2-spec/pixfmt-yuyv.sgml b/v4l2-spec/pixfmt-yuyv.sgml index 4f083b3be..bdb2ffacb 100644 --- a/v4l2-spec/pixfmt-yuyv.sgml +++ b/v4l2-spec/pixfmt-yuyv.sgml @@ -27,7 +27,7 @@ pixel image Each cell is one byte. - start + 0: diff --git a/v4l2-spec/pixfmt-yvyu.sgml b/v4l2-spec/pixfmt-yvyu.sgml index 734688fef..40d17ae39 100644 --- a/v4l2-spec/pixfmt-yvyu.sgml +++ b/v4l2-spec/pixfmt-yvyu.sgml @@ -27,7 +27,7 @@ pixel image Each cell is one byte. - start + 0: diff --git a/v4l2-spec/pixfmt.sgml b/v4l2-spec/pixfmt.sgml index 9e6bebeb4..aaea55d44 100644 --- a/v4l2-spec/pixfmt.sgml +++ b/v4l2-spec/pixfmt.sgml @@ -39,9 +39,9 @@ format is YUV 4:2:0, width and The pixel format or type of compression, set by the application. This is a little endian four character code. V4L2 defines -standard RGB formats in , YUV formats in , and reserved codes in +standard RGB formats in , YUV formats in , and reserved codes in &v4l2-field; @@ -50,7 +50,7 @@ linkend="reserved-formats"> can request to capture or output only the top or bottom field, or both fields interlaced or sequentially stored in one buffer or alternating in separate buffers. Drivers return the actual field order selected. -For details see . +For details see . __u32 @@ -94,7 +94,7 @@ hold an image. colorspace This information supplements the pixelformat and must be set by the driver, -see . +see . __u32 @@ -304,20 +304,20 @@ EB = clamp (b * 255);
enum v4l2_colorspace - - - - - - - - - - - - - - + + + + + + + + + + + + + + Identifier @@ -344,8 +344,8 @@ given in the CIE system (1931) V4L2_COLORSPACE_SMPTE170M 1 - NTSC/PAL according to , - + NTSC/PAL according to , + x = 0.630, y = 0.340 x = 0.310, y = 0.595 x = 0.155, y = 0.070 @@ -363,7 +363,7 @@ given in the CIE system (1931) V4L2_COLORSPACE_SMPTE240M 2 1125-Line (US) HDTV, see +linkend="smpte240m" /> x = 0.630, y = 0.340 x = 0.310, y = 0.595 x = 0.155, y = 0.070 @@ -381,7 +381,7 @@ linkend="smpte240m"> V4L2_COLORSPACE_REC709 3 HDTV and modern devices, see +linkend="itu709" /> x = 0.640, y = 0.330 x = 0.300, y = 0.600 x = 0.150, y = 0.060 @@ -404,7 +404,7 @@ quantizes E'Y to 238 levels, yielding a range of Y' = 16 … 253, unlike Rec. 601 Y' = 16 … 235. This is not a typo in the Bt878 documentation, it has been implemented in silicon. The chroma extents are unclear. - , + , ? ? ? @@ -423,8 +423,8 @@ implemented in silicon. The chroma extents are unclear. No identifier exists for M/PAL which uses the chromaticities of M/NTSC, the remaining parameters are equal to B and G/PAL. - according to , + according to , x = 0.67, y = 0.33 x = 0.21, y = 0.71 x = 0.14, y = 0.08 @@ -440,7 +440,7 @@ G/PAL. V4L2_COLORSPACE_470_SYSTEM_BG 6 625-line PAL and SECAM systems according to , +linkend="itu470" />, x = 0.64, y = 0.33 x = 0.29, y = 0.60 x = 0.15, y = 0.06 @@ -456,7 +456,7 @@ Illuminant D65 V4L2_COLORSPACE_JPEG 7 - JPEG Y'CbCr, see , + JPEG Y'CbCr, see , ? ? ? @@ -502,23 +502,23 @@ access the palette, this must be done with ioctls of the Linux framebuffer API.<
Indexed Image Format - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + Identifier @@ -565,7 +565,7 @@ access the palette, this must be done with ioctls of the Linux framebuffer API.< &sub-packed-rgb; &sub-sbggr8; &sub-sgbrg8; - &sub-sgrbg8 + &sub-sgrbg8; &sub-sbggr16; @@ -577,7 +577,7 @@ signals. It separates the brightness information (Y) from the color information (U and V or Cb and Cr). The color information consists of red and blue color difference signals, this way the green component can be reconstructed by subtracting from the -brightness component. See for conversion +brightness component. See for conversion examples. YUV was chosen because early television would only transmit brightness information. To add color in a way compatible with existing receivers a new signal carrier was added to transmit the color @@ -629,7 +629,7 @@ information. 'MPEG' MPEG stream. The actual format is determined by extended control V4L2_CID_MPEG_STREAM_TYPE, see -. +. diff --git a/v4l2-spec/v4l2.sgml b/v4l2-spec/v4l2.sgml index f274ab95b..62b8538a7 100644 --- a/v4l2-spec/v4l2.sgml +++ b/v4l2-spec/v4l2.sgml @@ -1,6 +1,7 @@ - %entities; - + %entities; + @@ -10,9 +11,9 @@ 2"> -"> -"> -"> +"> +"> +"> http://www.linuxtv.org/lists.php"> diff --git a/v4l2-spec/vidioc-cropcap.sgml b/v4l2-spec/vidioc-cropcap.sgml index 49bb9855b..816e90e28 100644 --- a/v4l2-spec/vidioc-cropcap.sgml +++ b/v4l2-spec/vidioc-cropcap.sgml @@ -104,7 +104,7 @@ frequency and the frequency required to get square pixels.When cropping coordinates refer to square pixels, the driver sets pixelaspect to 1/1. Other common values are 54/59 for PAL and SECAM, 11/10 for NTSC sampled -according to []. +according to []. diff --git a/v4l2-spec/vidioc-dbg-g-chip-ident.sgml b/v4l2-spec/vidioc-dbg-g-chip-ident.sgml index 84c704e61..4a09e203a 100644 --- a/v4l2-spec/vidioc-dbg-g-chip-ident.sgml +++ b/v4l2-spec/vidioc-dbg-g-chip-ident.sgml @@ -141,7 +141,7 @@ access instructions. __u32 type - See for a list of + See for a list of possible types. @@ -174,14 +174,14 @@ to the type field. struct v4l2_dbg_match match - How to match the chip, see . + How to match the chip, see . __u32 ident A chip identifier as defined in the Linux media/v4l2-chip-ident.h header file, or one of -the values from . +the values from . __u32 diff --git a/v4l2-spec/vidioc-dbg-g-register.sgml b/v4l2-spec/vidioc-dbg-g-register.sgml index de8aacc3f..980c7f3e2 100644 --- a/v4l2-spec/vidioc-dbg-g-register.sgml +++ b/v4l2-spec/vidioc-dbg-g-register.sgml @@ -156,7 +156,7 @@ access instructions. __u32 type - See for a list of + See for a list of possible types. @@ -185,14 +185,14 @@ to the type field.
struct <structname>v4l2_dbg_register</structname> - - - + + + struct v4l2_dbg_match match - How to match the chip, see . + How to match the chip, see . __u64 diff --git a/v4l2-spec/vidioc-encoder-cmd.sgml b/v4l2-spec/vidioc-encoder-cmd.sgml index 144b61c66..b0dde9438 100644 --- a/v4l2-spec/vidioc-encoder-cmd.sgml +++ b/v4l2-spec/vidioc-encoder-cmd.sgml @@ -95,13 +95,13 @@ them. They were introduced in Linux 2.6.21. __u32 cmd - The encoder command, see . + The encoder command, see . __u32 flags Flags to go with the command, see . If no flags are defined for + linkend="encoder-flags" />. If no flags are defined for this command, drivers and applications must set this field to zero. diff --git a/v4l2-spec/vidioc-enum-fmt.sgml b/v4l2-spec/vidioc-enum-fmt.sgml index 5e0c7c770..7a31c2349 100644 --- a/v4l2-spec/vidioc-enum-fmt.sgml +++ b/v4l2-spec/vidioc-enum-fmt.sgml @@ -84,7 +84,7 @@ and higher. __u32 flags - See + See __u8 @@ -104,7 +104,7 @@ macro: #define v4l2_fourcc(a,b,c,d) (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) Several image formats are already -defined by this specification in . Note these +defined by this specification in . Note these codes are not the same as those used in the Windows world. diff --git a/v4l2-spec/vidioc-enum-frameintervals.sgml b/v4l2-spec/vidioc-enum-frameintervals.sgml index fa0ac3616..3c216e113 100644 --- a/v4l2-spec/vidioc-enum-frameintervals.sgml +++ b/v4l2-spec/vidioc-enum-frameintervals.sgml @@ -62,7 +62,7 @@ type of frame intervals the device supports. Here are the semantics of the function for the different cases: - Discrete: The function + Discrete: The function returns success if the given index value (zero-based) is valid. The application should increase the index by one for each call until EINVAL is returned. The `v4l2_frmivalenum.type` @@ -70,7 +70,7 @@ field is set to `V4L2_FRMIVAL_TYPE_DISCRETE` by the driver. Of the union only the `discrete` member is valid. - Step-wise: The function + Step-wise: The function returns success if the given index value is zero and EINVAL for any other index value. The v4l2_frmivalenum.type field is set to @@ -79,7 +79,7 @@ union only the stepwise member is valid. - Continuous: This is a + Continuous: This is a special case of the step-wise type above. The function returns success if the given index value is zero and EINVAL for any other index value. The @@ -111,7 +111,7 @@ enumeration. - Frame intervals and frame + Frame intervals and frame rates: The V4L2 API uses frame intervals instead of frame rates. Given the frame interval the frame rate can be computed as follows:frame_rate = 1 / frame_interval @@ -156,10 +156,10 @@ application should zero out all members except for the
struct <structname>v4l2_frmivalenum</structname> - - - - + + + + __u32 diff --git a/v4l2-spec/vidioc-enum-framesizes.sgml b/v4l2-spec/vidioc-enum-framesizes.sgml index 909cda68b..6afa4542c 100644 --- a/v4l2-spec/vidioc-enum-framesizes.sgml +++ b/v4l2-spec/vidioc-enum-framesizes.sgml @@ -69,7 +69,7 @@ function for the different cases: - Discrete: The function + Discrete: The function returns success if the given index value (zero-based) is valid. The application should increase the index by one for each call until EINVAL is returned. The @@ -79,7 +79,7 @@ union only the discrete member is valid. - Step-wise: The function + Step-wise: The function returns success if the given index value is zero and EINVAL for any other index value. The v4l2_frmsizeenum.type field is set to @@ -88,7 +88,7 @@ union only the stepwise member is valid. - Continuous: This is a + Continuous: This is a special case of the step-wise type above. The function returns success if the given index value is zero and EINVAL for any other index value. The @@ -185,10 +185,10 @@ application should zero out all members except for the
struct <structname>v4l2_frmsizeenum</structname> - - - - + + + + __u32 diff --git a/v4l2-spec/vidioc-enumaudio.sgml b/v4l2-spec/vidioc-enumaudio.sgml index 2cd9e020d..9ae8f2d3a 100644 --- a/v4l2-spec/vidioc-enumaudio.sgml +++ b/v4l2-spec/vidioc-enumaudio.sgml @@ -57,7 +57,7 @@ to this structure. Drivers fill the rest of the structure or return an inputs applications shall begin at index zero, incrementing by one until the driver returns EINVAL. - See for a description of + See for a description of &v4l2-audio;. diff --git a/v4l2-spec/vidioc-enumaudioout.sgml b/v4l2-spec/vidioc-enumaudioout.sgml index 5c51e3bfe..d3d7c0ab1 100644 --- a/v4l2-spec/vidioc-enumaudioout.sgml +++ b/v4l2-spec/vidioc-enumaudioout.sgml @@ -60,7 +60,7 @@ until the driver returns EINVAL. Note connectors on a TV card to loop back the received audio signal to a sound card are not audio outputs in this sense. - See for a description of + See for a description of &v4l2-audioout;. diff --git a/v4l2-spec/vidioc-enuminput.sgml b/v4l2-spec/vidioc-enuminput.sgml index 824b47e5f..414856b82 100644 --- a/v4l2-spec/vidioc-enuminput.sgml +++ b/v4l2-spec/vidioc-enuminput.sgml @@ -79,7 +79,7 @@ for the user, preferably the connector label on the device itself. __u32 type Type of the input, see . + linkend="input-type" />. __u32 @@ -94,7 +94,7 @@ shall not interpret this as lack of audio support. Some drivers automatically select audio sources and do not enumerate them since there is no choice anyway.For details on audio inputs and how to select the current input see . + linkend="audio" />. __u32 @@ -104,7 +104,7 @@ demodulators). When the type is set to V4L2_INPUT_TYPE_TUNER this is an RF connector and this field identifies the tuner. It corresponds to &v4l2-tuner; field index. For details on -tuners see . +tuners see . &v4l2-std-id; @@ -112,13 +112,13 @@ tuners see . Every video input supports one or more different video standards. This field is a set of all supported standards. For details on video standards and how to switch see . +linkend="standard" />. __u32 status This field provides status information about the -input. See for flags. +input. See for flags. With the exception of the sensor orientation bits status is only valid when this is the current input. @@ -162,11 +162,11 @@ is OK." -->
Input Status Flags - - - + + + + align="left" /> General diff --git a/v4l2-spec/vidioc-enumoutput.sgml b/v4l2-spec/vidioc-enumoutput.sgml index 7e3481203..e8d16dcd5 100644 --- a/v4l2-spec/vidioc-enumoutput.sgml +++ b/v4l2-spec/vidioc-enumoutput.sgml @@ -78,7 +78,7 @@ user, preferably the connector label on the device itself. __u32 type Type of the output, see . + linkend="output-type" />. __u32 @@ -92,7 +92,7 @@ none.When the driver does not enumerate audio outputs no bits must be set. Applications shall not interpret this as lack of audio support. Drivers may automatically select audio outputs without enumerating them.For details on audio outputs and how to -select the current output see . +select the current output see . __u32 @@ -102,7 +102,7 @@ When the type is V4L2_OUTPUT_TYPE_MODULATOR this is an RF connector and this field identifies the modulator. It corresponds to &v4l2-modulator; field index. For details -on modulators see . +on modulators see . &v4l2-std-id; @@ -110,7 +110,7 @@ on modulators see . Every video output supports one or more different video standards. This field is a set of all supported standards. For details on video standards and how to switch see . + linkend="standard" />. __u32 diff --git a/v4l2-spec/vidioc-enumstd.sgml b/v4l2-spec/vidioc-enumstd.sgml index c775671bd..95803fe2c 100644 --- a/v4l2-spec/vidioc-enumstd.sgml +++ b/v4l2-spec/vidioc-enumstd.sgml @@ -78,7 +78,7 @@ application. &v4l2-std-id; id The bits in this field identify the standard as -one of the common standards listed in , +one of the common standards listed in , or if bits 32 to 63 are set as custom standards. Multiple bits can be set if the hardware does not distinguish between these standards, however separate indices do not indicate the opposite. The @@ -145,7 +145,7 @@ the array to zero. v4l2_std_id This type is a set, each bit representing another video standard as listed below and in . The 32 most significant bits are reserved +linkend="video-standards" />. The 32 most significant bits are reserved for custom (driver defined) video standards. @@ -252,20 +252,20 @@ url="http://linuxtv.org">http://linuxtv.org.
- Video Standards (based on [<xref linkend="itu470">]) + Video Standards (based on [<xref linkend="itu470" />]) - - - - - - - - - - - - + + + + + + + + + + + + Characteristics diff --git a/v4l2-spec/vidioc-g-audio.sgml b/v4l2-spec/vidioc-g-audio.sgml index 8b929158e..65361a8c2 100644 --- a/v4l2-spec/vidioc-g-audio.sgml +++ b/v4l2-spec/vidioc-g-audio.sgml @@ -99,13 +99,13 @@ user, preferably the connector label on the device itself. __u32 capability Audio capability flags, see . + linkend="audio-capability" />. __u32 mode Audio mode flags set by drivers and applications (on - VIDIOC_S_AUDIO ioctl), see . + VIDIOC_S_AUDIO ioctl), see . __u32 diff --git a/v4l2-spec/vidioc-g-enc-index.sgml b/v4l2-spec/vidioc-g-enc-index.sgml index bc4153647..9f242e4b2 100644 --- a/v4l2-spec/vidioc-g-enc-index.sgml +++ b/v4l2-spec/vidioc-g-enc-index.sgml @@ -126,8 +126,8 @@ order by their offset. The offset in bytes from the beginning of the compressed video stream to the beginning of this picture, that is a PES packet header as defined in or a picture -header as defined in . When + linkend="mpeg2part1" /> or a picture +header as defined in . When the encoder is stopped, the driver resets the offset to zero. @@ -135,7 +135,7 @@ the encoder is stopped, the driver resets the offset to zero. pts The 33 bit Presentation Time Stamp of this picture as defined in . + linkend="mpeg2part1" />. __u32 @@ -146,7 +146,7 @@ Stamp of this picture as defined in __u32 flags Flags containing the coding type of this picture, see . + linkend="enc-idx-flags" />. __u32 diff --git a/v4l2-spec/vidioc-g-ext-ctrls.sgml b/v4l2-spec/vidioc-g-ext-ctrls.sgml index 352f24cbf..3aa7f8f9f 100644 --- a/v4l2-spec/vidioc-g-ext-ctrls.sgml +++ b/v4l2-spec/vidioc-g-ext-ctrls.sgml @@ -56,7 +56,7 @@ VIDIOC_TRY_EXT_CTRLS These ioctls allow the caller to get or set multiple controls atomically. Control IDs are grouped into control classes (see -) and all controls in the control array +) and all controls in the control array must belong to the same control class. Applications must always fill in the @@ -183,7 +183,7 @@ applications must set the array to zero. __u32 ctrl_class The control class to which all controls belong, see -. +. __u32 @@ -225,7 +225,7 @@ if count equals zero. V4L2_CTRL_CLASS_USER 0x980000 The class containing user controls. These controls -are described in . All controls that can be set +are described in . All controls that can be set using the &VIDIOC-S-CTRL; and &VIDIOC-G-CTRL; ioctl belong to this class. @@ -234,21 +234,21 @@ class.0x990000The class containing MPEG compression controls. These controls are described in . + linkend="mpeg-controls" />. V4L2_CTRL_CLASS_CAMERA 0x9a0000 The class containing camera controls. These controls are described in . + linkend="camera-controls" />. V4L2_CTRL_CLASS_FM_TX 0x9b0000 The class containing FM Transmitter (FM TX) controls. These controls are described in . + linkend="fm-tx-controls" />. diff --git a/v4l2-spec/vidioc-g-fbuf.sgml b/v4l2-spec/vidioc-g-fbuf.sgml index 6781b5334..f70170626 100644 --- a/v4l2-spec/vidioc-g-fbuf.sgml +++ b/v4l2-spec/vidioc-g-fbuf.sgml @@ -118,14 +118,14 @@ can set the parameters for a destructive video overlay.capabilityOverlay capability flags set by the driver, see -. +. __u32 flags Overlay control flags set by application and -driver, see +driver, see void * @@ -149,7 +149,7 @@ provide a base address. The driver may accept only base addresses which are a multiple of two, four or eight bytes. For Video Output Overlays the driver must return a valid base address, so applications can find the corresponding Linux -framebuffer device (see ). +framebuffer device (see ). &v4l2-pix-format; @@ -157,7 +157,7 @@ framebuffer device (see ). Layout of the frame buffer. The v4l2_pix_format structure is defined in , for clarification the fields and acceptable values +linkend="pixfmt" />, for clarification the fields and acceptable values are listed below: @@ -207,7 +207,7 @@ not including V4L2_PIX_FMT_YUYV and V4L2_PIX_FMT_UYVY) and the V4L2_PIX_FMT_PAL8 format are also permitted. The behavior of the driver when an application requests a compressed -format is undefined. See for information on +format is undefined. See for information on pixel formats. @@ -270,7 +270,7 @@ driver. colorspace This information supplements the pixelformat and must be set by the driver, -see . +see . @@ -371,15 +371,15 @@ Most drivers seem to ignore these flags. For compatibility with the Use chroma-keying. The chroma-key color is determined by the chromakey field of &v4l2-window; and negotiated with the &VIDIOC-S-FMT; ioctl, see + linkend="overlay" /> and - . + . There are no flags to enable clipping using a list of clip rectangles or a bitmap. These methods are negotiated with the &VIDIOC-S-FMT; ioctl, see and . + linkend="overlay" /> and . V4L2_FBUF_FLAG_LOCAL_ALPHA @@ -398,8 +398,8 @@ with video images. The blend function is: output = (framebuffer pixel * alpha + video pixel * (255 - alpha)) / 255. The alpha value is determined by the global_alpha field of &v4l2-window; and negotiated with the &VIDIOC-S-FMT; ioctl, see -and . + linkend="overlay" /> +and . V4L2_FBUF_FLAG_LOCAL_INV_ALPHA diff --git a/v4l2-spec/vidioc-g-fmt.sgml b/v4l2-spec/vidioc-g-fmt.sgml index 0a466b2c7..7c7d1b72c 100644 --- a/v4l2-spec/vidioc-g-fmt.sgml +++ b/v4l2-spec/vidioc-g-fmt.sgml @@ -72,7 +72,7 @@ When the requested buffer type is not supported drivers return an initialize the type field and all fields of the respective fmt union member. For details see the documentation of the various devices -types in . Good practice is to query the +types in . Good practice is to query the current parameters first, and to modify only those parameters not suitable for the application. When the application calls the VIDIOC_S_FMT ioctl @@ -108,17 +108,17 @@ this ioctl.
struct <structname>v4l2_format</structname> - - - - + + + + &v4l2-buf-type; type Type of the data stream, see . + linkend="v4l2-buf-type" />. union @@ -129,7 +129,7 @@ this ioctl. &v4l2-pix-format; pix Definition of an image format, see , used by video capture and output + linkend="pixfmt" />, used by video capture and output devices. @@ -137,14 +137,14 @@ devices. &v4l2-window; win Definition of an overlaid image, see , used by video overlay devices. + linkend="overlay" />, used by video overlay devices. &v4l2-vbi-format; vbi Raw VBI capture or output parameters. This is -discussed in more detail in . Used by raw VBI +discussed in more detail in . Used by raw VBI capture and output devices. @@ -152,7 +152,7 @@ capture and output devices. &v4l2-sliced-vbi-format; sliced Sliced VBI capture or output parameters. See - for details. Used by sliced VBI + for details. Used by sliced VBI capture and output devices. diff --git a/v4l2-spec/vidioc-g-jpegcomp.sgml b/v4l2-spec/vidioc-g-jpegcomp.sgml index 0755b834b..77394b287 100644 --- a/v4l2-spec/vidioc-g-jpegcomp.sgml +++ b/v4l2-spec/vidioc-g-jpegcomp.sgml @@ -116,7 +116,7 @@ to add them. __u32 jpeg_markers - See . + See . diff --git a/v4l2-spec/vidioc-g-modulator.sgml b/v4l2-spec/vidioc-g-modulator.sgml index 945147f90..15ce660f0 100644 --- a/v4l2-spec/vidioc-g-modulator.sgml +++ b/v4l2-spec/vidioc-g-modulator.sgml @@ -128,7 +128,7 @@ Hz.txsubchansWith this field applications can determine how audio sub-carriers shall be modulated. It contains a set of flags as -defined in . Note the tuner +defined in . Note the tuner rxsubchans flags are reused, but the semantics are different. Video output devices are assumed to have an analog or PCM audio input with 1-3 channels. The diff --git a/v4l2-spec/vidioc-g-parm.sgml b/v4l2-spec/vidioc-g-parm.sgml index 6ad43823e..78332d365 100644 --- a/v4l2-spec/vidioc-g-parm.sgml +++ b/v4l2-spec/vidioc-g-parm.sgml @@ -123,12 +123,12 @@ higher. __u32 capability - See . + See . __u32 capturemode - Set by drivers and applications, see . + Set by drivers and applications, see . &v4l2-fract; @@ -153,7 +153,7 @@ zero.Drivers support this function only when they set the Custom (driver specific) streaming parameters. When unused, applications and drivers must set this field to zero. Applications using this field should check the driver name and -version, see . +version, see . __u32 @@ -163,7 +163,7 @@ of buffers used internally by the driver in &func-read; mode. Drivers return the actual number of buffers. When an application requests zero buffers, drivers should just return the current setting rather than the minimum or an error code. For details see . + linkend="rw" />. __u32 @@ -183,13 +183,13 @@ applications must set the array to zero. __u32 capability - See . + See . __u32 outputmode Set by drivers and applications, see . + linkend="parm-flags" />. &v4l2-fract; @@ -218,7 +218,7 @@ zero.Drivers support this function only when they set the Custom (driver specific) streaming parameters. When unused, applications and drivers must set this field to zero. Applications using this field should check the driver name and -version, see . +version, see . __u32 @@ -228,7 +228,7 @@ of buffers used internally by the driver in write() mode. Drivers return the actual number of buffers. When an application requests zero buffers, drivers should just return the current setting rather than the minimum or an error -code. For details see . +code. For details see . __u32 diff --git a/v4l2-spec/vidioc-g-sliced-vbi-cap.sgml b/v4l2-spec/vidioc-g-sliced-vbi-cap.sgml index 3568bacf1..10e721b17 100644 --- a/v4l2-spec/vidioc-g-sliced-vbi-cap.sgml +++ b/v4l2-spec/vidioc-g-sliced-vbi-cap.sgml @@ -63,12 +63,12 @@ and the ioctl changed from read-only to write-read, in Linux 2.6.19.
struct <structname>v4l2_sliced_vbi_cap</structname> - - - - - - + + + + + + __u16 @@ -83,10 +83,10 @@ supported by the driver. Equal to the union of all elements of the Each element of this array contains a set of data services the hardware can look for or insert into a particular scan line. Data services are defined in . Array indices map to ITU-R + linkend="vbi-services" />. Array indices map to ITU-R line numbers (see also and ) as follows: + linkend="vbi-525" /> and ) as follows: @@ -135,7 +135,7 @@ can identify on a given line may be limited. For example on PAL line 16 the hardware may be able to look for a VPS or Teletext signal, but not both at the same time. Applications can learn about these limits using the &VIDIOC-S-FMT; ioctl as described in . + linkend="sliced" />. @@ -151,7 +151,7 @@ using the &VIDIOC-S-FMT; ioctl as described in &v4l2-buf-type; type Type of the data stream, see . Should be + linkend="v4l2-buf-type" />. Should be V4L2_BUF_TYPE_SLICED_VBI_CAPTURE or V4L2_BUF_TYPE_SLICED_VBI_OUTPUT. @@ -169,12 +169,12 @@ extensions. Applications and drivers must set it to zero.
Sliced VBI services - - - - - - + + + + + + Symbol @@ -189,7 +189,7 @@ extensions. Applications and drivers must set it to zero. V4L2_SLICED_TELETEXT_B (Teletext System B) 0x0001 - , + , PAL/SECAM line 7-22, 320-335 (second field 7-22) Last 42 of the 45 byte Teletext packet, that is without clock run-in and framing code, lsb first transmitted. @@ -197,7 +197,7 @@ without clock run-in and framing code, lsb first transmitted. V4L2_SLICED_VPS 0x0400 - + PAL line 16 Byte number 3 to 15 according to Figure 9 of ETS 300 231, lsb first transmitted. @@ -205,7 +205,7 @@ ETS 300 231, lsb first transmitted. V4L2_SLICED_CAPTION_525 0x1000 - + NTSC line 21, 284 (second field 21) Two bytes in transmission order, including parity bit, lsb first transmitted. @@ -213,7 +213,7 @@ bit, lsb first transmitted. V4L2_SLICED_WSS_625 0x4000 - , + , PAL/SECAM line 23 Byte 0 1 diff --git a/v4l2-spec/vidioc-g-tuner.sgml b/v4l2-spec/vidioc-g-tuner.sgml index eb0b89e9a..bd98c734c 100644 --- a/v4l2-spec/vidioc-g-tuner.sgml +++ b/v4l2-spec/vidioc-g-tuner.sgml @@ -86,11 +86,11 @@ is available.
struct <structname>v4l2_tuner</structname> - - - - - + + + + + __u32 @@ -110,13 +110,13 @@ field is not quite clear.--> &v4l2-tuner-type; type Type of the tuner, see . + linkend="v4l2-tuner-type" />. __u32 capability Tuner capability flags, see -. Audio flags indicate the ability +. Audio flags indicate the ability to decode audio subprograms. They will not change, for example with the current video standard.When the structure refers to a radio tuner only the @@ -147,7 +147,7 @@ Hz. decoders can determine the received audio subprograms by analyzing audio carriers, pilot tones or other indicators. To pass this information drivers set flags defined in in this field. For + linkend="tuner-rxsubchans" /> in this field. For example: @@ -200,11 +200,11 @@ tuner. __u32 audmode The selected audio mode, see - for valid values. The audio mode does + for valid values. The audio mode does not affect audio subprogram detection, and like a control it does not automatically change unless the requested mode is invalid or unsupported. See for possible results when + linkend="tuner-matrix" /> for possible results when the selected and received audio programs do not match.Currently this is the only field of struct v4l2_tuner applications can @@ -436,12 +436,12 @@ mode.
Tuner Audio Matrix - - - - - - + + + + + + diff --git a/v4l2-spec/vidioc-overlay.sgml b/v4l2-spec/vidioc-overlay.sgml index d16709fd1..1036c582c 100644 --- a/v4l2-spec/vidioc-overlay.sgml +++ b/v4l2-spec/vidioc-overlay.sgml @@ -67,7 +67,7 @@ Video overlay is not supported, or the parameters have not been set up. See for the necessary steps. +linkend="overlay" /> for the necessary steps. diff --git a/v4l2-spec/vidioc-qbuf.sgml b/v4l2-spec/vidioc-qbuf.sgml index f02debb8c..187081778 100644 --- a/v4l2-spec/vidioc-qbuf.sgml +++ b/v4l2-spec/vidioc-qbuf.sgml @@ -71,7 +71,7 @@ intended for output (type is initialize the bytesused, field and timestamp fields. See for details. When + linkend="buffer" /> for details. When VIDIOC_QBUF is called with a pointer to this structure the driver sets the V4L2_BUF_FLAG_MAPPED and @@ -114,7 +114,7 @@ function, VIDIOC_DQBUF returns immediately with an &EAGAIN; when no buffer is available. The v4l2_buffer structure is -specified in . +specified in . diff --git a/v4l2-spec/vidioc-querybuf.sgml b/v4l2-spec/vidioc-querybuf.sgml index e5fb5ac7a..d834993e6 100644 --- a/v4l2-spec/vidioc-querybuf.sgml +++ b/v4l2-spec/vidioc-querybuf.sgml @@ -76,7 +76,7 @@ or may not set the remaining fields and flags, they are meaningless in this context. The v4l2_buffer structure is - specified in . + specified in . diff --git a/v4l2-spec/vidioc-querycap.sgml b/v4l2-spec/vidioc-querycap.sgml index fa12ae738..6ab7e25b3 100644 --- a/v4l2-spec/vidioc-querycap.sgml +++ b/v4l2-spec/vidioc-querycap.sgml @@ -122,7 +122,7 @@ printf ("Version: %u.%u.%u\n", __u32 capabilities Device capabilities, see . + linkend="device-capabilities" />. __u32 @@ -211,7 +211,7 @@ hardware frequency seeking. The device has some sort of tuner to receive RF-modulated video signals. For more information about tuner programming see -. +. V4L2_CAP_AUDIO @@ -220,7 +220,7 @@ tuner programming see may not support audio recording or playback, in PCM or compressed formats. PCM audio support must be implemented as ALSA or OSS interface. For more information on audio inputs and outputs see . + linkend="audio" />. V4L2_CAP_RADIO @@ -233,7 +233,7 @@ interface. For more information on audio inputs and outputs see The device has some sort of modulator to emit RF-modulated video/audio signals. For more information about modulator programming see -. +. V4L2_CAP_READWRITE diff --git a/v4l2-spec/vidioc-queryctrl.sgml b/v4l2-spec/vidioc-queryctrl.sgml index abf56b22e..4876ff1a1 100644 --- a/v4l2-spec/vidioc-queryctrl.sgml +++ b/v4l2-spec/vidioc-queryctrl.sgml @@ -106,7 +106,7 @@ by calling VIDIOC_QUERYMENU with successive minimum (0) to maximum, inclusive. - See also the examples in . + See also the examples in .
struct <structname>v4l2_queryctrl</structname> @@ -117,7 +117,7 @@ by calling VIDIOC_QUERYMENU with successive __u32idIdentifies the control, set by the application. See - for predefined IDs. When the ID is ORed + for predefined IDs. When the ID is ORed with V4L2_CTRL_FLAG_NEXT_CTRL the driver clears the flag and returns the first control with a higher ID. Drivers which do not support this flag yet always return an &EINVAL;. @@ -126,7 +126,7 @@ flag yet always return an &EINVAL;.&v4l2-ctrl-type;typeType of control, see . + linkend="v4l2-ctrl-type" />. __u8 @@ -196,7 +196,7 @@ func-open; is called. __u32 flags Control flags, see . + linkend="control-flags" />. __u32 @@ -245,11 +245,11 @@ the array to zero.
enum v4l2_ctrl_type - - - - - + + + + + Type @@ -325,7 +325,7 @@ should be part of the control documentation. n/a This is not a control. When VIDIOC_QUERYCTRL is called with a control ID -equal to a control class code (see ), the +equal to a control class code (see ), the ioctl returns the name of the control class and this control type. Older drivers which do not support this feature return an &EINVAL;. diff --git a/v4l2-spec/vidioc-reqbufs.sgml b/v4l2-spec/vidioc-reqbufs.sgml index fe3f63019..bab380844 100644 --- a/v4l2-spec/vidioc-reqbufs.sgml +++ b/v4l2-spec/vidioc-reqbufs.sgml @@ -106,7 +106,7 @@ field is only used when memory is set to type Type of the stream or buffers, this is the same as the &v4l2-format; type field. See for valid values. + linkend="v4l2-buf-type" /> for valid values. &v4l2-memory; -- cgit v1.2.3 From 8d8fcf827360554744a5411322e1151bd7185181 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 31 Aug 2009 21:30:25 -0300 Subject: Update do have the new "man" targets From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- INSTALL | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/INSTALL b/INSTALL index 3a4ea7cec..0b2f4c0bc 100644 --- a/INSTALL +++ b/INSTALL @@ -31,6 +31,8 @@ default - Continues building the latest module selection install - Installs all modules at kernel's default dir for V4L/DVB. Requires root access. +man_install - Install V4L2 API man pages. + rminstall - cleans previous installations of V4L/DVB modules sound-install - installs the sound modules related to V4L/DVB @@ -53,6 +55,8 @@ dvb-spec - Creates DVB API specification spec - Creates both V4L and DVB API specification +man - Creates V4L2 API man pages + ======================= Module selection rules: (Those may require write access to kernel tree) -- cgit v1.2.3 From 8c850fc231cec2a497311b88805c405dcdac6077 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 31 Aug 2009 22:52:22 -0300 Subject: v4l2-spec: A few minor language improvements From: Mauro Carvalho Chehab Just do 3 minor editorial revisions on the text added at the previous patches. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-spec/compat.sgml | 2 +- v4l2-spec/v4l2.sgml | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/v4l2-spec/compat.sgml b/v4l2-spec/compat.sgml index 50b784f46..4d1902a54 100644 --- a/v4l2-spec/compat.sgml +++ b/v4l2-spec/compat.sgml @@ -2298,7 +2298,7 @@ was renamed to v4l2_chip_ident_old In order to be easier to compare a V4L2 API and a kernel -version, now V4L2 API is numbered using Linux Kernel version numeration. +version, now V4L2 API is numbered using the Linux Kernel version numeration. Finalized the RDS capture API. See for diff --git a/v4l2-spec/v4l2.sgml b/v4l2-spec/v4l2.sgml index 15480451a..d4c13e51f 100644 --- a/v4l2-spec/v4l2.sgml +++ b/v4l2-spec/v4l2.sgml @@ -150,8 +150,8 @@ applications. --> 2009-08-31 mcc Now, revisions will match the kernel version where -the V4L2 API will be adopted by a driver. Added Remote Controller -chapter. +the V4L2 API changes will be used by the Linux Kernel. +Also added Remote Controller chapter. @@ -172,7 +172,8 @@ chapter. 0.27 2009-08-15 mcc - Added libv4l documentation and v4l2grab example. + Added libv4l and Remote Controller documentation; +added v4l2grab and keytable application examples. -- cgit v1.2.3 From c72ee0800635eed6f921b1597ebeabde51e195a4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 31 Aug 2009 23:14:06 -0300 Subject: ir-keymaps: Fix some trobles on a bad patch From: Mauro Carvalho Chehab Due to some merge conflicts, I had to manually fix one patch. It seems that I missed to convert some fields. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 42 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index 5ce47d775..b2f9a9693 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -2764,7 +2764,7 @@ EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog_table); /* Kaiomy TVnPC U2 Mauro Carvalho Chehab */ -IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_kaiomy[] = { { 0x43, KEY_POWER2}, { 0x01, KEY_LIST}, { 0x0b, KEY_ZOOM}, @@ -2812,9 +2812,9 @@ struct ir_scancode_table ir_codes_kaiomy_table = { .scan = ir_codes_kaiomy, .size = ARRAY_SIZE(ir_codes_kaiomy), }; -EXPORT_SYMBOL_GPL(ir_codes_kaiomy); +EXPORT_SYMBOL_GPL(ir_codes_kaiomy_table); -IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_avermedia_a16d[] = { { 0x20, KEY_LIST}, { 0x00, KEY_POWER}, { 0x28, KEY_1}, @@ -2854,12 +2854,12 @@ struct ir_scancode_table ir_codes_avermedia_a16d_table = { .scan = ir_codes_avermedia_a16d, .size = ARRAY_SIZE(ir_codes_avermedia_a16d), }; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d); +EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d_table); /* Encore ENLTV-FM v5.3 Mauro Carvalho Chehab */ -IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_encore_enltv_fm53[] = { { 0x10, KEY_POWER2}, { 0x06, KEY_MUTE}, @@ -2901,10 +2901,10 @@ struct ir_scancode_table ir_codes_encore_enltv_fm53_table = { .scan = ir_codes_encore_enltv_fm53, .size = ARRAY_SIZE(ir_codes_encore_enltv_fm53), }; -EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53); +EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53_table); /* Zogis Real Audio 220 - 32 keys IR */ -IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_real_audio_220_32_keys[] = { { 0x1c, KEY_RADIO}, { 0x12, KEY_POWER2}, @@ -2945,12 +2945,12 @@ struct ir_scancode_table ir_codes_real_audio_220_32_keys_table = { .scan = ir_codes_real_audio_220_32_keys, .size = ARRAY_SIZE(ir_codes_real_audio_220_32_keys), }; -EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys); +EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys_table); /* ATI TV Wonder HD 600 USB Devin Heitmueller */ -IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_ati_tv_wonder_hd_600[] = { { 0x00, KEY_RECORD}, /* Row 1 */ { 0x01, KEY_PLAYPAUSE}, { 0x02, KEY_STOP}, @@ -2980,12 +2980,12 @@ struct ir_scancode_table ir_codes_ati_tv_wonder_hd_600_table = { .scan = ir_codes_ati_tv_wonder_hd_600, .size = ARRAY_SIZE(ir_codes_ati_tv_wonder_hd_600), }; -EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600); +EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600_table); /* DVBWorld remotes Igor M. Liplianin */ -IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_dm1105_nec[] = { { 0x0a, KEY_POWER2}, /* power */ { 0x0c, KEY_MUTE}, /* mute */ { 0x11, KEY_1}, @@ -3022,13 +3022,12 @@ struct ir_scancode_table ir_codes_dm1105_nec_table = { .scan = ir_codes_dm1105_nec, .size = ARRAY_SIZE(ir_codes_dm1105_nec), }; -EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec); - +EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec_table); /* Terratec Cinergy Hybrid T USB XS Devin Heitmueller */ -IR_KEYTAB_TYPE ir_codes_terratec_cinergy_xs[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_terratec_cinergy_xs[] = { { 0x41, KEY_HOME}, { 0x01, KEY_POWER}, { 0x42, KEY_MENU}, @@ -3081,12 +3080,12 @@ struct ir_scancode_table ir_codes_terratec_cinergy_xs_table = { .scan = ir_codes_terratec_cinergy_xs, .size = ARRAY_SIZE(ir_codes_terratec_cinergy_xs), }; -EXPORT_SYMBOL_GPL(ir_codes_terratec_cinergy_xs); +EXPORT_SYMBOL_GPL(ir_codes_terratec_cinergy_xs_table); /* EVGA inDtube Devin Heitmueller */ -IR_KEYTAB_TYPE ir_codes_evga_indtube[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_evga_indtube[] = { { 0x12, KEY_POWER}, { 0x02, KEY_MODE}, /* TV */ { 0x14, KEY_MUTE}, @@ -3108,9 +3107,9 @@ struct ir_scancode_table ir_codes_evga_indtube_table = { .scan = ir_codes_evga_indtube, .size = ARRAY_SIZE(ir_codes_evga_indtube), }; -EXPORT_SYMBOL_GPL(ir_codes_evga_indtube); +EXPORT_SYMBOL_GPL(ir_codes_evga_indtube_table); -IR_KEYTAB_TYPE ir_codes_videomate_s350[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_videomate_s350[] = { { 0x00, KEY_TV}, { 0x01, KEY_DVD}, { 0x04, KEY_RECORD}, @@ -3160,13 +3159,12 @@ struct ir_scancode_table ir_codes_videomate_s350_table = { .scan = ir_codes_videomate_s350, .size = ARRAY_SIZE(ir_codes_videomate_s350), }; -EXPORT_SYMBOL_GPL(ir_codes_videomate_s350); - +EXPORT_SYMBOL_GPL(ir_codes_videomate_s350_table); /* GADMEI UTV330+ RM008Z remote Shine Liu */ -IR_KEYTAB_TYPE ir_codes_gadmei_rm008z[IR_KEYTAB_SIZE] = { +static struct ir_scancode ir_codes_gadmei_rm008z[] = { { 0x14, KEY_POWER2}, /* POWER OFF */ { 0x0c, KEY_MUTE}, /* MUTE */ @@ -3208,4 +3206,4 @@ struct ir_scancode_table ir_codes_gadmei_rm008z_table = { .scan = ir_codes_gadmei_rm008z, .size = ARRAY_SIZE(ir_codes_gadmei_rm008z), }; -EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z); +EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z_table); -- cgit v1.2.3 From 197089fa6affd498c9fcd892cd0d0e36c962fc36 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 31 Aug 2009 22:23:03 -0400 Subject: em28xx: better describe vinctrl registers From: Devin Heitmueller Properly document the video input control register, in preparation for the addition of VBI support. Note this patch makes no functional changes. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-cards.c | 3 ++- linux/drivers/media/video/em28xx/em28xx-reg.h | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index d50b478a4..ed3279d8c 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2700,7 +2700,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, * Default format, used for tvp5150 or saa711x output formats */ dev->vinmode = 0x10; - dev->vinctl = 0x11; + dev->vinctl = EM28XX_VINCTRL_INTERLACED | + EM28XX_VINCTRL_CCIR656_ENABLE; /* Do board specific init and eeprom reading */ em28xx_card_setup(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index 6bf84bd78..3bf69f9ec 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -86,7 +86,19 @@ #define EM28XX_XCLK_FREQUENCY_24MHZ 0x0b #define EM28XX_R10_VINMODE 0x10 + #define EM28XX_R11_VINCTRL 0x11 + +/* em28xx Video Input Control Register 0x11 */ +#define EM28XX_VINCTRL_VBI_SLICED 0x80 +#define EM28XX_VINCTRL_VBI_RAW 0x40 +#define EM28XX_VINCTRL_VOUT_MODE_IN 0x20 /* HREF,VREF,VACT in output */ +#define EM28XX_VINCTRL_CCIR656_ENABLE 0x10 +#define EM28XX_VINCTRL_VBI_16BIT_RAW 0x08 /* otherwise 8-bit raw */ +#define EM28XX_VINCTRL_FID_ON_HREF 0x04 +#define EM28XX_VINCTRL_DUAL_EDGE_STROBE 0x02 +#define EM28XX_VINCTRL_INTERLACED 0x01 + #define EM28XX_R12_VINENABLE 0x12 /* */ #define EM28XX_R14_GAMMA 0x14 -- cgit v1.2.3 From 466c486c15f125abfbd9b2a2c5ebea08e73f9b71 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 1 Sep 2009 00:19:46 -0400 Subject: em28xx: make video isoc stream work when VBI is enabled From: Devin Heitmueller Add code enabling the VBI registers for variants of the em28xx chip that support VBI, and make sure the isoc streaming code continues to work for the video component of the stream (note the video and vbi data arrive intermixed on the same isoc pipe). Note that this version just drops the actual VBI data onto the floor as opposed to processing it. The "#ifdef 0" tags are for the videobuf code that appears in the next patch in this series. We created a separate version of the isoc_copy version for parsing the version of the stream that includes VBI data. In theory, they might be able to be merged at some point in the future, but the initial goal is to ensure that we do not cause any regressions with devices that do not have VBI support. This work was sponsored by EyeMagnet Limited. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-core.c | 44 +++++- linux/drivers/media/video/em28xx/em28xx-reg.h | 4 + linux/drivers/media/video/em28xx/em28xx-video.c | 169 +++++++++++++++++++++++- linux/drivers/media/video/em28xx/em28xx.h | 7 + 4 files changed, 215 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 46cb13182..bbddeff72 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -54,6 +54,10 @@ static int alt = EM28XX_PINOUT; module_param(alt, int, 0644); MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); +static unsigned int disable_vbi; +module_param(disable_vbi, int, 0644); +MODULE_PARM_DESC(disable_vbi, "disable vbi support"); + /* FIXME */ #define em28xx_isocdbg(fmt, arg...) do {\ if (core_debug) \ @@ -648,9 +652,24 @@ int em28xx_capture_start(struct em28xx *dev, int start) return rc; } +int em28xx_vbi_supported(struct em28xx *dev) +{ + /* Modprobe option to manually disable */ + if (disable_vbi == 1) + return 0; + + if (dev->chip_id == CHIP_ID_EM2860 || + dev->chip_id == CHIP_ID_EM2883) + return 1; + + /* Version of em28xx that does not support VBI */ + return 0; +} + int em28xx_set_outfmt(struct em28xx *dev) { int ret; + u8 vinctrl; ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, dev->format->reg | 0x20, 0xff); @@ -661,7 +680,16 @@ int em28xx_set_outfmt(struct em28xx *dev) if (ret < 0) return ret; - return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, dev->vinctl); + vinctrl = dev->vinctl; + if (em28xx_vbi_supported(dev) == 1) { + vinctrl |= EM28XX_VINCTRL_VBI_RAW; + em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00); + em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09); + em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, 0xb4); + em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, 0x0c); + } + + return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl); } static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, @@ -732,7 +760,14 @@ int em28xx_resolution_set(struct em28xx *dev) em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); - em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); + + /* If we don't set the start position to 4 in VBI mode, we end up + with line 21 being YUYV encoded instead of being in 8-bit + greyscale */ + if (em28xx_vbi_supported(dev) == 1) + em28xx_capture_area_set(dev, 0, 4, width >> 2, height >> 2); + else + em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); return em28xx_scaler_set(dev, dev->hscale, dev->vscale); } @@ -853,8 +888,7 @@ static void em28xx_irq_callback(struct urb *urb, struct pt_regs *regs) static void em28xx_irq_callback(struct urb *urb) #endif { - struct em28xx_dmaqueue *dma_q = urb->context; - struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); + struct em28xx *dev = urb->context; int rc, i; switch (urb->status) { @@ -1003,7 +1037,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, usb_fill_int_urb(urb, dev->udev, pipe, dev->isoc_ctl.transfer_buffer[i], sb_size, - em28xx_irq_callback, dma_q, 1); + em28xx_irq_callback, dev, 1); urb->number_of_packets = max_packets; urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; diff --git a/linux/drivers/media/video/em28xx/em28xx-reg.h b/linux/drivers/media/video/em28xx/em28xx-reg.h index 3bf69f9ec..ed12e7ffc 100644 --- a/linux/drivers/media/video/em28xx/em28xx-reg.h +++ b/linux/drivers/media/video/em28xx/em28xx-reg.h @@ -147,6 +147,10 @@ #define EM28XX_R31_HSCALEHIGH 0x31 #define EM28XX_R32_VSCALELOW 0x32 #define EM28XX_R33_VSCALEHIGH 0x33 +#define EM28XX_R34_VBI_START_H 0x34 +#define EM28XX_R35_VBI_START_V 0x35 +#define EM28XX_R36_VBI_WIDTH 0x36 +#define EM28XX_R37_VBI_HEIGHT 0x37 #define EM28XX_R40_AC97LSB 0x40 #define EM28XX_R41_AC97MSB 0x41 diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index c7d723a03..d1308d256 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -351,7 +351,7 @@ static inline void get_next_buf(struct em28xx_dmaqueue *dma_q, static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) { struct em28xx_buffer *buf; - struct em28xx_dmaqueue *dma_q = urb->context; + struct em28xx_dmaqueue *dma_q = &dev->vidq; unsigned char *outp = NULL; int i, len = 0, rc = 1; unsigned char *p; @@ -432,6 +432,160 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) return rc; } +/* Version of isoc handler that takes into account a mixture of video and + VBI data */ +static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) +{ + struct em28xx_buffer *buf, *vbi_buf; + struct em28xx_dmaqueue *dma_q = &dev->vidq; +#if 0 + struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; +#endif + unsigned char *outp = NULL; + unsigned char *vbioutp = NULL; + int i, len = 0, rc = 1; + unsigned char *p; + int vbi_size; + + if (!dev) + return 0; + + if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) + return 0; + + if (urb->status < 0) { + print_err_status(dev, -1, urb->status); + if (urb->status == -ENOENT) + return 0; + } + + buf = dev->isoc_ctl.buf; + if (buf != NULL) + outp = videobuf_to_vmalloc(&buf->vb); +#if 0 + vbi_buf = dev->isoc_ctl.vbi_buf; + if (vbi_buf != NULL) + vbioutp = videobuf_to_vmalloc(&vbi_buf->vb); +#endif + for (i = 0; i < urb->number_of_packets; i++) { + int status = urb->iso_frame_desc[i].status; + + if (status < 0) { + print_err_status(dev, i, status); + if (urb->iso_frame_desc[i].status != -EPROTO) + continue; + } + + len = urb->iso_frame_desc[i].actual_length - 4; + + if (urb->iso_frame_desc[i].actual_length <= 0) { + /* em28xx_isocdbg("packet %d is empty",i); - spammy */ + continue; + } + if (urb->iso_frame_desc[i].actual_length > + dev->max_pkt_size) { + em28xx_isocdbg("packet bigger than packet size"); + continue; + } + + p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + + /* capture type 0 = vbi start + capture type 1 = video start + capture type 2 = video in progress */ + if (p[0] == 0x33 && p[1] == 0x95) { + dev->capture_type = 0; + dev->vbi_read = 0; + em28xx_isocdbg("VBI START HEADER!!!\n"); + dev->cur_field = p[2]; + } + + /* FIXME: get rid of hard-coded value */ + vbi_size = 720 * 0x0c; + + if (dev->capture_type == 0) { + if (dev->vbi_read >= vbi_size) { + /* We've already read all the VBI data, so + treat the rest as video */ + printk("djh c should never happen\n"); + } else if ((dev->vbi_read + len) < vbi_size) { + /* This entire frame is VBI data */ +#if 0 + if (dev->vbi_read == 0 && + (!(dev->cur_field & 1))) { + /* Brand new frame */ + if (vbi_buf != NULL) + vbi_buffer_filled(dev, + vbi_dma_q, + vbi_buf); + vbi_get_next_buf(vbi_dma_q, &vbi_buf); + if (vbi_buf == NULL) + vbioutp = NULL; + else { + vbioutp = videobuf_to_vmalloc(&vbi_buf->vb); + } + } + + if (dev->vbi_read == 0) { + vbi_dma_q->pos = 0; + if (vbi_buf != NULL) { + if (dev->cur_field & 1) + vbi_buf->top_field = 0; + else + vbi_buf->top_field = 1; + } + } +#endif + dev->vbi_read += len; +#if 0 + em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p, + vbioutp, len); +#endif + } else { + /* Some of this frame is VBI data and some is + video data */ + int vbi_data_len = vbi_size - dev->vbi_read; + dev->vbi_read += vbi_data_len; +#if 0 + em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p, + vbioutp, vbi_data_len); +#endif + dev->capture_type = 1; + p += vbi_data_len; + len -= vbi_data_len; + } + } + + if (dev->capture_type == 1) { + dev->capture_type = 2; + em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], + len, (p[2] & 1) ? "odd" : "even"); + + if (dev->progressive || !(dev->cur_field & 1)) { + if (buf != NULL) + buffer_filled(dev, dma_q, buf); + get_next_buf(dma_q, &buf); + if (buf == NULL) + outp = NULL; + else + outp = videobuf_to_vmalloc(&buf->vb); + } + if (buf != NULL) { + if (dev->cur_field & 1) + buf->top_field = 0; + else + buf->top_field = 1; + } + + dma_q->pos = 0; + } + if (buf != NULL && dev->capture_type == 2) + em28xx_copy_video(dev, dma_q, buf, p, outp, len); + } + return rc; +} + + /* ------------------------------------------------------------------ Videobuf operations ------------------------------------------------------------------*/ @@ -516,9 +670,16 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, urb_init = 1; if (urb_init) { - rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, - EM28XX_NUM_BUFS, dev->max_pkt_size, - em28xx_isoc_copy); + if (em28xx_vbi_supported(dev) == 1) + rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, + EM28XX_NUM_BUFS, + dev->max_pkt_size, + em28xx_isoc_copy_vbi); + else + rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, + EM28XX_NUM_BUFS, + dev->max_pkt_size, + em28xx_isoc_copy); if (rc < 0) goto fail; } diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 68f274dcc..ce8dd8c19 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -553,6 +553,12 @@ struct em28xx { enum em28xx_dev_state state; enum em28xx_io_method io; + /* vbi related state tracking */ + int capture_type; + int vbi_read; + unsigned char cur_field; + + struct work_struct request_module_wk; /* locks */ @@ -644,6 +650,7 @@ int em28xx_audio_setup(struct em28xx *dev); int em28xx_colorlevels_set_default(struct em28xx *dev); int em28xx_capture_start(struct em28xx *dev, int start); +int em28xx_vbi_supported(struct em28xx *dev); int em28xx_set_outfmt(struct em28xx *dev); int em28xx_resolution_set(struct em28xx *dev); int em28xx_set_alternate(struct em28xx *dev); -- cgit v1.2.3 From a5ed985ed0158950f8d037331fa29710db72831c Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 1 Sep 2009 00:54:54 -0400 Subject: em28xx: add raw VBI support for NTSC From: Devin Heitmueller Add support for raw VBI capture for the em28xx bridge, currently only for NTSC. Support for PAL capture to follow shortly (including the removal of numerous hard-coded NTSC-specific sizes for capture buffers, etc). Note that the code currently changes the default current norm from PAL to NTSC (so that zvbi-ntsc-cc works properly). The default norm really should be moved into a board-level parameter. This work was sponsored by EyeMagnet Limited. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/Makefile | 2 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 + linux/drivers/media/video/em28xx/em28xx-core.c | 5 +- linux/drivers/media/video/em28xx/em28xx-vbi.c | 150 +++++++++++++ linux/drivers/media/video/em28xx/em28xx-video.c | 282 +++++++++++++++++++----- linux/drivers/media/video/em28xx/em28xx.h | 8 +- 6 files changed, 388 insertions(+), 61 deletions(-) create mode 100644 linux/drivers/media/video/em28xx/em28xx-vbi.c diff --git a/linux/drivers/media/video/em28xx/Makefile b/linux/drivers/media/video/em28xx/Makefile index 8137a8c94..d0f093d1d 100644 --- a/linux/drivers/media/video/em28xx/Makefile +++ b/linux/drivers/media/video/em28xx/Makefile @@ -1,5 +1,5 @@ em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \ - em28xx-input.o + em28xx-input.o em28xx-vbi.o em28xx-alsa-objs := em28xx-audio.o diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index ed3279d8c..6afb9aa3d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2720,6 +2720,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); INIT_LIST_HEAD(&dev->vidq.queued); + INIT_LIST_HEAD(&dev->vbiq.active); + INIT_LIST_HEAD(&dev->vbiq.queued); #if 0 video_set_drvdata(dev->vbi_dev, dev); diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index bbddeff72..6ae539674 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -973,6 +973,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) { struct em28xx_dmaqueue *dma_q = &dev->vidq; + struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; int i; int sb_size, pipe; struct urb *urb; @@ -1002,7 +1003,8 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, } dev->isoc_ctl.max_pkt_size = max_pkt_size; - dev->isoc_ctl.buf = NULL; + dev->isoc_ctl.vid_buf = NULL; + dev->isoc_ctl.vbi_buf = NULL; sb_size = max_packets * dev->isoc_ctl.max_pkt_size; @@ -1052,6 +1054,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, } init_waitqueue_head(&dma_q->wq); + init_waitqueue_head(&vbi_dma_q->wq); em28xx_capture_start(dev, 1); diff --git a/linux/drivers/media/video/em28xx/em28xx-vbi.c b/linux/drivers/media/video/em28xx/em28xx-vbi.c new file mode 100644 index 000000000..b5802d4cb --- /dev/null +++ b/linux/drivers/media/video/em28xx/em28xx-vbi.c @@ -0,0 +1,150 @@ +/* + em28xx-vbi.c - VBI driver for em28xx + + Copyright (C) 2009 Devin Heitmueller + + This work was sponsored by EyeMagnet Limited. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include "em28xx.h" + +static unsigned int vbibufs = 5; +module_param(vbibufs,int,0644); +MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32"); + +static unsigned int vbi_debug; +module_param(vbi_debug,int,0644); +MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); + +#define dprintk(level,fmt, arg...) if (vbi_debug >= level) \ + printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg) + +/* ------------------------------------------------------------------ */ + +static void +free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf) +{ + struct em28xx_fh *fh = vq->priv_data; + struct em28xx *dev = fh->dev; + unsigned long flags = 0; + if (in_interrupt()) + BUG(); + + /* We used to wait for the buffer to finish here, but this didn't work + because, as we were keeping the state as VIDEOBUF_QUEUED, + videobuf_queue_cancel marked it as finished for us. + (Also, it could wedge forever if the hardware was misconfigured.) + + This should be safe; by the time we get here, the buffer isn't + queued anymore. If we ever start marking the buffers as + VIDEOBUF_ACTIVE, it won't be, though. + */ + spin_lock_irqsave(&dev->slock, flags); + if (dev->isoc_ctl.vbi_buf == buf) + dev->isoc_ctl.vbi_buf = NULL; + spin_unlock_irqrestore(&dev->slock, flags); + + videobuf_vmalloc_free(&buf->vb); + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + +static int +vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) +{ + *size = 720 * 12 * 2; + if (0 == *count) + *count = vbibufs; + if (*count < 2) + *count = 2; + if (*count > 32) + *count = 32; + return 0; +} + +static int +vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct em28xx_fh *fh = q->priv_data; + struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); + int rc = 0; + unsigned int size; + + size = 720 * 12 * 2; + + buf->vb.size = size; + + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + buf->vb.width = 720; + buf->vb.height = 12; + buf->vb.field = field; + + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { + rc = videobuf_iolock(q, &buf->vb, NULL); + if (rc < 0) + goto fail; + } + + buf->vb.state = VIDEOBUF_PREPARED; + return 0; + +fail: + free_buffer(q, buf); + return rc; +} + +static void +vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct em28xx_buffer *buf = container_of(vb, + struct em28xx_buffer, + vb); + struct em28xx_fh *fh = vq->priv_data; + struct em28xx *dev = fh->dev; + struct em28xx_dmaqueue *vbiq = &dev->vbiq; + + buf->vb.state = VIDEOBUF_QUEUED; + list_add_tail(&buf->vb.queue, &vbiq->active); +} + +static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) +{ + struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); + free_buffer(q, buf); +} + +struct videobuf_queue_ops em28xx_vbi_qops = { + .buf_setup = vbi_setup, + .buf_prepare = vbi_prepare, + .buf_queue = vbi_queue, + .buf_release = vbi_release, +}; + +/* ------------------------------------------------------------------ */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index d1308d256..449fec8f8 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -181,7 +181,24 @@ static inline void buffer_filled(struct em28xx *dev, buf->vb.field_count++; do_gettimeofday(&buf->vb.ts); - dev->isoc_ctl.buf = NULL; + dev->isoc_ctl.vid_buf = NULL; + + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); +} + +static inline void vbi_buffer_filled(struct em28xx *dev, + struct em28xx_dmaqueue *dma_q, + struct em28xx_buffer *buf) +{ + /* Advice that buffer was filled */ + em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); + + buf->vb.state = VIDEOBUF_DONE; + buf->vb.field_count++; + do_gettimeofday(&buf->vb.ts); + + dev->isoc_ctl.vbi_buf = NULL; list_del(&buf->vb.queue); wake_up(&buf->vb.done); @@ -274,6 +291,67 @@ static void em28xx_copy_video(struct em28xx *dev, dma_q->pos += len; } +static void em28xx_copy_vbi(struct em28xx *dev, + struct em28xx_dmaqueue *dma_q, + struct em28xx_buffer *buf, + unsigned char *p, + unsigned char *outp, unsigned long len) +{ + void *startwrite, *startread; + int offset; + int bytesperline = 720; + + if (dev == NULL) { + printk("dev is null\n"); + return; + } + + if (dma_q == NULL) { + printk("dma_q is null\n"); + return; + } + if (buf == NULL) { +#if 0 + /* Disable by default - too chatty */ + printk("buf is null\n"); +#endif + return; + } + if (p == NULL) { + printk("p is null\n"); + return; + } + if (outp == NULL) { + printk("outp is null\n"); + return; + } + + if (dma_q->pos + len > buf->vb.size) + len = buf->vb.size - dma_q->pos; + + if ((p[0] == 0x33 && p[1] == 0x95) || + (p[0] == 0x88 && p[1] == 0x88)) { + /* Header field, advance past it */ + p += 4; + } else { + len += 4; + } + + startread = p; + + startwrite = outp + dma_q->pos; + offset = dma_q->pos; + + /* Make sure the bottom field populates the second half of the frame */ + if (buf->top_field == 0) { + startwrite += bytesperline * 0x0c; + offset += bytesperline * 0x0c; + } + + memcpy(startwrite, startread, len); + dma_q->pos += len; +} + static inline void print_err_status(struct em28xx *dev, int packet, int status) { @@ -326,7 +404,7 @@ static inline void get_next_buf(struct em28xx_dmaqueue *dma_q, if (list_empty(&dma_q->active)) { em28xx_isocdbg("No active queue to serve\n"); - dev->isoc_ctl.buf = NULL; + dev->isoc_ctl.vid_buf = NULL; *buf = NULL; return; } @@ -340,7 +418,38 @@ static inline void get_next_buf(struct em28xx_dmaqueue *dma_q, memset(outp, 0, (*buf)->vb.size); #endif - dev->isoc_ctl.buf = *buf; + dev->isoc_ctl.vid_buf = *buf; + + return; +} + +/* + * video-buf generic routine to get the next available VBI buffer + */ +static inline void vbi_get_next_buf(struct em28xx_dmaqueue *dma_q, + struct em28xx_buffer **buf) +{ + struct em28xx *dev = container_of(dma_q, struct em28xx, vbiq); +#if 1 + char *outp; +#endif + + if (list_empty(&dma_q->active)) { + em28xx_isocdbg("No active queue to serve\n"); + dev->isoc_ctl.vbi_buf = NULL; + *buf = NULL; + return; + } + + /* Get the next buffer */ + *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); +#if 1 + /* Cleans up buffer - Usefull for testing for frame/URB loss */ + outp = videobuf_to_vmalloc(&(*buf)->vb); + memset(outp, 0x00, (*buf)->vb.size); +#endif + + dev->isoc_ctl.vbi_buf = *buf; return; } @@ -368,7 +477,7 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) return 0; } - buf = dev->isoc_ctl.buf; + buf = dev->isoc_ctl.vid_buf; if (buf != NULL) outp = videobuf_to_vmalloc(&buf->vb); @@ -438,9 +547,7 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) { struct em28xx_buffer *buf, *vbi_buf; struct em28xx_dmaqueue *dma_q = &dev->vidq; -#if 0 struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; -#endif unsigned char *outp = NULL; unsigned char *vbioutp = NULL; int i, len = 0, rc = 1; @@ -459,14 +566,14 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) return 0; } - buf = dev->isoc_ctl.buf; + buf = dev->isoc_ctl.vid_buf; if (buf != NULL) outp = videobuf_to_vmalloc(&buf->vb); -#if 0 + vbi_buf = dev->isoc_ctl.vbi_buf; if (vbi_buf != NULL) vbioutp = videobuf_to_vmalloc(&vbi_buf->vb); -#endif + for (i = 0; i < urb->number_of_packets; i++) { int status = urb->iso_frame_desc[i].status; @@ -510,7 +617,6 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) printk("djh c should never happen\n"); } else if ((dev->vbi_read + len) < vbi_size) { /* This entire frame is VBI data */ -#if 0 if (dev->vbi_read == 0 && (!(dev->cur_field & 1))) { /* Brand new frame */ @@ -535,21 +641,17 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) vbi_buf->top_field = 1; } } -#endif + dev->vbi_read += len; -#if 0 em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p, vbioutp, len); -#endif } else { /* Some of this frame is VBI data and some is video data */ int vbi_data_len = vbi_size - dev->vbi_read; dev->vbi_read += vbi_data_len; -#if 0 em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p, vbioutp, vbi_data_len); -#endif dev->capture_type = 1; p += vbi_data_len; len -= vbi_data_len; @@ -634,8 +736,8 @@ static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf) VIDEOBUF_ACTIVE, it won't be, though. */ spin_lock_irqsave(&dev->slock, flags); - if (dev->isoc_ctl.buf == buf) - dev->isoc_ctl.buf = NULL; + if (dev->isoc_ctl.vid_buf == buf) + dev->isoc_ctl.vid_buf = NULL; spin_unlock_irqrestore(&dev->slock, flags); videobuf_vmalloc_free(&buf->vb); @@ -1612,8 +1714,12 @@ static int vidioc_streamon(struct file *file, void *priv, mutex_lock(&dev->lock); rc = res_get(fh); - if (likely(rc >= 0)) - rc = videobuf_streamon(&fh->vb_vidq); + if (likely(rc >= 0)) { + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + rc = videobuf_streamon(&fh->vb_vidq); + else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + rc = videobuf_streamon(&fh->vb_vbiq); + } mutex_unlock(&dev->lock); @@ -1631,14 +1737,19 @@ static int vidioc_streamoff(struct file *file, void *priv, if (rc < 0) return rc; - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) return -EINVAL; if (type != fh->type) return -EINVAL; mutex_lock(&dev->lock); - videobuf_streamoff(&fh->vb_vidq); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + videobuf_streamoff(&fh->vb_vidq); + else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + videobuf_streamoff(&fh->vb_vbiq); + res_free(fh); mutex_unlock(&dev->lock); @@ -1659,9 +1770,7 @@ static int vidioc_querycap(struct file *file, void *priv, cap->version = EM28XX_VERSION_CODE; cap->capabilities = -#if 0 V4L2_CAP_VBI_CAPTURE | -#endif V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; @@ -1733,40 +1842,45 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, return 0; } -#if 0 /* RAW VBI ioctls */ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) + struct v4l2_format *format) { - format->fmt.vbi.sampling_rate = 6750000 * 4; - format->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */; + format->fmt.vbi.samples_per_line = 720; format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - format->fmt.vbi.offset = 64 * 4; - format->fmt.vbi.start[0] = norm->vbi_v_start_0; - format->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 + 1; - format->fmt.vbi.start[1] = norm->vbi_v_start_1; - format->fmt.vbi.count[1] = format->fmt.vbi.count[0]; - format->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */ + format->fmt.vbi.offset = 0; + format->fmt.vbi.flags = 0; + + /* Varies by video standard (NTSC, PAL, etc.) */ + /* FIXME: hard-coded for NTSC support */ + format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */ + format->fmt.vbi.count[0] = 12; + format->fmt.vbi.count[1] = 12; + format->fmt.vbi.start[0] = 10; + format->fmt.vbi.start[1] = 273; return 0; } -static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv, - struct v4l2_format *f) +static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv, + struct v4l2_format *format) { - format->type = V4L2_BUF_TYPE_VBI_CAPTURE; - format->fmt.vbi.sampling_rate = HZ; - format->fmt.vbi.samples_per_line = 2048; + format->fmt.vbi.samples_per_line = 720; format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - format->fmt.vbi.offset = 244; + format->fmt.vbi.offset = 0; format->fmt.vbi.flags = 0; - format->fmt.vbi.start[0] = 0; - format->fmt.vbi.start[1] = 0; + + /* Varies by video standard (NTSC, PAL, etc.) */ + /* FIXME: hard-coded for NTSC support */ + format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */ + format->fmt.vbi.count[0] = 12; + format->fmt.vbi.count[1] = 12; + format->fmt.vbi.start[0] = 10; + format->fmt.vbi.start[1] = 273; return 0; } -#endif static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *rb) @@ -1779,7 +1893,10 @@ static int vidioc_reqbufs(struct file *file, void *priv, if (rc < 0) return rc; - return videobuf_reqbufs(&fh->vb_vidq, rb); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + return videobuf_reqbufs(&fh->vb_vidq, rb); + else + return videobuf_reqbufs(&fh->vb_vbiq, rb); } static int vidioc_querybuf(struct file *file, void *priv, @@ -1793,7 +1910,18 @@ static int vidioc_querybuf(struct file *file, void *priv, if (rc < 0) return rc; - return videobuf_querybuf(&fh->vb_vidq, b); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + return videobuf_querybuf(&fh->vb_vidq, b); + else { + /* FIXME: I'm not sure yet whether this is a bug in zvbi or + the videobuf framework, but we probably shouldn't be + returning a buffer larger than that which was asked for. + At a minimum, it causes a crash in zvbi since it does + a memcpy based on the source buffer length */ + int result = videobuf_querybuf(&fh->vb_vbiq, b); + b->length = 17280; + return result; + } } static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1806,7 +1934,11 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) if (rc < 0) return rc; - return videobuf_qbuf(&fh->vb_vidq, b); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + return videobuf_qbuf(&fh->vb_vidq, b); + else { + return videobuf_qbuf(&fh->vb_vbiq, b); + } } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1819,7 +1951,12 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) if (rc < 0) return rc; - return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & + O_NONBLOCK); + else + return videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags & + O_NONBLOCK); } #ifdef CONFIG_VIDEO_V4L1_COMPAT @@ -1827,7 +1964,10 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) { struct em28xx_fh *fh = priv; - return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); + else + return videobuf_cgmbuf(&fh->vb_vbiq, mbuf, 8); } #endif @@ -2006,9 +2146,17 @@ static int em28xx_v4l2_open(struct file *filp) else field = V4L2_FIELD_INTERLACED; - videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, - NULL, &dev->slock, fh->type, field, - sizeof(struct em28xx_buffer), fh); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, + NULL, &dev->slock, fh->type, field, + sizeof(struct em28xx_buffer), fh); + + if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops, + NULL, &dev->slock, + V4L2_BUF_TYPE_VBI_CAPTURE, + V4L2_FIELD_SEQ_TB, + sizeof(struct em28xx_buffer), fh); mutex_unlock(&dev->lock); @@ -2070,7 +2218,7 @@ static int em28xx_v4l2_close(struct file *filp) if (res_check(fh)) res_free(fh); - if (dev->users == 1) { + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 1) { videobuf_stop(&fh->vb_vidq); videobuf_mmap_free(&fh->vb_vidq); @@ -2099,6 +2247,12 @@ static int em28xx_v4l2_close(struct file *filp) "0 (error=%i)\n", errCode); } } + + if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + videobuf_stop(&fh->vb_vbiq); + videobuf_mmap_free(&fh->vb_vbiq); + } + kfree(fh); dev->users--; wake_up_interruptible_nr(&dev->open, 1); @@ -2137,6 +2291,17 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count, return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, filp->f_flags & O_NONBLOCK); } + + + if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + mutex_lock(&dev->lock); + rc = res_get(fh); + mutex_unlock(&dev->lock); + + return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, + filp->f_flags & O_NONBLOCK); + } + return 0; } @@ -2161,10 +2326,12 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait) if (unlikely(rc < 0)) return POLLERR; - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + return videobuf_poll_stream(filp, &fh->vb_vidq, wait); + else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + return videobuf_poll_stream(filp, &fh->vb_vbiq, wait); + else return POLLERR; - - return videobuf_poll_stream(filp, &fh->vb_vidq, wait); } /* @@ -2213,11 +2380,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, -#if 0 .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, -#endif .vidioc_g_audio = vidioc_g_audio, .vidioc_s_audio = vidioc_s_audio, .vidioc_cropcap = vidioc_cropcap, @@ -2263,7 +2427,9 @@ static const struct video_device em28xx_video_template = { .minor = -1, .tvnorms = V4L2_STD_ALL, - .current_norm = V4L2_STD_PAL, + /* FIXME: we need this to be NTSC for VBI to work - it should + be moved to a per-board definition */ + .current_norm = V4L2_STD_NTSC, }; static const struct v4l2_file_operations radio_fops = { diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index ce8dd8c19..c81ec13d3 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -215,7 +215,8 @@ struct em28xx_usb_isoc_ctl { int tmp_buf_len; /* Stores already requested buffers */ - struct em28xx_buffer *buf; + struct em28xx_buffer *vid_buf; + struct em28xx_buffer *vbi_buf; /* Stores the number of received fields */ int nfields; @@ -476,6 +477,7 @@ struct em28xx_fh { int radio; struct videobuf_queue vb_vidq; + struct videobuf_queue vb_vbiq; enum v4l2_buf_type type; }; @@ -574,6 +576,7 @@ struct em28xx { /* Isoc control struct */ struct em28xx_dmaqueue vidq; + struct em28xx_dmaqueue vbiq; struct em28xx_usb_isoc_ctl isoc_ctl; spinlock_t slock; @@ -698,6 +701,9 @@ void em28xx_deregister_snapshot_button(struct em28xx *dev); int em28xx_ir_init(struct em28xx *dev); int em28xx_ir_fini(struct em28xx *dev); +/* Provided by em28xx-vbi.c */ +extern struct videobuf_queue_ops em28xx_vbi_qops; + /* printk macros */ #define em28xx_err(fmt, arg...) do {\ -- cgit v1.2.3 From ee6952a4ffb83a2360813db2f0e57afe4c3e306c Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Tue, 1 Sep 2009 09:58:26 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index ef3668c6c..1d53233db 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -92,6 +92,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "N10J ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb071, 0, "ASUSTeK Computer Inc. ", "N20A ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* Note no whitespace padding for these 2 models, this is not a typo */ { 0x04f2, 0xb071, 0, "ASUSTeK Computer INC.", "K50AB", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, -- cgit v1.2.3 From 6cfeba1c5b0ab06a02ce01ec90df65bbab1300e7 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Tue, 1 Sep 2009 10:03:27 +0200 Subject: libv4l: Document that passing in NULL as 3th arg to v4l2_ioctl is not allowed From: Hans de Goede libv4l: Document that passing in NULL as 3th arg to v4l2_ioctl is not allowed Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/include/libv4l2.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/v4l2-apps/libv4l/include/libv4l2.h b/v4l2-apps/libv4l/include/libv4l2.h index 5488b2b10..dfae21471 100644 --- a/v4l2-apps/libv4l/include/libv4l2.h +++ b/v4l2-apps/libv4l/include/libv4l2.h @@ -51,6 +51,13 @@ LIBV4L_PUBLIC extern FILE *v4l2_log_file; Note the device name passed to v4l2_open must be of a video4linux2 device, if it is anything else (including a video4linux1 device), v4l2_open will fail. + + Note that the argument to v4l2_ioctl after the request must be a valid + memory address of structure of the appropriate type for the request (for + v4l2 requests which expect a structure address). Passing in NULL or an + invalid memory address will not lead to failure with errno being EFAULT, + as it would with a real ioctl, but will cause libv4l2 to break, and you + get to keep both pieces. */ LIBV4L_PUBLIC int v4l2_open (const char *file, int oflag, ...); -- cgit v1.2.3 From 4d8330c0438337574c9009264646100a5d1c2060 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 2 Sep 2009 11:04:14 +0200 Subject: gspca - sunplus: The brightness is signed. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sunplus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c index 94a3f53c6..32ff7cd32 100644 --- a/linux/drivers/media/video/gspca/sunplus.c +++ b/linux/drivers/media/video/gspca/sunplus.c @@ -32,7 +32,7 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - u8 brightness; + s8 brightness; u8 contrast; u8 colors; u8 autogain; @@ -73,8 +73,8 @@ static struct ctrl sd_ctrls[] = { .id = V4L2_CID_BRIGHTNESS, .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", - .minimum = 0, - .maximum = 0xff, + .minimum = -128, + .maximum = 127, .step = 1, #define BRIGHTNESS_DEF 0 .default_value = BRIGHTNESS_DEF, -- cgit v1.2.3 From d7afea829cb355469ef35d43604dea1be4358210 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 1 Sep 2009 18:49:05 +0200 Subject: gspca - vc032x: Change the start exchanges of the sensor hv7131r. From: Jean-Francois Moine The new exchanges are taken from the information file of the ms-win driver (usbvm326.inf - webcam 15b8:6002). Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 245 +++++++++++++++++++++---------- 1 file changed, 168 insertions(+), 77 deletions(-) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 6f9aab89c..89e15d150 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -1940,109 +1940,200 @@ static const u8 po3130_initQVGA_data[][4] = { }; static const u8 hv7131r_gamma[17] = { -/* 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, - * 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff */ +#if 1 + 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, + 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff +#else 0x04, 0x1a, 0x36, 0x55, 0x6f, 0x87, 0x9d, 0xb0, 0xc1, 0xcf, 0xda, 0xe4, 0xec, 0xf3, 0xf8, 0xfd, 0xff +#endif }; static const u8 hv7131r_matrix[9] = { 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63 }; static const u8 hv7131r_initVGA_data[][4] = { - {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc}, + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x20, 0xdd}, {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x01, 0x45, 0xcc}, {0xb3, 0x03, 0x0b, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x03, 0xcc}, + {0xb3, 0x01, 0x45, 0xcc}, + {0xb3, 0x03, 0x0b, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x01, 0xcc}, {0xb3, 0x23, 0xe0, 0xcc}, - {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x02, 0xcc}, {0xb3, 0x16, 0x02, 0xcc}, - {0xb3, 0x17, 0x7f, 0xcc}, {0xb3, 0x34, 0x01, 0xcc}, - {0xb3, 0x35, 0x91, 0xcc}, {0xb3, 0x00, 0x27, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb3, 0x34, 0x01, 0xcc}, + {0xb3, 0x35, 0x91, 0xcc}, + {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x73, 0xcc}, - {0xb8, 0x00, 0x23, 0xcc}, {0x00, 0x01, 0x0c, 0xaa}, - {0x00, 0x14, 0x01, 0xaa}, {0x00, 0x15, 0xe6, 0xaa}, - {0x00, 0x16, 0x02, 0xaa}, - {0x00, 0x17, 0x86, 0xaa}, {0x00, 0x23, 0x00, 0xaa}, - {0x00, 0x25, 0x09, 0xaa}, {0x00, 0x26, 0x27, 0xaa}, - {0x00, 0x27, 0xc0, 0xaa}, - {0xb8, 0x2c, 0x60, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc}, - {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc}, + {0xb8, 0x00, 0x23, 0xcc}, + {0xb8, 0x2c, 0x50, 0xcc}, + {0xb8, 0x2d, 0xf8, 0xcc}, + {0xb8, 0x2e, 0xf8, 0xcc}, + {0xb8, 0x2f, 0xf8, 0xcc}, {0xb8, 0x30, 0x50, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, {0xb8, 0x32, 0xf8, 0xcc}, - {0xb8, 0x33, 0xf8, 0xcc}, {0xb8, 0x34, 0x65, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf8, 0xcc}, + {0xb8, 0x33, 0xf8, 0xcc}, + {0xb8, 0x34, 0x58, 0xcc}, {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc}, - {0xb8, 0x27, 0x20, 0xcc}, {0xb8, 0x01, 0x7d, 0xcc}, + {0xb8, 0x36, 0x00, 0xcc}, + {0xb8, 0x37, 0x00, 0xcc}, + {0xb8, 0x27, 0x20, 0xcc}, + {0xb8, 0x01, 0x7d, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0xfe, 0x00, 0xcc}, - {0xb8, 0xff, 0x28, 0xcc}, {0xb9, 0x00, 0x28, 0xcc}, - {0xb9, 0x01, 0x28, 0xcc}, - {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc}, - {0xb9, 0x06, 0x3c, 0xcc}, - {0xb9, 0x07, 0x3c, 0xcc}, {0xb9, 0x08, 0x3c, 0xcc}, - {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0x00, 0x01, 0x0c, 0xaa}, + {0x00, 0x14, 0x01, 0xaa}, + {0x00, 0x15, 0xe6, 0xaa}, + {0x00, 0x16, 0x02, 0xaa}, + {0x00, 0x17, 0x86, 0xaa}, + {0x00, 0x23, 0x00, 0xaa}, + {0x00, 0x25, 0x03, 0xaa}, + {0x00, 0x26, 0xa9, 0xaa}, + {0x00, 0x27, 0x80, 0xaa}, {0x00, 0x30, 0x18, 0xaa}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x02, 0xcc}, + {0xb6, 0x02, 0x80, 0xcc}, + {0xb6, 0x05, 0x01, 0xcc}, + {0xb6, 0x04, 0xe0, 0xcc}, + {0xb6, 0x12, 0x78, 0xcc}, + {0xb6, 0x18, 0x02, 0xcc}, + {0xb6, 0x17, 0x58, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x0a, 0xcc}, + {0xb9, 0x14, 0x0a, 0xcc}, + {0xb9, 0x15, 0x0a, 0xcc}, + {0xb9, 0x16, 0x0a, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x0f, 0xcc}, + {0xb9, 0x1a, 0x0f, 0xcc}, + {0xb9, 0x1b, 0x0f, 0xcc}, + {0xb9, 0x1c, 0x0f, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, {} }; static const u8 hv7131r_initQVGA_data[][4] = { - {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc}, - {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc}, + {0xb3, 0x01, 0x01, 0xcc}, + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0x00, 0x00, 0x20, 0xdd}, {0xb3, 0x00, 0x24, 0xcc}, - {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, - {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x01, 0xcc}, - {0xb3, 0x03, 0x0b, 0xcc}, {0xb3, 0x04, 0x05, 0xcc}, - {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x03, 0xcc}, + {0xb3, 0x01, 0x45, 0xcc}, + {0xb3, 0x03, 0x0b, 0xcc}, + {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc}, - {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x02, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, - {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0x91, 0xcc}, - {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc}, - {0xb8, 0x00, 0x21, 0xcc}, - {0x00, 0x01, 0x0c, 0xaa}, {0x00, 0x14, 0x01, 0xaa}, - {0x00, 0x15, 0xe6, 0xaa}, {0x00, 0x16, 0x02, 0xaa}, - {0x00, 0x17, 0x86, 0xaa}, - {0x00, 0x23, 0x00, 0xaa}, {0x00, 0x25, 0x01, 0xaa}, - {0x00, 0x26, 0xd4, 0xaa}, {0x00, 0x27, 0xc0, 0xaa}, - {0xbc, 0x02, 0x08, 0xcc}, - {0xbc, 0x03, 0x70, 0xcc}, {0xbc, 0x04, 0x08, 0xcc}, - {0xbc, 0x05, 0x00, 0xcc}, {0xbc, 0x06, 0x00, 0xcc}, - {0xbc, 0x08, 0x3c, 0xcc}, - {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x04, 0xcc}, - {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc}, - {0xb8, 0xfe, 0x02, 0xcc}, - {0xb8, 0xff, 0x07, 0xcc}, {0xb9, 0x00, 0x14, 0xcc}, - {0xb9, 0x01, 0x14, 0xcc}, {0xb9, 0x02, 0x14, 0xcc}, - {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x02, 0xcc}, {0xb9, 0x05, 0x05, 0xcc}, - {0xb9, 0x06, 0x0f, 0xcc}, {0xb9, 0x07, 0x0f, 0xcc}, - {0xb9, 0x08, 0x0f, 0xcc}, - {0xb8, 0x2c, 0x60, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc}, - {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc}, + {0xb3, 0x34, 0x01, 0xcc}, + {0xb3, 0x35, 0x91, 0xcc}, + {0xb3, 0x00, 0x27, 0xcc}, + {0xbc, 0x00, 0xd3, 0xcc}, + {0xb8, 0x00, 0x23, 0xcc}, + {0xb8, 0x2c, 0x50, 0xcc}, + {0xb8, 0x2d, 0xf8, 0xcc}, + {0xb8, 0x2e, 0xf8, 0xcc}, + {0xb8, 0x2f, 0xf8, 0xcc}, {0xb8, 0x30, 0x50, 0xcc}, - {0xb8, 0x31, 0xf8, 0xcc}, {0xb8, 0x32, 0xf8, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc}, - {0xb8, 0x34, 0x65, 0xcc}, {0xb8, 0x35, 0x00, 0xcc}, - {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc}, + {0xb8, 0x34, 0x58, 0xcc}, + {0xb8, 0x35, 0x00, 0xcc}, + {0xb8, 0x36, 0x00, 0xcc}, + {0xb8, 0x37, 0x00, 0xcc}, {0xb8, 0x27, 0x20, 0xcc}, - {0xb8, 0x01, 0x7d, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, - {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0xfe, 0x00, 0xcc}, - {0xb8, 0xff, 0x28, 0xcc}, - {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc}, - {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc}, - {0xb9, 0x04, 0x00, 0xcc}, - {0xb9, 0x05, 0x3c, 0xcc}, {0xb9, 0x06, 0x3c, 0xcc}, - {0xb9, 0x07, 0x3c, 0xcc}, {0xb9, 0x08, 0x3c, 0xcc}, + {0xb8, 0x01, 0x7d, 0xcc}, + {0xb8, 0x81, 0x09, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0x8e, 0x00, 0xcc}, - {0xb8, 0x8f, 0xff, 0xcc}, {0x00, 0x30, 0x18, 0xaa}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0x00, 0x01, 0x0c, 0xaa}, + {0x00, 0x14, 0x01, 0xaa}, + {0x00, 0x15, 0xe6, 0xaa}, + {0x00, 0x16, 0x02, 0xaa}, + {0x00, 0x17, 0x86, 0xaa}, + {0x00, 0x23, 0x00, 0xaa}, + {0x00, 0x25, 0x03, 0xaa}, + {0x00, 0x26, 0xa9, 0xaa}, + {0x00, 0x27, 0x80, 0xaa}, + {0x00, 0x30, 0x18, 0xaa}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x01, 0xcc}, + {0xb6, 0x02, 0x40, 0xcc}, + {0xb6, 0x05, 0x00, 0xcc}, + {0xb6, 0x04, 0xf0, 0xcc}, + {0xb6, 0x12, 0x78, 0xcc}, + {0xb6, 0x18, 0x00, 0xcc}, + {0xb6, 0x17, 0x96, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xbc, 0x02, 0x18, 0xcc}, + {0xbc, 0x03, 0x50, 0xcc}, + {0xbc, 0x04, 0x18, 0xcc}, + {0xbc, 0x05, 0x00, 0xcc}, + {0xbc, 0x06, 0x00, 0xcc}, + {0xbc, 0x08, 0x30, 0xcc}, + {0xbc, 0x09, 0x40, 0xcc}, + {0xbc, 0x0a, 0x10, 0xcc}, + {0xbc, 0x0b, 0x00, 0xcc}, + {0xbc, 0x0c, 0x00, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x0a, 0xcc}, + {0xb9, 0x14, 0x0a, 0xcc}, + {0xb9, 0x15, 0x0a, 0xcc}, + {0xb9, 0x16, 0x0a, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x0f, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xb9, 0x1a, 0x0f, 0xcc}, + {0xb9, 0x1b, 0x0f, 0xcc}, + {0xb9, 0x1c, 0x0f, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, {} }; -- cgit v1.2.3 From 62a6104ddcd7cf381c4f6802b5c029b096d95355 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 1 Sep 2009 19:02:22 +0200 Subject: gspca - vc032x: Do the LED work with the sensor hv7131r. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 89e15d150..9464454f1 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -3410,21 +3410,22 @@ static int sd_start(struct gspca_dev *gspca_dev) put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); /* set the led on 0x0892 0x0896 */ - if (sd->sensor == SENSOR_PO1200) { - setsharpness(gspca_dev); - sethvflip(gspca_dev); + switch (sd->sensor) { + case SENSOR_PO1200: + case SENSOR_HV7131R: reg_w(gspca_dev->dev, 0x89, 0x0400, 0x1415); - } else if (sd->sensor == SENSOR_MI1310_SOC) { + break; + case SENSOR_MI1310_SOC: reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000); - msleep(100); - sethvflip(gspca_dev); - setlightfreq(gspca_dev); - } else { + break; + default: reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); - msleep(100); - sethvflip(gspca_dev); - setlightfreq(gspca_dev); + break; } + msleep(100); + setsharpness(gspca_dev); + sethvflip(gspca_dev); + setlightfreq(gspca_dev); } return 0; } -- cgit v1.2.3 From fe71d82c6502272eee2df15c848cd067cfd7b2f0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 1 Sep 2009 19:52:04 +0200 Subject: gspca - sonixj / sn9c102: Two drivers for 0c45:60fc and 0c45:613e. From: Jean-Francois Moine Let 0c45:60fc in sn9c102 and 0c45:613e in gspca-sonixj (sensor not supported). Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 2 +- linux/drivers/media/video/sn9c102/sn9c102_devtable.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 55970fee6..3746ddbbe 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -2385,8 +2385,8 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)}, - {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE + {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)}, {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)}, #endif {USB_DEVICE(0x0c45, 0x6100), BSI(SN9C120, MI0360, 0x5d)}, /*sn9c128*/ diff --git a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h index 38a716020..36ee43a9e 100644 --- a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -123,8 +123,8 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, -#endif { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, +#endif { } }; -- cgit v1.2.3 From b381f98d1b3f7204d763fb132e1c6ee6f384008e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 1 Sep 2009 22:16:23 +0200 Subject: vino: add missing compat.h include. From: Hans Verkuil vino needs compat.h to get the I2C_ADDRS macro on kernels < 2.6.31. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/vino.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/drivers/media/video/vino.c b/linux/drivers/media/video/vino.c index 8383e6f80..5a8dd5e19 100644 --- a/linux/drivers/media/video/vino.c +++ b/linux/drivers/media/video/vino.c @@ -50,6 +50,7 @@ #include #include +#include "compat.h" #include "vino.h" #include "saa7191.h" #include "indycam.h" -- cgit v1.2.3 From 3218818d07892e9fd082cf1b3165164eae279bb5 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 2 Sep 2009 00:15:39 +0200 Subject: DVB: make DVB_MAX_ADAPTERS configurable From: Janne Grunau Support for more than 8 DVB devices is requested regularly so make it a kconfig variable instead of a header define. Values in the range 4-32 are tested. Priority: normal Signed-off-by: Janne Grunau Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/Kconfig | 13 +++++++++++++ linux/drivers/media/dvb/dvb-core/dvbdev.h | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/linux/drivers/media/dvb/Kconfig b/linux/drivers/media/dvb/Kconfig index b01986918..1d0e4b1ef 100644 --- a/linux/drivers/media/dvb/Kconfig +++ b/linux/drivers/media/dvb/Kconfig @@ -2,6 +2,19 @@ # DVB device configuration # +config DVB_MAX_ADAPTERS + int "maximum number of DVB/ATSC adapters" + depends on DVB_CORE + default 8 + range 1 255 + help + Maximum number of DVB/ATSC adapters. Increasing this number + increases the memory consumption of the DVB subsystem even + if a much lower number of DVB/ATSC adapters is present. + Only values in the range 4-32 are tested. + + If you are unsure about this, use the default value 8 + config DVB_DYNAMIC_MINORS bool "Dynamic DVB minor allocation" depends on DVB_CORE diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.h b/linux/drivers/media/dvb/dvb-core/dvbdev.h index 487919bea..895e2efca 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.h +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h @@ -30,7 +30,12 @@ #define DVB_MAJOR 212 +#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0 +#define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS +#else +#warning invalid CONFIG_DVB_MAX_ADAPTERS value #define DVB_MAX_ADAPTERS 8 +#endif #define DVB_UNSET (-1) -- cgit v1.2.3 From 39c7c8c56d56cc3a3fd5128d0598944303a929df Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 2 Sep 2009 00:23:09 +0200 Subject: dvb-core: check fe->ops.set_frontend return value From: Janne Grunau Various frontend driver have parameter checks in their set_frontend functions and return an error if the parameters are not supported, tda10021 and cx24116 to name two. The tuning ioctls FE_SET_FRONTEND/FE_SET_PROPERTY only change values in the property cache and return before set_frontend is called. If a set_frontend call in software zigzag algorithm fails and the card was previously locked it will report a lock and the new parameters but is still tuned to the old transport. This is not detectable from userspace. This change checks the return values of fe->ops.set_frontend and changes the state to the added FESTATE_ERROR for software zigzag. No lock will be reported to userspace if the State is FESTATE_ERROR. Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/dvb/dvb-core/dvb_frontend.c | 26 ++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index 41166d407..fbfccbd91 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -77,6 +77,7 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to seconds on open( #define FESTATE_ZIGZAG_FAST 32 #define FESTATE_ZIGZAG_SLOW 64 #define FESTATE_DISEQC 128 +#define FESTATE_ERROR 256 #define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC) #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST) #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW) @@ -274,6 +275,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra { int autoinversion; int ready = 0; + int fe_set_err = 0; struct dvb_frontend_private *fepriv = fe->frontend_priv; int original_inversion = fepriv->parameters.inversion; u32 original_frequency = fepriv->parameters.frequency; @@ -350,7 +352,11 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra if (autoinversion) fepriv->parameters.inversion = fepriv->inversion; if (fe->ops.set_frontend) - fe->ops.set_frontend(fe, &fepriv->parameters); + fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters); + if (fe_set_err < 0) { + fepriv->state = FESTATE_ERROR; + return fe_set_err; + } fepriv->parameters.frequency = original_frequency; fepriv->parameters.inversion = original_inversion; @@ -362,6 +368,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra static void dvb_frontend_swzigzag(struct dvb_frontend *fe) { fe_status_t s = 0; + int retval = 0; struct dvb_frontend_private *fepriv = fe->frontend_priv; /* if we've got no parameters, just keep idling */ @@ -375,8 +382,12 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) { if (fepriv->state & FESTATE_RETUNE) { if (fe->ops.set_frontend) - fe->ops.set_frontend(fe, &fepriv->parameters); - fepriv->state = FESTATE_TUNED; + retval = fe->ops.set_frontend(fe, + &fepriv->parameters); + if (retval < 0) + fepriv->state = FESTATE_ERROR; + else + fepriv->state = FESTATE_TUNED; } fepriv->delay = 3*HZ; fepriv->quality = 0; @@ -454,7 +465,11 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) fepriv->delay = fepriv->min_delay; /* peform a tune */ - if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) { + retval = dvb_frontend_swzigzag_autotune(fe, + fepriv->check_wrapped); + if (retval < 0) { + return; + } else if (retval) { /* OK, if we've run out of trials at the fast speed. * Drop back to slow for the _next_ attempt */ fepriv->state = FESTATE_SEARCHING_SLOW; @@ -1614,7 +1629,8 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, /* if retune was requested but hasn't occured yet, prevent * that user get signal state from previous tuning */ - if(fepriv->state == FESTATE_RETUNE) { + if (fepriv->state == FESTATE_RETUNE || + fepriv->state == FESTATE_ERROR) { err=0; *status = 0; break; -- cgit v1.2.3 From 47515034f52a7a8848e3636668e31e1af4a79fbe Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 2 Sep 2009 00:24:08 +0200 Subject: dvb-core: check supported QAM modulations From: Janne Grunau Check the modulation in dvb_frontend_check_parameters against frontend's capabilties for FE_QAM devices. Priority: normal Signed-off-by: Janne Grunau --- linux/drivers/media/dvb/dvb-core/dvb_frontend.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index fbfccbd91..56a11d32a 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -849,6 +849,15 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, } } + /* check for supported modulation */ + if (fe->ops.info.type == FE_QAM && + (parms->u.qam.modulation > QAM_AUTO || + !((1 << (parms->u.qam.modulation + 10)) & fe->ops.info.caps))) { + printk(KERN_WARNING "DVB: adapter %i frontend %i modulation %u not supported\n", + fe->dvb->num, fe->id, parms->u.qam.modulation); + return -EINVAL; + } + return 0; } -- cgit v1.2.3 From b61a3561ab2c5e47dddf11f3389fa7960edb1de5 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Wed, 2 Sep 2009 00:12:13 -0400 Subject: gspca - sn9c20x: Reduces size of object From: Joe Perches Use s16 instead of int where possible. Use struct instead of arrays Priority: normal Signed-off-by: Joe Perches Signed-off-by: Brian Johnson --- linux/drivers/media/video/gspca/sn9c20x.c | 101 +++++++++++++++++------------- 1 file changed, 56 insertions(+), 45 deletions(-) diff --git a/linux/drivers/media/video/gspca/sn9c20x.c b/linux/drivers/media/video/gspca/sn9c20x.c index fc47f978e..416a51fe7 100644 --- a/linux/drivers/media/video/gspca/sn9c20x.c +++ b/linux/drivers/media/video/gspca/sn9c20x.c @@ -97,6 +97,16 @@ struct sd { #endif }; +struct i2c_reg_u8 { + u8 reg; + u8 val; +}; + +struct i2c_reg_u16 { + u8 reg; + u16 val; +}; + static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val); static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val); @@ -406,7 +416,7 @@ static const struct v4l2_pix_format sxga_mode[] = { .priv = 3 | MODE_RAW | MODE_SXGA}, }; -static const int hsv_red_x[] = { +static const s16 hsv_red_x[] = { 41, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 81, 83, 85, 87, @@ -454,7 +464,7 @@ static const int hsv_red_x[] = { 24, 26, 28, 30, 33, 35, 37, 39, 41 }; -static const int hsv_red_y[] = { +static const s16 hsv_red_y[] = { 82, 80, 78, 76, 74, 73, 71, 69, 67, 65, 63, 61, 58, 56, 54, 52, 50, 48, 46, 44, 41, 39, 37, 35, @@ -502,7 +512,7 @@ static const int hsv_red_y[] = { 96, 94, 92, 91, 89, 87, 85, 84, 82 }; -static const int hsv_green_x[] = { +static const s16 hsv_green_x[] = { -124, -124, -125, -125, -125, -125, -125, -125, -125, -126, -126, -125, -125, -125, -125, -125, -125, -124, -124, -124, -123, -123, -122, -122, @@ -550,7 +560,7 @@ static const int hsv_green_x[] = { -120, -120, -121, -122, -122, -123, -123, -124, -124 }; -static const int hsv_green_y[] = { +static const s16 hsv_green_y[] = { -100, -99, -98, -97, -95, -94, -93, -91, -90, -89, -87, -86, -84, -83, -81, -80, -78, -76, -75, -73, -71, -70, -68, -66, @@ -598,7 +608,7 @@ static const int hsv_green_y[] = { -109, -108, -107, -106, -105, -104, -103, -102, -100 }; -static const int hsv_blue_x[] = { +static const s16 hsv_blue_x[] = { 112, 113, 114, 114, 115, 116, 117, 117, 118, 118, 119, 119, 120, 120, 120, 121, 121, 121, 122, 122, 122, 122, 122, 122, @@ -646,7 +656,7 @@ static const int hsv_blue_x[] = { 104, 105, 106, 107, 108, 109, 110, 111, 112 }; -static const int hsv_blue_y[] = { +static const s16 hsv_blue_y[] = { -11, -13, -15, -17, -19, -21, -23, -25, -27, -29, -31, -33, -35, -37, -39, -41, -43, -45, -46, -48, -50, -52, -54, -55, @@ -795,7 +805,7 @@ static u8 hv7131r_gain[] = { 0x78 /* 8x */ }; -static u8 soi968_init[][2] = { +static struct i2c_reg_u8 soi968_init[] = { {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f}, {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00}, {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c}, @@ -809,7 +819,7 @@ static u8 soi968_init[][2] = { {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80}, }; -static u8 ov7660_init[][2] = { +static struct i2c_reg_u8 ov7660_init[] = { {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3}, {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40}, {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a}, @@ -818,7 +828,7 @@ static u8 ov7660_init[][2] = { {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50}, }; -static u8 ov7670_init[][2] = { +static struct i2c_reg_u8 ov7670_init[] = { {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01}, {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00}, {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0}, @@ -875,7 +885,7 @@ static u8 ov7670_init[][2] = { {0x93, 0x00}, }; -static u8 ov9650_init[][2] = { +static struct i2c_reg_u8 ov9650_init[] = { {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78}, {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03}, {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00}, @@ -905,7 +915,7 @@ static u8 ov9650_init[][2] = { {0xaa, 0x92}, {0xab, 0x0a}, }; -static u8 ov9655_init[][2] = { +static struct i2c_reg_u8 ov9655_init[] = { {0x12, 0x80}, {0x12, 0x01}, {0x0d, 0x00}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba}, {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x1e, 0x04}, {0x1e, 0x04}, {0x27, 0x08}, @@ -942,7 +952,7 @@ static u8 ov9655_init[][2] = { {0x00, 0x03}, {0x00, 0x0a}, {0x00, 0x10}, {0x00, 0x13}, }; -static u16 mt9v112_init[][2] = { +static struct i2c_reg_u16 mt9v112_init[] = { {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020}, {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b}, {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001}, @@ -961,7 +971,7 @@ static u16 mt9v112_init[][2] = { {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae}, }; -static u16 mt9v111_init[][2] = { +static struct i2c_reg_u16 mt9v111_init[] = { {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x0001}, {0x02, 0x0016}, {0x03, 0x01e1}, {0x04, 0x0281}, {0x05, 0x0004}, {0x07, 0x3002}, @@ -988,7 +998,7 @@ static u16 mt9v111_init[][2] = { {0x0e, 0x0008}, {0x06, 0x002d}, {0x05, 0x0004}, }; -static u16 mt9v011_init[][2] = { +static struct i2c_reg_u16 mt9v011_init[] = { {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1}, {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006}, @@ -1015,7 +1025,7 @@ static u16 mt9v011_init[][2] = { {0x06, 0x0029}, {0x05, 0x0009}, }; -static u16 mt9m001_init[][2] = { +static struct i2c_reg_u16 mt9m001_init[] = { {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e}, {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501}, {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002}, @@ -1028,14 +1038,14 @@ static u16 mt9m001_init[][2] = { {0x2e, 0x0029}, {0x07, 0x0002}, }; -static u16 mt9m111_init[][2] = { +static struct i2c_reg_u16 mt9m111_init[] = { {0xf0, 0x0000}, {0x0d, 0x0008}, {0x0d, 0x0009}, {0x0d, 0x0008}, {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300}, {0xa1, 0x0280}, {0xa4, 0x0200}, {0x06, 0x308e}, {0xf0, 0x0000}, }; -static u8 hv7131r_init[][2] = { +static struct i2c_reg_u8 hv7131r_init[] = { {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08}, {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08}, @@ -1046,7 +1056,7 @@ static u8 hv7131r_init[][2] = { {0x23, 0x09}, {0x01, 0x08}, }; -int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length) +static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length) { struct usb_device *dev = gspca_dev->dev; int result; @@ -1065,7 +1075,8 @@ int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length) return 0; } -int reg_w(struct gspca_dev *gspca_dev, u16 reg, const u8 *buffer, int length) +static int reg_w(struct gspca_dev *gspca_dev, u16 reg, + const u8 *buffer, int length) { struct usb_device *dev = gspca_dev->dev; int result; @@ -1085,13 +1096,13 @@ int reg_w(struct gspca_dev *gspca_dev, u16 reg, const u8 *buffer, int length) return 0; } -int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) +static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) { u8 data[1] = {value}; return reg_w(gspca_dev, reg, data, 1); } -int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) +static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) { int i; reg_w(gspca_dev, 0x10c0, buffer, 8); @@ -1107,7 +1118,7 @@ int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) return -EIO; } -int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) +static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -1129,7 +1140,7 @@ int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) return i2c_w(gspca_dev, row); } -int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) +static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) { struct sd *sd = (struct sd *) gspca_dev; u8 row[8]; @@ -1206,8 +1217,8 @@ static int ov9650_init_sensor(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) { - if (i2c_w1(gspca_dev, ov9650_init[i][0], - ov9650_init[i][1]) < 0) { + if (i2c_w1(gspca_dev, ov9650_init[i].reg, + ov9650_init[i].val) < 0) { err("OV9650 sensor initialization failed"); return -ENODEV; } @@ -1223,8 +1234,8 @@ static int ov9655_init_sensor(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) { - if (i2c_w1(gspca_dev, ov9655_init[i][0], - ov9655_init[i][1]) < 0) { + if (i2c_w1(gspca_dev, ov9655_init[i].reg, + ov9655_init[i].val) < 0) { err("OV9655 sensor initialization failed"); return -ENODEV; } @@ -1242,8 +1253,8 @@ static int soi968_init_sensor(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; for (i = 0; i < ARRAY_SIZE(soi968_init); i++) { - if (i2c_w1(gspca_dev, soi968_init[i][0], - soi968_init[i][1]) < 0) { + if (i2c_w1(gspca_dev, soi968_init[i].reg, + soi968_init[i].val) < 0) { err("SOI968 sensor initialization failed"); return -ENODEV; } @@ -1261,8 +1272,8 @@ static int ov7660_init_sensor(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) { - if (i2c_w1(gspca_dev, ov7660_init[i][0], - ov7660_init[i][1]) < 0) { + if (i2c_w1(gspca_dev, ov7660_init[i].reg, + ov7660_init[i].val) < 0) { err("OV7660 sensor initialization failed"); return -ENODEV; } @@ -1280,8 +1291,8 @@ static int ov7670_init_sensor(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) { - if (i2c_w1(gspca_dev, ov7670_init[i][0], - ov7670_init[i][1]) < 0) { + if (i2c_w1(gspca_dev, ov7670_init[i].reg, + ov7670_init[i].val) < 0) { err("OV7670 sensor initialization failed"); return -ENODEV; } @@ -1304,8 +1315,8 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev) ret = i2c_r2(gspca_dev, 0xff, &value); if ((ret == 0) && (value == 0x8243)) { for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) { - if (i2c_w2(gspca_dev, mt9v011_init[i][0], - mt9v011_init[i][1]) < 0) { + if (i2c_w2(gspca_dev, mt9v011_init[i].reg, + mt9v011_init[i].val) < 0) { err("MT9V011 sensor initialization failed"); return -ENODEV; } @@ -1322,8 +1333,8 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev) ret = i2c_r2(gspca_dev, 0xff, &value); if ((ret == 0) && (value == 0x823a)) { for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) { - if (i2c_w2(gspca_dev, mt9v111_init[i][0], - mt9v111_init[i][1]) < 0) { + if (i2c_w2(gspca_dev, mt9v111_init[i].reg, + mt9v111_init[i].val) < 0) { err("MT9V111 sensor initialization failed"); return -ENODEV; } @@ -1344,8 +1355,8 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev) ret = i2c_r2(gspca_dev, 0x00, &value); if ((ret == 0) && (value == 0x1229)) { for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) { - if (i2c_w2(gspca_dev, mt9v112_init[i][0], - mt9v112_init[i][1]) < 0) { + if (i2c_w2(gspca_dev, mt9v112_init[i].reg, + mt9v112_init[i].val) < 0) { err("MT9V112 sensor initialization failed"); return -ENODEV; } @@ -1365,8 +1376,8 @@ static int mt9m111_init_sensor(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int i; for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) { - if (i2c_w2(gspca_dev, mt9m111_init[i][0], - mt9m111_init[i][1]) < 0) { + if (i2c_w2(gspca_dev, mt9m111_init[i].reg, + mt9m111_init[i].val) < 0) { err("MT9M111 sensor initialization failed"); return -ENODEV; } @@ -1381,8 +1392,8 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int i; for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) { - if (i2c_w2(gspca_dev, mt9m001_init[i][0], - mt9m001_init[i][1]) < 0) { + if (i2c_w2(gspca_dev, mt9m001_init[i].reg, + mt9m001_init[i].val) < 0) { err("MT9M001 sensor initialization failed"); return -ENODEV; } @@ -1400,8 +1411,8 @@ static int hv7131r_init_sensor(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) { - if (i2c_w1(gspca_dev, hv7131r_init[i][0], - hv7131r_init[i][1]) < 0) { + if (i2c_w1(gspca_dev, hv7131r_init[i].reg, + hv7131r_init[i].val) < 0) { err("HV7131R Sensor initialization failed"); return -ENODEV; } -- cgit v1.2.3 From 6d4b16398a93f0c4be6f731bfa00912ca870c775 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 2 Sep 2009 11:10:22 +0200 Subject: libv4l: beginning of 0.6.2 dev cycle From: Hans de Goede libv4l: beginning of 0.6.2 dev cycle Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 3 +++ v4l2-apps/libv4l/Makefile | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index e5c421532..112b80be9 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -1,3 +1,6 @@ +libv4l-0.6.2 +------------ + libv4l-0.6.1 ------------ * Add more laptop models to the upside down devices table diff --git a/v4l2-apps/libv4l/Makefile b/v4l2-apps/libv4l/Makefile index 18dd17bdc..1afca883c 100644 --- a/v4l2-apps/libv4l/Makefile +++ b/v4l2-apps/libv4l/Makefile @@ -1,5 +1,5 @@ LIB_RELEASE=0 -V4L2_LIB_VERSION=$(LIB_RELEASE).6.1 +V4L2_LIB_VERSION=$(LIB_RELEASE).6.2-test all install: $(MAKE) -C libv4lconvert V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@ -- cgit v1.2.3 From 1b64f6c0606b5ccc94e58456e22702c8078cd8ec Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 2 Sep 2009 11:16:18 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/ChangeLog | 1 + v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index 112b80be9..e2e7ac36f 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -1,5 +1,6 @@ libv4l-0.6.2 ------------ +* Add more laptop models to the upside down devices table libv4l-0.6.1 ------------ diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 1d53233db..5e39815c9 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -63,6 +63,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "F7SR ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "G50VT ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "W7S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "X55SR ", -- cgit v1.2.3 From 7e03d3ad29c248556b9818b159316f551b4b7c8c Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 2 Sep 2009 11:25:10 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 5e39815c9..755f9c7be 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -141,6 +141,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F5N ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "F5SL ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1S ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x174f, 0x5a35, 0, "ASUSTeK Computer Inc. ", "G1Sn ", -- cgit v1.2.3 From 187a80bf44bebae8fd3a7ff804ecc523aaf6f3ea Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 2 Sep 2009 14:55:16 +0200 Subject: gspca_mr97310a: Allow overriding of detected sensor type From: Hans de Goede gspca_mr97310a: Allow overriding of detected sensor type Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 8190a1d4d..169cdb65c 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -57,6 +57,11 @@ MODULE_AUTHOR("Kyle Guinn ," MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); MODULE_LICENSE("GPL"); +/* global parameters */ +int force_sensor_type = -1; +module_param(force_sensor_type, int, 0644); +MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)"); + /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ @@ -401,6 +406,12 @@ static int sd_config(struct gspca_dev *gspca_dev, PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d", sd->sensor_type); + if (force_sensor_type != -1) { + sd->sensor_type = !! force_sensor_type; + PDEBUG(D_PROBE, "Forcing sensor type to: %d", + sd->sensor_type); + } + if (sd->sensor_type == 0) gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); } else { @@ -606,6 +617,12 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) msleep(200); } + if (force_sensor_type != -1) { + sd->sensor_type = !! force_sensor_type; + PDEBUG(D_PROBE, "Forcing sensor type to: %d", + sd->sensor_type); + } + /* * Known VGA cameras. * This test is only run if the previous test returned 0x30, but -- cgit v1.2.3 From 51072bf38e1417c308f80fc6580030a5d8e38a11 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Wed, 2 Sep 2009 11:39:41 -0400 Subject: gspca - sn9c20x: Fix exposure on SOI968 sensors From: Brian Johnson Fixes broken exposure on SOI968 webcams that was causing the camera to display a black screen Priority: high Signed-off-by: Brian Johnson --- linux/drivers/media/video/gspca/sn9c20x.c | 53 ++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/linux/drivers/media/video/gspca/sn9c20x.c b/linux/drivers/media/video/gspca/sn9c20x.c index 416a51fe7..0ff478170 100644 --- a/linux/drivers/media/video/gspca/sn9c20x.c +++ b/linux/drivers/media/video/gspca/sn9c20x.c @@ -812,7 +812,7 @@ static struct i2c_reg_u8 soi968_init[] = { {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff}, {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20}, {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e}, - {0x13, 0x8a}, {0x12, 0x40}, {0x17, 0x13}, + {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13}, {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79}, {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40}, {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32}, @@ -1260,7 +1260,7 @@ static int soi968_init_sensor(struct gspca_dev *gspca_dev) } } /* disable hflip and vflip */ - gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); + gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << EXPOSURE_IDX); sd->hstart = 60; sd->vstart = 11; return 0; @@ -1636,7 +1636,6 @@ static int set_exposure(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_OV7660: case SENSOR_OV7670: - case SENSOR_SOI968: case SENSOR_OV9655: case SENSOR_OV9650: exp[0] |= (3 << 4); @@ -1661,6 +1660,8 @@ static int set_exposure(struct gspca_dev *gspca_dev) exp[4] = ((sd->exposure * 0xffffff) / 0xffff) >> 8; exp[5] = ((sd->exposure * 0xffffff) / 0xffff) & 0xff; break; + default: + return 0; } i2c_w(gspca_dev, exp); return 0; @@ -1704,6 +1705,8 @@ static int set_gain(struct gspca_dev *gspca_dev) gain[2] = 0x30; gain[3] = hv7131r_gain[sd->gain]; break; + default: + return 0; } i2c_w(gspca_dev, gain); return 0; @@ -2227,15 +2230,10 @@ static void sd_stop0(struct gspca_dev *gspca_dev) kfree(sd->jpeg_hdr); } -static void do_autoexposure(struct gspca_dev *gspca_dev) +static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) { struct sd *sd = (struct sd *) gspca_dev; - int avg_lum, new_exp; - - if (!sd->auto_exposure) - return; - - avg_lum = atomic_read(&sd->avg_lum); + s16 new_exp; /* * some hardcoded values are present @@ -2282,6 +2280,39 @@ static void do_autoexposure(struct gspca_dev *gspca_dev) } } +static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (avg_lum < MIN_AVG_LUM) { + if (sd->gain + 1 <= 28) { + sd->gain++; + set_gain(gspca_dev); + } + } + if (avg_lum > MAX_AVG_LUM) { + if (sd->gain - 1 >= 0) { + sd->gain--; + set_gain(gspca_dev); + } + } +} + +static void sd_dqcallback(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int avg_lum; + + if (!sd->auto_exposure) + return; + + avg_lum = atomic_read(&sd->avg_lum); + if (sd->sensor == SENSOR_SOI968) + do_autogain(gspca_dev, avg_lum); + else + do_autoexposure(gspca_dev, avg_lum); +} + static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ u8 *data, /* isoc packet */ @@ -2349,7 +2380,7 @@ static const struct sd_desc sd_desc = { .stopN = sd_stopN, .stop0 = sd_stop0, .pkt_scan = sd_pkt_scan, - .dq_callback = do_autoexposure, + .dq_callback = sd_dqcallback, #ifdef CONFIG_VIDEO_ADV_DEBUG .set_register = sd_dbg_s_register, .get_register = sd_dbg_g_register, -- cgit v1.2.3 From 93893ecd34381b8ced1c17166e194729c921ec90 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Wed, 2 Sep 2009 12:14:41 -0400 Subject: gspca - sn9c20x: Add SXGA support to SOI968 From: Brian Johnson Priority: normal Signed-off-by: Brian Johnson --- linux/drivers/media/video/gspca/sn9c20x.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/linux/drivers/media/video/gspca/sn9c20x.c b/linux/drivers/media/video/gspca/sn9c20x.c index 0ff478170..4342220b6 100644 --- a/linux/drivers/media/video/gspca/sn9c20x.c +++ b/linux/drivers/media/video/gspca/sn9c20x.c @@ -2010,6 +2010,7 @@ static int sd_config(struct gspca_dev *gspca_dev, switch (sd->sensor) { case SENSOR_OV9650: + case SENSOR_SOI968: cam->cam_mode = sxga_mode; cam->nmodes = ARRAY_SIZE(sxga_mode); break; @@ -2125,6 +2126,25 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) struct sd *sd = (struct sd *) gspca_dev; u8 value; switch (sd->sensor) { + case SENSOR_SOI968: + if (mode & MODE_SXGA) { + i2c_w1(gspca_dev, 0x17, 0x1d); + i2c_w1(gspca_dev, 0x18, 0xbd); + i2c_w1(gspca_dev, 0x19, 0x01); + i2c_w1(gspca_dev, 0x1a, 0x81); + i2c_w1(gspca_dev, 0x12, 0x00); + sd->hstart = 140; + sd->vstart = 19; + } else { + i2c_w1(gspca_dev, 0x17, 0x13); + i2c_w1(gspca_dev, 0x18, 0x63); + i2c_w1(gspca_dev, 0x19, 0x01); + i2c_w1(gspca_dev, 0x1a, 0x79); + i2c_w1(gspca_dev, 0x12, 0x40); + sd->hstart = 60; + sd->vstart = 11; + } + break; case SENSOR_OV9650: if (mode & MODE_SXGA) { i2c_w1(gspca_dev, 0x17, 0x1b); -- cgit v1.2.3 From 4acaf41f8f45a4b7c2403f979ffa23330ada7edf Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 2 Sep 2009 21:23:23 -0400 Subject: em28xx: fix mmap_mapper with vbi From: Devin Heitmueller When adding support for both video and VBI, I missed the mmap ioctl. Add the missing call. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-video.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 449fec8f8..a9b859959 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -2354,7 +2354,10 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) if (unlikely(rc < 0)) return rc; - rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); + else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma); em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n", (unsigned long)vma->vm_start, -- cgit v1.2.3 From 6cda07d20922305bb7b24c77dfbbb4be105f8416 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 2 Sep 2009 23:23:27 -0400 Subject: em28xx: restructure fh/dev locking to handle both video and vbi From: Devin Heitmueller The current locking infrastructure didn't support having multiple fds accessing the device (such as video and vbi). Rework the locking infrastructure, borrowing the design from cx88. This work was sponsored by EyeMagnet Limited. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-video.c | 182 ++++++++++++------------ linux/drivers/media/video/em28xx/em28xx.h | 10 +- 2 files changed, 102 insertions(+), 90 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index a9b859959..773016eb8 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -863,34 +863,63 @@ static void video_mux(struct em28xx *dev, int index) } /* Usage lock check functions */ -static int res_get(struct em28xx_fh *fh) +static int res_get(struct em28xx_fh *fh, unsigned int bit) { struct em28xx *dev = fh->dev; - int rc = 0; - /* This instance already has stream_on */ - if (fh->stream_on) - return rc; + if (fh->resources & bit) + /* have it already allocated */ + return 1; - if (dev->stream_on) - return -EBUSY; + /* is it free? */ + mutex_lock(&dev->lock); + if (dev->resources & bit) { + /* no, someone else uses it */ + mutex_unlock(&dev->lock); + return 0; + } + /* it's free, grab it */ + fh->resources |= bit; + dev->resources |= bit; + em28xx_videodbg("res: get %d\n", bit); + mutex_unlock(&dev->lock); + return 1; +} - dev->stream_on = 1; - fh->stream_on = 1; - return rc; +static int res_check(struct em28xx_fh *fh, unsigned int bit) +{ + return (fh->resources & bit); } -static int res_check(struct em28xx_fh *fh) +static int res_locked(struct em28xx *dev, unsigned int bit) { - return fh->stream_on; + return (dev->resources & bit); } -static void res_free(struct em28xx_fh *fh) +static void res_free(struct em28xx_fh *fh, unsigned int bits) { struct em28xx *dev = fh->dev; - fh->stream_on = 0; - dev->stream_on = 0; + BUG_ON((fh->resources & bits) != bits); + + mutex_lock(&dev->lock); + fh->resources &= ~bits; + dev->resources &= ~bits; + em28xx_videodbg("res: put %d\n", bits); + mutex_unlock(&dev->lock); +} + +static int get_ressource(struct em28xx_fh *fh) +{ + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return EM28XX_RESOURCE_VIDEO; + case V4L2_BUF_TYPE_VBI_CAPTURE: + return EM28XX_RESOURCE_VBI; + default: + BUG(); + return 0; + } } /* @@ -1133,12 +1162,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, goto out; } - if (dev->stream_on && !fh->stream_on) { - em28xx_errdev("%s device in use by another fh\n", __func__); - rc = -EBUSY; - goto out; - } - rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat, f->fmt.pix.width, f->fmt.pix.height); @@ -1704,24 +1727,25 @@ static int vidioc_streamon(struct file *file, void *priv, { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; - int rc; + int rc = -EINVAL; rc = check_dev(dev); if (rc < 0) return rc; + if (unlikely(type != fh->type)) + return -EINVAL; - mutex_lock(&dev->lock); - rc = res_get(fh); + em28xx_videodbg("vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n", + fh, type, fh->resources, dev->resources); - if (likely(rc >= 0)) { - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - rc = videobuf_streamon(&fh->vb_vidq); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - rc = videobuf_streamon(&fh->vb_vbiq); - } + if (unlikely(!res_get(fh,get_ressource(fh)))) + return -EBUSY; - mutex_unlock(&dev->lock); + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + rc = videobuf_streamon(&fh->vb_vidq); + else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + rc = videobuf_streamon(&fh->vb_vbiq); return rc; } @@ -1743,16 +1767,16 @@ static int vidioc_streamoff(struct file *file, void *priv, if (type != fh->type) return -EINVAL; - mutex_lock(&dev->lock); + em28xx_videodbg("vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n", + fh, type, fh->resources, dev->resources); - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { videobuf_streamoff(&fh->vb_vidq); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + res_free(fh, EM28XX_RESOURCE_VIDEO); + } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { videobuf_streamoff(&fh->vb_vbiq); - - res_free(fh); - - mutex_unlock(&dev->lock); + res_free(fh, EM28XX_RESOURCE_VBI); + } return 0; } @@ -2146,17 +2170,16 @@ static int em28xx_v4l2_open(struct file *filp) else field = V4L2_FIELD_INTERLACED; - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, - NULL, &dev->slock, fh->type, field, - sizeof(struct em28xx_buffer), fh); + videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, + NULL, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, field, + sizeof(struct em28xx_buffer), fh); - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) - videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops, - NULL, &dev->slock, - V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_FIELD_SEQ_TB, - sizeof(struct em28xx_buffer), fh); + videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops, + NULL, &dev->slock, + V4L2_BUF_TYPE_VBI_CAPTURE, + V4L2_FIELD_SEQ_TB, + sizeof(struct em28xx_buffer), fh); mutex_unlock(&dev->lock); @@ -2213,20 +2236,21 @@ static int em28xx_v4l2_close(struct file *filp) em28xx_videodbg("users=%d\n", dev->users); - - mutex_lock(&dev->lock); - if (res_check(fh)) - res_free(fh); - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 1) { + if (res_check(fh, EM28XX_RESOURCE_VIDEO)) { videobuf_stop(&fh->vb_vidq); - videobuf_mmap_free(&fh->vb_vidq); + res_free(fh, EM28XX_RESOURCE_VIDEO); + } + if (res_check(fh, EM28XX_RESOURCE_VBI)) { + videobuf_stop(&fh->vb_vbiq); + res_free(fh, EM28XX_RESOURCE_VBI); + } + + if(dev->users == 1) { /* the device is already disconnect, free the remaining resources */ if (dev->state & DEV_DISCONNECTED) { em28xx_release_resources(dev); - mutex_unlock(&dev->lock); kfree(dev); return 0; } @@ -2248,15 +2272,11 @@ static int em28xx_v4l2_close(struct file *filp) } } - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - videobuf_stop(&fh->vb_vbiq); - videobuf_mmap_free(&fh->vb_vbiq); - } - + videobuf_mmap_free(&fh->vb_vidq); + videobuf_mmap_free(&fh->vb_vbiq); kfree(fh); dev->users--; wake_up_interruptible_nr(&dev->open, 1); - mutex_unlock(&dev->lock); return 0; } @@ -2281,12 +2301,8 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count, */ if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - mutex_lock(&dev->lock); - rc = res_get(fh); - mutex_unlock(&dev->lock); - - if (unlikely(rc < 0)) - return rc; + if (res_locked(dev, EM28XX_RESOURCE_VIDEO)) + return -EBUSY; return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, filp->f_flags & O_NONBLOCK); @@ -2294,9 +2310,8 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count, if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { - mutex_lock(&dev->lock); - rc = res_get(fh); - mutex_unlock(&dev->lock); + if (!res_get(fh, EM28XX_RESOURCE_VBI)) + return -EBUSY; return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, filp->f_flags & O_NONBLOCK); @@ -2319,19 +2334,17 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait) if (rc < 0) return rc; - mutex_lock(&dev->lock); - rc = res_get(fh); - mutex_unlock(&dev->lock); - - if (unlikely(rc < 0)) - return POLLERR; - - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (!res_get(fh, EM28XX_RESOURCE_VIDEO)) + return POLLERR; return videobuf_poll_stream(filp, &fh->vb_vidq, wait); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + if (!res_get(fh, EM28XX_RESOURCE_VBI)) + return POLLERR; return videobuf_poll_stream(filp, &fh->vb_vbiq, wait); - else + } else { return POLLERR; + } } /* @@ -2347,13 +2360,6 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) if (rc < 0) return rc; - mutex_lock(&dev->lock); - rc = res_get(fh); - mutex_unlock(&dev->lock); - - if (unlikely(rc < 0)) - return rc; - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index c81ec13d3..09589ccca 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -445,6 +445,10 @@ enum em28xx_dev_state { #define EM28XX_AUDIO 0x10 #define EM28XX_DVB 0x20 +/* em28xx resource types (used for res_get/res_lock etc */ +#define EM28XX_RESOURCE_VIDEO 0x01 +#define EM28XX_RESOURCE_VBI 0x02 + struct em28xx_audio { char name[50]; char *transfer_buffer[EM28XX_AUDIO_BUFS]; @@ -473,8 +477,8 @@ struct em28xx; struct em28xx_fh { struct em28xx *dev; - unsigned int stream_on:1; /* Locks streams */ int radio; + unsigned int resources; struct videobuf_queue vb_vidq; struct videobuf_queue vb_vbiq; @@ -504,7 +508,6 @@ struct em28xx { /* Vinmode/Vinctl used at the driver */ int vinmode, vinctl; - unsigned int stream_on:1; /* Locks streams */ unsigned int has_audio_class:1; unsigned int has_alsa_audio:1; @@ -572,6 +575,9 @@ struct em28xx { struct video_device *vbi_dev; struct video_device *radio_dev; + /* resources in use */ + unsigned int resources; + unsigned char eedata[256]; /* Isoc control struct */ -- cgit v1.2.3 From f34b1cf00cddf45def1b83ac3b9ce9e09b12f3c8 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 2 Sep 2009 23:25:54 -0400 Subject: em28xx: remove unreferenced variable From: Devin Heitmueller Remove an unreferenced variable introduced during the VBI introduction. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-vbi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-vbi.c b/linux/drivers/media/video/em28xx/em28xx-vbi.c index b5802d4cb..27d7e860f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-vbi.c +++ b/linux/drivers/media/video/em28xx/em28xx-vbi.c @@ -85,7 +85,6 @@ static int vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { - struct em28xx_fh *fh = q->priv_data; struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); int rc = 0; unsigned int size; -- cgit v1.2.3 From 4b70cc85ac708fdb3107b4d17851e70e6bf9ecc6 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 3 Sep 2009 09:14:36 +0200 Subject: gspca_mr97310a: Add one more vivitar mini cam to the list of CIF cams From: Hans de Goede gspca_mr97310a: Add one more vivitar mini cam to the list of CIF cams Priority: normal Signed-off-by: Hans de Goede --- linux/drivers/media/video/gspca/mr97310a.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c index 169cdb65c..140c8f320 100644 --- a/linux/drivers/media/video/gspca/mr97310a.c +++ b/linux/drivers/media/video/gspca/mr97310a.c @@ -393,6 +393,7 @@ static int sd_config(struct gspca_dev *gspca_dev, * Sakar Spy-shot 0x28 T. Kilgore 0 * Innovage 0xf5 (unstable) T. Kilgore 0 * Vivitar Mini 0x53 H. De Goede 0 + * Vivitar Mini 0x04 / 0x24 E. Rodriguez 0 * Vivitar Mini 0x08 T. Kilgore 1 * Elta-Media 8212dc 0x23 T. Kaiser 1 * Philips dig. keych. 0x37 T. Kilgore 1 -- cgit v1.2.3 From 8ea6a6c6c6f581cbf41e8813f6edb45acd1181f6 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Thu, 3 Sep 2009 13:28:26 +0200 Subject: libv4l: enable libv4l2 usage with devices which just support read() From: Hans de Goede libv4l: enable libv4l2 usage with devices which just support read(), this allows applications to work with mpeg capture devices like the cx18, which only do read() and only support mpeg and some exotic raw format (which libv4l can convert). Thanks to Simon Farnsworth for testing this. Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4l2/libv4l2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/v4l2-apps/libv4l/libv4l2/libv4l2.c b/v4l2-apps/libv4l/libv4l2/libv4l2.c index c035ae533..3366538a7 100644 --- a/v4l2-apps/libv4l/libv4l2/libv4l2.c +++ b/v4l2-apps/libv4l/libv4l2/libv4l2.c @@ -312,7 +312,6 @@ static int v4l2_read_and_convert(int index, unsigned char *dest, int dest_size) int result, buf_size, tries = max_tries; buf_size = devices[index].dest_fmt.fmt.pix.sizeimage; - buf_size = (buf_size + 8191) & ~8191; if (devices[index].readbuf_size < buf_size) { unsigned char *new_buf; @@ -526,10 +525,9 @@ int v4l2_fd_open(int fd, int v4l2_flags) return -1; } - /* we only add functionality for video capture devices, and we do not - handle devices which don't do mmap */ + /* we only add functionality for video capture devices */ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) || - !(cap.capabilities & V4L2_CAP_STREAMING)) + !(cap.capabilities & (V4L2_CAP_STREAMING|V4L2_CAP_READWRITE))) return fd; /* Get current cam format */ @@ -564,6 +562,8 @@ int v4l2_fd_open(int fd, int v4l2_flags) devices[index].flags = v4l2_flags; if (cap.capabilities & V4L2_CAP_READWRITE) devices[index].flags |= V4L2_SUPPORTS_READ; + if (!(cap.capabilities & V4L2_CAP_STREAMING)) + devices[index].flags |= V4L2_USE_READ_FOR_READ; if (!strcmp((char *)cap.driver, "uvcvideo")) devices[index].flags |= V4L2_IS_UVC; devices[index].open_count = 1; @@ -571,7 +571,7 @@ int v4l2_fd_open(int fd, int v4l2_flags) devices[index].dest_fmt = fmt; /* When a user does a try_fmt with the current dest_fmt and the dest_fmt - is a supported one we will align the resulution (see try_fmt for why). + is a supported one we will align the resolution (see try_fmt for why). Do the same here now, so that a try_fmt on the result of a get_fmt done immediately after open leaves the fmt unchanged. */ if (v4lconvert_supported_dst_format( -- cgit v1.2.3 From 00c1eda676d0707af2602f156278772fe3c30cb8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 3 Sep 2009 09:06:34 -0300 Subject: v4l2-spec: Fix xmlto compilation with some versions of the tool From: Mauro Carvalho Chehab While some versions of xmlto accepts "Role" attribute for emphasis tag, with some others, it fails. Better to replace it to "role" to fix the issue. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-spec/remote_controllers.sgml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/v4l2-spec/remote_controllers.sgml b/v4l2-spec/remote_controllers.sgml index 6cbcd5869..eb669537a 100644 --- a/v4l2-spec/remote_controllers.sgml +++ b/v4l2-spec/remote_controllers.sgml @@ -18,7 +18,7 @@ Key examples on IR -Numeric keys +Numeric keysKEY_0Keyboard digit 00KEY_1Keyboard digit 11 @@ -31,7 +31,7 @@ KEY_8Keyboard digit 88KEY_9Keyboard digit 99 -Movie play control +Movie play controlKEY_FORWARDInstantly advance in time>> / FORWARDKEY_BACKInstantly go back in time<<< / BACK @@ -51,7 +51,7 @@ KEY_TITLEAllow changing the chapterCHAPTERKEY_SUBTITLEAllow changing the subtitleSUBTITLE -Image control +Image controlKEY_BRIGHTNESSDOWNDecrease BrightnessBRIGHTNESS DECREASEKEY_BRIGHTNESSUPIncrease BrightnessBRIGHTNESS INCREASE @@ -60,7 +60,7 @@ KEY_EPGOpen the Elecrowonic Play Guide (EPG)EPG / GUIDEKEY_TEXTActivate/change closed caption modeCLOSED CAPTION/TELETEXT / DVD TEXT / TELETEXT / TTX -Audio control +Audio controlKEY_AUDIOChange audio sourceAUDIO SOURCE / AUDIO / MUSICKEY_MUTEMute/unmute audioMUTE / DEMUTE / UNMUTE @@ -69,7 +69,7 @@ KEY_MODEChange sound modeMONO/STEREOKEY_LANGUAGESelect Language1ST / 2ND LANGUAGE / DVD LANG / MTS/SAP / MTS SEL -Channel control +Channel controlKEY_CHANNELGo to the next favorite channelALT / CHANNEL / CH SURFING / SURF / FAVKEY_CHANNELDOWNDecrease channel sequenciallyCHANNEL - / CHANNEL DOWN / DOWN @@ -77,14 +77,14 @@ KEY_DIGITSUse more than one digit for channelPLUS / 100/ 1xx / xxx / -/-- / Single Double Triple DigitKEY_SEARCHStart channel autoscanSCAN / AUTOSCAN -Colored keys +Colored keysKEY_BLUEIR Blue keyBLUEKEY_GREENIR Green KeyGREENKEY_REDIR Red keyREDKEY_YELLOWIR Yellow key YELLOW -Media selection +Media selectionKEY_CDChange input source to Compact DiscCDKEY_DVDChange input to DVDDVD / DVD MENU @@ -98,14 +98,14 @@ KEY_VCRSelect VCR modeVCR MODE / DTRKEY_VIDEOAlternate between input modesSOURCE / SELECT / DISPLAY / SWITCH INPUTS / VIDEO -Power control +Power controlKEY_POWERTurn on/off computerSYSTEM POWER / COMPUTER POWERKEY_POWER2Turn on/off applicationTV ON/OFF / POWERKEY_SLEEPActivate sleep timerSLEEP / SLEEP TIMERKEY_SUSPENDPut computer into suspend modeSTANDBY / SUSPEND -Window control +Window controlKEY_CLEARStop sroweam and return to default input video/audioCLEAR / RESET / BOSS KEYKEY_CYCLEWINDOWSMinimize windows and move to the next oneALT-TAB / MINIMIZE / DESKTOP @@ -116,7 +116,7 @@ KEY_SCREENSelect screen aspect ratio4:3 16:9 SELECTKEY_ZOOMPut device into zoom/full screen modeZOOM / FULL SCREEN / ZOOM+ / HIDE PANNEL / SWITCH -Navigation keys +Navigation keysKEY_ESCCancel current operationCANCEL / BACKKEY_HELPOpen a Help windowHELP @@ -128,7 +128,7 @@ KEY_LEFTLeft keyLEFTKEY_RIGHTRight keyRIGHT -Miscelaneous keys +Miscelaneous keysKEY_DOTReturn a dot.KEY_FNSelect a functionFUNCTION -- cgit v1.2.3 From 4883f84c11cb8a24270088af6b6381644a6caca3 Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Thu, 3 Sep 2009 18:07:13 -0400 Subject: gspca - sn9c20x: disable exposure/gain controls for MT9M111 sensors. From: Brian Johnson Using the MT9M111's IFP to handle exposure/gain gives better results. Priority: normal Signed-off-by: Brian Johnson --- linux/drivers/media/video/gspca/sn9c20x.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/linux/drivers/media/video/gspca/sn9c20x.c b/linux/drivers/media/video/gspca/sn9c20x.c index 4342220b6..86351f54e 100644 --- a/linux/drivers/media/video/gspca/sn9c20x.c +++ b/linux/drivers/media/video/gspca/sn9c20x.c @@ -1039,10 +1039,10 @@ static struct i2c_reg_u16 mt9m001_init[] = { }; static struct i2c_reg_u16 mt9m111_init[] = { - {0xf0, 0x0000}, {0x0d, 0x0008}, {0x0d, 0x0009}, - {0x0d, 0x0008}, {0xf0, 0x0001}, {0x3a, 0x4300}, - {0x9b, 0x4300}, {0xa1, 0x0280}, {0xa4, 0x0200}, - {0x06, 0x308e}, {0xf0, 0x0000}, + {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008}, + {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300}, + {0xa1, 0x0280}, {0xa4, 0x0200}, {0x06, 0x708e}, + {0xf0, 0x0002}, {0x2e, 0x0a1e}, {0xf0, 0x0000}, }; static struct i2c_reg_u8 hv7131r_init[] = { @@ -1382,6 +1382,7 @@ static int mt9m111_init_sensor(struct gspca_dev *gspca_dev) return -ENODEV; } } + gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << GAIN_IDX); sd->hstart = 0; sd->vstart = 2; return 0; @@ -1644,7 +1645,6 @@ static int set_exposure(struct gspca_dev *gspca_dev) exp[4] = sd->exposure >> 8; break; case SENSOR_MT9M001: - case SENSOR_MT9M111: case SENSOR_MT9V112: case SENSOR_MT9V111: case SENSOR_MT9V011: @@ -1688,7 +1688,6 @@ static int set_gain(struct gspca_dev *gspca_dev) gain[4] = micron1_gain[sd->gain] & 0xff; break; case SENSOR_MT9V112: - case SENSOR_MT9M111: gain[0] |= (3 << 4); gain[2] = 0x2f; gain[3] = micron1_gain[sd->gain] >> 8; -- cgit v1.2.3 From 0ceb8b67995dcbe0d5cbd99dddd64fad77d5181d Mon Sep 17 00:00:00 2001 From: Brian Johnson Date: Thu, 3 Sep 2009 18:10:15 -0400 Subject: gspca - sn9c20x: Add SXGA support to MT9M111 From: Brian Johnson Priority: normal Signed-off-by: Brian Johnson --- linux/drivers/media/video/gspca/sn9c20x.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/video/gspca/sn9c20x.c b/linux/drivers/media/video/gspca/sn9c20x.c index 86351f54e..99632a7d6 100644 --- a/linux/drivers/media/video/gspca/sn9c20x.c +++ b/linux/drivers/media/video/gspca/sn9c20x.c @@ -1041,8 +1041,8 @@ static struct i2c_reg_u16 mt9m001_init[] = { static struct i2c_reg_u16 mt9m111_init[] = { {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008}, {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300}, - {0xa1, 0x0280}, {0xa4, 0x0200}, {0x06, 0x708e}, - {0xf0, 0x0002}, {0x2e, 0x0a1e}, {0xf0, 0x0000}, + {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e}, + {0xf0, 0x0000}, }; static struct i2c_reg_u8 hv7131r_init[] = { @@ -2008,6 +2008,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->i2c_addr = id->driver_info & 0xff; switch (sd->sensor) { + case SENSOR_MT9M111: case SENSOR_OV9650: case SENSOR_SOI968: cam->cam_mode = sxga_mode; @@ -2161,6 +2162,17 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40); } break; + case SENSOR_MT9M111: + if (mode & MODE_SXGA) { + i2c_w2(gspca_dev, 0xf0, 0x0002); + i2c_w2(gspca_dev, 0xc8, 0x970b); + i2c_w2(gspca_dev, 0xf0, 0x0000); + } else { + i2c_w2(gspca_dev, 0xf0, 0x0002); + i2c_w2(gspca_dev, 0xc8, 0x8000); + i2c_w2(gspca_dev, 0xf0, 0x0000); + } + break; } } -- cgit v1.2.3 From 2518e6d5dd10b13a5598b37a58e1e53aa5699270 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 4 Sep 2009 21:36:56 +0200 Subject: SH: fix ap325rxa compilation breakage From: Guennadi Liakhovetski An unfortunate typo in an earlier patch broke ap325rxa compilation. Fix it. Signed-off-by: Guennadi Liakhovetski Priority: pending --- arch/sh/boards/board-ap325rxa.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) --- linux/arch/sh/boards/board-ap325rxa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux/arch/sh/boards/board-ap325rxa.c b/linux/arch/sh/boards/board-ap325rxa.c index 21469489d..96e5bae1c 100644 --- a/linux/arch/sh/boards/board-ap325rxa.c +++ b/linux/arch/sh/boards/board-ap325rxa.c @@ -359,8 +359,8 @@ static void ap325rxa_camera_del(struct soc_camera_link *icl) return; platform_device_unregister(&camera_device); - memset(&migor_camera_device.dev.kobj, 0, - sizeof(migor_camera_device.dev.kobj)); + memset(&camera_device.dev.kobj, 0, + sizeof(camera_device.dev.kobj)); } #endif /* CONFIG_I2C */ -- cgit v1.2.3 From 38df09ba8b967b4d219c2afe04dcc1ae743e766f Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 5 Sep 2009 09:58:37 -0400 Subject: cx18: ir-kbd-i2c initialization data should point to a persistent object From: Andy Walls ir-kbd-i2c's ir_probe() function can be called much later (i.e. at ir-kbd-i2c module load), than the lifetime of a struct IR_i2c_init_data allocated off of the stack in cx18_i2c_new_ir() at registration time. Make sure we pass a pointer to a persistent IR_i2c_init_data object at i2c registration time. Thanks to Brain Rogers for pointing out a solution, and Dustin Mitchell for testing against a 2.6.30 kernel. Reported-by: Dustin Mitchell Reported-by: Brian Rogers Priority: high Tested-by: Dustin Mitchell Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-i2c.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/video/cx18/cx18-i2c.c b/linux/drivers/media/video/cx18/cx18-i2c.c index fd789fad1..779ac7cbf 100644 --- a/linux/drivers/media/video/cx18/cx18-i2c.c +++ b/linux/drivers/media/video/cx18/cx18-i2c.c @@ -99,12 +99,18 @@ static const char * const hw_devicenames[] = { "ir_rx_z8f0811_haup", }; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) +static const struct IR_i2c_init_data z8f0811_ir_init_data = { + .ir_codes = &ir_codes_hauppauge_new_table, + .internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR, + .type = IR_TYPE_RC5, + .name = "CX23418 Z8F0811 Hauppauge", +}; + static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char *type, u8 addr) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) struct i2c_board_info info; - struct IR_i2c_init_data ir_init_data; unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; memset(&info, 0, sizeof(struct i2c_board_info)); @@ -113,22 +119,21 @@ static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char *type, /* Our default information for ir-kbd-i2c.c to use */ switch (hw) { case CX18_HW_Z8F0811_IR_RX_HAUP: - memset(&ir_init_data, 0, sizeof(struct IR_i2c_init_data)); - ir_init_data.ir_codes = &ir_codes_hauppauge_new_table; - ir_init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - ir_init_data.type = IR_TYPE_RC5; - ir_init_data.name = "CX23418 Z8F0811 Hauppauge"; - info.platform_data = &ir_init_data; + info.platform_data = &z8f0811_ir_init_data; break; default: break; } return i2c_new_probed_device(adap, &info, addr_list) == NULL ? -1 : 0; +} #else +static int cx18_i2c_new_ir(struct i2c_adapter *adap, u32 hw, const char *type, + u8 addr) +{ return -1; -#endif } +#endif int cx18_i2c_register(struct cx18 *cx, unsigned idx) { -- cgit v1.2.3 From 06f2ee05ed81b2c469ce5a83b0c90da01752166b Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Sun, 6 Sep 2009 10:41:37 +0200 Subject: libv4l: update upside down devices table From: Hans de Goede libv4l: update upside down devices table Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c index 755f9c7be..243f35dae 100644 --- a/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c +++ b/v4l2-apps/libv4l/libv4lconvert/control/libv4lcontrol.c @@ -3,6 +3,7 @@ # (C) 2008-2009 Sjoerd Piepenbrink # (C) 2008-2009 Radjnies Bhansingh # (C) 2008-2009 Hans de Goede +# (C) 2009 Paul Sladen # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -61,6 +62,8 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { /* Laptops */ { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "F7L ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "W7Sg ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "F7SR ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "G50VT ", @@ -71,6 +74,9 @@ static const struct v4lcontrol_flags_info v4lcontrol_flags[] = { V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "X55SV ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, + /* note different white space: http://launchpad.net/bugs/413752 */ + { 0x04f2, 0xb012, 0, "ASUSTeK Computer Inc. ", "X71SL ", + V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, /* These 3 PACKARD BELL's seem to be Asus notebook in disguise */ { 0x04f2, 0xb012, 0, "Packard Bell BV", "T32A ", V4LCONTROL_HFLIPPED|V4LCONTROL_VFLIPPED }, -- cgit v1.2.3 From 026fbaf9a959eb5b7770b075a604999f704640cb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 7 Sep 2009 08:40:24 +0200 Subject: v4l2-dev: add simple wrapper functions around the devnode numbers From: Hans Verkuil There are some subtle differences in the way the devnode numbers are handled depending on whether the FIXED_MINOR_RANGES config option is set. Add some simple wrapper functions to handle that correctly. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-dev.c | 53 ++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 77e650616..9a9fc1c83 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -88,6 +88,48 @@ static struct video_device *video_device[VIDEO_NUM_DEVICES]; static DEFINE_MUTEX(videodev_lock); static DECLARE_BITMAP(devnode_nums[VFL_TYPE_MAX], VIDEO_NUM_DEVICES); +/* Device node utility functions */ + +/* Note: these utility functions all assume that vfl_type is in the range + [0, VFL_TYPE_MAX-1]. */ + +#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES +/* Return the bitmap corresponding to vfl_type. */ +static inline unsigned long *devnode_bits(int vfl_type) +{ + /* Any types not assigned to fixed minor ranges must be mapped to + one single bitmap for the purposes of finding a free node number + since all those unassigned types use the same minor range. */ + int idx = (vfl_type > VFL_TYPE_VTX) ? VFL_TYPE_MAX - 1 : vfl_type; + + return devnode_nums[idx]; +} +#else +/* Return the bitmap corresponding to vfl_type. */ +static inline unsigned long *devnode_bits(int vfl_type) +{ + return devnode_nums[vfl_type]; +} +#endif + +/* Mark device node number vdev->num as used */ +static inline void devnode_set(struct video_device *vdev) +{ + set_bit(vdev->num, devnode_bits(vdev->vfl_type)); +} + +/* Mark device node number vdev->num as unused */ +static inline void devnode_clear(struct video_device *vdev) +{ + clear_bit(vdev->num, devnode_bits(vdev->vfl_type)); +} + +/* Try to find a free device node number in the range [from, to> */ +static inline int devnode_find(struct video_device *vdev, int from, int to) +{ + return find_next_zero_bit(devnode_bits(vdev->vfl_type), to, from); +} + struct video_device *video_device_alloc(void) { return kzalloc(sizeof(struct video_device), GFP_KERNEL); @@ -152,7 +194,7 @@ static void v4l2_device_release(struct device *cd) vdev->cdev = NULL; /* Mark device node number as free */ - clear_bit(vdev->num, devnode_nums[vdev->vfl_type]); + devnode_clear(vdev); mutex_unlock(&videodev_lock); @@ -473,9 +515,9 @@ int video_register_device(struct video_device *vdev, int type, int nr) /* Pick a device node number */ mutex_lock(&videodev_lock); - nr = find_next_zero_bit(devnode_nums[type], minor_cnt, nr == -1 ? 0 : nr); + nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt); if (nr == minor_cnt) - nr = find_first_zero_bit(devnode_nums[type], minor_cnt); + nr = devnode_find(vdev, 0, minor_cnt); if (nr == minor_cnt) { printk(KERN_ERR "could not get a free device node number\n"); mutex_unlock(&videodev_lock); @@ -498,7 +540,8 @@ int video_register_device(struct video_device *vdev, int type, int nr) #endif vdev->minor = i + minor_offset; vdev->num = nr; - set_bit(nr, devnode_nums[type]); + devnode_set(vdev); + /* Should not happen since we thought this minor was free */ WARN_ON(video_device[vdev->minor] != NULL); vdev->index = get_index(vdev); @@ -582,7 +625,7 @@ cleanup: mutex_lock(&videodev_lock); if (vdev->cdev) cdev_del(vdev->cdev); - clear_bit(vdev->num, devnode_nums[type]); + devnode_clear(vdev); mutex_unlock(&videodev_lock); /* Mark this video device as never having been registered. */ vdev->minor = -1; -- cgit v1.2.3 From 856378592a1b9be61e28092caf5e87446bae4694 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 6 Sep 2009 13:54:00 +0300 Subject: v4l: warn when desired devnodenr is in use & add _no_warn function From: Hans Verkuil Warn when the desired device node number is already in use, except when the new video_register_device_no_warn function is called since in some use-cases that warning is not relevant. Priority: normal Signed-off-by: Hans Verkuil --- linux/Documentation/video4linux/v4l2-framework.txt | 22 ++++++++++++++++------ linux/drivers/media/video/cx18/cx18-streams.c | 2 +- linux/drivers/media/video/ivtv/ivtv-streams.c | 2 +- linux/drivers/media/video/v4l2-dev.c | 20 +++++++++++++++++++- linux/include/media/v4l2-dev.h | 4 ++++ 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index 38b3716d8..b806edaf3 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -486,17 +486,27 @@ VFL_TYPE_RADIO: radioX for radio tuners VFL_TYPE_VTX: vtxX for teletext devices (deprecated, don't use) The last argument gives you a certain amount of control over the device -device node number used (i.e. the X in videoX). Normally you will pass -1 to -let the v4l2 framework pick the first free number. But if a driver creates -many devices, then it can be useful to have different video devices in -separate ranges. For example, video capture devices start at 0, video -output devices start at 16. - +device node number used (i.e. the X in videoX). Normally you will pass -1 +to let the v4l2 framework pick the first free number. But sometimes users +want to select a specific node number. It is common that drivers allow +the user to select a specific device node number through a driver module +option. That number is then passed to this function and video_register_device +will attempt to select that device node number. If that number was already +in use, then the next free device node number will be selected and it +will send a warning to the kernel log. + +Another use-case is if a driver creates many devices. In that case it can +be useful to place different video devices in separate ranges. For example, +video capture devices start at 0, video output devices start at 16. So you can use the last argument to specify a minimum device node number and the v4l2 framework will try to pick the first free number that is equal or higher to what you passed. If that fails, then it will just pick the first free number. +Since in this case you do not care about a warning about not being able +to select the specified device node number, you can call the function +video_register_device_no_warn() instead. + Whenever a device node is created some attributes are also created for you. If you look in /sys/class/video4linux you see the devices. Go into e.g. video0 and you will see 'name' and 'index' attributes. The 'name' attribute diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 816d70cc2..dabe3fadc 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -250,7 +250,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type) video_set_drvdata(s->video_dev, s); /* Register device. First try the desired minor, then any free one. */ - ret = video_register_device(s->video_dev, vfl_type, num); + ret = video_register_device_no_warn(s->video_dev, vfl_type, num); if (ret < 0) { CX18_ERR("Couldn't register v4l2 device for %s (device node number %d)\n", s->name, num); diff --git a/linux/drivers/media/video/ivtv/ivtv-streams.c b/linux/drivers/media/video/ivtv/ivtv-streams.c index 234000352..67699e3f2 100644 --- a/linux/drivers/media/video/ivtv/ivtv-streams.c +++ b/linux/drivers/media/video/ivtv/ivtv-streams.c @@ -261,7 +261,7 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) video_set_drvdata(s->vdev, s); /* Register device. First try the desired minor, then any free one. */ - if (video_register_device(s->vdev, vfl_type, num)) { + if (video_register_device_no_warn(s->vdev, vfl_type, num)) { IVTV_ERR("Couldn't register v4l2 device for %s (device node number %d)\n", s->name, num); video_device_release(s->vdev); diff --git a/linux/drivers/media/video/v4l2-dev.c b/linux/drivers/media/video/v4l2-dev.c index 9a9fc1c83..a6d761dec 100644 --- a/linux/drivers/media/video/v4l2-dev.c +++ b/linux/drivers/media/video/v4l2-dev.c @@ -420,6 +420,8 @@ static int get_index(struct video_device *vdev) * @type: type of device to register * @nr: which device node number (0 == /dev/video0, 1 == /dev/video1, ... * -1 == first free) + * @warn_if_nr_in_use: warn if the desired device node number + * was already in use and another number was chosen instead. * * The registration code assigns minor numbers and device node numbers * based on the requested type and registers the new device node with @@ -439,7 +441,8 @@ static int get_index(struct video_device *vdev) * * %VFL_TYPE_RADIO - A radio card */ -int video_register_device(struct video_device *vdev, int type, int nr) +static int __video_register_device(struct video_device *vdev, int type, int nr, + int warn_if_nr_in_use) { int i = 0; int ret; @@ -615,6 +618,10 @@ int video_register_device(struct video_device *vdev, int type, int nr) reference to the device goes away. */ vdev->dev.release = v4l2_device_release; + if (nr != -1 && nr != vdev->num && warn_if_nr_in_use) + printk(KERN_WARNING "%s: requested %s%d, got %s%d\n", + __func__, name_base, nr, name_base, vdev->num); + /* Part 5: Activate this minor. The char device can now be used. */ mutex_lock(&videodev_lock); video_device[vdev->minor] = vdev; @@ -631,8 +638,19 @@ cleanup: vdev->minor = -1; return ret; } + +int video_register_device(struct video_device *vdev, int type, int nr) +{ + return __video_register_device(vdev, type, nr, 1); +} EXPORT_SYMBOL(video_register_device); +int video_register_device_no_warn(struct video_device *vdev, int type, int nr) +{ + return __video_register_device(vdev, type, nr, 0); +} +EXPORT_SYMBOL(video_register_device_no_warn); + /** * video_unregister_device - unregister a video4linux device * @vdev: the device to unregister diff --git a/linux/include/media/v4l2-dev.h b/linux/include/media/v4l2-dev.h index 1cae97561..f813ae9c0 100644 --- a/linux/include/media/v4l2-dev.h +++ b/linux/include/media/v4l2-dev.h @@ -105,6 +105,10 @@ struct video_device Also note that vdev->minor is set to -1 if the registration failed. */ int __must_check video_register_device(struct video_device *vdev, int type, int nr); +/* Same as video_register_device, but no warning is issued if the desired + device node number was already in use. */ +int __must_check video_register_device_no_warn(struct video_device *vdev, int type, int nr); + /* Unregister video devices. Will do nothing if vdev == NULL or vdev->minor < 0. */ void video_unregister_device(struct video_device *vdev); -- cgit v1.2.3 From 89577c08b573b6e0d0474da70483aa7b8faea4b9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 6 Sep 2009 10:48:52 -0300 Subject: dvb-spec: Start a DocBook XML 4.1.2 version of DVB API docs From: Mauro Carvalho Chehab This is an unfinished work. It is a port of DVB API verison 3 from LaTex into DocBook. Currently, only chapters 1 and 2 were converted. Still pending the conversion of the remaining chapters and a good style revision after the end of the conversion. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- dvb-spec/sgml/Makefile | 135 + dvb-spec/sgml/README | 13 + dvb-spec/sgml/custom.dsl | 52 + dvb-spec/sgml/custom.xsl | 29 + dvb-spec/sgml/devices.sgml | 0 dvb-spec/sgml/dvbapi-complete.sgml | 9878 ++++++++++++++++++++++++++++++++++++ dvb-spec/sgml/dvbapi.sgml | 97 + dvb-spec/sgml/dvbstb.pdf | Bin 0 -> 1786 bytes dvb-spec/sgml/dvbstb.png | Bin 0 -> 22655 bytes dvb-spec/sgml/examples.sgml | 0 dvb-spec/sgml/fdl.sgml | 0 dvb-spec/sgml/frontend.sgml | 1816 +++++++ dvb-spec/sgml/intro.sgml | 191 + 13 files changed, 12211 insertions(+) create mode 100644 dvb-spec/sgml/Makefile create mode 100644 dvb-spec/sgml/README create mode 100644 dvb-spec/sgml/custom.dsl create mode 100644 dvb-spec/sgml/custom.xsl create mode 100644 dvb-spec/sgml/devices.sgml create mode 100644 dvb-spec/sgml/dvbapi-complete.sgml create mode 100644 dvb-spec/sgml/dvbapi.sgml create mode 100644 dvb-spec/sgml/dvbstb.pdf create mode 100644 dvb-spec/sgml/dvbstb.png create mode 100644 dvb-spec/sgml/examples.sgml create mode 100644 dvb-spec/sgml/fdl.sgml create mode 100644 dvb-spec/sgml/frontend.sgml create mode 100644 dvb-spec/sgml/intro.sgml diff --git a/dvb-spec/sgml/Makefile b/dvb-spec/sgml/Makefile new file mode 100644 index 000000000..f39d7a97c --- /dev/null +++ b/dvb-spec/sgml/Makefile @@ -0,0 +1,135 @@ +SHELL=/bin/bash + +SGMLS = \ + dvbapi.sgml \ + intro.sgml \ + frontend.sgml \ + devices.sgml \ + examples.sgml \ + fdl.sgml \ + entities.sgml \ + +PDFPICS = \ + dvbstb.pdf \ + +GIFPICS = \ + dvbstb.png \ + +# Some Jade warnings for authors. +WARN = +#WARN = -w all -w duplicate -w net + +# Stylesheet customization. + # docbook/db2 syntax +CUSTOM_HTML = --dsl custom.dsl\#html +CUSTOM_PRINT = --dsl custom.dsl\#print + # xmlto syntax +CUSTOM_HTML_XMLTO = -m custom.xsl +CUSTOM_PRINT_XMLTO = -m custom.xsl + +all: html-single + +html: html-build.stamp + +html-single: html-single-build.stamp + +pdf: pdf-build.stamp + +man: man-build.stamp + +man_install: man-build.stamp + install -d /usr/local/man/man2 + install -b man/* /usr/local/man/man2 + +entities.sgml: Makefile + echo "" >$@ + echo -e "\n" >>$@ + for file in $(SGMLS) ; do \ + entity=`echo "$$file" | sed 's/.sgml//;s/\./-/g'` ; \ + if ! echo "$$file" | \ + grep -q -E -e '^(func|vidioc|pixfmt)-' ; then \ + echo "" >>$@ ; \ + fi ; \ + done + +# Jade can auto-generate a list-of-tables, which includes all structs, +# but we only want data types, all types, and sorted please. +indices.sgml: Makefile + echo "" >$@ + echo -e "\nList of Types" >>$@ + for ident in $(TYPES) ; do \ + id=`echo $$ident | tr _ -` ; \ + echo "$$ident" >>$@ ; \ + done + for ident in $(ENUMS) ; do \ + echo "enum $$ident" >>$@ ; \ + done + for ident in $(STRUCTS) ; do \ + id=`echo $$ident | tr _ -` ; \ + echo "struct $$ident" >>$@ ; \ + done + echo "" >>$@ + +# HTML version. +html-build.stamp: Makefile $(SGMLS) $(GIFPICS) + rm -rf dvbapi + if which xmlto >/dev/null ; then \ + xmlto xhtml $(WARN) $(CUSTOM_HTML_XMLTO) -o dvbapi dvbapi.sgml ; \ + elif which docbook2html >/dev/null ; then \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl |head -1`"; \ + docbook2html $(WARN) $$DCL $(CUSTOM_HTML) --output dvbapi dvbapi.sgml ; \ + else \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl |head -1`"; \ + db2html $(WARN) $$DCL $(CUSTOM_HTML) --output dvbapi dvbapi.sgml ; \ + fi + cp $(GIFPICS) dvbapi/ + cd dvbapi ; \ + test -e index.html || ln -s book1.htm index.html ; \ + test -e capture-example.html || \ + ln -s `grep -l getopt_long *.htm` capture-example.html + chmod a+rX -R dvbapi + touch html-build.stamp + +# For online version. When you have a dial-up connection a single file +# is more convenient than clicking through dozens of pages. +html-single-build.stamp: Makefile $(SGMLS) $(GIFPICS) + rm -rf dvbapi-single + if which xmlto >/dev/null ; then \ + xmlto html-nochunks $(WARN) $(CUSTOM_HTML_XMLTO) -o dvbapi-single dvbapi.sgml ; \ + elif which docbook2html >/dev/null ; then \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl |head -1`"; \ + docbook2html $$DCL $(WARN) $(CUSTOM_HTML) --nochunks \ + --output dvbapi-single dvbapi.sgml ; \ + else \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl |head -1`"; \ + db2html $$DCL $(WARN) $(CUSTOM_HTML) --nochunks \ + --output dvbapi-single dvbapi.sgml ; \ + fi + cp $(GIFPICS) dvbapi-single/ + chmod a+rX -R dvbapi-single + touch html-single-build.stamp + +# For printing. +pdf-build.stamp: Makefile $(SGMLS) $(PDFPICS) + if which db2pdf >/dev/null ; then \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl|head -1`"; \ + db2pdf $$DCL $(WARN) $(CUSTOM_PRINT) dvbapi.sgml ; \ + elif which xmlto >/dev/null ; then \ + xmlto pdf $(WARN) $(CUSTOM_HTML_XMLTO) -o dvbapi-single dvbapi.sgml ; \ + else \ + export DCL="--dcl `find /usr/share/sgml -name xml.dcl |head -1`"; \ + docbook2pdf $$DCL $(WARN) $(CUSTOM_PRINT) dvbapi.sgml ; \ + fi + touch pdf-build.stamp + + +# For man +man-build.stamp: Makefile $(SGMLS) $(PDFPICS) + xmlto man $(WARN) $(CUSTOM_HTML_XMLTO) -o man dvbapi.sgml + +distclean clean: + rm -f *.stamp + rm -f indices.sgml entities.sgml diff --git a/dvb-spec/sgml/README b/dvb-spec/sgml/README new file mode 100644 index 000000000..99dd5fef3 --- /dev/null +++ b/dvb-spec/sgml/README @@ -0,0 +1,13 @@ +This directory doesn't contain the official DVB API + +It contains an effort of porting it from LaTex to Docbook XML 4.1.2 + +It is still a work undergoing. Contributions are welcome. + +CURRENT STATUS: + +Chapters 1 and 2 were converted. The remaining chapters aren't yet. + +File dvbapi-complete.sgml is a temporary file generated by a tool that +automatically do the conversion. While it doesn't compile, it is a good +starting point for the conversion. diff --git a/dvb-spec/sgml/custom.dsl b/dvb-spec/sgml/custom.dsl new file mode 100644 index 000000000..12a5e91d4 --- /dev/null +++ b/dvb-spec/sgml/custom.dsl @@ -0,0 +1,52 @@ + + + +]]> + + +]]> +]> + + + + + + + +(define %generate-reference-toc% #t) +(define %refentry-new-page% #t) +(define %number-programlisting-lines% #f) +(define %section-autolabel% #t) +(define bop-footnotes #t) + +(define ($generate-book-lot-list$) + (list (normalize "figure") + (normalize "example"))) + +(define %paper-type% "A4") + + + + + + + + +(define %generate-reference-toc% #t) +(define %number-programlisting-lines% #f) +(define %section-autolabel% #t) +(define bop-footnotes #t) + +(define ($generate-book-lot-list$) + (list (normalize "figure") + (normalize "example"))) + + + + + + + diff --git a/dvb-spec/sgml/custom.xsl b/dvb-spec/sgml/custom.xsl new file mode 100644 index 000000000..e1556c37c --- /dev/null +++ b/dvb-spec/sgml/custom.xsl @@ -0,0 +1,29 @@ + + + + + + + +1 +0 +0 +0 + +1 + +1 +1 +1 + +ansi +80 +1 + +1 +1 +1 +3 + +A4 + diff --git a/dvb-spec/sgml/devices.sgml b/dvb-spec/sgml/devices.sgml new file mode 100644 index 000000000..e69de29bb diff --git a/dvb-spec/sgml/dvbapi-complete.sgml b/dvb-spec/sgml/dvbapi-complete.sgml new file mode 100644 index 000000000..56edcf023 --- /dev/null +++ b/dvb-spec/sgml/dvbapi-complete.sgml @@ -0,0 +1,9878 @@ + +%docbook.dtd; +] > + + +
+ + +LINUX DVB API Version 3 + + + Copyright 2002, 2003 Convergence GmbH + Written by Dr. Ralph J.K. Metzler + <rjkm@metzlerbros.de> + and Dr. Marcus O.C. Metzler + <mocm@metzlerbros.de> + + +24/07/2003 +V 1.0.0 + +Permission is granted to copy, distribute and/or modify this document under the terms of +the GNU Free Documentation License, Version 1.1 or any later version published by the Free +Software Foundation. A copy of the license is included in the chapter entitled ”GNU Free +Documentation License”. + + + + +
Contents + + + + + +
Introduction +
<abbrev role="title-mark">1.1</abbrev>What you need to know +The reader of this document is required to have some knowledge in the area of digital +video broadcasting (DVB) and should be familiar with part I of the MPEG2 specification +ISO/IEC 13818 (aka ITU-T H.222), i.e you should know what a program/transport +stream (PS/TS) is and what is meant by a packetized elementary stream (PES) or an +I-frame. + +Various DVB standards documents are available from http://www.dvb.org/ and/or +http://www.etsi.org/. + +It is also necessary to know how to access unix/linux devices and how to use ioctl calls. +This also includes the knowledge of C or C++. + + +
<abbrev role="title-mark">1.2</abbrev>History +The first API for DVB cards we used at Convergence in late 1999 was an extension of the +Video4Linux API which was primarily developed for frame grabber cards. As such it +was not really well suited to be used for DVB cards and their new features like +recording MPEG streams and filtering several section and PES data streams at the same +time. + +In early 2000, we were approached by Nokia with a proposal for a new standard Linux +DVB API. As a commitment to the development of terminals based on open standards, Nokia +and Convergence made it available to all Linux developers and published it on +http://www.linuxtv.org/ in September 2000. Convergence is the maintainer of the +Linux DVB API. Together with the LinuxTV community (i.e. you, the reader of this +document), the Linux DVB API will be constantly reviewed and improved. With the Linux +driver for the Siemens/Hauppauge DVB PCI card Convergence provides a first +implementation of the Linux DVB API. + + +
<abbrev role="title-mark">1.3</abbrev>Overview +
<blockquote> +<section role="center"><title/> +<para><graphic width="306.14374pt" fileref="dvbstb.ps" ></graphic> +<blockquote role="caption"><title role="caption">Figure 1.1 +Components of a DVB card/STB +
+ +A DVB PCI card or DVB set-top-box (STB) usually consists of the following main +hardware components: + + + +Frontend consisting of tuner and DVB demodulator + +Here the raw signal reaches the DVB hardware from a satellite dish or antenna + or directly from cable. The frontend down-converts and demodulates this signal + into an MPEG transport stream (TS). In case of a satellite frontend, this includes + a facility for satellite equipment control (SEC), which allows control of LNB + polarization, multi feed switches or dish rotors. + + + +Conditional Access (CA) hardware like CI adapters and smartcard slots + +The complete TS is passed through the CA hardware. Programs to which the user + has access (controlled by the smart card) are decoded in real time and re-inserted + into the TS. + + + +Demultiplexer which filters the incoming DVB stream + +The demultiplexer splits the TS into its components like audio and video streams. + Besides usually several of such audio and video streams it also contains data + streams with information about the programs offered in this or other streams of + the same provider. + + + +MPEG2 audio and video decoder + +The main targets of the demultiplexer are the MPEG2 audio and video decoders. + After decoding they pass on the uncompressed audio and video to the computer + screen or (through a PAL/NTSC encoder) to a TV set. +Figure ?? shows a crude schematic of the control and data flow between those +components. + +On a DVB PCI card not all of these have to be present since some functionality can be +provided by the main CPU of the PC (e.g. MPEG picture and sound decoding) or is not +needed (e.g. for data-only uses like “internet over satellite”). Also not every card or STB +provides conditional access hardware. + +
<abbrev role="title-mark">1.4</abbrev>Linux DVB Devices +The Linux DVB API lets you control these hardware components through currently six +Unix-style character devices for video, audio, frontend, demux, CA and IP-over-DVB +networking. The video and audio devices control the MPEG2 decoder hardware, the frontend +device the tuner and the DVB demodulator. The demux device gives you control over the PES +and section filters of the hardware. If the hardware does not support filtering these filters can +be implemented in software. Finally, the CA device controls all the conditional access +capabilities of the hardware. It can depend on the individual security requirements of the +platform, if and how many of the CA functions are made available to the application through +this device. + +All devices can be found in the /dev tree under /dev/dvb. The individual devices are +called + + + +/dev/dvb/adapterN/audioM, + + + +/dev/dvb/adapterN/videoM, + + + +/dev/dvb/adapterN/frontendM, + + + +/dev/dvb/adapterN/netM, + + + +/dev/dvb/adapterN/demuxM, + + + +/dev/dvb/adapterN/caM, +where N enumerates the DVB PCI cards in a system starting from 0, and M enumerates the +devices of each type within each adapter, starting from 0, too. We will omit the +“/dev/dvb/adapterN/” in the further dicussion of these devices. The naming scheme +for the devices is the same wheter devfs is used or not. + +More details about the data structures and function calls of all the devices are described in +the following chapters. + + +
<abbrev role="title-mark">1.5</abbrev>API include files +For each of the DVB devices a corresponding include file exists. The DVB API include +files should be included in application sources with a partial path like: + + + #include <linux/dvb/frontend.h> + +To enable applications to support different API version, an additional include file +linux/dvb/version.h exists, which defines the constant DVB_API_VERSION. This +document describes DVB_API_VERSION 3. + + +
DVB Frontend API +The DVB frontend device controls the tuner and DVB demodulator hardware. It can be +accessed through /dev/dvb/adapter0/frontend0. Data types and and ioctl +definitions can be accessed by including linux/dvb/frontend.h in your +application. + +DVB frontends come in three varieties: DVB-S (satellite), DVB-C (cable) and DVB-T +(terrestrial). Transmission via the internet (DVB-IP) is not yet handled by this API but a +future extension is possible. For DVB-S the frontend device also supports satellite equipment +control (SEC) via DiSEqC and V-SEC protocols. The DiSEqC (digital SEC) specification is +available from Eutelsat http://www.eutelsat.org/. + +Note that the DVB API may also be used for MPEG decoder-only PCI cards, in which +case there exists no frontend device. + +
<abbrev role="title-mark">2.1</abbrev>Frontend Data Types + +
<abbrev role="title-mark">2.1.1</abbrev>frontend type +For historical reasons frontend types are named after the type of modulation used in +transmission. + + + typedef enum fe_type { + FE_QPSK, /⋆ DVB-S ⋆/ + FE_QAM, /⋆ DVB-C ⋆/ + FE_OFDM /⋆ DVB-T ⋆/ + } fe_type_t; + + +
<abbrev role="title-mark">2.1.2</abbrev>frontend capabilities +Capabilities describe what a frontend can do. Some capabilities can only be supported for +a specific frontend type. + + + typedef enum fe_caps { + FE_IS_STUPID = 0, + FE_CAN_INVERSION_AUTO = 0x1, + FE_CAN_FEC_1_2 = 0x2, + FE_CAN_FEC_2_3 = 0x4, + FE_CAN_FEC_3_4 = 0x8, + FE_CAN_FEC_4_5 = 0x10, + FE_CAN_FEC_5_6 = 0x20, + FE_CAN_FEC_6_7 = 0x40, + FE_CAN_FEC_7_8 = 0x80, + FE_CAN_FEC_8_9 = 0x100, + FE_CAN_FEC_AUTO = 0x200, + FE_CAN_QPSK = 0x400, + FE_CAN_QAM_16 = 0x800, + FE_CAN_QAM_32 = 0x1000, + FE_CAN_QAM_64 = 0x2000, + FE_CAN_QAM_128 = 0x4000, + FE_CAN_QAM_256 = 0x8000, + FE_CAN_QAM_AUTO = 0x10000, + FE_CAN_TRANSMISSION_MODE_AUTO = 0x20000, + FE_CAN_BANDWIDTH_AUTO = 0x40000, + FE_CAN_GUARD_INTERVAL_AUTO = 0x80000, + FE_CAN_HIERARCHY_AUTO = 0x100000, + FE_CAN_MUTE_TS = 0x80000000, + FE_CAN_CLEAN_SETUP = 0x40000000 + } fe_caps_t; + + +
<abbrev role="title-mark">2.1.3</abbrev>frontend information +Information about the frontend ca be queried with FE_GET_INFO (??). + + + struct dvb_frontend_info { + char name[128]; + fe_type_t type; + uint32_t frequency_min; + uint32_t frequency_max; + uint32_t frequency_stepsize; + uint32_t frequency_tolerance; + uint32_t symbol_rate_min; + uint32_t symbol_rate_max; + uint32_t symbol_rate_tolerance; /⋆ ppm ⋆/ + uint32_t notifier_delay; /⋆ ms ⋆/ + fe_caps_t caps; + }; + + +
<abbrev role="title-mark">2.1.4</abbrev>diseqc master command +A message sent from the frontend to DiSEqC capable equipment. + + + struct dvb_diseqc_master_cmd { + uint8_t msg [6]; /⋆ { framing, address, command, data[3] } ⋆/ + uint8_t msg_len; /⋆ valid values are 3...6 ⋆/ + }; + + +
<abbrev role="title-mark">2.1.5</abbrev>diseqc slave reply +A reply to the frontend from DiSEqC 2.0 capable equipment. + + + struct dvb_diseqc_slave_reply { + uint8_t msg [4]; /⋆ { framing, data [3] } ⋆/ + uint8_t msg_len; /⋆ valid values are 0...4, 0 means no msg ⋆/ + int timeout; /⋆ return from ioctl after timeout ms with ⋆/ + }; /⋆ errorcode when no message was received ⋆/ + + +
<abbrev role="title-mark">2.1.6</abbrev>SEC voltage +The voltage is usually used with non-DiSEqC capable LNBs to switch the polarzation +(horizontal/vertical). When using DiSEqC epuipment this voltage has to be switched +consistently to the DiSEqC commands as described in the DiSEqC spec. + + + typedef enum fe_sec_voltage { + SEC_VOLTAGE_13, + SEC_VOLTAGE_18 + } fe_sec_voltage_t; + + +
<abbrev role="title-mark">2.1.7</abbrev>SEC continuous tone +The continous 22KHz tone is usually used with non-DiSEqC capable LNBs to switch the +high/low band of a dual-band LNB. When using DiSEqC epuipment this voltage has to +be switched consistently to the DiSEqC commands as described in the DiSEqC +spec. + + + typedef enum fe_sec_tone_mode { + SEC_TONE_ON, + SEC_TONE_OFF + } fe_sec_tone_mode_t; + + +
<abbrev role="title-mark">2.1.8</abbrev>SEC tone burst +The 22KHz tone burst is usually used with non-DiSEqC capable switches to select +between two connected LNBs/satellites. When using DiSEqC epuipment this voltage has to +be switched consistently to the DiSEqC commands as described in the DiSEqC +spec. + + + typedef enum fe_sec_mini_cmd { + SEC_MINI_A, + SEC_MINI_B + } fe_sec_mini_cmd_t; + + +
<abbrev role="title-mark">2.1.9</abbrev>frontend status +Several functions of the frontend device use the fe_status data type defined +by + + + typedef enum fe_status { + FE_HAS_SIGNAL = 0x01, /⋆ found something above the noise level ⋆/ + FE_HAS_CARRIER = 0x02, /⋆ found a DVB signal ⋆/ + FE_HAS_VITERBI = 0x04, /⋆ FEC is stable ⋆/ + FE_HAS_SYNC = 0x08, /⋆ found sync bytes ⋆/ + FE_HAS_LOCK = 0x10, /⋆ everything's working... ⋆/ + FE_TIMEDOUT = 0x20, /⋆ no lock within the last ~2 seconds ⋆/ + FE_REINIT = 0x40 /⋆ frontend was reinitialized, ⋆/ + } fe_status_t; /⋆ application is recommned to reset ⋆/ + +to indicate the current state and/or state changes of the frontend hardware. + + +
<abbrev role="title-mark">2.1.10</abbrev>frontend parameters +The kind of parameters passed to the frontend device for tuning depend on the kind of +hardware you are using. All kinds of parameters are combined as a union in the +FrontendParameters structure: + + + struct dvb_frontend_parameters { + uint32_t frequency; /⋆ (absolute) frequency in Hz for QAM/OFDM ⋆/ + /⋆ intermediate frequency in kHz for QPSK ⋆/ + fe_spectral_inversion_t inversion; + union { + struct dvb_qpsk_parameters qpsk; + struct dvb_qam_parameters qam; + struct dvb_ofdm_parameters ofdm; + } u; + }; + +For satellite QPSK frontends you have to use the QPSKParameters member defined +by + + + struct dvb_qpsk_parameters { + uint32_t symbol_rate; /⋆ symbol rate in Symbols per second ⋆/ + fe_code_rate_t fec_inner; /⋆ forward error correction (see above) ⋆/ + }; + +for cable QAM frontend you use the QAMParameters structure + + + struct dvb_qam_parameters { + uint32_t symbol_rate; /⋆ symbol rate in Symbols per second ⋆/ + fe_code_rate_t fec_inner; /⋆ forward error correction (see above) ⋆/ + fe_modulation_t modulation; /⋆ modulation type (see above) ⋆/ + }; + +DVB-T frontends are supported by the OFDMParamters structure + + + struct dvb_ofdm_parameters { + fe_bandwidth_t bandwidth; + fe_code_rate_t code_rate_HP; /⋆ high priority stream code rate ⋆/ + fe_code_rate_t code_rate_LP; /⋆ low priority stream code rate ⋆/ + fe_modulation_t constellation; /⋆ modulation type (see above) ⋆/ + fe_transmit_mode_t transmission_mode; + fe_guard_interval_t guard_interval; + fe_hierarchy_t hierarchy_information; + }; + +In the case of QPSK frontends the Frequency field specifies the intermediate +frequency, i.e. the offset which is effectively added to the local oscillator frequency (LOF) of +the LNB. The intermediate frequency has to be specified in units of kHz. For QAM and +OFDM frontends the Frequency specifies the absolute frequency and is given in +Hz. + +The Inversion field can take one of these values: + + + typedef enum fe_spectral_inversion { + INVERSION_OFF, + INVERSION_ON, + INVERSION_AUTO + } fe_spectral_inversion_t; + +It indicates if spectral inversion should be presumed or not. In the automatic setting +(INVERSION_AUTO) the hardware will try to figure out the correct setting by +itself. + +The possible values for the FEC_inner field are + + + typedef enum fe_code_rate { + FEC_NONE = 0, + FEC_1_2, + FEC_2_3, + FEC_3_4, + FEC_4_5, + FEC_5_6, + FEC_6_7, + FEC_7_8, + FEC_8_9, + FEC_AUTO + } fe_code_rate_t; + +which correspond to error correction rates of 1/2, 2/3, etc., no error correction or auto +detection. + +For cable and terrestrial frontends (QAM and OFDM) one also has to specify the quadrature +modulation mode which can be one of the following: + + + typedef enum fe_modulation { + QPSK, + QAM_16, + QAM_32, + QAM_64, + QAM_128, + QAM_256, + QAM_AUTO + } fe_modulation_t; + +Finally, there are several more parameters for OFDM: + + + typedef enum fe_transmit_mode { + TRANSMISSION_MODE_2K, + TRANSMISSION_MODE_8K, + TRANSMISSION_MODE_AUTO + } fe_transmit_mode_t; + + + typedef enum fe_bandwidth { + BANDWIDTH_8_MHZ, + BANDWIDTH_7_MHZ, + BANDWIDTH_6_MHZ, + BANDWIDTH_AUTO + } fe_bandwidth_t; + + + typedef enum fe_guard_interval { + GUARD_INTERVAL_1_32, + GUARD_INTERVAL_1_16, + GUARD_INTERVAL_1_8, + GUARD_INTERVAL_1_4, + GUARD_INTERVAL_AUTO + } fe_guard_interval_t; + + + typedef enum fe_hierarchy { + HIERARCHY_NONE, + HIERARCHY_1, + HIERARCHY_2, + HIERARCHY_4, + HIERARCHY_AUTO + } fe_hierarchy_t; + + +
<abbrev role="title-mark">2.1.11</abbrev>frontend events + + struct dvb_frontend_event { + fe_status_t status; + struct dvb_frontend_parameters parameters; + }; + +
<abbrev role="title-mark">2.2</abbrev>Frontend Function Calls + +
<abbrev role="title-mark">2.2.1</abbrev>open() +DESCRIPTION + +
+This system call opens a named frontend device (/dev/dvb/adapter0/frontend0) + for subsequent use. Usually the first thing to do after a successful open is to + find out the frontend type with FE_GET_INFO. +The device can be opened in read-only mode, which only allows monitoring of + device status and statistics, or read/write mode, which allows any kind of use + (e.g. performing tuning operations.) + +In a system with multiple front-ends, it is usually the case that multiple devices + cannot be open in read/write mode simultaneously. As long as a front-end + device is opened in read/write mode, other open() calls in read/write mode will + either fail or block, depending on whether non-blocking or blocking mode was + specified. A front-end device opened in blocking mode can later be put into + non-blocking mode (and vice versa) using the F_SETFL command of the fcntl + system call. This is a standard system call, documented in the Linux manual + page for fcntl. When an open() call has succeeded, the device will be ready + for use in the specified mode. This implies that the corresponding hardware is + powered up, and that other front-ends may have been powered down to make + that possible. + + + +SYNOPSIS + + +int open(const char ⋆deviceName, int flags); + + +PARAMETERS + + +const char + *deviceName + +Name of specific video device. + + +int flags + +A bit-wise OR of the following flags: + + + +O_RDONLY read-only access + + + +O_RDWR read/write access + + + +O_NONBLOCK open in non-blocking mode + + + +(blocking mode is the default) + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EINTERNAL + +Internal error. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + + + + +
<abbrev role="title-mark">2.2.2</abbrev>close() +DESCRIPTION + +
+This system call closes a previously opened front-end device. After closing + a front-end device, its corresponding hardware might be powered down + automatically. + + +SYNOPSIS + + +int close(int fd); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + + + + +
<abbrev role="title-mark">2.2.3</abbrev>FE_READ_STATUS<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call returns status information about the front-end. This call only + requires read-only access to the device. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_READ_STATUS, + fe_status_t ⋆status); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_READ_STATUS for this command. + + +struct fe_status_t + *status + +Points to the location where the front-end status word is + to be stored. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +status points to invalid address. + + + + + +
<abbrev role="title-mark">2.2.4</abbrev>FE_READ_BER<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call returns the bit error rate for the signal currently + received/demodulated by the front-end. For this command, read-only access to + the device is sufficient. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_READ_BER, + uint32_t ⋆ber); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_READ_BER for this command. + + +uint32_t *ber + +The bit error rate is stored into *ber. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +ber points to invalid address. + + +ENOSIGNAL + +There is no signal, thus no meaningful bit error rate. Also + returned if the front-end is not turned on. + + +ENOSYS + +Function not available for this device. + + + +
<abbrev role="title-mark">2.2.5</abbrev>FE_READ_SNR<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call returns the signal-to-noise ratio for the signal currently received + by the front-end. For this command, read-only access to the device is sufficient. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_READ_SNR, int16_t + ⋆snr); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_READ_SNR for this command. + + +int16_t *snr + +The signal-to-noise ratio is stored into *snr. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +snr points to invalid address. + + +ENOSIGNAL + +There is no signal, thus no meaningful signal strength + value. Also returned if front-end is not turned on. + + +ENOSYS + +Function not available for this device. + + + +
<abbrev role="title-mark">2.2.6</abbrev>FE_READ_SIGNAL_STRENGTH<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call returns the signal strength value for the signal currently received + by the front-end. For this command, read-only access to the device is sufficient. + + +SYNOPSIS + + +int ioctl( int fd, int request = + FE_READ_SIGNAL_STRENGTH, int16_t ⋆strength); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_READ_SIGNAL_STRENGTH for this + command. + + +int16_t *strength + +The signal strength value is stored into *strength. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +status points to invalid address. + + +ENOSIGNAL + +There is no signal, thus no meaningful signal strength + value. Also returned if front-end is not turned on. + + +ENOSYS + +Function not available for this device. + + + +
<abbrev role="title-mark">2.2.7</abbrev>FE_READ_UNCORRECTED_BLOCKS<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call returns the number of uncorrected blocks detected by the device + driver during its lifetime. For meaningful measurements, the increment in block + count during a specific time interval should be calculated. For this command, + read-only access to the device is sufficient. + + +Note that the counter will wrap to zero after its maximum count has been + reached. + + +SYNOPSIS + + +int ioctl( int fd, int request = + FE_READ_UNCORRECTED_BLOCKS, uint32_t ⋆ublocks); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_READ_UNCORRECTED_BLOCKS for this + command. + + +uint32_t *ublocks + +The total number of uncorrected blocks seen by the driver + so far. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +ublocks points to invalid address. + + +ENOSYS + +Function not available for this device. + + + +
<abbrev role="title-mark">2.2.8</abbrev>FE_SET_FRONTEND<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call starts a tuning operation using specified parameters. The result + of this call will be successful if the parameters were valid and the tuning could + be initiated. The result of the tuning operation in itself, however, will arrive + asynchronously as an event (see documentation for FE_GET_EVENT and + FrontendEvent.) If a new FE_SET_FRONTEND operation is initiated before + the previous one was completed, the previous operation will be aborted in favor + of the new one. This command requires read/write access to the device. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_SET_FRONTEND, + struct dvb_frontend_parameters ⋆p); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_SET_FRONTEND for this command. + + +struct + dvb_frontend_parameters + *p + +Points to parameters for tuning operation. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +p points to invalid address. + + +EINVAL + +Maximum supported symbol rate reached. + + + + + +
<abbrev role="title-mark">2.2.9</abbrev>FE_GET_FRONTEND<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call queries the currently effective frontend parameters. For this + command, read-only access to the device is sufficient. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_GET_FRONTEND, + struct dvb_frontend_parameters ⋆p); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_SET_FRONTEND for this command. + + +struct + dvb_frontend_parameters + *p + +Points to parameters for tuning operation. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +p points to invalid address. + + +EINVAL + +Maximum supported symbol rate reached. + + + + + +
<abbrev role="title-mark">2.2.10</abbrev>FE_GET_EVENT<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call returns a frontend event if available. If an event is not + available, the behavior depends on whether the device is in blocking or + non-blocking mode. In the latter case, the call fails immediately with errno + set to EWOULDBLOCK. In the former case, the call blocks until an event + becomes available. + + +The standard Linux poll() and/or select() system calls can be used with the + device file descriptor to watch for new events. For select(), the file descriptor + should be included in the exceptfds argument, and for poll(), POLLPRI should + be specified as the wake-up condition. Since the event queue allocated is + rather small (room for 8 events), the queue must be serviced regularly to avoid + overflow. If an overflow happens, the oldest event is discarded from the queue, + and an error (EOVERFLOW) occurs the next time the queue is read. After + reporting the error condition in this fashion, subsequent FE_GET_EVENT + calls will return events from the queue as usual. + + +For the sake of implementation simplicity, this command requires read/write + access to the device. + + +SYNOPSIS + + +int ioctl(int fd, int request = QPSK_GET_EVENT, + struct dvb_frontend_event ⋆ev); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_GET_EVENT for this command. + + +struct + dvb_frontend_event + *ev + +Points to the location where the event, + + + +if any, is to be stored. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +ev points to invalid address. + + +EWOULDBLOCK + +There is no event pending, and the device is in + non-blocking mode. + + +EOVERFLOW + + + + +Overflow in event queue - one or more events were lost. + + + + + +
<abbrev role="title-mark">2.2.11</abbrev>FE_GET_INFO<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call returns information about the front-end. This call only requires + read-only access to the device. + + +SYNOPSIS + + + int ioctl(int fd, int request = FE_GET_INFO, struct + dvb_frontend_info ⋆info); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_GET_INFO for this command. + + +struct + dvb_frontend_info + *info + +Points to the location where the front-end information is + to be stored. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +info points to invalid address. + + + + + +
<abbrev role="title-mark">2.2.12</abbrev>FE_DISEQC_RESET_OVERLOAD<indexterm role="printindex" /> +DESCRIPTION + +
+If the bus has been automatically powered off due to power overload, this ioctl + call restores the power to the bus. The call requires read/write access to the + device. This call has no effect if the device is manually powered off. Not all + DVB adapters support this ioctl. + + +SYNOPSIS + + +int ioctl(int fd, int request = + FE_DISEQC_RESET_OVERLOAD); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_DISEQC_RESET_OVERLOAD for this + command. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EPERM + +Permission denied (needs read/write access). + + +EINTERNAL + +Internal error in the device driver. + + + + + +
<abbrev role="title-mark">2.2.13</abbrev>FE_DISEQC_SEND_MASTER_CMD<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call is used to send a a DiSEqC command. + + + + +SYNOPSIS + + +int ioctl(int fd, int request = + FE_DISEQC_SEND_MASTER_CMD, struct + dvb_diseqc_master_cmd ⋆cmd); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_DISEQC_SEND_MASTER_CMD for this + command. + + +struct + dvb_diseqc_master_cmd + *cmd + +Pointer to the command to be transmitted. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EFAULT + +Seq points to an invalid address. + + +EINVAL + +The data structure referred to by seq is invalid in some + way. + + +EPERM + +Permission denied (needs read/write access). + + +EINTERNAL + +Internal error in the device driver. + + + + + +
<abbrev role="title-mark">2.2.14</abbrev>FE_DISEQC_RECV_SLAVE_REPLY<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call is used to receive reply to a DiSEqC 2.0 command. + + + + +SYNOPSIS + + +int ioctl(int fd, int request = + FE_DISEQC_RECV_SLAVE_REPLY, struct + dvb_diseqc_slave_reply ⋆reply); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_DISEQC_RECV_SLAVE_REPLY for this + command. + + +struct + dvb_diseqc_slave_reply + *reply + +Pointer to the command to be received. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EFAULT + +Seq points to an invalid address. + + +EINVAL + +The data structure referred to by seq is invalid in some + way. + + +EPERM + +Permission denied (needs read/write access). + + +EINTERNAL + +Internal error in the device driver. + + + + + +
<abbrev role="title-mark">2.2.15</abbrev>FE_DISEQC_SEND_BURST<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call is used to send a 22KHz tone burst. + + + + +SYNOPSIS + + +int ioctl(int fd, int request = + FE_DISEQC_SEND_BURST, fe_sec_mini_cmd_t burst); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_DISEQC_SEND_BURST for this command. + + +fe_sec_mini_cmd_t + burst + +burst A or B. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EFAULT + +Seq points to an invalid address. + + +EINVAL + +The data structure referred to by seq is invalid in some + way. + + +EPERM + +Permission denied (needs read/write access). + + +EINTERNAL + +Internal error in the device driver. + + + + + +
<abbrev role="title-mark">2.2.16</abbrev>FE_SET_TONE<indexterm role="printindex" /> +DESCRIPTION + +
+This call is used to set the generation of the continuous 22kHz tone. This call + requires read/write permissions. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_SET_TONE, + fe_sec_tone_mode_t tone); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_SET_TONE for this command. + + +fe_sec_tone_mode_t + tone + +The requested tone generation mode (on/off). + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + +EPERM + +File not opened with read permissions. + + +EINTERNAL + +Internal error in the device driver. + + + + + +
<abbrev role="title-mark">2.2.17</abbrev>FE_SET_VOLTAGE<indexterm role="printindex" /> +DESCRIPTION + +
+This call is used to set the bus voltage. This call requires read/write + permissions. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_SET_VOLTAGE, + fe_sec_voltage_t voltage); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_SET_VOLTAGE for this command. + + +fe_sec_voltage_t + voltage + +The requested bus voltage. + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + +EPERM + +File not opened with read permissions. + + +EINTERNAL + +Internal error in the device driver. + + + + + +
<abbrev role="title-mark">2.2.18</abbrev>FE_ENABLE_HIGH_LNB_VOLTAGE<indexterm role="printindex" /> +DESCRIPTION + +
+If high != 0 enables slightly higher voltages instead of 13/18V (to compensate + for long cables). This call requires read/write permissions. Not all DVB + adapters support this ioctl. + + +SYNOPSIS + + +int ioctl(int fd, int request = + FE_ENABLE_HIGH_LNB_VOLTAGE, int high); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_SET_VOLTAGE for this command. + + +int high + +The requested bus voltage. + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + +EPERM + +File not opened with read permissions. + + +EINTERNAL + +Internal error in the device driver. + + + + + +
DVB Demux Device +The DVB demux device controls the filters of the DVB hardware/software. It can be +accessed through /dev/adapter0/demux0. Data types and and ioctl definitions can be +accessed by including linux/dvb/dmx.h in your application. + +
<abbrev role="title-mark">3.1</abbrev>Demux Data Types + +
<abbrev role="title-mark">3.1.1</abbrev>dmx_output_t + + typedef enum + { + DMX_OUT_DECODER, + DMX_OUT_TAP, + DMX_OUT_TS_TAP + } dmx_output_t; + +DMX_OUT_TAP delivers the stream output to the demux device on which the ioctl is +called. + +DMX_OUT_TS_TAP routes output to the logical DVR device /dev/dvb/adapter0/dvr0, +which delivers a TS multiplexed from all filters for which DMX_OUT_TS_TAP was +specified. + + +
<abbrev role="title-mark">3.1.2</abbrev>dmx_input_t + + typedef enum + { + DMX_IN_FRONTEND, + DMX_IN_DVR + } dmx_input_t; + + +
<abbrev role="title-mark">3.1.3</abbrev>dmx_pes_type_t + + typedef enum + { + DMX_PES_AUDIO, + DMX_PES_VIDEO, + DMX_PES_TELETEXT, + DMX_PES_SUBTITLE, + DMX_PES_PCR, + DMX_PES_OTHER + } dmx_pes_type_t; + + +
<abbrev role="title-mark">3.1.4</abbrev>dmx_event_t + + typedef enum + { + DMX_SCRAMBLING_EV, + DMX_FRONTEND_EV + } dmx_event_t; + + +
<abbrev role="title-mark">3.1.5</abbrev>dmx_scrambling_status_t + + typedef enum + { + DMX_SCRAMBLING_OFF, + DMX_SCRAMBLING_ON + } dmx_scrambling_status_t; + + +
<abbrev role="title-mark">3.1.6</abbrev>struct dmx_filter + + typedef struct dmx_filter + { + uint8_t filter[DMX_FILTER_SIZE]; + uint8_t mask[DMX_FILTER_SIZE]; + } dmx_filter_t; + + +
<abbrev role="title-mark">3.1.7</abbrev>struct dmx_sct_filter_params + + struct dmx_sct_filter_params + { + uint16_t pid; + dmx_filter_t filter; + uint32_t timeout; + uint32_t flags; + #define DMX_CHECK_CRC 1 + #define DMX_ONESHOT 2 + #define DMX_IMMEDIATE_START 4 + }; + + +
<abbrev role="title-mark">3.1.8</abbrev>struct dmx_pes_filter_params + + struct dmx_pes_filter_params + { + uint16_t pid; + dmx_input_t input; + dmx_output_t output; + dmx_pes_type_t pes_type; + uint32_t flags; + }; + + +
<abbrev role="title-mark">3.1.9</abbrev>struct dmx_event + + struct dmx_event + { + dmx_event_t event; + time_t timeStamp; + union + { + dmx_scrambling_status_t scrambling; + } u; + }; + + +
<abbrev role="title-mark">3.1.10</abbrev>struct dmx_stc + + struct dmx_stc { + unsigned int num; /⋆ input : which STC? 0..N ⋆/ + unsigned int base; /⋆ output: divisor for stc to get 90 kHz clock ⋆/ + uint64_t stc; /⋆ output: stc in 'base'⋆90 kHz units ⋆/ + }; + +
<abbrev role="title-mark">3.2</abbrev>Demux Function Calls + +
<abbrev role="title-mark">3.2.1</abbrev>open() +DESCRIPTION + +
+This system call, used with a device name of /dev/dvb/adapter0/demux0, + allocates a new filter and returns a handle which can be used for subsequent + control of that filter. This call has to be made for each filter to be used, i.e. every + returned file descriptor is a reference to a single filter. /dev/dvb/adapter0/dvr0 + is a logical device to be used for retrieving Transport Streams for digital + video recording. When reading from this device a transport stream containing + the packets from all PES filters set in the corresponding demux device + (/dev/dvb/adapter0/demux0) having the output set to DMX_OUT_TS_TAP. A + recorded Transport Stream is replayed by writing to this device. +The significance of blocking or non-blocking mode is described in the + documentation for functions where there is a difference. It does not affect the + semantics of the open() call itself. A device opened in blocking mode can later + be put into non-blocking mode (and vice versa) using the F_SETFL command + of the fcntl system call. + + + +SYNOPSIS + + +int open(const char ⋆deviceName, int flags); + + +PARAMETERS + + +const char + *deviceName + +Name of demux device. + + +int flags + +A bit-wise OR of the following flags: + + + +O_RDWR read/write access + + + +O_NONBLOCK open in non-blocking mode + + + +(blocking mode is the default) + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EINVAL + +Invalid argument. + + +EMFILE + +“Too many open files”, i.e. no more filters available. + + +ENOMEM + +The driver failed to allocate enough memory. + + + + + +
<abbrev role="title-mark">3.2.2</abbrev>close() +DESCRIPTION + +
+This system call deactivates and deallocates a filter that was previously + allocated via the open() call. + + +SYNOPSIS + + +int close(int fd); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + + + + +
<abbrev role="title-mark">3.2.3</abbrev>read() +DESCRIPTION + +
+This system call returns filtered data, which might be section or PES data. The + filtered data is transferred from the driver’s internal circular buffer to buf. The + maximum amount of data to be transferred is implied by count. + + +When returning section data the driver always tries to return a complete single + section (even though buf would provide buffer space for more data). If the size + of the buffer is smaller than the section as much as possible will be returned, + and the remaining data will be provided in subsequent calls. + + +The size of the internal buffer is 2 * 4096 bytes (the size of two maximum + sized sections) by default. The size of this buffer may be changed by using the + DMX_SET_BUFFER_SIZE function. If the buffer is not large enough, or if + the read operations are not performed fast enough, this may result in a buffer + overflow error. In this case EOVERFLOW will be returned, and the circular + buffer will be emptied. This call is blocking if there is no data to return, i.e. the + process will be put to sleep waiting for data, unless the O_NONBLOCK flag + is specified. + + +Note that in order to be able to read, the filtering process has to be started + by defining either a section or a PES filter by means of the ioctl functions, + and then starting the filtering process via the DMX_START ioctl function + or by setting the DMX_IMMEDIATE_START flag. If the reading is done + from a logical DVR demux device, the data will constitute a Transport Stream + including the packets from all PES filters in the corresponding demux device + /dev/dvb/adapter0/demux0 having the output set to DMX_OUT_TS_TAP. + + +SYNOPSIS + + +size_t read(int fd, void ⋆buf, size_t count); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +void *buf + +Pointer to the buffer to be used for returned filtered data. + + +size_t count + +Size of buf. + + + + +ERRORS + + +EWOULDBLOCK + +No data to return and O_NONBLOCK was specified. + + +EBADF + +fd is not a valid open file descriptor. + + +ECRC + +Last section had a CRC error - no data returned. The + buffer is flushed. + + +EOVERFLOW + + + + +The filtered data was not read from the buffer in due + time, resulting in non-read data being lost. The buffer is + flushed. + + +ETIMEDOUT + +The section was not loaded within the stated timeout + period. See ioctl DMX_SET_FILTER for how to set a + timeout. + + +EFAULT + +The driver failed to write to the callers buffer due to an + invalid *buf pointer. + + + + + +
<abbrev role="title-mark">3.2.4</abbrev>write() +DESCRIPTION + +
+This system call is only provided by the logical device /dev/dvb/adapter0/dvr0, + associated with the physical demux device that provides the actual DVR + functionality. It is used for replay of a digitally recorded Transport Stream. + Matching filters have to be defined in the corresponding physical demux + device, /dev/dvb/adapter0/demux0. The amount of data to be transferred is + implied by count. + + +SYNOPSIS + + +ssize_t write(int fd, const void ⋆buf, size_t + count); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +void *buf + +Pointer to the buffer containing the Transport Stream. + + +size_t count + +Size of buf. + + + + +ERRORS + + +EWOULDBLOCK + +No data was written. This + might happen if O_NONBLOCK was specified and there + is no more buffer space available (if O_NONBLOCK is + not specified the function will block until buffer space is + available). + + +EBUSY + +This error code indicates that there are conflicting + requests. The corresponding demux device is setup to + receive data from the front- end. Make sure that these + filters are stopped and that the filters with input set to + DMX_IN_DVR are started. + + +EBADF + +fd is not a valid open file descriptor. + + + + + +
<abbrev role="title-mark">3.2.5</abbrev>DMX_START<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call is used to start the actual filtering operation defined via the ioctl + calls DMX_SET_FILTER or DMX_SET_PES_FILTER. + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_START); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_START for this command. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EINVAL + +Invalid argument, i.e. no filtering parameters provided via + the DMX_SET_FILTER or DMX_SET_PES_FILTER + functions. + + +EBUSY + +This error code indicates that there are conflicting + requests. There are active filters filtering data from + another input source. Make sure that these filters are + stopped before starting this filter. + + + + + +
<abbrev role="title-mark">3.2.6</abbrev>DMX_STOP<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call is used to stop the actual filtering operation defined via the + ioctl calls DMX_SET_FILTER or DMX_SET_PES_FILTER and started via + the DMX_START command. + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_STOP); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_STOP for this command. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + + + + +
<abbrev role="title-mark">3.2.7</abbrev>DMX_SET_FILTER<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call sets up a filter according to the filter and mask parameters + provided. A timeout may be defined stating number of seconds to wait for a + section to be loaded. A value of 0 means that no timeout should be applied. + Finally there is a flag field where it is possible to state whether a section should + be CRC-checked, whether the filter should be a ”one-shot” filter, i.e. if the + filtering operation should be stopped after the first section is received, and + whether the filtering operation should be started immediately (without waiting + for a DMX_START ioctl call). If a filter was previously set-up, this filter will + be canceled, and the receive buffer will be flushed. + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_SET_FILTER, + struct dmx_sct_filter_params ⋆params); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_SET_FILTER for this command. + + +struct + dmx_sct_filter_params + *params + +Pointer to structure containing filter parameters. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EINVAL + +Invalid argument. + + + + + +
<abbrev role="title-mark">3.2.8</abbrev>DMX_SET_PES_FILTER<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call sets up a PES filter according to the parameters provided. By a + PES filter is meant a filter that is based just on the packet identifier (PID), i.e. + no PES header or payload filtering capability is supported. + + +The transport stream destination for the filtered output may be set. Also the + PES type may be stated in order to be able to e.g. direct a video stream directly + to the video decoder. Finally there is a flag field where it is possible to state + whether the filtering operation should be started immediately (without waiting + for a DMX_START ioctl call). If a filter was previously set-up, this filter will + be cancelled, and the receive buffer will be flushed. + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_SET_PES_FILTER, + struct dmx_pes_filter_params ⋆params); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_SET_PES_FILTER for this command. + + +struct + dmx_pes_filter_params + *params + +Pointer to structure containing filter parameters. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EINVAL + +Invalid argument. + + +EBUSY + +This error code indicates that there are conflicting + requests. There are active filters filtering data from + another input source. Make sure that these filters are + stopped before starting this filter. + + + + + +
<abbrev role="title-mark">3.2.9</abbrev>DMX_SET_BUFFER_SIZE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call is used to set the size of the circular buffer used for filtered data. + The default size is two maximum sized sections, i.e. if this function is not called + a buffer size of 2 * 4096 bytes will be used. + + +SYNOPSIS + + +int ioctl( int fd, int request = + DMX_SET_BUFFER_SIZE, unsigned long size); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_SET_BUFFER_SIZE for this command. + + +unsigned long size + +Size of circular buffer. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +ENOMEM + +The driver was not able to allocate a buffer of the + requested size. + + + + + +
<abbrev role="title-mark">3.2.10</abbrev>DMX_GET_EVENT<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call returns an event if available. If an event is not available, + the behavior depends on whether the device is in blocking or non-blocking + mode. In the latter case, the call fails immediately with errno set to + EWOULDBLOCK. In the former case, the call blocks until an event becomes + available. + + +The standard Linux poll() and/or select() system calls can be used with the + device file descriptor to watch for new events. For select(), the file descriptor + should be included in the exceptfds argument, and for poll(), POLLPRI should + be specified as the wake-up condition. Only the latest event for each filter is + saved. + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_GET_EVENT, + struct dmx_event ⋆ev); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_GET_EVENT for this command. + + +struct dmx_event *ev + +Pointer to the location where the event is to be stored. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EFAULT + +ev points to an invalid address. + + +EWOULDBLOCK + +There is no event pending, and the device is in + non-blocking mode. + + + + + +
<abbrev role="title-mark">3.2.11</abbrev>DMX_GET_STC<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call returns the current value of the system time counter (which is driven + by a PES filter of type DMX_PES_PCR). Some hardware supports more than one + STC, so you must specify which one by setting the num field of stc before the ioctl + (range 0...n). The result is returned in form of a ratio with a 64 bit numerator + and a 32 bit denominator, so the real 90kHz STC value is stc->stc / + stc->base + . + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_GET_STC, struct + dmx_stc ⋆stc); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_GET_STC for this command. + + +struct dmx_stc *stc + +Pointer to the location where the stc is to be stored. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EFAULT + +stc points to an invalid address. + + +EINVAL + +Invalid stc number. + + + + +
DVB Video Device +The DVB video device controls the MPEG2 video decoder of the DVB hardware. It +can be accessed through /dev/dvb/adapter0/video0. Data types and and +ioctl definitions can be accessed by including linux/dvb/video.h in your +application. + +Note that the DVB video device only controls decoding of the MPEG video stream, not +its presentation on the TV or computer screen. On PCs this is typically handled by an +associated video4linux device, e.g. /dev/video, which allows scaling and defining output +windows. + +Some DVB cards don’t have their own MPEG decoder, which results in the omission of +the audio and video device as well as the video4linux device. + +The ioctls that deal with SPUs (sub picture units) and navigation packets are only +supported on some MPEG decoders made for DVD playback. + +
<abbrev role="title-mark">4.1</abbrev>Video Data Types + +
<abbrev role="title-mark">4.1.1</abbrev>video_format_t +The video_format_t data type defined by + + + typedef enum { + VIDEO_FORMAT_4_3, + VIDEO_FORMAT_16_9 + } video_format_t; + +is used in the VIDEO_SET_FORMAT function (??) to tell the driver which aspect ratio +the output hardware (e.g. TV) has. It is also used in the data structures video_status +(??) returned by VIDEO_GET_STATUS (??) and video_event (??) returned by +VIDEO_GET_EVENT (??) which report about the display format of the current video +stream. + + +
<abbrev role="title-mark">4.1.2</abbrev>video_display_format_t +In case the display format of the video stream and of the display hardware differ the +application has to specify how to handle the cropping of the picture. This can be done using +the VIDEO_SET_DISPLAY_FORMAT call (??) which accepts + + + typedef enum { + VIDEO_PAN_SCAN, + VIDEO_LETTER_BOX, + VIDEO_CENTER_CUT_OUT + } video_display_format_t; + +as argument. + + +
<abbrev role="title-mark">4.1.3</abbrev>video stream source +The video stream source is set through the VIDEO_SELECT_SOURCE call and can take +the following values, depending on whether we are replaying from an internal (demuxer) or +external (user write) source. + + + typedef enum { + VIDEO_SOURCE_DEMUX, + VIDEO_SOURCE_MEMORY + } video_stream_source_t; + +VIDEO_SOURCE_DEMUX selects the demultiplexer (fed either by the frontend or the +DVR device) as the source of the video stream. If VIDEO_SOURCE_MEMORY +is selected the stream comes from the application through the write() system +call. + + +
<abbrev role="title-mark">4.1.4</abbrev>video play state +The following values can be returned by the VIDEO_GET_STATUS call representing the +state of video playback. + + + typedef enum { + VIDEO_STOPPED, + VIDEO_PLAYING, + VIDEO_FREEZED + } video_play_state_t; + + +
<abbrev role="title-mark">4.1.5</abbrev>struct video_event +The following is the structure of a video event as it is returned by the VIDEO_GET_EVENT +call. + + + struct video_event { + int32_t type; + time_t timestamp; + union { + video_format_t video_format; + } u; + }; + + +
<abbrev role="title-mark">4.1.6</abbrev>struct video_status +The VIDEO_GET_STATUS call returns the following structure informing about various +states of the playback operation. + + + struct video_status { + boolean video_blank; + video_play_state_t play_state; + video_stream_source_t stream_source; + video_format_t video_format; + video_displayformat_t display_format; + }; + +If video_blank is set video will be blanked out if the channel is changed or if playback is +stopped. Otherwise, the last picture will be displayed. play_state indicates if the video is +currently frozen, stopped, or being played back. The stream_source corresponds to the seleted +source for the video stream. It can come either from the demultiplexer or from memory. +The video_format indicates the aspect ratio (one of 4:3 or 16:9) of the currently +played video stream. Finally, display_format corresponds to the selected cropping +mode in case the source video format is not the same as the format of the output +device. + + +
<abbrev role="title-mark">4.1.7</abbrev>struct video_still_picture +An I-frame displayed via the VIDEO_STILLPICTURE call is passed on within the +following structure. + + + /⋆ pointer to and size of a single iframe in memory ⋆/ + struct video_still_picture { + char ⋆iFrame; + int32_t size; + }; + + +
<abbrev role="title-mark">4.1.8</abbrev>video capabilities +A call to VIDEO_GET_CAPABILITIES returns an unsigned integer with the following +bits set according to the hardwares capabilities. + + + /⋆ bit definitions for capabilities: ⋆/ + /⋆ can the hardware decode MPEG1 and/or MPEG2? ⋆/ + #define VIDEO_CAP_MPEG1 1 + #define VIDEO_CAP_MPEG2 2 + /⋆ can you send a system and/or program stream to video device? + (you still have to open the video and the audio device but only + send the stream to the video device) ⋆/ + #define VIDEO_CAP_SYS 4 + #define VIDEO_CAP_PROG 8 + /⋆ can the driver also handle SPU, NAVI and CSS encoded data? + (CSS API is not present yet) ⋆/ + #define VIDEO_CAP_SPU 16 + #define VIDEO_CAP_NAVI 32 + #define VIDEO_CAP_CSS 64 + + +
<abbrev role="title-mark">4.1.9</abbrev>video system +A call to VIDEO_SET_SYSTEM sets the desired video system for TV output. The +following system types can be set: + + + typedef enum { + VIDEO_SYSTEM_PAL, + VIDEO_SYSTEM_NTSC, + VIDEO_SYSTEM_PALN, + VIDEO_SYSTEM_PALNc, + VIDEO_SYSTEM_PALM, + VIDEO_SYSTEM_NTSC60, + VIDEO_SYSTEM_PAL60, + VIDEO_SYSTEM_PALM60 + } video_system_t; + + +
<abbrev role="title-mark">4.1.10</abbrev>struct video_highlight +Calling the ioctl VIDEO_SET_HIGHLIGHTS posts the SPU highlight information. The +call expects the following format for that information: + + + typedef + struct video_highlight { + boolean active; /⋆ 1=show highlight, 0=hide highlight ⋆/ + uint8_t contrast1; /⋆ 7- 4 Pattern pixel contrast ⋆/ + /⋆ 3- 0 Background pixel contrast ⋆/ + uint8_t contrast2; /⋆ 7- 4 Emphasis pixel-2 contrast ⋆/ + /⋆ 3- 0 Emphasis pixel-1 contrast ⋆/ + uint8_t color1; /⋆ 7- 4 Pattern pixel color ⋆/ + /⋆ 3- 0 Background pixel color ⋆/ + uint8_t color2; /⋆ 7- 4 Emphasis pixel-2 color ⋆/ + /⋆ 3- 0 Emphasis pixel-1 color ⋆/ + uint32_t ypos; /⋆ 23-22 auto action mode ⋆/ + /⋆ 21-12 start y ⋆/ + /⋆ 9- 0 end y ⋆/ + uint32_t xpos; /⋆ 23-22 button color number ⋆/ + /⋆ 21-12 start x ⋆/ + /⋆ 9- 0 end x ⋆/ + } video_highlight_t; + + +
<abbrev role="title-mark">4.1.11</abbrev>video SPU +Calling VIDEO_SET_SPU deactivates or activates SPU decoding, according to the +following format: + + + typedef + struct video_spu { + boolean active; + int stream_id; + } video_spu_t; + + +
<abbrev role="title-mark">4.1.12</abbrev>video SPU palette +The following structure is used to set the SPU palette by calling VIDEO_SPU_PALETTE: + + + typedef + struct video_spu_palette{ + int length; + uint8_t ⋆palette; + } video_spu_palette_t; + + +
<abbrev role="title-mark">4.1.13</abbrev>video NAVI pack +In order to get the navigational data the following structure has to be passed to the ioctl +VIDEO_GET_NAVI: + + + typedef + struct video_navi_pack{ + int length; /⋆ 0 ... 1024 ⋆/ + uint8_t data[1024]; + } video_navi_pack_t; + + +
<abbrev role="title-mark">4.1.14</abbrev>video attributes +The following attributes can be set by a call to VIDEO_SET_ATTRIBUTES: + + + typedef uint16_t video_attributes_t; + /⋆ bits: descr. ⋆/ + /⋆ 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) ⋆/ + /⋆ 13-12 TV system (0=525/60, 1=625/50) ⋆/ + /⋆ 11-10 Aspect ratio (0=4:3, 3=16:9) ⋆/ + /⋆ 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca ⋆/ + /⋆ 7 line 21-1 data present in GOP (1=yes, 0=no) ⋆/ + /⋆ 6 line 21-2 data present in GOP (1=yes, 0=no) ⋆/ + /⋆ 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 ⋆/ + /⋆ 2 source letterboxed (1=yes, 0=no) ⋆/ + /⋆ 0 film/camera mode (0=camera, 1=film (625/50 only)) ⋆/ + +
<abbrev role="title-mark">4.2</abbrev>Video Function Calls + +
<abbrev role="title-mark">4.2.1</abbrev>open() +DESCRIPTION + +
+This system call opens a named video device (e.g. /dev/dvb/adapter0/video0) + for subsequent use. +When an open() call has succeeded, the device will be ready for use. + The significance of blocking or non-blocking mode is described in the + documentation for functions where there is a difference. It does not affect the + semantics of the open() call itself. A device opened in blocking mode can later + be put into non-blocking mode (and vice versa) using the F_SETFL command + of the fcntl system call. This is a standard system call, documented in the Linux + manual page for fcntl. Only one user can open the Video Device in O_RDWR + mode. All other attempts to open the device in this mode will fail, and an + error-code will be returned. If the Video Device is opened in O_RDONLY + mode, the only ioctl call that can be used is VIDEO_GET_STATUS. All other + call will return an error code. + + + +SYNOPSIS + + +int open(const char ⋆deviceName, int flags); + + +PARAMETERS + + +const char + *deviceName + +Name of specific video device. + + +int flags + +A bit-wise OR of the following flags: + + + +O_RDONLY read-only access + + + +O_RDWR read/write access + + + +O_NONBLOCK open in non-blocking mode + + + +(blocking mode is the default) + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EINTERNAL + +Internal error. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + + + + +
<abbrev role="title-mark">4.2.2</abbrev>close() +DESCRIPTION + +
+This system call closes a previously opened video device. + + +SYNOPSIS + + +int close(int fd); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + + + + +
<abbrev role="title-mark">4.2.3</abbrev>write() +DESCRIPTION + +
+This system call can only be used if VIDEO_SOURCE_MEMORY is selected + in the ioctl call VIDEO_SELECT_SOURCE. The data provided shall be in + PES format, unless the capability allows other formats. If O_NONBLOCK is + not specified the function will block until buffer space is available. The amount + of data to be transferred is implied by count. + + +SYNOPSIS + + +size_t write(int fd, const void ⋆buf, size_t count); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +void *buf + +Pointer to the buffer containing the PES data. + + +size_t count + +Size of buf. + + + + +ERRORS + + +EPERM + +Mode VIDEO_SOURCE_MEMORY not selected. + + +ENOMEM + +Attempted to write more data than the internal buffer can + hold. + + +EBADF + +fd is not a valid open file descriptor. + + + + + +
<abbrev role="title-mark">4.2.4</abbrev>VIDEO_STOP<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Video Device to stop playing the current stream. + Depending on the input parameter, the screen can be blanked out or displaying + the last decoded frame. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_STOP, boolean + mode); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_STOP for this command. + + +Boolean mode + +Indicates how the screen shall be handled. + + + +TRUE: Blank screen when stop. + + + +FALSE: Show last decoded frame. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + + + + +
<abbrev role="title-mark">4.2.5</abbrev>VIDEO_PLAY<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Video Device to start playing a video stream from the + selected source. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_PLAY); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_PLAY for this command. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + + + + +
<abbrev role="title-mark">4.2.6</abbrev>VIDEO_FREEZE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call suspends the live video stream being played. Decoding + and playing are frozen. It is then possible to restart the decoding + and playing process of the video stream using the VIDEO_CONTINUE + command. If VIDEO_SOURCE_MEMORY is selected in the ioctl call + VIDEO_SELECT_SOURCE, the DVB subsystem will not decode any more + data until the ioctl call VIDEO_CONTINUE or VIDEO_PLAY is performed. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_FREEZE); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_FREEZE for this command. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + + + + +
<abbrev role="title-mark">4.2.7</abbrev>VIDEO_CONTINUE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call restarts decoding and playing processes of the video stream + which was played before a call to VIDEO_FREEZE was made. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_CONTINUE); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_CONTINUE for this command. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + + + + +
<abbrev role="title-mark">4.2.8</abbrev>VIDEO_SELECT_SOURCE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call informs the video device which source shall be used for the input + data. The possible sources are demux or memory. If memory is selected, the + data is fed to the video device through the write command. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_SELECT_SOURCE, + video_stream_source_t source); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SELECT_SOURCE for this command. + + +video_stream_source_t + source + +Indicates which source shall be used for the Video stream. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + + + + +
<abbrev role="title-mark">4.2.9</abbrev>VIDEO_SET_BLANK<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Video Device to blank out the picture. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_SET_BLANK, boolean + mode); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_BLANK for this command. + + +boolean mode + +TRUE: Blank screen when stop. + + + +FALSE: Show last decoded frame. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + +EINVAL + +Illegal input parameter + + + + + +
<abbrev role="title-mark">4.2.10</abbrev>VIDEO_GET_STATUS<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Video Device to return the current status of the device. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_GET_STATUS, struct + video_status ⋆status); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_GET_STATUS for this command. + + +struct video_status + *status + +Returns the current status of the Video Device. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + +EFAULT + +status points to invalid address + + + + + +
<abbrev role="title-mark">4.2.11</abbrev>VIDEO_GET_EVENT<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call returns an event of type video_event if available. If an event is + not available, the behavior depends on whether the device is in blocking or + non-blocking mode. In the latter case, the call fails immediately with errno + set to EWOULDBLOCK. In the former case, the call blocks until an event + becomes available. The standard Linux poll() and/or select() system calls can + be used with the device file descriptor to watch for new events. For select(), + the file descriptor should be included in the exceptfds argument, and for + poll(), POLLPRI should be specified as the wake-up condition. Read-only + permissions are sufficient for this ioctl call. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_GET_EVENT, struct + video_event ⋆ev); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_GET_EVENT for this command. + + +struct video_event + *ev + +Points to the location where the event, if any, is to be + stored. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EFAULT + +ev points to invalid address + + +EWOULDBLOCK + +There is no event pending, and the device is in + non-blocking mode. + + +EOVERFLOW + + + + +Overflow in event queue - one or more events were lost. + + + + + +
<abbrev role="title-mark">4.2.12</abbrev>VIDEO_SET_DISPLAY_FORMAT<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Video Device to select the video format to be applied + by the MPEG chip on the video. + + +SYNOPSIS + + + int ioctl(fd, int request = + VIDEO_SET_DISPLAY_FORMAT, video_display_format_t + format); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_DISPLAY_FORMAT for this + command. + + +video_display_format_t + format + +Selects the video format to be used. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal parameter format. + + + + + +
<abbrev role="title-mark">4.2.13</abbrev>VIDEO_STILLPICTURE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Video Device to display a still picture (I-frame). The + input data shall contain an I-frame. If the pointer is NULL, then the current + displayed still picture is blanked. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_STILLPICTURE, + struct video_still_picture ⋆sp); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_STILLPICTURE for this command. + + +struct + video_still_picture + *sp + +Pointer to a location where an I-frame and size is stored. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + +EFAULT + +sp points to an invalid iframe. + + + + + +
<abbrev role="title-mark">4.2.14</abbrev>VIDEO_FAST_FORWARD<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Video Device to skip decoding of N number of I-frames. + This call can only be used if VIDEO_SOURCE_MEMORY is selected. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_FAST_FORWARD, int + nFrames); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_FAST_FORWARD for this command. + + +int nFrames + +The number of frames to skip. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + +EPERM + +Mode VIDEO_SOURCE_MEMORY not selected. + + +EINVAL + +Illegal parameter format. + + + + + +
<abbrev role="title-mark">4.2.15</abbrev>VIDEO_SLOWMOTION<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the video device to repeat decoding frames N number of + times. This call can only be used if VIDEO_SOURCE_MEMORY is selected. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_SLOWMOTION, int + nFrames); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SLOWMOTION for this command. + + +int nFrames + +The number of times to repeat each frame. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + +EPERM + +Mode VIDEO_SOURCE_MEMORY not selected. + + +EINVAL + +Illegal parameter format. + + + + + +
<abbrev role="title-mark">4.2.16</abbrev>VIDEO_GET_CAPABILITIES<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the video device about its decoding capabilities. On success + it returns and integer which has bits set according to the defines in section ??. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_GET_CAPABILITIES, + unsigned int ⋆cap); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_GET_CAPABILITIES for this + command. + + +unsigned int *cap + +Pointer to a location where to store the capability + information. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EFAULT + +cap points to an invalid iframe. + + + + + +
<abbrev role="title-mark">4.2.17</abbrev>VIDEO_SET_ID<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl selects which sub-stream is to be decoded if a program or system + stream is sent to the video device. + + +SYNOPSIS + + +int ioctl(int fd, int request = VIDEO_SET_ID, int + id); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_ID for this command. + + +int id + +video sub-stream id + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Invalid sub-stream id. + + + +
<abbrev role="title-mark">4.2.18</abbrev>VIDEO_CLEAR_BUFFER<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call clears all video buffers in the driver and in the decoder hardware. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_CLEAR_BUFFER); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_CLEAR_BUFFER for this command. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + + + + +
<abbrev role="title-mark">4.2.19</abbrev>VIDEO_SET_STREAMTYPE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl tells the driver which kind of stream to expect being written to it. If + this call is not used the default of video PES is used. Some drivers might not + support this call and always expect PES. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_SET_STREAMTYPE, + int type); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_STREAMTYPE for this command. + + +int type + +stream type + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +type is not a valid or supported stream type. + + + + + +
<abbrev role="title-mark">4.2.20</abbrev>VIDEO_SET_FORMAT<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl sets the screen format (aspect ratio) of the connected output device + (TV) so that the output of the decoder can be adjusted accordingly. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_FORMAT, + video_format_t format); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_FORMAT for this command. + + +video_format_t + format + +video format of TV as defined in section ??. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +format is not a valid video format. + + + + + +
<abbrev role="title-mark">4.2.21</abbrev>VIDEO_SET_SYSTEM<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl sets the television output format. The format (see section ??) may + vary from the color format of the displayed MPEG stream. If the hardware is + not able to display the requested format the call will return an error. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_SYSTEM , + video_system_t system); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_FORMAT for this command. + + +video_system_t + system + +video system of TV output. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +system is not a valid or supported video system. + + + + + +
<abbrev role="title-mark">4.2.22</abbrev>VIDEO_SET_HIGHLIGHT<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl sets the SPU highlight information for the menu access of a DVD. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_HIGHLIGHT + ,video_highlight_t ⋆vhilite) + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_HIGHLIGHT for this command. + + +video_highlight_t + *vhilite + +SPU Highlight information according to section ??. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINVAL + +input is not a valid highlight setting. + + + + + +
<abbrev role="title-mark">4.2.23</abbrev>VIDEO_SET_SPU<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl activates or deactivates SPU decoding in a DVD input stream. It can + only be used, if the driver is able to handle a DVD stream. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_SPU , + video_spu_t ⋆spu) + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_SPU for this command. + + +video_spu_t *spu + +SPU decoding (de)activation and subid setting according + to section ??. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +input is not a valid spu setting or driver cannot handle + SPU. + + + + + +
<abbrev role="title-mark">4.2.24</abbrev>VIDEO_SET_SPU_PALETTE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl sets the SPU color palette. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_SPU_PALETTE + ,video_spu_palette_t ⋆palette ) + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_SPU_PALETTE for this command. + + +video_spu_palette_t + *palette + +SPU palette according to section ??. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +input is not a valid palette or driver doesn’t handle SPU. + + + + + +
<abbrev role="title-mark">4.2.25</abbrev>VIDEO_GET_NAVI<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl returns navigational information from the DVD stream. This is + especially needed if an encoded stream has to be decoded by the hardware. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_GET_NAVI , + video_navi_pack_t ⋆navipack) + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_GET_NAVI for this command. + + +video_navi_pack_t + *navipack + +PCI or DSI pack (private stream 2) according to section + ??. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EFAULT + +driver is not able to return navigational information + + + + + +
<abbrev role="title-mark">4.2.26</abbrev>VIDEO_SET_ATTRIBUTES<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl is intended for DVD playback and allows you to set certain + information about the stream. Some hardware may not need this information, + but the call also tells the hardware to prepare for DVD playback. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_ATTRIBUTE + ,video_attributes_t vattr) + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_ATTRIBUTE for this command. + + +video_attributes_t + vattr + +video attributes according to section ??. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +input is not a valid attribute setting. + + + + +
DVB Audio Device +The DVB audio device controls the MPEG2 audio decoder of the DVB hardware. It +can be accessed through /dev/dvb/adapter0/audio0. Data types and and +ioctl definitions can be accessed by including linux/dvb/video.h in your +application. + +Please note that some DVB cards don’t have their own MPEG decoder, which results in +the omission of the audio and video device. + +
<abbrev role="title-mark">5.1</abbrev>Audio Data Types +This section describes the structures, data types and defines used when talking to the +audio device. + + +
<abbrev role="title-mark">5.1.1</abbrev>audio_stream_source_t +The audio stream source is set through the AUDIO_SELECT_SOURCE call and can take +the following values, depending on whether we are replaying from an internal (demux) or +external (user write) source. + + + typedef enum { + AUDIO_SOURCE_DEMUX, + AUDIO_SOURCE_MEMORY + } audio_stream_source_t; + +AUDIO_SOURCE_DEMUX selects the demultiplexer (fed either by the frontend or the +DVR device) as the source of the video stream. If AUDIO_SOURCE_MEMORY +is selected the stream comes from the application through the write() system +call. + + +
<abbrev role="title-mark">5.1.2</abbrev>audio_play_state_t +The following values can be returned by the AUDIO_GET_STATUS call representing the +state of audio playback. + + + typedef enum { + AUDIO_STOPPED, + AUDIO_PLAYING, + AUDIO_PAUSED + } audio_play_state_t; + + +
<abbrev role="title-mark">5.1.3</abbrev>audio_channel_select_t +The audio channel selected via AUDIO_CHANNEL_SELECT is determined by the +following values. + + + typedef enum { + AUDIO_STEREO, + AUDIO_MONO_LEFT, + AUDIO_MONO_RIGHT, + } audio_channel_select_t; + + +
<abbrev role="title-mark">5.1.4</abbrev>struct audio_status +The AUDIO_GET_STATUS call returns the following structure informing about various +states of the playback operation. + + + typedef struct audio_status { + boolean AV_sync_state; + boolean mute_state; + audio_play_state_t play_state; + audio_stream_source_t stream_source; + audio_channel_select_t channel_select; + boolean bypass_mode; + } audio_status_t; + + +
<abbrev role="title-mark">5.1.5</abbrev>struct audio_mixer +The following structure is used by the AUDIO_SET_MIXER call to set the audio +volume. + + + typedef struct audio_mixer { + unsigned int volume_left; + unsigned int volume_right; + } audio_mixer_t; + + +
<abbrev role="title-mark">5.1.6</abbrev>audio encodings +A call to AUDIO_GET_CAPABILITIES returns an unsigned integer with the following +bits set according to the hardwares capabilities. + + + #define AUDIO_CAP_DTS 1 + #define AUDIO_CAP_LPCM 2 + #define AUDIO_CAP_MP1 4 + #define AUDIO_CAP_MP2 8 + #define AUDIO_CAP_MP3 16 + #define AUDIO_CAP_AAC 32 + #define AUDIO_CAP_OGG 64 + #define AUDIO_CAP_SDDS 128 + #define AUDIO_CAP_AC3 256 + + +
<abbrev role="title-mark">5.1.7</abbrev>struct audio_karaoke +The ioctl AUDIO_SET_KARAOKE uses the following format: + + + typedef + struct audio_karaoke{ + int vocal1; + int vocal2; + int melody; + } audio_karaoke_t; + +If Vocal1 or Vocal2 are non-zero, they get mixed into left and right t at 70% each. If both, +Vocal1 and Vocal2 are non-zero, Vocal1 gets mixed into the left channel and Vocal2 into the +right channel at 100% each. Ff Melody is non-zero, the melody channel gets mixed into left +and right. + + +
<abbrev role="title-mark">5.1.8</abbrev>audio attributes +The following attributes can be set by a call to AUDIO_SET_ATTRIBUTES: + + + typedef uint16_t audio_attributes_t; + /⋆ bits: descr. ⋆/ + /⋆ 15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, ⋆/ + /⋆ 12 multichannel extension ⋆/ + /⋆ 11-10 audio type (0=not spec, 1=language included) ⋆/ + /⋆ 9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) ⋆/ + /⋆ 7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit, ⋆/ + /⋆ 5- 4 Sample frequency fs (0=48kHz, 1=96kHz) ⋆/ + /⋆ 2- 0 number of audio channels (n+1 channels) ⋆/ + +
<abbrev role="title-mark">5.2</abbrev>Audio Function Calls + +
<abbrev role="title-mark">5.2.1</abbrev>open() +DESCRIPTION + +
+This system call opens a named audio device (e.g. /dev/dvb/adapter0/audio0) + for subsequent use. When an open() call has succeeded, the device will be ready + for use. The significance of blocking or non-blocking mode is described in the + documentation for functions where there is a difference. It does not affect the + semantics of the open() call itself. A device opened in blocking mode can later + be put into non-blocking mode (and vice versa) using the F_SETFL command + of the fcntl system call. This is a standard system call, documented in the Linux + manual page for fcntl. Only one user can open the Audio Device in O_RDWR + mode. All other attempts to open the device in this mode will fail, and an error + code will be returned. If the Audio Device is opened in O_RDONLY mode, the + only ioctl call that can be used is AUDIO_GET_STATUS. All other call will + return with an error code. + + +SYNOPSIS + + +int open(const char ⋆deviceName, int flags); + + +PARAMETERS + + +const char + *deviceName + +Name of specific audio device. + + +int flags + +A bit-wise OR of the following flags: + + + +O_RDONLY read-only access + + + +O_RDWR read/write access + + + +O_NONBLOCK open in non-blocking mode + + + +(blocking mode is the default) + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EINTERNAL + +Internal error. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + + + + +
<abbrev role="title-mark">5.2.2</abbrev>close() +DESCRIPTION + +
+This system call closes a previously opened audio device. + + +SYNOPSIS + + +int close(int fd); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + + + + +
<abbrev role="title-mark">5.2.3</abbrev>write() +DESCRIPTION + +
+This system call can only be used if AUDIO_SOURCE_MEMORY is selected + in the ioctl call AUDIO_SELECT_SOURCE. The data provided shall be in + PES format. If O_NONBLOCK is not specified the function will block until + buffer space is available. The amount of data to be transferred is implied by + count. + + +SYNOPSIS + + +size_t write(int fd, const void ⋆buf, size_t count); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +void *buf + +Pointer to the buffer containing the PES data. + + +size_t count + +Size of buf. + + + + +ERRORS + + +EPERM + +Mode AUDIO_SOURCE_MEMORY not selected. + + +ENOMEM + +Attempted to write more data than the internal buffer can + hold. + + +EBADF + +fd is not a valid open file descriptor. + + + + + +
<abbrev role="title-mark">5.2.4</abbrev>AUDIO_STOP<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Audio Device to stop playing the current stream. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_STOP); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_STOP for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + + +
<abbrev role="title-mark">5.2.5</abbrev>AUDIO_PLAY<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Audio Device to start playing an audio stream from the + selected source. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_PLAY); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_PLAY for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + + +
<abbrev role="title-mark">5.2.6</abbrev>AUDIO_PAUSE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call suspends the audio stream being played. Decoding and playing + are paused. It is then possible to restart again decoding and playing process of + the audio stream using AUDIO_CONTINUE command. + + +If AUDIO_SOURCE_MEMORY is selected in the ioctl call + AUDIO_SELECT_SOURCE, the DVB-subsystem will not decode (consume) + any more data until the ioctl call AUDIO_CONTINUE or AUDIO_PLAY is + performed. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_PAUSE); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_PAUSE for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + + +
<abbrev role="title-mark">5.2.7</abbrev>AUDIO_SELECT_SOURCE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call informs the audio device which source shall be used + for the input data. The possible sources are demux or memory. If + AUDIO_SOURCE_MEMORY is selected, the data is fed to the Audio Device + through the write command. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_SELECT_SOURCE, + audio_stream_source_t source); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SELECT_SOURCE for this command. + + +audio_stream_source_t + source + +Indicates the source that shall be used for the Audio + stream. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal input parameter. + + + +
<abbrev role="title-mark">5.2.8</abbrev>AUDIO_SET_MUTE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the audio device to mute the stream that is currently being + played. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_SET_MUTE, + boolean state); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_MUTE for this command. + + +boolean state + +Indicates if audio device shall mute or not. + + + +TRUE Audio Mute + + + +FALSE Audio Un-mute + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal input parameter. + + + +
<abbrev role="title-mark">5.2.9</abbrev>AUDIO_SET_AV_SYNC<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Audio Device to turn ON or OFF A/V synchronization. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_SET_AV_SYNC, + boolean state); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_AV_SYNC for this command. + + +boolean state + +Tells the DVB subsystem if A/V synchronization shall be + ON or OFF. + + + +TRUE AV-sync ON + + + +FALSE AV-sync OFF + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal input parameter. + + + +
<abbrev role="title-mark">5.2.10</abbrev>AUDIO_SET_BYPASS_MODE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Audio Device to bypass the Audio decoder and forward + the stream without decoding. This mode shall be used if streams that can’t be + handled by the DVB system shall be decoded. Dolby DigitalTM streams are + automatically forwarded by the DVB subsystem if the hardware can handle it. + + +SYNOPSIS + + +int ioctl(int fd, int request = + AUDIO_SET_BYPASS_MODE, boolean mode); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_BYPASS_MODE for this + command. + + +boolean mode + +Enables or disables the decoding of the current Audio + stream in the DVB subsystem. + + + +TRUE Bypass is disabled + + + +FALSE Bypass is enabled + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal input parameter. + + + +
<abbrev role="title-mark">5.2.11</abbrev>AUDIO_CHANNEL_SELECT<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Audio Device to select the requested channel if possible. + + +SYNOPSIS + + +int ioctl(int fd, int request = + AUDIO_CHANNEL_SELECT, audio_channel_select_t); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_CHANNEL_SELECT for this + command. + + +audio_channel_select_t + ch + +Select the output format of the audio (mono left/right, + stereo). + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal input parameter ch. + + + +
<abbrev role="title-mark">5.2.12</abbrev>AUDIO_GET_STATUS<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Audio Device to return the current state of the Audio + Device. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_GET_STATUS, + struct audio_status ⋆status); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_GET_STATUS for this command. + + +struct audio_status + *status + +Returns the current state of Audio Device. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EFAULT + +status points to invalid address. + + + +
<abbrev role="title-mark">5.2.13</abbrev>AUDIO_GET_CAPABILITIES<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Audio Device to tell us about the decoding capabilities + of the audio hardware. + + +SYNOPSIS + + +int ioctl(int fd, int request = + AUDIO_GET_CAPABILITIES, unsigned int ⋆cap); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_GET_CAPABILITIES for this + command. + + +unsigned int *cap + +Returns a bit array of supported sound formats. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EFAULT + +cap points to an invalid address. + + + +
<abbrev role="title-mark">5.2.14</abbrev>AUDIO_CLEAR_BUFFER<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl call asks the Audio Device to clear all software and hardware buffers + of the audio decoder device. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_CLEAR_BUFFER); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_CLEAR_BUFFER for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + + +
<abbrev role="title-mark">5.2.15</abbrev>AUDIO_SET_ID<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl selects which sub-stream is to be decoded if a program or system + stream is sent to the video device. If no audio stream type is set the id has to be + in [0xC0,0xDF] for MPEG sound, in [0x80,0x87] for AC3 and in [0xA0,0xA7] + for LPCM. More specifications may follow for other stream types. If the stream + type is set the id just specifies the substream id of the audio stream and only + the first 5 bits are recognized. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_SET_ID, int + id); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_ID for this command. + + +int id + +audio sub-stream id + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Invalid sub-stream id. + + + +
<abbrev role="title-mark">5.2.16</abbrev>AUDIO_SET_MIXER<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl lets you adjust the mixer settings of the audio decoder. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_SET_MIXER, + audio_mixer_t ⋆mix); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_ID for this command. + + +audio_mixer_t *mix + +mixer settings. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EFAULT + +mix points to an invalid address. + + + +
<abbrev role="title-mark">5.2.17</abbrev>AUDIO_SET_STREAMTYPE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl tells the driver which kind of audio stream to expect. This is useful + if the stream offers several audio sub-streams like LPCM and AC3. + + +SYNOPSIS + + +int ioctl(fd, int request = AUDIO_SET_STREAMTYPE, + int type); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_STREAMTYPE for this + command. + + +int type + +stream type + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +type is not a valid or supported stream type. + + + + + +
<abbrev role="title-mark">5.2.18</abbrev>AUDIO_SET_EXT_ID<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl can be used to set the extension id for MPEG streams in DVD + playback. Only the first 3 bits are recognized. + + +SYNOPSIS + + +int ioctl(fd, int request = AUDIO_SET_EXT_ID, int + id); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_EXT_ID for this command. + + +int id + +audio sub_stream_id + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +id is not a valid id. + + + + + +
<abbrev role="title-mark">5.2.19</abbrev>AUDIO_SET_ATTRIBUTES<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl is intended for DVD playback and allows you to set certain + information about the audio stream. + + +SYNOPSIS + + +int ioctl(fd, int request = AUDIO_SET_ATTRIBUTES, + audio_attributes_t attr ); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_ATTRIBUTES for this command. + + +audio_attributes_t + attr + +audio attributes according to section ?? + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +attr is not a valid or supported attribute setting. + + + + + +
<abbrev role="title-mark">5.2.20</abbrev>AUDIO_SET_KARAOKE<indexterm role="printindex" /> +DESCRIPTION + +
+This ioctl allows one to set the mixer settings for a karaoke DVD. + + +SYNOPSIS + + +int ioctl(fd, int request = AUDIO_SET_STREAMTYPE, + audio_karaoke_t ⋆karaoke); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_STREAMTYPE for this + command. + + +audio_karaoke_t + *karaoke + +karaoke settings according to section ??. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +karaoke is not a valid or supported karaoke setting. + + + + +
DVB CA Device +The DVB CA device controls the conditional access hardware. It can be accessed through +/dev/dvb/adapter0/ca0. Data types and and ioctl definitions can be accessed by +including linux/dvb/ca.h in your application. + +
<abbrev role="title-mark">6.1</abbrev>CA Data Types + +
<abbrev role="title-mark">6.1.1</abbrev>ca_slot_info_t + + /⋆ slot interface types and info ⋆/ + + typedef struct ca_slot_info_s { + int num; /⋆ slot number ⋆/ + + int type; /⋆ CA interface this slot supports ⋆/ + #define CA_CI 1 /⋆ CI high level interface ⋆/ + #define CA_CI_LINK 2 /⋆ CI link layer level interface ⋆/ + #define CA_CI_PHYS 4 /⋆ CI physical layer level interface ⋆/ + #define CA_SC 128 /⋆ simple smart card interface ⋆/ + + unsigned int flags; + #define CA_CI_MODULE_PRESENT 1 /⋆ module (or card) inserted ⋆/ + #define CA_CI_MODULE_READY 2 + } ca_slot_info_t; + + +
<abbrev role="title-mark">6.1.2</abbrev>ca_descr_info_t + + typedef struct ca_descr_info_s { + unsigned int num; /⋆ number of available descramblers (keys) ⋆/ + unsigned int type; /⋆ type of supported scrambling system ⋆/ + #define CA_ECD 1 + #define CA_NDS 2 + #define CA_DSS 4 + } ca_descr_info_t; + + +
<abbrev role="title-mark">6.1.3</abbrev>ca_cap_t + + typedef struct ca_cap_s { + unsigned int slot_num; /⋆ total number of CA card and module slots ⋆/ + unsigned int slot_type; /⋆ OR of all supported types ⋆/ + unsigned int descr_num; /⋆ total number of descrambler slots (keys) ⋆/ + unsigned int descr_type;/⋆ OR of all supported types ⋆/ + } ca_cap_t; + + +
<abbrev role="title-mark">6.1.4</abbrev>ca_msg_t + + /⋆ a message to/from a CI-CAM ⋆/ + typedef struct ca_msg_s { + unsigned int index; + unsigned int type; + unsigned int length; + unsigned char msg[256]; + } ca_msg_t; + + +
<abbrev role="title-mark">6.1.5</abbrev>ca_descr_t + + typedef struct ca_descr_s { + unsigned int index; + unsigned int parity; + unsigned char cw[8]; + } ca_descr_t; + +
<abbrev role="title-mark">6.2</abbrev>CA Function Calls + +
<abbrev role="title-mark">6.2.1</abbrev>open() +DESCRIPTION + +
+This system call opens a named ca device (e.g. /dev/ost/ca) for subsequent use. +When an open() call has succeeded, the device will be ready for use. + The significance of blocking or non-blocking mode is described in the + documentation for functions where there is a difference. It does not affect the + semantics of the open() call itself. A device opened in blocking mode can later + be put into non-blocking mode (and vice versa) using the F_SETFL command + of the fcntl system call. This is a standard system call, documented in the Linux + manual page for fcntl. Only one user can open the CA Device in O_RDWR + mode. All other attempts to open the device in this mode will fail, and an error + code will be returned. + + + +SYNOPSIS + + +int open(const char ⋆deviceName, int flags); + + +PARAMETERS + + +const char + *deviceName + +Name of specific video device. + + +int flags + +A bit-wise OR of the following flags: + + + +O_RDONLY read-only access + + + +O_RDWR read/write access + + + +O_NONBLOCK open in non-blocking mode + + + +(blocking mode is the default) + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EINTERNAL + +Internal error. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + + + + +
<abbrev role="title-mark">6.2.2</abbrev>close() +DESCRIPTION + +
+This system call closes a previously opened audio device. + + +SYNOPSIS + + +int close(int fd); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + + + +
DVB Network API +The DVB net device enables feeding of MPE (multi protocol encapsulation) packets +received via DVB into the Linux network protocol stack, e.g. for internet via satellite +applications. It can be accessed through /dev/dvb/adapter0/net0. Data types and +and ioctl definitions can be accessed by including linux/dvb/net.h in your +application. + +
<abbrev role="title-mark">7.1</abbrev>DVB Net Data Types +To be written… + + +
Kernel Demux API +The kernel demux API defines a driver-internal interface for registering low-level, +hardware specific driver to a hardware independent demux layer. It is only of interest for +DVB device driver writers. The header file for this API is named demux.h and located in +drivers/media/dvb/dvb-core. + +Maintainer note: This section must be reviewed. It is probably out of date. + +
<abbrev role="title-mark">8.1</abbrev>Kernel Demux Data Types + +
<abbrev role="title-mark">8.1.1</abbrev>dmx_success_t + + typedef enum { + DMX_OK = 0, /⋆ Received Ok ⋆/ + DMX_LENGTH_ERROR, /⋆ Incorrect length ⋆/ + DMX_OVERRUN_ERROR, /⋆ Receiver ring buffer overrun ⋆/ + DMX_CRC_ERROR, /⋆ Incorrect CRC ⋆/ + DMX_FRAME_ERROR, /⋆ Frame alignment error ⋆/ + DMX_FIFO_ERROR, /⋆ Receiver FIFO overrun ⋆/ + DMX_MISSED_ERROR /⋆ Receiver missed packet ⋆/ + } dmx_success_t; + + +
<abbrev role="title-mark">8.1.2</abbrev>TS filter types + + /⋆--------------------------------------------------------------------------⋆/ + /⋆ TS packet reception ⋆/ + /⋆--------------------------------------------------------------------------⋆/ + + /⋆ TS filter type for set_type() ⋆/ + + #define TS_PACKET 1 /⋆ send TS packets (188 bytes) to callback (default) ⋆/ + #define TS_PAYLOAD_ONLY 2 /⋆ in case TS_PACKET is set, only send the TS + payload (<=184 bytes per packet) to callback ⋆/ + #define TS_DECODER 4 /⋆ send stream to built-in decoder (if present) ⋆/ + + +
<abbrev role="title-mark">8.1.3</abbrev>dmx_ts_pes_t +The structure + + + typedef enum + { + DMX_TS_PES_AUDIO, /⋆ also send packets to audio decoder (if it exists) ⋆/ + DMX_TS_PES_VIDEO, /⋆ ... ⋆/ + DMX_TS_PES_TELETEXT, + DMX_TS_PES_SUBTITLE, + DMX_TS_PES_PCR, + DMX_TS_PES_OTHER, + } dmx_ts_pes_t; + +describes the PES type for filters which write to a built-in decoder. The correspond (and +should be kept identical) to the types in the demux device. + + + struct dmx_ts_feed_s { + int is_filtering; /⋆ Set to non-zero when filtering in progress ⋆/ + struct dmx_demux_s⋆ parent; /⋆ Back-pointer ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + int (⋆set) (struct dmx_ts_feed_s⋆ feed, + __u16 pid, + size_t callback_length, + size_t circular_buffer_size, + int descramble, + struct timespec timeout); + int (⋆start_filtering) (struct dmx_ts_feed_s⋆ feed); + int (⋆stop_filtering) (struct dmx_ts_feed_s⋆ feed); + int (⋆set_type) (struct dmx_ts_feed_s⋆ feed, + int type, + dmx_ts_pes_t pes_type); + }; + + typedef struct dmx_ts_feed_s dmx_ts_feed_t; + + + /⋆--------------------------------------------------------------------------⋆/ + /⋆ PES packet reception (not supported yet) ⋆/ + /⋆--------------------------------------------------------------------------⋆/ + + typedef struct dmx_pes_filter_s { + struct dmx_pes_s⋆ parent; /⋆ Back-pointer ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + } dmx_pes_filter_t; + + + typedef struct dmx_pes_feed_s { + int is_filtering; /⋆ Set to non-zero when filtering in progress ⋆/ + struct dmx_demux_s⋆ parent; /⋆ Back-pointer ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + int (⋆set) (struct dmx_pes_feed_s⋆ feed, + __u16 pid, + size_t circular_buffer_size, + int descramble, + struct timespec timeout); + int (⋆start_filtering) (struct dmx_pes_feed_s⋆ feed); + int (⋆stop_filtering) (struct dmx_pes_feed_s⋆ feed); + int (⋆allocate_filter) (struct dmx_pes_feed_s⋆ feed, + dmx_pes_filter_t⋆⋆ filter); + int (⋆release_filter) (struct dmx_pes_feed_s⋆ feed, + dmx_pes_filter_t⋆ filter); + } dmx_pes_feed_t; + + + typedef struct { + __u8 filter_value [DMX_MAX_FILTER_SIZE]; + __u8 filter_mask [DMX_MAX_FILTER_SIZE]; + struct dmx_section_feed_s⋆ parent; /⋆ Back-pointer ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + } dmx_section_filter_t; + + + struct dmx_section_feed_s { + int is_filtering; /⋆ Set to non-zero when filtering in progress ⋆/ + struct dmx_demux_s⋆ parent; /⋆ Back-pointer ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + int (⋆set) (struct dmx_section_feed_s⋆ feed, + __u16 pid, + size_t circular_buffer_size, + int descramble, + int check_crc); + int (⋆allocate_filter) (struct dmx_section_feed_s⋆ feed, + dmx_section_filter_t⋆⋆ filter); + int (⋆release_filter) (struct dmx_section_feed_s⋆ feed, + dmx_section_filter_t⋆ filter); + int (⋆start_filtering) (struct dmx_section_feed_s⋆ feed); + int (⋆stop_filtering) (struct dmx_section_feed_s⋆ feed); + }; + typedef struct dmx_section_feed_s dmx_section_feed_t; + + /⋆--------------------------------------------------------------------------⋆/ + /⋆ Callback functions ⋆/ + /⋆--------------------------------------------------------------------------⋆/ + + typedef int (⋆dmx_ts_cb) ( __u8 ⋆ buffer1, + size_t buffer1_length, + __u8 ⋆ buffer2, + size_t buffer2_length, + dmx_ts_feed_t⋆ source, + dmx_success_t success); + + typedef int (⋆dmx_section_cb) ( __u8 ⋆ buffer1, + size_t buffer1_len, + __u8 ⋆ buffer2, + size_t buffer2_len, + dmx_section_filter_t ⋆ source, + dmx_success_t success); + + typedef int (⋆dmx_pes_cb) ( __u8 ⋆ buffer1, + size_t buffer1_len, + __u8 ⋆ buffer2, + size_t buffer2_len, + dmx_pes_filter_t⋆ source, + dmx_success_t success); + + /⋆--------------------------------------------------------------------------⋆/ + /⋆ DVB Front-End ⋆/ + /⋆--------------------------------------------------------------------------⋆/ + + typedef enum { + DMX_OTHER_FE = 0, + DMX_SATELLITE_FE, + DMX_CABLE_FE, + DMX_TERRESTRIAL_FE, + DMX_LVDS_FE, + DMX_ASI_FE, /⋆ DVB-ASI interface ⋆/ + DMX_MEMORY_FE + } dmx_frontend_source_t; + + typedef struct { + /⋆ The following char⋆ fields point to NULL terminated strings ⋆/ + char⋆ id; /⋆ Unique front-end identifier ⋆/ + char⋆ vendor; /⋆ Name of the front-end vendor ⋆/ + char⋆ model; /⋆ Name of the front-end model ⋆/ + struct list_head connectivity_list; /⋆ List of front-ends that can + be connected to a particular + demux ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + dmx_frontend_source_t source; + } dmx_frontend_t; + + /⋆--------------------------------------------------------------------------⋆/ + /⋆ MPEG-2 TS Demux ⋆/ + /⋆--------------------------------------------------------------------------⋆/ + + /⋆ + ⋆ Flags OR'ed in the capabilites field of struct dmx_demux_s. + ⋆/ + + #define DMX_TS_FILTERING 1 + #define DMX_PES_FILTERING 2 + #define DMX_SECTION_FILTERING 4 + #define DMX_MEMORY_BASED_FILTERING 8 /⋆ write() available ⋆/ + #define DMX_CRC_CHECKING 16 + #define DMX_TS_DESCRAMBLING 32 + #define DMX_SECTION_PAYLOAD_DESCRAMBLING 64 + #define DMX_MAC_ADDRESS_DESCRAMBLING 128 + + +
<abbrev role="title-mark">8.1.4</abbrev>demux_demux_t + + /⋆ + ⋆ DMX_FE_ENTRY(): Casts elements in the list of registered + ⋆ front-ends from the generic type struct list_head + ⋆ to the type ⋆ dmx_frontend_t + ⋆. + ⋆/ + + #define DMX_FE_ENTRY(list) list_entry(list, dmx_frontend_t, connectivity_list) + + struct dmx_demux_s { + /⋆ The following char⋆ fields point to NULL terminated strings ⋆/ + char⋆ id; /⋆ Unique demux identifier ⋆/ + char⋆ vendor; /⋆ Name of the demux vendor ⋆/ + char⋆ model; /⋆ Name of the demux model ⋆/ + __u32 capabilities; /⋆ Bitfield of capability flags ⋆/ + dmx_frontend_t⋆ frontend; /⋆ Front-end connected to the demux ⋆/ + struct list_head reg_list; /⋆ List of registered demuxes ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + int users; /⋆ Number of users ⋆/ + int (⋆open) (struct dmx_demux_s⋆ demux); + int (⋆close) (struct dmx_demux_s⋆ demux); + int (⋆write) (struct dmx_demux_s⋆ demux, const char⋆ buf, size_t count); + int (⋆allocate_ts_feed) (struct dmx_demux_s⋆ demux, + dmx_ts_feed_t⋆⋆ feed, + dmx_ts_cb callback); + int (⋆release_ts_feed) (struct dmx_demux_s⋆ demux, + dmx_ts_feed_t⋆ feed); + int (⋆allocate_pes_feed) (struct dmx_demux_s⋆ demux, + dmx_pes_feed_t⋆⋆ feed, + dmx_pes_cb callback); + int (⋆release_pes_feed) (struct dmx_demux_s⋆ demux, + dmx_pes_feed_t⋆ feed); + int (⋆allocate_section_feed) (struct dmx_demux_s⋆ demux, + dmx_section_feed_t⋆⋆ feed, + dmx_section_cb callback); + int (⋆release_section_feed) (struct dmx_demux_s⋆ demux, + dmx_section_feed_t⋆ feed); + int (⋆descramble_mac_address) (struct dmx_demux_s⋆ demux, + __u8⋆ buffer1, + size_t buffer1_length, + __u8⋆ buffer2, + size_t buffer2_length, + __u16 pid); + int (⋆descramble_section_payload) (struct dmx_demux_s⋆ demux, + __u8⋆ buffer1, + size_t buffer1_length, + __u8⋆ buffer2, size_t buffer2_length, + __u16 pid); + int (⋆add_frontend) (struct dmx_demux_s⋆ demux, + dmx_frontend_t⋆ frontend); + int (⋆remove_frontend) (struct dmx_demux_s⋆ demux, + dmx_frontend_t⋆ frontend); + struct list_head⋆ (⋆get_frontends) (struct dmx_demux_s⋆ demux); + int (⋆connect_frontend) (struct dmx_demux_s⋆ demux, + dmx_frontend_t⋆ frontend); + int (⋆disconnect_frontend) (struct dmx_demux_s⋆ demux); + + + /⋆ added because js cannot keep track of these himself ⋆/ + int (⋆get_pes_pids) (struct dmx_demux_s⋆ demux, __u16 ⋆pids); + }; + typedef struct dmx_demux_s dmx_demux_t; + + +
<abbrev role="title-mark">8.1.5</abbrev>Demux directory + + /⋆ + ⋆ DMX_DIR_ENTRY(): Casts elements in the list of registered + ⋆ demuxes from the generic type struct list_head⋆ to the type dmx_demux_t + ⋆. + ⋆/ + + #define DMX_DIR_ENTRY(list) list_entry(list, dmx_demux_t, reg_list) + + int dmx_register_demux (dmx_demux_t⋆ demux); + int dmx_unregister_demux (dmx_demux_t⋆ demux); + struct list_head⋆ dmx_get_demuxes (void); + +
<abbrev role="title-mark">8.2</abbrev>Demux Directory API +The demux directory is a Linux kernel-wide facility for registering and accessing the +MPEG-2 TS demuxes in the system. Run-time registering and unregistering of demux drivers +is possible using this API. + +All demux drivers in the directory implement the abstract interface dmx_demux_t. + + +
<abbrev role="title-mark">8.2.1</abbrev>dmx_register_demux()<indexterm role="printindex" /> +DESCRIPTION + +
+This function makes a demux driver interface available to the Linux kernel. It is + usually called by the init_module() function of the kernel module that contains + the demux driver. The caller of this function is responsible for allocating + dynamic or static memory for the demux structure and for initializing its fields + before calling this function. The memory allocated for the demux structure + must not be freed before calling dmx_unregister_demux(), + + +SYNOPSIS + + +int dmx_register_demux ( dmx_demux_t ⋆demux ) + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux structure. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EEXIST + +A demux with the same value of the id field already stored + in the directory. + + +-ENOSPC + +No space left in the directory. + + + +
<abbrev role="title-mark">8.2.2</abbrev>dmx_unregister_demux()<indexterm role="printindex" /> +DESCRIPTION + +
+This function is called to indicate that the given demux interface is no + longer available. The caller of this function is responsible for freeing the + memory of the demux structure, if it was dynamically allocated before calling + dmx_register_demux(). The cleanup_module() function of the kernel module + that contains the demux driver should call this function. Note that this function + fails if the demux is currently in use, i.e., release_demux() has not been called + for the interface. + + +SYNOPSIS + + +int dmx_unregister_demux ( dmx_demux_t ⋆demux ) + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux structure which is to be + unregistered. + + +RETURNS + + +0 + +The function was completed without errors. + + +ENODEV + +The specified demux is not registered in the demux + directory. + + +EBUSY + +The specified demux is currently in use. + + + +
<abbrev role="title-mark">8.2.3</abbrev>dmx_get_demuxes()<indexterm role="printindex" /> +DESCRIPTION + +
+Provides the caller with the list of registered demux interfaces, using the + standard list structure defined in the include file linux/list.h. The include file + demux.h defines the macro DMX_DIR_ENTRY() for converting an element of + the generic type struct list_head* to the type dmx_demux_t*. The caller must + not free the memory of any of the elements obtained via this function call. + + +SYNOPSIS + + +struct list_head ⋆dmx_get_demuxes () + + +PARAMETERS + + +none + + +RETURNS + + +struct list_head * + +A list of demux interfaces, or NULL in the case of an + empty list. + + +
<abbrev role="title-mark">8.3</abbrev>Demux API +The demux API should be implemented for each demux in the system. It is used to select +the TS source of a demux and to manage the demux resources. When the demux +client allocates a resource via the demux API, it receives a pointer to the API of that +resource. + +Each demux receives its TS input from a DVB front-end or from memory, as set via the +demux API. In a system with more than one front-end, the API can be used to select one of +the DVB front-ends as a TS source for a demux, unless this is fixed in the HW platform. The +demux API only controls front-ends regarding their connections with demuxes; the APIs +used to set the other front-end parameters, such as tuning, are not defined in this +document. + +The functions that implement the abstract interface demux should be defined static or +module private and registered to the Demux Directory for external access. It is not necessary +to implement every function in the demux_t struct, however (for example, a demux interface +might support Section filtering, but not TS or PES filtering). The API client is expected to +check the value of any function pointer before calling the function: the value of NULL means +“function not available”. + +Whenever the functions of the demux API modify shared data, the possibilities of lost +update and race condition problems should be addressed, e.g. by protecting parts of code with +mutexes. This is especially important on multi-processor hosts. + +Note that functions called from a bottom half context must not sleep, at least in the 2.2.x +kernels. Even a simple memory allocation can result in a kernel thread being put to sleep if +swapping is needed. For example, the Linux kernel calls the functions of a network device +interface from a bottom half context. Thus, if a demux API function is called from network +device code, the function must not sleep. + + +
<abbrev role="title-mark">8.3.1</abbrev>open() +DESCRIPTION + +
+This function reserves the demux for use by the caller and, if necessary, + initializes the demux. When the demux is no longer needed, the function close() + should be called. It should be possible for multiple clients to access the demux + at the same time. Thus, the function implementation should increment the + demux usage count when open() is called and decrement it when close() is + called. + + +SYNOPSIS + + +int open ( demux_t⋆ demux ); + + +PARAMETERS + + +demux_t* demux + +Pointer to the demux API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EUSERS + +Maximum usage count reached. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.3.2</abbrev>close() +DESCRIPTION + +
+This function reserves the demux for use by the caller and, if necessary, + initializes the demux. When the demux is no longer needed, the function close() + should be called. It should be possible for multiple clients to access the demux + at the same time. Thus, the function implementation should increment the + demux usage count when open() is called and decrement it when close() is + called. + + +SYNOPSIS + + +int close(demux_t⋆ demux); + + +PARAMETERS + + +demux_t* demux + +Pointer to the demux API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENODEV + +The demux was not in use. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.3.3</abbrev>write() +DESCRIPTION + +
+This function provides the demux driver with a memory buffer containing TS + packets. Instead of receiving TS packets from the DVB front-end, the demux + driver software will read packets from memory. Any clients of this demux + with active TS, PES or Section filters will receive filtered data via the Demux + callback API (see 0). The function returns when all the data in the buffer has + been consumed by the demux. Demux hardware typically cannot read TS from + memory. If this is the case, memory-based filtering has to be implemented + entirely in software. + + +SYNOPSIS + + +int write(demux_t⋆ demux, const char⋆ buf, size_t + count); + + +PARAMETERS + + +demux_t* demux + +Pointer to the demux API and instance data. + + +const char* buf + +Pointer to the TS data in kernel-space memory. + + +size_t length + +Length of the TS data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOSYS + +The command is not implemented. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.3.4</abbrev>allocate_ts_feed()<indexterm role="printindex" /> +DESCRIPTION + +
+Allocates a new TS feed, which is used to filter the TS packets carrying a + certain PID. The TS feed normally corresponds to a hardware PID filter on the + demux chip. + + +SYNOPSIS + + +int allocate_ts_feed(dmx_demux_t⋆ demux, + dmx_ts_feed_t⋆⋆ feed, dmx_ts_cb callback); + + +PARAMETERS + + +demux_t* demux + +Pointer to the demux API and instance data. + + +dmx_ts_feed_t** + feed + +Pointer to the TS feed API and instance data. + + +dmx_ts_cb callback + +Pointer to the callback function for passing received TS + packet + + +RETURNS + + +0 + +The function was completed without errors. + + +-EBUSY + +No more TS feeds available. + + +-ENOSYS + +The command is not implemented. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.3.5</abbrev>release_ts_feed()<indexterm role="printindex" /> +DESCRIPTION + +
+Releases the resources allocated with allocate_ts_feed(). Any filtering in + progress on the TS feed should be stopped before calling this function. + + +SYNOPSIS + + +int release_ts_feed(dmx_demux_t⋆ demux, + dmx_ts_feed_t⋆ feed); + + +PARAMETERS + + +demux_t* demux + +Pointer to the demux API and instance data. + + +dmx_ts_feed_t* feed + +Pointer to the TS feed API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.3.6</abbrev>allocate_section_feed()<indexterm role="printindex" /> +DESCRIPTION + +
+Allocates a new section feed, i.e. a demux resource for filtering and receiving + sections. On platforms with hardware support for section filtering, a section + feed is directly mapped to the demux HW. On other platforms, TS packets are + first PID filtered in hardware and a hardware section filter then emulated in + software. The caller obtains an API pointer of type dmx_section_feed_t as an + out parameter. Using this API the caller can set filtering parameters and start + receiving sections. + + +SYNOPSIS + + +int allocate_section_feed(dmx_demux_t⋆ demux, + dmx_section_feed_t ⋆⋆feed, dmx_section_cb callback); + + +PARAMETERS + + +demux_t *demux + +Pointer to the demux API and instance data. + + +dmx_section_feed_t + **feed + +Pointer to the section feed API and instance data. + + +dmx_section_cb + callback + +Pointer to the callback function for passing received + sections. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EBUSY + +No more section feeds available. + + +-ENOSYS + +The command is not implemented. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.3.7</abbrev>release_section_feed()<indexterm role="printindex" /> +DESCRIPTION + +
+Releases the resources allocated with allocate_section_feed(), including + allocated filters. Any filtering in progress on the section feed should be stopped + before calling this function. + + +SYNOPSIS + + +int release_section_feed(dmx_demux_t⋆ demux, + dmx_section_feed_t ⋆feed); + + +PARAMETERS + + +demux_t *demux + +Pointer to the demux API and instance data. + + +dmx_section_feed_t + *feed + +Pointer to the section feed API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.3.8</abbrev>descramble_mac_address()<indexterm role="printindex" /> +DESCRIPTION + +
+This function runs a descrambling algorithm on the destination MAC + address field of a DVB Datagram Section, replacing the original address + with its un-encrypted version. Otherwise, the description on the function + descramble_section_payload() applies also to this function. + + +SYNOPSIS + + +int descramble_mac_address(dmx_demux_t⋆ demux, __u8 + ⋆buffer1, size_t buffer1_length, __u8 ⋆buffer2, + size_t buffer2_length, __u16 pid); + + +PARAMETERS + + +dmx_demux_t + *demux + +Pointer to the demux API and instance data. + + +__u8 *buffer1 + +Pointer to the first byte of the section. + + +size_t buffer1_length + +Length of the section data, including headers and CRC, + in buffer1. + + +__u8* buffer2 + +Pointer to the tail of the section data, or NULL. The + pointer has a non-NULL value if the section wraps past + the end of a circular buffer. + + +size_t buffer2_length + +Length of the section data, including headers and CRC, + in buffer2. + + +__u16 pid + +The PID on which the section was received. Useful + for obtaining the descrambling key, e.g. from a DVB + Common Access facility. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOSYS + +No descrambling facility available. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.3.9</abbrev>descramble_section_payload()<indexterm role="printindex" /> +DESCRIPTION + +
+This function runs a descrambling algorithm on the payload of a DVB + Datagram Section, replacing the original payload with its un-encrypted + version. The function will be called from the demux API implementation; + the API client need not call this function directly. Section-level scrambling + algorithms are currently standardized only for DVB-RCC (return channel + over 2-directional cable TV network) systems. For all other DVB networks, + encryption schemes are likely to be proprietary to each data broadcaster. Thus, + it is expected that this function pointer will have the value of NULL (i.e., + function not available) in most demux API implementations. Nevertheless, it + should be possible to use the function pointer as a hook for dynamically adding + a “plug-in” descrambling facility to a demux driver. + + +While this function is not needed with hardware-based section descrambling, + the descramble_section_payload function pointer can be used to override the + default hardware-based descrambling algorithm: if the function pointer has a + non-NULL value, the corresponding function should be used instead of any + descrambling hardware. + + +SYNOPSIS + + +int descramble_section_payload(dmx_demux_t⋆ demux, + __u8 ⋆buffer1, size_t buffer1_length, __u8 ⋆buffer2, + size_t buffer2_length, __u16 pid); + + +PARAMETERS + + +dmx_demux_t + *demux + +Pointer to the demux API and instance data. + + +__u8 *buffer1 + +Pointer to the first byte of the section. + + +size_t buffer1_length + +Length of the section data, including headers and CRC, + in buffer1. + + +__u8 *buffer2 + +Pointer to the tail of the section data, or NULL. The + pointer has a non-NULL value if the section wraps past + the end of a circular buffer. + + +size_t buffer2_length + +Length of the section data, including headers and CRC, + in buffer2. + + +__u16 pid + +The PID on which the section was received. Useful + for obtaining the descrambling key, e.g. from a DVB + Common Access facility. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOSYS + +No descrambling facility available. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.3.10</abbrev>add_frontend()<indexterm role="printindex" /> +DESCRIPTION + +
+Registers a connectivity between a demux and a front-end, i.e., indicates that + the demux can be connected via a call to connect_frontend() to use the given + front-end as a TS source. The client of this function has to allocate dynamic or + static memory for the frontend structure and initialize its fields before calling + this function. This function is normally called during the driver initialization. + The caller must not free the memory of the frontend struct before successfully + calling remove_frontend(). + + +SYNOPSIS + + +int add_frontend(dmx_demux_t ⋆demux, dmx_frontend_t + ⋆frontend); + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux API and instance data. + + +dmx_frontend_t* + frontend + +Pointer to the front-end instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EEXIST + +A front-end with the same value of the id field already + registered. + + +-EINUSE + +The demux is in use. + + +-ENOMEM + +No more front-ends can be added. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.3.11</abbrev>remove_frontend()<indexterm role="printindex" /> +DESCRIPTION + +
+Indicates that the given front-end, registered by a call to add_frontend(), can + no longer be connected as a TS source by this demux. The function should be + called when a front-end driver or a demux driver is removed from the system. + If the front-end is in use, the function fails with the return value of -EBUSY. + After successfully calling this function, the caller can free the memory of + the frontend struct if it was dynamically allocated before the add_frontend() + operation. + + +SYNOPSIS + + +int remove_frontend(dmx_demux_t⋆ demux, + dmx_frontend_t⋆ frontend); + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux API and instance data. + + +dmx_frontend_t* + frontend + +Pointer to the front-end instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + +-EBUSY + +The front-end is in use, i.e. a call to connect_frontend() + has not been followed by a call to disconnect_frontend(). + + + +
<abbrev role="title-mark">8.3.12</abbrev>get_frontends()<indexterm role="printindex" /> +DESCRIPTION + +
+Provides the APIs of the front-ends that have been registered for this demux. + Any of the front-ends obtained with this call can be used as a parameter for + connect_frontend(). + + +The include file demux.h contains the macro DMX_FE_ENTRY() for + converting an element of the generic type struct list_head* to the type + dmx_frontend_t*. The caller must not free the memory of any of the elements + obtained via this function call. + + +SYNOPSIS + + +struct list_head⋆ get_frontends(dmx_demux_t⋆ demux); + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux API and instance data. + + +RETURNS + + +dmx_demux_t* + +A list of front-end interfaces, or NULL in the case of an + empty list. + + + +
<abbrev role="title-mark">8.3.13</abbrev>connect_frontend()<indexterm role="printindex" /> +DESCRIPTION + +
+Connects the TS output of the front-end to the input of the demux. A demux + can only be connected to a front-end registered to the demux with the function + add_frontend(). + + +It may or may not be possible to connect multiple demuxes to the same + front-end, depending on the capabilities of the HW platform. When not used, + the front-end should be released by calling disconnect_frontend(). + + +SYNOPSIS + + +int connect_frontend(dmx_demux_t⋆ demux, + dmx_frontend_t⋆ frontend); + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux API and instance data. + + +dmx_frontend_t* + frontend + +Pointer to the front-end instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + +-EBUSY + +The front-end is in use. + + + +
<abbrev role="title-mark">8.3.14</abbrev>disconnect_frontend()<indexterm role="printindex" /> +DESCRIPTION + +
+Disconnects the demux and a front-end previously connected by a + connect_frontend() call. + + +SYNOPSIS + + +int disconnect_frontend(dmx_demux_t⋆ demux); + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + +
<abbrev role="title-mark">8.4</abbrev>Demux Callback API +This kernel-space API comprises the callback functions that deliver filtered data to the +demux client. Unlike the other APIs, these API functions are provided by the client and called +from the demux code. + +The function pointers of this abstract interface are not packed into a structure as in the +other demux APIs, because the callback functions are registered and used independent +of each other. As an example, it is possible for the API client to provide several +callback functions for receiving TS packets and no callbacks for PES packets or +sections. + +The functions that implement the callback API need not be re-entrant: when a demux +driver calls one of these functions, the driver is not allowed to call the function again before +the original call returns. If a callback is triggered by a hardware interrupt, it is recommended +to use the Linux “bottom half” mechanism or start a tasklet instead of making the callback +function call directly from a hardware interrupt. + + +
<abbrev role="title-mark">8.4.1</abbrev>dmx_ts_cb()<indexterm role="printindex" /> +DESCRIPTION + +
+This function, provided by the client of the demux API, is called from the + demux code. The function is only called when filtering on this TS feed has + been enabled using the start_filtering() function. + + +Any TS packets that match the filter settings are copied to a circular buffer. The + filtered TS packets are delivered to the client using this callback function. The + size of the circular buffer is controlled by the circular_buffer_size parameter + of the set() function in the TS Feed API. It is expected that the buffer1 and + buffer2 callback parameters point to addresses within the circular buffer, but + other implementations are also possible. Note that the called party should not + try to free the memory the buffer1 and buffer2 parameters point to. + + +When this function is called, the buffer1 parameter typically points to the + start of the first undelivered TS packet within a circular buffer. The buffer2 + buffer parameter is normally NULL, except when the received TS packets have + crossed the last address of the circular buffer and ”wrapped” to the beginning + of the buffer. In the latter case the buffer1 parameter would contain an address + within the circular buffer, while the buffer2 parameter would contain the first + address of the circular buffer. + + +The number of bytes delivered with this function (i.e. buffer1_length + + buffer2_length) is usually equal to the value of callback_length parameter + given in the set() function, with one exception: if a timeout occurs before + receiving callback_length bytes of TS data, any undelivered packets are + immediately delivered to the client by calling this function. The timeout + duration is controlled by the set() function in the TS Feed API. + + +If a TS packet is received with errors that could not be fixed by the TS-level + forward error correction (FEC), the Transport_error_indicator flag of the TS + packet header should be set. The TS packet should not be discarded, as + the error can possibly be corrected by a higher layer protocol. If the called + party is slow in processing the callback, it is possible that the circular buffer + eventually fills up. If this happens, the demux driver should discard any TS + packets received while the buffer is full. The error should be indicated to the + client on the next callback by setting the success parameter to the value of + DMX_OVERRUN_ERROR. + + +The type of data returned to the callback can be selected by the new + function int (*set_type) (struct dmx_ts_feed_s* feed, int type, dmx_ts_pes_t + pes_type) which is part of the dmx_ts_feed_s struct (also cf. to the + include file ost/demux.h) The type parameter decides if the raw TS packet + (TS_PACKET) or just the payload (TS_PACKET—TS_PAYLOAD_ONLY) + should be returned. If additionally the TS_DECODER bit is set the stream + will also be sent to the hardware MPEG decoder. In this case, the second + flag decides as what kind of data the stream should be interpreted. The + possible choices are one of DMX_TS_PES_AUDIO, DMX_TS_PES_VIDEO, + DMX_TS_PES_TELETEXT, DMX_TS_PES_SUBTITLE, + DMX_TS_PES_PCR, or DMX_TS_PES_OTHER. + + +SYNOPSIS + + +int dmx_ts_cb(__u8⋆ buffer1, size_t buffer1_length, + __u8⋆ buffer2, size_t buffer2_length, dmx_ts_feed_t⋆ + source, dmx_success_t success); + + +PARAMETERS + + +__u8* buffer1 + +Pointer to the start of the filtered TS packets. + + +size_t buffer1_length + +Length of the TS data in buffer1. + + +__u8* buffer2 + +Pointer to the tail of the filtered TS packets, or NULL. + + +size_t buffer2_length + +Length of the TS data in buffer2. + + +dmx_ts_feed_t* + source + +Indicates which TS feed is the source of the callback. + + +dmx_success_t + success + +Indicates if there was an error in TS reception. + + +RETURNS + + +0 + +Continue filtering. + + +-1 + +Stop filtering - has the same effect as a call to + stop_filtering() on the TS Feed API. + + + +
<abbrev role="title-mark">8.4.2</abbrev>dmx_section_cb()<indexterm role="printindex" /> +DESCRIPTION + +
+This function, provided by the client of the demux API, is called from the + demux code. The function is only called when filtering of sections has been + enabled using the function start_filtering() of the section feed API. When the + demux driver has received a complete section that matches at least one section + filter, the client is notified via this callback function. Normally this function is + called for each received section; however, it is also possible to deliver multiple + sections with one callback, for example when the system load is high. If an + error occurs while receiving a section, this function should be called with + the corresponding error type set in the success field, whether or not there is + data to deliver. The Section Feed implementation should maintain a circular + buffer for received sections. However, this is not necessary if the Section Feed + API is implemented as a client of the TS Feed API, because the TS Feed + implementation then buffers the received data. The size of the circular buffer + can be configured using the set() function in the Section Feed API. If there + is no room in the circular buffer when a new section is received, the section + must be discarded. If this happens, the value of the success parameter should + be DMX_OVERRUN_ERROR on the next callback. + + +SYNOPSIS + + +int dmx_section_cb(__u8⋆ buffer1, size_t + buffer1_length, __u8⋆ buffer2, size_t + buffer2_length, dmx_section_filter_t⋆ source, + dmx_success_t success); + + +PARAMETERS + + +__u8* buffer1 + +Pointer to the start of the filtered section, e.g. within the + circular buffer of the demux driver. + + +size_t buffer1_length + +Length of the filtered section data in buffer1, including + headers and CRC. + + +__u8* buffer2 + +Pointer to the tail of the filtered section data, or NULL. + Useful to handle the wrapping of a circular buffer. + + +size_t buffer2_length + +Length of the filtered section data in buffer2, including + headers and CRC. + + +dmx_section_filter_t* + filter + +Indicates the filter that triggered the callback. + + +dmx_success_t + success + +Indicates if there was an error in section reception. + + +RETURNS + + +0 + +Continue filtering. + + +-1 + +Stop filtering - has the same effect as a call to + stop_filtering() on the Section Feed API. + + +
<abbrev role="title-mark">8.5</abbrev>TS Feed API +A TS feed is typically mapped to a hardware PID filter on the demux chip. +Using this API, the client can set the filtering properties to start/stop filtering TS +packets on a particular TS feed. The API is defined as an abstract interface of the type +dmx_ts_feed_t. + +The functions that implement the interface should be defined static or module private. The +client can get the handle of a TS feed API by calling the function allocate_ts_feed() in the +demux API. + + +
<abbrev role="title-mark">8.5.1</abbrev>set()<indexterm role="printindex" /> +DESCRIPTION + +
+This function sets the parameters of a TS feed. Any filtering in progress on the + TS feed must be stopped before calling this function. + + +SYNOPSIS + + +int set ( dmx_ts_feed_t⋆ feed, __u16 pid, size_t + callback_length, size_t circular_buffer_size, int + descramble, struct timespec timeout); + + +PARAMETERS + + +dmx_ts_feed_t* feed + +Pointer to the TS feed API and instance data. + + +__u16 pid + +PID value to filter. Only the TS packets carrying the + specified PID will be passed to the API client. + + +size_t + callback_length + +Number of bytes to deliver with each call to the + dmx_ts_cb() callback function. The value of this + parameter should be a multiple of 188. + + +size_t + circular_buffer_size + +Size of the circular buffer for the filtered TS packets. + + +int descramble + +If non-zero, descramble the filtered TS packets. + + +struct timespec + timeout + +Maximum time to wait before delivering received TS + packets to the client. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOMEM + +Not enough memory for the requested buffer size. + + +-ENOSYS + +No descrambling facility available for TS. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.5.2</abbrev>start_filtering()<indexterm role="printindex" /> +DESCRIPTION + +
+Starts filtering TS packets on this TS feed, according to its settings. The PID + value to filter can be set by the API client. All matching TS packets are + delivered asynchronously to the client, using the callback function registered + with allocate_ts_feed(). + + +SYNOPSIS + + +int start_filtering(dmx_ts_feed_t⋆ feed); + + +PARAMETERS + + +dmx_ts_feed_t* feed + +Pointer to the TS feed API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.5.3</abbrev>stop_filtering()<indexterm role="printindex" /> +DESCRIPTION + +
+Stops filtering TS packets on this TS feed. + + +SYNOPSIS + + +int stop_filtering(dmx_ts_feed_t⋆ feed); + + +PARAMETERS + + +dmx_ts_feed_t* feed + +Pointer to the TS feed API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + +
<abbrev role="title-mark">8.6</abbrev>Section Feed API +A section feed is a resource consisting of a PID filter and a set of section filters. Using this +API, the client can set the properties of a section feed and to start/stop filtering. The API is +defined as an abstract interface of the type dmx_section_feed_t. The functions that implement +the interface should be defined static or module private. The client can get the handle of +a section feed API by calling the function allocate_section_feed() in the demux +API. + +On demux platforms that provide section filtering in hardware, the Section Feed API +implementation provides a software wrapper for the demux hardware. Other platforms may +support only PID filtering in hardware, requiring that TS packets are converted to sections in +software. In the latter case the Section Feed API implementation can be a client of the TS +Feed API. + + +
<abbrev role="title-mark">8.6.1</abbrev>set()<indexterm role="printindex" /> +DESCRIPTION + +
+This function sets the parameters of a section feed. Any filtering in progress on + the section feed must be stopped before calling this function. If descrambling + is enabled, the payload_scrambling_control and address_scrambling_control + fields of received DVB datagram sections should be observed. If either one is + non-zero, the section should be descrambled either in hardware or using the + functions descramble_mac_address() and descramble_section_payload() of the + demux API. Note that according to the MPEG-2 Systems specification, only + the payloads of private sections can be scrambled while the rest of the section + data must be sent in the clear. + + +SYNOPSIS + + +int set(dmx_section_feed_t⋆ feed, __u16 pid, size_t + circular_buffer_size, int descramble, int + check_crc); + + +PARAMETERS + + +dmx_section_feed_t* + feed + +Pointer to the section feed API and instance data. + + +__u16 pid + +PID value to filter; only the TS packets carrying the + specified PID will be accepted. + + +size_t + circular_buffer_size + +Size of the circular buffer for filtered sections. + + +int descramble + +If non-zero, descramble any sections that are scrambled. + + +int check_crc + +If non-zero, check the CRC values of filtered sections. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOMEM + +Not enough memory for the requested buffer size. + + +-ENOSYS + +No descrambling facility available for sections. + + +-EINVAL + +Bad parameters. + + + +
<abbrev role="title-mark">8.6.2</abbrev>allocate_filter()<indexterm role="printindex" /> +DESCRIPTION + +
+This function is used to allocate a section filter on the demux. It should only be + called when no filtering is in progress on this section feed. If a filter cannot be + allocated, the function fails with -ENOSPC. See in section ?? for the format of + the section filter. + + +The bitfields filter_mask and filter_value should only be modified when no + filtering is in progress on this section feed. filter_mask controls which bits of + filter_value are compared with the section headers/payload. On a binary value + of 1 in filter_mask, the corresponding bits are compared. The filter only accepts + sections that are equal to filter_value in all the tested bit positions. Any changes + to the values of filter_mask and filter_value are guaranteed to take effect only + when the start_filtering() function is called next time. The parent pointer in + the struct is initialized by the API implementation to the value of the feed + parameter. The priv pointer is not used by the API implementation, and can + thus be freely utilized by the caller of this function. Any data pointed to by the + priv pointer is available to the recipient of the dmx_section_cb() function call. + + +While the maximum section filter length (DMX_MAX_FILTER_SIZE) is + currently set at 16 bytes, hardware filters of that size are not available on all + platforms. Therefore, section filtering will often take place first in hardware, + followed by filtering in software for the header bytes that were not covered + by a hardware filter. The filter_mask field can be checked to determine how + many bytes of the section filter are actually used, and if the hardware filter will + suffice. Additionally, software-only section filters can optionally be allocated + to clients when all hardware section filters are in use. Note that on most demux + hardware it is not possible to filter on the section_length field of the section + header – thus this field is ignored, even though it is included in filter_value and + filter_mask fields. + + +SYNOPSIS + + +int allocate_filter(dmx_section_feed_t⋆ feed, + dmx_section_filter_t⋆⋆ filter); + + +PARAMETERS + + +dmx_section_feed_t* + feed + +Pointer to the section feed API and instance data. + + +dmx_section_filter_t** + filter + +Pointer to the allocated filter. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOSPC + +No filters of given type and length available. + + +-EINVAL + +Bad parameters. + + + +
<abbrev role="title-mark">8.6.3</abbrev>release_filter()<indexterm role="printindex" /> +DESCRIPTION + +
+This function releases all the resources of a previously allocated section filter. + The function should not be called while filtering is in progress on this section + feed. After calling this function, the caller should not try to dereference the + filter pointer. + + +SYNOPSIS + + +int release_filter ( dmx_section_feed_t⋆ feed, + dmx_section_filter_t⋆ filter); + + +PARAMETERS + + +dmx_section_feed_t* + feed + +Pointer to the section feed API and instance data. + + +dmx_section_filter_t* + filter + +I/O Pointer to the instance data of a section filter. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENODEV + +No such filter allocated. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.6.4</abbrev>start_filtering()<indexterm role="printindex" /> +DESCRIPTION + +
+Starts filtering sections on this section feed, according to its settings. Sections + are first filtered based on their PID and then matched with the section + filters allocated for this feed. If the section matches the PID filter and + at least one section filter, it is delivered to the API client. The section + is delivered asynchronously using the callback function registered with + allocate_section_feed(). + + +SYNOPSIS + + +int start_filtering ( dmx_section_feed_t⋆ feed ); + + +PARAMETERS + + +dmx_section_feed_t* + feed + +Pointer to the section feed API and instance data. + + + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + +
<abbrev role="title-mark">8.6.5</abbrev>stop_filtering()<indexterm role="printindex" /> +DESCRIPTION + +
+Stops filtering sections on this section feed. Note that any changes to the + filtering parameters (filter_value, filter_mask, etc.) should only be made when + filtering is stopped. + + +SYNOPSIS + + +int stop_filtering ( dmx_section_feed_t⋆ feed ); + + +PARAMETERS + + +dmx_section_feed_t* + feed + +Pointer to the section feed API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + +
Examples +In this section we would like to present some examples for using the DVB API. + +Maintainer note: This section is out of date. Please refer to the sample programs packaged +with the driver distribution from http://linuxtv.org/. + +
<abbrev role="title-mark">9.1</abbrev>Tuning +We will start with a generic tuning subroutine that uses the frontend and SEC, as well as +the demux devices. The example is given for QPSK tuners, but can easily be adjusted for +QAM. + + + #include <sys/ioctl.h> + #include <stdio.h> + #include <stdint.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> + #include <time.h> + #include <unistd.h> + + #include <linux/dvb/dmx.h> + #include <linux/dvb/frontend.h> + #include <linux/dvb/sec.h> + #include <sys/poll.h> + + #define DMX "/dev/dvb/adapter0/demux1" + #define FRONT "/dev/dvb/adapter0/frontend1" + #define SEC "/dev/dvb/adapter0/sec1" + + /⋆ routine for checking if we have a signal and other status information⋆/ + int FEReadStatus(int fd, fe_status_t ⋆stat) + { + int ans; + + if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){ + perror("FE READ STATUS: "); + return -1; + } + + if (⋆stat & FE_HAS_POWER) + printf("FE HAS POWER\n"); + + if (⋆stat & FE_HAS_SIGNAL) + printf("FE HAS SIGNAL\n"); + + if (⋆stat & FE_SPECTRUM_INV) + printf("SPEKTRUM INV\n"); + + return 0; + } + + + /⋆ tune qpsk ⋆/ + /⋆ freq: frequency of transponder ⋆/ + /⋆ vpid, apid, tpid: PIDs of video, audio and teletext TS packets ⋆/ + /⋆ diseqc: DiSEqC address of the used LNB ⋆/ + /⋆ pol: Polarisation ⋆/ + /⋆ srate: Symbol Rate ⋆/ + /⋆ fec. FEC ⋆/ + /⋆ lnb_lof1: local frequency of lower LNB band ⋆/ + /⋆ lnb_lof2: local frequency of upper LNB band ⋆/ + /⋆ lnb_slof: switch frequency of LNB ⋆/ + + int set_qpsk_channel(int freq, int vpid, int apid, int tpid, + int diseqc, int pol, int srate, int fec, int lnb_lof1, + int lnb_lof2, int lnb_slof) + { + struct secCommand scmd; + struct secCmdSequence scmds; + struct dmx_pes_filter_params pesFilterParams; + FrontendParameters frp; + struct pollfd pfd[1]; + FrontendEvent event; + int demux1, demux2, demux3, front; + + frequency = (uint32_t) freq; + symbolrate = (uint32_t) srate; + + if((front = open(FRONT,O_RDWR)) < 0){ + perror("FRONTEND DEVICE: "); + return -1; + } + + if((sec = open(SEC,O_RDWR)) < 0){ + perror("SEC DEVICE: "); + return -1; + } + + if (demux1 < 0){ + if ((demux1=open(DMX, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + if (demux2 < 0){ + if ((demux2=open(DMX, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + if (demux3 < 0){ + if ((demux3=open(DMX, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + if (freq < lnb_slof) { + frp.Frequency = (freq - lnb_lof1); + scmds.continuousTone = SEC_TONE_OFF; + } else { + frp.Frequency = (freq - lnb_lof2); + scmds.continuousTone = SEC_TONE_ON; + } + frp.Inversion = INVERSION_AUTO; + if (pol) scmds.voltage = SEC_VOLTAGE_18; + else scmds.voltage = SEC_VOLTAGE_13; + + scmd.type=0; + scmd.u.diseqc.addr=0x10; + scmd.u.diseqc.cmd=0x38; + scmd.u.diseqc.numParams=1; + scmd.u.diseqc.params[0] = 0xF0 | ((diseqc ⋆ 4) & 0x0F) | + (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) | + (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0); + + scmds.miniCommand=SEC_MINI_NONE; + scmds.numCommands=1; + scmds.commands=&scmd; + if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){ + perror("SEC SEND: "); + return -1; + } + + if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){ + perror("SEC SEND: "); + return -1; + } + + frp.u.qpsk.SymbolRate = srate; + frp.u.qpsk.FEC_inner = fec; + + if (ioctl(front, FE_SET_FRONTEND, &frp) < 0){ + perror("QPSK TUNE: "); + return -1; + } + + pfd[0].fd = front; + pfd[0].events = POLLIN; + + if (poll(pfd,1,3000)){ + if (pfd[0].revents & POLLIN){ + printf("Getting QPSK event\n"); + if ( ioctl(front, FE_GET_EVENT, &event) + + == -EOVERFLOW){ + perror("qpsk get event"); + return -1; + } + printf("Received "); + switch(event.type){ + case FE_UNEXPECTED_EV: + printf("unexpected event\n"); + return -1; + case FE_FAILURE_EV: + printf("failure event\n"); + return -1; + + case FE_COMPLETION_EV: + printf("completion event\n"); + } + } + } + + + pesFilterParams.pid = vpid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_DECODER; + pesFilterParams.pes_type = DMX_PES_VIDEO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("set_vpid"); + return -1; + } + + pesFilterParams.pid = apid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_DECODER; + pesFilterParams.pes_type = DMX_PES_AUDIO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("set_apid"); + return -1; + } + + pesFilterParams.pid = tpid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_DECODER; + pesFilterParams.pes_type = DMX_PES_TELETEXT; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux3, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("set_tpid"); + return -1; + } + + return has_signal(fds); + } + + +The program assumes that you are using a universal LNB and a standard DiSEqC +switch with up to 4 addresses. Of course, you could build in some more checking if +tuning was successful and maybe try to repeat the tuning process. Depending on the +external hardware, i.e. LNB and DiSEqC switch, and weather conditions this may be +necessary. + + +
<abbrev role="title-mark">9.2</abbrev>The DVR device +The following program code shows how to use the DVR device for recording. + + + #include <sys/ioctl.h> + #include <stdio.h> + #include <stdint.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> + #include <time.h> + #include <unistd.h> + + #include <linux/dvb/dmx.h> + #include <linux/dvb/video.h> + #include <sys/poll.h> + #define DVR "/dev/dvb/adapter0/dvr1" + #define AUDIO "/dev/dvb/adapter0/audio1" + #define VIDEO "/dev/dvb/adapter0/video1" + + #define BUFFY (188⋆20) + #define MAX_LENGTH (1024⋆1024⋆5) /⋆ record 5MB ⋆/ + + + /⋆ switch the demuxes to recording, assuming the transponder is tuned ⋆/ + + /⋆ demux1, demux2: file descriptor of video and audio filters ⋆/ + /⋆ vpid, apid: PIDs of video and audio channels ⋆/ + + int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid) + { + struct dmx_pes_filter_params pesFilterParams; + + if (demux1 < 0){ + if ((demux1=open(DMX, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + if (demux2 < 0){ + if ((demux2=open(DMX, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + pesFilterParams.pid = vpid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_TS_TAP; + pesFilterParams.pes_type = DMX_PES_VIDEO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("DEMUX DEVICE"); + return -1; + } + pesFilterParams.pid = apid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_TS_TAP; + pesFilterParams.pes_type = DMX_PES_AUDIO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("DEMUX DEVICE"); + return -1; + } + return 0; + } + + /⋆ start recording MAX_LENGTH , assuming the transponder is tuned ⋆/ + + /⋆ demux1, demux2: file descriptor of video and audio filters ⋆/ + /⋆ vpid, apid: PIDs of video and audio channels ⋆/ + int record_dvr(int demux1, int demux2, uint16_t vpid, uint16_t apid) + { + int i; + int len; + int written; + uint8_t buf[BUFFY]; + uint64_t length; + struct pollfd pfd[1]; + int dvr, dvr_out; + + /⋆ open dvr device ⋆/ + if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){ + perror("DVR DEVICE"); + return -1; + } + + /⋆ switch video and audio demuxes to dvr ⋆/ + printf ("Switching dvr on\n"); + i = switch_to_record(demux1, demux2, vpid, apid); + printf("finished: "); + + printf("Recording %2.0f MB of test file in TS format\n", + MAX_LENGTH/(1024.0⋆1024.0)); + length = 0; + + /⋆ open output file ⋆/ + if ((dvr_out = open(DVR_FILE,O_WRONLY|O_CREAT + |O_TRUNC, S_IRUSR|S_IWUSR + |S_IRGRP|S_IWGRP|S_IROTH| + S_IWOTH)) < 0){ + perror("Can't open file for dvr test"); + return -1; + } + + pfd[0].fd = dvr; + pfd[0].events = POLLIN; + + /⋆ poll for dvr data and write to file ⋆/ + while (length < MAX_LENGTH ) { + if (poll(pfd,1,1)){ + if (pfd[0].revents & POLLIN){ + len = read(dvr, buf, BUFFY); + if (len < 0){ + perror("recording"); + return -1; + } + if (len > 0){ + written = 0; + while (written < len) + written += + write (dvr_out, + buf, len); + length += len; + printf("written %2.0f MB\r", + length/1024./1024.); + } + } + } + } + return 0; + } + + + + + +
GNU Free Documentation License +Version 1.1, March 2000 + +Copyright 2000 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +Everyone is permitted to copy and distribute verbatim copies of this license document, but +changing it is not allowed. + +
Preamble +The purpose of this License is to make a manual, textbook, or other written document +“free” in the sense of freedom: to assure everyone the effective freedom to copy and +redistribute it, with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way to get credit +for their work, while not being considered responsible for modifications made by +others. + +This License is a kind of “copyleft”, which means that derivative works of the document +must themselves be free in the same sense. It complements the GNU General Public License, +which is a copyleft license designed for free software. + +We have designed this License in order to use it for manuals for free software, because +free software needs free documentation: a free program should come with manuals providing +the same freedoms that the software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or whether it is published as a +printed book. We recommend this License principally for works whose purpose is instruction +or reference. + + +
<abbrev role="title-mark">A.1</abbrev>Applicability and Definitions +This License applies to any manual or other work that contains a notice placed by the +copyright holder saying it can be distributed under the terms of this License. The +“Document”, below, refers to any such manual or work. Any member of the public is a +licensee, and is addressed as “you”. + +A “Modified Version” of the Document means any work containing the Document or a +portion of it, either copied verbatim, or with modifications and/or translated into another +language. + +A “Secondary Section” is a named appendix or a front-matter section of the Document +that deals exclusively with the relationship of the publishers or authors of the Document to +the Document’s overall subject (or to related matters) and contains nothing that could +fall directly within that overall subject. (For example, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any mathematics.) The +relationship could be a matter of historical connection with the subject or with related +matters, or of legal, commercial, philosophical, ethical or political position regarding +them. + +The “Invariant Sections” are certain Secondary Sections whose titles are designated, as +being those of Invariant Sections, in the notice that says that the Document is released under +this License. + +The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts +or Back-Cover Texts, in the notice that says that the Document is released under this +License. + +A “Transparent” copy of the Document means a machine-readable copy, represented in a +format whose specification is available to the general public, whose contents can be viewed +and edited directly and straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available drawing editor, and +that is suitable for input to text formatters or for automatic translation to a variety of +formats suitable for input to text formatters. A copy made in an otherwise Transparent +file format whose markup has been designed to thwart or discourage subsequent +modification by readers is not Transparent. A copy that is not “Transparent” is called +“Opaque”. + +Examples of suitable formats for Transparent copies include plain ASCII without markup, +Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, +and standard-conforming simple HTML designed for human modification. Opaque formats +include PostScript, PDF, proprietary formats that can be read and edited only by proprietary +word processors, SGML or XML for which the DTD and/or processing tools are not +generally available, and the machine-generated HTML produced by some word processors +for output purposes only. + +The “Title Page” means, for a printed book, the title page itself, plus such following pages +as are needed to hold, legibly, the material this License requires to appear in the title page. +For works in formats which do not have any title page as such, “Title Page” means the text +near the most prominent appearance of the work’s title, preceding the beginning of the body +of the text. + + +
<abbrev role="title-mark">A.2</abbrev>Verbatim Copying +You may copy and distribute the Document in any medium, either commercially or +noncommercially, provided that this License, the copyright notices, and the license notice +saying this License applies to the Document are reproduced in all copies, and that you add no +other conditions whatsoever to those of this License. You may not use technical measures to +obstruct or control the reading or further copying of the copies you make or distribute. +However, you may accept compensation in exchange for copies. If you distribute +a large enough number of copies you must also follow the conditions in section +3. + +You may also lend copies, under the same conditions stated above, and you may publicly +display copies. + + +
<abbrev role="title-mark">A.3</abbrev>Copying in Quantity +If you publish printed copies of the Document numbering more than 100, and the +Document’s license notice requires Cover Texts, you must enclose the copies in covers that +carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and +Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you +as the publisher of these copies. The front cover must present the full title with all words of +the title equally prominent and visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve the title of the +Document and satisfy these conditions, can be treated as verbatim copying in other +respects. + +If the required texts for either cover are too voluminous to fit legibly, you should put the +first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto +adjacent pages. + +If you publish or distribute Opaque copies of the Document numbering more than 100, +you must either include a machine-readable Transparent copy along with each Opaque copy, +or state in or with each Opaque copy a publicly-accessible computer-network location +containing a complete Transparent copy of the Document, free of added material, +which the general network-using public has access to download anonymously at +no charge using public-standard network protocols. If you use the latter option, +you must take reasonably prudent steps, when you begin distribution of Opaque +copies in quantity, to ensure that this Transparent copy will remain thus accessible +at the stated location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that edition to the +public. + +It is requested, but not required, that you contact the authors of the Document well before +redistributing any large number of copies, to give them a chance to provide you with an +updated version of the Document. + + +
<abbrev role="title-mark">A.4</abbrev>Modifications +You may copy and distribute a Modified Version of the Document under the conditions of +sections 2 and 3 above, provided that you release the Modified Version under precisely this +License, with the Modified Version filling the role of the Document, thus licensing +distribution and modification of the Modified Version to whoever possesses a copy of it. In +addition, you must do these things in the Modified Version: + + + + +Use in the Title Page (and on the covers, if any) a title distinct from that of the + Document, and from those of previous versions (which should, if there were any, + be listed in the History section of the Document). You may use the same title as + a previous version if the original publisher of that version gives permission. + + + +List on the Title Page, as authors, one or more persons or entities responsible for + authorship of the modifications in the Modified Version, together with at least + five of the principal authors of the Document (all of its principal authors, if it has + less than five). + + + +State on the Title page the name of the publisher of the Modified Version, as the + publisher. + + + +Preserve all the copyright notices of the Document. + + + +Add an appropriate copyright notice for your modifications adjacent to the other + copyright notices. + + + +Include, immediately after the copyright notices, a license notice giving the + public permission to use the Modified Version under the terms of this License, + in the form shown in the Addendum below. + + + +Preserve in that license notice the full lists of Invariant Sections and required + Cover Texts given in the Document’s license notice. + + + +Include an unaltered copy of this License. + + + +Preserve the section entitled “History”, and its title, and add to it an item stating + at least the title, year, new authors, and publisher of the Modified Version as + given on the Title Page. If there is no section entitled “History” in the Document, + create one stating the title, year, authors, and publisher of the Document as given + on its Title Page, then add an item describing the Modified Version as stated in + the previous sentence. + + + +Preserve the network location, if any, given in the Document for public access + to a Transparent copy of the Document, and likewise the network locations + given in the Document for previous versions it was based on. These may be + placed in the “History” section. You may omit a network location for a work that + was published at least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. + + + +In any section entitled “Acknowledgements” or “Dedications”, preserve the + section’s title, and preserve in the section all the substance and tone of each of + the contributor acknowledgements and/or dedications given therein. + + + +Preserve all the Invariant Sections of the Document, unaltered in their text and + in their titles. Section numbers or the equivalent are not considered part of the + section titles. + + + +Delete any section entitled “Endorsements”. Such a section may not be included + in the Modified Version. + + + +Do not retitle any existing section as “Endorsements” or to conflict in title with + any Invariant Section. + + +If the Modified Version includes new front-matter sections or appendices that qualify as +Secondary Sections and contain no material copied from the Document, you may at your +option designate some or all of these sections as invariant. To do this, add their titles to the list +of Invariant Sections in the Modified Version’s license notice. These titles must be distinct +from any other section titles. + +You may add a section entitled “Endorsements”, provided it contains nothing but +endorsements of your Modified Version by various parties – for example, statements of peer +review or that the text has been approved by an organization as the authoritative definition of +a standard. + +You may add a passage of up to five words as a Front-Cover Text, and a passage of up to +25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. +Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already includes a cover text +for the same cover, previously added by you or by arrangement made by the same +entity you are acting on behalf of, you may not add another; but you may replace +the old one, on explicit permission from the previous publisher that added the old +one. + +The author(s) and publisher(s) of the Document do not by this License give permission to +use their names for publicity for or to assert or imply endorsement of any Modified +Version. + + +
<abbrev role="title-mark">A.5</abbrev>Combining Documents +You may combine the Document with other documents released under this License, under +the terms defined in section 4 above for modified versions, provided that you include +in the combination all of the Invariant Sections of all of the original documents, +unmodified, and list them all as Invariant Sections of your combined work in its license +notice. + +The combined work need only contain one copy of this License, and multiple identical +Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections +with the same name but different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original author or publisher of +that section if known, or else a unique number. Make the same adjustment to the +section titles in the list of Invariant Sections in the license notice of the combined +work. + +In the combination, you must combine any sections entitled “History” in the various +original documents, forming one section entitled “History”; likewise combine any sections +entitled “Acknowledgements”, and any sections entitled “Dedications”. You must delete all +sections entitled “Endorsements.” + + +
<abbrev role="title-mark">A.6</abbrev>Collections of Documents +You may make a collection consisting of the Document and other documents released +under this License, and replace the individual copies of this License in the various documents +with a single copy that is included in the collection, provided that you follow the +rules of this License for verbatim copying of each of the documents in all other +respects. + +You may extract a single document from such a collection, and distribute it individually +under this License, provided you insert a copy of this License into the extracted document, +and follow this License in all other respects regarding verbatim copying of that +document. + + +
<abbrev role="title-mark">A.7</abbrev>Aggregation With Independent Works +A compilation of the Document or its derivatives with other separate and independent +documents or works, in or on a volume of a storage or distribution medium, does not as a +whole count as a Modified Version of the Document, provided no compilation copyright is +claimed for the compilation. Such a compilation is called an “aggregate”, and this License +does not apply to the other self-contained works thus compiled with the Document, on +account of their being thus compiled, if they are not themselves derivative works of the +Document. + +If the Cover Text requirement of section 3 is applicable to these copies of the Document, +then if the Document is less than one quarter of the entire aggregate, the Document’s Cover +Texts may be placed on covers that surround only the Document within the aggregate. +Otherwise they must appear on covers around the whole aggregate. + + +
<abbrev role="title-mark">A.8</abbrev>Translation +Translation is considered a kind of modification, so you may distribute translations of the +Document under the terms of section 4. Replacing Invariant Sections with translations +requires special permission from their copyright holders, but you may include translations of +some or all Invariant Sections in addition to the original versions of these Invariant Sections. +You may include a translation of this License provided that you also include the original +English version of this License. In case of a disagreement between the translation +and the original English version of this License, the original English version will +prevail. + + +
<abbrev role="title-mark">A.9</abbrev>Termination +You may not copy, modify, sublicense, or distribute the Document except as expressly +provided for under this License. Any other attempt to copy, modify, sublicense or +distribute the Document is void, and will automatically terminate your rights under this +License. However, parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such parties remain in full +compliance. + + +
<abbrev role="title-mark">A.10</abbrev>Future Revisions of This License +The Free Software Foundation may publish new, revised versions of the GNU Free +Documentation License from time to time. Such new versions will be similar in spirit to the +present version, but may differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. If the Document +specifies that a particular numbered version of this License ”or any later version” applies to it, +you have the option of following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the Free Software +Foundation. If the Document does not specify a version number of this License, +you may choose any version ever published (not as a draft) by the Free Software +Foundation. + + +
ADDENDUM: How to use this License for your documents +To use this License in a document you have written, include a copy of the License in the +document and put the following copyright and license notices just after the title +page: + + +Copyright YEAR YOUR NAME. Permission is granted to copy, + distribute and/or modify this document under the terms of the GNU Free + Documentation License, Version 1.1 or any later version published by the + Free Software Foundation; with the Invariant Sections being LIST THEIR + TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover + Texts being LIST. A copy of the license is included in the section entitled + “GNU Free Documentation License”. + +If you have no Invariant Sections, write “with no Invariant Sections” instead +of saying which ones are invariant. If you have no Front-Cover Texts, write “no +Front-Cover Texts” instead of “Front-Cover Texts being LIST”; likewise for Back-Cover +Texts. + +If your document contains nontrivial examples of program code, we recommend releasing +these examples in parallel under your choice of free software license, such as the GNU +General Public License, to permit their use in free software. + + + + +
diff --git a/dvb-spec/sgml/dvbapi.sgml b/dvb-spec/sgml/dvbapi.sgml new file mode 100644 index 000000000..e6f5674b8 --- /dev/null +++ b/dvb-spec/sgml/dvbapi.sgml @@ -0,0 +1,97 @@ + + %entities; +2C"> +]> + + + +LINUX DVB API +Version 3 + + +Ralph +Metzler +J. K. +
rjkm@metzlerbros.de
+
+ +Marcus +Metzler +O. C. +
rjkm@metzlerbros.de
+
+ +Mauro +Chehab +Carvalho +
mchehab@infradead.org
+
+
+ + +2002 +2003 +2009 +Convergence GmbH + + + +Permission is granted to copy, distribute and/or modify +this document under the terms of the GNU Free Documentation License, +Version 1.1 or any later version published by the Free Software +Foundation. A copy of the license is included in the chapter entitled +"GNU Free Documentation License" + + + + + +2.0.0 +2009-09-06 +mcc +Conversion from LaTex to DocBook XML. The +contents is the same as the original LaTex version. + + +1.0.0 +2003-07-24 +rjkm +Initial revision on LaTEX. + + + +
+ + + + + + &sub-intro; + + + &sub-frontend; + + + + +
diff --git a/dvb-spec/sgml/dvbstb.pdf b/dvb-spec/sgml/dvbstb.pdf new file mode 100644 index 000000000..5a4eff6cb Binary files /dev/null and b/dvb-spec/sgml/dvbstb.pdf differ diff --git a/dvb-spec/sgml/dvbstb.png b/dvb-spec/sgml/dvbstb.png new file mode 100644 index 000000000..9b8f372e7 Binary files /dev/null and b/dvb-spec/sgml/dvbstb.png differ diff --git a/dvb-spec/sgml/examples.sgml b/dvb-spec/sgml/examples.sgml new file mode 100644 index 000000000..e69de29bb diff --git a/dvb-spec/sgml/fdl.sgml b/dvb-spec/sgml/fdl.sgml new file mode 100644 index 000000000..e69de29bb diff --git a/dvb-spec/sgml/frontend.sgml b/dvb-spec/sgml/frontend.sgml new file mode 100644 index 000000000..d2a6ece04 --- /dev/null +++ b/dvb-spec/sgml/frontend.sgml @@ -0,0 +1,1816 @@ +DVB Frontend API + +The DVB frontend device controls the tuner and DVB demodulator +hardware. It can be accessed through /dev/dvb/adapter0/frontend0. Data types and and +ioctl definitions can be accessed by including linux/dvb/frontend.h in your application. + +DVB frontends come in three varieties: DVB-S (satellite), DVB-C +(cable) and DVB-T (terrestrial). Transmission via the internet (DVB-IP) +is not yet handled by this API but a future extension is possible. For +DVB-S the frontend device also supports satellite equipment control +(SEC) via DiSEqC and V-SEC protocols. The DiSEqC (digital SEC) +specification is available from Eutelsat http://www.eutelsat.org/. + +Note that the DVB API may also be used for MPEG decoder-only PCI +cards, in which case there exists no frontend device. + +
+Frontend Data Types + +
+frontend type + +For historical reasons frontend types are named after the type of modulation used in +transmission. + + typedef enum fe_type { + FE_QPSK, /⋆ DVB-S ⋆/ + FE_QAM, /⋆ DVB-C ⋆/ + FE_OFDM /⋆ DVB-T ⋆/ + } fe_type_t; + + +
+ +
+frontend capabilities + +Capabilities describe what a frontend can do. Some capabilities can only be supported for +a specific frontend type. + + typedef enum fe_caps { + FE_IS_STUPID = 0, + FE_CAN_INVERSION_AUTO = 0x1, + FE_CAN_FEC_1_2 = 0x2, + FE_CAN_FEC_2_3 = 0x4, + FE_CAN_FEC_3_4 = 0x8, + FE_CAN_FEC_4_5 = 0x10, + FE_CAN_FEC_5_6 = 0x20, + FE_CAN_FEC_6_7 = 0x40, + FE_CAN_FEC_7_8 = 0x80, + FE_CAN_FEC_8_9 = 0x100, + FE_CAN_FEC_AUTO = 0x200, + FE_CAN_QPSK = 0x400, + FE_CAN_QAM_16 = 0x800, + FE_CAN_QAM_32 = 0x1000, + FE_CAN_QAM_64 = 0x2000, + FE_CAN_QAM_128 = 0x4000, + FE_CAN_QAM_256 = 0x8000, + FE_CAN_QAM_AUTO = 0x10000, + FE_CAN_TRANSMISSION_MODE_AUTO = 0x20000, + FE_CAN_BANDWIDTH_AUTO = 0x40000, + FE_CAN_GUARD_INTERVAL_AUTO = 0x80000, + FE_CAN_HIERARCHY_AUTO = 0x100000, + FE_CAN_MUTE_TS = 0x80000000, + FE_CAN_CLEAN_SETUP = 0x40000000 + } fe_caps_t; + +
+ +
+frontend information + +Information about the frontend ca be queried with FE_GET_INFO. + + + struct dvb_frontend_info { + char name[128]; + fe_type_t type; + uint32_t frequency_min; + uint32_t frequency_max; + uint32_t frequency_stepsize; + uint32_t frequency_tolerance; + uint32_t symbol_rate_min; + uint32_t symbol_rate_max; + uint32_t symbol_rate_tolerance; /⋆ ppm ⋆/ + uint32_t notifier_delay; /⋆ ms ⋆/ + fe_caps_t caps; + }; + +
+ +
+diseqc master command + +A message sent from the frontend to DiSEqC capable equipment. + + struct dvb_diseqc_master_cmd { + uint8_t msg [6]; /⋆ { framing, address, command, data[3] } ⋆/ + uint8_t msg_len; /⋆ valid values are 3...6 ⋆/ + }; + +
+
+diseqc slave reply + +A reply to the frontend from DiSEqC 2.0 capable equipment. + + struct dvb_diseqc_slave_reply { + uint8_t msg [4]; /⋆ { framing, data [3] } ⋆/ + uint8_t msg_len; /⋆ valid values are 0...4, 0 means no msg ⋆/ + int timeout; /⋆ return from ioctl after timeout ms with ⋆/ + }; /⋆ errorcode when no message was received ⋆/ + +
+ +
+diseqc slave reply +The voltage is usually used with non-DiSEqC capable LNBs to switch the polarzation +(horizontal/vertical). When using DiSEqC epuipment this voltage has to be switched +consistently to the DiSEqC commands as described in the DiSEqC spec. + + typedef enum fe_sec_voltage { + SEC_VOLTAGE_13, + SEC_VOLTAGE_18 + } fe_sec_voltage_t; + +
+ +
+SEC continuous tone + +The continous 22KHz tone is usually used with non-DiSEqC capable LNBs to switch the +high/low band of a dual-band LNB. When using DiSEqC epuipment this voltage has to +be switched consistently to the DiSEqC commands as described in the DiSEqC +spec. + + typedef enum fe_sec_tone_mode { + SEC_TONE_ON, + SEC_TONE_OFF + } fe_sec_tone_mode_t; + +
+ +
+SEC tone burst + +The 22KHz tone burst is usually used with non-DiSEqC capable switches to select +between two connected LNBs/satellites. When using DiSEqC epuipment this voltage has to +be switched consistently to the DiSEqC commands as described in the DiSEqC +spec. + + typedef enum fe_sec_mini_cmd { + SEC_MINI_A, + SEC_MINI_B + } fe_sec_mini_cmd_t; + + + +
+ +
+frontend status +Several functions of the frontend device use the fe_status data type defined +by + + typedef enum fe_status { + FE_HAS_SIGNAL = 0x01, /⋆ found something above the noise level ⋆/ + FE_HAS_CARRIER = 0x02, /⋆ found a DVB signal ⋆/ + FE_HAS_VITERBI = 0x04, /⋆ FEC is stable ⋆/ + FE_HAS_SYNC = 0x08, /⋆ found sync bytes ⋆/ + FE_HAS_LOCK = 0x10, /⋆ everything's working... ⋆/ + FE_TIMEDOUT = 0x20, /⋆ no lock within the last ~2 seconds ⋆/ + FE_REINIT = 0x40 /⋆ frontend was reinitialized, ⋆/ + } fe_status_t; /⋆ application is recommned to reset ⋆/ + +to indicate the current state and/or state changes of the frontend hardware. + + +
+ +
+frontend parameters +The kind of parameters passed to the frontend device for tuning depend on +the kind of hardware you are using. All kinds of parameters are combined as an +union in the FrontendParameters structure: + + struct dvb_frontend_parameters { + uint32_t frequency; /⋆ (absolute) frequency in Hz for QAM/OFDM ⋆/ + /⋆ intermediate frequency in kHz for QPSK ⋆/ + fe_spectral_inversion_t inversion; + union { + struct dvb_qpsk_parameters qpsk; + struct dvb_qam_parameters qam; + struct dvb_ofdm_parameters ofdm; + } u; + }; + +For satellite QPSK frontends you have to use the QPSKParameters member defined by + + struct dvb_qpsk_parameters { + uint32_t symbol_rate; /⋆ symbol rate in Symbols per second ⋆/ + fe_code_rate_t fec_inner; /⋆ forward error correction (see above) ⋆/ + }; + +for cable QAM frontend you use the QAMParameters structure + + struct dvb_qam_parameters { + uint32_t symbol_rate; /⋆ symbol rate in Symbols per second ⋆/ + fe_code_rate_t fec_inner; /⋆ forward error correction (see above) ⋆/ + fe_modulation_t modulation; /⋆ modulation type (see above) ⋆/ + }; + +DVB-T frontends are supported by the OFDMParamters structure + + + struct dvb_ofdm_parameters { + fe_bandwidth_t bandwidth; + fe_code_rate_t code_rate_HP; /⋆ high priority stream code rate ⋆/ + fe_code_rate_t code_rate_LP; /⋆ low priority stream code rate ⋆/ + fe_modulation_t constellation; /⋆ modulation type (see above) ⋆/ + fe_transmit_mode_t transmission_mode; + fe_guard_interval_t guard_interval; + fe_hierarchy_t hierarchy_information; + }; + +In the case of QPSK frontends the Frequency field specifies the intermediate +frequency, i.e. the offset which is effectively added to the local oscillator frequency (LOF) of +the LNB. The intermediate frequency has to be specified in units of kHz. For QAM and +OFDM frontends the Frequency specifies the absolute frequency and is given in +Hz. + +The Inversion field can take one of these values: + + + typedef enum fe_spectral_inversion { + INVERSION_OFF, + INVERSION_ON, + INVERSION_AUTO + } fe_spectral_inversion_t; + +It indicates if spectral inversion should be presumed or not. In the automatic setting +(INVERSION_AUTO) the hardware will try to figure out the correct setting by +itself. + +The possible values for the FEC_inner field are + + + typedef enum fe_code_rate { + FEC_NONE = 0, + FEC_1_2, + FEC_2_3, + FEC_3_4, + FEC_4_5, + FEC_5_6, + FEC_6_7, + FEC_7_8, + FEC_8_9, + FEC_AUTO + } fe_code_rate_t; + +which correspond to error correction rates of 1/2, 2/3, etc., no error correction or auto +detection. + +For cable and terrestrial frontends (QAM and OFDM) one also has to specify the quadrature +modulation mode which can be one of the following: + + + typedef enum fe_modulation { + QPSK, + QAM_16, + QAM_32, + QAM_64, + QAM_128, + QAM_256, + QAM_AUTO + } fe_modulation_t; + +Finally, there are several more parameters for OFDM: + + + typedef enum fe_transmit_mode { + TRANSMISSION_MODE_2K, + TRANSMISSION_MODE_8K, + TRANSMISSION_MODE_AUTO + } fe_transmit_mode_t; + + + typedef enum fe_bandwidth { + BANDWIDTH_8_MHZ, + BANDWIDTH_7_MHZ, + BANDWIDTH_6_MHZ, + BANDWIDTH_AUTO + } fe_bandwidth_t; + + + typedef enum fe_guard_interval { + GUARD_INTERVAL_1_32, + GUARD_INTERVAL_1_16, + GUARD_INTERVAL_1_8, + GUARD_INTERVAL_1_4, + GUARD_INTERVAL_AUTO + } fe_guard_interval_t; + + + typedef enum fe_hierarchy { + HIERARCHY_NONE, + HIERARCHY_1, + HIERARCHY_2, + HIERARCHY_4, + HIERARCHY_AUTO + } fe_hierarchy_t; + + +
+ +
+frontend events + + struct dvb_frontend_event { + fe_status_t status; + struct dvb_frontend_parameters parameters; + }; + +
+
+ + +
+Frontend Function Calls + +
+open() +DESCRIPTION +
+ +This system call opens a named frontend device (/dev/dvb/adapter0/frontend0) + for subsequent use. Usually the first thing to do after a successful open is to + find out the frontend type with FE_GET_INFO. +The device can be opened in read-only mode, which only allows monitoring of + device status and statistics, or read/write mode, which allows any kind of use + (e.g. performing tuning operations.) + +In a system with multiple front-ends, it is usually the case that multiple devices + cannot be open in read/write mode simultaneously. As long as a front-end + device is opened in read/write mode, other open() calls in read/write mode will + either fail or block, depending on whether non-blocking or blocking mode was + specified. A front-end device opened in blocking mode can later be put into + non-blocking mode (and vice versa) using the F_SETFL command of the fcntl + system call. This is a standard system call, documented in the Linux manual + page for fcntl. When an open() call has succeeded, the device will be ready + for use in the specified mode. This implies that the corresponding hardware is + powered up, and that other front-ends may have been powered down to make + that possible. + + + +SYNOPSIS + +int open(const char ⋆deviceName, int flags); + + +PARAMETERS + + +const char + *deviceName + +Name of specific video device. + + +int flags + +A bit-wise OR of the following flags: + + + +O_RDONLY read-only access + + + +O_RDWR read/write access + + + +O_NONBLOCK open in non-blocking mode + + + +(blocking mode is the default) + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EINTERNAL + +Internal error. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + + + +
+close() +DESCRIPTION + +
+This system call closes a previously opened front-end device. After closing + a front-end device, its corresponding hardware might be powered down + automatically. + + +SYNOPSIS + + +int close(int fd); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + + + +
+FE_READ_STATUS +DESCRIPTION + +
+This ioctl call returns status information about the front-end. This call only + requires read-only access to the device. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_READ_STATUS, + fe_status_t ⋆status); + + +PARAMETERS + + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_READ_STATUS for this command. + + +struct fe_status_t + *status + +Points to the location where the front-end status word is + to be stored. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +status points to invalid address. + + + + +
+FE_READ_BER +DESCRIPTION + +
+This ioctl call returns the bit error rate for the signal currently + received/demodulated by the front-end. For this command, read-only access to + the device is sufficient. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_READ_BER, + uint32_t ⋆ber); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_READ_BER for this command. + + +uint32_t *ber + +The bit error rate is stored into *ber. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +ber points to invalid address. + + +ENOSIGNAL + +There is no signal, thus no meaningful bit error rate. Also + returned if the front-end is not turned on. + + +ENOSYS + +Function not available for this device. + + + + +
+FE_READ_SNR + +DESCRIPTION + +
+This ioctl call returns the signal-to-noise ratio for the signal currently received + by the front-end. For this command, read-only access to the device is sufficient. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_READ_SNR, int16_t + ⋆snr); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_READ_SNR for this command. + + +int16_t *snr + +The signal-to-noise ratio is stored into *snr. + + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +snr points to invalid address. + + +ENOSIGNAL + +There is no signal, thus no meaningful signal strength + value. Also returned if front-end is not turned on. + + +ENOSYS + +Function not available for this device. + + + + +
+FE_READ_SIGNAL_STRENGTH +DESCRIPTION + +
+This ioctl call returns the signal strength value for the signal currently received + by the front-end. For this command, read-only access to the device is sufficient. + + +SYNOPSIS + + +int ioctl( int fd, int request = + FE_READ_SIGNAL_STRENGTH, int16_t ⋆strength); + + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_READ_SIGNAL_STRENGTH for this + command. + + +int16_t *strength + +The signal strength value is stored into *strength. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +status points to invalid address. + + +ENOSIGNAL + +There is no signal, thus no meaningful signal strength + value. Also returned if front-end is not turned on. + + +ENOSYS + +Function not available for this device. + + + + +
+FE_READ_UNCORRECTED_BLOCKS +DESCRIPTION + +
+This ioctl call returns the number of uncorrected blocks detected by the device + driver during its lifetime. For meaningful measurements, the increment in block + count during a specific time interval should be calculated. For this command, + read-only access to the device is sufficient. + + +Note that the counter will wrap to zero after its maximum count has been + reached. + + +SYNOPSIS + + +int ioctl( int fd, int request = + FE_READ_UNCORRECTED_BLOCKS, uint32_t ⋆ublocks); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_READ_UNCORRECTED_BLOCKS for this + command. + + +uint32_t *ublocks + +The total number of uncorrected blocks seen by the driver + so far. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +ublocks points to invalid address. + + +ENOSYS + +Function not available for this device. + + + + +
+FE_SET_FRONTEND +DESCRIPTION + +
+This ioctl call starts a tuning operation using specified parameters. The result + of this call will be successful if the parameters were valid and the tuning could + be initiated. The result of the tuning operation in itself, however, will arrive + asynchronously as an event (see documentation for FE_GET_EVENT and + FrontendEvent.) If a new FE_SET_FRONTEND operation is initiated before + the previous one was completed, the previous operation will be aborted in favor + of the new one. This command requires read/write access to the device. + + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_SET_FRONTEND, + struct dvb_frontend_parameters ⋆p); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_SET_FRONTEND for this command. + + +struct + dvb_frontend_parameters + *p + +Points to parameters for tuning operation. + + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +p points to invalid address. + + +EINVAL + +Maximum supported symbol rate reached. + + + + +
+FE_GET_FRONTEND +DESCRIPTION + +
+This ioctl call queries the currently effective frontend parameters. For this + command, read-only access to the device is sufficient. + + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_GET_FRONTEND, + struct dvb_frontend_parameters ⋆p); + + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_SET_FRONTEND for this command. + + +struct + dvb_frontend_parameters + *p + +Points to parameters for tuning operation. + + + + + +ERRORS + + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +p points to invalid address. + + +EINVAL + +Maximum supported symbol rate reached. + + + + + +
+FE_GET_EVENT +DESCRIPTION + +
+This ioctl call returns a frontend event if available. If an event is not + available, the behavior depends on whether the device is in blocking or + non-blocking mode. In the latter case, the call fails immediately with errno + set to EWOULDBLOCK. In the former case, the call blocks until an event + becomes available. + + +The standard Linux poll() and/or select() system calls can be used with the + device file descriptor to watch for new events. For select(), the file descriptor + should be included in the exceptfds argument, and for poll(), POLLPRI should + be specified as the wake-up condition. Since the event queue allocated is + rather small (room for 8 events), the queue must be serviced regularly to avoid + overflow. If an overflow happens, the oldest event is discarded from the queue, + and an error (EOVERFLOW) occurs the next time the queue is read. After + reporting the error condition in this fashion, subsequent FE_GET_EVENT + calls will return events from the queue as usual. + + +For the sake of implementation simplicity, this command requires read/write + access to the device. + + + +SYNOPSIS + + +int ioctl(int fd, int request = QPSK_GET_EVENT, + struct dvb_frontend_event ⋆ev); + + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_GET_EVENT for this command. + + +struct + dvb_frontend_event + *ev + +Points to the location where the event, + + + +if any, is to be stored. + + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +ev points to invalid address. + + +EWOULDBLOCK + +There is no event pending, and the device is in + non-blocking mode. + + +EOVERFLOW + + + + +Overflow in event queue - one or more events were lost. + + + + +
+FE_GET_INFO +DESCRIPTION + +
+This ioctl call returns information about the front-end. This call only requires + read-only access to the device. + + +SYNOPSIS + + + + int ioctl(int fd, int request = FE_GET_INFO, struct + dvb_frontend_info ⋆info); + + +PARAMETERS + + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_GET_INFO for this command. + + +struct + dvb_frontend_info + *info + +Points to the location where the front-end information is + to be stored. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EFAULT + +info points to invalid address. + + + + +
+FE_DISEQC_RESET_OVERLOAD +DESCRIPTION + +
+If the bus has been automatically powered off due to power overload, this ioctl + call restores the power to the bus. The call requires read/write access to the + device. This call has no effect if the device is manually powered off. Not all + DVB adapters support this ioctl. + + + +SYNOPSIS + + +int ioctl(int fd, int request = + FE_DISEQC_RESET_OVERLOAD); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_DISEQC_RESET_OVERLOAD for this + command. + + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EPERM + +Permission denied (needs read/write access). + + +EINTERNAL + +Internal error in the device driver. + + + + +
+FE_DISEQC_SEND_MASTER_CMD +DESCRIPTION + +
+This ioctl call is used to send a a DiSEqC command. + + + + +SYNOPSIS + + +int ioctl(int fd, int request = + FE_DISEQC_SEND_MASTER_CMD, struct + dvb_diseqc_master_cmd ⋆cmd); + + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_DISEQC_SEND_MASTER_CMD for this + command. + + +struct + dvb_diseqc_master_cmd + *cmd + +Pointer to the command to be transmitted. + + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EFAULT + +Seq points to an invalid address. + + +EINVAL + +The data structure referred to by seq is invalid in some + way. + + +EPERM + +Permission denied (needs read/write access). + + +EINTERNAL + +Internal error in the device driver. + + + + +
+FE_DISEQC_RECV_SLAVE_REPLY +DESCRIPTION + +
+This ioctl call is used to receive reply to a DiSEqC 2.0 command. + + + + + +SYNOPSIS + + +int ioctl(int fd, int request = + FE_DISEQC_RECV_SLAVE_REPLY, struct + dvb_diseqc_slave_reply ⋆reply); + + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_DISEQC_RECV_SLAVE_REPLY for this + command. + + +struct + dvb_diseqc_slave_reply + *reply + +Pointer to the command to be received. + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EFAULT + +Seq points to an invalid address. + + +EINVAL + +The data structure referred to by seq is invalid in some + way. + + +EPERM + +Permission denied (needs read/write access). + + +EINTERNAL + +Internal error in the device driver. + + + + +
+FE_DISEQC_SEND_BURST +DESCRIPTION + +
+This ioctl call is used to send a 22KHz tone burst. + + + + + +SYNOPSIS + + +int ioctl(int fd, int request = + FE_DISEQC_SEND_BURST, fe_sec_mini_cmd_t burst); + + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_DISEQC_SEND_BURST for this command. + + +fe_sec_mini_cmd_t + burst + +burst A or B. + + + + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EFAULT + +Seq points to an invalid address. + + +EINVAL + +The data structure referred to by seq is invalid in some + way. + + +EPERM + +Permission denied (needs read/write access). + + +EINTERNAL + +Internal error in the device driver. + + + + +
+FE_SET_TONE +DESCRIPTION + +
+This call is used to set the generation of the continuous 22kHz tone. This call + requires read/write permissions. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_SET_TONE, + fe_sec_tone_mode_t tone); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_SET_TONE for this command. + + +fe_sec_tone_mode_t + tone + +The requested tone generation mode (on/off). + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + +EPERM + +File not opened with read permissions. + + +EINTERNAL + +Internal error in the device driver. + + + + +
+FE_SET_VOLTAGE +DESCRIPTION + +
+This call is used to set the bus voltage. This call requires read/write + permissions. + + +SYNOPSIS + + +int ioctl(int fd, int request = FE_SET_VOLTAGE, + fe_sec_voltage_t voltage); + + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_SET_VOLTAGE for this command. + + +fe_sec_voltage_t + voltage + +The requested bus voltage. + + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + +EPERM + +File not opened with read permissions. + + +EINTERNAL + +Internal error in the device driver. + + + + +
+FE_ENABLE_HIGH_LNB_VOLTAGE +DESCRIPTION + +
+If high != 0 enables slightly higher voltages instead of 13/18V (to compensate + for long cables). This call requires read/write permissions. Not all DVB + adapters support this ioctl. + + + +SYNOPSIS + + +int ioctl(int fd, int request = + FE_ENABLE_HIGH_LNB_VOLTAGE, int high); + + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals FE_SET_VOLTAGE for this command. + + +int high + +The requested bus voltage. + + + + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + +EPERM + +File not opened with read permissions. + + +EINTERNAL + +Internal error in the device driver. + + + + diff --git a/dvb-spec/sgml/intro.sgml b/dvb-spec/sgml/intro.sgml new file mode 100644 index 000000000..37d1c5055 --- /dev/null +++ b/dvb-spec/sgml/intro.sgml @@ -0,0 +1,191 @@ +Introduction + +
+What you need to know + +The reader of this document is required to have some knowledge in +the area of digital video broadcasting (DVB) and should be familiar with +part I of the MPEG2 specification ISO/IEC 13818 (aka ITU-T H.222), i.e +you should know what a program/transport stream (PS/TS) is and what is +meant by a packetized elementary stream (PES) or an I-frame. + +Various DVB standards documents are available from +http://www.dvb.org/ and/or +http://www.etsi.org/. + +It is also necessary to know how to access unix/linux devices and +how to use ioctl calls. This also includes the knowledge of C or C++. + +
+ +
+History + +The first API for DVB cards we used at Convergence in late 1999 +was an extension of the Video4Linux API which was primarily developed +for frame grabber cards. As such it was not really well suited to be +used for DVB cards and their new features like recording MPEG streams +and filtering several section and PES data streams at the same time. + + +In early 2000, we were approached by Nokia with a proposal for a +new standard Linux DVB API. As a commitment to the development of +terminals based on open standards, Nokia and Convergence made it +available to all Linux developers and published it on http://www.linuxtv.org/ in September 2000. +Convergence is the maintainer of the Linux DVB API. Together with the +LinuxTV community (i.e. you, the reader of this document), the Linux DVB +API will be constantly reviewed and improved. With the Linux driver for +the Siemens/Hauppauge DVB PCI card Convergence provides a first +implementation of the Linux DVB API. +
+ +
+Overview + +
+ Components of a DVB card/STB + + + + + + + + +
+ +A DVB PCI card or DVB set-top-box (STB) usually consists of the +following main hardware components: + + + + +Frontend consisting of tuner and DVB demodulator + +Here the raw signal reaches the DVB hardware from a satellite dish +or antenna or directly from cable. The frontend down-converts and +demodulates this signal into an MPEG transport stream (TS). In case of a +satellite frontend, this includes a facility for satellite equipment +control (SEC), which allows control of LNB polarization, multi feed +switches or dish rotors. + + + + +Conditional Access (CA) hardware like CI adapters and smartcard slots + + +The complete TS is passed through the CA hardware. Programs to +which the user has access (controlled by the smart card) are decoded in +real time and re-inserted into the TS. + + + + Demultiplexer which filters the incoming DVB stream + +The demultiplexer splits the TS into its components like audio and +video streams. Besides usually several of such audio and video streams +it also contains data streams with information about the programs +offered in this or other streams of the same provider. + + + + +MPEG2 audio and video decoder + +The main targets of the demultiplexer are the MPEG2 audio and +video decoders. After decoding they pass on the uncompressed audio and +video to the computer screen or (through a PAL/NTSC encoder) to a TV +set. + + + + + + shows a crude schematic of the control and data flow +between those components. + +On a DVB PCI card not all of these have to be present since some +functionality can be provided by the main CPU of the PC (e.g. MPEG +picture and sound decoding) or is not needed (e.g. for data-only uses +like “internet over satellite”). Also not every card or STB +provides conditional access hardware. + +
+ +
+Linux DVB Devices + +The Linux DVB API lets you control these hardware components +through currently six Unix-style character devices for video, audio, +frontend, demux, CA and IP-over-DVB networking. The video and audio +devices control the MPEG2 decoder hardware, the frontend device the +tuner and the DVB demodulator. The demux device gives you control over +the PES and section filters of the hardware. If the hardware does not +support filtering these filters can be implemented in software. Finally, +the CA device controls all the conditional access capabilities of the +hardware. It can depend on the individual security requirements of the +platform, if and how many of the CA functions are made available to the +application through this device. + +All devices can be found in the /dev +tree under /dev/dvb. The individual devices +are called: + + + + +/dev/dvb/adapterN/audioM, + + +/dev/dvb/adapterN/videoM, + + +/dev/dvb/adapterN/frontendM, + + + +/dev/dvb/adapterN/netM, + + + +/dev/dvb/adapterN/demuxM, + + + +/dev/dvb/adapterN/caM, + +where N enumerates the DVB PCI cards in a system starting +from 0, and M enumerates the devices of each type within each +adapter, starting from 0, too. We will omit the “/dev/dvb/adapterN/” in the further dicussion +of these devices. The naming scheme for the devices is the same wheter +devfs is used or not. + +More details about the data structures and function calls of all +the devices are described in the following chapters. + +
+ +
+API include files + +For each of the DVB devices a corresponding include file exists. +The DVB API include files should be included in application sources with +a partial path like: + + + + #include <linux/dvb/frontend.h> + + +To enable applications to support different API version, an +additional include file linux/dvb/version.h exists, which defines the +constant DVB_API_VERSION. This document +describes DVB_API_VERSION 3. + + +
+ -- cgit v1.2.3 From 9816ad7712708e239c037f0806901d02e0329b51 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 6 Sep 2009 14:43:34 -0300 Subject: dvb-spec/sgml: Remove blank cells from the tables From: Mauro Carvalho Chehab The htlatex added some empty rows at the tables. Remove it with this small script: perl -ne '$txt=""; while (<>) { $txt .=$_ }; $txt=~s,\[\s\n]*\]*>[\s\n]*\<\/entry\>[\n\s]*\<\/row\>,,g; print $txt; exit;' Signed-off-by: Mauro Carvalho Chehab --- dvb-spec/sgml/dvbapi-complete.sgml | 379 +------------------------------------ dvb-spec/sgml/frontend.sgml | 51 ----- 2 files changed, 2 insertions(+), 428 deletions(-) diff --git a/dvb-spec/sgml/dvbapi-complete.sgml b/dvb-spec/sgml/dvbapi-complete.sgml index 56edcf023..753efd3fe 100644 --- a/dvb-spec/sgml/dvbapi-complete.sgml +++ b/dvb-spec/sgml/dvbapi-complete.sgml @@ -577,9 +577,6 @@ role="subsection"><abbrev role="title-mark">2.2.1</abbrev>open() (blocking mode is the default) - - ERRORS @@ -611,9 +608,6 @@ role="subsection"><abbrev role="title-mark">2.2.1</abbrev>open() Invalid argument. - - @@ -643,9 +637,6 @@ role="subsection"><abbrev role="title-mark">2.2.2</abbrev>close() File descriptor returned by a previous call to open(). - - ERRORS @@ -656,9 +647,6 @@ role="subsection"><abbrev role="title-mark">2.2.2</abbrev>close() fd is not a valid open file descriptor. - - @@ -721,9 +709,6 @@ role="subsection"><abbrev role="title-mark">2.2.3</abbrev>FE_READ_STATUS< </entry><entry align="char"> <para>status points to invalid address.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -768,9 +753,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.4</abbrev>FE_READ_BER<ind </entry><entry align="char"> <para>The bit error rate is stored into *ber.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -846,9 +828,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.5</abbrev>FE_READ_SNR<ind </entry><entry align="char"> <para>The signal-to-noise ratio is stored into *snr.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -925,9 +904,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.6</abbrev>FE_READ_SIGNAL_ </entry><entry align="char"> <para>The signal strength value is stored into *strength.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1086,9 +1062,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.8</abbrev>FE_SET_FRONTEND </entry><entry align="char"> <para>Points to parameters for tuning operation.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1113,9 +1086,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.8</abbrev>FE_SET_FRONTEND </entry><entry align="char"> <para>Maximum supported symbol rate reached.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1161,9 +1131,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.9</abbrev>FE_GET_FRONTEND </entry><entry align="char"> <para>Points to parameters for tuning operation.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1188,9 +1155,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.9</abbrev>FE_GET_FRONTEND </entry><entry align="char"> <para>Maximum supported symbol rate reached.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1299,9 +1263,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.10</abbrev>FE_GET_EVENT<i </entry><entry align="char"> <para>Overflow in event queue - one or more events were lost.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1365,9 +1326,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.11</abbrev>FE_GET_INFO<in </entry><entry align="char"> <para>info points to invalid address.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1407,9 +1365,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.12</abbrev>FE_DISEQC_RESE align="char"> <para>Equals FE_DISEQC_RESET_OVERLOAD for this command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1434,9 +1389,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.12</abbrev>FE_DISEQC_RESE </entry><entry align="char"> <para>Internal error in the device driver.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1447,9 +1399,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.13</abbrev>FE_DISEQC_SEND <informaltable><tgroup cols="1"><tbody><row><entry align="char"> <para>This ioctl call is used to send a a DiSEqC command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>SYNOPSIS @@ -1486,9 +1435,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.13</abbrev>FE_DISEQC_SEND </entry><entry align="char"> <para>Pointer to the command to be transmitted.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1528,9 +1474,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.13</abbrev>FE_DISEQC_SEND </entry><entry align="char"> <para>Internal error in the device driver.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1541,9 +1484,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.14</abbrev>FE_DISEQC_RECV <informaltable><tgroup cols="1"><tbody><row><entry align="char"> <para>This ioctl call is used to receive reply to a DiSEqC 2.0 command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>SYNOPSIS @@ -1580,9 +1520,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.14</abbrev>FE_DISEQC_RECV </entry><entry align="char"> <para>Pointer to the command to be received.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1622,9 +1559,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.14</abbrev>FE_DISEQC_RECV </entry><entry align="char"> <para>Internal error in the device driver.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1635,9 +1569,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.15</abbrev>FE_DISEQC_SEND <informaltable><tgroup cols="1"><tbody><row><entry align="char"> <para>This ioctl call is used to send a 22KHz tone burst.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>SYNOPSIS @@ -1671,9 +1602,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.15</abbrev>FE_DISEQC_SEND </entry><entry align="char"> <para>burst A or B.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1713,9 +1641,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.15</abbrev>FE_DISEQC_SEND </entry><entry align="char"> <para>Internal error in the device driver.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1760,9 +1685,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.16</abbrev>FE_SET_TONE<in </entry><entry align="char"> <para>The requested tone generation mode (on/off).</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1801,9 +1723,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.16</abbrev>FE_SET_TONE<in </entry><entry align="char"> <para>Internal error in the device driver.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1848,9 +1767,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.17</abbrev>FE_SET_VOLTAGE </entry><entry align="char"> <para>The requested bus voltage.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1889,9 +1805,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.17</abbrev>FE_SET_VOLTAGE </entry><entry align="char"> <para>Internal error in the device driver.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1936,9 +1849,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.18</abbrev>FE_ENABLE_HIGH </entry><entry align="char"> <para>The requested bus voltage.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1977,9 +1887,6 @@ role="subsection"><title><abbrev role="title-mark">2.2.18</abbrev>FE_ENABLE_HIGH </entry><entry align="char"> <para>Internal error in the device driver.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -2182,9 +2089,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.1</abbrev>open() (blocking mode is the default) - - ERRORS @@ -2216,9 +2120,6 @@ role="subsection"><abbrev role="title-mark">3.2.1</abbrev>open() The driver failed to allocate enough memory. - - @@ -2247,9 +2148,6 @@ role="subsection"><abbrev role="title-mark">3.2.2</abbrev>close() File descriptor returned by a previous call to open(). - - ERRORS @@ -2260,9 +2158,6 @@ role="subsection"><abbrev role="title-mark">3.2.2</abbrev>close() fd is not a valid open file descriptor. - - @@ -2334,9 +2229,6 @@ role="subsection"><abbrev role="title-mark">3.2.3</abbrev>read() Size of buf. - - ERRORS @@ -2393,9 +2285,6 @@ role="subsection"><abbrev role="title-mark">3.2.3</abbrev>read() align="char"> The driver failed to write to the callers buffer due to an invalid *buf pointer. - - @@ -2443,9 +2332,6 @@ role="subsection"><abbrev role="title-mark">3.2.4</abbrev>write() Size of buf. - - ERRORS @@ -2478,9 +2364,6 @@ role="subsection"><abbrev role="title-mark">3.2.4</abbrev>write() fd is not a valid open file descriptor. - - @@ -2516,9 +2399,6 @@ role="subsection"><abbrev role="title-mark">3.2.5</abbrev>DMX_START<index </entry><entry align="char"> <para>Equals DMX_START for this command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -2548,9 +2428,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.5</abbrev>DMX_START<index requests. There are active filters filtering data from another input source. Make sure that these filters are stopped before starting this filter.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -2587,9 +2464,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.6</abbrev>DMX_STOP<indext </entry><entry align="char"> <para>Equals DMX_STOP for this command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -2600,9 +2474,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.6</abbrev>DMX_STOP<indext </entry><entry align="char"> <para>fd is not a valid file descriptor.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -2655,9 +2526,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.7</abbrev>DMX_SET_FILTER< </entry><entry align="char"> <para>Pointer to structure containing filter parameters.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -2675,9 +2543,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.7</abbrev>DMX_SET_FILTER< </entry><entry align="char"> <para>Invalid argument.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -2733,9 +2598,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.8</abbrev>DMX_SET_PES_FIL </entry><entry align="char"> <para>Pointer to structure containing filter parameters.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -2763,9 +2625,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.8</abbrev>DMX_SET_PES_FIL requests. There are active filters filtering data from another input source. Make sure that these filters are stopped before starting this filter.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -2810,9 +2669,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.9</abbrev>DMX_SET_BUFFER_ </entry><entry align="char"> <para>Size of circular buffer.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -2831,9 +2687,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.9</abbrev>DMX_SET_BUFFER_ align="char"> <para>The driver was not able to allocate a buffer of the requested size.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -2888,9 +2741,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.10</abbrev>DMX_GET_EVENT< </entry><entry align="char"> <para>Pointer to the location where the event is to be stored.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -2916,9 +2766,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.10</abbrev>DMX_GET_EVENT< align="char"> <para>There is no event pending, and the device is in non-blocking mode.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -2967,9 +2814,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.11</abbrev>DMX_GET_STC<in </entry><entry align="char"> <para>Pointer to the location where the stc is to be stored.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -2994,9 +2838,6 @@ role="subsection"><title><abbrev role="title-mark">3.2.11</abbrev>DMX_GET_STC<in </entry><entry align="char"> <para>Invalid stc number.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> </section></section></section><section @@ -3329,9 +3170,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.1</abbrev>open() (blocking mode is the default) - - ERRORS @@ -3363,9 +3201,6 @@ role="subsection"><abbrev role="title-mark">4.2.1</abbrev>open() Invalid argument. - - @@ -3393,9 +3228,6 @@ role="subsection"><abbrev role="title-mark">4.2.2</abbrev>close() File descriptor returned by a previous call to open(). - - ERRORS @@ -3406,9 +3238,6 @@ role="subsection"><abbrev role="title-mark">4.2.2</abbrev>close() fd is not a valid open file descriptor. - - @@ -3454,9 +3283,6 @@ role="subsection"><abbrev role="title-mark">4.2.3</abbrev>write() Size of buf. - - ERRORS @@ -3482,9 +3308,6 @@ role="subsection"><abbrev role="title-mark">4.2.3</abbrev>write() fd is not a valid open file descriptor. - - @@ -3541,9 +3364,6 @@ role="subsection"><abbrev role="title-mark">4.2.4</abbrev>VIDEO_STOP<inde </entry><entry align="char"> <para>FALSE: Show last decoded frame.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -3562,9 +3382,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.4</abbrev>VIDEO_STOP<inde align="char"> <para>Internal error, possibly in the communication with the DVB subsystem.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -3600,9 +3417,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.5</abbrev>VIDEO_PLAY<inde </entry><entry align="char"> <para>Equals VIDEO_PLAY for this command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -3621,9 +3435,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.5</abbrev>VIDEO_PLAY<inde align="char"> <para>Internal error, possibly in the communication with the DVB subsystem.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -3663,9 +3474,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.6</abbrev>VIDEO_FREEZE<in </entry><entry align="char"> <para>Equals VIDEO_FREEZE for this command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -3684,9 +3492,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.6</abbrev>VIDEO_FREEZE<in align="char"> <para>Internal error, possibly in the communication with the DVB subsystem.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -3722,9 +3527,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.7</abbrev>VIDEO_CONTINUE< </entry><entry align="char"> <para>Equals VIDEO_CONTINUE for this command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -3743,9 +3545,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.7</abbrev>VIDEO_CONTINUE< align="char"> <para>Internal error, possibly in the communication with the DVB subsystem.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -3791,9 +3590,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.8</abbrev>VIDEO_SELECT_SO </entry><entry align="char"> <para>Indicates which source shall be used for the Video stream.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -3812,9 +3608,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.8</abbrev>VIDEO_SELECT_SO align="char"> <para>Internal error, possibly in the communication with the DVB subsystem.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -3863,9 +3656,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.9</abbrev>VIDEO_SET_BLANK </entry><entry align="char"> <para>FALSE: Show last decoded frame.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -3891,9 +3681,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.9</abbrev>VIDEO_SET_BLANK </entry><entry align="char"> <para>Illegal input parameter</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -3937,9 +3724,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.10</abbrev>VIDEO_GET_STAT </entry><entry align="char"> <para>Returns the current status of the Video Device.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -3965,9 +3749,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.10</abbrev>VIDEO_GET_STAT </entry><entry align="char"> <para>status points to invalid address</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4020,9 +3801,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.11</abbrev>VIDEO_GET_EVEN align="char"> <para>Points to the location where the event, if any, is to be stored.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4060,9 +3838,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.11</abbrev>VIDEO_GET_EVEN </entry><entry align="char"> <para>Overflow in event queue - one or more events were lost.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4109,9 +3884,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.12</abbrev>VIDEO_SET_DISP </entry><entry align="char"> <para>Selects the video format to be used.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4136,9 +3908,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.12</abbrev>VIDEO_SET_DISP </entry><entry align="char"> <para>Illegal parameter format.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4185,9 +3954,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.13</abbrev>VIDEO_STILLPIC </entry><entry align="char"> <para>Pointer to a location where an I-frame and size is stored.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4212,9 +3978,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.13</abbrev>VIDEO_STILLPIC </entry><entry align="char"> <para>sp points to an invalid iframe.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4258,9 +4021,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.14</abbrev>VIDEO_FAST_FOR </entry><entry align="char"> <para>The number of frames to skip.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4292,9 +4052,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.14</abbrev>VIDEO_FAST_FOR </entry><entry align="char"> <para>Illegal parameter format.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4338,9 +4095,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.15</abbrev>VIDEO_SLOWMOTI </entry><entry align="char"> <para>The number of times to repeat each frame.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4372,9 +4126,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.15</abbrev>VIDEO_SLOWMOTI </entry><entry align="char"> <para>Illegal parameter format.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4420,9 +4171,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.16</abbrev>VIDEO_GET_CAPA align="char"> <para>Pointer to a location where to store the capability information.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4440,9 +4188,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.16</abbrev>VIDEO_GET_CAPA </entry><entry align="char"> <para>cap points to an invalid iframe.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4544,9 +4289,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.18</abbrev>VIDEO_CLEAR_BU </entry><entry align="char"> <para>Equals VIDEO_CLEAR_BUFFER for this command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4557,9 +4299,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.18</abbrev>VIDEO_CLEAR_BU </entry><entry align="char"> <para>fd is not a valid open file descriptor</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4604,9 +4343,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.19</abbrev>VIDEO_SET_STRE </entry><entry align="char"> <para>stream type</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4624,9 +4360,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.19</abbrev>VIDEO_SET_STRE </entry><entry align="char"> <para>type is not a valid or supported stream type.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4671,9 +4404,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.20</abbrev>VIDEO_SET_FORM </entry><entry align="char"> <para>video format of TV as defined in section ??.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4691,9 +4421,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.20</abbrev>VIDEO_SET_FORM </entry><entry align="char"> <para>format is not a valid video format.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4739,9 +4466,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.21</abbrev>VIDEO_SET_SYST </entry><entry align="char"> <para>video system of TV output.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4759,9 +4483,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.21</abbrev>VIDEO_SET_SYST </entry><entry align="char"> <para>system is not a valid or supported video system.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4805,9 +4526,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.22</abbrev>VIDEO_SET_HIGH </entry><entry align="char"> <para>SPU Highlight information according to section ??.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4825,9 +4543,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.22</abbrev>VIDEO_SET_HIGH </entry><entry align="char"> <para>input is not a valid highlight setting.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4872,9 +4587,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.23</abbrev>VIDEO_SET_SPU< align="char"> <para>SPU decoding (de)activation and subid setting according to section ??.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4893,9 +4605,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.23</abbrev>VIDEO_SET_SPU< align="char"> <para>input is not a valid spu setting or driver cannot handle SPU.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -4939,9 +4648,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.24</abbrev>VIDEO_SET_SPU_ </entry><entry align="char"> <para>SPU palette according to section ??.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -4959,9 +4665,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.24</abbrev>VIDEO_SET_SPU_ </entry><entry align="char"> <para>input is not a valid palette or driver doesn’t handle SPU.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -5007,9 +4710,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.25</abbrev>VIDEO_GET_NAVI align="char"> <para>PCI or DSI pack (private stream 2) according to section ??.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -5027,9 +4727,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.25</abbrev>VIDEO_GET_NAVI </entry><entry align="char"> <para>driver is not able to return navigational information</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -5075,9 +4772,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.26</abbrev>VIDEO_SET_ATTR </entry><entry align="char"> <para>video attributes according to section ??.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -5095,9 +4789,6 @@ role="subsection"><title><abbrev role="title-mark">4.2.26</abbrev>VIDEO_SET_ATTR </entry><entry align="char"> <para>input is not a valid attribute setting.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> </section></section></section><section @@ -5308,9 +4999,6 @@ role="subsection"><title><abbrev role="title-mark">5.2.1</abbrev>open() (blocking mode is the default) - - ERRORS @@ -5342,9 +5030,6 @@ role="subsection"><abbrev role="title-mark">5.2.1</abbrev>open() Invalid argument. - - @@ -5372,9 +5057,6 @@ role="subsection"><abbrev role="title-mark">5.2.2</abbrev>close() File descriptor returned by a previous call to open(). - - ERRORS @@ -5385,9 +5067,6 @@ role="subsection"><abbrev role="title-mark">5.2.2</abbrev>close() fd is not a valid open file descriptor. - - @@ -5433,9 +5112,6 @@ role="subsection"><abbrev role="title-mark">5.2.3</abbrev>write() Size of buf. - - ERRORS @@ -5461,9 +5137,6 @@ role="subsection"><abbrev role="title-mark">5.2.3</abbrev>write() fd is not a valid open file descriptor. - - @@ -5753,9 +5426,6 @@ role="subsection"><abbrev role="title-mark">5.2.8</abbrev>AUDIO_SET_MUTE< </entry><entry align="char"> <para>FALSE Audio Un-mute</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -5835,9 +5505,6 @@ role="subsection"><title><abbrev role="title-mark">5.2.9</abbrev>AUDIO_SET_AV_SY </entry><entry align="char"> <para>FALSE AV-sync OFF</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -5921,9 +5588,6 @@ role="subsection"><title><abbrev role="title-mark">5.2.10</abbrev>AUDIO_SET_BYPA </entry><entry align="char"> <para>FALSE Bypass is enabled</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -6386,9 +6050,6 @@ role="subsection"><title><abbrev role="title-mark">5.2.17</abbrev>AUDIO_SET_STRE </entry><entry align="char"> <para>stream type</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -6406,9 +6067,6 @@ role="subsection"><title><abbrev role="title-mark">5.2.17</abbrev>AUDIO_SET_STRE </entry><entry align="char"> <para>type is not a valid or supported stream type.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -6452,9 +6110,6 @@ role="subsection"><title><abbrev role="title-mark">5.2.18</abbrev>AUDIO_SET_EXT_ </entry><entry align="char"> <para>audio sub_stream_id</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -6472,9 +6127,6 @@ role="subsection"><title><abbrev role="title-mark">5.2.18</abbrev>AUDIO_SET_EXT_ </entry><entry align="char"> <para>id is not a valid id.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -6519,9 +6171,6 @@ role="subsection"><title><abbrev role="title-mark">5.2.19</abbrev>AUDIO_SET_ATTR </entry><entry align="char"> <para>audio attributes according to section ??</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -6539,9 +6188,6 @@ role="subsection"><title><abbrev role="title-mark">5.2.19</abbrev>AUDIO_SET_ATTR </entry><entry align="char"> <para>attr is not a valid or supported attribute setting.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -6586,9 +6232,6 @@ role="subsection"><title><abbrev role="title-mark">5.2.20</abbrev>AUDIO_SET_KARA </entry><entry align="char"> <para>karaoke settings according to section ??.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -6606,9 +6249,6 @@ role="subsection"><title><abbrev role="title-mark">5.2.20</abbrev>AUDIO_SET_KARA </entry><entry align="char"> <para>karaoke is not a valid or supported karaoke setting.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> </section></section></section><section @@ -6753,9 +6393,6 @@ role="subsection"><title><abbrev role="title-mark">6.2.1</abbrev>open() (blocking mode is the default) - - ERRORS @@ -6787,9 +6424,6 @@ role="subsection"><abbrev role="title-mark">6.2.1</abbrev>open() Invalid argument. - - @@ -6817,9 +6451,6 @@ role="subsection"><abbrev role="title-mark">6.2.2</abbrev>close() File descriptor returned by a previous call to open(). - - ERRORS @@ -6830,9 +6461,6 @@ role="subsection"><abbrev role="title-mark">6.2.2</abbrev>close() fd is not a valid open file descriptor. - -
<abbrev role="title-mark">8.6.4</abbrev>start_filtering </entry><entry align="char"> <para>Pointer to the section feed API and instance data.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>RETURNS @@ -9513,7 +9138,7 @@ role="section"><title><abbrev role="title-mark">9.2</abbrev>The DVR device</titl </section>GNU Free Documentation License <para>Version 1.1, March 2000 </para> -<para>Copyright 2000 Free Software Foundation, Inc. +<para>Copyright � 2000 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -9855,7 +9480,7 @@ document and put the following copyright and license notices just after the titl page: </para> -<para>Copyright YEAR YOUR NAME. Permission is granted to copy, +<para>Copyright � YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being LIST THEIR diff --git a/dvb-spec/sgml/frontend.sgml b/dvb-spec/sgml/frontend.sgml index d2a6ece04..91a749f70 100644 --- a/dvb-spec/sgml/frontend.sgml +++ b/dvb-spec/sgml/frontend.sgml @@ -403,9 +403,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>(blocking mode is the default)</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -467,9 +464,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>File descriptor returned by a previous call to open().</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -589,9 +583,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>The bit error rate is stored into *ber.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -669,9 +660,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>The signal-to-noise ratio is stored into *snr.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -751,9 +739,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>The signal strength value is stored into *strength.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -915,9 +900,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>Points to parameters for tuning operation.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -990,9 +972,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>Points to parameters for tuning operation.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1239,9 +1218,6 @@ modulation mode which can be one of the following: align="char"> <para>Equals FE_DISEQC_RESET_OVERLOAD for this command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1278,9 +1254,6 @@ modulation mode which can be one of the following: <informaltable><tgroup cols="1"><tbody><row><entry align="char"> <para>This ioctl call is used to send a a DiSEqC command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>SYNOPSIS @@ -1318,9 +1291,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>Pointer to the command to be transmitted.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1372,9 +1342,6 @@ modulation mode which can be one of the following: <informaltable><tgroup cols="1"><tbody><row><entry align="char"> <para>This ioctl call is used to receive reply to a DiSEqC 2.0 command.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1413,9 +1380,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>Pointer to the command to be received.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1466,9 +1430,6 @@ modulation mode which can be one of the following: <informaltable><tgroup cols="1"><tbody><row><entry align="char"> <para>This ioctl call is used to send a 22KHz tone burst.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1504,9 +1465,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>burst A or B.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1592,9 +1550,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>The requested tone generation mode (on/off).</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> <para>ERRORS @@ -1679,9 +1634,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>The requested bus voltage.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> @@ -1768,9 +1720,6 @@ modulation mode which can be one of the following: </entry><entry align="char"> <para>The requested bus voltage.</para> -</entry> - </row><row><entry - align="char"> </entry> </row></tbody></tgroup></informaltable> -- cgit v1.2.3 From b44bf030127d080ec77a3092ecd8ff84c8f2546f Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf <dougsland@redhat.com> Date: Sun, 6 Sep 2009 17:41:59 -0400 Subject: em28xx-cards: Add vendor/product id for Kworld DVD Maker 2 From: Douglas Schilling Landgraf <dougsland@redhat.com> Added Kworld DVD Maker 2 Thanks to C Western <l@c-m-w.me.uk> for reporting this board. Priority: normal Signed-off-by: Douglas Schilling Landgraf <dougsland@redhat.com> --- linux/Documentation/video4linux/CARDLIST.em28xx | 2 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index b37eff3c9..b13fcbd5d 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -7,7 +7,7 @@ 6 -> Terratec Cinergy 200 USB (em2800) 7 -> Leadtek Winfast USB II (em2800) [0413:6023] 8 -> Kworld USB2800 (em2800) - 9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,2304:0207,2304:021a] + 9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,1b80:e304,2304:0207,2304:021a] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 656604dc9..d3c55ef0d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1077,7 +1077,8 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_PINNACLE_DVC_90] = { - .name = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker", + .name = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker " + "/ Kworld DVD Maker 2", .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { @@ -1682,6 +1683,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2870_BOARD_KWORLD_355U }, { USB_DEVICE(0x1b80, 0xe302), .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */ + { USB_DEVICE(0x1b80, 0xe304), + .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kworld DVD Maker 2 */ { USB_DEVICE(0x0ccd, 0x0036), .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 }, { USB_DEVICE(0x0ccd, 0x004c), -- cgit v1.2.3 From 8de1392b607bd886b0a083452b85ce7144ad372c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Sun, 6 Sep 2009 22:25:36 -0300 Subject: dvb-spec/sgml: Finish conversion to DocBook XML 4.1.2 From: Mauro Carvalho Chehab <mchehab@redhat.com> With the conversion of both v4l2 and dvb-spec to the same DocBook version used in kernel, it is now possible to do some interesting things like adding the docs upstream and/or merge or share chapters between the two specs. Also, after promoting this version to official, just one set of text tools will be needed to generate both DVB and V4L2 specs. Yet, more work is needed to validate the conversion, improve the layout of the documents, provide cross references, etc. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- dvb-spec/sgml/Makefile | 7 +- dvb-spec/sgml/README | 12 +- dvb-spec/sgml/audio.sgml | 1473 ++++++ dvb-spec/sgml/ca.sgml | 221 + dvb-spec/sgml/demux.sgml | 973 ++++ dvb-spec/sgml/dvbapi-complete.sgml | 9503 ------------------------------------ dvb-spec/sgml/dvbapi.sgml | 34 +- dvb-spec/sgml/dvbstb.pdf | Bin 1786 -> 1881 bytes dvb-spec/sgml/examples.sgml | 365 ++ dvb-spec/sgml/fdl.sgml | 374 ++ dvb-spec/sgml/intro.sgml | 22 +- dvb-spec/sgml/kdapi.sgml | 2309 +++++++++ dvb-spec/sgml/net.sgml | 12 + dvb-spec/sgml/video.sgml | 1971 ++++++++ 14 files changed, 7740 insertions(+), 9536 deletions(-) create mode 100644 dvb-spec/sgml/audio.sgml create mode 100644 dvb-spec/sgml/ca.sgml create mode 100644 dvb-spec/sgml/demux.sgml delete mode 100644 dvb-spec/sgml/dvbapi-complete.sgml create mode 100644 dvb-spec/sgml/kdapi.sgml create mode 100644 dvb-spec/sgml/net.sgml create mode 100644 dvb-spec/sgml/video.sgml diff --git a/dvb-spec/sgml/Makefile b/dvb-spec/sgml/Makefile index f39d7a97c..9471e4b98 100644 --- a/dvb-spec/sgml/Makefile +++ b/dvb-spec/sgml/Makefile @@ -4,7 +4,12 @@ SGMLS = \ dvbapi.sgml \ intro.sgml \ frontend.sgml \ - devices.sgml \ + demux.sgml \ + video.sgml \ + audio.sgml \ + ca.sgml \ + net.sgml \ + kdapi.sgml \ examples.sgml \ fdl.sgml \ entities.sgml \ diff --git a/dvb-spec/sgml/README b/dvb-spec/sgml/README index 99dd5fef3..6f62d3ae2 100644 --- a/dvb-spec/sgml/README +++ b/dvb-spec/sgml/README @@ -1,13 +1,11 @@ -This directory doesn't contain the official DVB API +This directory doesn't contain the official DVB API. -It contains an effort of porting it from LaTex to Docbook XML 4.1.2 +It contains a port from LaTex to Docbook XML 4.1.2 It is still a work undergoing. Contributions are welcome. CURRENT STATUS: -Chapters 1 and 2 were converted. The remaining chapters aren't yet. - -File dvbapi-complete.sgml is a temporary file generated by a tool that -automatically do the conversion. While it doesn't compile, it is a good -starting point for the conversion. +All chapters were converted. The resulting pdf and html are close to the +original LaTex book. Yet, it lacks some efforts to improve +the output layout and it lacks a topic index. diff --git a/dvb-spec/sgml/audio.sgml b/dvb-spec/sgml/audio.sgml new file mode 100644 index 000000000..eeb96b8a0 --- /dev/null +++ b/dvb-spec/sgml/audio.sgml @@ -0,0 +1,1473 @@ +<title>DVB Audio Device +The DVB audio device controls the MPEG2 audio decoder of the DVB hardware. It +can be accessed through /dev/dvb/adapter0/audio0. Data types and and +ioctl definitions can be accessed by including linux/dvb/video.h in your +application. + +Please note that some DVB cards don’t have their own MPEG decoder, which results in +the omission of the audio and video device. + + +
+Audio Data Types +This section describes the structures, data types and defines used when talking to the +audio device. + + +
+audio_stream_source_t +The audio stream source is set through the AUDIO_SELECT_SOURCE call and can take +the following values, depending on whether we are replaying from an internal (demux) or +external (user write) source. + + + typedef enum { + AUDIO_SOURCE_DEMUX, + AUDIO_SOURCE_MEMORY + } audio_stream_source_t; + +AUDIO_SOURCE_DEMUX selects the demultiplexer (fed either by the frontend or the +DVR device) as the source of the video stream. If AUDIO_SOURCE_MEMORY +is selected the stream comes from the application through the write() system +call. + + +
+
+audio_play_state_t +The following values can be returned by the AUDIO_GET_STATUS call representing the +state of audio playback. + + + typedef enum { + AUDIO_STOPPED, + AUDIO_PLAYING, + AUDIO_PAUSED + } audio_play_state_t; + + +
+
+audio_channel_select_t +The audio channel selected via AUDIO_CHANNEL_SELECT is determined by the +following values. + + + typedef enum { + AUDIO_STEREO, + AUDIO_MONO_LEFT, + AUDIO_MONO_RIGHT, + } audio_channel_select_t; + + +
+
+struct audio_status +The AUDIO_GET_STATUS call returns the following structure informing about various +states of the playback operation. + + + typedef struct audio_status { + boolean AV_sync_state; + boolean mute_state; + audio_play_state_t play_state; + audio_stream_source_t stream_source; + audio_channel_select_t channel_select; + boolean bypass_mode; + } audio_status_t; + + +
+
+struct audio_mixer +The following structure is used by the AUDIO_SET_MIXER call to set the audio +volume. + + + typedef struct audio_mixer { + unsigned int volume_left; + unsigned int volume_right; + } audio_mixer_t; + + +
+
+audio encodings +A call to AUDIO_GET_CAPABILITIES returns an unsigned integer with the following +bits set according to the hardwares capabilities. + + + #define AUDIO_CAP_DTS 1 + #define AUDIO_CAP_LPCM 2 + #define AUDIO_CAP_MP1 4 + #define AUDIO_CAP_MP2 8 + #define AUDIO_CAP_MP3 16 + #define AUDIO_CAP_AAC 32 + #define AUDIO_CAP_OGG 64 + #define AUDIO_CAP_SDDS 128 + #define AUDIO_CAP_AC3 256 + + +
+
+struct audio_karaoke +The ioctl AUDIO_SET_KARAOKE uses the following format: + + + typedef + struct audio_karaoke{ + int vocal1; + int vocal2; + int melody; + } audio_karaoke_t; + +If Vocal1 or Vocal2 are non-zero, they get mixed into left and right t at 70% each. If both, +Vocal1 and Vocal2 are non-zero, Vocal1 gets mixed into the left channel and Vocal2 into the +right channel at 100% each. Ff Melody is non-zero, the melody channel gets mixed into left +and right. + + +
+
+audio attributes +The following attributes can be set by a call to AUDIO_SET_ATTRIBUTES: + + + typedef uint16_t audio_attributes_t; + /⋆ bits: descr. ⋆/ + /⋆ 15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, ⋆/ + /⋆ 12 multichannel extension ⋆/ + /⋆ 11-10 audio type (0=not spec, 1=language included) ⋆/ + /⋆ 9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) ⋆/ + /⋆ 7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit, ⋆/ + /⋆ 5- 4 Sample frequency fs (0=48kHz, 1=96kHz) ⋆/ + /⋆ 2- 0 number of audio channels (n+1 channels) ⋆/ + +
+
+Audio Function Calls + + +
+open() +DESCRIPTION + +
+This system call opens a named audio device (e.g. /dev/dvb/adapter0/audio0) + for subsequent use. When an open() call has succeeded, the device will be ready + for use. The significance of blocking or non-blocking mode is described in the + documentation for functions where there is a difference. It does not affect the + semantics of the open() call itself. A device opened in blocking mode can later + be put into non-blocking mode (and vice versa) using the F_SETFL command + of the fcntl system call. This is a standard system call, documented in the Linux + manual page for fcntl. Only one user can open the Audio Device in O_RDWR + mode. All other attempts to open the device in this mode will fail, and an error + code will be returned. If the Audio Device is opened in O_RDONLY mode, the + only ioctl call that can be used is AUDIO_GET_STATUS. All other call will + return with an error code. + + +SYNOPSIS + + +int open(const char ⋆deviceName, int flags); + + +PARAMETERS + + +const char + *deviceName + +Name of specific audio device. + + +int flags + +A bit-wise OR of the following flags: + + + +O_RDONLY read-only access + + + +O_RDWR read/write access + + + +O_NONBLOCK open in non-blocking mode + + + +(blocking mode is the default) + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EINTERNAL + +Internal error. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + + + +
+close() +DESCRIPTION + +
+This system call closes a previously opened audio device. + + +SYNOPSIS + + +int close(int fd); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + + + +
+write() +DESCRIPTION + +
+This system call can only be used if AUDIO_SOURCE_MEMORY is selected + in the ioctl call AUDIO_SELECT_SOURCE. The data provided shall be in + PES format. If O_NONBLOCK is not specified the function will block until + buffer space is available. The amount of data to be transferred is implied by + count. + + +SYNOPSIS + + +size_t write(int fd, const void ⋆buf, size_t count); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +void *buf + +Pointer to the buffer containing the PES data. + + +size_t count + +Size of buf. + + +ERRORS + + +EPERM + +Mode AUDIO_SOURCE_MEMORY not selected. + + +ENOMEM + +Attempted to write more data than the internal buffer can + hold. + + +EBADF + +fd is not a valid open file descriptor. + + + +
AUDIO_STOP +DESCRIPTION + +
+This ioctl call asks the Audio Device to stop playing the current stream. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_STOP); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_STOP for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + + +
AUDIO_PLAY +DESCRIPTION + +
+This ioctl call asks the Audio Device to start playing an audio stream from the + selected source. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_PLAY); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_PLAY for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + + +
AUDIO_PAUSE +DESCRIPTION + +
+This ioctl call suspends the audio stream being played. Decoding and playing + are paused. It is then possible to restart again decoding and playing process of + the audio stream using AUDIO_CONTINUE command. + + +If AUDIO_SOURCE_MEMORY is selected in the ioctl call + AUDIO_SELECT_SOURCE, the DVB-subsystem will not decode (consume) + any more data until the ioctl call AUDIO_CONTINUE or AUDIO_PLAY is + performed. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_PAUSE); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_PAUSE for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + + +
AUDIO_SELECT_SOURCE +DESCRIPTION + +
+This ioctl call informs the audio device which source shall be used + for the input data. The possible sources are demux or memory. If + AUDIO_SOURCE_MEMORY is selected, the data is fed to the Audio Device + through the write command. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_SELECT_SOURCE, + audio_stream_source_t source); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SELECT_SOURCE for this command. + + +audio_stream_source_t + source + +Indicates the source that shall be used for the Audio + stream. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal input parameter. + + + +
AUDIO_SET_MUTE +DESCRIPTION + +
+This ioctl call asks the audio device to mute the stream that is currently being + played. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_SET_MUTE, + boolean state); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_MUTE for this command. + + +boolean state + +Indicates if audio device shall mute or not. + + + +TRUE Audio Mute + + + +FALSE Audio Un-mute + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal input parameter. + + + +
AUDIO_SET_AV_SYNC +DESCRIPTION + +
+This ioctl call asks the Audio Device to turn ON or OFF A/V synchronization. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_SET_AV_SYNC, + boolean state); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_AV_SYNC for this command. + + +boolean state + +Tells the DVB subsystem if A/V synchronization shall be + ON or OFF. + + + +TRUE AV-sync ON + + + +FALSE AV-sync OFF + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal input parameter. + + + +
AUDIO_SET_BYPASS_MODE +DESCRIPTION + +
+This ioctl call asks the Audio Device to bypass the Audio decoder and forward + the stream without decoding. This mode shall be used if streams that can’t be + handled by the DVB system shall be decoded. Dolby DigitalTM streams are + automatically forwarded by the DVB subsystem if the hardware can handle it. + + +SYNOPSIS + + +int ioctl(int fd, int request = + AUDIO_SET_BYPASS_MODE, boolean mode); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_BYPASS_MODE for this + command. + + +boolean mode + +Enables or disables the decoding of the current Audio + stream in the DVB subsystem. + + + +TRUE Bypass is disabled + + + +FALSE Bypass is enabled + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal input parameter. + + + +
AUDIO_CHANNEL_SELECT +DESCRIPTION + +
+This ioctl call asks the Audio Device to select the requested channel if possible. + + +SYNOPSIS + + +int ioctl(int fd, int request = + AUDIO_CHANNEL_SELECT, audio_channel_select_t); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_CHANNEL_SELECT for this + command. + + +audio_channel_select_t + ch + +Select the output format of the audio (mono left/right, + stereo). + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal input parameter ch. + + + +
AUDIO_GET_STATUS +DESCRIPTION + +
+This ioctl call asks the Audio Device to return the current state of the Audio + Device. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_GET_STATUS, + struct audio_status ⋆status); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_GET_STATUS for this command. + + +struct audio_status + *status + +Returns the current state of Audio Device. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EFAULT + +status points to invalid address. + + + +
AUDIO_GET_CAPABILITIES +DESCRIPTION + +
+This ioctl call asks the Audio Device to tell us about the decoding capabilities + of the audio hardware. + + +SYNOPSIS + + +int ioctl(int fd, int request = + AUDIO_GET_CAPABILITIES, unsigned int ⋆cap); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_GET_CAPABILITIES for this + command. + + +unsigned int *cap + +Returns a bit array of supported sound formats. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EFAULT + +cap points to an invalid address. + + + +
AUDIO_CLEAR_BUFFER +DESCRIPTION + +
+This ioctl call asks the Audio Device to clear all software and hardware buffers + of the audio decoder device. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_CLEAR_BUFFER); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_CLEAR_BUFFER for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + + +
AUDIO_SET_ID +DESCRIPTION + +
+This ioctl selects which sub-stream is to be decoded if a program or system + stream is sent to the video device. If no audio stream type is set the id has to be + in [0xC0,0xDF] for MPEG sound, in [0x80,0x87] for AC3 and in [0xA0,0xA7] + for LPCM. More specifications may follow for other stream types. If the stream + type is set the id just specifies the substream id of the audio stream and only + the first 5 bits are recognized. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_SET_ID, int + id); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_ID for this command. + + +int id + +audio sub-stream id + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Invalid sub-stream id. + + + +
AUDIO_SET_MIXER +DESCRIPTION + +
+This ioctl lets you adjust the mixer settings of the audio decoder. + + +SYNOPSIS + + +int ioctl(int fd, int request = AUDIO_SET_MIXER, + audio_mixer_t ⋆mix); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_ID for this command. + + +audio_mixer_t *mix + +mixer settings. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EFAULT + +mix points to an invalid address. + + + +
AUDIO_SET_STREAMTYPE +DESCRIPTION + +
+This ioctl tells the driver which kind of audio stream to expect. This is useful + if the stream offers several audio sub-streams like LPCM and AC3. + + +SYNOPSIS + + +int ioctl(fd, int request = AUDIO_SET_STREAMTYPE, + int type); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_STREAMTYPE for this + command. + + +int type + +stream type + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +type is not a valid or supported stream type. + + + +
AUDIO_SET_EXT_ID +DESCRIPTION + +
+This ioctl can be used to set the extension id for MPEG streams in DVD + playback. Only the first 3 bits are recognized. + + +SYNOPSIS + + +int ioctl(fd, int request = AUDIO_SET_EXT_ID, int + id); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_EXT_ID for this command. + + +int id + +audio sub_stream_id + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +id is not a valid id. + + + +
AUDIO_SET_ATTRIBUTES +DESCRIPTION + +
+This ioctl is intended for DVD playback and allows you to set certain + information about the audio stream. + + +SYNOPSIS + + +int ioctl(fd, int request = AUDIO_SET_ATTRIBUTES, + audio_attributes_t attr ); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_ATTRIBUTES for this command. + + +audio_attributes_t + attr + +audio attributes according to section ?? + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +attr is not a valid or supported attribute setting. + + + +
AUDIO_SET_KARAOKE +DESCRIPTION + +
+This ioctl allows one to set the mixer settings for a karaoke DVD. + + +SYNOPSIS + + +int ioctl(fd, int request = AUDIO_SET_STREAMTYPE, + audio_karaoke_t ⋆karaoke); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals AUDIO_SET_STREAMTYPE for this + command. + + +audio_karaoke_t + *karaoke + +karaoke settings according to section ??. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +karaoke is not a valid or supported karaoke setting. + + + + diff --git a/dvb-spec/sgml/ca.sgml b/dvb-spec/sgml/ca.sgml new file mode 100644 index 000000000..e2a70797d --- /dev/null +++ b/dvb-spec/sgml/ca.sgml @@ -0,0 +1,221 @@ +DVB CA Device +The DVB CA device controls the conditional access hardware. It can be accessed through +/dev/dvb/adapter0/ca0. Data types and and ioctl definitions can be accessed by +including linux/dvb/ca.h in your application. + + +
+CA Data Types + + +
+ca_slot_info_t + + /⋆ slot interface types and info ⋆/ + + typedef struct ca_slot_info_s { + int num; /⋆ slot number ⋆/ + + int type; /⋆ CA interface this slot supports ⋆/ + #define CA_CI 1 /⋆ CI high level interface ⋆/ + #define CA_CI_LINK 2 /⋆ CI link layer level interface ⋆/ + #define CA_CI_PHYS 4 /⋆ CI physical layer level interface ⋆/ + #define CA_SC 128 /⋆ simple smart card interface ⋆/ + + unsigned int flags; + #define CA_CI_MODULE_PRESENT 1 /⋆ module (or card) inserted ⋆/ + #define CA_CI_MODULE_READY 2 + } ca_slot_info_t; + + +
+
+ca_descr_info_t + + typedef struct ca_descr_info_s { + unsigned int num; /⋆ number of available descramblers (keys) ⋆/ + unsigned int type; /⋆ type of supported scrambling system ⋆/ + #define CA_ECD 1 + #define CA_NDS 2 + #define CA_DSS 4 + } ca_descr_info_t; + + +
+
+ca_cap_t + + typedef struct ca_cap_s { + unsigned int slot_num; /⋆ total number of CA card and module slots ⋆/ + unsigned int slot_type; /⋆ OR of all supported types ⋆/ + unsigned int descr_num; /⋆ total number of descrambler slots (keys) ⋆/ + unsigned int descr_type;/⋆ OR of all supported types ⋆/ + } ca_cap_t; + + +
+
+ca_msg_t + + /⋆ a message to/from a CI-CAM ⋆/ + typedef struct ca_msg_s { + unsigned int index; + unsigned int type; + unsigned int length; + unsigned char msg[256]; + } ca_msg_t; + + +
+
+ca_descr_t + + typedef struct ca_descr_s { + unsigned int index; + unsigned int parity; + unsigned char cw[8]; + } ca_descr_t; + +
+
+CA Function Calls + + +
+open() +DESCRIPTION + +
+This system call opens a named ca device (e.g. /dev/ost/ca) for subsequent use. +When an open() call has succeeded, the device will be ready for use. + The significance of blocking or non-blocking mode is described in the + documentation for functions where there is a difference. It does not affect the + semantics of the open() call itself. A device opened in blocking mode can later + be put into non-blocking mode (and vice versa) using the F_SETFL command + of the fcntl system call. This is a standard system call, documented in the Linux + manual page for fcntl. Only one user can open the CA Device in O_RDWR + mode. All other attempts to open the device in this mode will fail, and an error + code will be returned. + + +SYNOPSIS + + +int open(const char ⋆deviceName, int flags); + + +PARAMETERS + + +const char + *deviceName + +Name of specific video device. + + +int flags + +A bit-wise OR of the following flags: + + + +O_RDONLY read-only access + + + +O_RDWR read/write access + + + +O_NONBLOCK open in non-blocking mode + + + +(blocking mode is the default) + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EINTERNAL + +Internal error. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + + + +
+close() +DESCRIPTION + +
+This system call closes a previously opened audio device. + + +SYNOPSIS + + +int close(int fd); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + + + \ No newline at end of file diff --git a/dvb-spec/sgml/demux.sgml b/dvb-spec/sgml/demux.sgml new file mode 100644 index 000000000..ad3448219 --- /dev/null +++ b/dvb-spec/sgml/demux.sgml @@ -0,0 +1,973 @@ +DVB Demux Device + +The DVB demux device controls the filters of the DVB hardware/software. It can be +accessed through /dev/adapter0/demux0. Data types and and ioctl definitions can be +accessed by including linux/dvb/dmx.h in your application. + +
+Demux Data Types + +
+dmx_output_t + + typedef enum + { + DMX_OUT_DECODER, + DMX_OUT_TAP, + DMX_OUT_TS_TAP + } dmx_output_t; + +DMX_OUT_TAP delivers the stream output to the demux device on which the ioctl is +called. + +DMX_OUT_TS_TAP routes output to the logical DVR device /dev/dvb/adapter0/dvr0, +which delivers a TS multiplexed from all filters for which DMX_OUT_TS_TAP was +specified. + +
+ +
+dmx_input_t + + typedef enum + { + DMX_IN_FRONTEND, + DMX_IN_DVR + } dmx_input_t; + +
+ +
+dmx_pes_type_t + + typedef enum + { + DMX_PES_AUDIO, + DMX_PES_VIDEO, + DMX_PES_TELETEXT, + DMX_PES_SUBTITLE, + DMX_PES_PCR, + DMX_PES_OTHER + } dmx_pes_type_t; + +
+ +
+dmx_event_t + + typedef enum + { + DMX_SCRAMBLING_EV, + DMX_FRONTEND_EV + } dmx_event_t; + +
+ +
+dmx_scrambling_status_t + + typedef enum + { + DMX_SCRAMBLING_OFF, + DMX_SCRAMBLING_ON + } dmx_scrambling_status_t; + +
+ +
+struct dmx_filter + + typedef struct dmx_filter + { + uint8_t filter[DMX_FILTER_SIZE]; + uint8_t mask[DMX_FILTER_SIZE]; + } dmx_filter_t; + +
+ +
+struct dmx_sct_filter_params + + struct dmx_sct_filter_params + { + uint16_t pid; + dmx_filter_t filter; + uint32_t timeout; + uint32_t flags; + #define DMX_CHECK_CRC 1 + #define DMX_ONESHOT 2 + #define DMX_IMMEDIATE_START 4 + }; + +
+ +
+struct dmx_pes_filter_params + + struct dmx_pes_filter_params + { + uint16_t pid; + dmx_input_t input; + dmx_output_t output; + dmx_pes_type_t pes_type; + uint32_t flags; + }; + +
+ +
+struct dmx_event + + struct dmx_event + { + dmx_event_t event; + time_t timeStamp; + union + { + dmx_scrambling_status_t scrambling; + } u; + }; + +
+ +
+struct dmx_stc + + struct dmx_stc { + unsigned int num; /⋆ input : which STC? 0..N ⋆/ + unsigned int base; /⋆ output: divisor for stc to get 90 kHz clock ⋆/ + uint64_t stc; /⋆ output: stc in 'base'⋆90 kHz units ⋆/ + }; + +
+ +
+ +
+Demux Function Calls + +
+open() +DESCRIPTION + +
+This system call, used with a device name of /dev/dvb/adapter0/demux0, + allocates a new filter and returns a handle which can be used for subsequent + control of that filter. This call has to be made for each filter to be used, i.e. every + returned file descriptor is a reference to a single filter. /dev/dvb/adapter0/dvr0 + is a logical device to be used for retrieving Transport Streams for digital + video recording. When reading from this device a transport stream containing + the packets from all PES filters set in the corresponding demux device + (/dev/dvb/adapter0/demux0) having the output set to DMX_OUT_TS_TAP. A + recorded Transport Stream is replayed by writing to this device. +The significance of blocking or non-blocking mode is described in the + documentation for functions where there is a difference. It does not affect the + semantics of the open() call itself. A device opened in blocking mode can later + be put into non-blocking mode (and vice versa) using the F_SETFL command + of the fcntl system call. + + +SYNOPSIS + + +int open(const char ⋆deviceName, int flags); + + +PARAMETERS + + +const char + *deviceName + +Name of demux device. + + +int flags + +A bit-wise OR of the following flags: + + + +O_RDWR read/write access + + + +O_NONBLOCK open in non-blocking mode + + + +(blocking mode is the default) + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EINVAL + +Invalid argument. + + +EMFILE + +“Too many open files”, i.e. no more filters available. + + +ENOMEM + +The driver failed to allocate enough memory. + + + + +
+close() +DESCRIPTION + +
+This system call deactivates and deallocates a filter that was previously + allocated via the open() call. + + +SYNOPSIS + + +int close(int fd); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + + + +
+read() +DESCRIPTION + +
+This system call returns filtered data, which might be section or PES data. The + filtered data is transferred from the driver’s internal circular buffer to buf. The + maximum amount of data to be transferred is implied by count. + + +When returning section data the driver always tries to return a complete single + section (even though buf would provide buffer space for more data). If the size + of the buffer is smaller than the section as much as possible will be returned, + and the remaining data will be provided in subsequent calls. + + +The size of the internal buffer is 2 * 4096 bytes (the size of two maximum + sized sections) by default. The size of this buffer may be changed by using the + DMX_SET_BUFFER_SIZE function. If the buffer is not large enough, or if + the read operations are not performed fast enough, this may result in a buffer + overflow error. In this case EOVERFLOW will be returned, and the circular + buffer will be emptied. This call is blocking if there is no data to return, i.e. the + process will be put to sleep waiting for data, unless the O_NONBLOCK flag + is specified. + + +Note that in order to be able to read, the filtering process has to be started + by defining either a section or a PES filter by means of the ioctl functions, + and then starting the filtering process via the DMX_START ioctl function + or by setting the DMX_IMMEDIATE_START flag. If the reading is done + from a logical DVR demux device, the data will constitute a Transport Stream + including the packets from all PES filters in the corresponding demux device + /dev/dvb/adapter0/demux0 having the output set to DMX_OUT_TS_TAP. + + +SYNOPSIS + + +size_t read(int fd, void ⋆buf, size_t count); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +void *buf + +Pointer to the buffer to be used for returned filtered data. + + +size_t count + +Size of buf. + + +ERRORS + + +EWOULDBLOCK + +No data to return and O_NONBLOCK was specified. + + +EBADF + +fd is not a valid open file descriptor. + + +ECRC + +Last section had a CRC error - no data returned. The + buffer is flushed. + + +EOVERFLOW + + + + +The filtered data was not read from the buffer in due + time, resulting in non-read data being lost. The buffer is + flushed. + + +ETIMEDOUT + +The section was not loaded within the stated timeout + period. See ioctl DMX_SET_FILTER for how to set a + timeout. + + +EFAULT + +The driver failed to write to the callers buffer due to an + invalid *buf pointer. + + + + +
+write() +DESCRIPTION + +
+This system call is only provided by the logical device /dev/dvb/adapter0/dvr0, + associated with the physical demux device that provides the actual DVR + functionality. It is used for replay of a digitally recorded Transport Stream. + Matching filters have to be defined in the corresponding physical demux + device, /dev/dvb/adapter0/demux0. The amount of data to be transferred is + implied by count. + + +SYNOPSIS + + +ssize_t write(int fd, const void ⋆buf, size_t + count); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +void *buf + +Pointer to the buffer containing the Transport Stream. + + +size_t count + +Size of buf. + + +ERRORS + + +EWOULDBLOCK + +No data was written. This + might happen if O_NONBLOCK was specified and there + is no more buffer space available (if O_NONBLOCK is + not specified the function will block until buffer space is + available). + + +EBUSY + +This error code indicates that there are conflicting + requests. The corresponding demux device is setup to + receive data from the front- end. Make sure that these + filters are stopped and that the filters with input set to + DMX_IN_DVR are started. + + +EBADF + +fd is not a valid open file descriptor. + + + + +
+DMX_START +DESCRIPTION + +
+This ioctl call is used to start the actual filtering operation defined via the ioctl + calls DMX_SET_FILTER or DMX_SET_PES_FILTER. + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_START); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_START for this command. + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EINVAL + +Invalid argument, i.e. no filtering parameters provided via + the DMX_SET_FILTER or DMX_SET_PES_FILTER + functions. + + +EBUSY + +This error code indicates that there are conflicting + requests. There are active filters filtering data from + another input source. Make sure that these filters are + stopped before starting this filter. + + + + +
+DMX_STOP +DESCRIPTION + +
+This ioctl call is used to stop the actual filtering operation defined via the + ioctl calls DMX_SET_FILTER or DMX_SET_PES_FILTER and started via + the DMX_START command. + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_STOP); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_STOP for this command. + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + + + +
+DMX_SET_FILTER +DESCRIPTION + +
+This ioctl call sets up a filter according to the filter and mask parameters + provided. A timeout may be defined stating number of seconds to wait for a + section to be loaded. A value of 0 means that no timeout should be applied. + Finally there is a flag field where it is possible to state whether a section should + be CRC-checked, whether the filter should be a ”one-shot” filter, i.e. if the + filtering operation should be stopped after the first section is received, and + whether the filtering operation should be started immediately (without waiting + for a DMX_START ioctl call). If a filter was previously set-up, this filter will + be canceled, and the receive buffer will be flushed. + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_SET_FILTER, + struct dmx_sct_filter_params ⋆params); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_SET_FILTER for this command. + + +struct + dmx_sct_filter_params + *params + +Pointer to structure containing filter parameters. + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EINVAL + +Invalid argument. + + + + +
+DMX_SET_PES_FILTER +DESCRIPTION + +
+This ioctl call sets up a PES filter according to the parameters provided. By a + PES filter is meant a filter that is based just on the packet identifier (PID), i.e. + no PES header or payload filtering capability is supported. + + +The transport stream destination for the filtered output may be set. Also the + PES type may be stated in order to be able to e.g. direct a video stream directly + to the video decoder. Finally there is a flag field where it is possible to state + whether the filtering operation should be started immediately (without waiting + for a DMX_START ioctl call). If a filter was previously set-up, this filter will + be cancelled, and the receive buffer will be flushed. + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_SET_PES_FILTER, + struct dmx_pes_filter_params ⋆params); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_SET_PES_FILTER for this command. + + +struct + dmx_pes_filter_params + *params + +Pointer to structure containing filter parameters. + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EINVAL + +Invalid argument. + + +EBUSY + +This error code indicates that there are conflicting + requests. There are active filters filtering data from + another input source. Make sure that these filters are + stopped before starting this filter. + + + + +
+DMX_SET_BUFFER_SIZE +DESCRIPTION + +
+This ioctl call is used to set the size of the circular buffer used for filtered data. + The default size is two maximum sized sections, i.e. if this function is not called + a buffer size of 2 * 4096 bytes will be used. + + +SYNOPSIS + + +int ioctl( int fd, int request = + DMX_SET_BUFFER_SIZE, unsigned long size); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_SET_BUFFER_SIZE for this command. + + +unsigned long size + +Size of circular buffer. + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +ENOMEM + +The driver was not able to allocate a buffer of the + requested size. + + + + +
+DMX_GET_EVENT +DESCRIPTION + +
+This ioctl call returns an event if available. If an event is not available, + the behavior depends on whether the device is in blocking or non-blocking + mode. In the latter case, the call fails immediately with errno set to + EWOULDBLOCK. In the former case, the call blocks until an event becomes + available. + + +The standard Linux poll() and/or select() system calls can be used with the + device file descriptor to watch for new events. For select(), the file descriptor + should be included in the exceptfds argument, and for poll(), POLLPRI should + be specified as the wake-up condition. Only the latest event for each filter is + saved. + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_GET_EVENT, + struct dmx_event ⋆ev); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_GET_EVENT for this command. + + +struct dmx_event *ev + +Pointer to the location where the event is to be stored. + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EFAULT + +ev points to an invalid address. + + +EWOULDBLOCK + +There is no event pending, and the device is in + non-blocking mode. + + + + +
+DMX_GET_STC +DESCRIPTION + +
+This ioctl call returns the current value of the system time counter (which is driven + by a PES filter of type DMX_PES_PCR). Some hardware supports more than one + STC, so you must specify which one by setting the num field of stc before the ioctl + (range 0...n). The result is returned in form of a ratio with a 64 bit numerator + and a 32 bit denominator, so the real 90kHz STC value is stc->stc / + stc->base + . + + +SYNOPSIS + + +int ioctl( int fd, int request = DMX_GET_STC, struct + dmx_stc ⋆stc); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals DMX_GET_STC for this command. + + +struct dmx_stc *stc + +Pointer to the location where the stc is to be stored. + + +ERRORS + + +EBADF + +fd is not a valid file descriptor. + + +EFAULT + +stc points to an invalid address. + + +EINVAL + +Invalid stc number. + + + \ No newline at end of file diff --git a/dvb-spec/sgml/dvbapi-complete.sgml b/dvb-spec/sgml/dvbapi-complete.sgml deleted file mode 100644 index 753efd3fe..000000000 --- a/dvb-spec/sgml/dvbapi-complete.sgml +++ /dev/null @@ -1,9503 +0,0 @@ - -%docbook.dtd; -] > - - -
- - -LINUX DVB API Version 3 - - - Copyright 2002, 2003 Convergence GmbH - Written by Dr. Ralph J.K. Metzler - <rjkm@metzlerbros.de> - and Dr. Marcus O.C. Metzler - <mocm@metzlerbros.de> - - -24/07/2003 -V 1.0.0 - -Permission is granted to copy, distribute and/or modify this document under the terms of -the GNU Free Documentation License, Version 1.1 or any later version published by the Free -Software Foundation. A copy of the license is included in the chapter entitled ”GNU Free -Documentation License”. - - - - -
Contents - - - - - -
Introduction -
<abbrev role="title-mark">1.1</abbrev>What you need to know -The reader of this document is required to have some knowledge in the area of digital -video broadcasting (DVB) and should be familiar with part I of the MPEG2 specification -ISO/IEC 13818 (aka ITU-T H.222), i.e you should know what a program/transport -stream (PS/TS) is and what is meant by a packetized elementary stream (PES) or an -I-frame. - -Various DVB standards documents are available from http://www.dvb.org/ and/or -http://www.etsi.org/. - -It is also necessary to know how to access unix/linux devices and how to use ioctl calls. -This also includes the knowledge of C or C++. - - -
<abbrev role="title-mark">1.2</abbrev>History -The first API for DVB cards we used at Convergence in late 1999 was an extension of the -Video4Linux API which was primarily developed for frame grabber cards. As such it -was not really well suited to be used for DVB cards and their new features like -recording MPEG streams and filtering several section and PES data streams at the same -time. - -In early 2000, we were approached by Nokia with a proposal for a new standard Linux -DVB API. As a commitment to the development of terminals based on open standards, Nokia -and Convergence made it available to all Linux developers and published it on -http://www.linuxtv.org/ in September 2000. Convergence is the maintainer of the -Linux DVB API. Together with the LinuxTV community (i.e. you, the reader of this -document), the Linux DVB API will be constantly reviewed and improved. With the Linux -driver for the Siemens/Hauppauge DVB PCI card Convergence provides a first -implementation of the Linux DVB API. - - -
<abbrev role="title-mark">1.3</abbrev>Overview -
<blockquote> -<section role="center"><title/> -<para><graphic width="306.14374pt" fileref="dvbstb.ps" ></graphic> -<blockquote role="caption"><title role="caption">Figure 1.1 -Components of a DVB card/STB -
- -A DVB PCI card or DVB set-top-box (STB) usually consists of the following main -hardware components: - - - -Frontend consisting of tuner and DVB demodulator - -Here the raw signal reaches the DVB hardware from a satellite dish or antenna - or directly from cable. The frontend down-converts and demodulates this signal - into an MPEG transport stream (TS). In case of a satellite frontend, this includes - a facility for satellite equipment control (SEC), which allows control of LNB - polarization, multi feed switches or dish rotors. - - - -Conditional Access (CA) hardware like CI adapters and smartcard slots - -The complete TS is passed through the CA hardware. Programs to which the user - has access (controlled by the smart card) are decoded in real time and re-inserted - into the TS. - - - -Demultiplexer which filters the incoming DVB stream - -The demultiplexer splits the TS into its components like audio and video streams. - Besides usually several of such audio and video streams it also contains data - streams with information about the programs offered in this or other streams of - the same provider. - - - -MPEG2 audio and video decoder - -The main targets of the demultiplexer are the MPEG2 audio and video decoders. - After decoding they pass on the uncompressed audio and video to the computer - screen or (through a PAL/NTSC encoder) to a TV set. -Figure ?? shows a crude schematic of the control and data flow between those -components. - -On a DVB PCI card not all of these have to be present since some functionality can be -provided by the main CPU of the PC (e.g. MPEG picture and sound decoding) or is not -needed (e.g. for data-only uses like “internet over satellite”). Also not every card or STB -provides conditional access hardware. - -
<abbrev role="title-mark">1.4</abbrev>Linux DVB Devices -The Linux DVB API lets you control these hardware components through currently six -Unix-style character devices for video, audio, frontend, demux, CA and IP-over-DVB -networking. The video and audio devices control the MPEG2 decoder hardware, the frontend -device the tuner and the DVB demodulator. The demux device gives you control over the PES -and section filters of the hardware. If the hardware does not support filtering these filters can -be implemented in software. Finally, the CA device controls all the conditional access -capabilities of the hardware. It can depend on the individual security requirements of the -platform, if and how many of the CA functions are made available to the application through -this device. - -All devices can be found in the /dev tree under /dev/dvb. The individual devices are -called - - - -/dev/dvb/adapterN/audioM, - - - -/dev/dvb/adapterN/videoM, - - - -/dev/dvb/adapterN/frontendM, - - - -/dev/dvb/adapterN/netM, - - - -/dev/dvb/adapterN/demuxM, - - - -/dev/dvb/adapterN/caM, -where N enumerates the DVB PCI cards in a system starting from 0, and M enumerates the -devices of each type within each adapter, starting from 0, too. We will omit the -“/dev/dvb/adapterN/” in the further dicussion of these devices. The naming scheme -for the devices is the same wheter devfs is used or not. - -More details about the data structures and function calls of all the devices are described in -the following chapters. - - -
<abbrev role="title-mark">1.5</abbrev>API include files -For each of the DVB devices a corresponding include file exists. The DVB API include -files should be included in application sources with a partial path like: - - - #include <linux/dvb/frontend.h> - -To enable applications to support different API version, an additional include file -linux/dvb/version.h exists, which defines the constant DVB_API_VERSION. This -document describes DVB_API_VERSION 3. - - -
DVB Frontend API -The DVB frontend device controls the tuner and DVB demodulator hardware. It can be -accessed through /dev/dvb/adapter0/frontend0. Data types and and ioctl -definitions can be accessed by including linux/dvb/frontend.h in your -application. - -DVB frontends come in three varieties: DVB-S (satellite), DVB-C (cable) and DVB-T -(terrestrial). Transmission via the internet (DVB-IP) is not yet handled by this API but a -future extension is possible. For DVB-S the frontend device also supports satellite equipment -control (SEC) via DiSEqC and V-SEC protocols. The DiSEqC (digital SEC) specification is -available from Eutelsat http://www.eutelsat.org/. - -Note that the DVB API may also be used for MPEG decoder-only PCI cards, in which -case there exists no frontend device. - -
<abbrev role="title-mark">2.1</abbrev>Frontend Data Types - -
<abbrev role="title-mark">2.1.1</abbrev>frontend type -For historical reasons frontend types are named after the type of modulation used in -transmission. - - - typedef enum fe_type { - FE_QPSK, /⋆ DVB-S ⋆/ - FE_QAM, /⋆ DVB-C ⋆/ - FE_OFDM /⋆ DVB-T ⋆/ - } fe_type_t; - - -
<abbrev role="title-mark">2.1.2</abbrev>frontend capabilities -Capabilities describe what a frontend can do. Some capabilities can only be supported for -a specific frontend type. - - - typedef enum fe_caps { - FE_IS_STUPID = 0, - FE_CAN_INVERSION_AUTO = 0x1, - FE_CAN_FEC_1_2 = 0x2, - FE_CAN_FEC_2_3 = 0x4, - FE_CAN_FEC_3_4 = 0x8, - FE_CAN_FEC_4_5 = 0x10, - FE_CAN_FEC_5_6 = 0x20, - FE_CAN_FEC_6_7 = 0x40, - FE_CAN_FEC_7_8 = 0x80, - FE_CAN_FEC_8_9 = 0x100, - FE_CAN_FEC_AUTO = 0x200, - FE_CAN_QPSK = 0x400, - FE_CAN_QAM_16 = 0x800, - FE_CAN_QAM_32 = 0x1000, - FE_CAN_QAM_64 = 0x2000, - FE_CAN_QAM_128 = 0x4000, - FE_CAN_QAM_256 = 0x8000, - FE_CAN_QAM_AUTO = 0x10000, - FE_CAN_TRANSMISSION_MODE_AUTO = 0x20000, - FE_CAN_BANDWIDTH_AUTO = 0x40000, - FE_CAN_GUARD_INTERVAL_AUTO = 0x80000, - FE_CAN_HIERARCHY_AUTO = 0x100000, - FE_CAN_MUTE_TS = 0x80000000, - FE_CAN_CLEAN_SETUP = 0x40000000 - } fe_caps_t; - - -
<abbrev role="title-mark">2.1.3</abbrev>frontend information -Information about the frontend ca be queried with FE_GET_INFO (??). - - - struct dvb_frontend_info { - char name[128]; - fe_type_t type; - uint32_t frequency_min; - uint32_t frequency_max; - uint32_t frequency_stepsize; - uint32_t frequency_tolerance; - uint32_t symbol_rate_min; - uint32_t symbol_rate_max; - uint32_t symbol_rate_tolerance; /⋆ ppm ⋆/ - uint32_t notifier_delay; /⋆ ms ⋆/ - fe_caps_t caps; - }; - - -
<abbrev role="title-mark">2.1.4</abbrev>diseqc master command -A message sent from the frontend to DiSEqC capable equipment. - - - struct dvb_diseqc_master_cmd { - uint8_t msg [6]; /⋆ { framing, address, command, data[3] } ⋆/ - uint8_t msg_len; /⋆ valid values are 3...6 ⋆/ - }; - - -
<abbrev role="title-mark">2.1.5</abbrev>diseqc slave reply -A reply to the frontend from DiSEqC 2.0 capable equipment. - - - struct dvb_diseqc_slave_reply { - uint8_t msg [4]; /⋆ { framing, data [3] } ⋆/ - uint8_t msg_len; /⋆ valid values are 0...4, 0 means no msg ⋆/ - int timeout; /⋆ return from ioctl after timeout ms with ⋆/ - }; /⋆ errorcode when no message was received ⋆/ - - -
<abbrev role="title-mark">2.1.6</abbrev>SEC voltage -The voltage is usually used with non-DiSEqC capable LNBs to switch the polarzation -(horizontal/vertical). When using DiSEqC epuipment this voltage has to be switched -consistently to the DiSEqC commands as described in the DiSEqC spec. - - - typedef enum fe_sec_voltage { - SEC_VOLTAGE_13, - SEC_VOLTAGE_18 - } fe_sec_voltage_t; - - -
<abbrev role="title-mark">2.1.7</abbrev>SEC continuous tone -The continous 22KHz tone is usually used with non-DiSEqC capable LNBs to switch the -high/low band of a dual-band LNB. When using DiSEqC epuipment this voltage has to -be switched consistently to the DiSEqC commands as described in the DiSEqC -spec. - - - typedef enum fe_sec_tone_mode { - SEC_TONE_ON, - SEC_TONE_OFF - } fe_sec_tone_mode_t; - - -
<abbrev role="title-mark">2.1.8</abbrev>SEC tone burst -The 22KHz tone burst is usually used with non-DiSEqC capable switches to select -between two connected LNBs/satellites. When using DiSEqC epuipment this voltage has to -be switched consistently to the DiSEqC commands as described in the DiSEqC -spec. - - - typedef enum fe_sec_mini_cmd { - SEC_MINI_A, - SEC_MINI_B - } fe_sec_mini_cmd_t; - - -
<abbrev role="title-mark">2.1.9</abbrev>frontend status -Several functions of the frontend device use the fe_status data type defined -by - - - typedef enum fe_status { - FE_HAS_SIGNAL = 0x01, /⋆ found something above the noise level ⋆/ - FE_HAS_CARRIER = 0x02, /⋆ found a DVB signal ⋆/ - FE_HAS_VITERBI = 0x04, /⋆ FEC is stable ⋆/ - FE_HAS_SYNC = 0x08, /⋆ found sync bytes ⋆/ - FE_HAS_LOCK = 0x10, /⋆ everything's working... ⋆/ - FE_TIMEDOUT = 0x20, /⋆ no lock within the last ~2 seconds ⋆/ - FE_REINIT = 0x40 /⋆ frontend was reinitialized, ⋆/ - } fe_status_t; /⋆ application is recommned to reset ⋆/ - -to indicate the current state and/or state changes of the frontend hardware. - - -
<abbrev role="title-mark">2.1.10</abbrev>frontend parameters -The kind of parameters passed to the frontend device for tuning depend on the kind of -hardware you are using. All kinds of parameters are combined as a union in the -FrontendParameters structure: - - - struct dvb_frontend_parameters { - uint32_t frequency; /⋆ (absolute) frequency in Hz for QAM/OFDM ⋆/ - /⋆ intermediate frequency in kHz for QPSK ⋆/ - fe_spectral_inversion_t inversion; - union { - struct dvb_qpsk_parameters qpsk; - struct dvb_qam_parameters qam; - struct dvb_ofdm_parameters ofdm; - } u; - }; - -For satellite QPSK frontends you have to use the QPSKParameters member defined -by - - - struct dvb_qpsk_parameters { - uint32_t symbol_rate; /⋆ symbol rate in Symbols per second ⋆/ - fe_code_rate_t fec_inner; /⋆ forward error correction (see above) ⋆/ - }; - -for cable QAM frontend you use the QAMParameters structure - - - struct dvb_qam_parameters { - uint32_t symbol_rate; /⋆ symbol rate in Symbols per second ⋆/ - fe_code_rate_t fec_inner; /⋆ forward error correction (see above) ⋆/ - fe_modulation_t modulation; /⋆ modulation type (see above) ⋆/ - }; - -DVB-T frontends are supported by the OFDMParamters structure - - - struct dvb_ofdm_parameters { - fe_bandwidth_t bandwidth; - fe_code_rate_t code_rate_HP; /⋆ high priority stream code rate ⋆/ - fe_code_rate_t code_rate_LP; /⋆ low priority stream code rate ⋆/ - fe_modulation_t constellation; /⋆ modulation type (see above) ⋆/ - fe_transmit_mode_t transmission_mode; - fe_guard_interval_t guard_interval; - fe_hierarchy_t hierarchy_information; - }; - -In the case of QPSK frontends the Frequency field specifies the intermediate -frequency, i.e. the offset which is effectively added to the local oscillator frequency (LOF) of -the LNB. The intermediate frequency has to be specified in units of kHz. For QAM and -OFDM frontends the Frequency specifies the absolute frequency and is given in -Hz. - -The Inversion field can take one of these values: - - - typedef enum fe_spectral_inversion { - INVERSION_OFF, - INVERSION_ON, - INVERSION_AUTO - } fe_spectral_inversion_t; - -It indicates if spectral inversion should be presumed or not. In the automatic setting -(INVERSION_AUTO) the hardware will try to figure out the correct setting by -itself. - -The possible values for the FEC_inner field are - - - typedef enum fe_code_rate { - FEC_NONE = 0, - FEC_1_2, - FEC_2_3, - FEC_3_4, - FEC_4_5, - FEC_5_6, - FEC_6_7, - FEC_7_8, - FEC_8_9, - FEC_AUTO - } fe_code_rate_t; - -which correspond to error correction rates of 1/2, 2/3, etc., no error correction or auto -detection. - -For cable and terrestrial frontends (QAM and OFDM) one also has to specify the quadrature -modulation mode which can be one of the following: - - - typedef enum fe_modulation { - QPSK, - QAM_16, - QAM_32, - QAM_64, - QAM_128, - QAM_256, - QAM_AUTO - } fe_modulation_t; - -Finally, there are several more parameters for OFDM: - - - typedef enum fe_transmit_mode { - TRANSMISSION_MODE_2K, - TRANSMISSION_MODE_8K, - TRANSMISSION_MODE_AUTO - } fe_transmit_mode_t; - - - typedef enum fe_bandwidth { - BANDWIDTH_8_MHZ, - BANDWIDTH_7_MHZ, - BANDWIDTH_6_MHZ, - BANDWIDTH_AUTO - } fe_bandwidth_t; - - - typedef enum fe_guard_interval { - GUARD_INTERVAL_1_32, - GUARD_INTERVAL_1_16, - GUARD_INTERVAL_1_8, - GUARD_INTERVAL_1_4, - GUARD_INTERVAL_AUTO - } fe_guard_interval_t; - - - typedef enum fe_hierarchy { - HIERARCHY_NONE, - HIERARCHY_1, - HIERARCHY_2, - HIERARCHY_4, - HIERARCHY_AUTO - } fe_hierarchy_t; - - -
<abbrev role="title-mark">2.1.11</abbrev>frontend events - - struct dvb_frontend_event { - fe_status_t status; - struct dvb_frontend_parameters parameters; - }; - -
<abbrev role="title-mark">2.2</abbrev>Frontend Function Calls - -
<abbrev role="title-mark">2.2.1</abbrev>open() -DESCRIPTION - -
-This system call opens a named frontend device (/dev/dvb/adapter0/frontend0) - for subsequent use. Usually the first thing to do after a successful open is to - find out the frontend type with FE_GET_INFO. -The device can be opened in read-only mode, which only allows monitoring of - device status and statistics, or read/write mode, which allows any kind of use - (e.g. performing tuning operations.) - -In a system with multiple front-ends, it is usually the case that multiple devices - cannot be open in read/write mode simultaneously. As long as a front-end - device is opened in read/write mode, other open() calls in read/write mode will - either fail or block, depending on whether non-blocking or blocking mode was - specified. A front-end device opened in blocking mode can later be put into - non-blocking mode (and vice versa) using the F_SETFL command of the fcntl - system call. This is a standard system call, documented in the Linux manual - page for fcntl. When an open() call has succeeded, the device will be ready - for use in the specified mode. This implies that the corresponding hardware is - powered up, and that other front-ends may have been powered down to make - that possible. - - - -SYNOPSIS - - -int open(const char ⋆deviceName, int flags); - - -PARAMETERS - - -const char - *deviceName - -Name of specific video device. - - -int flags - -A bit-wise OR of the following flags: - - - -O_RDONLY read-only access - - - -O_RDWR read/write access - - - -O_NONBLOCK open in non-blocking mode - - - -(blocking mode is the default) - - -ERRORS - - -ENODEV - -Device driver not loaded/available. - - -EINTERNAL - -Internal error. - - -EBUSY - -Device or resource busy. - - -EINVAL - -Invalid argument. - - - -
<abbrev role="title-mark">2.2.2</abbrev>close() -DESCRIPTION - -
-This system call closes a previously opened front-end device. After closing - a front-end device, its corresponding hardware might be powered down - automatically. - - -SYNOPSIS - - -int close(int fd); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - - -
<abbrev role="title-mark">2.2.3</abbrev>FE_READ_STATUS<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call returns status information about the front-end. This call only - requires read-only access to the device. - - -SYNOPSIS - - -int ioctl(int fd, int request = FE_READ_STATUS, - fe_status_t ⋆status); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_READ_STATUS for this command. - - -struct fe_status_t - *status - -Points to the location where the front-end status word is - to be stored. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EFAULT - -status points to invalid address. - - - -
<abbrev role="title-mark">2.2.4</abbrev>FE_READ_BER<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call returns the bit error rate for the signal currently - received/demodulated by the front-end. For this command, read-only access to - the device is sufficient. - - -SYNOPSIS - - -int ioctl(int fd, int request = FE_READ_BER, - uint32_t ⋆ber); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_READ_BER for this command. - - -uint32_t *ber - -The bit error rate is stored into *ber. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EFAULT - -ber points to invalid address. - - -ENOSIGNAL - -There is no signal, thus no meaningful bit error rate. Also - returned if the front-end is not turned on. - - -ENOSYS - -Function not available for this device. - - - -
<abbrev role="title-mark">2.2.5</abbrev>FE_READ_SNR<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call returns the signal-to-noise ratio for the signal currently received - by the front-end. For this command, read-only access to the device is sufficient. - - -SYNOPSIS - - -int ioctl(int fd, int request = FE_READ_SNR, int16_t - ⋆snr); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_READ_SNR for this command. - - -int16_t *snr - -The signal-to-noise ratio is stored into *snr. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EFAULT - -snr points to invalid address. - - -ENOSIGNAL - -There is no signal, thus no meaningful signal strength - value. Also returned if front-end is not turned on. - - -ENOSYS - -Function not available for this device. - - - -
<abbrev role="title-mark">2.2.6</abbrev>FE_READ_SIGNAL_STRENGTH<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call returns the signal strength value for the signal currently received - by the front-end. For this command, read-only access to the device is sufficient. - - -SYNOPSIS - - -int ioctl( int fd, int request = - FE_READ_SIGNAL_STRENGTH, int16_t ⋆strength); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_READ_SIGNAL_STRENGTH for this - command. - - -int16_t *strength - -The signal strength value is stored into *strength. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EFAULT - -status points to invalid address. - - -ENOSIGNAL - -There is no signal, thus no meaningful signal strength - value. Also returned if front-end is not turned on. - - -ENOSYS - -Function not available for this device. - - - -
<abbrev role="title-mark">2.2.7</abbrev>FE_READ_UNCORRECTED_BLOCKS<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call returns the number of uncorrected blocks detected by the device - driver during its lifetime. For meaningful measurements, the increment in block - count during a specific time interval should be calculated. For this command, - read-only access to the device is sufficient. - - -Note that the counter will wrap to zero after its maximum count has been - reached. - - -SYNOPSIS - - -int ioctl( int fd, int request = - FE_READ_UNCORRECTED_BLOCKS, uint32_t ⋆ublocks); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_READ_UNCORRECTED_BLOCKS for this - command. - - -uint32_t *ublocks - -The total number of uncorrected blocks seen by the driver - so far. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EFAULT - -ublocks points to invalid address. - - -ENOSYS - -Function not available for this device. - - - -
<abbrev role="title-mark">2.2.8</abbrev>FE_SET_FRONTEND<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call starts a tuning operation using specified parameters. The result - of this call will be successful if the parameters were valid and the tuning could - be initiated. The result of the tuning operation in itself, however, will arrive - asynchronously as an event (see documentation for FE_GET_EVENT and - FrontendEvent.) If a new FE_SET_FRONTEND operation is initiated before - the previous one was completed, the previous operation will be aborted in favor - of the new one. This command requires read/write access to the device. - - -SYNOPSIS - - -int ioctl(int fd, int request = FE_SET_FRONTEND, - struct dvb_frontend_parameters ⋆p); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_SET_FRONTEND for this command. - - -struct - dvb_frontend_parameters - *p - -Points to parameters for tuning operation. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EFAULT - -p points to invalid address. - - -EINVAL - -Maximum supported symbol rate reached. - - - -
<abbrev role="title-mark">2.2.9</abbrev>FE_GET_FRONTEND<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call queries the currently effective frontend parameters. For this - command, read-only access to the device is sufficient. - - -SYNOPSIS - - -int ioctl(int fd, int request = FE_GET_FRONTEND, - struct dvb_frontend_parameters ⋆p); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_SET_FRONTEND for this command. - - -struct - dvb_frontend_parameters - *p - -Points to parameters for tuning operation. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EFAULT - -p points to invalid address. - - -EINVAL - -Maximum supported symbol rate reached. - - - -
<abbrev role="title-mark">2.2.10</abbrev>FE_GET_EVENT<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call returns a frontend event if available. If an event is not - available, the behavior depends on whether the device is in blocking or - non-blocking mode. In the latter case, the call fails immediately with errno - set to EWOULDBLOCK. In the former case, the call blocks until an event - becomes available. - - -The standard Linux poll() and/or select() system calls can be used with the - device file descriptor to watch for new events. For select(), the file descriptor - should be included in the exceptfds argument, and for poll(), POLLPRI should - be specified as the wake-up condition. Since the event queue allocated is - rather small (room for 8 events), the queue must be serviced regularly to avoid - overflow. If an overflow happens, the oldest event is discarded from the queue, - and an error (EOVERFLOW) occurs the next time the queue is read. After - reporting the error condition in this fashion, subsequent FE_GET_EVENT - calls will return events from the queue as usual. - - -For the sake of implementation simplicity, this command requires read/write - access to the device. - - -SYNOPSIS - - -int ioctl(int fd, int request = QPSK_GET_EVENT, - struct dvb_frontend_event ⋆ev); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_GET_EVENT for this command. - - -struct - dvb_frontend_event - *ev - -Points to the location where the event, - - - -if any, is to be stored. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EFAULT - -ev points to invalid address. - - -EWOULDBLOCK - -There is no event pending, and the device is in - non-blocking mode. - - -EOVERFLOW - - - - -Overflow in event queue - one or more events were lost. - - - -
<abbrev role="title-mark">2.2.11</abbrev>FE_GET_INFO<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call returns information about the front-end. This call only requires - read-only access to the device. - - -SYNOPSIS - - - int ioctl(int fd, int request = FE_GET_INFO, struct - dvb_frontend_info ⋆info); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_GET_INFO for this command. - - -struct - dvb_frontend_info - *info - -Points to the location where the front-end information is - to be stored. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EFAULT - -info points to invalid address. - - - -
<abbrev role="title-mark">2.2.12</abbrev>FE_DISEQC_RESET_OVERLOAD<indexterm role="printindex" /> -DESCRIPTION - -
-If the bus has been automatically powered off due to power overload, this ioctl - call restores the power to the bus. The call requires read/write access to the - device. This call has no effect if the device is manually powered off. Not all - DVB adapters support this ioctl. - - -SYNOPSIS - - -int ioctl(int fd, int request = - FE_DISEQC_RESET_OVERLOAD); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_DISEQC_RESET_OVERLOAD for this - command. - - -ERRORS - - -EBADF - -fd is not a valid file descriptor. - - -EPERM - -Permission denied (needs read/write access). - - -EINTERNAL - -Internal error in the device driver. - - - -
<abbrev role="title-mark">2.2.13</abbrev>FE_DISEQC_SEND_MASTER_CMD<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call is used to send a a DiSEqC command. - - -SYNOPSIS - - -int ioctl(int fd, int request = - FE_DISEQC_SEND_MASTER_CMD, struct - dvb_diseqc_master_cmd ⋆cmd); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_DISEQC_SEND_MASTER_CMD for this - command. - - -struct - dvb_diseqc_master_cmd - *cmd - -Pointer to the command to be transmitted. - - -ERRORS - - -EBADF - -fd is not a valid file descriptor. - - -EFAULT - -Seq points to an invalid address. - - -EINVAL - -The data structure referred to by seq is invalid in some - way. - - -EPERM - -Permission denied (needs read/write access). - - -EINTERNAL - -Internal error in the device driver. - - - -
<abbrev role="title-mark">2.2.14</abbrev>FE_DISEQC_RECV_SLAVE_REPLY<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call is used to receive reply to a DiSEqC 2.0 command. - - -SYNOPSIS - - -int ioctl(int fd, int request = - FE_DISEQC_RECV_SLAVE_REPLY, struct - dvb_diseqc_slave_reply ⋆reply); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_DISEQC_RECV_SLAVE_REPLY for this - command. - - -struct - dvb_diseqc_slave_reply - *reply - -Pointer to the command to be received. - - -ERRORS - - -EBADF - -fd is not a valid file descriptor. - - -EFAULT - -Seq points to an invalid address. - - -EINVAL - -The data structure referred to by seq is invalid in some - way. - - -EPERM - -Permission denied (needs read/write access). - - -EINTERNAL - -Internal error in the device driver. - - - -
<abbrev role="title-mark">2.2.15</abbrev>FE_DISEQC_SEND_BURST<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call is used to send a 22KHz tone burst. - - -SYNOPSIS - - -int ioctl(int fd, int request = - FE_DISEQC_SEND_BURST, fe_sec_mini_cmd_t burst); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_DISEQC_SEND_BURST for this command. - - -fe_sec_mini_cmd_t - burst - -burst A or B. - - -ERRORS - - -EBADF - -fd is not a valid file descriptor. - - -EFAULT - -Seq points to an invalid address. - - -EINVAL - -The data structure referred to by seq is invalid in some - way. - - -EPERM - -Permission denied (needs read/write access). - - -EINTERNAL - -Internal error in the device driver. - - - -
<abbrev role="title-mark">2.2.16</abbrev>FE_SET_TONE<indexterm role="printindex" /> -DESCRIPTION - -
-This call is used to set the generation of the continuous 22kHz tone. This call - requires read/write permissions. - - -SYNOPSIS - - -int ioctl(int fd, int request = FE_SET_TONE, - fe_sec_tone_mode_t tone); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_SET_TONE for this command. - - -fe_sec_tone_mode_t - tone - -The requested tone generation mode (on/off). - - -ERRORS - - -ENODEV - -Device driver not loaded/available. - - -EBUSY - -Device or resource busy. - - -EINVAL - -Invalid argument. - - -EPERM - -File not opened with read permissions. - - -EINTERNAL - -Internal error in the device driver. - - - -
<abbrev role="title-mark">2.2.17</abbrev>FE_SET_VOLTAGE<indexterm role="printindex" /> -DESCRIPTION - -
-This call is used to set the bus voltage. This call requires read/write - permissions. - - -SYNOPSIS - - -int ioctl(int fd, int request = FE_SET_VOLTAGE, - fe_sec_voltage_t voltage); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_SET_VOLTAGE for this command. - - -fe_sec_voltage_t - voltage - -The requested bus voltage. - - -ERRORS - - -ENODEV - -Device driver not loaded/available. - - -EBUSY - -Device or resource busy. - - -EINVAL - -Invalid argument. - - -EPERM - -File not opened with read permissions. - - -EINTERNAL - -Internal error in the device driver. - - - -
<abbrev role="title-mark">2.2.18</abbrev>FE_ENABLE_HIGH_LNB_VOLTAGE<indexterm role="printindex" /> -DESCRIPTION - -
-If high != 0 enables slightly higher voltages instead of 13/18V (to compensate - for long cables). This call requires read/write permissions. Not all DVB - adapters support this ioctl. - - -SYNOPSIS - - -int ioctl(int fd, int request = - FE_ENABLE_HIGH_LNB_VOLTAGE, int high); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals FE_SET_VOLTAGE for this command. - - -int high - -The requested bus voltage. - - -ERRORS - - -ENODEV - -Device driver not loaded/available. - - -EBUSY - -Device or resource busy. - - -EINVAL - -Invalid argument. - - -EPERM - -File not opened with read permissions. - - -EINTERNAL - -Internal error in the device driver. - - - -
DVB Demux Device -The DVB demux device controls the filters of the DVB hardware/software. It can be -accessed through /dev/adapter0/demux0. Data types and and ioctl definitions can be -accessed by including linux/dvb/dmx.h in your application. - -
<abbrev role="title-mark">3.1</abbrev>Demux Data Types - -
<abbrev role="title-mark">3.1.1</abbrev>dmx_output_t - - typedef enum - { - DMX_OUT_DECODER, - DMX_OUT_TAP, - DMX_OUT_TS_TAP - } dmx_output_t; - -DMX_OUT_TAP delivers the stream output to the demux device on which the ioctl is -called. - -DMX_OUT_TS_TAP routes output to the logical DVR device /dev/dvb/adapter0/dvr0, -which delivers a TS multiplexed from all filters for which DMX_OUT_TS_TAP was -specified. - - -
<abbrev role="title-mark">3.1.2</abbrev>dmx_input_t - - typedef enum - { - DMX_IN_FRONTEND, - DMX_IN_DVR - } dmx_input_t; - - -
<abbrev role="title-mark">3.1.3</abbrev>dmx_pes_type_t - - typedef enum - { - DMX_PES_AUDIO, - DMX_PES_VIDEO, - DMX_PES_TELETEXT, - DMX_PES_SUBTITLE, - DMX_PES_PCR, - DMX_PES_OTHER - } dmx_pes_type_t; - - -
<abbrev role="title-mark">3.1.4</abbrev>dmx_event_t - - typedef enum - { - DMX_SCRAMBLING_EV, - DMX_FRONTEND_EV - } dmx_event_t; - - -
<abbrev role="title-mark">3.1.5</abbrev>dmx_scrambling_status_t - - typedef enum - { - DMX_SCRAMBLING_OFF, - DMX_SCRAMBLING_ON - } dmx_scrambling_status_t; - - -
<abbrev role="title-mark">3.1.6</abbrev>struct dmx_filter - - typedef struct dmx_filter - { - uint8_t filter[DMX_FILTER_SIZE]; - uint8_t mask[DMX_FILTER_SIZE]; - } dmx_filter_t; - - -
<abbrev role="title-mark">3.1.7</abbrev>struct dmx_sct_filter_params - - struct dmx_sct_filter_params - { - uint16_t pid; - dmx_filter_t filter; - uint32_t timeout; - uint32_t flags; - #define DMX_CHECK_CRC 1 - #define DMX_ONESHOT 2 - #define DMX_IMMEDIATE_START 4 - }; - - -
<abbrev role="title-mark">3.1.8</abbrev>struct dmx_pes_filter_params - - struct dmx_pes_filter_params - { - uint16_t pid; - dmx_input_t input; - dmx_output_t output; - dmx_pes_type_t pes_type; - uint32_t flags; - }; - - -
<abbrev role="title-mark">3.1.9</abbrev>struct dmx_event - - struct dmx_event - { - dmx_event_t event; - time_t timeStamp; - union - { - dmx_scrambling_status_t scrambling; - } u; - }; - - -
<abbrev role="title-mark">3.1.10</abbrev>struct dmx_stc - - struct dmx_stc { - unsigned int num; /⋆ input : which STC? 0..N ⋆/ - unsigned int base; /⋆ output: divisor for stc to get 90 kHz clock ⋆/ - uint64_t stc; /⋆ output: stc in 'base'⋆90 kHz units ⋆/ - }; - -
<abbrev role="title-mark">3.2</abbrev>Demux Function Calls - -
<abbrev role="title-mark">3.2.1</abbrev>open() -DESCRIPTION - -
-This system call, used with a device name of /dev/dvb/adapter0/demux0, - allocates a new filter and returns a handle which can be used for subsequent - control of that filter. This call has to be made for each filter to be used, i.e. every - returned file descriptor is a reference to a single filter. /dev/dvb/adapter0/dvr0 - is a logical device to be used for retrieving Transport Streams for digital - video recording. When reading from this device a transport stream containing - the packets from all PES filters set in the corresponding demux device - (/dev/dvb/adapter0/demux0) having the output set to DMX_OUT_TS_TAP. A - recorded Transport Stream is replayed by writing to this device. -The significance of blocking or non-blocking mode is described in the - documentation for functions where there is a difference. It does not affect the - semantics of the open() call itself. A device opened in blocking mode can later - be put into non-blocking mode (and vice versa) using the F_SETFL command - of the fcntl system call. - - - -SYNOPSIS - - -int open(const char ⋆deviceName, int flags); - - -PARAMETERS - - -const char - *deviceName - -Name of demux device. - - -int flags - -A bit-wise OR of the following flags: - - - -O_RDWR read/write access - - - -O_NONBLOCK open in non-blocking mode - - - -(blocking mode is the default) - - -ERRORS - - -ENODEV - -Device driver not loaded/available. - - -EINVAL - -Invalid argument. - - -EMFILE - -“Too many open files”, i.e. no more filters available. - - -ENOMEM - -The driver failed to allocate enough memory. - - - -
<abbrev role="title-mark">3.2.2</abbrev>close() -DESCRIPTION - -
-This system call deactivates and deallocates a filter that was previously - allocated via the open() call. - - -SYNOPSIS - - -int close(int fd); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - - -
<abbrev role="title-mark">3.2.3</abbrev>read() -DESCRIPTION - -
-This system call returns filtered data, which might be section or PES data. The - filtered data is transferred from the driver’s internal circular buffer to buf. The - maximum amount of data to be transferred is implied by count. - - -When returning section data the driver always tries to return a complete single - section (even though buf would provide buffer space for more data). If the size - of the buffer is smaller than the section as much as possible will be returned, - and the remaining data will be provided in subsequent calls. - - -The size of the internal buffer is 2 * 4096 bytes (the size of two maximum - sized sections) by default. The size of this buffer may be changed by using the - DMX_SET_BUFFER_SIZE function. If the buffer is not large enough, or if - the read operations are not performed fast enough, this may result in a buffer - overflow error. In this case EOVERFLOW will be returned, and the circular - buffer will be emptied. This call is blocking if there is no data to return, i.e. the - process will be put to sleep waiting for data, unless the O_NONBLOCK flag - is specified. - - -Note that in order to be able to read, the filtering process has to be started - by defining either a section or a PES filter by means of the ioctl functions, - and then starting the filtering process via the DMX_START ioctl function - or by setting the DMX_IMMEDIATE_START flag. If the reading is done - from a logical DVR demux device, the data will constitute a Transport Stream - including the packets from all PES filters in the corresponding demux device - /dev/dvb/adapter0/demux0 having the output set to DMX_OUT_TS_TAP. - - -SYNOPSIS - - -size_t read(int fd, void ⋆buf, size_t count); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -void *buf - -Pointer to the buffer to be used for returned filtered data. - - -size_t count - -Size of buf. - - -ERRORS - - -EWOULDBLOCK - -No data to return and O_NONBLOCK was specified. - - -EBADF - -fd is not a valid open file descriptor. - - -ECRC - -Last section had a CRC error - no data returned. The - buffer is flushed. - - -EOVERFLOW - - - - -The filtered data was not read from the buffer in due - time, resulting in non-read data being lost. The buffer is - flushed. - - -ETIMEDOUT - -The section was not loaded within the stated timeout - period. See ioctl DMX_SET_FILTER for how to set a - timeout. - - -EFAULT - -The driver failed to write to the callers buffer due to an - invalid *buf pointer. - - - -
<abbrev role="title-mark">3.2.4</abbrev>write() -DESCRIPTION - -
-This system call is only provided by the logical device /dev/dvb/adapter0/dvr0, - associated with the physical demux device that provides the actual DVR - functionality. It is used for replay of a digitally recorded Transport Stream. - Matching filters have to be defined in the corresponding physical demux - device, /dev/dvb/adapter0/demux0. The amount of data to be transferred is - implied by count. - - -SYNOPSIS - - -ssize_t write(int fd, const void ⋆buf, size_t - count); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -void *buf - -Pointer to the buffer containing the Transport Stream. - - -size_t count - -Size of buf. - - -ERRORS - - -EWOULDBLOCK - -No data was written. This - might happen if O_NONBLOCK was specified and there - is no more buffer space available (if O_NONBLOCK is - not specified the function will block until buffer space is - available). - - -EBUSY - -This error code indicates that there are conflicting - requests. The corresponding demux device is setup to - receive data from the front- end. Make sure that these - filters are stopped and that the filters with input set to - DMX_IN_DVR are started. - - -EBADF - -fd is not a valid open file descriptor. - - - -
<abbrev role="title-mark">3.2.5</abbrev>DMX_START<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call is used to start the actual filtering operation defined via the ioctl - calls DMX_SET_FILTER or DMX_SET_PES_FILTER. - - -SYNOPSIS - - -int ioctl( int fd, int request = DMX_START); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals DMX_START for this command. - - -ERRORS - - -EBADF - -fd is not a valid file descriptor. - - -EINVAL - -Invalid argument, i.e. no filtering parameters provided via - the DMX_SET_FILTER or DMX_SET_PES_FILTER - functions. - - -EBUSY - -This error code indicates that there are conflicting - requests. There are active filters filtering data from - another input source. Make sure that these filters are - stopped before starting this filter. - - - -
<abbrev role="title-mark">3.2.6</abbrev>DMX_STOP<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call is used to stop the actual filtering operation defined via the - ioctl calls DMX_SET_FILTER or DMX_SET_PES_FILTER and started via - the DMX_START command. - - -SYNOPSIS - - -int ioctl( int fd, int request = DMX_STOP); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals DMX_STOP for this command. - - -ERRORS - - -EBADF - -fd is not a valid file descriptor. - - - -
<abbrev role="title-mark">3.2.7</abbrev>DMX_SET_FILTER<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call sets up a filter according to the filter and mask parameters - provided. A timeout may be defined stating number of seconds to wait for a - section to be loaded. A value of 0 means that no timeout should be applied. - Finally there is a flag field where it is possible to state whether a section should - be CRC-checked, whether the filter should be a ”one-shot” filter, i.e. if the - filtering operation should be stopped after the first section is received, and - whether the filtering operation should be started immediately (without waiting - for a DMX_START ioctl call). If a filter was previously set-up, this filter will - be canceled, and the receive buffer will be flushed. - - -SYNOPSIS - - -int ioctl( int fd, int request = DMX_SET_FILTER, - struct dmx_sct_filter_params ⋆params); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals DMX_SET_FILTER for this command. - - -struct - dmx_sct_filter_params - *params - -Pointer to structure containing filter parameters. - - -ERRORS - - -EBADF - -fd is not a valid file descriptor. - - -EINVAL - -Invalid argument. - - - -
<abbrev role="title-mark">3.2.8</abbrev>DMX_SET_PES_FILTER<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call sets up a PES filter according to the parameters provided. By a - PES filter is meant a filter that is based just on the packet identifier (PID), i.e. - no PES header or payload filtering capability is supported. - - -The transport stream destination for the filtered output may be set. Also the - PES type may be stated in order to be able to e.g. direct a video stream directly - to the video decoder. Finally there is a flag field where it is possible to state - whether the filtering operation should be started immediately (without waiting - for a DMX_START ioctl call). If a filter was previously set-up, this filter will - be cancelled, and the receive buffer will be flushed. - - -SYNOPSIS - - -int ioctl( int fd, int request = DMX_SET_PES_FILTER, - struct dmx_pes_filter_params ⋆params); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals DMX_SET_PES_FILTER for this command. - - -struct - dmx_pes_filter_params - *params - -Pointer to structure containing filter parameters. - - -ERRORS - - -EBADF - -fd is not a valid file descriptor. - - -EINVAL - -Invalid argument. - - -EBUSY - -This error code indicates that there are conflicting - requests. There are active filters filtering data from - another input source. Make sure that these filters are - stopped before starting this filter. - - - -
<abbrev role="title-mark">3.2.9</abbrev>DMX_SET_BUFFER_SIZE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call is used to set the size of the circular buffer used for filtered data. - The default size is two maximum sized sections, i.e. if this function is not called - a buffer size of 2 * 4096 bytes will be used. - - -SYNOPSIS - - -int ioctl( int fd, int request = - DMX_SET_BUFFER_SIZE, unsigned long size); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals DMX_SET_BUFFER_SIZE for this command. - - -unsigned long size - -Size of circular buffer. - - -ERRORS - - -EBADF - -fd is not a valid file descriptor. - - -ENOMEM - -The driver was not able to allocate a buffer of the - requested size. - - - -
<abbrev role="title-mark">3.2.10</abbrev>DMX_GET_EVENT<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call returns an event if available. If an event is not available, - the behavior depends on whether the device is in blocking or non-blocking - mode. In the latter case, the call fails immediately with errno set to - EWOULDBLOCK. In the former case, the call blocks until an event becomes - available. - - -The standard Linux poll() and/or select() system calls can be used with the - device file descriptor to watch for new events. For select(), the file descriptor - should be included in the exceptfds argument, and for poll(), POLLPRI should - be specified as the wake-up condition. Only the latest event for each filter is - saved. - - -SYNOPSIS - - -int ioctl( int fd, int request = DMX_GET_EVENT, - struct dmx_event ⋆ev); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals DMX_GET_EVENT for this command. - - -struct dmx_event *ev - -Pointer to the location where the event is to be stored. - - -ERRORS - - -EBADF - -fd is not a valid file descriptor. - - -EFAULT - -ev points to an invalid address. - - -EWOULDBLOCK - -There is no event pending, and the device is in - non-blocking mode. - - - -
<abbrev role="title-mark">3.2.11</abbrev>DMX_GET_STC<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call returns the current value of the system time counter (which is driven - by a PES filter of type DMX_PES_PCR). Some hardware supports more than one - STC, so you must specify which one by setting the num field of stc before the ioctl - (range 0...n). The result is returned in form of a ratio with a 64 bit numerator - and a 32 bit denominator, so the real 90kHz STC value is stc->stc / - stc->base - . - - -SYNOPSIS - - -int ioctl( int fd, int request = DMX_GET_STC, struct - dmx_stc ⋆stc); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals DMX_GET_STC for this command. - - -struct dmx_stc *stc - -Pointer to the location where the stc is to be stored. - - -ERRORS - - -EBADF - -fd is not a valid file descriptor. - - -EFAULT - -stc points to an invalid address. - - -EINVAL - -Invalid stc number. - - -
DVB Video Device -The DVB video device controls the MPEG2 video decoder of the DVB hardware. It -can be accessed through /dev/dvb/adapter0/video0. Data types and and -ioctl definitions can be accessed by including linux/dvb/video.h in your -application. - -Note that the DVB video device only controls decoding of the MPEG video stream, not -its presentation on the TV or computer screen. On PCs this is typically handled by an -associated video4linux device, e.g. /dev/video, which allows scaling and defining output -windows. - -Some DVB cards don’t have their own MPEG decoder, which results in the omission of -the audio and video device as well as the video4linux device. - -The ioctls that deal with SPUs (sub picture units) and navigation packets are only -supported on some MPEG decoders made for DVD playback. - -
<abbrev role="title-mark">4.1</abbrev>Video Data Types - -
<abbrev role="title-mark">4.1.1</abbrev>video_format_t -The video_format_t data type defined by - - - typedef enum { - VIDEO_FORMAT_4_3, - VIDEO_FORMAT_16_9 - } video_format_t; - -is used in the VIDEO_SET_FORMAT function (??) to tell the driver which aspect ratio -the output hardware (e.g. TV) has. It is also used in the data structures video_status -(??) returned by VIDEO_GET_STATUS (??) and video_event (??) returned by -VIDEO_GET_EVENT (??) which report about the display format of the current video -stream. - - -
<abbrev role="title-mark">4.1.2</abbrev>video_display_format_t -In case the display format of the video stream and of the display hardware differ the -application has to specify how to handle the cropping of the picture. This can be done using -the VIDEO_SET_DISPLAY_FORMAT call (??) which accepts - - - typedef enum { - VIDEO_PAN_SCAN, - VIDEO_LETTER_BOX, - VIDEO_CENTER_CUT_OUT - } video_display_format_t; - -as argument. - - -
<abbrev role="title-mark">4.1.3</abbrev>video stream source -The video stream source is set through the VIDEO_SELECT_SOURCE call and can take -the following values, depending on whether we are replaying from an internal (demuxer) or -external (user write) source. - - - typedef enum { - VIDEO_SOURCE_DEMUX, - VIDEO_SOURCE_MEMORY - } video_stream_source_t; - -VIDEO_SOURCE_DEMUX selects the demultiplexer (fed either by the frontend or the -DVR device) as the source of the video stream. If VIDEO_SOURCE_MEMORY -is selected the stream comes from the application through the write() system -call. - - -
<abbrev role="title-mark">4.1.4</abbrev>video play state -The following values can be returned by the VIDEO_GET_STATUS call representing the -state of video playback. - - - typedef enum { - VIDEO_STOPPED, - VIDEO_PLAYING, - VIDEO_FREEZED - } video_play_state_t; - - -
<abbrev role="title-mark">4.1.5</abbrev>struct video_event -The following is the structure of a video event as it is returned by the VIDEO_GET_EVENT -call. - - - struct video_event { - int32_t type; - time_t timestamp; - union { - video_format_t video_format; - } u; - }; - - -
<abbrev role="title-mark">4.1.6</abbrev>struct video_status -The VIDEO_GET_STATUS call returns the following structure informing about various -states of the playback operation. - - - struct video_status { - boolean video_blank; - video_play_state_t play_state; - video_stream_source_t stream_source; - video_format_t video_format; - video_displayformat_t display_format; - }; - -If video_blank is set video will be blanked out if the channel is changed or if playback is -stopped. Otherwise, the last picture will be displayed. play_state indicates if the video is -currently frozen, stopped, or being played back. The stream_source corresponds to the seleted -source for the video stream. It can come either from the demultiplexer or from memory. -The video_format indicates the aspect ratio (one of 4:3 or 16:9) of the currently -played video stream. Finally, display_format corresponds to the selected cropping -mode in case the source video format is not the same as the format of the output -device. - - -
<abbrev role="title-mark">4.1.7</abbrev>struct video_still_picture -An I-frame displayed via the VIDEO_STILLPICTURE call is passed on within the -following structure. - - - /⋆ pointer to and size of a single iframe in memory ⋆/ - struct video_still_picture { - char ⋆iFrame; - int32_t size; - }; - - -
<abbrev role="title-mark">4.1.8</abbrev>video capabilities -A call to VIDEO_GET_CAPABILITIES returns an unsigned integer with the following -bits set according to the hardwares capabilities. - - - /⋆ bit definitions for capabilities: ⋆/ - /⋆ can the hardware decode MPEG1 and/or MPEG2? ⋆/ - #define VIDEO_CAP_MPEG1 1 - #define VIDEO_CAP_MPEG2 2 - /⋆ can you send a system and/or program stream to video device? - (you still have to open the video and the audio device but only - send the stream to the video device) ⋆/ - #define VIDEO_CAP_SYS 4 - #define VIDEO_CAP_PROG 8 - /⋆ can the driver also handle SPU, NAVI and CSS encoded data? - (CSS API is not present yet) ⋆/ - #define VIDEO_CAP_SPU 16 - #define VIDEO_CAP_NAVI 32 - #define VIDEO_CAP_CSS 64 - - -
<abbrev role="title-mark">4.1.9</abbrev>video system -A call to VIDEO_SET_SYSTEM sets the desired video system for TV output. The -following system types can be set: - - - typedef enum { - VIDEO_SYSTEM_PAL, - VIDEO_SYSTEM_NTSC, - VIDEO_SYSTEM_PALN, - VIDEO_SYSTEM_PALNc, - VIDEO_SYSTEM_PALM, - VIDEO_SYSTEM_NTSC60, - VIDEO_SYSTEM_PAL60, - VIDEO_SYSTEM_PALM60 - } video_system_t; - - -
<abbrev role="title-mark">4.1.10</abbrev>struct video_highlight -Calling the ioctl VIDEO_SET_HIGHLIGHTS posts the SPU highlight information. The -call expects the following format for that information: - - - typedef - struct video_highlight { - boolean active; /⋆ 1=show highlight, 0=hide highlight ⋆/ - uint8_t contrast1; /⋆ 7- 4 Pattern pixel contrast ⋆/ - /⋆ 3- 0 Background pixel contrast ⋆/ - uint8_t contrast2; /⋆ 7- 4 Emphasis pixel-2 contrast ⋆/ - /⋆ 3- 0 Emphasis pixel-1 contrast ⋆/ - uint8_t color1; /⋆ 7- 4 Pattern pixel color ⋆/ - /⋆ 3- 0 Background pixel color ⋆/ - uint8_t color2; /⋆ 7- 4 Emphasis pixel-2 color ⋆/ - /⋆ 3- 0 Emphasis pixel-1 color ⋆/ - uint32_t ypos; /⋆ 23-22 auto action mode ⋆/ - /⋆ 21-12 start y ⋆/ - /⋆ 9- 0 end y ⋆/ - uint32_t xpos; /⋆ 23-22 button color number ⋆/ - /⋆ 21-12 start x ⋆/ - /⋆ 9- 0 end x ⋆/ - } video_highlight_t; - - -
<abbrev role="title-mark">4.1.11</abbrev>video SPU -Calling VIDEO_SET_SPU deactivates or activates SPU decoding, according to the -following format: - - - typedef - struct video_spu { - boolean active; - int stream_id; - } video_spu_t; - - -
<abbrev role="title-mark">4.1.12</abbrev>video SPU palette -The following structure is used to set the SPU palette by calling VIDEO_SPU_PALETTE: - - - typedef - struct video_spu_palette{ - int length; - uint8_t ⋆palette; - } video_spu_palette_t; - - -
<abbrev role="title-mark">4.1.13</abbrev>video NAVI pack -In order to get the navigational data the following structure has to be passed to the ioctl -VIDEO_GET_NAVI: - - - typedef - struct video_navi_pack{ - int length; /⋆ 0 ... 1024 ⋆/ - uint8_t data[1024]; - } video_navi_pack_t; - - -
<abbrev role="title-mark">4.1.14</abbrev>video attributes -The following attributes can be set by a call to VIDEO_SET_ATTRIBUTES: - - - typedef uint16_t video_attributes_t; - /⋆ bits: descr. ⋆/ - /⋆ 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) ⋆/ - /⋆ 13-12 TV system (0=525/60, 1=625/50) ⋆/ - /⋆ 11-10 Aspect ratio (0=4:3, 3=16:9) ⋆/ - /⋆ 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca ⋆/ - /⋆ 7 line 21-1 data present in GOP (1=yes, 0=no) ⋆/ - /⋆ 6 line 21-2 data present in GOP (1=yes, 0=no) ⋆/ - /⋆ 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 ⋆/ - /⋆ 2 source letterboxed (1=yes, 0=no) ⋆/ - /⋆ 0 film/camera mode (0=camera, 1=film (625/50 only)) ⋆/ - -
<abbrev role="title-mark">4.2</abbrev>Video Function Calls - -
<abbrev role="title-mark">4.2.1</abbrev>open() -DESCRIPTION - -
-This system call opens a named video device (e.g. /dev/dvb/adapter0/video0) - for subsequent use. -When an open() call has succeeded, the device will be ready for use. - The significance of blocking or non-blocking mode is described in the - documentation for functions where there is a difference. It does not affect the - semantics of the open() call itself. A device opened in blocking mode can later - be put into non-blocking mode (and vice versa) using the F_SETFL command - of the fcntl system call. This is a standard system call, documented in the Linux - manual page for fcntl. Only one user can open the Video Device in O_RDWR - mode. All other attempts to open the device in this mode will fail, and an - error-code will be returned. If the Video Device is opened in O_RDONLY - mode, the only ioctl call that can be used is VIDEO_GET_STATUS. All other - call will return an error code. - - - -SYNOPSIS - - -int open(const char ⋆deviceName, int flags); - - -PARAMETERS - - -const char - *deviceName - -Name of specific video device. - - -int flags - -A bit-wise OR of the following flags: - - - -O_RDONLY read-only access - - - -O_RDWR read/write access - - - -O_NONBLOCK open in non-blocking mode - - - -(blocking mode is the default) - - -ERRORS - - -ENODEV - -Device driver not loaded/available. - - -EINTERNAL - -Internal error. - - -EBUSY - -Device or resource busy. - - -EINVAL - -Invalid argument. - - - -
<abbrev role="title-mark">4.2.2</abbrev>close() -DESCRIPTION - -
-This system call closes a previously opened video device. - - -SYNOPSIS - - -int close(int fd); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - - -
<abbrev role="title-mark">4.2.3</abbrev>write() -DESCRIPTION - -
-This system call can only be used if VIDEO_SOURCE_MEMORY is selected - in the ioctl call VIDEO_SELECT_SOURCE. The data provided shall be in - PES format, unless the capability allows other formats. If O_NONBLOCK is - not specified the function will block until buffer space is available. The amount - of data to be transferred is implied by count. - - -SYNOPSIS - - -size_t write(int fd, const void ⋆buf, size_t count); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -void *buf - -Pointer to the buffer containing the PES data. - - -size_t count - -Size of buf. - - -ERRORS - - -EPERM - -Mode VIDEO_SOURCE_MEMORY not selected. - - -ENOMEM - -Attempted to write more data than the internal buffer can - hold. - - -EBADF - -fd is not a valid open file descriptor. - - - -
<abbrev role="title-mark">4.2.4</abbrev>VIDEO_STOP<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Video Device to stop playing the current stream. - Depending on the input parameter, the screen can be blanked out or displaying - the last decoded frame. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_STOP, boolean - mode); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_STOP for this command. - - -Boolean mode - -Indicates how the screen shall be handled. - - - -TRUE: Blank screen when stop. - - - -FALSE: Show last decoded frame. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error, possibly in the communication with the - DVB subsystem. - - - -
<abbrev role="title-mark">4.2.5</abbrev>VIDEO_PLAY<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Video Device to start playing a video stream from the - selected source. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_PLAY); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_PLAY for this command. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error, possibly in the communication with the - DVB subsystem. - - - -
<abbrev role="title-mark">4.2.6</abbrev>VIDEO_FREEZE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call suspends the live video stream being played. Decoding - and playing are frozen. It is then possible to restart the decoding - and playing process of the video stream using the VIDEO_CONTINUE - command. If VIDEO_SOURCE_MEMORY is selected in the ioctl call - VIDEO_SELECT_SOURCE, the DVB subsystem will not decode any more - data until the ioctl call VIDEO_CONTINUE or VIDEO_PLAY is performed. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_FREEZE); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_FREEZE for this command. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error, possibly in the communication with the - DVB subsystem. - - - -
<abbrev role="title-mark">4.2.7</abbrev>VIDEO_CONTINUE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call restarts decoding and playing processes of the video stream - which was played before a call to VIDEO_FREEZE was made. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_CONTINUE); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_CONTINUE for this command. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error, possibly in the communication with the - DVB subsystem. - - - -
<abbrev role="title-mark">4.2.8</abbrev>VIDEO_SELECT_SOURCE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call informs the video device which source shall be used for the input - data. The possible sources are demux or memory. If memory is selected, the - data is fed to the video device through the write command. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_SELECT_SOURCE, - video_stream_source_t source); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SELECT_SOURCE for this command. - - -video_stream_source_t - source - -Indicates which source shall be used for the Video stream. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error, possibly in the communication with the - DVB subsystem. - - - -
<abbrev role="title-mark">4.2.9</abbrev>VIDEO_SET_BLANK<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Video Device to blank out the picture. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_SET_BLANK, boolean - mode); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SET_BLANK for this command. - - -boolean mode - -TRUE: Blank screen when stop. - - - -FALSE: Show last decoded frame. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error, possibly in the communication with the - DVB subsystem. - - -EINVAL - -Illegal input parameter - - - -
<abbrev role="title-mark">4.2.10</abbrev>VIDEO_GET_STATUS<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Video Device to return the current status of the device. - - -SYNOPSIS - - - int ioctl(fd, int request = VIDEO_GET_STATUS, struct - video_status ⋆status); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_GET_STATUS for this command. - - -struct video_status - *status - -Returns the current status of the Video Device. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error, possibly in the communication with the - DVB subsystem. - - -EFAULT - -status points to invalid address - - - -
<abbrev role="title-mark">4.2.11</abbrev>VIDEO_GET_EVENT<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call returns an event of type video_event if available. If an event is - not available, the behavior depends on whether the device is in blocking or - non-blocking mode. In the latter case, the call fails immediately with errno - set to EWOULDBLOCK. In the former case, the call blocks until an event - becomes available. The standard Linux poll() and/or select() system calls can - be used with the device file descriptor to watch for new events. For select(), - the file descriptor should be included in the exceptfds argument, and for - poll(), POLLPRI should be specified as the wake-up condition. Read-only - permissions are sufficient for this ioctl call. - - -SYNOPSIS - - - int ioctl(fd, int request = VIDEO_GET_EVENT, struct - video_event ⋆ev); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_GET_EVENT for this command. - - -struct video_event - *ev - -Points to the location where the event, if any, is to be - stored. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EFAULT - -ev points to invalid address - - -EWOULDBLOCK - -There is no event pending, and the device is in - non-blocking mode. - - -EOVERFLOW - - - - -Overflow in event queue - one or more events were lost. - - - -
<abbrev role="title-mark">4.2.12</abbrev>VIDEO_SET_DISPLAY_FORMAT<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Video Device to select the video format to be applied - by the MPEG chip on the video. - - -SYNOPSIS - - - int ioctl(fd, int request = - VIDEO_SET_DISPLAY_FORMAT, video_display_format_t - format); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SET_DISPLAY_FORMAT for this - command. - - -video_display_format_t - format - -Selects the video format to be used. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error. - - -EINVAL - -Illegal parameter format. - - - -
<abbrev role="title-mark">4.2.13</abbrev>VIDEO_STILLPICTURE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Video Device to display a still picture (I-frame). The - input data shall contain an I-frame. If the pointer is NULL, then the current - displayed still picture is blanked. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_STILLPICTURE, - struct video_still_picture ⋆sp); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_STILLPICTURE for this command. - - -struct - video_still_picture - *sp - -Pointer to a location where an I-frame and size is stored. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error. - - -EFAULT - -sp points to an invalid iframe. - - - -
<abbrev role="title-mark">4.2.14</abbrev>VIDEO_FAST_FORWARD<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Video Device to skip decoding of N number of I-frames. - This call can only be used if VIDEO_SOURCE_MEMORY is selected. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_FAST_FORWARD, int - nFrames); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_FAST_FORWARD for this command. - - -int nFrames - -The number of frames to skip. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error. - - -EPERM - -Mode VIDEO_SOURCE_MEMORY not selected. - - -EINVAL - -Illegal parameter format. - - - -
<abbrev role="title-mark">4.2.15</abbrev>VIDEO_SLOWMOTION<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the video device to repeat decoding frames N number of - times. This call can only be used if VIDEO_SOURCE_MEMORY is selected. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_SLOWMOTION, int - nFrames); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SLOWMOTION for this command. - - -int nFrames - -The number of times to repeat each frame. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error. - - -EPERM - -Mode VIDEO_SOURCE_MEMORY not selected. - - -EINVAL - -Illegal parameter format. - - - -
<abbrev role="title-mark">4.2.16</abbrev>VIDEO_GET_CAPABILITIES<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the video device about its decoding capabilities. On success - it returns and integer which has bits set according to the defines in section ??. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_GET_CAPABILITIES, - unsigned int ⋆cap); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_GET_CAPABILITIES for this - command. - - -unsigned int *cap - -Pointer to a location where to store the capability - information. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EFAULT - -cap points to an invalid iframe. - - - -
<abbrev role="title-mark">4.2.17</abbrev>VIDEO_SET_ID<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl selects which sub-stream is to be decoded if a program or system - stream is sent to the video device. - - -SYNOPSIS - - -int ioctl(int fd, int request = VIDEO_SET_ID, int - id); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SET_ID for this command. - - -int id - -video sub-stream id - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - -EINVAL - -Invalid sub-stream id. - - - -
<abbrev role="title-mark">4.2.18</abbrev>VIDEO_CLEAR_BUFFER<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call clears all video buffers in the driver and in the decoder hardware. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_CLEAR_BUFFER); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_CLEAR_BUFFER for this command. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - - -
<abbrev role="title-mark">4.2.19</abbrev>VIDEO_SET_STREAMTYPE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl tells the driver which kind of stream to expect being written to it. If - this call is not used the default of video PES is used. Some drivers might not - support this call and always expect PES. - - -SYNOPSIS - - -int ioctl(fd, int request = VIDEO_SET_STREAMTYPE, - int type); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SET_STREAMTYPE for this command. - - -int type - -stream type - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINVAL - -type is not a valid or supported stream type. - - - -
<abbrev role="title-mark">4.2.20</abbrev>VIDEO_SET_FORMAT<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl sets the screen format (aspect ratio) of the connected output device - (TV) so that the output of the decoder can be adjusted accordingly. - - -SYNOPSIS - - - int ioctl(fd, int request = VIDEO_SET_FORMAT, - video_format_t format); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SET_FORMAT for this command. - - -video_format_t - format - -video format of TV as defined in section ??. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINVAL - -format is not a valid video format. - - - -
<abbrev role="title-mark">4.2.21</abbrev>VIDEO_SET_SYSTEM<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl sets the television output format. The format (see section ??) may - vary from the color format of the displayed MPEG stream. If the hardware is - not able to display the requested format the call will return an error. - - -SYNOPSIS - - - int ioctl(fd, int request = VIDEO_SET_SYSTEM , - video_system_t system); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SET_FORMAT for this command. - - -video_system_t - system - -video system of TV output. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINVAL - -system is not a valid or supported video system. - - - -
<abbrev role="title-mark">4.2.22</abbrev>VIDEO_SET_HIGHLIGHT<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl sets the SPU highlight information for the menu access of a DVD. - - -SYNOPSIS - - - int ioctl(fd, int request = VIDEO_SET_HIGHLIGHT - ,video_highlight_t ⋆vhilite) - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SET_HIGHLIGHT for this command. - - -video_highlight_t - *vhilite - -SPU Highlight information according to section ??. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINVAL - -input is not a valid highlight setting. - - - -
<abbrev role="title-mark">4.2.23</abbrev>VIDEO_SET_SPU<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl activates or deactivates SPU decoding in a DVD input stream. It can - only be used, if the driver is able to handle a DVD stream. - - -SYNOPSIS - - - int ioctl(fd, int request = VIDEO_SET_SPU , - video_spu_t ⋆spu) - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SET_SPU for this command. - - -video_spu_t *spu - -SPU decoding (de)activation and subid setting according - to section ??. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINVAL - -input is not a valid spu setting or driver cannot handle - SPU. - - - -
<abbrev role="title-mark">4.2.24</abbrev>VIDEO_SET_SPU_PALETTE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl sets the SPU color palette. - - -SYNOPSIS - - - int ioctl(fd, int request = VIDEO_SET_SPU_PALETTE - ,video_spu_palette_t ⋆palette ) - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SET_SPU_PALETTE for this command. - - -video_spu_palette_t - *palette - -SPU palette according to section ??. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINVAL - -input is not a valid palette or driver doesn’t handle SPU. - - - -
<abbrev role="title-mark">4.2.25</abbrev>VIDEO_GET_NAVI<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl returns navigational information from the DVD stream. This is - especially needed if an encoded stream has to be decoded by the hardware. - - -SYNOPSIS - - - int ioctl(fd, int request = VIDEO_GET_NAVI , - video_navi_pack_t ⋆navipack) - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_GET_NAVI for this command. - - -video_navi_pack_t - *navipack - -PCI or DSI pack (private stream 2) according to section - ??. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EFAULT - -driver is not able to return navigational information - - - -
<abbrev role="title-mark">4.2.26</abbrev>VIDEO_SET_ATTRIBUTES<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl is intended for DVD playback and allows you to set certain - information about the stream. Some hardware may not need this information, - but the call also tells the hardware to prepare for DVD playback. - - -SYNOPSIS - - - int ioctl(fd, int request = VIDEO_SET_ATTRIBUTE - ,video_attributes_t vattr) - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals VIDEO_SET_ATTRIBUTE for this command. - - -video_attributes_t - vattr - -video attributes according to section ??. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINVAL - -input is not a valid attribute setting. - - -
DVB Audio Device -The DVB audio device controls the MPEG2 audio decoder of the DVB hardware. It -can be accessed through /dev/dvb/adapter0/audio0. Data types and and -ioctl definitions can be accessed by including linux/dvb/video.h in your -application. - -Please note that some DVB cards don’t have their own MPEG decoder, which results in -the omission of the audio and video device. - -
<abbrev role="title-mark">5.1</abbrev>Audio Data Types -This section describes the structures, data types and defines used when talking to the -audio device. - - -
<abbrev role="title-mark">5.1.1</abbrev>audio_stream_source_t -The audio stream source is set through the AUDIO_SELECT_SOURCE call and can take -the following values, depending on whether we are replaying from an internal (demux) or -external (user write) source. - - - typedef enum { - AUDIO_SOURCE_DEMUX, - AUDIO_SOURCE_MEMORY - } audio_stream_source_t; - -AUDIO_SOURCE_DEMUX selects the demultiplexer (fed either by the frontend or the -DVR device) as the source of the video stream. If AUDIO_SOURCE_MEMORY -is selected the stream comes from the application through the write() system -call. - - -
<abbrev role="title-mark">5.1.2</abbrev>audio_play_state_t -The following values can be returned by the AUDIO_GET_STATUS call representing the -state of audio playback. - - - typedef enum { - AUDIO_STOPPED, - AUDIO_PLAYING, - AUDIO_PAUSED - } audio_play_state_t; - - -
<abbrev role="title-mark">5.1.3</abbrev>audio_channel_select_t -The audio channel selected via AUDIO_CHANNEL_SELECT is determined by the -following values. - - - typedef enum { - AUDIO_STEREO, - AUDIO_MONO_LEFT, - AUDIO_MONO_RIGHT, - } audio_channel_select_t; - - -
<abbrev role="title-mark">5.1.4</abbrev>struct audio_status -The AUDIO_GET_STATUS call returns the following structure informing about various -states of the playback operation. - - - typedef struct audio_status { - boolean AV_sync_state; - boolean mute_state; - audio_play_state_t play_state; - audio_stream_source_t stream_source; - audio_channel_select_t channel_select; - boolean bypass_mode; - } audio_status_t; - - -
<abbrev role="title-mark">5.1.5</abbrev>struct audio_mixer -The following structure is used by the AUDIO_SET_MIXER call to set the audio -volume. - - - typedef struct audio_mixer { - unsigned int volume_left; - unsigned int volume_right; - } audio_mixer_t; - - -
<abbrev role="title-mark">5.1.6</abbrev>audio encodings -A call to AUDIO_GET_CAPABILITIES returns an unsigned integer with the following -bits set according to the hardwares capabilities. - - - #define AUDIO_CAP_DTS 1 - #define AUDIO_CAP_LPCM 2 - #define AUDIO_CAP_MP1 4 - #define AUDIO_CAP_MP2 8 - #define AUDIO_CAP_MP3 16 - #define AUDIO_CAP_AAC 32 - #define AUDIO_CAP_OGG 64 - #define AUDIO_CAP_SDDS 128 - #define AUDIO_CAP_AC3 256 - - -
<abbrev role="title-mark">5.1.7</abbrev>struct audio_karaoke -The ioctl AUDIO_SET_KARAOKE uses the following format: - - - typedef - struct audio_karaoke{ - int vocal1; - int vocal2; - int melody; - } audio_karaoke_t; - -If Vocal1 or Vocal2 are non-zero, they get mixed into left and right t at 70% each. If both, -Vocal1 and Vocal2 are non-zero, Vocal1 gets mixed into the left channel and Vocal2 into the -right channel at 100% each. Ff Melody is non-zero, the melody channel gets mixed into left -and right. - - -
<abbrev role="title-mark">5.1.8</abbrev>audio attributes -The following attributes can be set by a call to AUDIO_SET_ATTRIBUTES: - - - typedef uint16_t audio_attributes_t; - /⋆ bits: descr. ⋆/ - /⋆ 15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, ⋆/ - /⋆ 12 multichannel extension ⋆/ - /⋆ 11-10 audio type (0=not spec, 1=language included) ⋆/ - /⋆ 9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) ⋆/ - /⋆ 7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit, ⋆/ - /⋆ 5- 4 Sample frequency fs (0=48kHz, 1=96kHz) ⋆/ - /⋆ 2- 0 number of audio channels (n+1 channels) ⋆/ - -
<abbrev role="title-mark">5.2</abbrev>Audio Function Calls - -
<abbrev role="title-mark">5.2.1</abbrev>open() -DESCRIPTION - -
-This system call opens a named audio device (e.g. /dev/dvb/adapter0/audio0) - for subsequent use. When an open() call has succeeded, the device will be ready - for use. The significance of blocking or non-blocking mode is described in the - documentation for functions where there is a difference. It does not affect the - semantics of the open() call itself. A device opened in blocking mode can later - be put into non-blocking mode (and vice versa) using the F_SETFL command - of the fcntl system call. This is a standard system call, documented in the Linux - manual page for fcntl. Only one user can open the Audio Device in O_RDWR - mode. All other attempts to open the device in this mode will fail, and an error - code will be returned. If the Audio Device is opened in O_RDONLY mode, the - only ioctl call that can be used is AUDIO_GET_STATUS. All other call will - return with an error code. - - -SYNOPSIS - - -int open(const char ⋆deviceName, int flags); - - -PARAMETERS - - -const char - *deviceName - -Name of specific audio device. - - -int flags - -A bit-wise OR of the following flags: - - - -O_RDONLY read-only access - - - -O_RDWR read/write access - - - -O_NONBLOCK open in non-blocking mode - - - -(blocking mode is the default) - - -ERRORS - - -ENODEV - -Device driver not loaded/available. - - -EINTERNAL - -Internal error. - - -EBUSY - -Device or resource busy. - - -EINVAL - -Invalid argument. - - - -
<abbrev role="title-mark">5.2.2</abbrev>close() -DESCRIPTION - -
-This system call closes a previously opened audio device. - - -SYNOPSIS - - -int close(int fd); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - - -
<abbrev role="title-mark">5.2.3</abbrev>write() -DESCRIPTION - -
-This system call can only be used if AUDIO_SOURCE_MEMORY is selected - in the ioctl call AUDIO_SELECT_SOURCE. The data provided shall be in - PES format. If O_NONBLOCK is not specified the function will block until - buffer space is available. The amount of data to be transferred is implied by - count. - - -SYNOPSIS - - -size_t write(int fd, const void ⋆buf, size_t count); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -void *buf - -Pointer to the buffer containing the PES data. - - -size_t count - -Size of buf. - - -ERRORS - - -EPERM - -Mode AUDIO_SOURCE_MEMORY not selected. - - -ENOMEM - -Attempted to write more data than the internal buffer can - hold. - - -EBADF - -fd is not a valid open file descriptor. - - - -
<abbrev role="title-mark">5.2.4</abbrev>AUDIO_STOP<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Audio Device to stop playing the current stream. - - -SYNOPSIS - - -int ioctl(int fd, int request = AUDIO_STOP); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_STOP for this command. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error. - - - -
<abbrev role="title-mark">5.2.5</abbrev>AUDIO_PLAY<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Audio Device to start playing an audio stream from the - selected source. - - -SYNOPSIS - - -int ioctl(int fd, int request = AUDIO_PLAY); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_PLAY for this command. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINTERNAL - -Internal error. - - - -
<abbrev role="title-mark">5.2.6</abbrev>AUDIO_PAUSE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call suspends the audio stream being played. Decoding and playing - are paused. It is then possible to restart again decoding and playing process of - the audio stream using AUDIO_CONTINUE command. - - -If AUDIO_SOURCE_MEMORY is selected in the ioctl call - AUDIO_SELECT_SOURCE, the DVB-subsystem will not decode (consume) - any more data until the ioctl call AUDIO_CONTINUE or AUDIO_PLAY is - performed. - - -SYNOPSIS - - -int ioctl(int fd, int request = AUDIO_PAUSE); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_PAUSE for this command. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - - -
<abbrev role="title-mark">5.2.7</abbrev>AUDIO_SELECT_SOURCE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call informs the audio device which source shall be used - for the input data. The possible sources are demux or memory. If - AUDIO_SOURCE_MEMORY is selected, the data is fed to the Audio Device - through the write command. - - -SYNOPSIS - - -int ioctl(int fd, int request = AUDIO_SELECT_SOURCE, - audio_stream_source_t source); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_SELECT_SOURCE for this command. - - -audio_stream_source_t - source - -Indicates the source that shall be used for the Audio - stream. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - -EINVAL - -Illegal input parameter. - - - -
<abbrev role="title-mark">5.2.8</abbrev>AUDIO_SET_MUTE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the audio device to mute the stream that is currently being - played. - - -SYNOPSIS - - -int ioctl(int fd, int request = AUDIO_SET_MUTE, - boolean state); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_SET_MUTE for this command. - - -boolean state - -Indicates if audio device shall mute or not. - - - -TRUE Audio Mute - - - -FALSE Audio Un-mute - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - -EINVAL - -Illegal input parameter. - - - -
<abbrev role="title-mark">5.2.9</abbrev>AUDIO_SET_AV_SYNC<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Audio Device to turn ON or OFF A/V synchronization. - - -SYNOPSIS - - -int ioctl(int fd, int request = AUDIO_SET_AV_SYNC, - boolean state); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_AV_SYNC for this command. - - -boolean state - -Tells the DVB subsystem if A/V synchronization shall be - ON or OFF. - - - -TRUE AV-sync ON - - - -FALSE AV-sync OFF - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - -EINVAL - -Illegal input parameter. - - - -
<abbrev role="title-mark">5.2.10</abbrev>AUDIO_SET_BYPASS_MODE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Audio Device to bypass the Audio decoder and forward - the stream without decoding. This mode shall be used if streams that can’t be - handled by the DVB system shall be decoded. Dolby DigitalTM streams are - automatically forwarded by the DVB subsystem if the hardware can handle it. - - -SYNOPSIS - - -int ioctl(int fd, int request = - AUDIO_SET_BYPASS_MODE, boolean mode); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_SET_BYPASS_MODE for this - command. - - -boolean mode - -Enables or disables the decoding of the current Audio - stream in the DVB subsystem. - - - -TRUE Bypass is disabled - - - -FALSE Bypass is enabled - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - -EINVAL - -Illegal input parameter. - - - -
<abbrev role="title-mark">5.2.11</abbrev>AUDIO_CHANNEL_SELECT<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Audio Device to select the requested channel if possible. - - -SYNOPSIS - - -int ioctl(int fd, int request = - AUDIO_CHANNEL_SELECT, audio_channel_select_t); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_CHANNEL_SELECT for this - command. - - -audio_channel_select_t - ch - -Select the output format of the audio (mono left/right, - stereo). - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - -EINVAL - -Illegal input parameter ch. - - - -
<abbrev role="title-mark">5.2.12</abbrev>AUDIO_GET_STATUS<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Audio Device to return the current state of the Audio - Device. - - -SYNOPSIS - - -int ioctl(int fd, int request = AUDIO_GET_STATUS, - struct audio_status ⋆status); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_GET_STATUS for this command. - - -struct audio_status - *status - -Returns the current state of Audio Device. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - -EFAULT - -status points to invalid address. - - - -
<abbrev role="title-mark">5.2.13</abbrev>AUDIO_GET_CAPABILITIES<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Audio Device to tell us about the decoding capabilities - of the audio hardware. - - -SYNOPSIS - - -int ioctl(int fd, int request = - AUDIO_GET_CAPABILITIES, unsigned int ⋆cap); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_GET_CAPABILITIES for this - command. - - -unsigned int *cap - -Returns a bit array of supported sound formats. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - -EFAULT - -cap points to an invalid address. - - - -
<abbrev role="title-mark">5.2.14</abbrev>AUDIO_CLEAR_BUFFER<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl call asks the Audio Device to clear all software and hardware buffers - of the audio decoder device. - - -SYNOPSIS - - -int ioctl(int fd, int request = AUDIO_CLEAR_BUFFER); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_CLEAR_BUFFER for this command. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - - -
<abbrev role="title-mark">5.2.15</abbrev>AUDIO_SET_ID<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl selects which sub-stream is to be decoded if a program or system - stream is sent to the video device. If no audio stream type is set the id has to be - in [0xC0,0xDF] for MPEG sound, in [0x80,0x87] for AC3 and in [0xA0,0xA7] - for LPCM. More specifications may follow for other stream types. If the stream - type is set the id just specifies the substream id of the audio stream and only - the first 5 bits are recognized. - - -SYNOPSIS - - -int ioctl(int fd, int request = AUDIO_SET_ID, int - id); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_SET_ID for this command. - - -int id - -audio sub-stream id - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - -EINVAL - -Invalid sub-stream id. - - - -
<abbrev role="title-mark">5.2.16</abbrev>AUDIO_SET_MIXER<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl lets you adjust the mixer settings of the audio decoder. - - -SYNOPSIS - - -int ioctl(int fd, int request = AUDIO_SET_MIXER, - audio_mixer_t ⋆mix); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_SET_ID for this command. - - -audio_mixer_t *mix - -mixer settings. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -EINTERNAL - -Internal error. - - -EFAULT - -mix points to an invalid address. - - - -
<abbrev role="title-mark">5.2.17</abbrev>AUDIO_SET_STREAMTYPE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl tells the driver which kind of audio stream to expect. This is useful - if the stream offers several audio sub-streams like LPCM and AC3. - - -SYNOPSIS - - -int ioctl(fd, int request = AUDIO_SET_STREAMTYPE, - int type); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_SET_STREAMTYPE for this - command. - - -int type - -stream type - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINVAL - -type is not a valid or supported stream type. - - - -
<abbrev role="title-mark">5.2.18</abbrev>AUDIO_SET_EXT_ID<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl can be used to set the extension id for MPEG streams in DVD - playback. Only the first 3 bits are recognized. - - -SYNOPSIS - - -int ioctl(fd, int request = AUDIO_SET_EXT_ID, int - id); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_SET_EXT_ID for this command. - - -int id - -audio sub_stream_id - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINVAL - -id is not a valid id. - - - -
<abbrev role="title-mark">5.2.19</abbrev>AUDIO_SET_ATTRIBUTES<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl is intended for DVD playback and allows you to set certain - information about the audio stream. - - -SYNOPSIS - - -int ioctl(fd, int request = AUDIO_SET_ATTRIBUTES, - audio_attributes_t attr ); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_SET_ATTRIBUTES for this command. - - -audio_attributes_t - attr - -audio attributes according to section ?? - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINVAL - -attr is not a valid or supported attribute setting. - - - -
<abbrev role="title-mark">5.2.20</abbrev>AUDIO_SET_KARAOKE<indexterm role="printindex" /> -DESCRIPTION - -
-This ioctl allows one to set the mixer settings for a karaoke DVD. - - -SYNOPSIS - - -int ioctl(fd, int request = AUDIO_SET_STREAMTYPE, - audio_karaoke_t ⋆karaoke); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -int request - -Equals AUDIO_SET_STREAMTYPE for this - command. - - -audio_karaoke_t - *karaoke - -karaoke settings according to section ??. - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor - - -EINVAL - -karaoke is not a valid or supported karaoke setting. - - -
DVB CA Device -The DVB CA device controls the conditional access hardware. It can be accessed through -/dev/dvb/adapter0/ca0. Data types and and ioctl definitions can be accessed by -including linux/dvb/ca.h in your application. - -
<abbrev role="title-mark">6.1</abbrev>CA Data Types - -
<abbrev role="title-mark">6.1.1</abbrev>ca_slot_info_t - - /⋆ slot interface types and info ⋆/ - - typedef struct ca_slot_info_s { - int num; /⋆ slot number ⋆/ - - int type; /⋆ CA interface this slot supports ⋆/ - #define CA_CI 1 /⋆ CI high level interface ⋆/ - #define CA_CI_LINK 2 /⋆ CI link layer level interface ⋆/ - #define CA_CI_PHYS 4 /⋆ CI physical layer level interface ⋆/ - #define CA_SC 128 /⋆ simple smart card interface ⋆/ - - unsigned int flags; - #define CA_CI_MODULE_PRESENT 1 /⋆ module (or card) inserted ⋆/ - #define CA_CI_MODULE_READY 2 - } ca_slot_info_t; - - -
<abbrev role="title-mark">6.1.2</abbrev>ca_descr_info_t - - typedef struct ca_descr_info_s { - unsigned int num; /⋆ number of available descramblers (keys) ⋆/ - unsigned int type; /⋆ type of supported scrambling system ⋆/ - #define CA_ECD 1 - #define CA_NDS 2 - #define CA_DSS 4 - } ca_descr_info_t; - - -
<abbrev role="title-mark">6.1.3</abbrev>ca_cap_t - - typedef struct ca_cap_s { - unsigned int slot_num; /⋆ total number of CA card and module slots ⋆/ - unsigned int slot_type; /⋆ OR of all supported types ⋆/ - unsigned int descr_num; /⋆ total number of descrambler slots (keys) ⋆/ - unsigned int descr_type;/⋆ OR of all supported types ⋆/ - } ca_cap_t; - - -
<abbrev role="title-mark">6.1.4</abbrev>ca_msg_t - - /⋆ a message to/from a CI-CAM ⋆/ - typedef struct ca_msg_s { - unsigned int index; - unsigned int type; - unsigned int length; - unsigned char msg[256]; - } ca_msg_t; - - -
<abbrev role="title-mark">6.1.5</abbrev>ca_descr_t - - typedef struct ca_descr_s { - unsigned int index; - unsigned int parity; - unsigned char cw[8]; - } ca_descr_t; - -
<abbrev role="title-mark">6.2</abbrev>CA Function Calls - -
<abbrev role="title-mark">6.2.1</abbrev>open() -DESCRIPTION - -
-This system call opens a named ca device (e.g. /dev/ost/ca) for subsequent use. -When an open() call has succeeded, the device will be ready for use. - The significance of blocking or non-blocking mode is described in the - documentation for functions where there is a difference. It does not affect the - semantics of the open() call itself. A device opened in blocking mode can later - be put into non-blocking mode (and vice versa) using the F_SETFL command - of the fcntl system call. This is a standard system call, documented in the Linux - manual page for fcntl. Only one user can open the CA Device in O_RDWR - mode. All other attempts to open the device in this mode will fail, and an error - code will be returned. - - - -SYNOPSIS - - -int open(const char ⋆deviceName, int flags); - - -PARAMETERS - - -const char - *deviceName - -Name of specific video device. - - -int flags - -A bit-wise OR of the following flags: - - - -O_RDONLY read-only access - - - -O_RDWR read/write access - - - -O_NONBLOCK open in non-blocking mode - - - -(blocking mode is the default) - - -ERRORS - - -ENODEV - -Device driver not loaded/available. - - -EINTERNAL - -Internal error. - - -EBUSY - -Device or resource busy. - - -EINVAL - -Invalid argument. - - - -
<abbrev role="title-mark">6.2.2</abbrev>close() -DESCRIPTION - -
-This system call closes a previously opened audio device. - - -SYNOPSIS - - -int close(int fd); - - -PARAMETERS - - -int fd - -File descriptor returned by a previous call to open(). - - -ERRORS - - -EBADF - -fd is not a valid open file descriptor. - - -
DVB Network API -The DVB net device enables feeding of MPE (multi protocol encapsulation) packets -received via DVB into the Linux network protocol stack, e.g. for internet via satellite -applications. It can be accessed through /dev/dvb/adapter0/net0. Data types and -and ioctl definitions can be accessed by including linux/dvb/net.h in your -application. - -
<abbrev role="title-mark">7.1</abbrev>DVB Net Data Types -To be written… - - -
Kernel Demux API -The kernel demux API defines a driver-internal interface for registering low-level, -hardware specific driver to a hardware independent demux layer. It is only of interest for -DVB device driver writers. The header file for this API is named demux.h and located in -drivers/media/dvb/dvb-core. - -Maintainer note: This section must be reviewed. It is probably out of date. - -
<abbrev role="title-mark">8.1</abbrev>Kernel Demux Data Types - -
<abbrev role="title-mark">8.1.1</abbrev>dmx_success_t - - typedef enum { - DMX_OK = 0, /⋆ Received Ok ⋆/ - DMX_LENGTH_ERROR, /⋆ Incorrect length ⋆/ - DMX_OVERRUN_ERROR, /⋆ Receiver ring buffer overrun ⋆/ - DMX_CRC_ERROR, /⋆ Incorrect CRC ⋆/ - DMX_FRAME_ERROR, /⋆ Frame alignment error ⋆/ - DMX_FIFO_ERROR, /⋆ Receiver FIFO overrun ⋆/ - DMX_MISSED_ERROR /⋆ Receiver missed packet ⋆/ - } dmx_success_t; - - -
<abbrev role="title-mark">8.1.2</abbrev>TS filter types - - /⋆--------------------------------------------------------------------------⋆/ - /⋆ TS packet reception ⋆/ - /⋆--------------------------------------------------------------------------⋆/ - - /⋆ TS filter type for set_type() ⋆/ - - #define TS_PACKET 1 /⋆ send TS packets (188 bytes) to callback (default) ⋆/ - #define TS_PAYLOAD_ONLY 2 /⋆ in case TS_PACKET is set, only send the TS - payload (<=184 bytes per packet) to callback ⋆/ - #define TS_DECODER 4 /⋆ send stream to built-in decoder (if present) ⋆/ - - -
<abbrev role="title-mark">8.1.3</abbrev>dmx_ts_pes_t -The structure - - - typedef enum - { - DMX_TS_PES_AUDIO, /⋆ also send packets to audio decoder (if it exists) ⋆/ - DMX_TS_PES_VIDEO, /⋆ ... ⋆/ - DMX_TS_PES_TELETEXT, - DMX_TS_PES_SUBTITLE, - DMX_TS_PES_PCR, - DMX_TS_PES_OTHER, - } dmx_ts_pes_t; - -describes the PES type for filters which write to a built-in decoder. The correspond (and -should be kept identical) to the types in the demux device. - - - struct dmx_ts_feed_s { - int is_filtering; /⋆ Set to non-zero when filtering in progress ⋆/ - struct dmx_demux_s⋆ parent; /⋆ Back-pointer ⋆/ - void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ - int (⋆set) (struct dmx_ts_feed_s⋆ feed, - __u16 pid, - size_t callback_length, - size_t circular_buffer_size, - int descramble, - struct timespec timeout); - int (⋆start_filtering) (struct dmx_ts_feed_s⋆ feed); - int (⋆stop_filtering) (struct dmx_ts_feed_s⋆ feed); - int (⋆set_type) (struct dmx_ts_feed_s⋆ feed, - int type, - dmx_ts_pes_t pes_type); - }; - - typedef struct dmx_ts_feed_s dmx_ts_feed_t; - - - /⋆--------------------------------------------------------------------------⋆/ - /⋆ PES packet reception (not supported yet) ⋆/ - /⋆--------------------------------------------------------------------------⋆/ - - typedef struct dmx_pes_filter_s { - struct dmx_pes_s⋆ parent; /⋆ Back-pointer ⋆/ - void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ - } dmx_pes_filter_t; - - - typedef struct dmx_pes_feed_s { - int is_filtering; /⋆ Set to non-zero when filtering in progress ⋆/ - struct dmx_demux_s⋆ parent; /⋆ Back-pointer ⋆/ - void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ - int (⋆set) (struct dmx_pes_feed_s⋆ feed, - __u16 pid, - size_t circular_buffer_size, - int descramble, - struct timespec timeout); - int (⋆start_filtering) (struct dmx_pes_feed_s⋆ feed); - int (⋆stop_filtering) (struct dmx_pes_feed_s⋆ feed); - int (⋆allocate_filter) (struct dmx_pes_feed_s⋆ feed, - dmx_pes_filter_t⋆⋆ filter); - int (⋆release_filter) (struct dmx_pes_feed_s⋆ feed, - dmx_pes_filter_t⋆ filter); - } dmx_pes_feed_t; - - - typedef struct { - __u8 filter_value [DMX_MAX_FILTER_SIZE]; - __u8 filter_mask [DMX_MAX_FILTER_SIZE]; - struct dmx_section_feed_s⋆ parent; /⋆ Back-pointer ⋆/ - void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ - } dmx_section_filter_t; - - - struct dmx_section_feed_s { - int is_filtering; /⋆ Set to non-zero when filtering in progress ⋆/ - struct dmx_demux_s⋆ parent; /⋆ Back-pointer ⋆/ - void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ - int (⋆set) (struct dmx_section_feed_s⋆ feed, - __u16 pid, - size_t circular_buffer_size, - int descramble, - int check_crc); - int (⋆allocate_filter) (struct dmx_section_feed_s⋆ feed, - dmx_section_filter_t⋆⋆ filter); - int (⋆release_filter) (struct dmx_section_feed_s⋆ feed, - dmx_section_filter_t⋆ filter); - int (⋆start_filtering) (struct dmx_section_feed_s⋆ feed); - int (⋆stop_filtering) (struct dmx_section_feed_s⋆ feed); - }; - typedef struct dmx_section_feed_s dmx_section_feed_t; - - /⋆--------------------------------------------------------------------------⋆/ - /⋆ Callback functions ⋆/ - /⋆--------------------------------------------------------------------------⋆/ - - typedef int (⋆dmx_ts_cb) ( __u8 ⋆ buffer1, - size_t buffer1_length, - __u8 ⋆ buffer2, - size_t buffer2_length, - dmx_ts_feed_t⋆ source, - dmx_success_t success); - - typedef int (⋆dmx_section_cb) ( __u8 ⋆ buffer1, - size_t buffer1_len, - __u8 ⋆ buffer2, - size_t buffer2_len, - dmx_section_filter_t ⋆ source, - dmx_success_t success); - - typedef int (⋆dmx_pes_cb) ( __u8 ⋆ buffer1, - size_t buffer1_len, - __u8 ⋆ buffer2, - size_t buffer2_len, - dmx_pes_filter_t⋆ source, - dmx_success_t success); - - /⋆--------------------------------------------------------------------------⋆/ - /⋆ DVB Front-End ⋆/ - /⋆--------------------------------------------------------------------------⋆/ - - typedef enum { - DMX_OTHER_FE = 0, - DMX_SATELLITE_FE, - DMX_CABLE_FE, - DMX_TERRESTRIAL_FE, - DMX_LVDS_FE, - DMX_ASI_FE, /⋆ DVB-ASI interface ⋆/ - DMX_MEMORY_FE - } dmx_frontend_source_t; - - typedef struct { - /⋆ The following char⋆ fields point to NULL terminated strings ⋆/ - char⋆ id; /⋆ Unique front-end identifier ⋆/ - char⋆ vendor; /⋆ Name of the front-end vendor ⋆/ - char⋆ model; /⋆ Name of the front-end model ⋆/ - struct list_head connectivity_list; /⋆ List of front-ends that can - be connected to a particular - demux ⋆/ - void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ - dmx_frontend_source_t source; - } dmx_frontend_t; - - /⋆--------------------------------------------------------------------------⋆/ - /⋆ MPEG-2 TS Demux ⋆/ - /⋆--------------------------------------------------------------------------⋆/ - - /⋆ - ⋆ Flags OR'ed in the capabilites field of struct dmx_demux_s. - ⋆/ - - #define DMX_TS_FILTERING 1 - #define DMX_PES_FILTERING 2 - #define DMX_SECTION_FILTERING 4 - #define DMX_MEMORY_BASED_FILTERING 8 /⋆ write() available ⋆/ - #define DMX_CRC_CHECKING 16 - #define DMX_TS_DESCRAMBLING 32 - #define DMX_SECTION_PAYLOAD_DESCRAMBLING 64 - #define DMX_MAC_ADDRESS_DESCRAMBLING 128 - - -
<abbrev role="title-mark">8.1.4</abbrev>demux_demux_t - - /⋆ - ⋆ DMX_FE_ENTRY(): Casts elements in the list of registered - ⋆ front-ends from the generic type struct list_head - ⋆ to the type ⋆ dmx_frontend_t - ⋆. - ⋆/ - - #define DMX_FE_ENTRY(list) list_entry(list, dmx_frontend_t, connectivity_list) - - struct dmx_demux_s { - /⋆ The following char⋆ fields point to NULL terminated strings ⋆/ - char⋆ id; /⋆ Unique demux identifier ⋆/ - char⋆ vendor; /⋆ Name of the demux vendor ⋆/ - char⋆ model; /⋆ Name of the demux model ⋆/ - __u32 capabilities; /⋆ Bitfield of capability flags ⋆/ - dmx_frontend_t⋆ frontend; /⋆ Front-end connected to the demux ⋆/ - struct list_head reg_list; /⋆ List of registered demuxes ⋆/ - void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ - int users; /⋆ Number of users ⋆/ - int (⋆open) (struct dmx_demux_s⋆ demux); - int (⋆close) (struct dmx_demux_s⋆ demux); - int (⋆write) (struct dmx_demux_s⋆ demux, const char⋆ buf, size_t count); - int (⋆allocate_ts_feed) (struct dmx_demux_s⋆ demux, - dmx_ts_feed_t⋆⋆ feed, - dmx_ts_cb callback); - int (⋆release_ts_feed) (struct dmx_demux_s⋆ demux, - dmx_ts_feed_t⋆ feed); - int (⋆allocate_pes_feed) (struct dmx_demux_s⋆ demux, - dmx_pes_feed_t⋆⋆ feed, - dmx_pes_cb callback); - int (⋆release_pes_feed) (struct dmx_demux_s⋆ demux, - dmx_pes_feed_t⋆ feed); - int (⋆allocate_section_feed) (struct dmx_demux_s⋆ demux, - dmx_section_feed_t⋆⋆ feed, - dmx_section_cb callback); - int (⋆release_section_feed) (struct dmx_demux_s⋆ demux, - dmx_section_feed_t⋆ feed); - int (⋆descramble_mac_address) (struct dmx_demux_s⋆ demux, - __u8⋆ buffer1, - size_t buffer1_length, - __u8⋆ buffer2, - size_t buffer2_length, - __u16 pid); - int (⋆descramble_section_payload) (struct dmx_demux_s⋆ demux, - __u8⋆ buffer1, - size_t buffer1_length, - __u8⋆ buffer2, size_t buffer2_length, - __u16 pid); - int (⋆add_frontend) (struct dmx_demux_s⋆ demux, - dmx_frontend_t⋆ frontend); - int (⋆remove_frontend) (struct dmx_demux_s⋆ demux, - dmx_frontend_t⋆ frontend); - struct list_head⋆ (⋆get_frontends) (struct dmx_demux_s⋆ demux); - int (⋆connect_frontend) (struct dmx_demux_s⋆ demux, - dmx_frontend_t⋆ frontend); - int (⋆disconnect_frontend) (struct dmx_demux_s⋆ demux); - - - /⋆ added because js cannot keep track of these himself ⋆/ - int (⋆get_pes_pids) (struct dmx_demux_s⋆ demux, __u16 ⋆pids); - }; - typedef struct dmx_demux_s dmx_demux_t; - - -
<abbrev role="title-mark">8.1.5</abbrev>Demux directory - - /⋆ - ⋆ DMX_DIR_ENTRY(): Casts elements in the list of registered - ⋆ demuxes from the generic type struct list_head⋆ to the type dmx_demux_t - ⋆. - ⋆/ - - #define DMX_DIR_ENTRY(list) list_entry(list, dmx_demux_t, reg_list) - - int dmx_register_demux (dmx_demux_t⋆ demux); - int dmx_unregister_demux (dmx_demux_t⋆ demux); - struct list_head⋆ dmx_get_demuxes (void); - -
<abbrev role="title-mark">8.2</abbrev>Demux Directory API -The demux directory is a Linux kernel-wide facility for registering and accessing the -MPEG-2 TS demuxes in the system. Run-time registering and unregistering of demux drivers -is possible using this API. - -All demux drivers in the directory implement the abstract interface dmx_demux_t. - - -
<abbrev role="title-mark">8.2.1</abbrev>dmx_register_demux()<indexterm role="printindex" /> -DESCRIPTION - -
-This function makes a demux driver interface available to the Linux kernel. It is - usually called by the init_module() function of the kernel module that contains - the demux driver. The caller of this function is responsible for allocating - dynamic or static memory for the demux structure and for initializing its fields - before calling this function. The memory allocated for the demux structure - must not be freed before calling dmx_unregister_demux(), - - -SYNOPSIS - - -int dmx_register_demux ( dmx_demux_t ⋆demux ) - - -PARAMETERS - - -dmx_demux_t* - demux - -Pointer to the demux structure. - - -RETURNS - - -0 - -The function was completed without errors. - - --EEXIST - -A demux with the same value of the id field already stored - in the directory. - - --ENOSPC - -No space left in the directory. - - - -
<abbrev role="title-mark">8.2.2</abbrev>dmx_unregister_demux()<indexterm role="printindex" /> -DESCRIPTION - -
-This function is called to indicate that the given demux interface is no - longer available. The caller of this function is responsible for freeing the - memory of the demux structure, if it was dynamically allocated before calling - dmx_register_demux(). The cleanup_module() function of the kernel module - that contains the demux driver should call this function. Note that this function - fails if the demux is currently in use, i.e., release_demux() has not been called - for the interface. - - -SYNOPSIS - - -int dmx_unregister_demux ( dmx_demux_t ⋆demux ) - - -PARAMETERS - - -dmx_demux_t* - demux - -Pointer to the demux structure which is to be - unregistered. - - -RETURNS - - -0 - -The function was completed without errors. - - -ENODEV - -The specified demux is not registered in the demux - directory. - - -EBUSY - -The specified demux is currently in use. - - - -
<abbrev role="title-mark">8.2.3</abbrev>dmx_get_demuxes()<indexterm role="printindex" /> -DESCRIPTION - -
-Provides the caller with the list of registered demux interfaces, using the - standard list structure defined in the include file linux/list.h. The include file - demux.h defines the macro DMX_DIR_ENTRY() for converting an element of - the generic type struct list_head* to the type dmx_demux_t*. The caller must - not free the memory of any of the elements obtained via this function call. - - -SYNOPSIS - - -struct list_head ⋆dmx_get_demuxes () - - -PARAMETERS - - -none - - -RETURNS - - -struct list_head * - -A list of demux interfaces, or NULL in the case of an - empty list. - - -
<abbrev role="title-mark">8.3</abbrev>Demux API -The demux API should be implemented for each demux in the system. It is used to select -the TS source of a demux and to manage the demux resources. When the demux -client allocates a resource via the demux API, it receives a pointer to the API of that -resource. - -Each demux receives its TS input from a DVB front-end or from memory, as set via the -demux API. In a system with more than one front-end, the API can be used to select one of -the DVB front-ends as a TS source for a demux, unless this is fixed in the HW platform. The -demux API only controls front-ends regarding their connections with demuxes; the APIs -used to set the other front-end parameters, such as tuning, are not defined in this -document. - -The functions that implement the abstract interface demux should be defined static or -module private and registered to the Demux Directory for external access. It is not necessary -to implement every function in the demux_t struct, however (for example, a demux interface -might support Section filtering, but not TS or PES filtering). The API client is expected to -check the value of any function pointer before calling the function: the value of NULL means -“function not available”. - -Whenever the functions of the demux API modify shared data, the possibilities of lost -update and race condition problems should be addressed, e.g. by protecting parts of code with -mutexes. This is especially important on multi-processor hosts. - -Note that functions called from a bottom half context must not sleep, at least in the 2.2.x -kernels. Even a simple memory allocation can result in a kernel thread being put to sleep if -swapping is needed. For example, the Linux kernel calls the functions of a network device -interface from a bottom half context. Thus, if a demux API function is called from network -device code, the function must not sleep. - - -
<abbrev role="title-mark">8.3.1</abbrev>open() -DESCRIPTION - -
-This function reserves the demux for use by the caller and, if necessary, - initializes the demux. When the demux is no longer needed, the function close() - should be called. It should be possible for multiple clients to access the demux - at the same time. Thus, the function implementation should increment the - demux usage count when open() is called and decrement it when close() is - called. - - -SYNOPSIS - - -int open ( demux_t⋆ demux ); - - -PARAMETERS - - -demux_t* demux - -Pointer to the demux API and instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --EUSERS - -Maximum usage count reached. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.3.2</abbrev>close() -DESCRIPTION - -
-This function reserves the demux for use by the caller and, if necessary, - initializes the demux. When the demux is no longer needed, the function close() - should be called. It should be possible for multiple clients to access the demux - at the same time. Thus, the function implementation should increment the - demux usage count when open() is called and decrement it when close() is - called. - - -SYNOPSIS - - -int close(demux_t⋆ demux); - - -PARAMETERS - - -demux_t* demux - -Pointer to the demux API and instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --ENODEV - -The demux was not in use. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.3.3</abbrev>write() -DESCRIPTION - -
-This function provides the demux driver with a memory buffer containing TS - packets. Instead of receiving TS packets from the DVB front-end, the demux - driver software will read packets from memory. Any clients of this demux - with active TS, PES or Section filters will receive filtered data via the Demux - callback API (see 0). The function returns when all the data in the buffer has - been consumed by the demux. Demux hardware typically cannot read TS from - memory. If this is the case, memory-based filtering has to be implemented - entirely in software. - - -SYNOPSIS - - -int write(demux_t⋆ demux, const char⋆ buf, size_t - count); - - -PARAMETERS - - -demux_t* demux - -Pointer to the demux API and instance data. - - -const char* buf - -Pointer to the TS data in kernel-space memory. - - -size_t length - -Length of the TS data. - - -RETURNS - - -0 - -The function was completed without errors. - - --ENOSYS - -The command is not implemented. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.3.4</abbrev>allocate_ts_feed()<indexterm role="printindex" /> -DESCRIPTION - -
-Allocates a new TS feed, which is used to filter the TS packets carrying a - certain PID. The TS feed normally corresponds to a hardware PID filter on the - demux chip. - - -SYNOPSIS - - -int allocate_ts_feed(dmx_demux_t⋆ demux, - dmx_ts_feed_t⋆⋆ feed, dmx_ts_cb callback); - - -PARAMETERS - - -demux_t* demux - -Pointer to the demux API and instance data. - - -dmx_ts_feed_t** - feed - -Pointer to the TS feed API and instance data. - - -dmx_ts_cb callback - -Pointer to the callback function for passing received TS - packet - - -RETURNS - - -0 - -The function was completed without errors. - - --EBUSY - -No more TS feeds available. - - --ENOSYS - -The command is not implemented. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.3.5</abbrev>release_ts_feed()<indexterm role="printindex" /> -DESCRIPTION - -
-Releases the resources allocated with allocate_ts_feed(). Any filtering in - progress on the TS feed should be stopped before calling this function. - - -SYNOPSIS - - -int release_ts_feed(dmx_demux_t⋆ demux, - dmx_ts_feed_t⋆ feed); - - -PARAMETERS - - -demux_t* demux - -Pointer to the demux API and instance data. - - -dmx_ts_feed_t* feed - -Pointer to the TS feed API and instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.3.6</abbrev>allocate_section_feed()<indexterm role="printindex" /> -DESCRIPTION - -
-Allocates a new section feed, i.e. a demux resource for filtering and receiving - sections. On platforms with hardware support for section filtering, a section - feed is directly mapped to the demux HW. On other platforms, TS packets are - first PID filtered in hardware and a hardware section filter then emulated in - software. The caller obtains an API pointer of type dmx_section_feed_t as an - out parameter. Using this API the caller can set filtering parameters and start - receiving sections. - - -SYNOPSIS - - -int allocate_section_feed(dmx_demux_t⋆ demux, - dmx_section_feed_t ⋆⋆feed, dmx_section_cb callback); - - -PARAMETERS - - -demux_t *demux - -Pointer to the demux API and instance data. - - -dmx_section_feed_t - **feed - -Pointer to the section feed API and instance data. - - -dmx_section_cb - callback - -Pointer to the callback function for passing received - sections. - - -RETURNS - - -0 - -The function was completed without errors. - - --EBUSY - -No more section feeds available. - - --ENOSYS - -The command is not implemented. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.3.7</abbrev>release_section_feed()<indexterm role="printindex" /> -DESCRIPTION - -
-Releases the resources allocated with allocate_section_feed(), including - allocated filters. Any filtering in progress on the section feed should be stopped - before calling this function. - - -SYNOPSIS - - -int release_section_feed(dmx_demux_t⋆ demux, - dmx_section_feed_t ⋆feed); - - -PARAMETERS - - -demux_t *demux - -Pointer to the demux API and instance data. - - -dmx_section_feed_t - *feed - -Pointer to the section feed API and instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.3.8</abbrev>descramble_mac_address()<indexterm role="printindex" /> -DESCRIPTION - -
-This function runs a descrambling algorithm on the destination MAC - address field of a DVB Datagram Section, replacing the original address - with its un-encrypted version. Otherwise, the description on the function - descramble_section_payload() applies also to this function. - - -SYNOPSIS - - -int descramble_mac_address(dmx_demux_t⋆ demux, __u8 - ⋆buffer1, size_t buffer1_length, __u8 ⋆buffer2, - size_t buffer2_length, __u16 pid); - - -PARAMETERS - - -dmx_demux_t - *demux - -Pointer to the demux API and instance data. - - -__u8 *buffer1 - -Pointer to the first byte of the section. - - -size_t buffer1_length - -Length of the section data, including headers and CRC, - in buffer1. - - -__u8* buffer2 - -Pointer to the tail of the section data, or NULL. The - pointer has a non-NULL value if the section wraps past - the end of a circular buffer. - - -size_t buffer2_length - -Length of the section data, including headers and CRC, - in buffer2. - - -__u16 pid - -The PID on which the section was received. Useful - for obtaining the descrambling key, e.g. from a DVB - Common Access facility. - - -RETURNS - - -0 - -The function was completed without errors. - - --ENOSYS - -No descrambling facility available. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.3.9</abbrev>descramble_section_payload()<indexterm role="printindex" /> -DESCRIPTION - -
-This function runs a descrambling algorithm on the payload of a DVB - Datagram Section, replacing the original payload with its un-encrypted - version. The function will be called from the demux API implementation; - the API client need not call this function directly. Section-level scrambling - algorithms are currently standardized only for DVB-RCC (return channel - over 2-directional cable TV network) systems. For all other DVB networks, - encryption schemes are likely to be proprietary to each data broadcaster. Thus, - it is expected that this function pointer will have the value of NULL (i.e., - function not available) in most demux API implementations. Nevertheless, it - should be possible to use the function pointer as a hook for dynamically adding - a “plug-in” descrambling facility to a demux driver. - - -While this function is not needed with hardware-based section descrambling, - the descramble_section_payload function pointer can be used to override the - default hardware-based descrambling algorithm: if the function pointer has a - non-NULL value, the corresponding function should be used instead of any - descrambling hardware. - - -SYNOPSIS - - -int descramble_section_payload(dmx_demux_t⋆ demux, - __u8 ⋆buffer1, size_t buffer1_length, __u8 ⋆buffer2, - size_t buffer2_length, __u16 pid); - - -PARAMETERS - - -dmx_demux_t - *demux - -Pointer to the demux API and instance data. - - -__u8 *buffer1 - -Pointer to the first byte of the section. - - -size_t buffer1_length - -Length of the section data, including headers and CRC, - in buffer1. - - -__u8 *buffer2 - -Pointer to the tail of the section data, or NULL. The - pointer has a non-NULL value if the section wraps past - the end of a circular buffer. - - -size_t buffer2_length - -Length of the section data, including headers and CRC, - in buffer2. - - -__u16 pid - -The PID on which the section was received. Useful - for obtaining the descrambling key, e.g. from a DVB - Common Access facility. - - -RETURNS - - -0 - -The function was completed without errors. - - --ENOSYS - -No descrambling facility available. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.3.10</abbrev>add_frontend()<indexterm role="printindex" /> -DESCRIPTION - -
-Registers a connectivity between a demux and a front-end, i.e., indicates that - the demux can be connected via a call to connect_frontend() to use the given - front-end as a TS source. The client of this function has to allocate dynamic or - static memory for the frontend structure and initialize its fields before calling - this function. This function is normally called during the driver initialization. - The caller must not free the memory of the frontend struct before successfully - calling remove_frontend(). - - -SYNOPSIS - - -int add_frontend(dmx_demux_t ⋆demux, dmx_frontend_t - ⋆frontend); - - -PARAMETERS - - -dmx_demux_t* - demux - -Pointer to the demux API and instance data. - - -dmx_frontend_t* - frontend - -Pointer to the front-end instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --EEXIST - -A front-end with the same value of the id field already - registered. - - --EINUSE - -The demux is in use. - - --ENOMEM - -No more front-ends can be added. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.3.11</abbrev>remove_frontend()<indexterm role="printindex" /> -DESCRIPTION - -
-Indicates that the given front-end, registered by a call to add_frontend(), can - no longer be connected as a TS source by this demux. The function should be - called when a front-end driver or a demux driver is removed from the system. - If the front-end is in use, the function fails with the return value of -EBUSY. - After successfully calling this function, the caller can free the memory of - the frontend struct if it was dynamically allocated before the add_frontend() - operation. - - -SYNOPSIS - - -int remove_frontend(dmx_demux_t⋆ demux, - dmx_frontend_t⋆ frontend); - - -PARAMETERS - - -dmx_demux_t* - demux - -Pointer to the demux API and instance data. - - -dmx_frontend_t* - frontend - -Pointer to the front-end instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --EINVAL - -Bad parameter. - - --EBUSY - -The front-end is in use, i.e. a call to connect_frontend() - has not been followed by a call to disconnect_frontend(). - - - -
<abbrev role="title-mark">8.3.12</abbrev>get_frontends()<indexterm role="printindex" /> -DESCRIPTION - -
-Provides the APIs of the front-ends that have been registered for this demux. - Any of the front-ends obtained with this call can be used as a parameter for - connect_frontend(). - - -The include file demux.h contains the macro DMX_FE_ENTRY() for - converting an element of the generic type struct list_head* to the type - dmx_frontend_t*. The caller must not free the memory of any of the elements - obtained via this function call. - - -SYNOPSIS - - -struct list_head⋆ get_frontends(dmx_demux_t⋆ demux); - - -PARAMETERS - - -dmx_demux_t* - demux - -Pointer to the demux API and instance data. - - -RETURNS - - -dmx_demux_t* - -A list of front-end interfaces, or NULL in the case of an - empty list. - - - -
<abbrev role="title-mark">8.3.13</abbrev>connect_frontend()<indexterm role="printindex" /> -DESCRIPTION - -
-Connects the TS output of the front-end to the input of the demux. A demux - can only be connected to a front-end registered to the demux with the function - add_frontend(). - - -It may or may not be possible to connect multiple demuxes to the same - front-end, depending on the capabilities of the HW platform. When not used, - the front-end should be released by calling disconnect_frontend(). - - -SYNOPSIS - - -int connect_frontend(dmx_demux_t⋆ demux, - dmx_frontend_t⋆ frontend); - - -PARAMETERS - - -dmx_demux_t* - demux - -Pointer to the demux API and instance data. - - -dmx_frontend_t* - frontend - -Pointer to the front-end instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --EINVAL - -Bad parameter. - - --EBUSY - -The front-end is in use. - - - -
<abbrev role="title-mark">8.3.14</abbrev>disconnect_frontend()<indexterm role="printindex" /> -DESCRIPTION - -
-Disconnects the demux and a front-end previously connected by a - connect_frontend() call. - - -SYNOPSIS - - -int disconnect_frontend(dmx_demux_t⋆ demux); - - -PARAMETERS - - -dmx_demux_t* - demux - -Pointer to the demux API and instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --EINVAL - -Bad parameter. - - -
<abbrev role="title-mark">8.4</abbrev>Demux Callback API -This kernel-space API comprises the callback functions that deliver filtered data to the -demux client. Unlike the other APIs, these API functions are provided by the client and called -from the demux code. - -The function pointers of this abstract interface are not packed into a structure as in the -other demux APIs, because the callback functions are registered and used independent -of each other. As an example, it is possible for the API client to provide several -callback functions for receiving TS packets and no callbacks for PES packets or -sections. - -The functions that implement the callback API need not be re-entrant: when a demux -driver calls one of these functions, the driver is not allowed to call the function again before -the original call returns. If a callback is triggered by a hardware interrupt, it is recommended -to use the Linux “bottom half” mechanism or start a tasklet instead of making the callback -function call directly from a hardware interrupt. - - -
<abbrev role="title-mark">8.4.1</abbrev>dmx_ts_cb()<indexterm role="printindex" /> -DESCRIPTION - -
-This function, provided by the client of the demux API, is called from the - demux code. The function is only called when filtering on this TS feed has - been enabled using the start_filtering() function. - - -Any TS packets that match the filter settings are copied to a circular buffer. The - filtered TS packets are delivered to the client using this callback function. The - size of the circular buffer is controlled by the circular_buffer_size parameter - of the set() function in the TS Feed API. It is expected that the buffer1 and - buffer2 callback parameters point to addresses within the circular buffer, but - other implementations are also possible. Note that the called party should not - try to free the memory the buffer1 and buffer2 parameters point to. - - -When this function is called, the buffer1 parameter typically points to the - start of the first undelivered TS packet within a circular buffer. The buffer2 - buffer parameter is normally NULL, except when the received TS packets have - crossed the last address of the circular buffer and ”wrapped” to the beginning - of the buffer. In the latter case the buffer1 parameter would contain an address - within the circular buffer, while the buffer2 parameter would contain the first - address of the circular buffer. - - -The number of bytes delivered with this function (i.e. buffer1_length + - buffer2_length) is usually equal to the value of callback_length parameter - given in the set() function, with one exception: if a timeout occurs before - receiving callback_length bytes of TS data, any undelivered packets are - immediately delivered to the client by calling this function. The timeout - duration is controlled by the set() function in the TS Feed API. - - -If a TS packet is received with errors that could not be fixed by the TS-level - forward error correction (FEC), the Transport_error_indicator flag of the TS - packet header should be set. The TS packet should not be discarded, as - the error can possibly be corrected by a higher layer protocol. If the called - party is slow in processing the callback, it is possible that the circular buffer - eventually fills up. If this happens, the demux driver should discard any TS - packets received while the buffer is full. The error should be indicated to the - client on the next callback by setting the success parameter to the value of - DMX_OVERRUN_ERROR. - - -The type of data returned to the callback can be selected by the new - function int (*set_type) (struct dmx_ts_feed_s* feed, int type, dmx_ts_pes_t - pes_type) which is part of the dmx_ts_feed_s struct (also cf. to the - include file ost/demux.h) The type parameter decides if the raw TS packet - (TS_PACKET) or just the payload (TS_PACKET—TS_PAYLOAD_ONLY) - should be returned. If additionally the TS_DECODER bit is set the stream - will also be sent to the hardware MPEG decoder. In this case, the second - flag decides as what kind of data the stream should be interpreted. The - possible choices are one of DMX_TS_PES_AUDIO, DMX_TS_PES_VIDEO, - DMX_TS_PES_TELETEXT, DMX_TS_PES_SUBTITLE, - DMX_TS_PES_PCR, or DMX_TS_PES_OTHER. - - -SYNOPSIS - - -int dmx_ts_cb(__u8⋆ buffer1, size_t buffer1_length, - __u8⋆ buffer2, size_t buffer2_length, dmx_ts_feed_t⋆ - source, dmx_success_t success); - - -PARAMETERS - - -__u8* buffer1 - -Pointer to the start of the filtered TS packets. - - -size_t buffer1_length - -Length of the TS data in buffer1. - - -__u8* buffer2 - -Pointer to the tail of the filtered TS packets, or NULL. - - -size_t buffer2_length - -Length of the TS data in buffer2. - - -dmx_ts_feed_t* - source - -Indicates which TS feed is the source of the callback. - - -dmx_success_t - success - -Indicates if there was an error in TS reception. - - -RETURNS - - -0 - -Continue filtering. - - --1 - -Stop filtering - has the same effect as a call to - stop_filtering() on the TS Feed API. - - - -
<abbrev role="title-mark">8.4.2</abbrev>dmx_section_cb()<indexterm role="printindex" /> -DESCRIPTION - -
-This function, provided by the client of the demux API, is called from the - demux code. The function is only called when filtering of sections has been - enabled using the function start_filtering() of the section feed API. When the - demux driver has received a complete section that matches at least one section - filter, the client is notified via this callback function. Normally this function is - called for each received section; however, it is also possible to deliver multiple - sections with one callback, for example when the system load is high. If an - error occurs while receiving a section, this function should be called with - the corresponding error type set in the success field, whether or not there is - data to deliver. The Section Feed implementation should maintain a circular - buffer for received sections. However, this is not necessary if the Section Feed - API is implemented as a client of the TS Feed API, because the TS Feed - implementation then buffers the received data. The size of the circular buffer - can be configured using the set() function in the Section Feed API. If there - is no room in the circular buffer when a new section is received, the section - must be discarded. If this happens, the value of the success parameter should - be DMX_OVERRUN_ERROR on the next callback. - - -SYNOPSIS - - -int dmx_section_cb(__u8⋆ buffer1, size_t - buffer1_length, __u8⋆ buffer2, size_t - buffer2_length, dmx_section_filter_t⋆ source, - dmx_success_t success); - - -PARAMETERS - - -__u8* buffer1 - -Pointer to the start of the filtered section, e.g. within the - circular buffer of the demux driver. - - -size_t buffer1_length - -Length of the filtered section data in buffer1, including - headers and CRC. - - -__u8* buffer2 - -Pointer to the tail of the filtered section data, or NULL. - Useful to handle the wrapping of a circular buffer. - - -size_t buffer2_length - -Length of the filtered section data in buffer2, including - headers and CRC. - - -dmx_section_filter_t* - filter - -Indicates the filter that triggered the callback. - - -dmx_success_t - success - -Indicates if there was an error in section reception. - - -RETURNS - - -0 - -Continue filtering. - - --1 - -Stop filtering - has the same effect as a call to - stop_filtering() on the Section Feed API. - - -
<abbrev role="title-mark">8.5</abbrev>TS Feed API -A TS feed is typically mapped to a hardware PID filter on the demux chip. -Using this API, the client can set the filtering properties to start/stop filtering TS -packets on a particular TS feed. The API is defined as an abstract interface of the type -dmx_ts_feed_t. - -The functions that implement the interface should be defined static or module private. The -client can get the handle of a TS feed API by calling the function allocate_ts_feed() in the -demux API. - - -
<abbrev role="title-mark">8.5.1</abbrev>set()<indexterm role="printindex" /> -DESCRIPTION - -
-This function sets the parameters of a TS feed. Any filtering in progress on the - TS feed must be stopped before calling this function. - - -SYNOPSIS - - -int set ( dmx_ts_feed_t⋆ feed, __u16 pid, size_t - callback_length, size_t circular_buffer_size, int - descramble, struct timespec timeout); - - -PARAMETERS - - -dmx_ts_feed_t* feed - -Pointer to the TS feed API and instance data. - - -__u16 pid - -PID value to filter. Only the TS packets carrying the - specified PID will be passed to the API client. - - -size_t - callback_length - -Number of bytes to deliver with each call to the - dmx_ts_cb() callback function. The value of this - parameter should be a multiple of 188. - - -size_t - circular_buffer_size - -Size of the circular buffer for the filtered TS packets. - - -int descramble - -If non-zero, descramble the filtered TS packets. - - -struct timespec - timeout - -Maximum time to wait before delivering received TS - packets to the client. - - -RETURNS - - -0 - -The function was completed without errors. - - --ENOMEM - -Not enough memory for the requested buffer size. - - --ENOSYS - -No descrambling facility available for TS. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.5.2</abbrev>start_filtering()<indexterm role="printindex" /> -DESCRIPTION - -
-Starts filtering TS packets on this TS feed, according to its settings. The PID - value to filter can be set by the API client. All matching TS packets are - delivered asynchronously to the client, using the callback function registered - with allocate_ts_feed(). - - -SYNOPSIS - - -int start_filtering(dmx_ts_feed_t⋆ feed); - - -PARAMETERS - - -dmx_ts_feed_t* feed - -Pointer to the TS feed API and instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.5.3</abbrev>stop_filtering()<indexterm role="printindex" /> -DESCRIPTION - -
-Stops filtering TS packets on this TS feed. - - -SYNOPSIS - - -int stop_filtering(dmx_ts_feed_t⋆ feed); - - -PARAMETERS - - -dmx_ts_feed_t* feed - -Pointer to the TS feed API and instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --EINVAL - -Bad parameter. - - -
<abbrev role="title-mark">8.6</abbrev>Section Feed API -A section feed is a resource consisting of a PID filter and a set of section filters. Using this -API, the client can set the properties of a section feed and to start/stop filtering. The API is -defined as an abstract interface of the type dmx_section_feed_t. The functions that implement -the interface should be defined static or module private. The client can get the handle of -a section feed API by calling the function allocate_section_feed() in the demux -API. - -On demux platforms that provide section filtering in hardware, the Section Feed API -implementation provides a software wrapper for the demux hardware. Other platforms may -support only PID filtering in hardware, requiring that TS packets are converted to sections in -software. In the latter case the Section Feed API implementation can be a client of the TS -Feed API. - - -
<abbrev role="title-mark">8.6.1</abbrev>set()<indexterm role="printindex" /> -DESCRIPTION - -
-This function sets the parameters of a section feed. Any filtering in progress on - the section feed must be stopped before calling this function. If descrambling - is enabled, the payload_scrambling_control and address_scrambling_control - fields of received DVB datagram sections should be observed. If either one is - non-zero, the section should be descrambled either in hardware or using the - functions descramble_mac_address() and descramble_section_payload() of the - demux API. Note that according to the MPEG-2 Systems specification, only - the payloads of private sections can be scrambled while the rest of the section - data must be sent in the clear. - - -SYNOPSIS - - -int set(dmx_section_feed_t⋆ feed, __u16 pid, size_t - circular_buffer_size, int descramble, int - check_crc); - - -PARAMETERS - - -dmx_section_feed_t* - feed - -Pointer to the section feed API and instance data. - - -__u16 pid - -PID value to filter; only the TS packets carrying the - specified PID will be accepted. - - -size_t - circular_buffer_size - -Size of the circular buffer for filtered sections. - - -int descramble - -If non-zero, descramble any sections that are scrambled. - - -int check_crc - -If non-zero, check the CRC values of filtered sections. - - -RETURNS - - -0 - -The function was completed without errors. - - --ENOMEM - -Not enough memory for the requested buffer size. - - --ENOSYS - -No descrambling facility available for sections. - - --EINVAL - -Bad parameters. - - - -
<abbrev role="title-mark">8.6.2</abbrev>allocate_filter()<indexterm role="printindex" /> -DESCRIPTION - -
-This function is used to allocate a section filter on the demux. It should only be - called when no filtering is in progress on this section feed. If a filter cannot be - allocated, the function fails with -ENOSPC. See in section ?? for the format of - the section filter. - - -The bitfields filter_mask and filter_value should only be modified when no - filtering is in progress on this section feed. filter_mask controls which bits of - filter_value are compared with the section headers/payload. On a binary value - of 1 in filter_mask, the corresponding bits are compared. The filter only accepts - sections that are equal to filter_value in all the tested bit positions. Any changes - to the values of filter_mask and filter_value are guaranteed to take effect only - when the start_filtering() function is called next time. The parent pointer in - the struct is initialized by the API implementation to the value of the feed - parameter. The priv pointer is not used by the API implementation, and can - thus be freely utilized by the caller of this function. Any data pointed to by the - priv pointer is available to the recipient of the dmx_section_cb() function call. - - -While the maximum section filter length (DMX_MAX_FILTER_SIZE) is - currently set at 16 bytes, hardware filters of that size are not available on all - platforms. Therefore, section filtering will often take place first in hardware, - followed by filtering in software for the header bytes that were not covered - by a hardware filter. The filter_mask field can be checked to determine how - many bytes of the section filter are actually used, and if the hardware filter will - suffice. Additionally, software-only section filters can optionally be allocated - to clients when all hardware section filters are in use. Note that on most demux - hardware it is not possible to filter on the section_length field of the section - header – thus this field is ignored, even though it is included in filter_value and - filter_mask fields. - - -SYNOPSIS - - -int allocate_filter(dmx_section_feed_t⋆ feed, - dmx_section_filter_t⋆⋆ filter); - - -PARAMETERS - - -dmx_section_feed_t* - feed - -Pointer to the section feed API and instance data. - - -dmx_section_filter_t** - filter - -Pointer to the allocated filter. - - -RETURNS - - -0 - -The function was completed without errors. - - --ENOSPC - -No filters of given type and length available. - - --EINVAL - -Bad parameters. - - - -
<abbrev role="title-mark">8.6.3</abbrev>release_filter()<indexterm role="printindex" /> -DESCRIPTION - -
-This function releases all the resources of a previously allocated section filter. - The function should not be called while filtering is in progress on this section - feed. After calling this function, the caller should not try to dereference the - filter pointer. - - -SYNOPSIS - - -int release_filter ( dmx_section_feed_t⋆ feed, - dmx_section_filter_t⋆ filter); - - -PARAMETERS - - -dmx_section_feed_t* - feed - -Pointer to the section feed API and instance data. - - -dmx_section_filter_t* - filter - -I/O Pointer to the instance data of a section filter. - - -RETURNS - - -0 - -The function was completed without errors. - - --ENODEV - -No such filter allocated. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.6.4</abbrev>start_filtering()<indexterm role="printindex" /> -DESCRIPTION - -
-Starts filtering sections on this section feed, according to its settings. Sections - are first filtered based on their PID and then matched with the section - filters allocated for this feed. If the section matches the PID filter and - at least one section filter, it is delivered to the API client. The section - is delivered asynchronously using the callback function registered with - allocate_section_feed(). - - -SYNOPSIS - - -int start_filtering ( dmx_section_feed_t⋆ feed ); - - -PARAMETERS - - -dmx_section_feed_t* - feed - -Pointer to the section feed API and instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --EINVAL - -Bad parameter. - - - -
<abbrev role="title-mark">8.6.5</abbrev>stop_filtering()<indexterm role="printindex" /> -DESCRIPTION - -
-Stops filtering sections on this section feed. Note that any changes to the - filtering parameters (filter_value, filter_mask, etc.) should only be made when - filtering is stopped. - - -SYNOPSIS - - -int stop_filtering ( dmx_section_feed_t⋆ feed ); - - -PARAMETERS - - -dmx_section_feed_t* - feed - -Pointer to the section feed API and instance data. - - -RETURNS - - -0 - -The function was completed without errors. - - --EINVAL - -Bad parameter. - - - -
Examples -In this section we would like to present some examples for using the DVB API. - -Maintainer note: This section is out of date. Please refer to the sample programs packaged -with the driver distribution from http://linuxtv.org/. - -
<abbrev role="title-mark">9.1</abbrev>Tuning -We will start with a generic tuning subroutine that uses the frontend and SEC, as well as -the demux devices. The example is given for QPSK tuners, but can easily be adjusted for -QAM. - - - #include <sys/ioctl.h> - #include <stdio.h> - #include <stdint.h> - #include <sys/types.h> - #include <sys/stat.h> - #include <fcntl.h> - #include <time.h> - #include <unistd.h> - - #include <linux/dvb/dmx.h> - #include <linux/dvb/frontend.h> - #include <linux/dvb/sec.h> - #include <sys/poll.h> - - #define DMX "/dev/dvb/adapter0/demux1" - #define FRONT "/dev/dvb/adapter0/frontend1" - #define SEC "/dev/dvb/adapter0/sec1" - - /⋆ routine for checking if we have a signal and other status information⋆/ - int FEReadStatus(int fd, fe_status_t ⋆stat) - { - int ans; - - if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){ - perror("FE READ STATUS: "); - return -1; - } - - if (⋆stat & FE_HAS_POWER) - printf("FE HAS POWER\n"); - - if (⋆stat & FE_HAS_SIGNAL) - printf("FE HAS SIGNAL\n"); - - if (⋆stat & FE_SPECTRUM_INV) - printf("SPEKTRUM INV\n"); - - return 0; - } - - - /⋆ tune qpsk ⋆/ - /⋆ freq: frequency of transponder ⋆/ - /⋆ vpid, apid, tpid: PIDs of video, audio and teletext TS packets ⋆/ - /⋆ diseqc: DiSEqC address of the used LNB ⋆/ - /⋆ pol: Polarisation ⋆/ - /⋆ srate: Symbol Rate ⋆/ - /⋆ fec. FEC ⋆/ - /⋆ lnb_lof1: local frequency of lower LNB band ⋆/ - /⋆ lnb_lof2: local frequency of upper LNB band ⋆/ - /⋆ lnb_slof: switch frequency of LNB ⋆/ - - int set_qpsk_channel(int freq, int vpid, int apid, int tpid, - int diseqc, int pol, int srate, int fec, int lnb_lof1, - int lnb_lof2, int lnb_slof) - { - struct secCommand scmd; - struct secCmdSequence scmds; - struct dmx_pes_filter_params pesFilterParams; - FrontendParameters frp; - struct pollfd pfd[1]; - FrontendEvent event; - int demux1, demux2, demux3, front; - - frequency = (uint32_t) freq; - symbolrate = (uint32_t) srate; - - if((front = open(FRONT,O_RDWR)) < 0){ - perror("FRONTEND DEVICE: "); - return -1; - } - - if((sec = open(SEC,O_RDWR)) < 0){ - perror("SEC DEVICE: "); - return -1; - } - - if (demux1 < 0){ - if ((demux1=open(DMX, O_RDWR|O_NONBLOCK)) - < 0){ - perror("DEMUX DEVICE: "); - return -1; - } - } - - if (demux2 < 0){ - if ((demux2=open(DMX, O_RDWR|O_NONBLOCK)) - < 0){ - perror("DEMUX DEVICE: "); - return -1; - } - } - - if (demux3 < 0){ - if ((demux3=open(DMX, O_RDWR|O_NONBLOCK)) - < 0){ - perror("DEMUX DEVICE: "); - return -1; - } - } - - if (freq < lnb_slof) { - frp.Frequency = (freq - lnb_lof1); - scmds.continuousTone = SEC_TONE_OFF; - } else { - frp.Frequency = (freq - lnb_lof2); - scmds.continuousTone = SEC_TONE_ON; - } - frp.Inversion = INVERSION_AUTO; - if (pol) scmds.voltage = SEC_VOLTAGE_18; - else scmds.voltage = SEC_VOLTAGE_13; - - scmd.type=0; - scmd.u.diseqc.addr=0x10; - scmd.u.diseqc.cmd=0x38; - scmd.u.diseqc.numParams=1; - scmd.u.diseqc.params[0] = 0xF0 | ((diseqc ⋆ 4) & 0x0F) | - (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) | - (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0); - - scmds.miniCommand=SEC_MINI_NONE; - scmds.numCommands=1; - scmds.commands=&scmd; - if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){ - perror("SEC SEND: "); - return -1; - } - - if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){ - perror("SEC SEND: "); - return -1; - } - - frp.u.qpsk.SymbolRate = srate; - frp.u.qpsk.FEC_inner = fec; - - if (ioctl(front, FE_SET_FRONTEND, &frp) < 0){ - perror("QPSK TUNE: "); - return -1; - } - - pfd[0].fd = front; - pfd[0].events = POLLIN; - - if (poll(pfd,1,3000)){ - if (pfd[0].revents & POLLIN){ - printf("Getting QPSK event\n"); - if ( ioctl(front, FE_GET_EVENT, &event) - - == -EOVERFLOW){ - perror("qpsk get event"); - return -1; - } - printf("Received "); - switch(event.type){ - case FE_UNEXPECTED_EV: - printf("unexpected event\n"); - return -1; - case FE_FAILURE_EV: - printf("failure event\n"); - return -1; - - case FE_COMPLETION_EV: - printf("completion event\n"); - } - } - } - - - pesFilterParams.pid = vpid; - pesFilterParams.input = DMX_IN_FRONTEND; - pesFilterParams.output = DMX_OUT_DECODER; - pesFilterParams.pes_type = DMX_PES_VIDEO; - pesFilterParams.flags = DMX_IMMEDIATE_START; - if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ - perror("set_vpid"); - return -1; - } - - pesFilterParams.pid = apid; - pesFilterParams.input = DMX_IN_FRONTEND; - pesFilterParams.output = DMX_OUT_DECODER; - pesFilterParams.pes_type = DMX_PES_AUDIO; - pesFilterParams.flags = DMX_IMMEDIATE_START; - if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ - perror("set_apid"); - return -1; - } - - pesFilterParams.pid = tpid; - pesFilterParams.input = DMX_IN_FRONTEND; - pesFilterParams.output = DMX_OUT_DECODER; - pesFilterParams.pes_type = DMX_PES_TELETEXT; - pesFilterParams.flags = DMX_IMMEDIATE_START; - if (ioctl(demux3, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ - perror("set_tpid"); - return -1; - } - - return has_signal(fds); - } - - -The program assumes that you are using a universal LNB and a standard DiSEqC -switch with up to 4 addresses. Of course, you could build in some more checking if -tuning was successful and maybe try to repeat the tuning process. Depending on the -external hardware, i.e. LNB and DiSEqC switch, and weather conditions this may be -necessary. - - -
<abbrev role="title-mark">9.2</abbrev>The DVR device -The following program code shows how to use the DVR device for recording. - - - #include <sys/ioctl.h> - #include <stdio.h> - #include <stdint.h> - #include <sys/types.h> - #include <sys/stat.h> - #include <fcntl.h> - #include <time.h> - #include <unistd.h> - - #include <linux/dvb/dmx.h> - #include <linux/dvb/video.h> - #include <sys/poll.h> - #define DVR "/dev/dvb/adapter0/dvr1" - #define AUDIO "/dev/dvb/adapter0/audio1" - #define VIDEO "/dev/dvb/adapter0/video1" - - #define BUFFY (188⋆20) - #define MAX_LENGTH (1024⋆1024⋆5) /⋆ record 5MB ⋆/ - - - /⋆ switch the demuxes to recording, assuming the transponder is tuned ⋆/ - - /⋆ demux1, demux2: file descriptor of video and audio filters ⋆/ - /⋆ vpid, apid: PIDs of video and audio channels ⋆/ - - int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid) - { - struct dmx_pes_filter_params pesFilterParams; - - if (demux1 < 0){ - if ((demux1=open(DMX, O_RDWR|O_NONBLOCK)) - < 0){ - perror("DEMUX DEVICE: "); - return -1; - } - } - - if (demux2 < 0){ - if ((demux2=open(DMX, O_RDWR|O_NONBLOCK)) - < 0){ - perror("DEMUX DEVICE: "); - return -1; - } - } - - pesFilterParams.pid = vpid; - pesFilterParams.input = DMX_IN_FRONTEND; - pesFilterParams.output = DMX_OUT_TS_TAP; - pesFilterParams.pes_type = DMX_PES_VIDEO; - pesFilterParams.flags = DMX_IMMEDIATE_START; - if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ - perror("DEMUX DEVICE"); - return -1; - } - pesFilterParams.pid = apid; - pesFilterParams.input = DMX_IN_FRONTEND; - pesFilterParams.output = DMX_OUT_TS_TAP; - pesFilterParams.pes_type = DMX_PES_AUDIO; - pesFilterParams.flags = DMX_IMMEDIATE_START; - if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ - perror("DEMUX DEVICE"); - return -1; - } - return 0; - } - - /⋆ start recording MAX_LENGTH , assuming the transponder is tuned ⋆/ - - /⋆ demux1, demux2: file descriptor of video and audio filters ⋆/ - /⋆ vpid, apid: PIDs of video and audio channels ⋆/ - int record_dvr(int demux1, int demux2, uint16_t vpid, uint16_t apid) - { - int i; - int len; - int written; - uint8_t buf[BUFFY]; - uint64_t length; - struct pollfd pfd[1]; - int dvr, dvr_out; - - /⋆ open dvr device ⋆/ - if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){ - perror("DVR DEVICE"); - return -1; - } - - /⋆ switch video and audio demuxes to dvr ⋆/ - printf ("Switching dvr on\n"); - i = switch_to_record(demux1, demux2, vpid, apid); - printf("finished: "); - - printf("Recording %2.0f MB of test file in TS format\n", - MAX_LENGTH/(1024.0⋆1024.0)); - length = 0; - - /⋆ open output file ⋆/ - if ((dvr_out = open(DVR_FILE,O_WRONLY|O_CREAT - |O_TRUNC, S_IRUSR|S_IWUSR - |S_IRGRP|S_IWGRP|S_IROTH| - S_IWOTH)) < 0){ - perror("Can't open file for dvr test"); - return -1; - } - - pfd[0].fd = dvr; - pfd[0].events = POLLIN; - - /⋆ poll for dvr data and write to file ⋆/ - while (length < MAX_LENGTH ) { - if (poll(pfd,1,1)){ - if (pfd[0].revents & POLLIN){ - len = read(dvr, buf, BUFFY); - if (len < 0){ - perror("recording"); - return -1; - } - if (len > 0){ - written = 0; - while (written < len) - written += - write (dvr_out, - buf, len); - length += len; - printf("written %2.0f MB\r", - length/1024./1024.); - } - } - } - } - return 0; - } - - - - - -
GNU Free Documentation License -Version 1.1, March 2000 - -Copyright � 2000 Free Software Foundation, Inc. -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -Everyone is permitted to copy and distribute verbatim copies of this license document, but -changing it is not allowed. - -
Preamble -The purpose of this License is to make a manual, textbook, or other written document -“free” in the sense of freedom: to assure everyone the effective freedom to copy and -redistribute it, with or without modifying it, either commercially or noncommercially. -Secondarily, this License preserves for the author and publisher a way to get credit -for their work, while not being considered responsible for modifications made by -others. - -This License is a kind of “copyleft”, which means that derivative works of the document -must themselves be free in the same sense. It complements the GNU General Public License, -which is a copyleft license designed for free software. - -We have designed this License in order to use it for manuals for free software, because -free software needs free documentation: a free program should come with manuals providing -the same freedoms that the software does. But this License is not limited to software manuals; -it can be used for any textual work, regardless of subject matter or whether it is published as a -printed book. We recommend this License principally for works whose purpose is instruction -or reference. - - -
<abbrev role="title-mark">A.1</abbrev>Applicability and Definitions -This License applies to any manual or other work that contains a notice placed by the -copyright holder saying it can be distributed under the terms of this License. The -“Document”, below, refers to any such manual or work. Any member of the public is a -licensee, and is addressed as “you”. - -A “Modified Version” of the Document means any work containing the Document or a -portion of it, either copied verbatim, or with modifications and/or translated into another -language. - -A “Secondary Section” is a named appendix or a front-matter section of the Document -that deals exclusively with the relationship of the publishers or authors of the Document to -the Document’s overall subject (or to related matters) and contains nothing that could -fall directly within that overall subject. (For example, if the Document is in part a -textbook of mathematics, a Secondary Section may not explain any mathematics.) The -relationship could be a matter of historical connection with the subject or with related -matters, or of legal, commercial, philosophical, ethical or political position regarding -them. - -The “Invariant Sections” are certain Secondary Sections whose titles are designated, as -being those of Invariant Sections, in the notice that says that the Document is released under -this License. - -The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts -or Back-Cover Texts, in the notice that says that the Document is released under this -License. - -A “Transparent” copy of the Document means a machine-readable copy, represented in a -format whose specification is available to the general public, whose contents can be viewed -and edited directly and straightforwardly with generic text editors or (for images composed of -pixels) generic paint programs or (for drawings) some widely available drawing editor, and -that is suitable for input to text formatters or for automatic translation to a variety of -formats suitable for input to text formatters. A copy made in an otherwise Transparent -file format whose markup has been designed to thwart or discourage subsequent -modification by readers is not Transparent. A copy that is not “Transparent” is called -“Opaque”. - -Examples of suitable formats for Transparent copies include plain ASCII without markup, -Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, -and standard-conforming simple HTML designed for human modification. Opaque formats -include PostScript, PDF, proprietary formats that can be read and edited only by proprietary -word processors, SGML or XML for which the DTD and/or processing tools are not -generally available, and the machine-generated HTML produced by some word processors -for output purposes only. - -The “Title Page” means, for a printed book, the title page itself, plus such following pages -as are needed to hold, legibly, the material this License requires to appear in the title page. -For works in formats which do not have any title page as such, “Title Page” means the text -near the most prominent appearance of the work’s title, preceding the beginning of the body -of the text. - - -
<abbrev role="title-mark">A.2</abbrev>Verbatim Copying -You may copy and distribute the Document in any medium, either commercially or -noncommercially, provided that this License, the copyright notices, and the license notice -saying this License applies to the Document are reproduced in all copies, and that you add no -other conditions whatsoever to those of this License. You may not use technical measures to -obstruct or control the reading or further copying of the copies you make or distribute. -However, you may accept compensation in exchange for copies. If you distribute -a large enough number of copies you must also follow the conditions in section -3. - -You may also lend copies, under the same conditions stated above, and you may publicly -display copies. - - -
<abbrev role="title-mark">A.3</abbrev>Copying in Quantity -If you publish printed copies of the Document numbering more than 100, and the -Document’s license notice requires Cover Texts, you must enclose the copies in covers that -carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and -Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you -as the publisher of these copies. The front cover must present the full title with all words of -the title equally prominent and visible. You may add other material on the covers in addition. -Copying with changes limited to the covers, as long as they preserve the title of the -Document and satisfy these conditions, can be treated as verbatim copying in other -respects. - -If the required texts for either cover are too voluminous to fit legibly, you should put the -first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto -adjacent pages. - -If you publish or distribute Opaque copies of the Document numbering more than 100, -you must either include a machine-readable Transparent copy along with each Opaque copy, -or state in or with each Opaque copy a publicly-accessible computer-network location -containing a complete Transparent copy of the Document, free of added material, -which the general network-using public has access to download anonymously at -no charge using public-standard network protocols. If you use the latter option, -you must take reasonably prudent steps, when you begin distribution of Opaque -copies in quantity, to ensure that this Transparent copy will remain thus accessible -at the stated location until at least one year after the last time you distribute an -Opaque copy (directly or through your agents or retailers) of that edition to the -public. - -It is requested, but not required, that you contact the authors of the Document well before -redistributing any large number of copies, to give them a chance to provide you with an -updated version of the Document. - - -
<abbrev role="title-mark">A.4</abbrev>Modifications -You may copy and distribute a Modified Version of the Document under the conditions of -sections 2 and 3 above, provided that you release the Modified Version under precisely this -License, with the Modified Version filling the role of the Document, thus licensing -distribution and modification of the Modified Version to whoever possesses a copy of it. In -addition, you must do these things in the Modified Version: - - - - -Use in the Title Page (and on the covers, if any) a title distinct from that of the - Document, and from those of previous versions (which should, if there were any, - be listed in the History section of the Document). You may use the same title as - a previous version if the original publisher of that version gives permission. - - - -List on the Title Page, as authors, one or more persons or entities responsible for - authorship of the modifications in the Modified Version, together with at least - five of the principal authors of the Document (all of its principal authors, if it has - less than five). - - - -State on the Title page the name of the publisher of the Modified Version, as the - publisher. - - - -Preserve all the copyright notices of the Document. - - - -Add an appropriate copyright notice for your modifications adjacent to the other - copyright notices. - - - -Include, immediately after the copyright notices, a license notice giving the - public permission to use the Modified Version under the terms of this License, - in the form shown in the Addendum below. - - - -Preserve in that license notice the full lists of Invariant Sections and required - Cover Texts given in the Document’s license notice. - - - -Include an unaltered copy of this License. - - - -Preserve the section entitled “History”, and its title, and add to it an item stating - at least the title, year, new authors, and publisher of the Modified Version as - given on the Title Page. If there is no section entitled “History” in the Document, - create one stating the title, year, authors, and publisher of the Document as given - on its Title Page, then add an item describing the Modified Version as stated in - the previous sentence. - - - -Preserve the network location, if any, given in the Document for public access - to a Transparent copy of the Document, and likewise the network locations - given in the Document for previous versions it was based on. These may be - placed in the “History” section. You may omit a network location for a work that - was published at least four years before the Document itself, or if the original - publisher of the version it refers to gives permission. - - - -In any section entitled “Acknowledgements” or “Dedications”, preserve the - section’s title, and preserve in the section all the substance and tone of each of - the contributor acknowledgements and/or dedications given therein. - - - -Preserve all the Invariant Sections of the Document, unaltered in their text and - in their titles. Section numbers or the equivalent are not considered part of the - section titles. - - - -Delete any section entitled “Endorsements”. Such a section may not be included - in the Modified Version. - - - -Do not retitle any existing section as “Endorsements” or to conflict in title with - any Invariant Section. - - -If the Modified Version includes new front-matter sections or appendices that qualify as -Secondary Sections and contain no material copied from the Document, you may at your -option designate some or all of these sections as invariant. To do this, add their titles to the list -of Invariant Sections in the Modified Version’s license notice. These titles must be distinct -from any other section titles. - -You may add a section entitled “Endorsements”, provided it contains nothing but -endorsements of your Modified Version by various parties – for example, statements of peer -review or that the text has been approved by an organization as the authoritative definition of -a standard. - -You may add a passage of up to five words as a Front-Cover Text, and a passage of up to -25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. -Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or -through arrangements made by) any one entity. If the Document already includes a cover text -for the same cover, previously added by you or by arrangement made by the same -entity you are acting on behalf of, you may not add another; but you may replace -the old one, on explicit permission from the previous publisher that added the old -one. - -The author(s) and publisher(s) of the Document do not by this License give permission to -use their names for publicity for or to assert or imply endorsement of any Modified -Version. - - -
<abbrev role="title-mark">A.5</abbrev>Combining Documents -You may combine the Document with other documents released under this License, under -the terms defined in section 4 above for modified versions, provided that you include -in the combination all of the Invariant Sections of all of the original documents, -unmodified, and list them all as Invariant Sections of your combined work in its license -notice. - -The combined work need only contain one copy of this License, and multiple identical -Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections -with the same name but different contents, make the title of each such section unique by -adding at the end of it, in parentheses, the name of the original author or publisher of -that section if known, or else a unique number. Make the same adjustment to the -section titles in the list of Invariant Sections in the license notice of the combined -work. - -In the combination, you must combine any sections entitled “History” in the various -original documents, forming one section entitled “History”; likewise combine any sections -entitled “Acknowledgements”, and any sections entitled “Dedications”. You must delete all -sections entitled “Endorsements.” - - -
<abbrev role="title-mark">A.6</abbrev>Collections of Documents -You may make a collection consisting of the Document and other documents released -under this License, and replace the individual copies of this License in the various documents -with a single copy that is included in the collection, provided that you follow the -rules of this License for verbatim copying of each of the documents in all other -respects. - -You may extract a single document from such a collection, and distribute it individually -under this License, provided you insert a copy of this License into the extracted document, -and follow this License in all other respects regarding verbatim copying of that -document. - - -
<abbrev role="title-mark">A.7</abbrev>Aggregation With Independent Works -A compilation of the Document or its derivatives with other separate and independent -documents or works, in or on a volume of a storage or distribution medium, does not as a -whole count as a Modified Version of the Document, provided no compilation copyright is -claimed for the compilation. Such a compilation is called an “aggregate”, and this License -does not apply to the other self-contained works thus compiled with the Document, on -account of their being thus compiled, if they are not themselves derivative works of the -Document. - -If the Cover Text requirement of section 3 is applicable to these copies of the Document, -then if the Document is less than one quarter of the entire aggregate, the Document’s Cover -Texts may be placed on covers that surround only the Document within the aggregate. -Otherwise they must appear on covers around the whole aggregate. - - -
<abbrev role="title-mark">A.8</abbrev>Translation -Translation is considered a kind of modification, so you may distribute translations of the -Document under the terms of section 4. Replacing Invariant Sections with translations -requires special permission from their copyright holders, but you may include translations of -some or all Invariant Sections in addition to the original versions of these Invariant Sections. -You may include a translation of this License provided that you also include the original -English version of this License. In case of a disagreement between the translation -and the original English version of this License, the original English version will -prevail. - - -
<abbrev role="title-mark">A.9</abbrev>Termination -You may not copy, modify, sublicense, or distribute the Document except as expressly -provided for under this License. Any other attempt to copy, modify, sublicense or -distribute the Document is void, and will automatically terminate your rights under this -License. However, parties who have received copies, or rights, from you under this -License will not have their licenses terminated so long as such parties remain in full -compliance. - - -
<abbrev role="title-mark">A.10</abbrev>Future Revisions of This License -The Free Software Foundation may publish new, revised versions of the GNU Free -Documentation License from time to time. Such new versions will be similar in spirit to the -present version, but may differ in detail to address new problems or concerns. See -http://www.gnu.org/copyleft/. - -Each version of the License is given a distinguishing version number. If the Document -specifies that a particular numbered version of this License ”or any later version” applies to it, -you have the option of following the terms and conditions either of that specified version or -of any later version that has been published (not as a draft) by the Free Software -Foundation. If the Document does not specify a version number of this License, -you may choose any version ever published (not as a draft) by the Free Software -Foundation. - - -
ADDENDUM: How to use this License for your documents -To use this License in a document you have written, include a copy of the License in the -document and put the following copyright and license notices just after the title -page: - - -Copyright � YEAR YOUR NAME. Permission is granted to copy, - distribute and/or modify this document under the terms of the GNU Free - Documentation License, Version 1.1 or any later version published by the - Free Software Foundation; with the Invariant Sections being LIST THEIR - TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover - Texts being LIST. A copy of the license is included in the section entitled - “GNU Free Documentation License”. - -If you have no Invariant Sections, write “with no Invariant Sections” instead -of saying which ones are invariant. If you have no Front-Cover Texts, write “no -Front-Cover Texts” instead of “Front-Cover Texts being LIST”; likewise for Back-Cover -Texts. - -If your document contains nontrivial examples of program code, we recommend releasing -these examples in parallel under your choice of free software license, such as the GNU -General Public License, to permit their use in free software. - - - - -
diff --git a/dvb-spec/sgml/dvbapi.sgml b/dvb-spec/sgml/dvbapi.sgml index e6f5674b8..6b4b96fe5 100644 --- a/dvb-spec/sgml/dvbapi.sgml +++ b/dvb-spec/sgml/dvbapi.sgml @@ -27,6 +27,7 @@ ChehabCarvalho
mchehab@infradead.org
+Ported document to Docbook XML. @@ -73,25 +74,30 @@ contents is the same as the original LaTex version. &sub-frontend; - + diff --git a/dvb-spec/sgml/dvbstb.pdf b/dvb-spec/sgml/dvbstb.pdf index 5a4eff6cb..0fa75d90c 100644 Binary files a/dvb-spec/sgml/dvbstb.pdf and b/dvb-spec/sgml/dvbstb.pdf differ diff --git a/dvb-spec/sgml/examples.sgml b/dvb-spec/sgml/examples.sgml index e69de29bb..fcdea820a 100644 --- a/dvb-spec/sgml/examples.sgml +++ b/dvb-spec/sgml/examples.sgml @@ -0,0 +1,365 @@ +Examples +In this section we would like to present some examples for using the DVB API. + +Maintainer note: This section is out of date. Please refer to the sample programs packaged +with the driver distribution from http://linuxtv.org/. + + +
+Tuning +We will start with a generic tuning subroutine that uses the frontend and SEC, as well as +the demux devices. The example is given for QPSK tuners, but can easily be adjusted for +QAM. + + + #include <sys/ioctl.h> + #include <stdio.h> + #include <stdint.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> + #include <time.h> + #include <unistd.h> + + #include <linux/dvb/dmx.h> + #include <linux/dvb/frontend.h> + #include <linux/dvb/sec.h> + #include <sys/poll.h> + + #define DMX "/dev/dvb/adapter0/demux1" + #define FRONT "/dev/dvb/adapter0/frontend1" + #define SEC "/dev/dvb/adapter0/sec1" + + /⋆ routine for checking if we have a signal and other status information⋆/ + int FEReadStatus(int fd, fe_status_t ⋆stat) + { + int ans; + + if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){ + perror("FE READ STATUS: "); + return -1; + } + + if (⋆stat & FE_HAS_POWER) + printf("FE HAS POWER\n"); + + if (⋆stat & FE_HAS_SIGNAL) + printf("FE HAS SIGNAL\n"); + + if (⋆stat & FE_SPECTRUM_INV) + printf("SPEKTRUM INV\n"); + + return 0; + } + + + /⋆ tune qpsk ⋆/ + /⋆ freq: frequency of transponder ⋆/ + /⋆ vpid, apid, tpid: PIDs of video, audio and teletext TS packets ⋆/ + /⋆ diseqc: DiSEqC address of the used LNB ⋆/ + /⋆ pol: Polarisation ⋆/ + /⋆ srate: Symbol Rate ⋆/ + /⋆ fec. FEC ⋆/ + /⋆ lnb_lof1: local frequency of lower LNB band ⋆/ + /⋆ lnb_lof2: local frequency of upper LNB band ⋆/ + /⋆ lnb_slof: switch frequency of LNB ⋆/ + + int set_qpsk_channel(int freq, int vpid, int apid, int tpid, + int diseqc, int pol, int srate, int fec, int lnb_lof1, + int lnb_lof2, int lnb_slof) + { + struct secCommand scmd; + struct secCmdSequence scmds; + struct dmx_pes_filter_params pesFilterParams; + FrontendParameters frp; + struct pollfd pfd[1]; + FrontendEvent event; + int demux1, demux2, demux3, front; + + frequency = (uint32_t) freq; + symbolrate = (uint32_t) srate; + + if((front = open(FRONT,O_RDWR)) < 0){ + perror("FRONTEND DEVICE: "); + return -1; + } + + if((sec = open(SEC,O_RDWR)) < 0){ + perror("SEC DEVICE: "); + return -1; + } + + if (demux1 < 0){ + if ((demux1=open(DMX, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + if (demux2 < 0){ + if ((demux2=open(DMX, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + if (demux3 < 0){ + if ((demux3=open(DMX, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + if (freq < lnb_slof) { + frp.Frequency = (freq - lnb_lof1); + scmds.continuousTone = SEC_TONE_OFF; + } else { + frp.Frequency = (freq - lnb_lof2); + scmds.continuousTone = SEC_TONE_ON; + } + frp.Inversion = INVERSION_AUTO; + if (pol) scmds.voltage = SEC_VOLTAGE_18; + else scmds.voltage = SEC_VOLTAGE_13; + + scmd.type=0; + scmd.u.diseqc.addr=0x10; + scmd.u.diseqc.cmd=0x38; + scmd.u.diseqc.numParams=1; + scmd.u.diseqc.params[0] = 0xF0 | ((diseqc ⋆ 4) & 0x0F) | + (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) | + (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0); + + scmds.miniCommand=SEC_MINI_NONE; + scmds.numCommands=1; + scmds.commands=&scmd; + if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){ + perror("SEC SEND: "); + return -1; + } + + if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){ + perror("SEC SEND: "); + return -1; + } + + frp.u.qpsk.SymbolRate = srate; + frp.u.qpsk.FEC_inner = fec; + + if (ioctl(front, FE_SET_FRONTEND, &frp) < 0){ + perror("QPSK TUNE: "); + return -1; + } + + pfd[0].fd = front; + pfd[0].events = POLLIN; + + if (poll(pfd,1,3000)){ + if (pfd[0].revents & POLLIN){ + printf("Getting QPSK event\n"); + if ( ioctl(front, FE_GET_EVENT, &event) + + == -EOVERFLOW){ + perror("qpsk get event"); + return -1; + } + printf("Received "); + switch(event.type){ + case FE_UNEXPECTED_EV: + printf("unexpected event\n"); + return -1; + case FE_FAILURE_EV: + printf("failure event\n"); + return -1; + + case FE_COMPLETION_EV: + printf("completion event\n"); + } + } + } + + + pesFilterParams.pid = vpid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_DECODER; + pesFilterParams.pes_type = DMX_PES_VIDEO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("set_vpid"); + return -1; + } + + pesFilterParams.pid = apid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_DECODER; + pesFilterParams.pes_type = DMX_PES_AUDIO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("set_apid"); + return -1; + } + + pesFilterParams.pid = tpid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_DECODER; + pesFilterParams.pes_type = DMX_PES_TELETEXT; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux3, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("set_tpid"); + return -1; + } + + return has_signal(fds); + } + + +The program assumes that you are using a universal LNB and a standard DiSEqC +switch with up to 4 addresses. Of course, you could build in some more checking if +tuning was successful and maybe try to repeat the tuning process. Depending on the +external hardware, i.e. LNB and DiSEqC switch, and weather conditions this may be +necessary. + +
+ +
+The DVR device +The following program code shows how to use the DVR device for recording. + + + #include <sys/ioctl.h> + #include <stdio.h> + #include <stdint.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> + #include <time.h> + #include <unistd.h> + + #include <linux/dvb/dmx.h> + #include <linux/dvb/video.h> + #include <sys/poll.h> + #define DVR "/dev/dvb/adapter0/dvr1" + #define AUDIO "/dev/dvb/adapter0/audio1" + #define VIDEO "/dev/dvb/adapter0/video1" + + #define BUFFY (188⋆20) + #define MAX_LENGTH (1024⋆1024⋆5) /⋆ record 5MB ⋆/ + + + /⋆ switch the demuxes to recording, assuming the transponder is tuned ⋆/ + + /⋆ demux1, demux2: file descriptor of video and audio filters ⋆/ + /⋆ vpid, apid: PIDs of video and audio channels ⋆/ + + int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid) + { + struct dmx_pes_filter_params pesFilterParams; + + if (demux1 < 0){ + if ((demux1=open(DMX, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + if (demux2 < 0){ + if ((demux2=open(DMX, O_RDWR|O_NONBLOCK)) + < 0){ + perror("DEMUX DEVICE: "); + return -1; + } + } + + pesFilterParams.pid = vpid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_TS_TAP; + pesFilterParams.pes_type = DMX_PES_VIDEO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("DEMUX DEVICE"); + return -1; + } + pesFilterParams.pid = apid; + pesFilterParams.input = DMX_IN_FRONTEND; + pesFilterParams.output = DMX_OUT_TS_TAP; + pesFilterParams.pes_type = DMX_PES_AUDIO; + pesFilterParams.flags = DMX_IMMEDIATE_START; + if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ + perror("DEMUX DEVICE"); + return -1; + } + return 0; + } + + /⋆ start recording MAX_LENGTH , assuming the transponder is tuned ⋆/ + + /⋆ demux1, demux2: file descriptor of video and audio filters ⋆/ + /⋆ vpid, apid: PIDs of video and audio channels ⋆/ + int record_dvr(int demux1, int demux2, uint16_t vpid, uint16_t apid) + { + int i; + int len; + int written; + uint8_t buf[BUFFY]; + uint64_t length; + struct pollfd pfd[1]; + int dvr, dvr_out; + + /⋆ open dvr device ⋆/ + if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){ + perror("DVR DEVICE"); + return -1; + } + + /⋆ switch video and audio demuxes to dvr ⋆/ + printf ("Switching dvr on\n"); + i = switch_to_record(demux1, demux2, vpid, apid); + printf("finished: "); + + printf("Recording %2.0f MB of test file in TS format\n", + MAX_LENGTH/(1024.0⋆1024.0)); + length = 0; + + /⋆ open output file ⋆/ + if ((dvr_out = open(DVR_FILE,O_WRONLY|O_CREAT + |O_TRUNC, S_IRUSR|S_IWUSR + |S_IRGRP|S_IWGRP|S_IROTH| + S_IWOTH)) < 0){ + perror("Can't open file for dvr test"); + return -1; + } + + pfd[0].fd = dvr; + pfd[0].events = POLLIN; + + /⋆ poll for dvr data and write to file ⋆/ + while (length < MAX_LENGTH ) { + if (poll(pfd,1,1)){ + if (pfd[0].revents & POLLIN){ + len = read(dvr, buf, BUFFY); + if (len < 0){ + perror("recording"); + return -1; + } + if (len > 0){ + written = 0; + while (written < len) + written += + write (dvr_out, + buf, len); + length += len; + printf("written %2.0f MB\r", + length/1024./1024.); + } + } + } + } + return 0; + } + + + +
\ No newline at end of file diff --git a/dvb-spec/sgml/fdl.sgml b/dvb-spec/sgml/fdl.sgml index e69de29bb..3b992d039 100644 --- a/dvb-spec/sgml/fdl.sgml +++ b/dvb-spec/sgml/fdl.sgml @@ -0,0 +1,374 @@ +GNU Free Documentation License +Version 1.1, March 2000 + +Copyright © 2000 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +Everyone is permitted to copy and distribute verbatim copies of this license document, but +changing it is not allowed. + +
+Preamble +The purpose of this License is to make a manual, textbook, or other written document +“free” in the sense of freedom: to assure everyone the effective freedom to copy and +redistribute it, with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way to get credit +for their work, while not being considered responsible for modifications made by +others. + +This License is a kind of “copyleft”, which means that derivative works of the document +must themselves be free in the same sense. It complements the GNU General Public License, +which is a copyleft license designed for free software. + +We have designed this License in order to use it for manuals for free software, because +free software needs free documentation: a free program should come with manuals providing +the same freedoms that the software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or whether it is published as a +printed book. We recommend this License principally for works whose purpose is instruction +or reference. + +
+ +
+Applicability and Definitions +This License applies to any manual or other work that contains a notice placed by the +copyright holder saying it can be distributed under the terms of this License. The +“Document”, below, refers to any such manual or work. Any member of the public is a +licensee, and is addressed as “you”. + +A “Modified Version” of the Document means any work containing the Document or a +portion of it, either copied verbatim, or with modifications and/or translated into another +language. + +A “Secondary Section” is a named appendix or a front-matter section of the Document +that deals exclusively with the relationship of the publishers or authors of the Document to +the Document’s overall subject (or to related matters) and contains nothing that could +fall directly within that overall subject. (For example, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any mathematics.) The +relationship could be a matter of historical connection with the subject or with related +matters, or of legal, commercial, philosophical, ethical or political position regarding +them. + +The “Invariant Sections” are certain Secondary Sections whose titles are designated, as +being those of Invariant Sections, in the notice that says that the Document is released under +this License. + +The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts +or Back-Cover Texts, in the notice that says that the Document is released under this +License. + +A “Transparent” copy of the Document means a machine-readable copy, represented in a +format whose specification is available to the general public, whose contents can be viewed +and edited directly and straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available drawing editor, and +that is suitable for input to text formatters or for automatic translation to a variety of +formats suitable for input to text formatters. A copy made in an otherwise Transparent +file format whose markup has been designed to thwart or discourage subsequent +modification by readers is not Transparent. A copy that is not “Transparent” is called +“Opaque”. + +Examples of suitable formats for Transparent copies include plain ASCII without markup, +Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, +and standard-conforming simple HTML designed for human modification. Opaque formats +include PostScript, PDF, proprietary formats that can be read and edited only by proprietary +word processors, SGML or XML for which the DTD and/or processing tools are not +generally available, and the machine-generated HTML produced by some word processors +for output purposes only. + +The “Title Page” means, for a printed book, the title page itself, plus such following pages +as are needed to hold, legibly, the material this License requires to appear in the title page. +For works in formats which do not have any title page as such, “Title Page” means the text +near the most prominent appearance of the work’s title, preceding the beginning of the body +of the text. + +
+ +
+Verbatim Copying +You may copy and distribute the Document in any medium, either commercially or +noncommercially, provided that this License, the copyright notices, and the license notice +saying this License applies to the Document are reproduced in all copies, and that you add no +other conditions whatsoever to those of this License. You may not use technical measures to +obstruct or control the reading or further copying of the copies you make or distribute. +However, you may accept compensation in exchange for copies. If you distribute +a large enough number of copies you must also follow the conditions in section +3. + +You may also lend copies, under the same conditions stated above, and you may publicly +display copies. + +
+ +
+Copying in Quantity +If you publish printed copies of the Document numbering more than 100, and the +Document’s license notice requires Cover Texts, you must enclose the copies in covers that +carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and +Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you +as the publisher of these copies. The front cover must present the full title with all words of +the title equally prominent and visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve the title of the +Document and satisfy these conditions, can be treated as verbatim copying in other +respects. + +If the required texts for either cover are too voluminous to fit legibly, you should put the +first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto +adjacent pages. + +If you publish or distribute Opaque copies of the Document numbering more than 100, +you must either include a machine-readable Transparent copy along with each Opaque copy, +or state in or with each Opaque copy a publicly-accessible computer-network location +containing a complete Transparent copy of the Document, free of added material, +which the general network-using public has access to download anonymously at +no charge using public-standard network protocols. If you use the latter option, +you must take reasonably prudent steps, when you begin distribution of Opaque +copies in quantity, to ensure that this Transparent copy will remain thus accessible +at the stated location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that edition to the +public. + +It is requested, but not required, that you contact the authors of the Document well before +redistributing any large number of copies, to give them a chance to provide you with an +updated version of the Document. + +
+ +
+Modifications +You may copy and distribute a Modified Version of the Document under the conditions of +sections 2 and 3 above, provided that you release the Modified Version under precisely this +License, with the Modified Version filling the role of the Document, thus licensing +distribution and modification of the Modified Version to whoever possesses a copy of it. In +addition, you must do these things in the Modified Version: + + + + +Use in the Title Page (and on the covers, if any) a title distinct from that of the + Document, and from those of previous versions (which should, if there were any, + be listed in the History section of the Document). You may use the same title as + a previous version if the original publisher of that version gives permission. + + + +List on the Title Page, as authors, one or more persons or entities responsible for + authorship of the modifications in the Modified Version, together with at least + five of the principal authors of the Document (all of its principal authors, if it has + less than five). + + + +State on the Title page the name of the publisher of the Modified Version, as the + publisher. + + + +Preserve all the copyright notices of the Document. + + + +Add an appropriate copyright notice for your modifications adjacent to the other + copyright notices. + + + +Include, immediately after the copyright notices, a license notice giving the + public permission to use the Modified Version under the terms of this License, + in the form shown in the Addendum below. + + + +Preserve in that license notice the full lists of Invariant Sections and required + Cover Texts given in the Document’s license notice. + + + +Include an unaltered copy of this License. + + + +Preserve the section entitled “History”, and its title, and add to it an item stating + at least the title, year, new authors, and publisher of the Modified Version as + given on the Title Page. If there is no section entitled “History” in the Document, + create one stating the title, year, authors, and publisher of the Document as given + on its Title Page, then add an item describing the Modified Version as stated in + the previous sentence. + + + +Preserve the network location, if any, given in the Document for public access + to a Transparent copy of the Document, and likewise the network locations + given in the Document for previous versions it was based on. These may be + placed in the “History” section. You may omit a network location for a work that + was published at least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. + + + +In any section entitled “Acknowledgements” or “Dedications”, preserve the + section’s title, and preserve in the section all the substance and tone of each of + the contributor acknowledgements and/or dedications given therein. + + + +Preserve all the Invariant Sections of the Document, unaltered in their text and + in their titles. Section numbers or the equivalent are not considered part of the + section titles. + + + +Delete any section entitled “Endorsements”. Such a section may not be included + in the Modified Version. + + + +Do not retitle any existing section as “Endorsements” or to conflict in title with + any Invariant Section. + + +If the Modified Version includes new front-matter sections or appendices that qualify as +Secondary Sections and contain no material copied from the Document, you may at your +option designate some or all of these sections as invariant. To do this, add their titles to the list +of Invariant Sections in the Modified Version’s license notice. These titles must be distinct +from any other section titles. + +You may add a section entitled “Endorsements”, provided it contains nothing but +endorsements of your Modified Version by various parties – for example, statements of peer +review or that the text has been approved by an organization as the authoritative definition of +a standard. + +You may add a passage of up to five words as a Front-Cover Text, and a passage of up to +25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. +Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already includes a cover text +for the same cover, previously added by you or by arrangement made by the same +entity you are acting on behalf of, you may not add another; but you may replace +the old one, on explicit permission from the previous publisher that added the old +one. + +The author(s) and publisher(s) of the Document do not by this License give permission to +use their names for publicity for or to assert or imply endorsement of any Modified +Version. + +
+ +
+Combining Documents +You may combine the Document with other documents released under this License, under +the terms defined in section 4 above for modified versions, provided that you include +in the combination all of the Invariant Sections of all of the original documents, +unmodified, and list them all as Invariant Sections of your combined work in its license +notice. + +The combined work need only contain one copy of this License, and multiple identical +Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections +with the same name but different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original author or publisher of +that section if known, or else a unique number. Make the same adjustment to the +section titles in the list of Invariant Sections in the license notice of the combined +work. + +In the combination, you must combine any sections entitled “History” in the various +original documents, forming one section entitled “History”; likewise combine any sections +entitled “Acknowledgements”, and any sections entitled “Dedications”. You must delete all +sections entitled “Endorsements.” + +
+ +
+Collections of Documents +You may make a collection consisting of the Document and other documents released +under this License, and replace the individual copies of this License in the various documents +with a single copy that is included in the collection, provided that you follow the +rules of this License for verbatim copying of each of the documents in all other +respects. + +You may extract a single document from such a collection, and distribute it individually +under this License, provided you insert a copy of this License into the extracted document, +and follow this License in all other respects regarding verbatim copying of that +document. + +
+ +
+Aggregation With Independent Works +A compilation of the Document or its derivatives with other separate and independent +documents or works, in or on a volume of a storage or distribution medium, does not as a +whole count as a Modified Version of the Document, provided no compilation copyright is +claimed for the compilation. Such a compilation is called an “aggregate”, and this License +does not apply to the other self-contained works thus compiled with the Document, on +account of their being thus compiled, if they are not themselves derivative works of the +Document. + +If the Cover Text requirement of section 3 is applicable to these copies of the Document, +then if the Document is less than one quarter of the entire aggregate, the Document’s Cover +Texts may be placed on covers that surround only the Document within the aggregate. +Otherwise they must appear on covers around the whole aggregate. + +
+ +
+Translation +Translation is considered a kind of modification, so you may distribute translations of the +Document under the terms of section 4. Replacing Invariant Sections with translations +requires special permission from their copyright holders, but you may include translations of +some or all Invariant Sections in addition to the original versions of these Invariant Sections. +You may include a translation of this License provided that you also include the original +English version of this License. In case of a disagreement between the translation +and the original English version of this License, the original English version will +prevail. + +
+ +
+Termination +You may not copy, modify, sublicense, or distribute the Document except as expressly +provided for under this License. Any other attempt to copy, modify, sublicense or +distribute the Document is void, and will automatically terminate your rights under this +License. However, parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such parties remain in full +compliance. + +
+ +
+Future Revisions of This License +The Free Software Foundation may publish new, revised versions of the GNU Free +Documentation License from time to time. Such new versions will be similar in spirit to the +present version, but may differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. If the Document +specifies that a particular numbered version of this License ”or any later version” applies to it, +you have the option of following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the Free Software +Foundation. If the Document does not specify a version number of this License, +you may choose any version ever published (not as a draft) by the Free Software +Foundation. + +
+ +
+ADDENDUM: How to use this License for your documents +To use this License in a document you have written, include a copy of the License in the +document and put the following copyright and license notices just after the title +page: + + +Copyright © YEAR YOUR NAME. Permission is granted to copy, + distribute and/or modify this document under the terms of the GNU Free + Documentation License, Version 1.1 or any later version published by the + Free Software Foundation; with the Invariant Sections being LIST THEIR + TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover + Texts being LIST. A copy of the license is included in the section entitled + “GNU Free Documentation License”. + +If you have no Invariant Sections, write “with no Invariant Sections” instead +of saying which ones are invariant. If you have no Front-Cover Texts, write “no +Front-Cover Texts” instead of “Front-Cover Texts being LIST”; likewise for Back-Cover +Texts. + +If your document contains nontrivial examples of program code, we recommend releasing +these examples in parallel under your choice of free software license, such as the GNU +General Public License, to permit their use in free software. + +
diff --git a/dvb-spec/sgml/intro.sgml b/dvb-spec/sgml/intro.sgml index 37d1c5055..83676c44e 100644 --- a/dvb-spec/sgml/intro.sgml +++ b/dvb-spec/sgml/intro.sgml @@ -43,17 +43,17 @@ implementation of the Linux DVB API.
Overview -
- Components of a DVB card/STB - - - - - - - - -
+
+Components of a DVB card/STB + + + + + + + + +
A DVB PCI card or DVB set-top-box (STB) usually consists of the following main hardware components: diff --git a/dvb-spec/sgml/kdapi.sgml b/dvb-spec/sgml/kdapi.sgml new file mode 100644 index 000000000..f0684cfbc --- /dev/null +++ b/dvb-spec/sgml/kdapi.sgml @@ -0,0 +1,2309 @@ +Kernel Demux API +The kernel demux API defines a driver-internal interface for registering low-level, +hardware specific driver to a hardware independent demux layer. It is only of interest for +DVB device driver writers. The header file for this API is named demux.h and located in +drivers/media/dvb/dvb-core. + +Maintainer note: This section must be reviewed. It is probably out of date. + + +
+Kernel Demux Data Types + + +
+dmx_success_t + + typedef enum { + DMX_OK = 0, /⋆ Received Ok ⋆/ + DMX_LENGTH_ERROR, /⋆ Incorrect length ⋆/ + DMX_OVERRUN_ERROR, /⋆ Receiver ring buffer overrun ⋆/ + DMX_CRC_ERROR, /⋆ Incorrect CRC ⋆/ + DMX_FRAME_ERROR, /⋆ Frame alignment error ⋆/ + DMX_FIFO_ERROR, /⋆ Receiver FIFO overrun ⋆/ + DMX_MISSED_ERROR /⋆ Receiver missed packet ⋆/ + } dmx_success_t; + + +
+
+TS filter types + + /⋆--------------------------------------------------------------------------⋆/ + /⋆ TS packet reception ⋆/ + /⋆--------------------------------------------------------------------------⋆/ + + /⋆ TS filter type for set_type() ⋆/ + + #define TS_PACKET 1 /⋆ send TS packets (188 bytes) to callback (default) ⋆/ + #define TS_PAYLOAD_ONLY 2 /⋆ in case TS_PACKET is set, only send the TS + payload (<=184 bytes per packet) to callback ⋆/ + #define TS_DECODER 4 /⋆ send stream to built-in decoder (if present) ⋆/ + + +
+
+dmx_ts_pes_t +The structure + + + typedef enum + { + DMX_TS_PES_AUDIO, /⋆ also send packets to audio decoder (if it exists) ⋆/ + DMX_TS_PES_VIDEO, /⋆ ... ⋆/ + DMX_TS_PES_TELETEXT, + DMX_TS_PES_SUBTITLE, + DMX_TS_PES_PCR, + DMX_TS_PES_OTHER, + } dmx_ts_pes_t; + +describes the PES type for filters which write to a built-in decoder. The correspond (and +should be kept identical) to the types in the demux device. + + + struct dmx_ts_feed_s { + int is_filtering; /⋆ Set to non-zero when filtering in progress ⋆/ + struct dmx_demux_s⋆ parent; /⋆ Back-pointer ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + int (⋆set) (struct dmx_ts_feed_s⋆ feed, + __u16 pid, + size_t callback_length, + size_t circular_buffer_size, + int descramble, + struct timespec timeout); + int (⋆start_filtering) (struct dmx_ts_feed_s⋆ feed); + int (⋆stop_filtering) (struct dmx_ts_feed_s⋆ feed); + int (⋆set_type) (struct dmx_ts_feed_s⋆ feed, + int type, + dmx_ts_pes_t pes_type); + }; + + typedef struct dmx_ts_feed_s dmx_ts_feed_t; + + + /⋆--------------------------------------------------------------------------⋆/ + /⋆ PES packet reception (not supported yet) ⋆/ + /⋆--------------------------------------------------------------------------⋆/ + + typedef struct dmx_pes_filter_s { + struct dmx_pes_s⋆ parent; /⋆ Back-pointer ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + } dmx_pes_filter_t; + + + typedef struct dmx_pes_feed_s { + int is_filtering; /⋆ Set to non-zero when filtering in progress ⋆/ + struct dmx_demux_s⋆ parent; /⋆ Back-pointer ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + int (⋆set) (struct dmx_pes_feed_s⋆ feed, + __u16 pid, + size_t circular_buffer_size, + int descramble, + struct timespec timeout); + int (⋆start_filtering) (struct dmx_pes_feed_s⋆ feed); + int (⋆stop_filtering) (struct dmx_pes_feed_s⋆ feed); + int (⋆allocate_filter) (struct dmx_pes_feed_s⋆ feed, + dmx_pes_filter_t⋆⋆ filter); + int (⋆release_filter) (struct dmx_pes_feed_s⋆ feed, + dmx_pes_filter_t⋆ filter); + } dmx_pes_feed_t; + + + typedef struct { + __u8 filter_value [DMX_MAX_FILTER_SIZE]; + __u8 filter_mask [DMX_MAX_FILTER_SIZE]; + struct dmx_section_feed_s⋆ parent; /⋆ Back-pointer ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + } dmx_section_filter_t; + + + struct dmx_section_feed_s { + int is_filtering; /⋆ Set to non-zero when filtering in progress ⋆/ + struct dmx_demux_s⋆ parent; /⋆ Back-pointer ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + int (⋆set) (struct dmx_section_feed_s⋆ feed, + __u16 pid, + size_t circular_buffer_size, + int descramble, + int check_crc); + int (⋆allocate_filter) (struct dmx_section_feed_s⋆ feed, + dmx_section_filter_t⋆⋆ filter); + int (⋆release_filter) (struct dmx_section_feed_s⋆ feed, + dmx_section_filter_t⋆ filter); + int (⋆start_filtering) (struct dmx_section_feed_s⋆ feed); + int (⋆stop_filtering) (struct dmx_section_feed_s⋆ feed); + }; + typedef struct dmx_section_feed_s dmx_section_feed_t; + + /⋆--------------------------------------------------------------------------⋆/ + /⋆ Callback functions ⋆/ + /⋆--------------------------------------------------------------------------⋆/ + + typedef int (⋆dmx_ts_cb) ( __u8 ⋆ buffer1, + size_t buffer1_length, + __u8 ⋆ buffer2, + size_t buffer2_length, + dmx_ts_feed_t⋆ source, + dmx_success_t success); + + typedef int (⋆dmx_section_cb) ( __u8 ⋆ buffer1, + size_t buffer1_len, + __u8 ⋆ buffer2, + size_t buffer2_len, + dmx_section_filter_t ⋆ source, + dmx_success_t success); + + typedef int (⋆dmx_pes_cb) ( __u8 ⋆ buffer1, + size_t buffer1_len, + __u8 ⋆ buffer2, + size_t buffer2_len, + dmx_pes_filter_t⋆ source, + dmx_success_t success); + + /⋆--------------------------------------------------------------------------⋆/ + /⋆ DVB Front-End ⋆/ + /⋆--------------------------------------------------------------------------⋆/ + + typedef enum { + DMX_OTHER_FE = 0, + DMX_SATELLITE_FE, + DMX_CABLE_FE, + DMX_TERRESTRIAL_FE, + DMX_LVDS_FE, + DMX_ASI_FE, /⋆ DVB-ASI interface ⋆/ + DMX_MEMORY_FE + } dmx_frontend_source_t; + + typedef struct { + /⋆ The following char⋆ fields point to NULL terminated strings ⋆/ + char⋆ id; /⋆ Unique front-end identifier ⋆/ + char⋆ vendor; /⋆ Name of the front-end vendor ⋆/ + char⋆ model; /⋆ Name of the front-end model ⋆/ + struct list_head connectivity_list; /⋆ List of front-ends that can + be connected to a particular + demux ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + dmx_frontend_source_t source; + } dmx_frontend_t; + + /⋆--------------------------------------------------------------------------⋆/ + /⋆ MPEG-2 TS Demux ⋆/ + /⋆--------------------------------------------------------------------------⋆/ + + /⋆ + ⋆ Flags OR'ed in the capabilites field of struct dmx_demux_s. + ⋆/ + + #define DMX_TS_FILTERING 1 + #define DMX_PES_FILTERING 2 + #define DMX_SECTION_FILTERING 4 + #define DMX_MEMORY_BASED_FILTERING 8 /⋆ write() available ⋆/ + #define DMX_CRC_CHECKING 16 + #define DMX_TS_DESCRAMBLING 32 + #define DMX_SECTION_PAYLOAD_DESCRAMBLING 64 + #define DMX_MAC_ADDRESS_DESCRAMBLING 128 + + +
+
+demux_demux_t + + /⋆ + ⋆ DMX_FE_ENTRY(): Casts elements in the list of registered + ⋆ front-ends from the generic type struct list_head + ⋆ to the type ⋆ dmx_frontend_t + ⋆. + ⋆/ + + #define DMX_FE_ENTRY(list) list_entry(list, dmx_frontend_t, connectivity_list) + + struct dmx_demux_s { + /⋆ The following char⋆ fields point to NULL terminated strings ⋆/ + char⋆ id; /⋆ Unique demux identifier ⋆/ + char⋆ vendor; /⋆ Name of the demux vendor ⋆/ + char⋆ model; /⋆ Name of the demux model ⋆/ + __u32 capabilities; /⋆ Bitfield of capability flags ⋆/ + dmx_frontend_t⋆ frontend; /⋆ Front-end connected to the demux ⋆/ + struct list_head reg_list; /⋆ List of registered demuxes ⋆/ + void⋆ priv; /⋆ Pointer to private data of the API client ⋆/ + int users; /⋆ Number of users ⋆/ + int (⋆open) (struct dmx_demux_s⋆ demux); + int (⋆close) (struct dmx_demux_s⋆ demux); + int (⋆write) (struct dmx_demux_s⋆ demux, const char⋆ buf, size_t count); + int (⋆allocate_ts_feed) (struct dmx_demux_s⋆ demux, + dmx_ts_feed_t⋆⋆ feed, + dmx_ts_cb callback); + int (⋆release_ts_feed) (struct dmx_demux_s⋆ demux, + dmx_ts_feed_t⋆ feed); + int (⋆allocate_pes_feed) (struct dmx_demux_s⋆ demux, + dmx_pes_feed_t⋆⋆ feed, + dmx_pes_cb callback); + int (⋆release_pes_feed) (struct dmx_demux_s⋆ demux, + dmx_pes_feed_t⋆ feed); + int (⋆allocate_section_feed) (struct dmx_demux_s⋆ demux, + dmx_section_feed_t⋆⋆ feed, + dmx_section_cb callback); + int (⋆release_section_feed) (struct dmx_demux_s⋆ demux, + dmx_section_feed_t⋆ feed); + int (⋆descramble_mac_address) (struct dmx_demux_s⋆ demux, + __u8⋆ buffer1, + size_t buffer1_length, + __u8⋆ buffer2, + size_t buffer2_length, + __u16 pid); + int (⋆descramble_section_payload) (struct dmx_demux_s⋆ demux, + __u8⋆ buffer1, + size_t buffer1_length, + __u8⋆ buffer2, size_t buffer2_length, + __u16 pid); + int (⋆add_frontend) (struct dmx_demux_s⋆ demux, + dmx_frontend_t⋆ frontend); + int (⋆remove_frontend) (struct dmx_demux_s⋆ demux, + dmx_frontend_t⋆ frontend); + struct list_head⋆ (⋆get_frontends) (struct dmx_demux_s⋆ demux); + int (⋆connect_frontend) (struct dmx_demux_s⋆ demux, + dmx_frontend_t⋆ frontend); + int (⋆disconnect_frontend) (struct dmx_demux_s⋆ demux); + + + /⋆ added because js cannot keep track of these himself ⋆/ + int (⋆get_pes_pids) (struct dmx_demux_s⋆ demux, __u16 ⋆pids); + }; + typedef struct dmx_demux_s dmx_demux_t; + + +
+
+Demux directory + + /⋆ + ⋆ DMX_DIR_ENTRY(): Casts elements in the list of registered + ⋆ demuxes from the generic type struct list_head⋆ to the type dmx_demux_t + ⋆. + ⋆/ + + #define DMX_DIR_ENTRY(list) list_entry(list, dmx_demux_t, reg_list) + + int dmx_register_demux (dmx_demux_t⋆ demux); + int dmx_unregister_demux (dmx_demux_t⋆ demux); + struct list_head⋆ dmx_get_demuxes (void); + +
+
+Demux Directory API +The demux directory is a Linux kernel-wide facility for registering and accessing the +MPEG-2 TS demuxes in the system. Run-time registering and unregistering of demux drivers +is possible using this API. + +All demux drivers in the directory implement the abstract interface dmx_demux_t. + + +
dmx_register_demux() +DESCRIPTION + +
+This function makes a demux driver interface available to the Linux kernel. It is + usually called by the init_module() function of the kernel module that contains + the demux driver. The caller of this function is responsible for allocating + dynamic or static memory for the demux structure and for initializing its fields + before calling this function. The memory allocated for the demux structure + must not be freed before calling dmx_unregister_demux(), + + +SYNOPSIS + + +int dmx_register_demux ( dmx_demux_t ⋆demux ) + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux structure. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EEXIST + +A demux with the same value of the id field already stored + in the directory. + + +-ENOSPC + +No space left in the directory. + + + +
dmx_unregister_demux() +DESCRIPTION + +
+This function is called to indicate that the given demux interface is no + longer available. The caller of this function is responsible for freeing the + memory of the demux structure, if it was dynamically allocated before calling + dmx_register_demux(). The cleanup_module() function of the kernel module + that contains the demux driver should call this function. Note that this function + fails if the demux is currently in use, i.e., release_demux() has not been called + for the interface. + + +SYNOPSIS + + +int dmx_unregister_demux ( dmx_demux_t ⋆demux ) + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux structure which is to be + unregistered. + + +RETURNS + + +0 + +The function was completed without errors. + + +ENODEV + +The specified demux is not registered in the demux + directory. + + +EBUSY + +The specified demux is currently in use. + + + +
dmx_get_demuxes() +DESCRIPTION + +
+Provides the caller with the list of registered demux interfaces, using the + standard list structure defined in the include file linux/list.h. The include file + demux.h defines the macro DMX_DIR_ENTRY() for converting an element of + the generic type struct list_head* to the type dmx_demux_t*. The caller must + not free the memory of any of the elements obtained via this function call. + + +SYNOPSIS + + +struct list_head ⋆dmx_get_demuxes () + + +PARAMETERS + + +none + + +RETURNS + + +struct list_head * + +A list of demux interfaces, or NULL in the case of an + empty list. + + + +
+Demux API +The demux API should be implemented for each demux in the system. It is used to select +the TS source of a demux and to manage the demux resources. When the demux +client allocates a resource via the demux API, it receives a pointer to the API of that +resource. + +Each demux receives its TS input from a DVB front-end or from memory, as set via the +demux API. In a system with more than one front-end, the API can be used to select one of +the DVB front-ends as a TS source for a demux, unless this is fixed in the HW platform. The +demux API only controls front-ends regarding their connections with demuxes; the APIs +used to set the other front-end parameters, such as tuning, are not defined in this +document. + +The functions that implement the abstract interface demux should be defined static or +module private and registered to the Demux Directory for external access. It is not necessary +to implement every function in the demux_t struct, however (for example, a demux interface +might support Section filtering, but not TS or PES filtering). The API client is expected to +check the value of any function pointer before calling the function: the value of NULL means +“function not available”. + +Whenever the functions of the demux API modify shared data, the possibilities of lost +update and race condition problems should be addressed, e.g. by protecting parts of code with +mutexes. This is especially important on multi-processor hosts. + +Note that functions called from a bottom half context must not sleep, at least in the 2.2.x +kernels. Even a simple memory allocation can result in a kernel thread being put to sleep if +swapping is needed. For example, the Linux kernel calls the functions of a network device +interface from a bottom half context. Thus, if a demux API function is called from network +device code, the function must not sleep. + + + +
+open() +DESCRIPTION + +
+This function reserves the demux for use by the caller and, if necessary, + initializes the demux. When the demux is no longer needed, the function close() + should be called. It should be possible for multiple clients to access the demux + at the same time. Thus, the function implementation should increment the + demux usage count when open() is called and decrement it when close() is + called. + + +SYNOPSIS + + +int open ( demux_t⋆ demux ); + + +PARAMETERS + + +demux_t* demux + +Pointer to the demux API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EUSERS + +Maximum usage count reached. + + +-EINVAL + +Bad parameter. + + + + +
+close() +DESCRIPTION + +
+This function reserves the demux for use by the caller and, if necessary, + initializes the demux. When the demux is no longer needed, the function close() + should be called. It should be possible for multiple clients to access the demux + at the same time. Thus, the function implementation should increment the + demux usage count when open() is called and decrement it when close() is + called. + + +SYNOPSIS + + +int close(demux_t⋆ demux); + + +PARAMETERS + + +demux_t* demux + +Pointer to the demux API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENODEV + +The demux was not in use. + + +-EINVAL + +Bad parameter. + + + + +
+write() +DESCRIPTION + +
+This function provides the demux driver with a memory buffer containing TS + packets. Instead of receiving TS packets from the DVB front-end, the demux + driver software will read packets from memory. Any clients of this demux + with active TS, PES or Section filters will receive filtered data via the Demux + callback API (see 0). The function returns when all the data in the buffer has + been consumed by the demux. Demux hardware typically cannot read TS from + memory. If this is the case, memory-based filtering has to be implemented + entirely in software. + + +SYNOPSIS + + +int write(demux_t⋆ demux, const char⋆ buf, size_t + count); + + +PARAMETERS + + +demux_t* demux + +Pointer to the demux API and instance data. + + +const char* buf + +Pointer to the TS data in kernel-space memory. + + +size_t length + +Length of the TS data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOSYS + +The command is not implemented. + + +-EINVAL + +Bad parameter. + + + +
allocate_ts_feed() +DESCRIPTION + +
+Allocates a new TS feed, which is used to filter the TS packets carrying a + certain PID. The TS feed normally corresponds to a hardware PID filter on the + demux chip. + + +SYNOPSIS + + +int allocate_ts_feed(dmx_demux_t⋆ demux, + dmx_ts_feed_t⋆⋆ feed, dmx_ts_cb callback); + + +PARAMETERS + + +demux_t* demux + +Pointer to the demux API and instance data. + + +dmx_ts_feed_t** + feed + +Pointer to the TS feed API and instance data. + + +dmx_ts_cb callback + +Pointer to the callback function for passing received TS + packet + + +RETURNS + + +0 + +The function was completed without errors. + + +-EBUSY + +No more TS feeds available. + + +-ENOSYS + +The command is not implemented. + + +-EINVAL + +Bad parameter. + + + +
release_ts_feed() +DESCRIPTION + +
+Releases the resources allocated with allocate_ts_feed(). Any filtering in + progress on the TS feed should be stopped before calling this function. + + +SYNOPSIS + + +int release_ts_feed(dmx_demux_t⋆ demux, + dmx_ts_feed_t⋆ feed); + + +PARAMETERS + + +demux_t* demux + +Pointer to the demux API and instance data. + + +dmx_ts_feed_t* feed + +Pointer to the TS feed API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + +
allocate_section_feed() +DESCRIPTION + +
+Allocates a new section feed, i.e. a demux resource for filtering and receiving + sections. On platforms with hardware support for section filtering, a section + feed is directly mapped to the demux HW. On other platforms, TS packets are + first PID filtered in hardware and a hardware section filter then emulated in + software. The caller obtains an API pointer of type dmx_section_feed_t as an + out parameter. Using this API the caller can set filtering parameters and start + receiving sections. + + +SYNOPSIS + + +int allocate_section_feed(dmx_demux_t⋆ demux, + dmx_section_feed_t ⋆⋆feed, dmx_section_cb callback); + + +PARAMETERS + + +demux_t *demux + +Pointer to the demux API and instance data. + + +dmx_section_feed_t + **feed + +Pointer to the section feed API and instance data. + + +dmx_section_cb + callback + +Pointer to the callback function for passing received + sections. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EBUSY + +No more section feeds available. + + +-ENOSYS + +The command is not implemented. + + +-EINVAL + +Bad parameter. + + + +
release_section_feed() +DESCRIPTION + +
+Releases the resources allocated with allocate_section_feed(), including + allocated filters. Any filtering in progress on the section feed should be stopped + before calling this function. + + +SYNOPSIS + + +int release_section_feed(dmx_demux_t⋆ demux, + dmx_section_feed_t ⋆feed); + + +PARAMETERS + + +demux_t *demux + +Pointer to the demux API and instance data. + + +dmx_section_feed_t + *feed + +Pointer to the section feed API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + +
descramble_mac_address() +DESCRIPTION + +
+This function runs a descrambling algorithm on the destination MAC + address field of a DVB Datagram Section, replacing the original address + with its un-encrypted version. Otherwise, the description on the function + descramble_section_payload() applies also to this function. + + +SYNOPSIS + + +int descramble_mac_address(dmx_demux_t⋆ demux, __u8 + ⋆buffer1, size_t buffer1_length, __u8 ⋆buffer2, + size_t buffer2_length, __u16 pid); + + +PARAMETERS + + +dmx_demux_t + *demux + +Pointer to the demux API and instance data. + + +__u8 *buffer1 + +Pointer to the first byte of the section. + + +size_t buffer1_length + +Length of the section data, including headers and CRC, + in buffer1. + + +__u8* buffer2 + +Pointer to the tail of the section data, or NULL. The + pointer has a non-NULL value if the section wraps past + the end of a circular buffer. + + +size_t buffer2_length + +Length of the section data, including headers and CRC, + in buffer2. + + +__u16 pid + +The PID on which the section was received. Useful + for obtaining the descrambling key, e.g. from a DVB + Common Access facility. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOSYS + +No descrambling facility available. + + +-EINVAL + +Bad parameter. + + + +
descramble_section_payload() +DESCRIPTION + +
+This function runs a descrambling algorithm on the payload of a DVB + Datagram Section, replacing the original payload with its un-encrypted + version. The function will be called from the demux API implementation; + the API client need not call this function directly. Section-level scrambling + algorithms are currently standardized only for DVB-RCC (return channel + over 2-directional cable TV network) systems. For all other DVB networks, + encryption schemes are likely to be proprietary to each data broadcaster. Thus, + it is expected that this function pointer will have the value of NULL (i.e., + function not available) in most demux API implementations. Nevertheless, it + should be possible to use the function pointer as a hook for dynamically adding + a “plug-in” descrambling facility to a demux driver. + + +While this function is not needed with hardware-based section descrambling, + the descramble_section_payload function pointer can be used to override the + default hardware-based descrambling algorithm: if the function pointer has a + non-NULL value, the corresponding function should be used instead of any + descrambling hardware. + + +SYNOPSIS + + +int descramble_section_payload(dmx_demux_t⋆ demux, + __u8 ⋆buffer1, size_t buffer1_length, __u8 ⋆buffer2, + size_t buffer2_length, __u16 pid); + + +PARAMETERS + + +dmx_demux_t + *demux + +Pointer to the demux API and instance data. + + +__u8 *buffer1 + +Pointer to the first byte of the section. + + +size_t buffer1_length + +Length of the section data, including headers and CRC, + in buffer1. + + +__u8 *buffer2 + +Pointer to the tail of the section data, or NULL. The + pointer has a non-NULL value if the section wraps past + the end of a circular buffer. + + +size_t buffer2_length + +Length of the section data, including headers and CRC, + in buffer2. + + +__u16 pid + +The PID on which the section was received. Useful + for obtaining the descrambling key, e.g. from a DVB + Common Access facility. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOSYS + +No descrambling facility available. + + +-EINVAL + +Bad parameter. + + + +
add_frontend() +DESCRIPTION + +
+Registers a connectivity between a demux and a front-end, i.e., indicates that + the demux can be connected via a call to connect_frontend() to use the given + front-end as a TS source. The client of this function has to allocate dynamic or + static memory for the frontend structure and initialize its fields before calling + this function. This function is normally called during the driver initialization. + The caller must not free the memory of the frontend struct before successfully + calling remove_frontend(). + + +SYNOPSIS + + +int add_frontend(dmx_demux_t ⋆demux, dmx_frontend_t + ⋆frontend); + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux API and instance data. + + +dmx_frontend_t* + frontend + +Pointer to the front-end instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EEXIST + +A front-end with the same value of the id field already + registered. + + +-EINUSE + +The demux is in use. + + +-ENOMEM + +No more front-ends can be added. + + +-EINVAL + +Bad parameter. + + + +
remove_frontend() +DESCRIPTION + +
+Indicates that the given front-end, registered by a call to add_frontend(), can + no longer be connected as a TS source by this demux. The function should be + called when a front-end driver or a demux driver is removed from the system. + If the front-end is in use, the function fails with the return value of -EBUSY. + After successfully calling this function, the caller can free the memory of + the frontend struct if it was dynamically allocated before the add_frontend() + operation. + + +SYNOPSIS + + +int remove_frontend(dmx_demux_t⋆ demux, + dmx_frontend_t⋆ frontend); + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux API and instance data. + + +dmx_frontend_t* + frontend + +Pointer to the front-end instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + +-EBUSY + +The front-end is in use, i.e. a call to connect_frontend() + has not been followed by a call to disconnect_frontend(). + + + +
get_frontends() +DESCRIPTION + +
+Provides the APIs of the front-ends that have been registered for this demux. + Any of the front-ends obtained with this call can be used as a parameter for + connect_frontend(). + + +The include file demux.h contains the macro DMX_FE_ENTRY() for + converting an element of the generic type struct list_head* to the type + dmx_frontend_t*. The caller must not free the memory of any of the elements + obtained via this function call. + + +SYNOPSIS + + +struct list_head⋆ get_frontends(dmx_demux_t⋆ demux); + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux API and instance data. + + +RETURNS + + +dmx_demux_t* + +A list of front-end interfaces, or NULL in the case of an + empty list. + + + +
connect_frontend() +DESCRIPTION + +
+Connects the TS output of the front-end to the input of the demux. A demux + can only be connected to a front-end registered to the demux with the function + add_frontend(). + + +It may or may not be possible to connect multiple demuxes to the same + front-end, depending on the capabilities of the HW platform. When not used, + the front-end should be released by calling disconnect_frontend(). + + +SYNOPSIS + + +int connect_frontend(dmx_demux_t⋆ demux, + dmx_frontend_t⋆ frontend); + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux API and instance data. + + +dmx_frontend_t* + frontend + +Pointer to the front-end instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + +-EBUSY + +The front-end is in use. + + + +
disconnect_frontend() +DESCRIPTION + +
+Disconnects the demux and a front-end previously connected by a + connect_frontend() call. + + +SYNOPSIS + + +int disconnect_frontend(dmx_demux_t⋆ demux); + + +PARAMETERS + + +dmx_demux_t* + demux + +Pointer to the demux API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + +
+Demux Callback API +This kernel-space API comprises the callback functions that deliver filtered data to the +demux client. Unlike the other APIs, these API functions are provided by the client and called +from the demux code. + +The function pointers of this abstract interface are not packed into a structure as in the +other demux APIs, because the callback functions are registered and used independent +of each other. As an example, it is possible for the API client to provide several +callback functions for receiving TS packets and no callbacks for PES packets or +sections. + +The functions that implement the callback API need not be re-entrant: when a demux +driver calls one of these functions, the driver is not allowed to call the function again before +the original call returns. If a callback is triggered by a hardware interrupt, it is recommended +to use the Linux “bottom half” mechanism or start a tasklet instead of making the callback +function call directly from a hardware interrupt. + + +
dmx_ts_cb() +DESCRIPTION + +
+This function, provided by the client of the demux API, is called from the + demux code. The function is only called when filtering on this TS feed has + been enabled using the start_filtering() function. + + +Any TS packets that match the filter settings are copied to a circular buffer. The + filtered TS packets are delivered to the client using this callback function. The + size of the circular buffer is controlled by the circular_buffer_size parameter + of the set() function in the TS Feed API. It is expected that the buffer1 and + buffer2 callback parameters point to addresses within the circular buffer, but + other implementations are also possible. Note that the called party should not + try to free the memory the buffer1 and buffer2 parameters point to. + + +When this function is called, the buffer1 parameter typically points to the + start of the first undelivered TS packet within a circular buffer. The buffer2 + buffer parameter is normally NULL, except when the received TS packets have + crossed the last address of the circular buffer and ”wrapped” to the beginning + of the buffer. In the latter case the buffer1 parameter would contain an address + within the circular buffer, while the buffer2 parameter would contain the first + address of the circular buffer. + + +The number of bytes delivered with this function (i.e. buffer1_length + + buffer2_length) is usually equal to the value of callback_length parameter + given in the set() function, with one exception: if a timeout occurs before + receiving callback_length bytes of TS data, any undelivered packets are + immediately delivered to the client by calling this function. The timeout + duration is controlled by the set() function in the TS Feed API. + + +If a TS packet is received with errors that could not be fixed by the TS-level + forward error correction (FEC), the Transport_error_indicator flag of the TS + packet header should be set. The TS packet should not be discarded, as + the error can possibly be corrected by a higher layer protocol. If the called + party is slow in processing the callback, it is possible that the circular buffer + eventually fills up. If this happens, the demux driver should discard any TS + packets received while the buffer is full. The error should be indicated to the + client on the next callback by setting the success parameter to the value of + DMX_OVERRUN_ERROR. + + +The type of data returned to the callback can be selected by the new + function int (*set_type) (struct dmx_ts_feed_s* feed, int type, dmx_ts_pes_t + pes_type) which is part of the dmx_ts_feed_s struct (also cf. to the + include file ost/demux.h) The type parameter decides if the raw TS packet + (TS_PACKET) or just the payload (TS_PACKET—TS_PAYLOAD_ONLY) + should be returned. If additionally the TS_DECODER bit is set the stream + will also be sent to the hardware MPEG decoder. In this case, the second + flag decides as what kind of data the stream should be interpreted. The + possible choices are one of DMX_TS_PES_AUDIO, DMX_TS_PES_VIDEO, + DMX_TS_PES_TELETEXT, DMX_TS_PES_SUBTITLE, + DMX_TS_PES_PCR, or DMX_TS_PES_OTHER. + + +SYNOPSIS + + +int dmx_ts_cb(__u8⋆ buffer1, size_t buffer1_length, + __u8⋆ buffer2, size_t buffer2_length, dmx_ts_feed_t⋆ + source, dmx_success_t success); + + +PARAMETERS + + +__u8* buffer1 + +Pointer to the start of the filtered TS packets. + + +size_t buffer1_length + +Length of the TS data in buffer1. + + +__u8* buffer2 + +Pointer to the tail of the filtered TS packets, or NULL. + + +size_t buffer2_length + +Length of the TS data in buffer2. + + +dmx_ts_feed_t* + source + +Indicates which TS feed is the source of the callback. + + +dmx_success_t + success + +Indicates if there was an error in TS reception. + + +RETURNS + + +0 + +Continue filtering. + + +-1 + +Stop filtering - has the same effect as a call to + stop_filtering() on the TS Feed API. + + + +
dmx_section_cb() +DESCRIPTION + +
+This function, provided by the client of the demux API, is called from the + demux code. The function is only called when filtering of sections has been + enabled using the function start_filtering() of the section feed API. When the + demux driver has received a complete section that matches at least one section + filter, the client is notified via this callback function. Normally this function is + called for each received section; however, it is also possible to deliver multiple + sections with one callback, for example when the system load is high. If an + error occurs while receiving a section, this function should be called with + the corresponding error type set in the success field, whether or not there is + data to deliver. The Section Feed implementation should maintain a circular + buffer for received sections. However, this is not necessary if the Section Feed + API is implemented as a client of the TS Feed API, because the TS Feed + implementation then buffers the received data. The size of the circular buffer + can be configured using the set() function in the Section Feed API. If there + is no room in the circular buffer when a new section is received, the section + must be discarded. If this happens, the value of the success parameter should + be DMX_OVERRUN_ERROR on the next callback. + + +SYNOPSIS + + +int dmx_section_cb(__u8⋆ buffer1, size_t + buffer1_length, __u8⋆ buffer2, size_t + buffer2_length, dmx_section_filter_t⋆ source, + dmx_success_t success); + + +PARAMETERS + + +__u8* buffer1 + +Pointer to the start of the filtered section, e.g. within the + circular buffer of the demux driver. + + +size_t buffer1_length + +Length of the filtered section data in buffer1, including + headers and CRC. + + +__u8* buffer2 + +Pointer to the tail of the filtered section data, or NULL. + Useful to handle the wrapping of a circular buffer. + + +size_t buffer2_length + +Length of the filtered section data in buffer2, including + headers and CRC. + + +dmx_section_filter_t* + filter + +Indicates the filter that triggered the callback. + + +dmx_success_t + success + +Indicates if there was an error in section reception. + + +RETURNS + + +0 + +Continue filtering. + + +-1 + +Stop filtering - has the same effect as a call to + stop_filtering() on the Section Feed API. + + + +
+TS Feed API +A TS feed is typically mapped to a hardware PID filter on the demux chip. +Using this API, the client can set the filtering properties to start/stop filtering TS +packets on a particular TS feed. The API is defined as an abstract interface of the type +dmx_ts_feed_t. + +The functions that implement the interface should be defined static or module private. The +client can get the handle of a TS feed API by calling the function allocate_ts_feed() in the +demux API. + + +
set() +DESCRIPTION + +
+This function sets the parameters of a TS feed. Any filtering in progress on the + TS feed must be stopped before calling this function. + + +SYNOPSIS + + +int set ( dmx_ts_feed_t⋆ feed, __u16 pid, size_t + callback_length, size_t circular_buffer_size, int + descramble, struct timespec timeout); + + +PARAMETERS + + +dmx_ts_feed_t* feed + +Pointer to the TS feed API and instance data. + + +__u16 pid + +PID value to filter. Only the TS packets carrying the + specified PID will be passed to the API client. + + +size_t + callback_length + +Number of bytes to deliver with each call to the + dmx_ts_cb() callback function. The value of this + parameter should be a multiple of 188. + + +size_t + circular_buffer_size + +Size of the circular buffer for the filtered TS packets. + + +int descramble + +If non-zero, descramble the filtered TS packets. + + +struct timespec + timeout + +Maximum time to wait before delivering received TS + packets to the client. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOMEM + +Not enough memory for the requested buffer size. + + +-ENOSYS + +No descrambling facility available for TS. + + +-EINVAL + +Bad parameter. + + + +
start_filtering() +DESCRIPTION + +
+Starts filtering TS packets on this TS feed, according to its settings. The PID + value to filter can be set by the API client. All matching TS packets are + delivered asynchronously to the client, using the callback function registered + with allocate_ts_feed(). + + +SYNOPSIS + + +int start_filtering(dmx_ts_feed_t⋆ feed); + + +PARAMETERS + + +dmx_ts_feed_t* feed + +Pointer to the TS feed API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + +
stop_filtering() +DESCRIPTION + +
+Stops filtering TS packets on this TS feed. + + +SYNOPSIS + + +int stop_filtering(dmx_ts_feed_t⋆ feed); + + +PARAMETERS + + +dmx_ts_feed_t* feed + +Pointer to the TS feed API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + +
+Section Feed API +A section feed is a resource consisting of a PID filter and a set of section filters. Using this +API, the client can set the properties of a section feed and to start/stop filtering. The API is +defined as an abstract interface of the type dmx_section_feed_t. The functions that implement +the interface should be defined static or module private. The client can get the handle of +a section feed API by calling the function allocate_section_feed() in the demux +API. + +On demux platforms that provide section filtering in hardware, the Section Feed API +implementation provides a software wrapper for the demux hardware. Other platforms may +support only PID filtering in hardware, requiring that TS packets are converted to sections in +software. In the latter case the Section Feed API implementation can be a client of the TS +Feed API. + + +
+
+set() +DESCRIPTION + +
+This function sets the parameters of a section feed. Any filtering in progress on + the section feed must be stopped before calling this function. If descrambling + is enabled, the payload_scrambling_control and address_scrambling_control + fields of received DVB datagram sections should be observed. If either one is + non-zero, the section should be descrambled either in hardware or using the + functions descramble_mac_address() and descramble_section_payload() of the + demux API. Note that according to the MPEG-2 Systems specification, only + the payloads of private sections can be scrambled while the rest of the section + data must be sent in the clear. + + +SYNOPSIS + + +int set(dmx_section_feed_t⋆ feed, __u16 pid, size_t + circular_buffer_size, int descramble, int + check_crc); + + +PARAMETERS + + +dmx_section_feed_t* + feed + +Pointer to the section feed API and instance data. + + +__u16 pid + +PID value to filter; only the TS packets carrying the + specified PID will be accepted. + + +size_t + circular_buffer_size + +Size of the circular buffer for filtered sections. + + +int descramble + +If non-zero, descramble any sections that are scrambled. + + +int check_crc + +If non-zero, check the CRC values of filtered sections. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOMEM + +Not enough memory for the requested buffer size. + + +-ENOSYS + +No descrambling facility available for sections. + + +-EINVAL + +Bad parameters. + + + +
allocate_filter() +DESCRIPTION + +
+This function is used to allocate a section filter on the demux. It should only be + called when no filtering is in progress on this section feed. If a filter cannot be + allocated, the function fails with -ENOSPC. See in section ?? for the format of + the section filter. + + +The bitfields filter_mask and filter_value should only be modified when no + filtering is in progress on this section feed. filter_mask controls which bits of + filter_value are compared with the section headers/payload. On a binary value + of 1 in filter_mask, the corresponding bits are compared. The filter only accepts + sections that are equal to filter_value in all the tested bit positions. Any changes + to the values of filter_mask and filter_value are guaranteed to take effect only + when the start_filtering() function is called next time. The parent pointer in + the struct is initialized by the API implementation to the value of the feed + parameter. The priv pointer is not used by the API implementation, and can + thus be freely utilized by the caller of this function. Any data pointed to by the + priv pointer is available to the recipient of the dmx_section_cb() function call. + + +While the maximum section filter length (DMX_MAX_FILTER_SIZE) is + currently set at 16 bytes, hardware filters of that size are not available on all + platforms. Therefore, section filtering will often take place first in hardware, + followed by filtering in software for the header bytes that were not covered + by a hardware filter. The filter_mask field can be checked to determine how + many bytes of the section filter are actually used, and if the hardware filter will + suffice. Additionally, software-only section filters can optionally be allocated + to clients when all hardware section filters are in use. Note that on most demux + hardware it is not possible to filter on the section_length field of the section + header – thus this field is ignored, even though it is included in filter_value and + filter_mask fields. + + +SYNOPSIS + + +int allocate_filter(dmx_section_feed_t⋆ feed, + dmx_section_filter_t⋆⋆ filter); + + +PARAMETERS + + +dmx_section_feed_t* + feed + +Pointer to the section feed API and instance data. + + +dmx_section_filter_t** + filter + +Pointer to the allocated filter. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENOSPC + +No filters of given type and length available. + + +-EINVAL + +Bad parameters. + + + +
release_filter() +DESCRIPTION + +
+This function releases all the resources of a previously allocated section filter. + The function should not be called while filtering is in progress on this section + feed. After calling this function, the caller should not try to dereference the + filter pointer. + + +SYNOPSIS + + +int release_filter ( dmx_section_feed_t⋆ feed, + dmx_section_filter_t⋆ filter); + + +PARAMETERS + + +dmx_section_feed_t* + feed + +Pointer to the section feed API and instance data. + + +dmx_section_filter_t* + filter + +I/O Pointer to the instance data of a section filter. + + +RETURNS + + +0 + +The function was completed without errors. + + +-ENODEV + +No such filter allocated. + + +-EINVAL + +Bad parameter. + + + +
start_filtering() +DESCRIPTION + +
+Starts filtering sections on this section feed, according to its settings. Sections + are first filtered based on their PID and then matched with the section + filters allocated for this feed. If the section matches the PID filter and + at least one section filter, it is delivered to the API client. The section + is delivered asynchronously using the callback function registered with + allocate_section_feed(). + + +SYNOPSIS + + +int start_filtering ( dmx_section_feed_t⋆ feed ); + + +PARAMETERS + + +dmx_section_feed_t* + feed + +Pointer to the section feed API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + +
stop_filtering() +DESCRIPTION + +
+Stops filtering sections on this section feed. Note that any changes to the + filtering parameters (filter_value, filter_mask, etc.) should only be made when + filtering is stopped. + + +SYNOPSIS + + +int stop_filtering ( dmx_section_feed_t⋆ feed ); + + +PARAMETERS + + +dmx_section_feed_t* + feed + +Pointer to the section feed API and instance data. + + +RETURNS + + +0 + +The function was completed without errors. + + +-EINVAL + +Bad parameter. + + + + \ No newline at end of file diff --git a/dvb-spec/sgml/net.sgml b/dvb-spec/sgml/net.sgml new file mode 100644 index 000000000..77557ae2a --- /dev/null +++ b/dvb-spec/sgml/net.sgml @@ -0,0 +1,12 @@ +DVB Network API +The DVB net device enables feeding of MPE (multi protocol encapsulation) packets +received via DVB into the Linux network protocol stack, e.g. for internet via satellite +applications. It can be accessed through /dev/dvb/adapter0/net0. Data types and +and ioctl definitions can be accessed by including linux/dvb/net.h in your +application. + +
+DVB Net Data Types +To be written… + +
\ No newline at end of file diff --git a/dvb-spec/sgml/video.sgml b/dvb-spec/sgml/video.sgml new file mode 100644 index 000000000..5e35abcdf --- /dev/null +++ b/dvb-spec/sgml/video.sgml @@ -0,0 +1,1971 @@ +DVB Video Device +The DVB video device controls the MPEG2 video decoder of the DVB hardware. It +can be accessed through /dev/dvb/adapter0/video0. Data types and and +ioctl definitions can be accessed by including linux/dvb/video.h in your +application. + +Note that the DVB video device only controls decoding of the MPEG video stream, not +its presentation on the TV or computer screen. On PCs this is typically handled by an +associated video4linux device, e.g. /dev/video, which allows scaling and defining output +windows. + +Some DVB cards don’t have their own MPEG decoder, which results in the omission of +the audio and video device as well as the video4linux device. + +The ioctls that deal with SPUs (sub picture units) and navigation packets are only +supported on some MPEG decoders made for DVD playback. + +
+Video Data Types + +
+video_format_t +The video_format_t data type defined by + + + typedef enum { + VIDEO_FORMAT_4_3, + VIDEO_FORMAT_16_9 + } video_format_t; + +is used in the VIDEO_SET_FORMAT function (??) to tell the driver which aspect ratio +the output hardware (e.g. TV) has. It is also used in the data structures video_status +(??) returned by VIDEO_GET_STATUS (??) and video_event (??) returned by +VIDEO_GET_EVENT (??) which report about the display format of the current video +stream. + +
+ +
+video_display_format_t +In case the display format of the video stream and of the display hardware differ the +application has to specify how to handle the cropping of the picture. This can be done using +the VIDEO_SET_DISPLAY_FORMAT call (??) which accepts + + + typedef enum { + VIDEO_PAN_SCAN, + VIDEO_LETTER_BOX, + VIDEO_CENTER_CUT_OUT + } video_display_format_t; + +as argument. + +
+ +
+video stream source +The video stream source is set through the VIDEO_SELECT_SOURCE call and can take +the following values, depending on whether we are replaying from an internal (demuxer) or +external (user write) source. + + + typedef enum { + VIDEO_SOURCE_DEMUX, + VIDEO_SOURCE_MEMORY + } video_stream_source_t; + +VIDEO_SOURCE_DEMUX selects the demultiplexer (fed either by the frontend or the +DVR device) as the source of the video stream. If VIDEO_SOURCE_MEMORY +is selected the stream comes from the application through the write() system +call. + +
+ +
+video play state +The following values can be returned by the VIDEO_GET_STATUS call representing the +state of video playback. + + + typedef enum { + VIDEO_STOPPED, + VIDEO_PLAYING, + VIDEO_FREEZED + } video_play_state_t; + +
+ +
+struct video_event +The following is the structure of a video event as it is returned by the VIDEO_GET_EVENT +call. + + + struct video_event { + int32_t type; + time_t timestamp; + union { + video_format_t video_format; + } u; + }; + +
+ +
+struct video_status +The VIDEO_GET_STATUS call returns the following structure informing about various +states of the playback operation. + + + struct video_status { + boolean video_blank; + video_play_state_t play_state; + video_stream_source_t stream_source; + video_format_t video_format; + video_displayformat_t display_format; + }; + +If video_blank is set video will be blanked out if the channel is changed or if playback is +stopped. Otherwise, the last picture will be displayed. play_state indicates if the video is +currently frozen, stopped, or being played back. The stream_source corresponds to the seleted +source for the video stream. It can come either from the demultiplexer or from memory. +The video_format indicates the aspect ratio (one of 4:3 or 16:9) of the currently +played video stream. Finally, display_format corresponds to the selected cropping +mode in case the source video format is not the same as the format of the output +device. + +
+ +
+struct video_still_picture +An I-frame displayed via the VIDEO_STILLPICTURE call is passed on within the +following structure. + + + /⋆ pointer to and size of a single iframe in memory ⋆/ + struct video_still_picture { + char ⋆iFrame; + int32_t size; + }; + +
+ +
+video capabilities +A call to VIDEO_GET_CAPABILITIES returns an unsigned integer with the following +bits set according to the hardwares capabilities. + + + /⋆ bit definitions for capabilities: ⋆/ + /⋆ can the hardware decode MPEG1 and/or MPEG2? ⋆/ + #define VIDEO_CAP_MPEG1 1 + #define VIDEO_CAP_MPEG2 2 + /⋆ can you send a system and/or program stream to video device? + (you still have to open the video and the audio device but only + send the stream to the video device) ⋆/ + #define VIDEO_CAP_SYS 4 + #define VIDEO_CAP_PROG 8 + /⋆ can the driver also handle SPU, NAVI and CSS encoded data? + (CSS API is not present yet) ⋆/ + #define VIDEO_CAP_SPU 16 + #define VIDEO_CAP_NAVI 32 + #define VIDEO_CAP_CSS 64 + +
+ +
+video system +A call to VIDEO_SET_SYSTEM sets the desired video system for TV output. The +following system types can be set: + + + typedef enum { + VIDEO_SYSTEM_PAL, + VIDEO_SYSTEM_NTSC, + VIDEO_SYSTEM_PALN, + VIDEO_SYSTEM_PALNc, + VIDEO_SYSTEM_PALM, + VIDEO_SYSTEM_NTSC60, + VIDEO_SYSTEM_PAL60, + VIDEO_SYSTEM_PALM60 + } video_system_t; + +
+ +
+struct video_highlight +Calling the ioctl VIDEO_SET_HIGHLIGHTS posts the SPU highlight information. The +call expects the following format for that information: + + + typedef + struct video_highlight { + boolean active; /⋆ 1=show highlight, 0=hide highlight ⋆/ + uint8_t contrast1; /⋆ 7- 4 Pattern pixel contrast ⋆/ + /⋆ 3- 0 Background pixel contrast ⋆/ + uint8_t contrast2; /⋆ 7- 4 Emphasis pixel-2 contrast ⋆/ + /⋆ 3- 0 Emphasis pixel-1 contrast ⋆/ + uint8_t color1; /⋆ 7- 4 Pattern pixel color ⋆/ + /⋆ 3- 0 Background pixel color ⋆/ + uint8_t color2; /⋆ 7- 4 Emphasis pixel-2 color ⋆/ + /⋆ 3- 0 Emphasis pixel-1 color ⋆/ + uint32_t ypos; /⋆ 23-22 auto action mode ⋆/ + /⋆ 21-12 start y ⋆/ + /⋆ 9- 0 end y ⋆/ + uint32_t xpos; /⋆ 23-22 button color number ⋆/ + /⋆ 21-12 start x ⋆/ + /⋆ 9- 0 end x ⋆/ + } video_highlight_t; + + +
+
+video SPU +Calling VIDEO_SET_SPU deactivates or activates SPU decoding, according to the +following format: + + + typedef + struct video_spu { + boolean active; + int stream_id; + } video_spu_t; + + +
+
+video SPU palette +The following structure is used to set the SPU palette by calling VIDEO_SPU_PALETTE: + + + typedef + struct video_spu_palette{ + int length; + uint8_t ⋆palette; + } video_spu_palette_t; + + +
+
+video NAVI pack +In order to get the navigational data the following structure has to be passed to the ioctl +VIDEO_GET_NAVI: + + + typedef + struct video_navi_pack{ + int length; /⋆ 0 ... 1024 ⋆/ + uint8_t data[1024]; + } video_navi_pack_t; + +
+ + +
+video attributes +The following attributes can be set by a call to VIDEO_SET_ATTRIBUTES: + + + typedef uint16_t video_attributes_t; + /⋆ bits: descr. ⋆/ + /⋆ 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) ⋆/ + /⋆ 13-12 TV system (0=525/60, 1=625/50) ⋆/ + /⋆ 11-10 Aspect ratio (0=4:3, 3=16:9) ⋆/ + /⋆ 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca ⋆/ + /⋆ 7 line 21-1 data present in GOP (1=yes, 0=no) ⋆/ + /⋆ 6 line 21-2 data present in GOP (1=yes, 0=no) ⋆/ + /⋆ 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 ⋆/ + /⋆ 2 source letterboxed (1=yes, 0=no) ⋆/ + /⋆ 0 film/camera mode (0=camera, 1=film (625/50 only)) ⋆/ + +
+ + +
+Video Function Calls + + +
+open() +DESCRIPTION + +
+This system call opens a named video device (e.g. /dev/dvb/adapter0/video0) + for subsequent use. +When an open() call has succeeded, the device will be ready for use. + The significance of blocking or non-blocking mode is described in the + documentation for functions where there is a difference. It does not affect the + semantics of the open() call itself. A device opened in blocking mode can later + be put into non-blocking mode (and vice versa) using the F_SETFL command + of the fcntl system call. This is a standard system call, documented in the Linux + manual page for fcntl. Only one user can open the Video Device in O_RDWR + mode. All other attempts to open the device in this mode will fail, and an + error-code will be returned. If the Video Device is opened in O_RDONLY + mode, the only ioctl call that can be used is VIDEO_GET_STATUS. All other + call will return an error code. + + + +SYNOPSIS + + +int open(const char ⋆deviceName, int flags); + + +PARAMETERS + + +const char + *deviceName + +Name of specific video device. + + +int flags + +A bit-wise OR of the following flags: + + + +O_RDONLY read-only access + + + +O_RDWR read/write access + + + +O_NONBLOCK open in non-blocking mode + + + +(blocking mode is the default) + + +ERRORS + + +ENODEV + +Device driver not loaded/available. + + +EINTERNAL + +Internal error. + + +EBUSY + +Device or resource busy. + + +EINVAL + +Invalid argument. + + + + +
+close() +DESCRIPTION + +
+This system call closes a previously opened video device. + + +SYNOPSIS + + +int close(int fd); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + + + +
+write() +DESCRIPTION + +
+This system call can only be used if VIDEO_SOURCE_MEMORY is selected + in the ioctl call VIDEO_SELECT_SOURCE. The data provided shall be in + PES format, unless the capability allows other formats. If O_NONBLOCK is + not specified the function will block until buffer space is available. The amount + of data to be transferred is implied by count. + + +SYNOPSIS + + +size_t write(int fd, const void ⋆buf, size_t count); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +void *buf + +Pointer to the buffer containing the PES data. + + +size_t count + +Size of buf. + + +ERRORS + + +EPERM + +Mode VIDEO_SOURCE_MEMORY not selected. + + +ENOMEM + +Attempted to write more data than the internal buffer can + hold. + + +EBADF + +fd is not a valid open file descriptor. + + + +
VIDEO_STOP +DESCRIPTION + +
+This ioctl call asks the Video Device to stop playing the current stream. + Depending on the input parameter, the screen can be blanked out or displaying + the last decoded frame. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_STOP, boolean + mode); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_STOP for this command. + + +Boolean mode + +Indicates how the screen shall be handled. + + + +TRUE: Blank screen when stop. + + + +FALSE: Show last decoded frame. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + + +
VIDEO_PLAY +DESCRIPTION + +
+This ioctl call asks the Video Device to start playing a video stream from the + selected source. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_PLAY); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_PLAY for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + + +
VIDEO_FREEZE +DESCRIPTION + +
+This ioctl call suspends the live video stream being played. Decoding + and playing are frozen. It is then possible to restart the decoding + and playing process of the video stream using the VIDEO_CONTINUE + command. If VIDEO_SOURCE_MEMORY is selected in the ioctl call + VIDEO_SELECT_SOURCE, the DVB subsystem will not decode any more + data until the ioctl call VIDEO_CONTINUE or VIDEO_PLAY is performed. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_FREEZE); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_FREEZE for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + + +
VIDEO_CONTINUE +DESCRIPTION + +
+This ioctl call restarts decoding and playing processes of the video stream + which was played before a call to VIDEO_FREEZE was made. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_CONTINUE); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_CONTINUE for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + + +
VIDEO_SELECT_SOURCE +DESCRIPTION + +
+This ioctl call informs the video device which source shall be used for the input + data. The possible sources are demux or memory. If memory is selected, the + data is fed to the video device through the write command. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_SELECT_SOURCE, + video_stream_source_t source); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SELECT_SOURCE for this command. + + +video_stream_source_t + source + +Indicates which source shall be used for the Video stream. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + + +
VIDEO_SET_BLANK +DESCRIPTION + +
+This ioctl call asks the Video Device to blank out the picture. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_SET_BLANK, boolean + mode); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_BLANK for this command. + + +boolean mode + +TRUE: Blank screen when stop. + + + +FALSE: Show last decoded frame. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + +EINVAL + +Illegal input parameter + + + +
VIDEO_GET_STATUS +DESCRIPTION + +
+This ioctl call asks the Video Device to return the current status of the device. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_GET_STATUS, struct + video_status ⋆status); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_GET_STATUS for this command. + + +struct video_status + *status + +Returns the current status of the Video Device. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error, possibly in the communication with the + DVB subsystem. + + +EFAULT + +status points to invalid address + + + +
VIDEO_GET_EVENT +DESCRIPTION + +
+This ioctl call returns an event of type video_event if available. If an event is + not available, the behavior depends on whether the device is in blocking or + non-blocking mode. In the latter case, the call fails immediately with errno + set to EWOULDBLOCK. In the former case, the call blocks until an event + becomes available. The standard Linux poll() and/or select() system calls can + be used with the device file descriptor to watch for new events. For select(), + the file descriptor should be included in the exceptfds argument, and for + poll(), POLLPRI should be specified as the wake-up condition. Read-only + permissions are sufficient for this ioctl call. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_GET_EVENT, struct + video_event ⋆ev); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_GET_EVENT for this command. + + +struct video_event + *ev + +Points to the location where the event, if any, is to be + stored. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EFAULT + +ev points to invalid address + + +EWOULDBLOCK + +There is no event pending, and the device is in + non-blocking mode. + + +EOVERFLOW + + + + +Overflow in event queue - one or more events were lost. + + + +
VIDEO_SET_DISPLAY_FORMAT +DESCRIPTION + +
+This ioctl call asks the Video Device to select the video format to be applied + by the MPEG chip on the video. + + +SYNOPSIS + + + int ioctl(fd, int request = + VIDEO_SET_DISPLAY_FORMAT, video_display_format_t + format); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_DISPLAY_FORMAT for this + command. + + +video_display_format_t + format + +Selects the video format to be used. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + +EINVAL + +Illegal parameter format. + + + +
VIDEO_STILLPICTURE +DESCRIPTION + +
+This ioctl call asks the Video Device to display a still picture (I-frame). The + input data shall contain an I-frame. If the pointer is NULL, then the current + displayed still picture is blanked. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_STILLPICTURE, + struct video_still_picture ⋆sp); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_STILLPICTURE for this command. + + +struct + video_still_picture + *sp + +Pointer to a location where an I-frame and size is stored. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + +EFAULT + +sp points to an invalid iframe. + + + +
VIDEO_FAST_FORWARD +DESCRIPTION + +
+This ioctl call asks the Video Device to skip decoding of N number of I-frames. + This call can only be used if VIDEO_SOURCE_MEMORY is selected. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_FAST_FORWARD, int + nFrames); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_FAST_FORWARD for this command. + + +int nFrames + +The number of frames to skip. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + +EPERM + +Mode VIDEO_SOURCE_MEMORY not selected. + + +EINVAL + +Illegal parameter format. + + + +
VIDEO_SLOWMOTION +DESCRIPTION + +
+This ioctl call asks the video device to repeat decoding frames N number of + times. This call can only be used if VIDEO_SOURCE_MEMORY is selected. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_SLOWMOTION, int + nFrames); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SLOWMOTION for this command. + + +int nFrames + +The number of times to repeat each frame. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINTERNAL + +Internal error. + + +EPERM + +Mode VIDEO_SOURCE_MEMORY not selected. + + +EINVAL + +Illegal parameter format. + + + +
VIDEO_GET_CAPABILITIES +DESCRIPTION + +
+This ioctl call asks the video device about its decoding capabilities. On success + it returns and integer which has bits set according to the defines in section ??. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_GET_CAPABILITIES, + unsigned int ⋆cap); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_GET_CAPABILITIES for this + command. + + +unsigned int *cap + +Pointer to a location where to store the capability + information. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EFAULT + +cap points to an invalid iframe. + + + +
VIDEO_SET_ID +DESCRIPTION + +
+This ioctl selects which sub-stream is to be decoded if a program or system + stream is sent to the video device. + + +SYNOPSIS + + +int ioctl(int fd, int request = VIDEO_SET_ID, int + id); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_ID for this command. + + +int id + +video sub-stream id + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINTERNAL + +Internal error. + + +EINVAL + +Invalid sub-stream id. + + + +
VIDEO_CLEAR_BUFFER +DESCRIPTION + +
+This ioctl call clears all video buffers in the driver and in the decoder hardware. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_CLEAR_BUFFER); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_CLEAR_BUFFER for this command. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + + +
VIDEO_SET_STREAMTYPE +DESCRIPTION + +
+This ioctl tells the driver which kind of stream to expect being written to it. If + this call is not used the default of video PES is used. Some drivers might not + support this call and always expect PES. + + +SYNOPSIS + + +int ioctl(fd, int request = VIDEO_SET_STREAMTYPE, + int type); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_STREAMTYPE for this command. + + +int type + +stream type + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +type is not a valid or supported stream type. + + + +
VIDEO_SET_FORMAT +DESCRIPTION + +
+This ioctl sets the screen format (aspect ratio) of the connected output device + (TV) so that the output of the decoder can be adjusted accordingly. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_FORMAT, + video_format_t format); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_FORMAT for this command. + + +video_format_t + format + +video format of TV as defined in section ??. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +format is not a valid video format. + + + +
VIDEO_SET_SYSTEM +DESCRIPTION + +
+This ioctl sets the television output format. The format (see section ??) may + vary from the color format of the displayed MPEG stream. If the hardware is + not able to display the requested format the call will return an error. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_SYSTEM , + video_system_t system); + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_FORMAT for this command. + + +video_system_t + system + +video system of TV output. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +system is not a valid or supported video system. + + + +
VIDEO_SET_HIGHLIGHT +DESCRIPTION + +
+This ioctl sets the SPU highlight information for the menu access of a DVD. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_HIGHLIGHT + ,video_highlight_t ⋆vhilite) + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_HIGHLIGHT for this command. + + +video_highlight_t + *vhilite + +SPU Highlight information according to section ??. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor. + + +EINVAL + +input is not a valid highlight setting. + + + +
VIDEO_SET_SPU +DESCRIPTION + +
+This ioctl activates or deactivates SPU decoding in a DVD input stream. It can + only be used, if the driver is able to handle a DVD stream. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_SPU , + video_spu_t ⋆spu) + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_SPU for this command. + + +video_spu_t *spu + +SPU decoding (de)activation and subid setting according + to section ??. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +input is not a valid spu setting or driver cannot handle + SPU. + + + +
VIDEO_SET_SPU_PALETTE +DESCRIPTION + +
+This ioctl sets the SPU color palette. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_SPU_PALETTE + ,video_spu_palette_t ⋆palette ) + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_SPU_PALETTE for this command. + + +video_spu_palette_t + *palette + +SPU palette according to section ??. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +input is not a valid palette or driver doesn’t handle SPU. + + + +
VIDEO_GET_NAVI +DESCRIPTION + +
+This ioctl returns navigational information from the DVD stream. This is + especially needed if an encoded stream has to be decoded by the hardware. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_GET_NAVI , + video_navi_pack_t ⋆navipack) + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_GET_NAVI for this command. + + +video_navi_pack_t + *navipack + +PCI or DSI pack (private stream 2) according to section + ??. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EFAULT + +driver is not able to return navigational information + + + +
VIDEO_SET_ATTRIBUTES +DESCRIPTION + +
+This ioctl is intended for DVD playback and allows you to set certain + information about the stream. Some hardware may not need this information, + but the call also tells the hardware to prepare for DVD playback. + + +SYNOPSIS + + + int ioctl(fd, int request = VIDEO_SET_ATTRIBUTE + ,video_attributes_t vattr) + + +PARAMETERS + + +int fd + +File descriptor returned by a previous call to open(). + + +int request + +Equals VIDEO_SET_ATTRIBUTE for this command. + + +video_attributes_t + vattr + +video attributes according to section ??. + + +ERRORS + + +EBADF + +fd is not a valid open file descriptor + + +EINVAL + +input is not a valid attribute setting. + + + \ No newline at end of file -- cgit v1.2.3 From d4dfbc77d05b36e9d4a7c12a0ace8336733df6ac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 6 Sep 2009 22:53:45 -0300 Subject: dvb-spec/sgml: A few fixes to make hg status/hg diff happy From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- .hgignore | 8 ++++++++ dvb-spec/sgml/ca.sgml | 2 +- dvb-spec/sgml/demux.sgml | 2 +- dvb-spec/sgml/devices.sgml | 0 dvb-spec/sgml/examples.sgml | 2 +- dvb-spec/sgml/kdapi.sgml | 2 +- dvb-spec/sgml/net.sgml | 2 +- dvb-spec/sgml/video.sgml | 2 +- 8 files changed, 14 insertions(+), 6 deletions(-) delete mode 100644 dvb-spec/sgml/devices.sgml diff --git a/.hgignore b/.hgignore index a48595f3a..bf4137aad 100644 --- a/.hgignore +++ b/.hgignore @@ -94,3 +94,11 @@ dvb-spec/dvbapi/dvbapi.ps dvb-spec/dvbapi/dvbapi.toc dvb-spec/dvbapi/dvbstb.ps dvb-spec/dvbapi/dvbstb.pst +dvb-spec/sgml/dvbapi/ +dvb-spec/sgml/dvbapi-single/ +dvb-spec/sgml/dvbapi.pdf$ +dvb-spec/sgml/entities.sgml$ +dvb-spec/sgml/html-build.stamp$ +dvb-spec/sgml/html-single-build.stamp$ +dvb-spec/sgml/pdf-build.stamp$ + diff --git a/dvb-spec/sgml/ca.sgml b/dvb-spec/sgml/ca.sgml index e2a70797d..b1f1d2fad 100644 --- a/dvb-spec/sgml/ca.sgml +++ b/dvb-spec/sgml/ca.sgml @@ -218,4 +218,4 @@ including linux/dvb/ca.h in your application. - \ No newline at end of file + diff --git a/dvb-spec/sgml/demux.sgml b/dvb-spec/sgml/demux.sgml index ad3448219..1b8c4e983 100644 --- a/dvb-spec/sgml/demux.sgml +++ b/dvb-spec/sgml/demux.sgml @@ -970,4 +970,4 @@ specified. Invalid stc number. - \ No newline at end of file + diff --git a/dvb-spec/sgml/devices.sgml b/dvb-spec/sgml/devices.sgml deleted file mode 100644 index e69de29bb..000000000 diff --git a/dvb-spec/sgml/examples.sgml b/dvb-spec/sgml/examples.sgml index fcdea820a..b89dceda6 100644 --- a/dvb-spec/sgml/examples.sgml +++ b/dvb-spec/sgml/examples.sgml @@ -362,4 +362,4 @@ necessary. - \ No newline at end of file + diff --git a/dvb-spec/sgml/kdapi.sgml b/dvb-spec/sgml/kdapi.sgml index f0684cfbc..6c67481ea 100644 --- a/dvb-spec/sgml/kdapi.sgml +++ b/dvb-spec/sgml/kdapi.sgml @@ -2306,4 +2306,4 @@ role="subsection">stop_filtering() - \ No newline at end of file + diff --git a/dvb-spec/sgml/net.sgml b/dvb-spec/sgml/net.sgml index 77557ae2a..94e388d94 100644 --- a/dvb-spec/sgml/net.sgml +++ b/dvb-spec/sgml/net.sgml @@ -9,4 +9,4 @@ application. DVB Net Data Types To be written… - \ No newline at end of file + diff --git a/dvb-spec/sgml/video.sgml b/dvb-spec/sgml/video.sgml index 5e35abcdf..7bb287e67 100644 --- a/dvb-spec/sgml/video.sgml +++ b/dvb-spec/sgml/video.sgml @@ -1968,4 +1968,4 @@ role="subsection">VIDEO_SET_ATTRIBUTES input is not a valid attribute setting. - \ No newline at end of file + -- cgit v1.2.3 From b90712cf41e75451c3b515ed41d2eda714db3de1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 7 Sep 2009 01:16:50 -0300 Subject: em28xx: ir-kbd-i2c initialization data should point to a persistent object From: Mauro Carvalho Chehab ir-kbd-i2c's ir_probe() function can be called much later (i.e. at ir-kbd-i2c module load), than the lifetime of a struct IR_i2c_init_data allocated off of the stack in cx18_i2c_new_ir() at registration time. Make sure we pass a pointer to a persistent IR_i2c_init_data object at i2c registration time. Thanks to Brain Rogers, Dustin Mitchell, Andy Walls and Jean Delvare to rise this question. Before this patch, if ir-kbd-i2c were probed after em28xx, trash data were used. After the patch, no matter what order, it is properly reported as tested by me: input: i2c IR (i2c IR (EM2840 Hauppaug as /class/input/input10 ir-kbd-i2c: i2c IR (i2c IR (EM2840 Hauppaug detected at i2c-4/4-0030/ir0 [em28xx #0] Priority: high Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 34 ++++++++++++------------- linux/drivers/media/video/em28xx/em28xx.h | 4 +++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 656604dc9..d12c8c890 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2275,11 +2275,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) if (disable_ir) { ir->get_key = NULL; - return ; + return; } #else - struct i2c_board_info info; - struct IR_i2c_init_data init_data; const unsigned short addr_list[] = { 0x30, 0x47, I2C_CLIENT_END }; @@ -2287,9 +2285,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) if (disable_ir) return; - memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + memset(&dev->info, 0, sizeof(&dev->info)); + memset(&dev->init_data, 0, sizeof(dev->init_data)); + strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); #endif /* detect & configure */ @@ -2306,9 +2304,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) snprintf(ir->name, sizeof(ir->name), "i2c IR (EM28XX Terratec)"); #else - init_data.ir_codes = &ir_codes_em_terratec_table; - init_data.get_key = em28xx_get_key_terratec; - init_data.name = "i2c IR (EM28XX Terratec)"; + dev->init_data.ir_codes = &ir_codes_em_terratec_table; + dev->init_data.get_key = em28xx_get_key_terratec; + dev->init_data.name = "i2c IR (EM28XX Terratec)"; #endif break; case (EM2820_BOARD_PINNACLE_USB_2): @@ -2318,9 +2316,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) snprintf(ir->name, sizeof(ir->name), "i2c IR (EM28XX Pinnacle PCTV)"); #else - init_data.ir_codes = &ir_codes_pinnacle_grey_table; - init_data.get_key = em28xx_get_key_pinnacle_usb_grey; - init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; + dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; + dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; + dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; #endif break; case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): @@ -2330,9 +2328,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) snprintf(ir->name, sizeof(ir->name), "i2c IR (EM2840 Hauppauge)"); #else - init_data.ir_codes = &ir_codes_hauppauge_new_table; - init_data.get_key = em28xx_get_key_em_haup; - init_data.name = "i2c IR (EM2840 Hauppauge)"; + dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; + dev->init_data.get_key = em28xx_get_key_em_haup; + dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; #endif break; case (EM2820_BOARD_MSI_VOX_USB_2): @@ -2346,9 +2344,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) - if (init_data.name) - info.platform_data = &init_data; - i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); + if (dev->init_data.name) + dev->info.platform_data = &dev->init_data; + i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); #endif } diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index a603d981b..e5d6b0695 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -606,6 +606,10 @@ struct em28xx { struct delayed_work sbutton_query_work; struct em28xx_dvb *dvb; + + /* I2C keyboard data */ + struct i2c_board_info info; + struct IR_i2c_init_data init_data; }; struct em28xx_ops { -- cgit v1.2.3 From bc8e54076f8ea66c087fbf2e293d9fd3439f358c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 7 Sep 2009 01:30:57 -0300 Subject: changeset: 12701:86bff049a6fb From: Mauro Carvalho Chehab tag: tip user: Mauro Carvalho Chehab date: Mon Sep 07 01:30:10 2009 -0300 files: linux/drivers/media/video/saa7134/saa7134-input.c linux/drivers/media/video/saa7134/saa7134.h description: SAA7134: ir-kbd-i2c initialization data should point to a persistent object ir-kbd-i2c's ir_probe() function can be called much later (i.e. at ir-kbd-i2c module load), than the lifetime of a struct IR_i2c_init_data allocated off of the stack in cx18_i2c_new_ir() at registration time. Make sure we pass a pointer to a persistent IR_i2c_init_data object at i2c registration time. Thanks to Brain Rogers, Dustin Mitchell, Andy Walls and Jean Delvare to rise this question. Before this patch, if ir-kbd-i2c were probed after SAA7134, trash data were used. Compile tested only, but the patch is identical to em28xx one. So, it should work properly. Priority: high Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-input.c | 60 +++++++++++------------ linux/drivers/media/video/saa7134/saa7134.h | 4 ++ 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/linux/drivers/media/video/saa7134/saa7134-input.c b/linux/drivers/media/video/saa7134/saa7134-input.c index 261c86639..153fb3c5b 100644 --- a/linux/drivers/media/video/saa7134/saa7134-input.c +++ b/linux/drivers/media/video/saa7134/saa7134-input.c @@ -741,8 +741,6 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) #endif { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) - struct i2c_board_info info; - struct IR_i2c_init_data init_data; const unsigned short addr_list[] = { 0x7a, 0x47, 0x71, 0x2d, I2C_CLIENT_END @@ -769,9 +767,9 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) - memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + memset(&dev->info, 0, sizeof(dev->info)); + memset(&dev->init_data, 0, sizeof(dev->init_data)); + strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); #endif switch (dev->board) { @@ -780,25 +778,25 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV"); #else - init_data.name = "Pinnacle PCTV"; + dev->init_data.name = "Pinnacle PCTV"; #endif if (pinnacle_remote == 0) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ir->get_key = get_key_pinnacle_color; ir->ir_codes = &ir_codes_pinnacle_color_table; #else - init_data.get_key = get_key_pinnacle_color; - init_data.ir_codes = &ir_codes_pinnacle_color_table; - info.addr = 0x47; + dev->init_data.get_key = get_key_pinnacle_color; + dev->init_data.ir_codes = &ir_codes_pinnacle_color_table; + dev->info.addr = 0x47; #endif } else { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ir->get_key = get_key_pinnacle_grey; ir->ir_codes = &ir_codes_pinnacle_grey_table; #else - init_data.get_key = get_key_pinnacle_grey; - init_data.ir_codes = &ir_codes_pinnacle_grey_table; - info.addr = 0x47; + dev->init_data.get_key = get_key_pinnacle_grey; + dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; + dev->info.addr = 0x47; #endif } break; @@ -808,9 +806,9 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) ir->get_key = get_key_purpletv; ir->ir_codes = &ir_codes_purpletv_table; #else - init_data.name = "Purple TV"; - init_data.get_key = get_key_purpletv; - init_data.ir_codes = &ir_codes_purpletv_table; + dev->init_data.name = "Purple TV"; + dev->init_data.get_key = get_key_purpletv; + dev->init_data.ir_codes = &ir_codes_purpletv_table; #endif break; case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: @@ -819,10 +817,10 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) ir->get_key = get_key_msi_tvanywhere_plus; ir->ir_codes = &ir_codes_msi_tvanywhere_plus_table; #else - init_data.name = "MSI TV@nywhere Plus"; - init_data.get_key = get_key_msi_tvanywhere_plus; - init_data.ir_codes = &ir_codes_msi_tvanywhere_plus_table; - info.addr = 0x30; + dev->init_data.name = "MSI TV@nywhere Plus"; + dev->init_data.get_key = get_key_msi_tvanywhere_plus; + dev->init_data.ir_codes = &ir_codes_msi_tvanywhere_plus_table; + dev->info.addr = 0x30; /* MSI TV@nywhere Plus controller doesn't seem to respond to probes unless we read something from an existing device. Weird... @@ -839,9 +837,9 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) ir->get_key = get_key_hvr1110; ir->ir_codes = &ir_codes_hauppauge_new_table; #else - init_data.name = "HVR 1110"; - init_data.get_key = get_key_hvr1110; - init_data.ir_codes = &ir_codes_hauppauge_new_table; + dev->init_data.name = "HVR 1110"; + dev->init_data.get_key = get_key_hvr1110; + dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; #endif break; case SAA7134_BOARD_BEHOLD_607FM_MK3: @@ -862,9 +860,9 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) ir->get_key = get_key_beholdm6xx; ir->ir_codes = &ir_codes_behold_table; #else - init_data.name = "BeholdTV"; - init_data.get_key = get_key_beholdm6xx; - init_data.ir_codes = &ir_codes_behold_table; + dev->init_data.name = "BeholdTV"; + dev->init_data.get_key = get_key_beholdm6xx; + dev->init_data.ir_codes = &ir_codes_behold_table; #endif break; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) @@ -873,22 +871,22 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) #else case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: - info.addr = 0x40; + dev->info.addr = 0x40; #endif break; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) - if (init_data.name) - info.platform_data = &init_data; + if (dev->init_data.name) + dev->info.platform_data = &dev->init_data; /* No need to probe if address is known */ - if (info.addr) { - i2c_new_device(&dev->i2c_adap, &info); + if (dev->info.addr) { + i2c_new_device(&dev->i2c_adap, &dev->info); return; } /* Address not known, fallback to probing */ - i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); + i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); #endif } diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 8c164bc79..d01281d1e 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -594,6 +594,10 @@ struct saa7134_dev { int nosignal; unsigned int insuspend; + /* I2C keyboard data */ + struct i2c_board_info info; + struct IR_i2c_init_data init_data; + /* SAA7134_MPEG_* */ struct saa7134_ts ts; struct saa7134_dmaqueue ts_q; -- cgit v1.2.3 From f74e25d0120dfd079832a3224fa46dec4105b3ad Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 7 Sep 2009 01:39:49 -0300 Subject: make_kconfig.pl: properly initialize DVB_MAX_ADAPTERS From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l/scripts/make_kconfig.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/v4l/scripts/make_kconfig.pl b/v4l/scripts/make_kconfig.pl index cfe53a636..4690f6ab4 100755 --- a/v4l/scripts/make_kconfig.pl +++ b/v4l/scripts/make_kconfig.pl @@ -592,6 +592,7 @@ disable_config('DVB_AV7110_FIRMWARE'); disable_config('DVB_CINERGYT2_TUNING'); disable_config('VIDEO_HELPER_CHIPS_AUTO'); disable_config('VIDEO_FIXED_MINOR_RANGES'); +$intopt { "DVB_MAX_ADAPTERS" } = 8; # Check dependencies my %newconfig = checkdeps(); -- cgit v1.2.3 From f3fb970832182809d9bf8b397fe34f70404e51fd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 7 Sep 2009 12:38:46 -0300 Subject: building system: fix compilation with kernels older than 2.6.30 From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | 8 ++++++-- linux/drivers/media/video/em28xx/em28xx.h | 2 ++ linux/drivers/media/video/saa7134/saa7134.h | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index df72c8637..76c281b9d 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -12,6 +12,7 @@ #include #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) static int dvb_usb_getkeycode(struct input_dev *dev, int scancode, int *keycode) { @@ -76,6 +77,7 @@ static int dvb_usb_setkeycode(struct input_dev *dev, return -EINVAL; } +#endif /* Remote-control poll function - called every dib->rc_query_interval ms to see * whether the remote control has received anything. @@ -189,11 +191,11 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) usb_to_input_id(d->udev, &input_dev->id); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) input_dev->dev.parent = &d->udev->dev; + input_dev->getkeycode = dvb_usb_getkeycode; + input_dev->setkeycode = dvb_usb_setkeycode; #else input_dev->cdev.dev = &d->udev->dev; #endif - input_dev->getkeycode = dvb_usb_getkeycode; - input_dev->setkeycode = dvb_usb_setkeycode; /* set the bits for the keys */ deb_rc("key map size: %d\n", d->props.rc_key_map_size); @@ -211,7 +213,9 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) input_dev->rep[REP_PERIOD] = d->props.rc_interval; input_dev->rep[REP_DELAY] = d->props.rc_interval + 150; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) input_set_drvdata(input_dev, d); +#endif err = input_register_device(input_dev); if (err) { diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index e5d6b0695..2d0aa6edb 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -607,9 +607,11 @@ struct em28xx { struct em28xx_dvb *dvb; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) /* I2C keyboard data */ struct i2c_board_info info; struct IR_i2c_init_data init_data; +#endif }; struct em28xx_ops { diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index d01281d1e..1bf2837b4 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -595,8 +595,10 @@ struct saa7134_dev { unsigned int insuspend; /* I2C keyboard data */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) struct i2c_board_info info; struct IR_i2c_init_data init_data; +#endif /* SAA7134_MPEG_* */ struct saa7134_ts ts; -- cgit v1.2.3 From f5d442837683ba80a9c7ef89e51df2677ec99ae0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Sep 2009 14:04:41 -0300 Subject: em28xx: properly load ir-kbd-i2c when needed From: Mauro Carvalho Chehab Currently, the logic to load ir i2c ancillary module is broken. It is associated to Hauppauge devices with IR flag on their eeprom, no matter if the device uses i2c or em28xx direct IR support. That's wrong. Instead, add a flag to the boards that use i2c IR chips and load the module only for those devices and if ir is not disabled. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 14 +++++++++----- linux/drivers/media/video/em28xx/em28xx.h | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index d12c8c890..bfee6c39b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -314,6 +314,7 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_TERRATEC_CINERGY_250] = { .name = "Terratec Cinergy 250 USB", .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .has_ir_i2c = 1, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA711X, .input = { { @@ -333,6 +334,7 @@ struct em28xx_board em28xx_boards[] = { [EM2820_BOARD_PINNACLE_USB_2] = { .name = "Pinnacle PCTV USB 2", .tuner_type = TUNER_LG_PAL_NEW_TAPC, + .has_ir_i2c = 1, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA711X, .input = { { @@ -357,6 +359,7 @@ struct em28xx_board em28xx_boards[] = { TDA9887_PORT2_ACTIVE, .decoder = EM28XX_TVP5150, .has_msp34xx = 1, + .has_ir_i2c = 1, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -1004,6 +1007,7 @@ struct em28xx_board em28xx_boards[] = { [EM2800_BOARD_TERRATEC_CINERGY_200] = { .name = "Terratec Cinergy 200 USB", .is_em2800 = 1, + .has_ir_i2c = 1, .tuner_type = TUNER_LG_PAL_NEW_TAPC, .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA711X, @@ -2383,7 +2387,7 @@ void em28xx_card_setup(struct em28xx *dev) case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: { struct tveeprom tv; -#ifdef CONFIG_MODULES +#if defined(CONFIG_MODULES) && defined(MODULE) request_module("tveeprom"); #endif /* Call first TVeeprom */ @@ -2397,10 +2401,6 @@ void em28xx_card_setup(struct em28xx *dev) dev->i2s_speed = 2048000; dev->board.has_msp34xx = 1; } -#ifdef CONFIG_MODULES - if (tv.has_ir) - request_module("ir-kbd-i2c"); -#endif break; } case EM2882_BOARD_KWORLD_ATSC_315U: @@ -2441,6 +2441,10 @@ void em28xx_card_setup(struct em28xx *dev) break; } +#if defined(CONFIG_MODULES) && defined(MODULE) + if (dev->board.has_ir_i2c && !disable_ir) + request_module("ir-kbd-i2c"); +#endif if (dev->board.has_snapshot_button) em28xx_register_snapshot_button(dev); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 2d0aa6edb..3614402da 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -401,6 +401,7 @@ struct em28xx_board { unsigned int is_webcam:1; unsigned int no_audio:1; unsigned int valid:1; + unsigned int has_ir_i2c:1; unsigned char xclk, i2c_speed; unsigned char radio_addr; -- cgit v1.2.3 From 6ed2bc52272241302be2b6c9f04cbb99abe799d6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Sep 2009 14:07:05 -0300 Subject: em28xx: Cleanups at ir_i2c handler From: Mauro Carvalho Chehab There are some extra parenthesis at the clauses, and some switch() tests for boards that don't have i2c ir. Remove those extra code. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/em28xx/em28xx-cards.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index bfee6c39b..7e014ceb0 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -2296,12 +2296,8 @@ void em28xx_register_i2c_ir(struct em28xx *dev) /* detect & configure */ switch (dev->model) { - case (EM2800_BOARD_UNKNOWN): - break; - case (EM2820_BOARD_UNKNOWN): - break; - case (EM2800_BOARD_TERRATEC_CINERGY_200): - case (EM2820_BOARD_TERRATEC_CINERGY_250): + case EM2800_BOARD_TERRATEC_CINERGY_200: + case EM2820_BOARD_TERRATEC_CINERGY_250: #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ir->ir_codes = &ir_codes_em_terratec_table; ir->get_key = em28xx_get_key_terratec; @@ -2313,7 +2309,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) dev->init_data.name = "i2c IR (EM28XX Terratec)"; #endif break; - case (EM2820_BOARD_PINNACLE_USB_2): + case EM2820_BOARD_PINNACLE_USB_2: #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ir->ir_codes = &ir_codes_pinnacle_grey_table; ir->get_key = em28xx_get_key_pinnacle_usb_grey; @@ -2325,7 +2321,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; #endif break; - case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2): + case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30) ir->ir_codes = &ir_codes_hauppauge_new_table; ir->get_key = em28xx_get_key_em_haup; @@ -2337,14 +2333,6 @@ void em28xx_register_i2c_ir(struct em28xx *dev) dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; #endif break; - case (EM2820_BOARD_MSI_VOX_USB_2): - break; - case (EM2800_BOARD_LEADTEK_WINFAST_USBII): - break; - case (EM2800_BOARD_KWORLD_USB2800): - break; - case (EM2800_BOARD_GRABBEEX_USB2800): - break; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) -- cgit v1.2.3 From a8f908ae4e4df8c18b0fe87bfae722392b5429d8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 10 Sep 2009 19:58:39 +0200 Subject: v4l: Merge drivers/staging/go7007 in v4l-dvb. From: Hans Verkuil Having go7007 as part of v4l-dvb makes it easier to continue developing this driver. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/staging/go7007/Kconfig | 37 + linux/drivers/staging/go7007/Makefile | 27 + linux/drivers/staging/go7007/README | 11 + linux/drivers/staging/go7007/go7007-driver.c | 682 +++++++++ linux/drivers/staging/go7007/go7007-fw.c | 1638 +++++++++++++++++++++ linux/drivers/staging/go7007/go7007-i2c.c | 225 +++ linux/drivers/staging/go7007/go7007-priv.h | 282 ++++ linux/drivers/staging/go7007/go7007-usb.c | 1287 +++++++++++++++++ linux/drivers/staging/go7007/go7007-v4l2.c | 1876 +++++++++++++++++++++++++ linux/drivers/staging/go7007/go7007.h | 114 ++ linux/drivers/staging/go7007/go7007.txt | 481 +++++++ linux/drivers/staging/go7007/s2250-board.c | 622 ++++++++ linux/drivers/staging/go7007/s2250-loader.c | 189 +++ linux/drivers/staging/go7007/s2250-loader.h | 24 + linux/drivers/staging/go7007/saa7134-go7007.c | 532 +++++++ linux/drivers/staging/go7007/snd-go7007.c | 305 ++++ linux/drivers/staging/go7007/wis-i2c.h | 47 + linux/drivers/staging/go7007/wis-ov7640.c | 107 ++ linux/drivers/staging/go7007/wis-saa7113.c | 335 +++++ linux/drivers/staging/go7007/wis-saa7115.c | 468 ++++++ linux/drivers/staging/go7007/wis-sony-tuner.c | 719 ++++++++++ linux/drivers/staging/go7007/wis-tw2804.c | 358 +++++ linux/drivers/staging/go7007/wis-tw9903.c | 339 +++++ linux/drivers/staging/go7007/wis-uda1342.c | 113 ++ v4l/Kconfig.staging | 66 + v4l/Makefile | 2 + v4l/Makefile.staging | 39 + v4l/scripts/make_kconfig.pl | 1 + 28 files changed, 10926 insertions(+) create mode 100644 linux/drivers/staging/go7007/Kconfig create mode 100644 linux/drivers/staging/go7007/Makefile create mode 100644 linux/drivers/staging/go7007/README create mode 100644 linux/drivers/staging/go7007/go7007-driver.c create mode 100644 linux/drivers/staging/go7007/go7007-fw.c create mode 100644 linux/drivers/staging/go7007/go7007-i2c.c create mode 100644 linux/drivers/staging/go7007/go7007-priv.h create mode 100644 linux/drivers/staging/go7007/go7007-usb.c create mode 100644 linux/drivers/staging/go7007/go7007-v4l2.c create mode 100644 linux/drivers/staging/go7007/go7007.h create mode 100644 linux/drivers/staging/go7007/go7007.txt create mode 100644 linux/drivers/staging/go7007/s2250-board.c create mode 100644 linux/drivers/staging/go7007/s2250-loader.c create mode 100644 linux/drivers/staging/go7007/s2250-loader.h create mode 100644 linux/drivers/staging/go7007/saa7134-go7007.c create mode 100644 linux/drivers/staging/go7007/snd-go7007.c create mode 100644 linux/drivers/staging/go7007/wis-i2c.h create mode 100644 linux/drivers/staging/go7007/wis-ov7640.c create mode 100644 linux/drivers/staging/go7007/wis-saa7113.c create mode 100644 linux/drivers/staging/go7007/wis-saa7115.c create mode 100644 linux/drivers/staging/go7007/wis-sony-tuner.c create mode 100644 linux/drivers/staging/go7007/wis-tw2804.c create mode 100644 linux/drivers/staging/go7007/wis-tw9903.c create mode 100644 linux/drivers/staging/go7007/wis-uda1342.c create mode 100644 v4l/Kconfig.staging create mode 100644 v4l/Makefile.staging diff --git a/linux/drivers/staging/go7007/Kconfig b/linux/drivers/staging/go7007/Kconfig new file mode 100644 index 000000000..ca6ade6c4 --- /dev/null +++ b/linux/drivers/staging/go7007/Kconfig @@ -0,0 +1,37 @@ +config VIDEO_GO7007 + tristate "Go 7007 support" + depends on VIDEO_DEV && PCI && I2C && INPUT + depends on SND + select VIDEOBUF_DMA_SG + select VIDEO_IR + select VIDEO_TUNER + select VIDEO_TVEEPROM + select SND_PCM + select CRC32 + default N + ---help--- + This is a video4linux driver for some weird device... + + To compile this driver as a module, choose M here: the + module will be called go7007 + +config VIDEO_GO7007_USB + tristate "Go 7007 USB support" + depends on VIDEO_GO7007 && USB + default N + ---help--- + This is a video4linux driver for some weird device... + + To compile this driver as a module, choose M here: the + module will be called go7007-usb + +config VIDEO_GO7007_USB_S2250_BOARD + tristate "Sensoray 2250/2251 support" + depends on VIDEO_GO7007_USB && DVB_USB + default N + ---help--- + This is a video4linux driver for the Sensoray 2250/2251 device + + To compile this driver as a module, choose M here: the + module will be called s2250-board + diff --git a/linux/drivers/staging/go7007/Makefile b/linux/drivers/staging/go7007/Makefile new file mode 100644 index 000000000..e514b4af6 --- /dev/null +++ b/linux/drivers/staging/go7007/Makefile @@ -0,0 +1,27 @@ +#obj-m += go7007.o go7007-usb.o snd-go7007.o wis-saa7115.o wis-tw9903.o \ + wis-uda1342.o wis-sony-tuner.o wis-saa7113.o wis-ov7640.o \ + wis-tw2804.o + + +obj-$(CONFIG_VIDEO_GO7007) += go7007.o +obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o +obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o + +go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ + snd-go7007.o wis-saa7113.o + +s2250-objs += s2250-board.o s2250-loader.o + +# Uncompile when the saa7134 patches get into upstream +#ifneq ($(CONFIG_VIDEO_SAA7134),) +#obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o +#EXTRA_CFLAGS += -Idrivers/media/video/saa7134 +#endif + +ifneq ($(CONFIG_VIDEO_GO7007_USB_S2250_BOARD),) +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb +endif + +EXTRA_CFLAGS += -Idrivers/staging/saa7134 +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core diff --git a/linux/drivers/staging/go7007/README b/linux/drivers/staging/go7007/README new file mode 100644 index 000000000..48f447637 --- /dev/null +++ b/linux/drivers/staging/go7007/README @@ -0,0 +1,11 @@ +Todo: + - checkpatch.pl cleanups + - sparse cleanups + - lots of little modules, should be merged together + and added to the build. + - testing? + - handle churn in v4l layer. + +Please send patchs to Greg Kroah-Hartman and Cc: Ross +Cohen as well. + diff --git a/linux/drivers/staging/go7007/go7007-driver.c b/linux/drivers/staging/go7007/go7007-driver.c new file mode 100644 index 000000000..77b1e769a --- /dev/null +++ b/linux/drivers/staging/go7007/go7007-driver.c @@ -0,0 +1,682 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "go7007-priv.h" +#include "wis-i2c.h" + +/* + * Wait for an interrupt to be delivered from the GO7007SB and return + * the associated value and data. + * + * Must be called with the hw_lock held. + */ +int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data) +{ + go->interrupt_available = 0; + go->hpi_ops->read_interrupt(go); + if (wait_event_timeout(go->interrupt_waitq, + go->interrupt_available, 5*HZ) < 0) { + printk(KERN_ERR "go7007: timeout waiting for read interrupt\n"); + return -1; + } + if (!go->interrupt_available) + return -1; + go->interrupt_available = 0; + *value = go->interrupt_value & 0xfffe; + *data = go->interrupt_data; + return 0; +} +EXPORT_SYMBOL(go7007_read_interrupt); + +/* + * Read a register/address on the GO7007SB. + * + * Must be called with the hw_lock held. + */ +int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data) +{ + int count = 100; + u16 value; + + if (go7007_write_interrupt(go, 0x0010, addr) < 0) + return -EIO; + while (count-- > 0) { + if (go7007_read_interrupt(go, &value, data) == 0 && + value == 0xa000) + return 0; + } + return -EIO; +} +EXPORT_SYMBOL(go7007_read_addr); + +/* + * Send the boot firmware to the encoder, which just wakes it up and lets + * us talk to the GPIO pins and on-board I2C adapter. + * + * Must be called with the hw_lock held. + */ +static int go7007_load_encoder(struct go7007 *go) +{ + const struct firmware *fw_entry; + char fw_name[] = "go7007fw.bin"; + void *bounce; + int fw_len, rv = 0; + u16 intr_val, intr_data; + + if (request_firmware(&fw_entry, fw_name, go->dev)) { + printk(KERN_ERR + "go7007: unable to load firmware from file \"%s\"\n", + fw_name); + return -1; + } + if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) { + printk(KERN_ERR "go7007: file \"%s\" does not appear to be " + "go7007 firmware\n", fw_name); + release_firmware(fw_entry); + return -1; + } + fw_len = fw_entry->size - 16; + bounce = kmalloc(fw_len, GFP_KERNEL); + if (bounce == NULL) { + printk(KERN_ERR "go7007: unable to allocate %d bytes for " + "firmware transfer\n", fw_len); + release_firmware(fw_entry); + return -1; + } + memcpy(bounce, fw_entry->data + 16, fw_len); + release_firmware(fw_entry); + if (go7007_interface_reset(go) < 0 || + go7007_send_firmware(go, bounce, fw_len) < 0 || + go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || + (intr_val & ~0x1) != 0x5a5a) { + printk(KERN_ERR "go7007: error transferring firmware\n"); + rv = -1; + } + kfree(bounce); + return rv; +} + +/* + * Boot the encoder and register the I2C adapter if requested. Do the + * minimum initialization necessary, since the board-specific code may + * still need to probe the board ID. + * + * Must NOT be called with the hw_lock held. + */ +int go7007_boot_encoder(struct go7007 *go, int init_i2c) +{ + int ret; + + down(&go->hw_lock); + ret = go7007_load_encoder(go); + up(&go->hw_lock); + if (ret < 0) + return -1; + if (!init_i2c) + return 0; + if (go7007_i2c_init(go) < 0) + return -1; + go->i2c_adapter_online = 1; + return 0; +} +EXPORT_SYMBOL(go7007_boot_encoder); + +/* + * Configure any hardware-related registers in the GO7007, such as GPIO + * pins and bus parameters, which are board-specific. This assumes + * the boot firmware has already been downloaded. + * + * Must be called with the hw_lock held. + */ +static int go7007_init_encoder(struct go7007 *go) +{ + if (go->board_info->audio_flags & GO7007_AUDIO_I2S_MASTER) { + go7007_write_addr(go, 0x1000, 0x0811); + go7007_write_addr(go, 0x1000, 0x0c11); + } + if (go->board_id == GO7007_BOARDID_MATRIX_REV) { + /* Set GPIO pin 0 to be an output (audio clock control) */ + go7007_write_addr(go, 0x3c82, 0x0001); + go7007_write_addr(go, 0x3c80, 0x00fe); + } + return 0; +} + +/* + * Send the boot firmware to the GO7007 and configure the registers. This + * is the only way to stop the encoder once it has started streaming video. + * + * Must be called with the hw_lock held. + */ +int go7007_reset_encoder(struct go7007 *go) +{ + if (go7007_load_encoder(go) < 0) + return -1; + return go7007_init_encoder(go); +} + +/* + * Attempt to instantiate an I2C client by ID, probably loading a module. + */ +static int init_i2c_module(struct i2c_adapter *adapter, const char *type, + int id, int addr) +{ + struct i2c_board_info info; + char *modname; + + switch (id) { + case I2C_DRIVERID_WIS_SAA7115: + modname = "wis-saa7115"; + break; + case I2C_DRIVERID_WIS_SAA7113: + modname = "wis-saa7113"; + break; + case I2C_DRIVERID_WIS_UDA1342: + modname = "wis-uda1342"; + break; + case I2C_DRIVERID_WIS_SONY_TUNER: + modname = "wis-sony-tuner"; + break; + case I2C_DRIVERID_WIS_TW9903: + modname = "wis-tw9903"; + break; + case I2C_DRIVERID_WIS_TW2804: + modname = "wis-tw2804"; + break; + case I2C_DRIVERID_WIS_OV7640: + modname = "wis-ov7640"; + break; + case I2C_DRIVERID_S2250: + modname = "s2250-board"; + break; + default: + modname = NULL; + break; + } + if (modname != NULL) + request_module(modname); + + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = addr; + strlcpy(info.type, type, I2C_NAME_SIZE); + if (!i2c_new_device(adapter, &info)) + return 0; + if (modname != NULL) + printk(KERN_INFO + "go7007: probing for module %s failed\n", modname); + else + printk(KERN_INFO + "go7007: sensor %u seems to be unsupported!\n", id); + return -1; +} + +/* + * Finalize the GO7007 hardware setup, register the on-board I2C adapter + * (if used on this board), load the I2C client driver for the sensor + * (SAA7115 or whatever) and other devices, and register the ALSA and V4L2 + * interfaces. + * + * Must NOT be called with the hw_lock held. + */ +int go7007_register_encoder(struct go7007 *go) +{ + int i, ret; + + printk(KERN_INFO "go7007: registering new %s\n", go->name); + + down(&go->hw_lock); + ret = go7007_init_encoder(go); + up(&go->hw_lock); + if (ret < 0) + return -1; + + if (!go->i2c_adapter_online && + go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) { + if (go7007_i2c_init(go) < 0) + return -1; + go->i2c_adapter_online = 1; + } + if (go->i2c_adapter_online) { + for (i = 0; i < go->board_info->num_i2c_devs; ++i) + init_i2c_module(&go->i2c_adapter, + go->board_info->i2c_devs[i].type, + go->board_info->i2c_devs[i].id, + go->board_info->i2c_devs[i].addr); + if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) + i2c_clients_command(&go->i2c_adapter, + DECODER_SET_CHANNEL, &go->channel_number); + } + if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) { + go->audio_enabled = 1; + go7007_snd_init(go); + } + return go7007_v4l2_init(go); +} +EXPORT_SYMBOL(go7007_register_encoder); + +/* + * Send the encode firmware to the encoder, which will cause it + * to immediately start delivering the video and audio streams. + * + * Must be called with the hw_lock held. + */ +int go7007_start_encoder(struct go7007 *go) +{ + u8 *fw; + int fw_len, rv = 0, i; + u16 intr_val, intr_data; + + go->modet_enable = 0; + if (!go->dvd_mode) + for (i = 0; i < 4; ++i) { + if (go->modet[i].enable) { + go->modet_enable = 1; + continue; + } + go->modet[i].pixel_threshold = 32767; + go->modet[i].motion_threshold = 32767; + go->modet[i].mb_threshold = 32767; + } + + if (go7007_construct_fw_image(go, &fw, &fw_len) < 0) + return -1; + + if (go7007_send_firmware(go, fw, fw_len) < 0 || + go7007_read_interrupt(go, &intr_val, &intr_data) < 0) { + printk(KERN_ERR "go7007: error transferring firmware\n"); + rv = -1; + goto start_error; + } + + go->state = STATE_DATA; + go->parse_length = 0; + go->seen_frame = 0; + if (go7007_stream_start(go) < 0) { + printk(KERN_ERR "go7007: error starting stream transfer\n"); + rv = -1; + goto start_error; + } + +start_error: + kfree(fw); + return rv; +} + +/* + * Store a byte in the current video buffer, if there is one. + */ +static inline void store_byte(struct go7007_buffer *gobuf, u8 byte) +{ + if (gobuf != NULL && gobuf->bytesused < GO7007_BUF_SIZE) { + unsigned int pgidx = gobuf->offset >> PAGE_SHIFT; + unsigned int pgoff = gobuf->offset & ~PAGE_MASK; + + *((u8 *)page_address(gobuf->pages[pgidx]) + pgoff) = byte; + ++gobuf->offset; + ++gobuf->bytesused; + } +} + +/* + * Deliver the last video buffer and get a new one to start writing to. + */ +static void frame_boundary(struct go7007 *go) +{ + struct go7007_buffer *gobuf; + int i; + + if (go->active_buf) { + if (go->active_buf->modet_active) { + if (go->active_buf->bytesused + 216 < GO7007_BUF_SIZE) { + for (i = 0; i < 216; ++i) + store_byte(go->active_buf, + go->active_map[i]); + go->active_buf->bytesused -= 216; + } else + go->active_buf->modet_active = 0; + } + go->active_buf->state = BUF_STATE_DONE; + wake_up_interruptible(&go->frame_waitq); + go->active_buf = NULL; + } + list_for_each_entry(gobuf, &go->stream, stream) + if (gobuf->state == BUF_STATE_QUEUED) { + gobuf->seq = go->next_seq; + do_gettimeofday(&gobuf->timestamp); + go->active_buf = gobuf; + break; + } + ++go->next_seq; +} + +static void write_bitmap_word(struct go7007 *go) +{ + int x, y, i, stride = ((go->width >> 4) + 7) >> 3; + + for (i = 0; i < 16; ++i) { + y = (((go->parse_length - 1) << 3) + i) / (go->width >> 4); + x = (((go->parse_length - 1) << 3) + i) % (go->width >> 4); + go->active_map[stride * y + (x >> 3)] |= + (go->modet_word & 1) << (x & 0x7); + go->modet_word >>= 1; + } +} + +/* + * Parse a chunk of the video stream into frames. The frames are not + * delimited by the hardware, so we have to parse the frame boundaries + * based on the type of video stream we're receiving. + */ +void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) +{ + int i, seq_start_code = -1, frame_start_code = -1; + + spin_lock(&go->spinlock); + + switch (go->format) { + case GO7007_FORMAT_MPEG4: + seq_start_code = 0xB0; + frame_start_code = 0xB6; + break; + case GO7007_FORMAT_MPEG1: + case GO7007_FORMAT_MPEG2: + seq_start_code = 0xB3; + frame_start_code = 0x00; + break; + } + + for (i = 0; i < length; ++i) { + if (go->active_buf != NULL && + go->active_buf->bytesused >= GO7007_BUF_SIZE - 3) { + printk(KERN_DEBUG "go7007: dropping oversized frame\n"); + go->active_buf->offset -= go->active_buf->bytesused; + go->active_buf->bytesused = 0; + go->active_buf->modet_active = 0; + go->active_buf = NULL; + } + + switch (go->state) { + case STATE_DATA: + switch (buf[i]) { + case 0x00: + go->state = STATE_00; + break; + case 0xFF: + go->state = STATE_FF; + break; + default: + store_byte(go->active_buf, buf[i]); + break; + } + break; + case STATE_00: + switch (buf[i]) { + case 0x00: + go->state = STATE_00_00; + break; + case 0xFF: + store_byte(go->active_buf, 0x00); + go->state = STATE_FF; + break; + default: + store_byte(go->active_buf, 0x00); + store_byte(go->active_buf, buf[i]); + go->state = STATE_DATA; + break; + } + break; + case STATE_00_00: + switch (buf[i]) { + case 0x00: + store_byte(go->active_buf, 0x00); + /* go->state remains STATE_00_00 */ + break; + case 0x01: + go->state = STATE_00_00_01; + break; + case 0xFF: + store_byte(go->active_buf, 0x00); + store_byte(go->active_buf, 0x00); + go->state = STATE_FF; + break; + default: + store_byte(go->active_buf, 0x00); + store_byte(go->active_buf, 0x00); + store_byte(go->active_buf, buf[i]); + go->state = STATE_DATA; + break; + } + break; + case STATE_00_00_01: + /* If this is the start of a new MPEG frame, + * get a new buffer */ + if ((go->format == GO7007_FORMAT_MPEG1 || + go->format == GO7007_FORMAT_MPEG2 || + go->format == GO7007_FORMAT_MPEG4) && + (buf[i] == seq_start_code || + buf[i] == 0xB8 || /* GOP code */ + buf[i] == frame_start_code)) { + if (go->active_buf == NULL || go->seen_frame) + frame_boundary(go); + if (buf[i] == frame_start_code) { + if (go->active_buf != NULL) + go->active_buf->frame_offset = + go->active_buf->offset; + go->seen_frame = 1; + } else { + go->seen_frame = 0; + } + } + /* Handle any special chunk types, or just write the + * start code to the (potentially new) buffer */ + switch (buf[i]) { + case 0xF5: /* timestamp */ + go->parse_length = 12; + go->state = STATE_UNPARSED; + break; + case 0xF6: /* vbi */ + go->state = STATE_VBI_LEN_A; + break; + case 0xF8: /* MD map */ + go->parse_length = 0; + memset(go->active_map, 0, + sizeof(go->active_map)); + go->state = STATE_MODET_MAP; + break; + case 0xFF: /* Potential JPEG start code */ + store_byte(go->active_buf, 0x00); + store_byte(go->active_buf, 0x00); + store_byte(go->active_buf, 0x01); + go->state = STATE_FF; + break; + default: + store_byte(go->active_buf, 0x00); + store_byte(go->active_buf, 0x00); + store_byte(go->active_buf, 0x01); + store_byte(go->active_buf, buf[i]); + go->state = STATE_DATA; + break; + } + break; + case STATE_FF: + switch (buf[i]) { + case 0x00: + store_byte(go->active_buf, 0xFF); + go->state = STATE_00; + break; + case 0xFF: + store_byte(go->active_buf, 0xFF); + /* go->state remains STATE_FF */ + break; + case 0xD8: + if (go->format == GO7007_FORMAT_MJPEG) + frame_boundary(go); + /* fall through */ + default: + store_byte(go->active_buf, 0xFF); + store_byte(go->active_buf, buf[i]); + go->state = STATE_DATA; + break; + } + break; + case STATE_VBI_LEN_A: + go->parse_length = buf[i] << 8; + go->state = STATE_VBI_LEN_B; + break; + case STATE_VBI_LEN_B: + go->parse_length |= buf[i]; + if (go->parse_length > 0) + go->state = STATE_UNPARSED; + else + go->state = STATE_DATA; + break; + case STATE_MODET_MAP: + if (go->parse_length < 204) { + if (go->parse_length & 1) { + go->modet_word |= buf[i]; + write_bitmap_word(go); + } else + go->modet_word = buf[i] << 8; + } else if (go->parse_length == 207 && go->active_buf) { + go->active_buf->modet_active = buf[i]; + } + if (++go->parse_length == 208) + go->state = STATE_DATA; + break; + case STATE_UNPARSED: + if (--go->parse_length == 0) + go->state = STATE_DATA; + break; + } + } + + spin_unlock(&go->spinlock); +} +EXPORT_SYMBOL(go7007_parse_video_stream); + +/* + * Allocate a new go7007 struct. Used by the hardware-specific probe. + */ +struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev) +{ + struct go7007 *go; + int i; + + go = kmalloc(sizeof(struct go7007), GFP_KERNEL); + if (go == NULL) + return NULL; + go->dev = dev; + go->board_info = board; + go->board_id = 0; + go->tuner_type = -1; + go->channel_number = 0; + go->name[0] = 0; + init_MUTEX(&go->hw_lock); + init_waitqueue_head(&go->frame_waitq); + spin_lock_init(&go->spinlock); + go->video_dev = NULL; + go->ref_count = 0; + go->status = STATUS_INIT; + memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter)); + go->i2c_adapter_online = 0; + go->interrupt_available = 0; + init_waitqueue_head(&go->interrupt_waitq); + go->in_use = 0; + go->input = 0; + if (board->sensor_flags & GO7007_SENSOR_TV) { + go->standard = GO7007_STD_NTSC; + go->width = 720; + go->height = 480; + go->sensor_framerate = 30000; + } else { + go->standard = GO7007_STD_OTHER; + go->width = board->sensor_width; + go->height = board->sensor_height; + go->sensor_framerate = board->sensor_framerate; + } + go->encoder_v_offset = board->sensor_v_offset; + go->encoder_h_offset = board->sensor_h_offset; + go->encoder_h_halve = 0; + go->encoder_v_halve = 0; + go->encoder_subsample = 0; + go->streaming = 0; + go->format = GO7007_FORMAT_MJPEG; + go->bitrate = 1500000; + go->fps_scale = 1; + go->pali = 0; + go->aspect_ratio = GO7007_RATIO_1_1; + go->gop_size = 0; + go->ipb = 0; + go->closed_gop = 0; + go->repeat_seqhead = 0; + go->seq_header_enable = 0; + go->gop_header_enable = 0; + go->dvd_mode = 0; + go->interlace_coding = 0; + for (i = 0; i < 4; ++i) + go->modet[i].enable = 0;; + for (i = 0; i < 1624; ++i) + go->modet_map[i] = 0; + go->audio_deliver = NULL; + go->audio_enabled = 0; + INIT_LIST_HEAD(&go->stream); + + return go; +} +EXPORT_SYMBOL(go7007_alloc); + +/* + * Detach and unregister the encoder. The go7007 struct won't be freed + * until v4l2 finishes releasing its resources and all associated fds are + * closed by applications. + */ +void go7007_remove(struct go7007 *go) +{ + if (go->i2c_adapter_online) { + if (i2c_del_adapter(&go->i2c_adapter) == 0) + go->i2c_adapter_online = 0; + else + printk(KERN_ERR + "go7007: error removing I2C adapter!\n"); + } + + if (go->audio_enabled) + go7007_snd_remove(go); + go7007_v4l2_remove(go); +} +EXPORT_SYMBOL(go7007_remove); + +MODULE_LICENSE("GPL v2"); diff --git a/linux/drivers/staging/go7007/go7007-fw.c b/linux/drivers/staging/go7007/go7007-fw.c new file mode 100644 index 000000000..871ed43e4 --- /dev/null +++ b/linux/drivers/staging/go7007/go7007-fw.c @@ -0,0 +1,1638 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +/* + * This file contains code to generate a firmware image for the GO7007SB + * encoder. Much of the firmware is read verbatim from a file, but some of + * it concerning bitrate control and other things that can be configured at + * run-time are generated dynamically. Note that the format headers + * generated here do not affect the functioning of the encoder; they are + * merely parroted back to the host at the start of each frame. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "go7007-priv.h" + +/* Constants used in the source firmware image to describe code segments */ + +#define FLAG_MODE_MJPEG (1) +#define FLAG_MODE_MPEG1 (1<<1) +#define FLAG_MODE_MPEG2 (1<<2) +#define FLAG_MODE_MPEG4 (1<<3) +#define FLAG_MODE_H263 (1<<4) +#define FLAG_MODE_ALL (FLAG_MODE_MJPEG | FLAG_MODE_MPEG1 | \ + FLAG_MODE_MPEG2 | FLAG_MODE_MPEG4 | \ + FLAG_MODE_H263) +#define FLAG_SPECIAL (1<<8) + +#define SPECIAL_FRM_HEAD 0 +#define SPECIAL_BRC_CTRL 1 +#define SPECIAL_CONFIG 2 +#define SPECIAL_SEQHEAD 3 +#define SPECIAL_AV_SYNC 4 +#define SPECIAL_FINAL 5 +#define SPECIAL_AUDIO 6 +#define SPECIAL_MODET 7 + +/* Little data class for creating MPEG headers bit-by-bit */ + +struct code_gen { + unsigned char *p; /* destination */ + u32 a; /* collects bits at the top of the variable */ + int b; /* bit position of most recently-written bit */ + int len; /* written out so far */ +}; + +#define CODE_GEN(name, dest) struct code_gen name = { dest, 0, 32, 0 } + +#define CODE_ADD(name, val, length) do { \ + name.b -= (length); \ + name.a |= (val) << name.b; \ + while (name.b <= 24) { \ + *name.p = name.a >> 24; \ + ++name.p; \ + name.a <<= 8; \ + name.b += 8; \ + name.len += 8; \ + } \ +} while (0) + +#define CODE_LENGTH(name) (name.len + (32 - name.b)) + +/* Tables for creating the bitrate control data */ + +static const s16 converge_speed_ip[101] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, + 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, + 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, + 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, + 19, 20, 22, 23, 25, 27, 30, 32, 35, 38, + 41, 45, 49, 53, 58, 63, 69, 76, 83, 91, + 100 +}; + +static const s16 converge_speed_ipb[101] = { + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, + 6, 6, 6, 7, 7, 7, 7, 8, 8, 9, + 9, 9, 10, 10, 11, 12, 12, 13, 14, 14, + 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, + 28, 30, 32, 34, 37, 40, 42, 46, 49, 53, + 57, 61, 66, 71, 77, 83, 90, 97, 106, 115, + 125, 135, 147, 161, 175, 191, 209, 228, 249, 273, + 300 +}; + +static const s16 LAMBDA_table[4][101] = { + { 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, + 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, + 22, 23, 23, 24, 24, 25, 25, 25, 26, 26, + 27, 27, 28, 28, 29, 29, 30, 31, 31, 32, + 32, 33, 33, 34, 35, 35, 36, 37, 37, 38, + 39, 39, 40, 41, 42, 42, 43, 44, 45, 46, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, + 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, + 96 + }, + { + 20, 20, 20, 21, 21, 21, 22, 22, 23, 23, + 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, + 28, 29, 29, 30, 30, 31, 31, 32, 33, 33, + 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, + 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 64, 65, 66, 67, 68, + 70, 71, 72, 73, 75, 76, 78, 79, 80, 82, + 83, 85, 86, 88, 90, 91, 93, 95, 96, 98, + 100, 102, 103, 105, 107, 109, 111, 113, 115, 117, + 120 + }, + { + 24, 24, 24, 25, 25, 26, 26, 27, 27, 28, + 28, 29, 29, 30, 30, 31, 31, 32, 33, 33, + 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, + 41, 41, 42, 43, 44, 44, 45, 46, 47, 48, + 49, 50, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 62, 63, 64, 65, 66, 67, 69, + 70, 71, 72, 74, 75, 76, 78, 79, 81, 82, + 84, 85, 87, 88, 90, 92, 93, 95, 97, 98, + 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, + 120, 122, 124, 127, 129, 131, 134, 136, 138, 141, + 144 + }, + { + 32, 32, 33, 33, 34, 34, 35, 36, 36, 37, + 38, 38, 39, 40, 41, 41, 42, 43, 44, 44, + 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 62, 63, 64, + 65, 66, 67, 69, 70, 71, 72, 74, 75, 76, + 78, 79, 81, 82, 84, 85, 87, 88, 90, 92, + 93, 95, 97, 98, 100, 102, 104, 106, 108, 110, + 112, 114, 116, 118, 120, 122, 124, 127, 129, 131, + 134, 136, 139, 141, 144, 146, 149, 152, 154, 157, + 160, 163, 166, 169, 172, 175, 178, 181, 185, 188, + 192 + } +}; + +/* MPEG blank frame generation tables */ + +enum mpeg_frame_type { + PFRAME, + BFRAME_PRE, + BFRAME_POST, + BFRAME_BIDIR, + BFRAME_EMPTY +}; + +static const u32 addrinctab[33][2] = { + { 0x01, 1 }, { 0x03, 3 }, { 0x02, 3 }, { 0x03, 4 }, + { 0x02, 4 }, { 0x03, 5 }, { 0x02, 5 }, { 0x07, 7 }, + { 0x06, 7 }, { 0x0b, 8 }, { 0x0a, 8 }, { 0x09, 8 }, + { 0x08, 8 }, { 0x07, 8 }, { 0x06, 8 }, { 0x17, 10 }, + { 0x16, 10 }, { 0x15, 10 }, { 0x14, 10 }, { 0x13, 10 }, + { 0x12, 10 }, { 0x23, 11 }, { 0x22, 11 }, { 0x21, 11 }, + { 0x20, 11 }, { 0x1f, 11 }, { 0x1e, 11 }, { 0x1d, 11 }, + { 0x1c, 11 }, { 0x1b, 11 }, { 0x1a, 11 }, { 0x19, 11 }, + { 0x18, 11 } +}; + +/* Standard JPEG tables */ + +static const u8 default_intra_quant_table[] = { + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 22, 24, 27, 29, 34, 37, + 19, 22, 26, 27, 29, 34, 34, 38, + 22, 22, 26, 27, 29, 34, 37, 40, + 22, 26, 27, 29, 32, 35, 40, 48, + 26, 27, 29, 32, 35, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83 +}; + +static const u8 bits_dc_luminance[] = { + 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 +}; + +static const u8 val_dc_luminance[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +}; + +static const u8 bits_dc_chrominance[] = { + 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 +}; + +static const u8 val_dc_chrominance[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +}; + +static const u8 bits_ac_luminance[] = { + 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d +}; + +static const u8 val_ac_luminance[] = { + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +static const u8 bits_ac_chrominance[] = { + 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 +}; + +static const u8 val_ac_chrominance[] = { + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +/* Zig-zag mapping for quant table + * + * OK, let's do this mapping on the actual table above so it doesn't have + * to be done on the fly. + */ +static const int zz[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +static int copy_packages(__le16 *dest, u16 *src, int pkg_cnt, int space) +{ + int i, cnt = pkg_cnt * 32; + + if (space < cnt) + return -1; + + for (i = 0; i < cnt; ++i) + dest[i] = cpu_to_le16p(src + i); + + return cnt; +} + +static int mjpeg_frame_header(struct go7007 *go, unsigned char *buf, int q) +{ + int i, p = 0; + + buf[p++] = 0xff; + buf[p++] = 0xd8; + buf[p++] = 0xff; + buf[p++] = 0xdb; + buf[p++] = 0; + buf[p++] = 2 + 65; + buf[p++] = 0; + buf[p++] = default_intra_quant_table[0]; + for (i = 1; i < 64; ++i) + /* buf[p++] = (default_intra_quant_table[i] * q) >> 3; */ + buf[p++] = (default_intra_quant_table[zz[i]] * q) >> 3; + buf[p++] = 0xff; + buf[p++] = 0xc0; + buf[p++] = 0; + buf[p++] = 17; + buf[p++] = 8; + buf[p++] = go->height >> 8; + buf[p++] = go->height & 0xff; + buf[p++] = go->width >> 8; + buf[p++] = go->width & 0xff; + buf[p++] = 3; + buf[p++] = 1; + buf[p++] = 0x22; + buf[p++] = 0; + buf[p++] = 2; + buf[p++] = 0x11; + buf[p++] = 0; + buf[p++] = 3; + buf[p++] = 0x11; + buf[p++] = 0; + buf[p++] = 0xff; + buf[p++] = 0xc4; + buf[p++] = 418 >> 8; + buf[p++] = 418 & 0xff; + buf[p++] = 0x00; + memcpy(buf + p, bits_dc_luminance + 1, 16); + p += 16; + memcpy(buf + p, val_dc_luminance, sizeof(val_dc_luminance)); + p += sizeof(val_dc_luminance); + buf[p++] = 0x01; + memcpy(buf + p, bits_dc_chrominance + 1, 16); + p += 16; + memcpy(buf + p, val_dc_chrominance, sizeof(val_dc_chrominance)); + p += sizeof(val_dc_chrominance); + buf[p++] = 0x10; + memcpy(buf + p, bits_ac_luminance + 1, 16); + p += 16; + memcpy(buf + p, val_ac_luminance, sizeof(val_ac_luminance)); + p += sizeof(val_ac_luminance); + buf[p++] = 0x11; + memcpy(buf + p, bits_ac_chrominance + 1, 16); + p += 16; + memcpy(buf + p, val_ac_chrominance, sizeof(val_ac_chrominance)); + p += sizeof(val_ac_chrominance); + buf[p++] = 0xff; + buf[p++] = 0xda; + buf[p++] = 0; + buf[p++] = 12; + buf[p++] = 3; + buf[p++] = 1; + buf[p++] = 0x00; + buf[p++] = 2; + buf[p++] = 0x11; + buf[p++] = 3; + buf[p++] = 0x11; + buf[p++] = 0; + buf[p++] = 63; + buf[p++] = 0; + return p; +} + +static int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space) +{ + u8 *buf; + u16 mem = 0x3e00; + unsigned int addr = 0x19; + int size = 0, i, off = 0, chunk; + + buf = kmalloc(4096, GFP_KERNEL); + if (buf == NULL) { + printk(KERN_ERR "go7007: unable to allocate 4096 bytes for " + "firmware construction\n"); + return -1; + } + memset(buf, 0, 4096); + + for (i = 1; i < 32; ++i) { + mjpeg_frame_header(go, buf + size, i); + size += 80; + } + chunk = mjpeg_frame_header(go, buf + size, 1); + memmove(buf + size, buf + size + 80, chunk - 80); + size += chunk - 80; + + for (i = 0; i < size; i += chunk * 2) { + if (space - off < 32) { + off = -1; + goto done; + } + + code[off + 1] = __cpu_to_le16(0x8000 | mem); + + chunk = 28; + if (mem + chunk > 0x4000) + chunk = 0x4000 - mem; + if (i + 2 * chunk > size) + chunk = (size - i) / 2; + + if (chunk < 28) { + code[off] = __cpu_to_le16(0x4000 | chunk); + code[off + 31] = __cpu_to_le16(addr++); + mem = 0x3e00; + } else { + code[off] = __cpu_to_le16(0x1000 | 28); + code[off + 31] = 0; + mem += 28; + } + + memcpy(&code[off + 2], buf + i, chunk * 2); + off += 32; + } +done: + kfree(buf); + return off; +} + +static int mpeg1_frame_header(struct go7007 *go, unsigned char *buf, + int modulo, int pict_struct, enum mpeg_frame_type frame) +{ + int i, j, mb_code, mb_len; + int rows = go->interlace_coding ? go->height / 32 : go->height / 16; + CODE_GEN(c, buf + 6); + + switch (frame) { + case PFRAME: + mb_code = 0x1; + mb_len = 3; + break; + case BFRAME_PRE: + mb_code = 0x2; + mb_len = 4; + break; + case BFRAME_POST: + mb_code = 0x2; + mb_len = 3; + break; + case BFRAME_BIDIR: + mb_code = 0x2; + mb_len = 2; + break; + default: /* keep the compiler happy */ + mb_code = mb_len = 0; + break; + } + + CODE_ADD(c, frame == PFRAME ? 0x2 : 0x3, 13); + CODE_ADD(c, 0xffff, 16); + CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 0x7 : 0x4, 4); + if (frame != PFRAME) + CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 0x7 : 0x4, 4); + else + CODE_ADD(c, 0, 4); /* Is this supposed to be here?? */ + CODE_ADD(c, 0, 3); /* What is this?? */ + /* Byte-align with zeros */ + j = 8 - (CODE_LENGTH(c) % 8); + if (j != 8) + CODE_ADD(c, 0, j); + + if (go->format == GO7007_FORMAT_MPEG2) { + CODE_ADD(c, 0x1, 24); + CODE_ADD(c, 0xb5, 8); + CODE_ADD(c, 0x844, 12); + CODE_ADD(c, frame == PFRAME ? 0xff : 0x44, 8); + if (go->interlace_coding) { + CODE_ADD(c, pict_struct, 4); + if (go->dvd_mode) + CODE_ADD(c, 0x000, 11); + else + CODE_ADD(c, 0x200, 11); + } else { + CODE_ADD(c, 0x3, 4); + CODE_ADD(c, 0x20c, 11); + } + /* Byte-align with zeros */ + j = 8 - (CODE_LENGTH(c) % 8); + if (j != 8) + CODE_ADD(c, 0, j); + } + + for (i = 0; i < rows; ++i) { + CODE_ADD(c, 1, 24); + CODE_ADD(c, i + 1, 8); + CODE_ADD(c, 0x2, 6); + CODE_ADD(c, 0x1, 1); + CODE_ADD(c, mb_code, mb_len); + if (go->interlace_coding) { + CODE_ADD(c, 0x1, 2); + CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); + } + if (frame == BFRAME_BIDIR) { + CODE_ADD(c, 0x3, 2); + if (go->interlace_coding) + CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); + } + CODE_ADD(c, 0x3, 2); + for (j = (go->width >> 4) - 2; j >= 33; j -= 33) + CODE_ADD(c, 0x8, 11); + CODE_ADD(c, addrinctab[j][0], addrinctab[j][1]); + CODE_ADD(c, mb_code, mb_len); + if (go->interlace_coding) { + CODE_ADD(c, 0x1, 2); + CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); + } + if (frame == BFRAME_BIDIR) { + CODE_ADD(c, 0x3, 2); + if (go->interlace_coding) + CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); + } + CODE_ADD(c, 0x3, 2); + + /* Byte-align with zeros */ + j = 8 - (CODE_LENGTH(c) % 8); + if (j != 8) + CODE_ADD(c, 0, j); + } + + i = CODE_LENGTH(c) + 4 * 8; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = 0x01; + buf[5] = 0x00; + return i; +} + +static int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext) +{ + int i, aspect_ratio, picture_rate; + CODE_GEN(c, buf + 6); + + if (go->format == GO7007_FORMAT_MPEG1) { + switch (go->aspect_ratio) { + case GO7007_RATIO_4_3: + aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2; + break; + case GO7007_RATIO_16_9: + aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4; + break; + default: + aspect_ratio = 1; + break; + } + } else { + switch (go->aspect_ratio) { + case GO7007_RATIO_4_3: + aspect_ratio = 2; + break; + case GO7007_RATIO_16_9: + aspect_ratio = 3; + break; + default: + aspect_ratio = 1; + break; + } + } + switch (go->sensor_framerate) { + case 24000: + picture_rate = 1; + break; + case 24024: + picture_rate = 2; + break; + case 25025: + picture_rate = go->interlace_coding ? 6 : 3; + break; + case 30000: + picture_rate = go->interlace_coding ? 7 : 4; + break; + case 30030: + picture_rate = go->interlace_coding ? 8 : 5; + break; + default: + picture_rate = 5; /* 30 fps seems like a reasonable default */ + break; + } + + CODE_ADD(c, go->width, 12); + CODE_ADD(c, go->height, 12); + CODE_ADD(c, aspect_ratio, 4); + CODE_ADD(c, picture_rate, 4); + CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 20000 : 0x3ffff, 18); + CODE_ADD(c, 1, 1); + CODE_ADD(c, go->format == GO7007_FORMAT_MPEG2 ? 112 : 20, 10); + CODE_ADD(c, 0, 3); + + /* Byte-align with zeros */ + i = 8 - (CODE_LENGTH(c) % 8); + if (i != 8) + CODE_ADD(c, 0, i); + + if (go->format == GO7007_FORMAT_MPEG2) { + CODE_ADD(c, 0x1, 24); + CODE_ADD(c, 0xb5, 8); + CODE_ADD(c, 0x148, 12); + if (go->interlace_coding) + CODE_ADD(c, 0x20001, 20); + else + CODE_ADD(c, 0xa0001, 20); + CODE_ADD(c, 0, 16); + + /* Byte-align with zeros */ + i = 8 - (CODE_LENGTH(c) % 8); + if (i != 8) + CODE_ADD(c, 0, i); + + if (ext) { + CODE_ADD(c, 0x1, 24); + CODE_ADD(c, 0xb52, 12); + CODE_ADD(c, go->standard == GO7007_STD_NTSC ? 2 : 1, 3); + CODE_ADD(c, 0x105, 9); + CODE_ADD(c, 0x505, 16); + CODE_ADD(c, go->width, 14); + CODE_ADD(c, 1, 1); + CODE_ADD(c, go->height, 14); + + /* Byte-align with zeros */ + i = 8 - (CODE_LENGTH(c) % 8); + if (i != 8) + CODE_ADD(c, 0, i); + } + } + + i = CODE_LENGTH(c) + 4 * 8; + buf[0] = i & 0xff; + buf[1] = i >> 8; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = 0x01; + buf[5] = 0xb3; + return i; +} + +static int gen_mpeg1hdr_to_package(struct go7007 *go, + __le16 *code, int space, int *framelen) +{ + u8 *buf; + u16 mem = 0x3e00; + unsigned int addr = 0x19; + int i, off = 0, chunk; + + buf = kmalloc(5120, GFP_KERNEL); + if (buf == NULL) { + printk(KERN_ERR "go7007: unable to allocate 5120 bytes for " + "firmware construction\n"); + return -1; + } + memset(buf, 0, 5120); + framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME); + if (go->interlace_coding) + framelen[0] += mpeg1_frame_header(go, buf + framelen[0] / 8, + 0, 2, PFRAME); + buf[0] = framelen[0] & 0xff; + buf[1] = framelen[0] >> 8; + i = 368; + framelen[1] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_PRE); + if (go->interlace_coding) + framelen[1] += mpeg1_frame_header(go, buf + i + framelen[1] / 8, + 0, 2, BFRAME_PRE); + buf[i] = framelen[1] & 0xff; + buf[i + 1] = framelen[1] >> 8; + i += 1632; + framelen[2] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_POST); + if (go->interlace_coding) + framelen[2] += mpeg1_frame_header(go, buf + i + framelen[2] / 8, + 0, 2, BFRAME_POST); + buf[i] = framelen[2] & 0xff; + buf[i + 1] = framelen[2] >> 8; + i += 1432; + framelen[3] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_BIDIR); + if (go->interlace_coding) + framelen[3] += mpeg1_frame_header(go, buf + i + framelen[3] / 8, + 0, 2, BFRAME_BIDIR); + buf[i] = framelen[3] & 0xff; + buf[i + 1] = framelen[3] >> 8; + i += 1632 + 16; + mpeg1_sequence_header(go, buf + i, 0); + i += 40; + for (i = 0; i < 5120; i += chunk * 2) { + if (space - off < 32) { + off = -1; + goto done; + } + + code[off + 1] = __cpu_to_le16(0x8000 | mem); + + chunk = 28; + if (mem + chunk > 0x4000) + chunk = 0x4000 - mem; + if (i + 2 * chunk > 5120) + chunk = (5120 - i) / 2; + + if (chunk < 28) { + code[off] = __cpu_to_le16(0x4000 | chunk); + code[off + 31] = __cpu_to_le16(addr); + if (mem + chunk == 0x4000) { + mem = 0x3e00; + ++addr; + } + } else { + code[off] = __cpu_to_le16(0x1000 | 28); + code[off + 31] = 0; + mem += 28; + } + + memcpy(&code[off + 2], buf + i, chunk * 2); + off += 32; + } +done: + kfree(buf); + return off; +} + +static int vti_bitlen(struct go7007 *go) +{ + unsigned int i, max_time_incr = go->sensor_framerate / go->fps_scale; + + for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i); + return i + 1; +} + +static int mpeg4_frame_header(struct go7007 *go, unsigned char *buf, + int modulo, enum mpeg_frame_type frame) +{ + int i; + CODE_GEN(c, buf + 6); + int mb_count = (go->width >> 4) * (go->height >> 4); + + CODE_ADD(c, frame == PFRAME ? 0x1 : 0x2, 2); + if (modulo) + CODE_ADD(c, 0x1, 1); + CODE_ADD(c, 0x1, 2); + CODE_ADD(c, 0, vti_bitlen(go)); + CODE_ADD(c, 0x3, 2); + if (frame == PFRAME) + CODE_ADD(c, 0, 1); + CODE_ADD(c, 0xc, 11); + if (frame != PFRAME) + CODE_ADD(c, 0x4, 3); + if (frame != BFRAME_EMPTY) { + for (i = 0; i < mb_count; ++i) { + switch (frame) { + case PFRAME: + CODE_ADD(c, 0x1, 1); + break; + case BFRAME_PRE: + CODE_ADD(c, 0x47, 8); + break; + case BFRAME_POST: + CODE_ADD(c, 0x27, 7); + break; + case BFRAME_BIDIR: + CODE_ADD(c, 0x5f, 8); + break; + case BFRAME_EMPTY: /* keep compiler quiet */ + break; + } + } + } + + /* Byte-align with a zero followed by ones */ + i = 8 - (CODE_LENGTH(c) % 8); + CODE_ADD(c, 0, 1); + CODE_ADD(c, (1 << (i - 1)) - 1, i - 1); + + i = CODE_LENGTH(c) + 4 * 8; + buf[0] = i & 0xff; + buf[1] = i >> 8; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = 0x01; + buf[5] = 0xb6; + return i; +} + +static int mpeg4_sequence_header(struct go7007 *go, unsigned char *buf, int ext) +{ + const unsigned char head[] = { 0x00, 0x00, 0x01, 0xb0, go->pali, + 0x00, 0x00, 0x01, 0xb5, 0x09, + 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x20, }; + int i, aspect_ratio; + int fps = go->sensor_framerate / go->fps_scale; + CODE_GEN(c, buf + 2 + sizeof(head)); + + switch (go->aspect_ratio) { + case GO7007_RATIO_4_3: + aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2; + break; + case GO7007_RATIO_16_9: + aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4; + break; + default: + aspect_ratio = 1; + break; + } + + memcpy(buf + 2, head, sizeof(head)); + CODE_ADD(c, 0x191, 17); + CODE_ADD(c, aspect_ratio, 4); + CODE_ADD(c, 0x1, 4); + CODE_ADD(c, fps, 16); + CODE_ADD(c, 0x3, 2); + CODE_ADD(c, 1001, vti_bitlen(go)); + CODE_ADD(c, 1, 1); + CODE_ADD(c, go->width, 13); + CODE_ADD(c, 1, 1); + CODE_ADD(c, go->height, 13); + CODE_ADD(c, 0x2830, 14); + + /* Byte-align */ + i = 8 - (CODE_LENGTH(c) % 8); + CODE_ADD(c, 0, 1); + CODE_ADD(c, (1 << (i - 1)) - 1, i - 1); + + i = CODE_LENGTH(c) + sizeof(head) * 8; + buf[0] = i & 0xff; + buf[1] = i >> 8; + return i; +} + +static int gen_mpeg4hdr_to_package(struct go7007 *go, + __le16 *code, int space, int *framelen) +{ + u8 *buf; + u16 mem = 0x3e00; + unsigned int addr = 0x19; + int i, off = 0, chunk; + + buf = kmalloc(5120, GFP_KERNEL); + if (buf == NULL) { + printk(KERN_ERR "go7007: unable to allocate 5120 bytes for " + "firmware construction\n"); + return -1; + } + memset(buf, 0, 5120); + framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME); + i = 368; + framelen[1] = mpeg4_frame_header(go, buf + i, 0, BFRAME_PRE); + i += 1632; + framelen[2] = mpeg4_frame_header(go, buf + i, 0, BFRAME_POST); + i += 1432; + framelen[3] = mpeg4_frame_header(go, buf + i, 0, BFRAME_BIDIR); + i += 1632; + mpeg4_frame_header(go, buf + i, 0, BFRAME_EMPTY); + i += 16; + mpeg4_sequence_header(go, buf + i, 0); + i += 40; + for (i = 0; i < 5120; i += chunk * 2) { + if (space - off < 32) { + off = -1; + goto done; + } + + code[off + 1] = __cpu_to_le16(0x8000 | mem); + + chunk = 28; + if (mem + chunk > 0x4000) + chunk = 0x4000 - mem; + if (i + 2 * chunk > 5120) + chunk = (5120 - i) / 2; + + if (chunk < 28) { + code[off] = __cpu_to_le16(0x4000 | chunk); + code[off + 31] = __cpu_to_le16(addr); + if (mem + chunk == 0x4000) { + mem = 0x3e00; + ++addr; + } + } else { + code[off] = __cpu_to_le16(0x1000 | 28); + code[off + 31] = 0; + mem += 28; + } + + memcpy(&code[off + 2], buf + i, chunk * 2); + off += 32; + } + mem = 0x3e00; + addr = go->ipb ? 0x14f9 : 0x0af9; + memset(buf, 0, 5120); + framelen[4] = mpeg4_frame_header(go, buf, 1, PFRAME); + i = 368; + framelen[5] = mpeg4_frame_header(go, buf + i, 1, BFRAME_PRE); + i += 1632; + framelen[6] = mpeg4_frame_header(go, buf + i, 1, BFRAME_POST); + i += 1432; + framelen[7] = mpeg4_frame_header(go, buf + i, 1, BFRAME_BIDIR); + i += 1632; + mpeg4_frame_header(go, buf + i, 1, BFRAME_EMPTY); + i += 16; + for (i = 0; i < 5120; i += chunk * 2) { + if (space - off < 32) { + off = -1; + goto done; + } + + code[off + 1] = __cpu_to_le16(0x8000 | mem); + + chunk = 28; + if (mem + chunk > 0x4000) + chunk = 0x4000 - mem; + if (i + 2 * chunk > 5120) + chunk = (5120 - i) / 2; + + if (chunk < 28) { + code[off] = __cpu_to_le16(0x4000 | chunk); + code[off + 31] = __cpu_to_le16(addr); + if (mem + chunk == 0x4000) { + mem = 0x3e00; + ++addr; + } + } else { + code[off] = __cpu_to_le16(0x1000 | 28); + code[off + 31] = 0; + mem += 28; + } + + memcpy(&code[off + 2], buf + i, chunk * 2); + off += 32; + } +done: + kfree(buf); + return off; +} + +static int brctrl_to_package(struct go7007 *go, + __le16 *code, int space, int *framelen) +{ + int converge_speed = 0; + int lambda = (go->format == GO7007_FORMAT_MJPEG || go->dvd_mode) ? + 100 : 0; + int peak_rate = 6 * go->bitrate / 5; + int vbv_buffer = go->format == GO7007_FORMAT_MJPEG ? + go->bitrate : + (go->dvd_mode ? 900000 : peak_rate); + int fps = go->sensor_framerate / go->fps_scale; + int q = 0; + /* Bizarre math below depends on rounding errors in division */ + u32 sgop_expt_addr = go->bitrate / 32 * (go->ipb ? 3 : 1) * 1001 / fps; + u32 sgop_peak_addr = peak_rate / 32 * 1001 / fps; + u32 total_expt_addr = go->bitrate / 32 * 1000 / fps * (fps / 1000); + u32 vbv_alert_addr = vbv_buffer * 3 / (4 * 32); + u32 cplx[] = { + q > 0 ? sgop_expt_addr * q : + 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, + q > 0 ? sgop_expt_addr * q : + 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, + q > 0 ? sgop_expt_addr * q : + 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, + q > 0 ? sgop_expt_addr * q : + 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, + }; + u32 calc_q = q > 0 ? q : cplx[0] / sgop_expt_addr; + u16 pack[] = { + 0x200e, 0x0000, + 0xBF20, go->ipb ? converge_speed_ipb[converge_speed] + : converge_speed_ip[converge_speed], + 0xBF21, go->ipb ? 2 : 0, + 0xBF22, go->ipb ? LAMBDA_table[0][lambda / 2 + 50] + : 32767, + 0xBF23, go->ipb ? LAMBDA_table[1][lambda] : 32767, + 0xBF24, 32767, + 0xBF25, lambda > 99 ? 32767 : LAMBDA_table[3][lambda], + 0xBF26, sgop_expt_addr & 0x0000FFFF, + 0xBF27, sgop_expt_addr >> 16, + 0xBF28, sgop_peak_addr & 0x0000FFFF, + 0xBF29, sgop_peak_addr >> 16, + 0xBF2A, vbv_alert_addr & 0x0000FFFF, + 0xBF2B, vbv_alert_addr >> 16, + 0xBF2C, 0, + 0xBF2D, 0, + 0, 0, + + 0x200e, 0x0000, + 0xBF2E, vbv_alert_addr & 0x0000FFFF, + 0xBF2F, vbv_alert_addr >> 16, + 0xBF30, cplx[0] & 0x0000FFFF, + 0xBF31, cplx[0] >> 16, + 0xBF32, cplx[1] & 0x0000FFFF, + 0xBF33, cplx[1] >> 16, + 0xBF34, cplx[2] & 0x0000FFFF, + 0xBF35, cplx[2] >> 16, + 0xBF36, cplx[3] & 0x0000FFFF, + 0xBF37, cplx[3] >> 16, + 0xBF38, 0, + 0xBF39, 0, + 0xBF3A, total_expt_addr & 0x0000FFFF, + 0xBF3B, total_expt_addr >> 16, + 0, 0, + + 0x200e, 0x0000, + 0xBF3C, total_expt_addr & 0x0000FFFF, + 0xBF3D, total_expt_addr >> 16, + 0xBF3E, 0, + 0xBF3F, 0, + 0xBF48, 0, + 0xBF49, 0, + 0xBF4A, calc_q < 4 ? 4 : (calc_q > 124 ? 124 : calc_q), + 0xBF4B, 4, + 0xBF4C, 0, + 0xBF4D, 0, + 0xBF4E, 0, + 0xBF4F, 0, + 0xBF50, 0, + 0xBF51, 0, + 0, 0, + + 0x200e, 0x0000, + 0xBF40, sgop_expt_addr & 0x0000FFFF, + 0xBF41, sgop_expt_addr >> 16, + 0xBF42, 0, + 0xBF43, 0, + 0xBF44, 0, + 0xBF45, 0, + 0xBF46, (go->width >> 4) * (go->height >> 4), + 0xBF47, 0, + 0xBF64, 0, + 0xBF65, 0, + 0xBF18, framelen[4], + 0xBF19, framelen[5], + 0xBF1A, framelen[6], + 0xBF1B, framelen[7], + 0, 0, + +#if 0 /* Remove once we don't care about matching */ + 0x200e, 0x0000, + 0xBF56, 4, + 0xBF57, 0, + 0xBF58, 5, + 0xBF59, 0, + 0xBF5A, 6, + 0xBF5B, 0, + 0xBF5C, 8, + 0xBF5D, 0, + 0xBF5E, 1, + 0xBF5F, 0, + 0xBF60, 1, + 0xBF61, 0, + 0xBF62, 0, + 0xBF63, 0, + 0, 0, +#else + 0x2008, 0x0000, + 0xBF56, 4, + 0xBF57, 0, + 0xBF58, 5, + 0xBF59, 0, + 0xBF5A, 6, + 0xBF5B, 0, + 0xBF5C, 8, + 0xBF5D, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, +#endif + + 0x200e, 0x0000, + 0xBF10, 0, + 0xBF11, 0, + 0xBF12, 0, + 0xBF13, 0, + 0xBF14, 0, + 0xBF15, 0, + 0xBF16, 0, + 0xBF17, 0, + 0xBF7E, 0, + 0xBF7F, 1, + 0xBF52, framelen[0], + 0xBF53, framelen[1], + 0xBF54, framelen[2], + 0xBF55, framelen[3], + 0, 0, + }; + + return copy_packages(code, pack, 6, space); +} + +static int config_package(struct go7007 *go, __le16 *code, int space) +{ + int fps = go->sensor_framerate / go->fps_scale / 1000; + int rows = go->interlace_coding ? go->height / 32 : go->height / 16; + int brc_window_size = fps; + int q_min = 2, q_max = 31; + int THACCoeffSet0 = 0; + u16 pack[] = { + 0x200e, 0x0000, + 0xc002, 0x14b4, + 0xc003, 0x28b4, + 0xc004, 0x3c5a, + 0xdc05, 0x2a77, + 0xc6c3, go->format == GO7007_FORMAT_MPEG4 ? 0 : + (go->format == GO7007_FORMAT_H263 ? 0 : 1), + 0xc680, go->format == GO7007_FORMAT_MPEG4 ? 0xf1 : + (go->format == GO7007_FORMAT_H263 ? 0x61 : + 0xd3), + 0xc780, 0x0140, + 0xe009, 0x0001, + 0xc60f, 0x0008, + 0xd4ff, 0x0002, + 0xe403, 2340, + 0xe406, 75, + 0xd411, 0x0001, + 0xd410, 0xa1d6, + 0x0001, 0x2801, + + 0x200d, 0x0000, + 0xe402, 0x018b, + 0xe401, 0x8b01, + 0xd472, (go->board_info->sensor_flags & + GO7007_SENSOR_TV) && + (!go->interlace_coding) ? + 0x01b0 : 0x0170, + 0xd475, (go->board_info->sensor_flags & + GO7007_SENSOR_TV) && + (!go->interlace_coding) ? + 0x0008 : 0x0009, + 0xc404, go->interlace_coding ? 0x44 : + (go->format == GO7007_FORMAT_MPEG4 ? 0x11 : + (go->format == GO7007_FORMAT_MPEG1 ? 0x02 : + (go->format == GO7007_FORMAT_MPEG2 ? 0x04 : + (go->format == GO7007_FORMAT_H263 ? 0x08 : + 0x20)))), + 0xbf0a, (go->format == GO7007_FORMAT_MPEG4 ? 8 : + (go->format == GO7007_FORMAT_MPEG1 ? 1 : + (go->format == GO7007_FORMAT_MPEG2 ? 2 : + (go->format == GO7007_FORMAT_H263 ? 4 : 16)))) | + ((go->repeat_seqhead ? 1 : 0) << 6) | + ((go->dvd_mode ? 1 : 0) << 9) | + ((go->gop_header_enable ? 1 : 0) << 10), + 0xbf0b, 0, + 0xdd5a, go->ipb ? 0x14 : 0x0a, + 0xbf0c, 0, + 0xbf0d, 0, + 0xc683, THACCoeffSet0, + 0xc40a, (go->width << 4) | rows, + 0xe01a, go->board_info->hpi_buffer_cap, + 0, 0, + 0, 0, + + 0x2008, 0, + 0xe402, 0x88, + 0xe401, 0x8f01, + 0xbf6a, 0, + 0xbf6b, 0, + 0xbf6c, 0, + 0xbf6d, 0, + 0xbf6e, 0, + 0xbf6f, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + + 0x200e, 0, + 0xbf66, brc_window_size, + 0xbf67, 0, + 0xbf68, q_min, + 0xbf69, q_max, + 0xbfe0, 0, + 0xbfe1, 0, + 0xbfe2, 0, + 0xbfe3, go->ipb ? 3 : 1, + 0xc031, go->board_info->sensor_flags & + GO7007_SENSOR_VBI ? 1 : 0, + 0xc01c, 0x1f, + 0xdd8c, 0x15, + 0xdd94, 0x15, + 0xdd88, go->ipb ? 0x1401 : 0x0a01, + 0xdd90, go->ipb ? 0x1401 : 0x0a01, + 0, 0, + + 0x200e, 0, + 0xbfe4, 0, + 0xbfe5, 0, + 0xbfe6, 0, + 0xbfe7, fps << 8, + 0xbfe8, 0x3a00, + 0xbfe9, 0, + 0xbfea, 0, + 0xbfeb, 0, + 0xbfec, (go->interlace_coding ? 1 << 15 : 0) | + (go->modet_enable ? 0xa : 0) | + (go->board_info->sensor_flags & + GO7007_SENSOR_VBI ? 1 : 0), + 0xbfed, 0, + 0xbfee, 0, + 0xbfef, 0, + 0xbff0, go->board_info->sensor_flags & + GO7007_SENSOR_TV ? 0xf060 : 0xb060, + 0xbff1, 0, + 0, 0, + }; + + return copy_packages(code, pack, 5, space); +} + +static int seqhead_to_package(struct go7007 *go, __le16 *code, int space, + int (*sequence_header_func)(struct go7007 *go, + unsigned char *buf, int ext)) +{ + int vop_time_increment_bitlength = vti_bitlen(go); + int fps = go->sensor_framerate / go->fps_scale * + (go->interlace_coding ? 2 : 1); + unsigned char buf[40] = { }; + int len = sequence_header_func(go, buf, 1); + u16 pack[] = { + 0x2006, 0, + 0xbf08, fps, + 0xbf09, 0, + 0xbff2, vop_time_increment_bitlength, + 0xbff3, (1 << vop_time_increment_bitlength) - 1, + 0xbfe6, 0, + 0xbfe7, (fps / 1000) << 8, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + + 0x2007, 0, + 0xc800, buf[2] << 8 | buf[3], + 0xc801, buf[4] << 8 | buf[5], + 0xc802, buf[6] << 8 | buf[7], + 0xc803, buf[8] << 8 | buf[9], + 0xc406, 64, + 0xc407, len - 64, + 0xc61b, 1, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + + 0x200e, 0, + 0xc808, buf[10] << 8 | buf[11], + 0xc809, buf[12] << 8 | buf[13], + 0xc80a, buf[14] << 8 | buf[15], + 0xc80b, buf[16] << 8 | buf[17], + 0xc80c, buf[18] << 8 | buf[19], + 0xc80d, buf[20] << 8 | buf[21], + 0xc80e, buf[22] << 8 | buf[23], + 0xc80f, buf[24] << 8 | buf[25], + 0xc810, buf[26] << 8 | buf[27], + 0xc811, buf[28] << 8 | buf[29], + 0xc812, buf[30] << 8 | buf[31], + 0xc813, buf[32] << 8 | buf[33], + 0xc814, buf[34] << 8 | buf[35], + 0xc815, buf[36] << 8 | buf[37], + 0, 0, + 0, 0, + 0, 0, + }; + + return copy_packages(code, pack, 3, space); +} + +static int relative_prime(int big, int little) +{ + int remainder; + + while (little != 0) { + remainder = big % little; + big = little; + little = remainder; + } + return big; +} + +static int avsync_to_package(struct go7007 *go, __le16 *code, int space) +{ + int arate = go->board_info->audio_rate * 1001 * go->fps_scale; + int ratio = arate / go->sensor_framerate; + int adjratio = ratio * 215 / 100; + int rprime = relative_prime(go->sensor_framerate, + arate % go->sensor_framerate); + int f1 = (arate % go->sensor_framerate) / rprime; + int f2 = (go->sensor_framerate - arate % go->sensor_framerate) / rprime; + u16 pack[] = { + 0x200e, 0, + 0xbf98, (u16)((-adjratio) & 0xffff), + 0xbf99, (u16)((-adjratio) >> 16), + 0xbf92, 0, + 0xbf93, 0, + 0xbff4, f1 > f2 ? f1 : f2, + 0xbff5, f1 < f2 ? f1 : f2, + 0xbff6, f1 < f2 ? ratio : ratio + 1, + 0xbff7, f1 > f2 ? ratio : ratio + 1, + 0xbff8, 0, + 0xbff9, 0, + 0xbffa, adjratio & 0xffff, + 0xbffb, adjratio >> 16, + 0xbf94, 0, + 0xbf95, 0, + 0, 0, + }; + + return copy_packages(code, pack, 1, space); +} + +static int final_package(struct go7007 *go, __le16 *code, int space) +{ + int rows = go->interlace_coding ? go->height / 32 : go->height / 16; + u16 pack[] = { + 0x8000, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + ((go->board_info->sensor_flags & GO7007_SENSOR_TV) && + (!go->interlace_coding) ? + (1 << 14) | (1 << 9) : 0) | + ((go->encoder_subsample ? 1 : 0) << 8) | + (go->board_info->sensor_flags & + GO7007_SENSOR_CONFIG_MASK), + ((go->encoder_v_halve ? 1 : 0) << 14) | + (go->encoder_v_halve ? rows << 9 : rows << 8) | + (go->encoder_h_halve ? 1 << 6 : 0) | + (go->encoder_h_halve ? go->width >> 3 : go->width >> 4), + (1 << 15) | (go->encoder_v_offset << 6) | + (1 << 7) | (go->encoder_h_offset >> 2), + (1 << 6), + 0, + 0, + ((go->fps_scale - 1) << 8) | + (go->board_info->sensor_flags & GO7007_SENSOR_TV ? + (1 << 7) : 0) | + 0x41, + go->ipb ? 0xd4c : 0x36b, + (rows << 8) | (go->width >> 4), + go->format == GO7007_FORMAT_MPEG4 ? 0x0404 : 0, + (1 << 15) | ((go->interlace_coding ? 1 : 0) << 13) | + ((go->closed_gop ? 1 : 0) << 12) | + ((go->format == GO7007_FORMAT_MPEG4 ? 1 : 0) << 11) | + /* (1 << 9) | */ + ((go->ipb ? 3 : 0) << 7) | + ((go->modet_enable ? 1 : 0) << 2) | + ((go->dvd_mode ? 1 : 0) << 1) | 1, + (go->format == GO7007_FORMAT_MPEG1 ? 0x89a0 : + (go->format == GO7007_FORMAT_MPEG2 ? 0x89a0 : + (go->format == GO7007_FORMAT_MJPEG ? 0x89a0 : + (go->format == GO7007_FORMAT_MPEG4 ? 0x8920 : + (go->format == GO7007_FORMAT_H263 ? 0x8920 : 0))))), + go->ipb ? 0x1f15 : 0x1f0b, + go->ipb ? 0x0015 : 0x000b, + go->ipb ? 0xa800 : 0x5800, + 0xffff, + 0x0020 + 0x034b * 0, + 0x0020 + 0x034b * 1, + 0x0020 + 0x034b * 2, + 0x0020 + 0x034b * 3, + 0x0020 + 0x034b * 4, + 0x0020 + 0x034b * 5, + go->ipb ? (go->gop_size / 3) : go->gop_size, + (go->height >> 4) * (go->width >> 4) * 110 / 100, + }; + + return copy_packages(code, pack, 1, space); +} + +static int audio_to_package(struct go7007 *go, __le16 *code, int space) +{ + int clock_config = ((go->board_info->audio_flags & + GO7007_AUDIO_I2S_MASTER ? 1 : 0) << 11) | + ((go->board_info->audio_flags & + GO7007_AUDIO_OKI_MODE ? 1 : 0) << 8) | + (((go->board_info->audio_bclk_div / 4) - 1) << 4) | + (go->board_info->audio_main_div - 1); + u16 pack[] = { + 0x200d, 0, + 0x9002, 0, + 0x9002, 0, + 0x9031, 0, + 0x9032, 0, + 0x9033, 0, + 0x9034, 0, + 0x9035, 0, + 0x9036, 0, + 0x9037, 0, + 0x9040, 0, + 0x9000, clock_config, + 0x9001, (go->board_info->audio_flags & 0xffff) | + (1 << 9), + 0x9000, ((go->board_info->audio_flags & + GO7007_AUDIO_I2S_MASTER ? + 1 : 0) << 10) | + clock_config, + 0, 0, + 0, 0, + 0x2005, 0, + 0x9041, 0, + 0x9042, 256, + 0x9043, 0, + 0x9044, 16, + 0x9045, 16, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + }; + + return copy_packages(code, pack, 2, space); +} + +static int modet_to_package(struct go7007 *go, __le16 *code, int space) +{ + int ret, mb, i, addr, cnt = 0; + u16 pack[32]; + u16 thresholds[] = { + 0x200e, 0, + 0xbf82, go->modet[0].pixel_threshold, + 0xbf83, go->modet[1].pixel_threshold, + 0xbf84, go->modet[2].pixel_threshold, + 0xbf85, go->modet[3].pixel_threshold, + 0xbf86, go->modet[0].motion_threshold, + 0xbf87, go->modet[1].motion_threshold, + 0xbf88, go->modet[2].motion_threshold, + 0xbf89, go->modet[3].motion_threshold, + 0xbf8a, go->modet[0].mb_threshold, + 0xbf8b, go->modet[1].mb_threshold, + 0xbf8c, go->modet[2].mb_threshold, + 0xbf8d, go->modet[3].mb_threshold, + 0xbf8e, 0, + 0xbf8f, 0, + 0, 0, + }; + + ret = copy_packages(code, thresholds, 1, space); + if (ret < 0) + return -1; + cnt += ret; + + addr = 0xbac0; + memset(pack, 0, 64); + i = 0; + for (mb = 0; mb < 1624; ++mb) { + pack[i * 2 + 3] <<= 2; + pack[i * 2 + 3] |= go->modet_map[mb]; + if (mb % 8 != 7) + continue; + pack[i * 2 + 2] = addr++; + ++i; + if (i == 10 || mb == 1623) { + pack[0] = 0x2000 | i; + ret = copy_packages(code + cnt, pack, 1, space - cnt); + if (ret < 0) + return -1; + cnt += ret; + i = 0; + memset(pack, 0, 64); + } + pack[i * 2 + 3] = 0; + } + + memset(pack, 0, 64); + i = 0; + for (addr = 0xbb90; addr < 0xbbfa; ++addr) { + pack[i * 2 + 2] = addr; + pack[i * 2 + 3] = 0; + ++i; + if (i == 10 || addr == 0xbbf9) { + pack[0] = 0x2000 | i; + ret = copy_packages(code + cnt, pack, 1, space - cnt); + if (ret < 0) + return -1; + cnt += ret; + i = 0; + memset(pack, 0, 64); + } + } + return cnt; +} + +static int do_special(struct go7007 *go, u16 type, __le16 *code, int space, + int *framelen) +{ + switch (type) { + case SPECIAL_FRM_HEAD: + switch (go->format) { + case GO7007_FORMAT_MJPEG: + return gen_mjpeghdr_to_package(go, code, space); + case GO7007_FORMAT_MPEG1: + case GO7007_FORMAT_MPEG2: + return gen_mpeg1hdr_to_package(go, code, space, + framelen); + case GO7007_FORMAT_MPEG4: + return gen_mpeg4hdr_to_package(go, code, space, + framelen); + } + case SPECIAL_BRC_CTRL: + return brctrl_to_package(go, code, space, framelen); + case SPECIAL_CONFIG: + return config_package(go, code, space); + case SPECIAL_SEQHEAD: + switch (go->format) { + case GO7007_FORMAT_MPEG1: + case GO7007_FORMAT_MPEG2: + return seqhead_to_package(go, code, space, + mpeg1_sequence_header); + case GO7007_FORMAT_MPEG4: + return seqhead_to_package(go, code, space, + mpeg4_sequence_header); + default: + return 0; + } + case SPECIAL_AV_SYNC: + return avsync_to_package(go, code, space); + case SPECIAL_FINAL: + return final_package(go, code, space); + case SPECIAL_AUDIO: + return audio_to_package(go, code, space); + case SPECIAL_MODET: + return modet_to_package(go, code, space); + } + printk(KERN_ERR + "go7007: firmware file contains unsupported feature %04x\n", + type); + return -1; +} + +int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen) +{ + const struct firmware *fw_entry; + __le16 *code, *src; + int framelen[8] = { }; /* holds the lengths of empty frame templates */ + int codespace = 64 * 1024, i = 0, srclen, chunk_len, chunk_flags; + int mode_flag; + int ret; + + switch (go->format) { + case GO7007_FORMAT_MJPEG: + mode_flag = FLAG_MODE_MJPEG; + break; + case GO7007_FORMAT_MPEG1: + mode_flag = FLAG_MODE_MPEG1; + break; + case GO7007_FORMAT_MPEG2: + mode_flag = FLAG_MODE_MPEG2; + break; + case GO7007_FORMAT_MPEG4: + mode_flag = FLAG_MODE_MPEG4; + break; + default: + return -1; + } + if (request_firmware(&fw_entry, go->board_info->firmware, go->dev)) { + printk(KERN_ERR + "go7007: unable to load firmware from file \"%s\"\n", + go->board_info->firmware); + return -1; + } + code = kmalloc(codespace * 2, GFP_KERNEL); + if (code == NULL) { + printk(KERN_ERR "go7007: unable to allocate %d bytes for " + "firmware construction\n", codespace * 2); + goto fw_failed; + } + memset(code, 0, codespace * 2); + src = (__le16 *)fw_entry->data; + srclen = fw_entry->size / 2; + while (srclen >= 2) { + chunk_flags = __le16_to_cpu(src[0]); + chunk_len = __le16_to_cpu(src[1]); + if (chunk_len + 2 > srclen) { + printk(KERN_ERR "go7007: firmware file \"%s\" " + "appears to be corrupted\n", + go->board_info->firmware); + goto fw_failed; + } + if (chunk_flags & mode_flag) { + if (chunk_flags & FLAG_SPECIAL) { + ret = do_special(go, __le16_to_cpu(src[2]), + &code[i], codespace - i, framelen); + if (ret < 0) { + printk(KERN_ERR "go7007: insufficient " + "memory for firmware " + "construction\n"); + goto fw_failed; + } + i += ret; + } else { + if (codespace - i < chunk_len) { + printk(KERN_ERR "go7007: insufficient " + "memory for firmware " + "construction\n"); + goto fw_failed; + } + memcpy(&code[i], &src[2], chunk_len * 2); + i += chunk_len; + } + } + srclen -= chunk_len + 2; + src += chunk_len + 2; + } + release_firmware(fw_entry); + *fw = (u8 *)code; + *fwlen = i * 2; + return 0; + +fw_failed: + kfree(code); + release_firmware(fw_entry); + return -1; +} diff --git a/linux/drivers/staging/go7007/go7007-i2c.c b/linux/drivers/staging/go7007/go7007-i2c.c new file mode 100644 index 000000000..c82867fdd --- /dev/null +++ b/linux/drivers/staging/go7007/go7007-i2c.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "go7007-priv.h" +#include "wis-i2c.h" + +/********************* Driver for on-board I2C adapter *********************/ + +/* #define GO7007_I2C_DEBUG */ + +#define SPI_I2C_ADDR_BASE 0x1400 +#define STATUS_REG_ADDR (SPI_I2C_ADDR_BASE + 0x2) +#define I2C_CTRL_REG_ADDR (SPI_I2C_ADDR_BASE + 0x6) +#define I2C_DEV_UP_ADDR_REG_ADDR (SPI_I2C_ADDR_BASE + 0x7) +#define I2C_LO_ADDR_REG_ADDR (SPI_I2C_ADDR_BASE + 0x8) +#define I2C_DATA_REG_ADDR (SPI_I2C_ADDR_BASE + 0x9) +#define I2C_CLKFREQ_REG_ADDR (SPI_I2C_ADDR_BASE + 0xa) + +#define I2C_STATE_MASK 0x0007 +#define I2C_READ_READY_MASK 0x0008 + +/* There is only one I2C port on the TW2804 that feeds all four GO7007 VIPs + * on the Adlink PCI-MPG24, so access is shared between all of them. */ +static DECLARE_MUTEX(adlink_mpg24_i2c_lock); + +static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read, + u16 command, int flags, u8 *data) +{ + int i, ret = -1; + u16 val; + + if (go->status == STATUS_SHUTDOWN) + return -1; + +#ifdef GO7007_I2C_DEBUG + if (read) + printk(KERN_DEBUG "go7007-i2c: reading 0x%02x on 0x%02x\n", + command, addr); + else + printk(KERN_DEBUG + "go7007-i2c: writing 0x%02x to 0x%02x on 0x%02x\n", + *data, command, addr); +#endif + + down(&go->hw_lock); + + if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { + /* Bridge the I2C port on this GO7007 to the shared bus */ + down(&adlink_mpg24_i2c_lock); + go7007_write_addr(go, 0x3c82, 0x0020); + } + + /* Wait for I2C adapter to be ready */ + for (i = 0; i < 10; ++i) { + if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0) + goto i2c_done; + if (!(val & I2C_STATE_MASK)) + break; + msleep(100); + } + if (i == 10) { + printk(KERN_ERR "go7007-i2c: I2C adapter is hung\n"); + goto i2c_done; + } + + /* Set target register (command) */ + go7007_write_addr(go, I2C_CTRL_REG_ADDR, flags); + go7007_write_addr(go, I2C_LO_ADDR_REG_ADDR, command); + + /* If we're writing, send the data and target address and we're done */ + if (!read) { + go7007_write_addr(go, I2C_DATA_REG_ADDR, *data); + go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR, + (addr << 9) | (command >> 8)); + ret = 0; + goto i2c_done; + } + + /* Otherwise, we're reading. First clear i2c_rx_data_rdy. */ + if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0) + goto i2c_done; + + /* Send the target address plus read flag */ + go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR, + (addr << 9) | 0x0100 | (command >> 8)); + + /* Wait for i2c_rx_data_rdy */ + for (i = 0; i < 10; ++i) { + if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0) + goto i2c_done; + if (val & I2C_READ_READY_MASK) + break; + msleep(100); + } + if (i == 10) { + printk(KERN_ERR "go7007-i2c: I2C adapter is hung\n"); + goto i2c_done; + } + + /* Retrieve the read byte */ + if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0) + goto i2c_done; + *data = val; + ret = 0; + +i2c_done: + if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { + /* Isolate the I2C port on this GO7007 from the shared bus */ + go7007_write_addr(go, 0x3c82, 0x0000); + up(&adlink_mpg24_i2c_lock); + } + up(&go->hw_lock); + return ret; +} + +static int go7007_smbus_xfer(struct i2c_adapter *adapter, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data) +{ + struct go7007 *go = i2c_get_adapdata(adapter); + + if (size != I2C_SMBUS_BYTE_DATA) + return -1; + return go7007_i2c_xfer(go, addr, read_write == I2C_SMBUS_READ, command, + flags & I2C_CLIENT_SCCB ? 0x10 : 0x00, &data->byte); +} + +/* VERY LIMITED I2C master xfer function -- only needed because the + * SMBus functions only support 8-bit commands and the SAA7135 uses + * 16-bit commands. The I2C interface on the GO7007, as limited as + * it is, does support this mode. */ + +static int go7007_i2c_master_xfer(struct i2c_adapter *adapter, + struct i2c_msg msgs[], int num) +{ + struct go7007 *go = i2c_get_adapdata(adapter); + int i; + + for (i = 0; i < num; ++i) { + /* We can only do two things here -- write three bytes, or + * write two bytes and read one byte. */ + if (msgs[i].len == 2) { + if (i + 1 == num || msgs[i].addr != msgs[i + 1].addr || + (msgs[i].flags & I2C_M_RD) || + !(msgs[i + 1].flags & I2C_M_RD) || + msgs[i + 1].len != 1) + return -1; + if (go7007_i2c_xfer(go, msgs[i].addr, 1, + (msgs[i].buf[0] << 8) | msgs[i].buf[1], + 0x01, &msgs[i + 1].buf[0]) < 0) + return -1; + ++i; + } else if (msgs[i].len == 3) { + if (msgs[i].flags & I2C_M_RD) + return -1; + if (msgs[i].len != 3) + return -1; + if (go7007_i2c_xfer(go, msgs[i].addr, 0, + (msgs[i].buf[0] << 8) | msgs[i].buf[1], + 0x01, &msgs[i].buf[2]) < 0) + return -1; + } else + return -1; + } + + return 0; +} + +static u32 go7007_functionality(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_BYTE_DATA; +} + +static struct i2c_algorithm go7007_algo = { + .smbus_xfer = go7007_smbus_xfer, + .master_xfer = go7007_i2c_master_xfer, + .functionality = go7007_functionality, +}; + +static struct i2c_adapter go7007_adap_templ = { + .owner = THIS_MODULE, + .name = "WIS GO7007SB", + .algo = &go7007_algo, +}; + +int go7007_i2c_init(struct go7007 *go) +{ + memcpy(&go->i2c_adapter, &go7007_adap_templ, + sizeof(go7007_adap_templ)); + go->i2c_adapter.dev.parent = go->dev; + i2c_set_adapdata(&go->i2c_adapter, go); + if (i2c_add_adapter(&go->i2c_adapter) < 0) { + printk(KERN_ERR + "go7007-i2c: error: i2c_add_adapter failed\n"); + return -1; + } + return 0; +} diff --git a/linux/drivers/staging/go7007/go7007-priv.h b/linux/drivers/staging/go7007/go7007-priv.h new file mode 100644 index 000000000..178d18119 --- /dev/null +++ b/linux/drivers/staging/go7007/go7007-priv.h @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +/* + * This is the private include file for the go7007 driver. It should not + * be included by anybody but the driver itself, and especially not by + * user-space applications. + */ + +struct go7007; + +/* IDs to activate board-specific support code */ +#define GO7007_BOARDID_MATRIX_II 0 +#define GO7007_BOARDID_MATRIX_RELOAD 1 +#define GO7007_BOARDID_STAR_TREK 2 +#define GO7007_BOARDID_PCI_VOYAGER 3 +#define GO7007_BOARDID_XMEN 4 +#define GO7007_BOARDID_XMEN_II 5 +#define GO7007_BOARDID_XMEN_III 6 +#define GO7007_BOARDID_MATRIX_REV 7 +#define GO7007_BOARDID_PX_M402U 16 +#define GO7007_BOARDID_PX_TV402U_ANY 17 /* need to check tuner model */ +#define GO7007_BOARDID_PX_TV402U_NA 18 /* detected NTSC tuner */ +#define GO7007_BOARDID_PX_TV402U_EU 19 /* detected PAL tuner */ +#define GO7007_BOARDID_PX_TV402U_JP 20 /* detected NTSC-J tuner */ +#define GO7007_BOARDID_LIFEVIEW_LR192 21 /* TV Walker Ultra */ +#define GO7007_BOARDID_ENDURA 22 +#define GO7007_BOARDID_ADLINK_MPG24 23 +#define GO7007_BOARDID_SENSORAY_2250 24 /* Sensoray 2250/2251 */ + +/* Various characteristics of each board */ +#define GO7007_BOARD_HAS_AUDIO (1<<0) +#define GO7007_BOARD_USE_ONBOARD_I2C (1<<1) +#define GO7007_BOARD_HAS_TUNER (1<<2) + +/* Characteristics of sensor devices */ +#define GO7007_SENSOR_VALID_POLAR (1<<0) +#define GO7007_SENSOR_HREF_POLAR (1<<1) +#define GO7007_SENSOR_VREF_POLAR (1<<2) +#define GO7007_SENSOR_FIELD_ID_POLAR (1<<3) +#define GO7007_SENSOR_BIT_WIDTH (1<<4) +#define GO7007_SENSOR_VALID_ENABLE (1<<5) +#define GO7007_SENSOR_656 (1<<6) +#define GO7007_SENSOR_CONFIG_MASK 0x7f +#define GO7007_SENSOR_TV (1<<7) +#define GO7007_SENSOR_VBI (1<<8) +#define GO7007_SENSOR_SCALING (1<<9) + +/* Characteristics of audio sensor devices */ +#define GO7007_AUDIO_I2S_MODE_1 (1) +#define GO7007_AUDIO_I2S_MODE_2 (2) +#define GO7007_AUDIO_I2S_MODE_3 (3) +#define GO7007_AUDIO_BCLK_POLAR (1<<2) +#define GO7007_AUDIO_WORD_14 (14<<4) +#define GO7007_AUDIO_WORD_16 (16<<4) +#define GO7007_AUDIO_ONE_CHANNEL (1<<11) +#define GO7007_AUDIO_I2S_MASTER (1<<16) +#define GO7007_AUDIO_OKI_MODE (1<<17) + +struct go7007_board_info { + char *firmware; + unsigned int flags; + int hpi_buffer_cap; + unsigned int sensor_flags; + int sensor_width; + int sensor_height; + int sensor_framerate; + int sensor_h_offset; + int sensor_v_offset; + unsigned int audio_flags; + int audio_rate; + int audio_bclk_div; + int audio_main_div; + int num_i2c_devs; + struct { + const char *type; + int id; + int addr; + } i2c_devs[4]; + int num_inputs; + struct { + int video_input; + int audio_input; + char *name; + } inputs[4]; +}; + +struct go7007_hpi_ops { + int (*interface_reset)(struct go7007 *go); + int (*write_interrupt)(struct go7007 *go, int addr, int data); + int (*read_interrupt)(struct go7007 *go); + int (*stream_start)(struct go7007 *go); + int (*stream_stop)(struct go7007 *go); + int (*send_firmware)(struct go7007 *go, u8 *data, int len); + int (*send_command)(struct go7007 *go, unsigned int cmd, void *arg); +}; + +/* The video buffer size must be a multiple of PAGE_SIZE */ +#define GO7007_BUF_PAGES (128 * 1024 / PAGE_SIZE) +#define GO7007_BUF_SIZE (GO7007_BUF_PAGES << PAGE_SHIFT) + +struct go7007_buffer { + struct go7007 *go; /* Reverse reference for VMA ops */ + int index; /* Reverse reference for DQBUF */ + enum { BUF_STATE_IDLE, BUF_STATE_QUEUED, BUF_STATE_DONE } state; + u32 seq; + struct timeval timestamp; + struct list_head stream; + struct page *pages[GO7007_BUF_PAGES + 1]; /* extra for straddling */ + unsigned long user_addr; + unsigned int page_count; + unsigned int offset; + unsigned int bytesused; + unsigned int frame_offset; + u32 modet_active; + int mapped; +}; + +struct go7007_file { + struct go7007 *go; + struct semaphore lock; + int buf_count; + struct go7007_buffer *bufs; +}; + +#define GO7007_FORMAT_MJPEG 0 +#define GO7007_FORMAT_MPEG4 1 +#define GO7007_FORMAT_MPEG1 2 +#define GO7007_FORMAT_MPEG2 3 +#define GO7007_FORMAT_H263 4 + +#define GO7007_RATIO_1_1 0 +#define GO7007_RATIO_4_3 1 +#define GO7007_RATIO_16_9 2 + +enum go7007_parser_state { + STATE_DATA, + STATE_00, + STATE_00_00, + STATE_00_00_01, + STATE_FF, + STATE_VBI_LEN_A, + STATE_VBI_LEN_B, + STATE_MODET_MAP, + STATE_UNPARSED, +}; + +struct go7007 { + struct device *dev; + struct go7007_board_info *board_info; + unsigned int board_id; + int tuner_type; + int channel_number; /* for multi-channel boards like Adlink PCI-MPG24 */ + char name[64]; + struct video_device *video_dev; + int ref_count; + enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status; + spinlock_t spinlock; + struct semaphore hw_lock; + int streaming; + int in_use; + int audio_enabled; + + /* Video input */ + int input; + enum { GO7007_STD_NTSC, GO7007_STD_PAL, GO7007_STD_OTHER } standard; + int sensor_framerate; + int width; + int height; + int encoder_h_offset; + int encoder_v_offset; + unsigned int encoder_h_halve:1; + unsigned int encoder_v_halve:1; + unsigned int encoder_subsample:1; + + /* Encoder config */ + int format; + int bitrate; + int fps_scale; + int pali; + int aspect_ratio; + int gop_size; + unsigned int ipb:1; + unsigned int closed_gop:1; + unsigned int repeat_seqhead:1; + unsigned int seq_header_enable:1; + unsigned int gop_header_enable:1; + unsigned int dvd_mode:1; + unsigned int interlace_coding:1; + + /* Motion detection */ + unsigned int modet_enable:1; + struct { + unsigned int enable:1; + int pixel_threshold; + int motion_threshold; + int mb_threshold; + } modet[4]; + unsigned char modet_map[1624]; + unsigned char active_map[216]; + + /* Video streaming */ + struct go7007_buffer *active_buf; + enum go7007_parser_state state; + int parse_length; + u16 modet_word; + int seen_frame; + u32 next_seq; + struct list_head stream; + wait_queue_head_t frame_waitq; + + /* Audio streaming */ + void (*audio_deliver)(struct go7007 *go, u8 *buf, int length); + void *snd_context; + + /* I2C */ + int i2c_adapter_online; + struct i2c_adapter i2c_adapter; + + /* HPI driver */ + struct go7007_hpi_ops *hpi_ops; + void *hpi_context; + int interrupt_available; + wait_queue_head_t interrupt_waitq; + unsigned short interrupt_value; + unsigned short interrupt_data; +}; + +/* All of these must be called with the hpi_lock semaphore held! */ +#define go7007_interface_reset(go) \ + ((go)->hpi_ops->interface_reset(go)) +#define go7007_write_interrupt(go, x, y) \ + ((go)->hpi_ops->write_interrupt)((go), (x), (y)) +#define go7007_stream_start(go) \ + ((go)->hpi_ops->stream_start(go)) +#define go7007_stream_stop(go) \ + ((go)->hpi_ops->stream_stop(go)) +#define go7007_send_firmware(go, x, y) \ + ((go)->hpi_ops->send_firmware)((go), (x), (y)) +#define go7007_write_addr(go, x, y) \ + ((go)->hpi_ops->write_interrupt)((go), (x)|0x8000, (y)) + +/* go7007-driver.c */ +int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data); +int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data); +int go7007_boot_encoder(struct go7007 *go, int init_i2c); +int go7007_reset_encoder(struct go7007 *go); +int go7007_register_encoder(struct go7007 *go); +int go7007_start_encoder(struct go7007 *go); +void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length); +struct go7007 *go7007_alloc(struct go7007_board_info *board, + struct device *dev); +void go7007_remove(struct go7007 *go); + +/* go7007-fw.c */ +int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen); + +/* go7007-i2c.c */ +int go7007_i2c_init(struct go7007 *go); +int go7007_i2c_remove(struct go7007 *go); + +/* go7007-v4l2.c */ +int go7007_v4l2_init(struct go7007 *go); +void go7007_v4l2_remove(struct go7007 *go); + +/* snd-go7007.c */ +int go7007_snd_init(struct go7007 *go); +int go7007_snd_remove(struct go7007 *go); diff --git a/linux/drivers/staging/go7007/go7007-usb.c b/linux/drivers/staging/go7007/go7007-usb.c new file mode 100644 index 000000000..aa4a9e0b9 --- /dev/null +++ b/linux/drivers/staging/go7007/go7007-usb.c @@ -0,0 +1,1287 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "go7007-priv.h" +#include "wis-i2c.h" + +static unsigned int assume_endura; +module_param(assume_endura, int, 0644); +MODULE_PARM_DESC(assume_endura, "when probing fails, hardware is a Pelco Endura"); + +/* #define GO7007_USB_DEBUG */ +/* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */ + +#define HPI_STATUS_ADDR 0xFFF4 +#define INT_PARAM_ADDR 0xFFF6 +#define INT_INDEX_ADDR 0xFFF8 + +/* + * Pipes on EZ-USB interface: + * 0 snd - Control + * 0 rcv - Control + * 2 snd - Download firmware (control) + * 4 rcv - Read Interrupt (interrupt) + * 6 rcv - Read Video (bulk) + * 8 rcv - Read Audio (bulk) + */ + +#define GO7007_USB_EZUSB (1<<0) +#define GO7007_USB_EZUSB_I2C (1<<1) + +struct go7007_usb_board { + unsigned int flags; + struct go7007_board_info main_info; +}; + +struct go7007_usb { + struct go7007_usb_board *board; + struct semaphore i2c_lock; + struct usb_device *usbdev; + struct urb *video_urbs[8]; + struct urb *audio_urbs[8]; + struct urb *intr_urb; +}; + +/*********************** Product specification data ***********************/ + +static struct go7007_usb_board board_matrix_ii = { + .flags = GO7007_USB_EZUSB, + .main_info = { + .firmware = "go7007tv.bin", + .flags = GO7007_BOARD_HAS_AUDIO | + GO7007_BOARD_USE_ONBOARD_I2C, + .audio_flags = GO7007_AUDIO_I2S_MODE_1 | + GO7007_AUDIO_WORD_16, + .audio_rate = 48000, + .audio_bclk_div = 8, + .audio_main_div = 2, + .hpi_buffer_cap = 7, + .sensor_flags = GO7007_SENSOR_656 | + GO7007_SENSOR_VALID_ENABLE | + GO7007_SENSOR_TV | + GO7007_SENSOR_VBI | + GO7007_SENSOR_SCALING, + .num_i2c_devs = 1, + .i2c_devs = { + { + .type = "wis_saa7115", + .id = I2C_DRIVERID_WIS_SAA7115, + .addr = 0x20, + }, + }, + .num_inputs = 2, + .inputs = { + { + .video_input = 0, + .name = "Composite", + }, + { + .video_input = 9, + .name = "S-Video", + }, + }, + }, +}; + +static struct go7007_usb_board board_matrix_reload = { + .flags = GO7007_USB_EZUSB, + .main_info = { + .firmware = "go7007tv.bin", + .flags = GO7007_BOARD_HAS_AUDIO | + GO7007_BOARD_USE_ONBOARD_I2C, + .audio_flags = GO7007_AUDIO_I2S_MODE_1 | + GO7007_AUDIO_I2S_MASTER | + GO7007_AUDIO_WORD_16, + .audio_rate = 48000, + .audio_bclk_div = 8, + .audio_main_div = 2, + .hpi_buffer_cap = 7, + .sensor_flags = GO7007_SENSOR_656 | + GO7007_SENSOR_TV, + .num_i2c_devs = 1, + .i2c_devs = { + { + .type = "wis_saa7113", + .id = I2C_DRIVERID_WIS_SAA7113, + .addr = 0x25, + }, + }, + .num_inputs = 2, + .inputs = { + { + .video_input = 0, + .name = "Composite", + }, + { + .video_input = 9, + .name = "S-Video", + }, + }, + }, +}; + +static struct go7007_usb_board board_star_trek = { + .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, + .main_info = { + .firmware = "go7007tv.bin", + .flags = GO7007_BOARD_HAS_AUDIO, /* | + GO7007_BOARD_HAS_TUNER, */ + .sensor_flags = GO7007_SENSOR_656 | + GO7007_SENSOR_VALID_ENABLE | + GO7007_SENSOR_TV | + GO7007_SENSOR_VBI | + GO7007_SENSOR_SCALING, + .audio_flags = GO7007_AUDIO_I2S_MODE_1 | + GO7007_AUDIO_WORD_16, + .audio_bclk_div = 8, + .audio_main_div = 2, + .hpi_buffer_cap = 7, + .num_i2c_devs = 1, + .i2c_devs = { + { + .type = "wis_saa7115", + .id = I2C_DRIVERID_WIS_SAA7115, + .addr = 0x20, + }, + }, + .num_inputs = 2, + .inputs = { + { + .video_input = 1, + /* .audio_input = AUDIO_EXTERN, */ + .name = "Composite", + }, + { + .video_input = 8, + /* .audio_input = AUDIO_EXTERN, */ + .name = "S-Video", + }, + /* { + * .video_input = 3, + * .audio_input = AUDIO_TUNER, + * .name = "Tuner", + * }, + */ + }, + }, +}; + +static struct go7007_usb_board board_px_tv402u = { + .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, + .main_info = { + .firmware = "go7007tv.bin", + .flags = GO7007_BOARD_HAS_AUDIO | + GO7007_BOARD_HAS_TUNER, + .sensor_flags = GO7007_SENSOR_656 | + GO7007_SENSOR_VALID_ENABLE | + GO7007_SENSOR_TV | + GO7007_SENSOR_VBI | + GO7007_SENSOR_SCALING, + .audio_flags = GO7007_AUDIO_I2S_MODE_1 | + GO7007_AUDIO_WORD_16, + .audio_bclk_div = 8, + .audio_main_div = 2, + .hpi_buffer_cap = 7, + .num_i2c_devs = 3, + .i2c_devs = { + { + .type = "wis_saa7115", + .id = I2C_DRIVERID_WIS_SAA7115, + .addr = 0x20, + }, + { + .type = "wis_uda1342", + .id = I2C_DRIVERID_WIS_UDA1342, + .addr = 0x1a, + }, + { + .type = "wis_sony_tuner", + .id = I2C_DRIVERID_WIS_SONY_TUNER, + .addr = 0x60, + }, + }, + .num_inputs = 3, + .inputs = { + { + .video_input = 1, + .audio_input = TVAUDIO_INPUT_EXTERN, + .name = "Composite", + }, + { + .video_input = 8, + .audio_input = TVAUDIO_INPUT_EXTERN, + .name = "S-Video", + }, + { + .video_input = 3, + .audio_input = TVAUDIO_INPUT_TUNER, + .name = "Tuner", + }, + }, + }, +}; + +static struct go7007_usb_board board_xmen = { + .flags = 0, + .main_info = { + .firmware = "go7007tv.bin", + .flags = GO7007_BOARD_USE_ONBOARD_I2C, + .hpi_buffer_cap = 0, + .sensor_flags = GO7007_SENSOR_VREF_POLAR, + .sensor_width = 320, + .sensor_height = 240, + .sensor_framerate = 30030, + .audio_flags = GO7007_AUDIO_ONE_CHANNEL | + GO7007_AUDIO_I2S_MODE_3 | + GO7007_AUDIO_WORD_14 | + GO7007_AUDIO_I2S_MASTER | + GO7007_AUDIO_BCLK_POLAR | + GO7007_AUDIO_OKI_MODE, + .audio_rate = 8000, + .audio_bclk_div = 48, + .audio_main_div = 1, + .num_i2c_devs = 1, + .i2c_devs = { + { + .type = "wis_ov7640", + .id = I2C_DRIVERID_WIS_OV7640, + .addr = 0x21, + }, + }, + .num_inputs = 1, + .inputs = { + { + .name = "Camera", + }, + }, + }, +}; + +static struct go7007_usb_board board_matrix_revolution = { + .flags = GO7007_USB_EZUSB, + .main_info = { + .firmware = "go7007tv.bin", + .flags = GO7007_BOARD_HAS_AUDIO | + GO7007_BOARD_USE_ONBOARD_I2C, + .audio_flags = GO7007_AUDIO_I2S_MODE_1 | + GO7007_AUDIO_I2S_MASTER | + GO7007_AUDIO_WORD_16, + .audio_rate = 48000, + .audio_bclk_div = 8, + .audio_main_div = 2, + .hpi_buffer_cap = 7, + .sensor_flags = GO7007_SENSOR_656 | + GO7007_SENSOR_TV | + GO7007_SENSOR_VBI, + .num_i2c_devs = 1, + .i2c_devs = { + { + .type = "wis_tw9903", + .id = I2C_DRIVERID_WIS_TW9903, + .addr = 0x44, + }, + }, + .num_inputs = 2, + .inputs = { + { + .video_input = 2, + .name = "Composite", + }, + { + .video_input = 8, + .name = "S-Video", + }, + }, + }, +}; + +static struct go7007_usb_board board_lifeview_lr192 = { + .flags = GO7007_USB_EZUSB, + .main_info = { + .firmware = "go7007tv.bin", + .flags = GO7007_BOARD_HAS_AUDIO | + GO7007_BOARD_USE_ONBOARD_I2C, + .audio_flags = GO7007_AUDIO_I2S_MODE_1 | + GO7007_AUDIO_WORD_16, + .audio_rate = 48000, + .audio_bclk_div = 8, + .audio_main_div = 2, + .hpi_buffer_cap = 7, + .sensor_flags = GO7007_SENSOR_656 | + GO7007_SENSOR_VALID_ENABLE | + GO7007_SENSOR_TV | + GO7007_SENSOR_VBI | + GO7007_SENSOR_SCALING, + .num_i2c_devs = 0, + .num_inputs = 1, + .inputs = { + { + .video_input = 0, + .name = "Composite", + }, + }, + }, +}; + +static struct go7007_usb_board board_endura = { + .flags = 0, + .main_info = { + .firmware = "go7007tv.bin", + .flags = 0, + .audio_flags = GO7007_AUDIO_I2S_MODE_1 | + GO7007_AUDIO_I2S_MASTER | + GO7007_AUDIO_WORD_16, + .audio_rate = 8000, + .audio_bclk_div = 48, + .audio_main_div = 8, + .hpi_buffer_cap = 0, + .sensor_flags = GO7007_SENSOR_656 | + GO7007_SENSOR_TV, + .sensor_h_offset = 8, + .num_i2c_devs = 0, + .num_inputs = 1, + .inputs = { + { + .name = "Camera", + }, + }, + }, +}; + +static struct go7007_usb_board board_adlink_mpg24 = { + .flags = 0, + .main_info = { + .firmware = "go7007tv.bin", + .flags = GO7007_BOARD_USE_ONBOARD_I2C, + .audio_flags = GO7007_AUDIO_I2S_MODE_1 | + GO7007_AUDIO_I2S_MASTER | + GO7007_AUDIO_WORD_16, + .audio_rate = 48000, + .audio_bclk_div = 8, + .audio_main_div = 2, + .hpi_buffer_cap = 0, + .sensor_flags = GO7007_SENSOR_656 | + GO7007_SENSOR_TV | + GO7007_SENSOR_VBI, + .num_i2c_devs = 1, + .i2c_devs = { + { + .type = "wis_twTW2804", + .id = I2C_DRIVERID_WIS_TW2804, + .addr = 0x00, /* yes, really */ + }, + }, + .num_inputs = 1, + .inputs = { + { + .name = "Composite", + }, + }, + }, +}; + +static struct go7007_usb_board board_sensoray_2250 = { + .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, + .main_info = { + .firmware = "go7007tv.bin", + .audio_flags = GO7007_AUDIO_I2S_MODE_1 | + GO7007_AUDIO_I2S_MASTER | + GO7007_AUDIO_WORD_16, + .flags = GO7007_BOARD_HAS_AUDIO, + .audio_rate = 48000, + .audio_bclk_div = 8, + .audio_main_div = 2, + .hpi_buffer_cap = 7, + .sensor_flags = GO7007_SENSOR_656 | + GO7007_SENSOR_TV, + .num_i2c_devs = 1, + .i2c_devs = { + { + .type = "s2250_board", + .id = I2C_DRIVERID_S2250, + .addr = 0x43, + }, + }, + .num_inputs = 2, + .inputs = { + { + .video_input = 0, + .name = "Composite", + }, + { + .video_input = 1, + .name = "S-Video", + }, + }, + }, +}; + +static struct usb_device_id go7007_usb_id_table[] = { + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | + USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ + .idProduct = 0x7007, /* Product ID of GO7007SB chip */ + .bcdDevice_lo = 0x200, /* Revision number of XMen */ + .bcdDevice_hi = 0x200, + .bInterfaceClass = 255, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 255, + .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN, + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, + .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ + .idProduct = 0x7007, /* Product ID of GO7007SB chip */ + .bcdDevice_lo = 0x202, /* Revision number of Matrix II */ + .bcdDevice_hi = 0x202, + .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_II, + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, + .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ + .idProduct = 0x7007, /* Product ID of GO7007SB chip */ + .bcdDevice_lo = 0x204, /* Revision number of Matrix */ + .bcdDevice_hi = 0x204, /* Reloaded */ + .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD, + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | + USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ + .idProduct = 0x7007, /* Product ID of GO7007SB chip */ + .bcdDevice_lo = 0x205, /* Revision number of XMen-II */ + .bcdDevice_hi = 0x205, + .bInterfaceClass = 255, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 255, + .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_II, + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, + .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ + .idProduct = 0x7007, /* Product ID of GO7007SB chip */ + .bcdDevice_lo = 0x208, /* Revision number of Star Trek */ + .bcdDevice_hi = 0x208, + .driver_info = (kernel_ulong_t)GO7007_BOARDID_STAR_TREK, + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | + USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ + .idProduct = 0x7007, /* Product ID of GO7007SB chip */ + .bcdDevice_lo = 0x209, /* Revision number of XMen-III */ + .bcdDevice_hi = 0x209, + .bInterfaceClass = 255, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 255, + .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_III, + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, + .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ + .idProduct = 0x7007, /* Product ID of GO7007SB chip */ + .bcdDevice_lo = 0x210, /* Revision number of Matrix */ + .bcdDevice_hi = 0x210, /* Revolution */ + .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_REV, + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, + .idVendor = 0x093b, /* Vendor ID of Plextor */ + .idProduct = 0xa102, /* Product ID of M402U */ + .bcdDevice_lo = 0x1, /* revision number of Blueberry */ + .bcdDevice_hi = 0x1, + .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_M402U, + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, + .idVendor = 0x093b, /* Vendor ID of Plextor */ + .idProduct = 0xa104, /* Product ID of TV402U */ + .bcdDevice_lo = 0x1, + .bcdDevice_hi = 0x1, + .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_TV402U_ANY, + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, + .idVendor = 0x10fd, /* Vendor ID of Anubis Electronics */ + .idProduct = 0xde00, /* Product ID of Lifeview LR192 */ + .bcdDevice_lo = 0x1, + .bcdDevice_hi = 0x1, + .driver_info = (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192, + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, + .idVendor = 0x1943, /* Vendor ID Sensoray */ + .idProduct = 0x2250, /* Product ID of 2250/2251 */ + .bcdDevice_lo = 0x1, + .bcdDevice_hi = 0x1, + .driver_info = (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250, + }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, go7007_usb_id_table); + +/********************* Driver for EZ-USB HPI interface *********************/ + +static int go7007_usb_vendor_request(struct go7007 *go, int request, + int value, int index, void *transfer_buffer, int length, int in) +{ + struct go7007_usb *usb = go->hpi_context; + int timeout = 5000; + + if (in) { + return usb_control_msg(usb->usbdev, + usb_rcvctrlpipe(usb->usbdev, 0), request, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + value, index, transfer_buffer, length, timeout); + } else { + return usb_control_msg(usb->usbdev, + usb_sndctrlpipe(usb->usbdev, 0), request, + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, index, transfer_buffer, length, timeout); + } +} + +static int go7007_usb_interface_reset(struct go7007 *go) +{ + struct go7007_usb *usb = go->hpi_context; + u16 intr_val, intr_data; + + /* Reset encoder */ + if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) + return -1; + msleep(100); + + if (usb->board->flags & GO7007_USB_EZUSB) { + /* Reset buffer in EZ-USB */ +#ifdef GO7007_USB_DEBUG + printk(KERN_DEBUG "go7007-usb: resetting EZ-USB buffers\n"); +#endif + if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 || + go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0) + return -1; + + /* Reset encoder again */ + if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) + return -1; + msleep(100); + } + + /* Wait for an interrupt to indicate successful hardware reset */ + if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || + (intr_val & ~0x1) != 0x55aa) { + printk(KERN_ERR + "go7007-usb: unable to reset the USB interface\n"); + return -1; + } + return 0; +} + +static int go7007_usb_ezusb_write_interrupt(struct go7007 *go, + int addr, int data) +{ + struct go7007_usb *usb = go->hpi_context; + int i, r; + u16 status_reg; + int timeout = 500; + +#ifdef GO7007_USB_DEBUG + printk(KERN_DEBUG + "go7007-usb: WriteInterrupt: %04x %04x\n", addr, data); +#endif + + for (i = 0; i < 100; ++i) { + r = usb_control_msg(usb->usbdev, + usb_rcvctrlpipe(usb->usbdev, 0), 0x14, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0, HPI_STATUS_ADDR, &status_reg, + sizeof(status_reg), timeout); + if (r < 0) + goto write_int_error; + __le16_to_cpus(&status_reg); + if (!(status_reg & 0x0010)) + break; + msleep(10); + } + if (i == 100) { + printk(KERN_ERR + "go7007-usb: device is hung, status reg = 0x%04x\n", + status_reg); + return -1; + } + r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 0x12, + USB_TYPE_VENDOR | USB_RECIP_DEVICE, data, + INT_PARAM_ADDR, NULL, 0, timeout); + if (r < 0) + goto write_int_error; + r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), + 0x12, USB_TYPE_VENDOR | USB_RECIP_DEVICE, addr, + INT_INDEX_ADDR, NULL, 0, timeout); + if (r < 0) + goto write_int_error; + return 0; + +write_int_error: + printk(KERN_ERR "go7007-usb: error in WriteInterrupt: %d\n", r); + return r; +} + +static int go7007_usb_onboard_write_interrupt(struct go7007 *go, + int addr, int data) +{ + struct go7007_usb *usb = go->hpi_context; + u8 *tbuf; + int r; + int timeout = 500; + +#ifdef GO7007_USB_DEBUG + printk(KERN_DEBUG + "go7007-usb: WriteInterrupt: %04x %04x\n", addr, data); +#endif + + tbuf = kmalloc(8, GFP_KERNEL); + if (tbuf == NULL) + return -ENOMEM; + memset(tbuf, 0, 8); + tbuf[0] = data & 0xff; + tbuf[1] = data >> 8; + tbuf[2] = addr & 0xff; + tbuf[3] = addr >> 8; + r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 2), 0x00, + USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa, + 0xf0f0, tbuf, 8, timeout); + kfree(tbuf); + if (r < 0) { + printk(KERN_ERR "go7007-usb: error in WriteInterrupt: %d\n", r); + return r; + } + return 0; +} + +static void go7007_usb_readinterrupt_complete(struct urb *urb) +{ + struct go7007 *go = (struct go7007 *)urb->context; + u16 *regs = (u16 *)urb->transfer_buffer; + int status = urb->status; + + if (status) { + if (status != -ESHUTDOWN && + go->status != STATUS_SHUTDOWN) { + printk(KERN_ERR + "go7007-usb: error in read interrupt: %d\n", + urb->status); + } else { + wake_up(&go->interrupt_waitq); + return; + } + } else if (urb->actual_length != urb->transfer_buffer_length) { + printk(KERN_ERR "go7007-usb: short read in interrupt pipe!\n"); + } else { + go->interrupt_available = 1; + go->interrupt_data = __le16_to_cpu(regs[0]); + go->interrupt_value = __le16_to_cpu(regs[1]); +#ifdef GO7007_USB_DEBUG + printk(KERN_DEBUG "go7007-usb: ReadInterrupt: %04x %04x\n", + go->interrupt_value, go->interrupt_data); +#endif + } + + wake_up(&go->interrupt_waitq); +} + +static int go7007_usb_read_interrupt(struct go7007 *go) +{ + struct go7007_usb *usb = go->hpi_context; + int r; + + r = usb_submit_urb(usb->intr_urb, GFP_KERNEL); + if (r < 0) { + printk(KERN_ERR + "go7007-usb: unable to submit interrupt urb: %d\n", r); + return r; + } + return 0; +} + +static void go7007_usb_read_video_pipe_complete(struct urb *urb) +{ + struct go7007 *go = (struct go7007 *)urb->context; + int r, status = urb-> status; + + if (!go->streaming) { + wake_up_interruptible(&go->frame_waitq); + return; + } + if (status) { + printk(KERN_ERR "go7007-usb: error in video pipe: %d\n", status); + return; + } + if (urb->actual_length != urb->transfer_buffer_length) { + printk(KERN_ERR "go7007-usb: short read in video pipe!\n"); + return; + } + go7007_parse_video_stream(go, urb->transfer_buffer, urb->actual_length); + r = usb_submit_urb(urb, GFP_ATOMIC); + if (r < 0) + printk(KERN_ERR "go7007-usb: error in video pipe: %d\n", r); +} + +static void go7007_usb_read_audio_pipe_complete(struct urb *urb) +{ + struct go7007 *go = (struct go7007 *)urb->context; + int r, status = urb->status; + + if (!go->streaming) + return; + if (status) { + printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", status); + return; + } + if (urb->actual_length != urb->transfer_buffer_length) { + printk(KERN_ERR "go7007-usb: short read in audio pipe!\n"); + return; + } + if (go->audio_deliver != NULL) + go->audio_deliver(go, urb->transfer_buffer, urb->actual_length); + r = usb_submit_urb(urb, GFP_ATOMIC); + if (r < 0) + printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", r); +} + +static int go7007_usb_stream_start(struct go7007 *go) +{ + struct go7007_usb *usb = go->hpi_context; + int i, r; + + for (i = 0; i < 8; ++i) { + r = usb_submit_urb(usb->video_urbs[i], GFP_KERNEL); + if (r < 0) { + printk(KERN_ERR "go7007-usb: error submitting video " + "urb %d: %d\n", i, r); + goto video_submit_failed; + } + } + if (!go->audio_enabled) + return 0; + + for (i = 0; i < 8; ++i) { + r = usb_submit_urb(usb->audio_urbs[i], GFP_KERNEL); + if (r < 0) { + printk(KERN_ERR "go7007-usb: error submitting audio " + "urb %d: %d\n", i, r); + goto audio_submit_failed; + } + } + return 0; + +audio_submit_failed: + for (i = 0; i < 7; ++i) + usb_kill_urb(usb->audio_urbs[i]); +video_submit_failed: + for (i = 0; i < 8; ++i) + usb_kill_urb(usb->video_urbs[i]); + return -1; +} + +static int go7007_usb_stream_stop(struct go7007 *go) +{ + struct go7007_usb *usb = go->hpi_context; + int i; + + if (go->status == STATUS_SHUTDOWN) + return 0; + for (i = 0; i < 8; ++i) + usb_kill_urb(usb->video_urbs[i]); + if (go->audio_enabled) + for (i = 0; i < 8; ++i) + usb_kill_urb(usb->audio_urbs[i]); + return 0; +} + +static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len) +{ + struct go7007_usb *usb = go->hpi_context; + int transferred, pipe; + int timeout = 500; + +#ifdef GO7007_USB_DEBUG + printk(KERN_DEBUG "go7007-usb: DownloadBuffer sending %d bytes\n", len); +#endif + + if (usb->board->flags & GO7007_USB_EZUSB) + pipe = usb_sndbulkpipe(usb->usbdev, 2); + else + pipe = usb_sndbulkpipe(usb->usbdev, 3); + + return usb_bulk_msg(usb->usbdev, pipe, data, len, + &transferred, timeout); +} + +static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { + .interface_reset = go7007_usb_interface_reset, + .write_interrupt = go7007_usb_ezusb_write_interrupt, + .read_interrupt = go7007_usb_read_interrupt, + .stream_start = go7007_usb_stream_start, + .stream_stop = go7007_usb_stream_stop, + .send_firmware = go7007_usb_send_firmware, +}; + +static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { + .interface_reset = go7007_usb_interface_reset, + .write_interrupt = go7007_usb_onboard_write_interrupt, + .read_interrupt = go7007_usb_read_interrupt, + .stream_start = go7007_usb_stream_start, + .stream_stop = go7007_usb_stream_stop, + .send_firmware = go7007_usb_send_firmware, +}; + +/********************* Driver for EZ-USB I2C adapter *********************/ + +static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, + struct i2c_msg msgs[], int num) +{ + struct go7007 *go = i2c_get_adapdata(adapter); + struct go7007_usb *usb = go->hpi_context; + u8 buf[16]; + int buf_len, i; + int ret = -1; + + if (go->status == STATUS_SHUTDOWN) + return -1; + + down(&usb->i2c_lock); + + for (i = 0; i < num; ++i) { + /* The hardware command is "write some bytes then read some + * bytes", so we try to coalesce a write followed by a read + * into a single USB transaction */ + if (i + 1 < num && msgs[i].addr == msgs[i + 1].addr && + !(msgs[i].flags & I2C_M_RD) && + (msgs[i + 1].flags & I2C_M_RD)) { +#ifdef GO7007_I2C_DEBUG + printk(KERN_DEBUG "go7007-usb: i2c write/read %d/%d " + "bytes on %02x\n", msgs[i].len, + msgs[i + 1].len, msgs[i].addr); +#endif + buf[0] = 0x01; + buf[1] = msgs[i].len + 1; + buf[2] = msgs[i].addr << 1; + memcpy(&buf[3], msgs[i].buf, msgs[i].len); + buf_len = msgs[i].len + 3; + buf[buf_len++] = msgs[++i].len; + } else if (msgs[i].flags & I2C_M_RD) { +#ifdef GO7007_I2C_DEBUG + printk(KERN_DEBUG "go7007-usb: i2c read %d " + "bytes on %02x\n", msgs[i].len, + msgs[i].addr); +#endif + buf[0] = 0x01; + buf[1] = 1; + buf[2] = msgs[i].addr << 1; + buf[3] = msgs[i].len; + buf_len = 4; + } else { +#ifdef GO7007_I2C_DEBUG + printk(KERN_DEBUG "go7007-usb: i2c write %d " + "bytes on %02x\n", msgs[i].len, + msgs[i].addr); +#endif + buf[0] = 0x00; + buf[1] = msgs[i].len + 1; + buf[2] = msgs[i].addr << 1; + memcpy(&buf[3], msgs[i].buf, msgs[i].len); + buf_len = msgs[i].len + 3; + buf[buf_len++] = 0; + } + if (go7007_usb_vendor_request(go, 0x24, 0, 0, + buf, buf_len, 0) < 0) + goto i2c_done; + if (msgs[i].flags & I2C_M_RD) { + memset(buf, 0, sizeof(buf)); + if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf, + msgs[i].len + 1, 1) < 0) + goto i2c_done; + memcpy(msgs[i].buf, buf + 1, msgs[i].len); + } + } + ret = 0; + +i2c_done: + up(&usb->i2c_lock); + return ret; +} + +static u32 go7007_usb_functionality(struct i2c_adapter *adapter) +{ + /* No errors are reported by the hardware, so we don't bother + * supporting quick writes to avoid confusing probing */ + return (I2C_FUNC_SMBUS_EMUL) & ~I2C_FUNC_SMBUS_QUICK; +} + +static struct i2c_algorithm go7007_usb_algo = { + .master_xfer = go7007_usb_i2c_master_xfer, + .functionality = go7007_usb_functionality, +}; + +static struct i2c_adapter go7007_usb_adap_templ = { + .owner = THIS_MODULE, + .name = "WIS GO7007SB EZ-USB", + .algo = &go7007_usb_algo, +}; + +/********************* USB add/remove functions *********************/ + +static int go7007_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct go7007 *go; + struct go7007_usb *usb; + struct go7007_usb_board *board; + struct usb_device *usbdev = interface_to_usbdev(intf); + char *name; + int video_pipe, i, v_urb_len; + + printk(KERN_DEBUG "go7007-usb: probing new GO7007 USB board\n"); + + switch (id->driver_info) { + case GO7007_BOARDID_MATRIX_II: + name = "WIS Matrix II or compatible"; + board = &board_matrix_ii; + break; + case GO7007_BOARDID_MATRIX_RELOAD: + name = "WIS Matrix Reloaded or compatible"; + board = &board_matrix_reload; + break; + case GO7007_BOARDID_MATRIX_REV: + name = "WIS Matrix Revolution or compatible"; + board = &board_matrix_revolution; + break; + case GO7007_BOARDID_STAR_TREK: + name = "WIS Star Trek or compatible"; + board = &board_star_trek; + break; + case GO7007_BOARDID_XMEN: + name = "WIS XMen or compatible"; + board = &board_xmen; + break; + case GO7007_BOARDID_XMEN_II: + name = "WIS XMen II or compatible"; + board = &board_xmen; + break; + case GO7007_BOARDID_XMEN_III: + name = "WIS XMen III or compatible"; + board = &board_xmen; + break; + case GO7007_BOARDID_PX_M402U: + name = "Plextor PX-M402U"; + board = &board_matrix_ii; + break; + case GO7007_BOARDID_PX_TV402U_ANY: + name = "Plextor PX-TV402U (unknown tuner)"; + board = &board_px_tv402u; + break; + case GO7007_BOARDID_LIFEVIEW_LR192: + printk(KERN_ERR "go7007-usb: The Lifeview TV Walker Ultra " + "is not supported. Sorry!\n"); + return 0; + name = "Lifeview TV Walker Ultra"; + board = &board_lifeview_lr192; + break; + case GO7007_BOARDID_SENSORAY_2250: + printk(KERN_INFO "Sensoray 2250 found\n"); + name = "Sensoray 2250/2251\n"; + board = &board_sensoray_2250; + break; + default: + printk(KERN_ERR "go7007-usb: unknown board ID %d!\n", + (unsigned int)id->driver_info); + return 0; + } + + usb = kzalloc(sizeof(struct go7007_usb), GFP_KERNEL); + if (usb == NULL) + return -ENOMEM; + + /* Allocate the URB and buffer for receiving incoming interrupts */ + usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL); + if (usb->intr_urb == NULL) + goto allocfail; + usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL); + if (usb->intr_urb->transfer_buffer == NULL) + goto allocfail; + + go = go7007_alloc(&board->main_info, &intf->dev); + if (go == NULL) + goto allocfail; + usb->board = board; + usb->usbdev = usbdev; + go->board_id = id->driver_info; + strncpy(go->name, name, sizeof(go->name)); + if (board->flags & GO7007_USB_EZUSB) + go->hpi_ops = &go7007_usb_ezusb_hpi_ops; + else + go->hpi_ops = &go7007_usb_onboard_hpi_ops; + go->hpi_context = usb; + usb_fill_int_urb(usb->intr_urb, usb->usbdev, + usb_rcvintpipe(usb->usbdev, 4), + usb->intr_urb->transfer_buffer, 2*sizeof(u16), + go7007_usb_readinterrupt_complete, go, 8); + usb_set_intfdata(intf, go); + + /* Boot the GO7007 */ + if (go7007_boot_encoder(go, go->board_info->flags & + GO7007_BOARD_USE_ONBOARD_I2C) < 0) + goto initfail; + + /* Register the EZ-USB I2C adapter, if we're using it */ + if (board->flags & GO7007_USB_EZUSB_I2C) { + memcpy(&go->i2c_adapter, &go7007_usb_adap_templ, + sizeof(go7007_usb_adap_templ)); + init_MUTEX(&usb->i2c_lock); + go->i2c_adapter.dev.parent = go->dev; + i2c_set_adapdata(&go->i2c_adapter, go); + if (i2c_add_adapter(&go->i2c_adapter) < 0) { + printk(KERN_ERR + "go7007-usb: error: i2c_add_adapter failed\n"); + goto initfail; + } + go->i2c_adapter_online = 1; + } + + /* Pelco and Adlink reused the XMen and XMen-III vendor and product + * IDs for their own incompatible designs. We can detect XMen boards + * by probing the sensor, but there is no way to probe the sensors on + * the Pelco and Adlink designs so we default to the Adlink. If it + * is actually a Pelco, the user must set the assume_endura module + * parameter. */ + if ((go->board_id == GO7007_BOARDID_XMEN || + go->board_id == GO7007_BOARDID_XMEN_III) && + go->i2c_adapter_online) { + union i2c_smbus_data data; + + /* Check to see if register 0x0A is 0x76 */ + i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB, + I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data); + if (data.byte != 0x76) { + if (assume_endura) { + go->board_id = GO7007_BOARDID_ENDURA; + usb->board = board = &board_endura; + go->board_info = &board->main_info; + strncpy(go->name, "Pelco Endura", + sizeof(go->name)); + } else { + u16 channel; + + /* set GPIO5 to be an output, currently low */ + go7007_write_addr(go, 0x3c82, 0x0000); + go7007_write_addr(go, 0x3c80, 0x00df); + /* read channel number from GPIO[1:0] */ + go7007_read_addr(go, 0x3c81, &channel); + channel &= 0x3; + go->board_id = GO7007_BOARDID_ADLINK_MPG24; + usb->board = board = &board_adlink_mpg24; + go->board_info = &board->main_info; + go->channel_number = channel; + snprintf(go->name, sizeof(go->name), + "Adlink PCI-MPG24, channel #%d", + channel); + } + } + } + + /* Probe the tuner model on the TV402U */ + if (go->board_id == GO7007_BOARDID_PX_TV402U_ANY) { + u8 data[3]; + + /* Board strapping indicates tuner model */ + if (go7007_usb_vendor_request(go, 0x41, 0, 0, data, 3, 1) < 0) { + printk(KERN_ERR "go7007-usb: GPIO read failed!\n"); + goto initfail; + } + switch (data[0] >> 6) { + case 1: + go->board_id = GO7007_BOARDID_PX_TV402U_EU; + go->tuner_type = TUNER_SONY_BTF_PG472Z; + strncpy(go->name, "Plextor PX-TV402U-EU", + sizeof(go->name)); + break; + case 2: + go->board_id = GO7007_BOARDID_PX_TV402U_JP; + go->tuner_type = TUNER_SONY_BTF_PK467Z; + strncpy(go->name, "Plextor PX-TV402U-JP", + sizeof(go->name)); + break; + case 3: + go->board_id = GO7007_BOARDID_PX_TV402U_NA; + go->tuner_type = TUNER_SONY_BTF_PB463Z; + strncpy(go->name, "Plextor PX-TV402U-NA", + sizeof(go->name)); + break; + default: + printk(KERN_DEBUG "go7007-usb: unable to detect " + "tuner type!\n"); + break; + } + /* Configure tuner mode selection inputs connected + * to the EZ-USB GPIO output pins */ + if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0, + NULL, 0, 0) < 0) { + printk(KERN_ERR + "go7007-usb: GPIO write failed!\n"); + goto initfail; + } + } + + /* Print a nasty message if the user attempts to use a USB2.0 device in + * a USB1.1 port. There will be silent corruption of the stream. */ + if ((board->flags & GO7007_USB_EZUSB) && + usbdev->speed != USB_SPEED_HIGH) + printk(KERN_ERR "go7007-usb: *** WARNING *** This device " + "must be connected to a USB 2.0 port! " + "Attempting to capture video through a USB 1.1 " + "port will result in stream corruption, even " + "at low bitrates!\n"); + + /* Do any final GO7007 initialization, then register the + * V4L2 and ALSA interfaces */ + if (go7007_register_encoder(go) < 0) + goto initfail; + + /* Allocate the URBs and buffers for receiving the video stream */ + if (board->flags & GO7007_USB_EZUSB) { + v_urb_len = 1024; + video_pipe = usb_rcvbulkpipe(usb->usbdev, 6); + } else { + v_urb_len = 512; + video_pipe = usb_rcvbulkpipe(usb->usbdev, 1); + } + for (i = 0; i < 8; ++i) { + usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); + if (usb->video_urbs[i] == NULL) + goto initfail; + usb->video_urbs[i]->transfer_buffer = + kmalloc(v_urb_len, GFP_KERNEL); + if (usb->video_urbs[i]->transfer_buffer == NULL) + goto initfail; + usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe, + usb->video_urbs[i]->transfer_buffer, v_urb_len, + go7007_usb_read_video_pipe_complete, go); + } + + /* Allocate the URBs and buffers for receiving the audio stream */ + if ((board->flags & GO7007_USB_EZUSB) && go->audio_enabled) + for (i = 0; i < 8; ++i) { + usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); + if (usb->audio_urbs[i] == NULL) + goto initfail; + usb->audio_urbs[i]->transfer_buffer = kmalloc(4096, + GFP_KERNEL); + if (usb->audio_urbs[i]->transfer_buffer == NULL) + goto initfail; + usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev, + usb_rcvbulkpipe(usb->usbdev, 8), + usb->audio_urbs[i]->transfer_buffer, 4096, + go7007_usb_read_audio_pipe_complete, go); + } + + + go->status = STATUS_ONLINE; + return 0; + +initfail: + go->status = STATUS_SHUTDOWN; + return 0; + +allocfail: + if (usb->intr_urb) { + kfree(usb->intr_urb->transfer_buffer); + usb_free_urb(usb->intr_urb); + } + kfree(usb); + return -ENOMEM; +} + +static void go7007_usb_disconnect(struct usb_interface *intf) +{ + struct go7007 *go = usb_get_intfdata(intf); + struct go7007_usb *usb = go->hpi_context; + struct urb *vurb, *aurb; + int i; + + go->status = STATUS_SHUTDOWN; + usb_kill_urb(usb->intr_urb); + + /* Free USB-related structs */ + for (i = 0; i < 8; ++i) { + vurb = usb->video_urbs[i]; + if (vurb) { + usb_kill_urb(vurb); + if (vurb->transfer_buffer) + kfree(vurb->transfer_buffer); + usb_free_urb(vurb); + } + aurb = usb->audio_urbs[i]; + if (aurb) { + usb_kill_urb(aurb); + if (aurb->transfer_buffer) + kfree(aurb->transfer_buffer); + usb_free_urb(aurb); + } + } + kfree(usb->intr_urb->transfer_buffer); + usb_free_urb(usb->intr_urb); + + kfree(go->hpi_context); + + go7007_remove(go); +} + +static struct usb_driver go7007_usb_driver = { + .name = "go7007", + .probe = go7007_usb_probe, + .disconnect = go7007_usb_disconnect, + .id_table = go7007_usb_id_table, +}; + +static int __init go7007_usb_init(void) +{ + return usb_register(&go7007_usb_driver); +} + +static void __exit go7007_usb_cleanup(void) +{ + usb_deregister(&go7007_usb_driver); +} + +module_init(go7007_usb_init); +module_exit(go7007_usb_cleanup); + +MODULE_LICENSE("GPL v2"); diff --git a/linux/drivers/staging/go7007/go7007-v4l2.c b/linux/drivers/staging/go7007/go7007-v4l2.c new file mode 100644 index 000000000..06cacd37b --- /dev/null +++ b/linux/drivers/staging/go7007/go7007-v4l2.c @@ -0,0 +1,1876 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "go7007.h" +#include "go7007-priv.h" +#include "wis-i2c.h" + +/* Temporary defines until accepted in v4l-dvb */ +#ifndef V4L2_MPEG_STREAM_TYPE_MPEG_ELEM +#define V4L2_MPEG_STREAM_TYPE_MPEG_ELEM 6 /* MPEG elementary stream */ +#endif +#ifndef V4L2_MPEG_VIDEO_ENCODING_MPEG_4 +#define V4L2_MPEG_VIDEO_ENCODING_MPEG_4 3 +#endif + +static void deactivate_buffer(struct go7007_buffer *gobuf) +{ + int i; + + if (gobuf->state != BUF_STATE_IDLE) { + list_del(&gobuf->stream); + gobuf->state = BUF_STATE_IDLE; + } + if (gobuf->page_count > 0) { + for (i = 0; i < gobuf->page_count; ++i) + page_cache_release(gobuf->pages[i]); + gobuf->page_count = 0; + } +} + +static void abort_queued(struct go7007 *go) +{ + struct go7007_buffer *gobuf, *next; + + list_for_each_entry_safe(gobuf, next, &go->stream, stream) { + deactivate_buffer(gobuf); + } +} + +static int go7007_streamoff(struct go7007 *go) +{ + int retval = -EINVAL; + unsigned long flags; + + down(&go->hw_lock); + if (go->streaming) { + go->streaming = 0; + go7007_stream_stop(go); + spin_lock_irqsave(&go->spinlock, flags); + abort_queued(go); + spin_unlock_irqrestore(&go->spinlock, flags); + go7007_reset_encoder(go); + retval = 0; + } + up(&go->hw_lock); + return 0; +} + +static int go7007_open(struct file *file) +{ + struct go7007 *go = video_get_drvdata(video_devdata(file)); + struct go7007_file *gofh; + + if (go->status != STATUS_ONLINE) + return -EBUSY; + gofh = kmalloc(sizeof(struct go7007_file), GFP_KERNEL); + if (gofh == NULL) + return -ENOMEM; + ++go->ref_count; + gofh->go = go; + init_MUTEX(&gofh->lock); + gofh->buf_count = 0; + file->private_data = gofh; + return 0; +} + +static int go7007_release(struct file *file) +{ + struct go7007_file *gofh = file->private_data; + struct go7007 *go = gofh->go; + + if (gofh->buf_count > 0) { + go7007_streamoff(go); + go->in_use = 0; + kfree(gofh->bufs); + gofh->buf_count = 0; + } + kfree(gofh); + if (--go->ref_count == 0) + kfree(go); + file->private_data = NULL; + return 0; +} + +static u32 get_frame_type_flag(struct go7007_buffer *gobuf, int format) +{ + u8 *f = page_address(gobuf->pages[0]); + + switch (format) { + case GO7007_FORMAT_MJPEG: + return V4L2_BUF_FLAG_KEYFRAME; + case GO7007_FORMAT_MPEG4: + switch ((f[gobuf->frame_offset + 4] >> 6) & 0x3) { + case 0: + return V4L2_BUF_FLAG_KEYFRAME; + case 1: + return V4L2_BUF_FLAG_PFRAME; + case 2: + return V4L2_BUF_FLAG_BFRAME; + default: + return 0; + } + case GO7007_FORMAT_MPEG1: + case GO7007_FORMAT_MPEG2: + switch ((f[gobuf->frame_offset + 5] >> 3) & 0x7) { + case 1: + return V4L2_BUF_FLAG_KEYFRAME; + case 2: + return V4L2_BUF_FLAG_PFRAME; + case 3: + return V4L2_BUF_FLAG_BFRAME; + default: + return 0; + } + } + + return 0; +} + +static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try) +{ + int sensor_height = 0, sensor_width = 0; + int width, height, i; + + if (fmt != NULL && fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG && + fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG && + fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG4) + return -EINVAL; + + switch (go->standard) { + case GO7007_STD_NTSC: + sensor_width = 720; + sensor_height = 480; + break; + case GO7007_STD_PAL: + sensor_width = 720; + sensor_height = 576; + break; + case GO7007_STD_OTHER: + sensor_width = go->board_info->sensor_width; + sensor_height = go->board_info->sensor_height; + break; + } + + if (fmt == NULL) { + width = sensor_width; + height = sensor_height; + } else if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) { + if (fmt->fmt.pix.width > sensor_width) + width = sensor_width; + else if (fmt->fmt.pix.width < 144) + width = 144; + else + width = fmt->fmt.pix.width & ~0x0f; + + if (fmt->fmt.pix.height > sensor_height) + height = sensor_height; + else if (fmt->fmt.pix.height < 96) + height = 96; + else + height = fmt->fmt.pix.height & ~0x0f; + } else { + int requested_size = fmt->fmt.pix.width * fmt->fmt.pix.height; + int sensor_size = sensor_width * sensor_height; + + if (64 * requested_size < 9 * sensor_size) { + width = sensor_width / 4; + height = sensor_height / 4; + } else if (64 * requested_size < 36 * sensor_size) { + width = sensor_width / 2; + height = sensor_height / 2; + } else { + width = sensor_width; + height = sensor_height; + } + width &= ~0xf; + height &= ~0xf; + } + + if (fmt != NULL) { + u32 pixelformat = fmt->fmt.pix.pixelformat; + + memset(fmt, 0, sizeof(*fmt)); + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt->fmt.pix.width = width; + fmt->fmt.pix.height = height; + fmt->fmt.pix.pixelformat = pixelformat; + fmt->fmt.pix.field = V4L2_FIELD_NONE; + fmt->fmt.pix.bytesperline = 0; + fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE; + fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* ?? */ + } + + if (try) + return 0; + + go->width = width; + go->height = height; + go->encoder_h_offset = go->board_info->sensor_h_offset; + go->encoder_v_offset = go->board_info->sensor_v_offset; + for (i = 0; i < 4; ++i) + go->modet[i].enable = 0; + for (i = 0; i < 1624; ++i) + go->modet_map[i] = 0; + + if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) { + struct video_decoder_resolution res; + + res.width = width; + if (height > sensor_height / 2) { + res.height = height / 2; + go->encoder_v_halve = 0; + } else { + res.height = height; + go->encoder_v_halve = 1; + } + if (go->i2c_adapter_online) + i2c_clients_command(&go->i2c_adapter, + DECODER_SET_RESOLUTION, &res); + } else { + if (width <= sensor_width / 4) { + go->encoder_h_halve = 1; + go->encoder_v_halve = 1; + go->encoder_subsample = 1; + } else if (width <= sensor_width / 2) { + go->encoder_h_halve = 1; + go->encoder_v_halve = 1; + go->encoder_subsample = 0; + } else { + go->encoder_h_halve = 0; + go->encoder_v_halve = 0; + go->encoder_subsample = 0; + } + } + + if (fmt == NULL) + return 0; + + switch (fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_MPEG: + if (go->format == GO7007_FORMAT_MPEG1 || + go->format == GO7007_FORMAT_MPEG2 || + go->format == GO7007_FORMAT_MPEG4) + break; + go->format = GO7007_FORMAT_MPEG1; + go->pali = 0; + go->aspect_ratio = GO7007_RATIO_1_1; + go->gop_size = go->sensor_framerate / 1000; + go->ipb = 0; + go->closed_gop = 1; + go->repeat_seqhead = 1; + go->seq_header_enable = 1; + go->gop_header_enable = 1; + go->dvd_mode = 0; + break; + /* Backwards compatibility only! */ + case V4L2_PIX_FMT_MPEG4: + if (go->format == GO7007_FORMAT_MPEG4) + break; + go->format = GO7007_FORMAT_MPEG4; + go->pali = 0xf5; + go->aspect_ratio = GO7007_RATIO_1_1; + go->gop_size = go->sensor_framerate / 1000; + go->ipb = 0; + go->closed_gop = 1; + go->repeat_seqhead = 1; + go->seq_header_enable = 1; + go->gop_header_enable = 1; + go->dvd_mode = 0; + break; + case V4L2_PIX_FMT_MJPEG: + go->format = GO7007_FORMAT_MJPEG; + go->pali = 0; + go->aspect_ratio = GO7007_RATIO_1_1; + go->gop_size = 0; + go->ipb = 0; + go->closed_gop = 0; + go->repeat_seqhead = 0; + go->seq_header_enable = 0; + go->gop_header_enable = 0; + go->dvd_mode = 0; + break; + } + return 0; +} + +#if 0 +static int clip_to_modet_map(struct go7007 *go, int region, + struct v4l2_clip *clip_list) +{ + struct v4l2_clip clip, *clip_ptr; + int x, y, mbnum; + + /* Check if coordinates are OK and if any macroblocks are already + * used by other regions (besides 0) */ + clip_ptr = clip_list; + while (clip_ptr) { + if (copy_from_user(&clip, clip_ptr, sizeof(clip))) + return -EFAULT; + if (clip.c.left < 0 || (clip.c.left & 0xF) || + clip.c.width <= 0 || (clip.c.width & 0xF)) + return -EINVAL; + if (clip.c.left + clip.c.width > go->width) + return -EINVAL; + if (clip.c.top < 0 || (clip.c.top & 0xF) || + clip.c.height <= 0 || (clip.c.height & 0xF)) + return -EINVAL; + if (clip.c.top + clip.c.height > go->height) + return -EINVAL; + for (y = 0; y < clip.c.height; y += 16) + for (x = 0; x < clip.c.width; x += 16) { + mbnum = (go->width >> 4) * + ((clip.c.top + y) >> 4) + + ((clip.c.left + x) >> 4); + if (go->modet_map[mbnum] != 0 && + go->modet_map[mbnum] != region) + return -EBUSY; + } + clip_ptr = clip.next; + } + + /* Clear old region macroblocks */ + for (mbnum = 0; mbnum < 1624; ++mbnum) + if (go->modet_map[mbnum] == region) + go->modet_map[mbnum] = 0; + + /* Claim macroblocks in this list */ + clip_ptr = clip_list; + while (clip_ptr) { + if (copy_from_user(&clip, clip_ptr, sizeof(clip))) + return -EFAULT; + for (y = 0; y < clip.c.height; y += 16) + for (x = 0; x < clip.c.width; x += 16) { + mbnum = (go->width >> 4) * + ((clip.c.top + y) >> 4) + + ((clip.c.left + x) >> 4); + go->modet_map[mbnum] = region; + } + clip_ptr = clip.next; + } + return 0; +} + +static int mpeg_queryctrl(u32 id, struct v4l2_queryctrl *ctrl) +{ + static const u32 user_ctrls[] = { + V4L2_CID_USER_CLASS, + 0 + }; + static const u32 mpeg_ctrls[] = { + V4L2_CID_MPEG_CLASS, + V4L2_CID_MPEG_STREAM_TYPE, + V4L2_CID_MPEG_VIDEO_ENCODING, + V4L2_CID_MPEG_VIDEO_ASPECT, + V4L2_CID_MPEG_VIDEO_GOP_SIZE, + V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, + V4L2_CID_MPEG_VIDEO_BITRATE, + 0 + }; + static const u32 *ctrl_classes[] = { + user_ctrls, + mpeg_ctrls, + NULL + }; + + /* The ctrl may already contain the queried i2c controls, + * query the mpeg controls if the existing ctrl id is + * greater than the next mpeg ctrl id. + */ + id = v4l2_ctrl_next(ctrl_classes, id); + if (id >= ctrl->id && ctrl->name[0]) + return 0; + + memset(ctrl, 0, sizeof(*ctrl)); + ctrl->id = id; + + switch (ctrl->id) { + case V4L2_CID_USER_CLASS: + case V4L2_CID_MPEG_CLASS: + return v4l2_ctrl_query_fill_std(ctrl); + case V4L2_CID_MPEG_STREAM_TYPE: + return v4l2_ctrl_query_fill(ctrl, + V4L2_MPEG_STREAM_TYPE_MPEG2_DVD, + V4L2_MPEG_STREAM_TYPE_MPEG_ELEM, 1, + V4L2_MPEG_STREAM_TYPE_MPEG_ELEM); + case V4L2_CID_MPEG_VIDEO_ENCODING: + return v4l2_ctrl_query_fill(ctrl, + V4L2_MPEG_VIDEO_ENCODING_MPEG_1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4, 1, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2); + case V4L2_CID_MPEG_VIDEO_ASPECT: + return v4l2_ctrl_query_fill(ctrl, + V4L2_MPEG_VIDEO_ASPECT_1x1, + V4L2_MPEG_VIDEO_ASPECT_16x9, 1, + V4L2_MPEG_VIDEO_ASPECT_1x1); + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + return v4l2_ctrl_query_fill_std(ctrl); + case V4L2_CID_MPEG_VIDEO_BITRATE: + return v4l2_ctrl_query_fill(ctrl, + 64000, + 10000000, 1, + 9800000); + default: + break; + } + return -EINVAL; +} + +static int mpeg_s_control(struct v4l2_control *ctrl, struct go7007 *go) +{ + /* pretty sure we can't change any of these while streaming */ + if (go->streaming) + return -EBUSY; + + switch (ctrl->id) { + case V4L2_CID_MPEG_STREAM_TYPE: + switch (ctrl->value) { + case V4L2_MPEG_STREAM_TYPE_MPEG2_DVD: + go->format = GO7007_FORMAT_MPEG2; + go->bitrate = 9800000; + go->gop_size = 15; + go->pali = 0x48; + go->closed_gop = 1; + go->repeat_seqhead = 0; + go->seq_header_enable = 1; + go->gop_header_enable = 1; + go->dvd_mode = 1; + break; + case V4L2_MPEG_STREAM_TYPE_MPEG_ELEM: + /* todo: */ + break; + default: + return -EINVAL; + } + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + switch (ctrl->value) { + case V4L2_MPEG_VIDEO_ENCODING_MPEG_1: + go->format = GO7007_FORMAT_MPEG1; + go->pali = 0; + break; + case V4L2_MPEG_VIDEO_ENCODING_MPEG_2: + go->format = GO7007_FORMAT_MPEG2; + /*if (mpeg->pali >> 24 == 2) + go->pali = mpeg->pali & 0xff; + else*/ + go->pali = 0x48; + break; + case V4L2_MPEG_VIDEO_ENCODING_MPEG_4: + go->format = GO7007_FORMAT_MPEG4; + /*if (mpeg->pali >> 24 == 4) + go->pali = mpeg->pali & 0xff; + else*/ + go->pali = 0xf5; + break; + default: + return -EINVAL; + } + go->gop_header_enable = + /*mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER + ? 0 :*/ 1; + /*if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER) + go->repeat_seqhead = 1; + else*/ + go->repeat_seqhead = 0; + go->dvd_mode = 0; + break; + case V4L2_CID_MPEG_VIDEO_ASPECT: + if (go->format == GO7007_FORMAT_MJPEG) + return -EINVAL; + switch (ctrl->value) { + case V4L2_MPEG_VIDEO_ASPECT_1x1: + go->aspect_ratio = GO7007_RATIO_1_1; + break; + case V4L2_MPEG_VIDEO_ASPECT_4x3: + go->aspect_ratio = GO7007_RATIO_4_3; + break; + case V4L2_MPEG_VIDEO_ASPECT_16x9: + go->aspect_ratio = GO7007_RATIO_16_9; + break; + case V4L2_MPEG_VIDEO_ASPECT_221x100: + default: + return -EINVAL; + } + break; + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + go->gop_size = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + if (ctrl->value != 0 && ctrl->value != 1) + return -EINVAL; + go->closed_gop = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + /* Upper bound is kind of arbitrary here */ + if (ctrl->value < 64000 || ctrl->value > 10000000) + return -EINVAL; + go->bitrate = ctrl->value; + break; + default: + return -EINVAL; + } + return 0; +} + +static int mpeg_g_control(struct v4l2_control *ctrl, struct go7007 *go) +{ + switch (ctrl->id) { + case V4L2_CID_MPEG_STREAM_TYPE: + if (go->dvd_mode) + ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; + else + ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG_ELEM; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + switch (go->format) { + case GO7007_FORMAT_MPEG1: + ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_1; + break; + case GO7007_FORMAT_MPEG2: + ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; + break; + case GO7007_FORMAT_MPEG4: + ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4; + break; + default: + return -EINVAL; + } + break; + case V4L2_CID_MPEG_VIDEO_ASPECT: + switch (go->aspect_ratio) { + case GO7007_RATIO_1_1: + ctrl->value = V4L2_MPEG_VIDEO_ASPECT_1x1; + break; + case GO7007_RATIO_4_3: + ctrl->value = V4L2_MPEG_VIDEO_ASPECT_4x3; + break; + case GO7007_RATIO_16_9: + ctrl->value = V4L2_MPEG_VIDEO_ASPECT_16x9; + break; + default: + return -EINVAL; + } + break; + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + ctrl->value = go->gop_size; + break; + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + ctrl->value = go->closed_gop; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + ctrl->value = go->bitrate; + break; + default: + return -EINVAL; + } + return 0; +} +#endif + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + strlcpy(cap->driver, "go7007", sizeof(cap->driver)); + strlcpy(cap->card, go->name, sizeof(cap->card)); +#if 0 + strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info)); +#endif + + cap->version = KERNEL_VERSION(0, 9, 8); + + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING; /* | V4L2_CAP_AUDIO; */ + + if (go->board_info->flags & GO7007_BOARD_HAS_TUNER) + cap->capabilities |= V4L2_CAP_TUNER; + + return 0; +} + +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *fmt) +{ + char *desc = NULL; + + switch (fmt->index) { + case 0: + fmt->pixelformat = V4L2_PIX_FMT_MJPEG; + desc = "Motion-JPEG"; + break; + case 1: + fmt->pixelformat = V4L2_PIX_FMT_MPEG; + desc = "MPEG1/MPEG2/MPEG4"; + break; + default: + return -EINVAL; + } + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt->flags = V4L2_FMT_FLAG_COMPRESSED; + + strncpy(fmt->description, desc, sizeof(fmt->description)); + + return 0; +} + +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt->fmt.pix.width = go->width; + fmt->fmt.pix.height = go->height; + fmt->fmt.pix.pixelformat = (go->format == GO7007_FORMAT_MJPEG) ? + V4L2_PIX_FMT_MJPEG : V4L2_PIX_FMT_MPEG; + fmt->fmt.pix.field = V4L2_FIELD_NONE; + fmt->fmt.pix.bytesperline = 0; + fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE; + fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + + return 0; +} + +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + return set_capture_size(go, fmt, 1); +} + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *fmt) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (go->streaming) + return -EBUSY; + + return set_capture_size(go, fmt, 0); +} + +static int vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *req) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + int retval = -EBUSY; + unsigned int count, i; + + if (go->streaming) + return retval; + + if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + req->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + down(&gofh->lock); + for (i = 0; i < gofh->buf_count; ++i) + if (gofh->bufs[i].mapped > 0) + goto unlock_and_return; + + down(&go->hw_lock); + if (go->in_use > 0 && gofh->buf_count == 0) { + up(&go->hw_lock); + goto unlock_and_return; + } + + if (gofh->buf_count > 0) + kfree(gofh->bufs); + + retval = -ENOMEM; + count = req->count; + if (count > 0) { + if (count < 2) + count = 2; + if (count > 32) + count = 32; + + gofh->bufs = kmalloc(count * sizeof(struct go7007_buffer), + GFP_KERNEL); + + if (!gofh->bufs) { + up(&go->hw_lock); + goto unlock_and_return; + } + + memset(gofh->bufs, 0, count * sizeof(struct go7007_buffer)); + + for (i = 0; i < count; ++i) { + gofh->bufs[i].go = go; + gofh->bufs[i].index = i; + gofh->bufs[i].state = BUF_STATE_IDLE; + gofh->bufs[i].mapped = 0; + } + + go->in_use = 1; + } else { + go->in_use = 0; + } + + gofh->buf_count = count; + up(&go->hw_lock); + up(&gofh->lock); + + memset(req, 0, sizeof(*req)); + + req->count = count; + req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req->memory = V4L2_MEMORY_MMAP; + + return 0; + +unlock_and_return: + up(&gofh->lock); + return retval; +} + +static int vidioc_querybuf(struct file *file, void *priv, + struct v4l2_buffer *buf) +{ + struct go7007_file *gofh = priv; + int retval = -EINVAL; + unsigned int index; + + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return retval; + + index = buf->index; + + down(&gofh->lock); + if (index >= gofh->buf_count) + goto unlock_and_return; + + memset(buf, 0, sizeof(*buf)); + buf->index = index; + buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + switch (gofh->bufs[index].state) { + case BUF_STATE_QUEUED: + buf->flags = V4L2_BUF_FLAG_QUEUED; + break; + case BUF_STATE_DONE: + buf->flags = V4L2_BUF_FLAG_DONE; + break; + default: + buf->flags = 0; + } + + if (gofh->bufs[index].mapped) + buf->flags |= V4L2_BUF_FLAG_MAPPED; + buf->memory = V4L2_MEMORY_MMAP; + buf->m.offset = index * GO7007_BUF_SIZE; + buf->length = GO7007_BUF_SIZE; + up(&gofh->lock); + + return 0; + +unlock_and_return: + up(&gofh->lock); + return retval; +} + +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + struct go7007_buffer *gobuf; + unsigned long flags; + int retval = -EINVAL; + int ret; + + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + buf->memory != V4L2_MEMORY_MMAP) + return retval; + + down(&gofh->lock); + if (buf->index < 0 || buf->index >= gofh->buf_count) + goto unlock_and_return; + + gobuf = &gofh->bufs[buf->index]; + if (!gobuf->mapped) + goto unlock_and_return; + + retval = -EBUSY; + if (gobuf->state != BUF_STATE_IDLE) + goto unlock_and_return; + + /* offset will be 0 until we really support USERPTR streaming */ + gobuf->offset = gobuf->user_addr & ~PAGE_MASK; + gobuf->bytesused = 0; + gobuf->frame_offset = 0; + gobuf->modet_active = 0; + if (gobuf->offset > 0) + gobuf->page_count = GO7007_BUF_PAGES + 1; + else + gobuf->page_count = GO7007_BUF_PAGES; + + retval = -ENOMEM; + down_read(¤t->mm->mmap_sem); + ret = get_user_pages(current, current->mm, + gobuf->user_addr & PAGE_MASK, gobuf->page_count, + 1, 1, gobuf->pages, NULL); + up_read(¤t->mm->mmap_sem); + + if (ret != gobuf->page_count) { + int i; + for (i = 0; i < ret; ++i) + page_cache_release(gobuf->pages[i]); + gobuf->page_count = 0; + goto unlock_and_return; + } + + gobuf->state = BUF_STATE_QUEUED; + spin_lock_irqsave(&go->spinlock, flags); + list_add_tail(&gobuf->stream, &go->stream); + spin_unlock_irqrestore(&go->spinlock, flags); + up(&gofh->lock); + + return 0; + +unlock_and_return: + up(&gofh->lock); + return retval; +} + + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + struct go7007_buffer *gobuf; + int retval = -EINVAL; + unsigned long flags; + u32 frame_type_flag; + DEFINE_WAIT(wait); + + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return retval; + if (buf->memory != V4L2_MEMORY_MMAP) + return retval; + + down(&gofh->lock); + if (list_empty(&go->stream)) + goto unlock_and_return; + gobuf = list_entry(go->stream.next, + struct go7007_buffer, stream); + + retval = -EAGAIN; + if (gobuf->state != BUF_STATE_DONE && + !(file->f_flags & O_NONBLOCK)) { + for (;;) { + prepare_to_wait(&go->frame_waitq, &wait, + TASK_INTERRUPTIBLE); + if (gobuf->state == BUF_STATE_DONE) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } + finish_wait(&go->frame_waitq, &wait); + } + if (gobuf->state != BUF_STATE_DONE) + goto unlock_and_return; + + spin_lock_irqsave(&go->spinlock, flags); + deactivate_buffer(gobuf); + spin_unlock_irqrestore(&go->spinlock, flags); + frame_type_flag = get_frame_type_flag(gobuf, go->format); + gobuf->state = BUF_STATE_IDLE; + + memset(buf, 0, sizeof(*buf)); + buf->index = gobuf->index; + buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf->bytesused = gobuf->bytesused; + buf->flags = V4L2_BUF_FLAG_MAPPED | frame_type_flag; + buf->field = V4L2_FIELD_NONE; + buf->timestamp = gobuf->timestamp; + buf->sequence = gobuf->seq; + buf->memory = V4L2_MEMORY_MMAP; + buf->m.offset = gobuf->index * GO7007_BUF_SIZE; + buf->length = GO7007_BUF_SIZE; + buf->reserved = gobuf->modet_active; + + up(&gofh->lock); + return 0; + +unlock_and_return: + up(&gofh->lock); + return retval; +} + +static int vidioc_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + int retval = 0; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + down(&gofh->lock); + down(&go->hw_lock); + + if (!go->streaming) { + go->streaming = 1; + go->next_seq = 0; + go->active_buf = NULL; + if (go7007_start_encoder(go) < 0) + retval = -EIO; + else + retval = 0; + } + up(&go->hw_lock); + up(&gofh->lock); + + return retval; +} + +static int vidioc_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + down(&gofh->lock); + go7007_streamoff(go); + up(&gofh->lock); + + return 0; +} + +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *query) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (!go->i2c_adapter_online) + return -EIO; + + i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, query); + + return (!query->name[0]) ? -EINVAL : 0; +} + +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + struct v4l2_queryctrl query; + + if (!go->i2c_adapter_online) + return -EIO; + + memset(&query, 0, sizeof(query)); + query.id = ctrl->id; + i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query); + if (query.name[0] == 0) + return -EINVAL; + i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, ctrl); + + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + struct v4l2_queryctrl query; + + if (!go->i2c_adapter_online) + return -EIO; + + memset(&query, 0, sizeof(query)); + query.id = ctrl->id; + i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query); + if (query.name[0] == 0) + return -EINVAL; + i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, ctrl); + + return 0; +} + +static int vidioc_g_parm(struct file *filp, void *priv, + struct v4l2_streamparm *parm) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + struct v4l2_fract timeperframe = { + .numerator = 1001 * go->fps_scale, + .denominator = go->sensor_framerate, + }; + + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME; + parm->parm.capture.timeperframe = timeperframe; + + return 0; +} + +static int vidioc_s_parm(struct file *filp, void *priv, + struct v4l2_streamparm *parm) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + unsigned int n, d; + + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (parm->parm.capture.capturemode != 0) + return -EINVAL; + + n = go->sensor_framerate * + parm->parm.capture.timeperframe.numerator; + d = 1001 * parm->parm.capture.timeperframe.denominator; + if (n != 0 && d != 0 && n > d) + go->fps_scale = (n + d/2) / d; + else + go->fps_scale = 1; + + return 0; +} + +/* VIDIOC_ENUMSTD on go7007 were used for enumberating the supported fps and + its resolution, when the device is not connected to TV. + This were an API abuse, probably used by the lack of specific IOCTL's to + enumberate it, by the time the driver were written. + + However, since kernel 2.6.19, two new ioctls (VIDIOC_ENUM_FRAMEINTERVALS + and VIDIOC_ENUM_FRAMESIZES) were added for this purpose. + + The two functions bellow implements the newer ioctls +*/ +static int vidioc_enum_framesizes(struct file *filp, void *priv, + struct v4l2_frmsizeenum *fsize) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + /* Return -EINVAL, if it is a TV board */ + if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) || + (go->board_info->sensor_flags & GO7007_SENSOR_TV)) + return -EINVAL; + + if (fsize->index > 0) + return -EINVAL; + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = go->board_info->sensor_width; + fsize->discrete.height = go->board_info->sensor_height; + + return 0; +} + +static int vidioc_enum_frameintervals(struct file *filp, void *priv, + struct v4l2_frmivalenum *fival) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + /* Return -EINVAL, if it is a TV board */ + if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) || + (go->board_info->sensor_flags & GO7007_SENSOR_TV)) + return -EINVAL; + + if (fival->index > 0) + return -EINVAL; + + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; + fival->discrete.numerator = 1001; + fival->discrete.denominator = go->board_info->sensor_framerate; + + return 0; +} + +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (go->streaming) + return -EBUSY; + + if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) && + *std != 0) + return -EINVAL; + + if (*std == 0) + return -EINVAL; + + if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) && + go->input == go->board_info->num_inputs - 1) { + if (!go->i2c_adapter_online) + return -EIO; + i2c_clients_command(&go->i2c_adapter, + VIDIOC_S_STD, std); + if (!*std) /* hack to indicate EINVAL from tuner */ + return -EINVAL; + } + + if (*std & V4L2_STD_NTSC) { + go->standard = GO7007_STD_NTSC; + go->sensor_framerate = 30000; + } else if (*std & V4L2_STD_PAL) { + go->standard = GO7007_STD_PAL; + go->sensor_framerate = 25025; + } else if (*std & V4L2_STD_SECAM) { + go->standard = GO7007_STD_PAL; + go->sensor_framerate = 25025; + } else + return -EINVAL; + + if (go->i2c_adapter_online) + i2c_clients_command(&go->i2c_adapter, + VIDIOC_S_STD, std); + set_capture_size(go, NULL, 0); + + return 0; +} + +#if 0 + case VIDIOC_QUERYSTD: + { + v4l2_std_id *std = arg; + + if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) && + go->input == go->board_info->num_inputs - 1) { + if (!go->i2c_adapter_online) + return -EIO; + i2c_clients_command(&go->i2c_adapter, + VIDIOC_QUERYSTD, arg); + } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV) + *std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; + else + *std = 0; + return 0; + } +#endif + +static int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (inp->index >= go->board_info->num_inputs) + return -EINVAL; + + strncpy(inp->name, go->board_info->inputs[inp->index].name, + sizeof(inp->name)); + + /* If this board has a tuner, it will be the last input */ + if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) && + inp->index == go->board_info->num_inputs - 1) + inp->type = V4L2_INPUT_TYPE_TUNER; + else + inp->type = V4L2_INPUT_TYPE_CAMERA; + + inp->audioset = 0; + inp->tuner = 0; + if (go->board_info->sensor_flags & GO7007_SENSOR_TV) + inp->std = V4L2_STD_NTSC | V4L2_STD_PAL | + V4L2_STD_SECAM; + else + inp->std = 0; + + return 0; +} + + +static int vidioc_g_input(struct file *file, void *priv, unsigned int *input) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + *input = go->input; + + return 0; +} + +static int vidioc_s_input(struct file *file, void *priv, unsigned int input) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (input >= go->board_info->num_inputs) + return -EINVAL; + if (go->streaming) + return -EBUSY; + + go->input = input; + if (go->i2c_adapter_online) { + i2c_clients_command(&go->i2c_adapter, VIDIOC_S_INPUT, + &go->board_info->inputs[input].video_input); + i2c_clients_command(&go->i2c_adapter, VIDIOC_S_AUDIO, + &go->board_info->inputs[input].audio_input); + } + + return 0; +} + +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) + return -EINVAL; + if (t->index != 0) + return -EINVAL; + if (!go->i2c_adapter_online) + return -EIO; + + i2c_clients_command(&go->i2c_adapter, VIDIOC_G_TUNER, t); + + t->index = 0; + return 0; +} + +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) + return -EINVAL; + if (t->index != 0) + return -EINVAL; + if (!go->i2c_adapter_online) + return -EIO; + + switch (go->board_id) { + case GO7007_BOARDID_PX_TV402U_NA: + case GO7007_BOARDID_PX_TV402U_JP: + /* No selectable options currently */ + if (t->audmode != V4L2_TUNER_MODE_STEREO) + return -EINVAL; + break; + } + + i2c_clients_command(&go->i2c_adapter, VIDIOC_S_TUNER, t); + + return 0; +} + +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) + return -EINVAL; + if (!go->i2c_adapter_online) + return -EIO; + + f->type = V4L2_TUNER_ANALOG_TV; + i2c_clients_command(&go->i2c_adapter, VIDIOC_G_FREQUENCY, f); + return 0; +} + +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) + return -EINVAL; + if (!go->i2c_adapter_online) + return -EIO; + + i2c_clients_command(&go->i2c_adapter, VIDIOC_S_FREQUENCY, f); + + return 0; +} + +static int vidioc_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *cropcap) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + /* These specify the raw input of the sensor */ + switch (go->standard) { + case GO7007_STD_NTSC: + cropcap->bounds.top = 0; + cropcap->bounds.left = 0; + cropcap->bounds.width = 720; + cropcap->bounds.height = 480; + cropcap->defrect.top = 0; + cropcap->defrect.left = 0; + cropcap->defrect.width = 720; + cropcap->defrect.height = 480; + break; + case GO7007_STD_PAL: + cropcap->bounds.top = 0; + cropcap->bounds.left = 0; + cropcap->bounds.width = 720; + cropcap->bounds.height = 576; + cropcap->defrect.top = 0; + cropcap->defrect.left = 0; + cropcap->defrect.width = 720; + cropcap->defrect.height = 576; + break; + case GO7007_STD_OTHER: + cropcap->bounds.top = 0; + cropcap->bounds.left = 0; + cropcap->bounds.width = go->board_info->sensor_width; + cropcap->bounds.height = go->board_info->sensor_height; + cropcap->defrect.top = 0; + cropcap->defrect.left = 0; + cropcap->defrect.width = go->board_info->sensor_width; + cropcap->defrect.height = go->board_info->sensor_height; + break; + } + + return 0; +} + +static int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) +{ + struct go7007_file *gofh = priv; + struct go7007 *go = gofh->go; + + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + /* These specify the raw input of the sensor */ + switch (go->standard) { + case GO7007_STD_NTSC: + crop->c.top = 0; + crop->c.left = 0; + crop->c.width = 720; + crop->c.height = 480; + break; + case GO7007_STD_PAL: + crop->c.top = 0; + crop->c.left = 0; + crop->c.width = 720; + crop->c.height = 576; + break; + case GO7007_STD_OTHER: + crop->c.top = 0; + crop->c.left = 0; + crop->c.width = go->board_info->sensor_width; + crop->c.height = go->board_info->sensor_height; + break; + } + + return 0; +} + +/* FIXME: vidioc_s_crop is not really implemented!!! + */ +static int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop) +{ + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + return 0; +} + +static int vidioc_g_jpegcomp(struct file *file, void *priv, + struct v4l2_jpegcompression *params) +{ + memset(params, 0, sizeof(*params)); + params->quality = 50; /* ?? */ + params->jpeg_markers = V4L2_JPEG_MARKER_DHT | + V4L2_JPEG_MARKER_DQT; + + return 0; +} + +static int vidioc_s_jpegcomp(struct file *file, void *priv, + struct v4l2_jpegcompression *params) +{ + if (params->quality != 50 || + params->jpeg_markers != (V4L2_JPEG_MARKER_DHT | + V4L2_JPEG_MARKER_DQT)) + return -EINVAL; + + return 0; +} + +/* FIXME: + Those ioctls are private, and not needed, since several standard + extended controls already provide streaming control. + So, those ioctls should be converted into vidioc_g_ext_ctrls() + and vidioc_s_ext_ctrls() + */ + +#if 0 + /* Temporary ioctls for controlling compression characteristics */ + case GO7007IOC_S_BITRATE: + { + int *bitrate = arg; + + if (go->streaming) + return -EINVAL; + /* Upper bound is kind of arbitrary here */ + if (*bitrate < 64000 || *bitrate > 10000000) + return -EINVAL; + go->bitrate = *bitrate; + return 0; + } + case GO7007IOC_G_BITRATE: + { + int *bitrate = arg; + + *bitrate = go->bitrate; + return 0; + } + case GO7007IOC_S_COMP_PARAMS: + { + struct go7007_comp_params *comp = arg; + + if (go->format == GO7007_FORMAT_MJPEG) + return -EINVAL; + if (comp->gop_size > 0) + go->gop_size = comp->gop_size; + else + go->gop_size = go->sensor_framerate / 1000; + if (go->gop_size != 15) + go->dvd_mode = 0; + /*go->ipb = comp->max_b_frames > 0;*/ /* completely untested */ + if (go->board_info->sensor_flags & GO7007_SENSOR_TV) { + switch (comp->aspect_ratio) { + case GO7007_ASPECT_RATIO_4_3_NTSC: + case GO7007_ASPECT_RATIO_4_3_PAL: + go->aspect_ratio = GO7007_RATIO_4_3; + break; + case GO7007_ASPECT_RATIO_16_9_NTSC: + case GO7007_ASPECT_RATIO_16_9_PAL: + go->aspect_ratio = GO7007_RATIO_16_9; + break; + default: + go->aspect_ratio = GO7007_RATIO_1_1; + break; + } + } + if (comp->flags & GO7007_COMP_OMIT_SEQ_HEADER) { + go->dvd_mode = 0; + go->seq_header_enable = 0; + } else { + go->seq_header_enable = 1; + } + /* fall-through */ + } + case GO7007IOC_G_COMP_PARAMS: + { + struct go7007_comp_params *comp = arg; + + if (go->format == GO7007_FORMAT_MJPEG) + return -EINVAL; + memset(comp, 0, sizeof(*comp)); + comp->gop_size = go->gop_size; + comp->max_b_frames = go->ipb ? 2 : 0; + switch (go->aspect_ratio) { + case GO7007_RATIO_4_3: + if (go->standard == GO7007_STD_NTSC) + comp->aspect_ratio = + GO7007_ASPECT_RATIO_4_3_NTSC; + else + comp->aspect_ratio = + GO7007_ASPECT_RATIO_4_3_PAL; + break; + case GO7007_RATIO_16_9: + if (go->standard == GO7007_STD_NTSC) + comp->aspect_ratio = + GO7007_ASPECT_RATIO_16_9_NTSC; + else + comp->aspect_ratio = + GO7007_ASPECT_RATIO_16_9_PAL; + break; + default: + comp->aspect_ratio = GO7007_ASPECT_RATIO_1_1; + break; + } + if (go->closed_gop) + comp->flags |= GO7007_COMP_CLOSED_GOP; + if (!go->seq_header_enable) + comp->flags |= GO7007_COMP_OMIT_SEQ_HEADER; + return 0; + } + case GO7007IOC_S_MPEG_PARAMS: + { + struct go7007_mpeg_params *mpeg = arg; + + if (go->format != GO7007_FORMAT_MPEG1 && + go->format != GO7007_FORMAT_MPEG2 && + go->format != GO7007_FORMAT_MPEG4) + return -EINVAL; + + if (mpeg->flags & GO7007_MPEG_FORCE_DVD_MODE) { + go->format = GO7007_FORMAT_MPEG2; + go->bitrate = 9800000; + go->gop_size = 15; + go->pali = 0x48; + go->closed_gop = 1; + go->repeat_seqhead = 0; + go->seq_header_enable = 1; + go->gop_header_enable = 1; + go->dvd_mode = 1; + } else { + switch (mpeg->mpeg_video_standard) { + case GO7007_MPEG_VIDEO_MPEG1: + go->format = GO7007_FORMAT_MPEG1; + go->pali = 0; + break; + case GO7007_MPEG_VIDEO_MPEG2: + go->format = GO7007_FORMAT_MPEG2; + if (mpeg->pali >> 24 == 2) + go->pali = mpeg->pali & 0xff; + else + go->pali = 0x48; + break; + case GO7007_MPEG_VIDEO_MPEG4: + go->format = GO7007_FORMAT_MPEG4; + if (mpeg->pali >> 24 == 4) + go->pali = mpeg->pali & 0xff; + else + go->pali = 0xf5; + break; + default: + return -EINVAL; + } + go->gop_header_enable = + mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER + ? 0 : 1; + if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER) + go->repeat_seqhead = 1; + else + go->repeat_seqhead = 0; + go->dvd_mode = 0; + } + /* fall-through */ + } + case GO7007IOC_G_MPEG_PARAMS: + { + struct go7007_mpeg_params *mpeg = arg; + + memset(mpeg, 0, sizeof(*mpeg)); + switch (go->format) { + case GO7007_FORMAT_MPEG1: + mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG1; + mpeg->pali = 0; + break; + case GO7007_FORMAT_MPEG2: + mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG2; + mpeg->pali = GO7007_MPEG_PROFILE(2, go->pali); + break; + case GO7007_FORMAT_MPEG4: + mpeg->mpeg_video_standard = GO7007_MPEG_VIDEO_MPEG4; + mpeg->pali = GO7007_MPEG_PROFILE(4, go->pali); + break; + default: + return -EINVAL; + } + if (!go->gop_header_enable) + mpeg->flags |= GO7007_MPEG_OMIT_GOP_HEADER; + if (go->repeat_seqhead) + mpeg->flags |= GO7007_MPEG_REPEAT_SEQHEADER; + if (go->dvd_mode) + mpeg->flags |= GO7007_MPEG_FORCE_DVD_MODE; + return 0; + } + case GO7007IOC_S_MD_PARAMS: + { + struct go7007_md_params *mdp = arg; + + if (mdp->region > 3) + return -EINVAL; + if (mdp->trigger > 0) { + go->modet[mdp->region].pixel_threshold = + mdp->pixel_threshold >> 1; + go->modet[mdp->region].motion_threshold = + mdp->motion_threshold >> 1; + go->modet[mdp->region].mb_threshold = + mdp->trigger >> 1; + go->modet[mdp->region].enable = 1; + } else + go->modet[mdp->region].enable = 0; + /* fall-through */ + } + case GO7007IOC_G_MD_PARAMS: + { + struct go7007_md_params *mdp = arg; + int region = mdp->region; + + if (mdp->region > 3) + return -EINVAL; + memset(mdp, 0, sizeof(struct go7007_md_params)); + mdp->region = region; + if (!go->modet[region].enable) + return 0; + mdp->pixel_threshold = + (go->modet[region].pixel_threshold << 1) + 1; + mdp->motion_threshold = + (go->modet[region].motion_threshold << 1) + 1; + mdp->trigger = + (go->modet[region].mb_threshold << 1) + 1; + return 0; + } + case GO7007IOC_S_MD_REGION: + { + struct go7007_md_region *region = arg; + + if (region->region < 1 || region->region > 3) + return -EINVAL; + return clip_to_modet_map(go, region->region, region->clips); + } +#endif + +static ssize_t go7007_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) +{ + return -EINVAL; +} + +static void go7007_vm_open(struct vm_area_struct *vma) +{ + struct go7007_buffer *gobuf = vma->vm_private_data; + + ++gobuf->mapped; +} + +static void go7007_vm_close(struct vm_area_struct *vma) +{ + struct go7007_buffer *gobuf = vma->vm_private_data; + unsigned long flags; + + if (--gobuf->mapped == 0) { + spin_lock_irqsave(&gobuf->go->spinlock, flags); + deactivate_buffer(gobuf); + spin_unlock_irqrestore(&gobuf->go->spinlock, flags); + } +} + +/* Copied from videobuf-dma-sg.c */ +static int go7007_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct page *page; + + page = alloc_page(GFP_USER | __GFP_DMA32); + if (!page) + return VM_FAULT_OOM; + clear_user_highpage(page, (unsigned long)vmf->virtual_address); + vmf->page = page; + return 0; +} + +static struct vm_operations_struct go7007_vm_ops = { + .open = go7007_vm_open, + .close = go7007_vm_close, + .fault = go7007_vm_fault, +}; + +static int go7007_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct go7007_file *gofh = file->private_data; + unsigned int index; + + if (gofh->go->status != STATUS_ONLINE) + return -EIO; + if (!(vma->vm_flags & VM_SHARED)) + return -EINVAL; /* only support VM_SHARED mapping */ + if (vma->vm_end - vma->vm_start != GO7007_BUF_SIZE) + return -EINVAL; /* must map exactly one full buffer */ + down(&gofh->lock); + index = vma->vm_pgoff / GO7007_BUF_PAGES; + if (index >= gofh->buf_count) { + up(&gofh->lock); + return -EINVAL; /* trying to map beyond requested buffers */ + } + if (index * GO7007_BUF_PAGES != vma->vm_pgoff) { + up(&gofh->lock); + return -EINVAL; /* offset is not aligned on buffer boundary */ + } + if (gofh->bufs[index].mapped > 0) { + up(&gofh->lock); + return -EBUSY; + } + gofh->bufs[index].mapped = 1; + gofh->bufs[index].user_addr = vma->vm_start; + vma->vm_ops = &go7007_vm_ops; + vma->vm_flags |= VM_DONTEXPAND; + vma->vm_flags &= ~VM_IO; + vma->vm_private_data = &gofh->bufs[index]; + up(&gofh->lock); + return 0; +} + +static unsigned int go7007_poll(struct file *file, poll_table *wait) +{ + struct go7007_file *gofh = file->private_data; + struct go7007_buffer *gobuf; + + if (list_empty(&gofh->go->stream)) + return POLLERR; + gobuf = list_entry(gofh->go->stream.next, struct go7007_buffer, stream); + poll_wait(file, &gofh->go->frame_waitq, wait); + if (gobuf->state == BUF_STATE_DONE) + return POLLIN | POLLRDNORM; + return 0; +} + +static void go7007_vfl_release(struct video_device *vfd) +{ + struct go7007 *go = video_get_drvdata(vfd); + + video_device_release(vfd); + if (--go->ref_count == 0) + kfree(go); +} + +static struct v4l2_file_operations go7007_fops = { + .owner = THIS_MODULE, + .open = go7007_open, + .release = go7007_release, + .ioctl = video_ioctl2, + .read = go7007_read, + .mmap = go7007_mmap, + .poll = go7007_poll, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_s_std = vidioc_s_std, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_parm = vidioc_g_parm, + .vidioc_s_parm = vidioc_s_parm, + .vidioc_enum_framesizes = vidioc_enum_framesizes, + .vidioc_enum_frameintervals = vidioc_enum_frameintervals, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_jpegcomp = vidioc_g_jpegcomp, + .vidioc_s_jpegcomp = vidioc_s_jpegcomp, +}; + +static struct video_device go7007_template = { + .name = "go7007", + .fops = &go7007_fops, + .minor = -1, + .release = go7007_vfl_release, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = V4L2_STD_ALL, + .current_norm = V4L2_STD_NTSC, +}; + +int go7007_v4l2_init(struct go7007 *go) +{ + int rv; + + go->video_dev = video_device_alloc(); + if (go->video_dev == NULL) + return -ENOMEM; + memcpy(go->video_dev, &go7007_template, sizeof(go7007_template)); + go->video_dev->parent = go->dev; + rv = video_register_device(go->video_dev, VFL_TYPE_GRABBER, -1); + if (rv < 0) { + video_device_release(go->video_dev); + go->video_dev = NULL; + return rv; + } + video_set_drvdata(go->video_dev, go); + ++go->ref_count; + printk(KERN_INFO "%s: registered device video%d [v4l2]\n", + go->video_dev->name, go->video_dev->num); + + return 0; +} + +void go7007_v4l2_remove(struct go7007 *go) +{ + unsigned long flags; + + down(&go->hw_lock); + if (go->streaming) { + go->streaming = 0; + go7007_stream_stop(go); + spin_lock_irqsave(&go->spinlock, flags); + abort_queued(go); + spin_unlock_irqrestore(&go->spinlock, flags); + } + up(&go->hw_lock); + if (go->video_dev) + video_unregister_device(go->video_dev); +} diff --git a/linux/drivers/staging/go7007/go7007.h b/linux/drivers/staging/go7007/go7007.h new file mode 100644 index 000000000..7399c915a --- /dev/null +++ b/linux/drivers/staging/go7007/go7007.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and the associated README documentation file (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* DEPRECATED -- use V4L2_PIX_FMT_MPEG and then call GO7007IOC_S_MPEG_PARAMS + * to select between MPEG1, MPEG2, and MPEG4 */ +#define V4L2_PIX_FMT_MPEG4 v4l2_fourcc('M', 'P', 'G', '4') /* MPEG4 */ + +/* These will be replaced with a better interface + * soon, so don't get too attached to them */ +#define GO7007IOC_S_BITRATE _IOW('V', BASE_VIDIOC_PRIVATE + 0, int) +#define GO7007IOC_G_BITRATE _IOR('V', BASE_VIDIOC_PRIVATE + 1, int) + +enum go7007_aspect_ratio { + GO7007_ASPECT_RATIO_1_1 = 0, + GO7007_ASPECT_RATIO_4_3_NTSC = 1, + GO7007_ASPECT_RATIO_4_3_PAL = 2, + GO7007_ASPECT_RATIO_16_9_NTSC = 3, + GO7007_ASPECT_RATIO_16_9_PAL = 4, +}; + +/* Used to set generic compression parameters */ +struct go7007_comp_params { + __u32 gop_size; + __u32 max_b_frames; + enum go7007_aspect_ratio aspect_ratio; + __u32 flags; + __u32 reserved[8]; +}; + +#define GO7007_COMP_CLOSED_GOP 0x00000001 +#define GO7007_COMP_OMIT_SEQ_HEADER 0x00000002 + +enum go7007_mpeg_video_standard { + GO7007_MPEG_VIDEO_MPEG1 = 0, + GO7007_MPEG_VIDEO_MPEG2 = 1, + GO7007_MPEG_VIDEO_MPEG4 = 2, +}; + +/* Used to set parameters for V4L2_PIX_FMT_MPEG format */ +struct go7007_mpeg_params { + enum go7007_mpeg_video_standard mpeg_video_standard; + __u32 flags; + __u32 pali; + __u32 reserved[8]; +}; + +#define GO7007_MPEG_FORCE_DVD_MODE 0x00000001 +#define GO7007_MPEG_OMIT_GOP_HEADER 0x00000002 +#define GO7007_MPEG_REPEAT_SEQHEADER 0x00000004 + +#define GO7007_MPEG_PROFILE(format, pali) (((format)<<24)|(pali)) + +#define GO7007_MPEG2_PROFILE_MAIN_MAIN GO7007_MPEG_PROFILE(2, 0x48) + +#define GO7007_MPEG4_PROFILE_S_L0 GO7007_MPEG_PROFILE(4, 0x08) +#define GO7007_MPEG4_PROFILE_S_L1 GO7007_MPEG_PROFILE(4, 0x01) +#define GO7007_MPEG4_PROFILE_S_L2 GO7007_MPEG_PROFILE(4, 0x02) +#define GO7007_MPEG4_PROFILE_S_L3 GO7007_MPEG_PROFILE(4, 0x03) +#define GO7007_MPEG4_PROFILE_ARTS_L1 GO7007_MPEG_PROFILE(4, 0x91) +#define GO7007_MPEG4_PROFILE_ARTS_L2 GO7007_MPEG_PROFILE(4, 0x92) +#define GO7007_MPEG4_PROFILE_ARTS_L3 GO7007_MPEG_PROFILE(4, 0x93) +#define GO7007_MPEG4_PROFILE_ARTS_L4 GO7007_MPEG_PROFILE(4, 0x94) +#define GO7007_MPEG4_PROFILE_AS_L0 GO7007_MPEG_PROFILE(4, 0xf0) +#define GO7007_MPEG4_PROFILE_AS_L1 GO7007_MPEG_PROFILE(4, 0xf1) +#define GO7007_MPEG4_PROFILE_AS_L2 GO7007_MPEG_PROFILE(4, 0xf2) +#define GO7007_MPEG4_PROFILE_AS_L3 GO7007_MPEG_PROFILE(4, 0xf3) +#define GO7007_MPEG4_PROFILE_AS_L4 GO7007_MPEG_PROFILE(4, 0xf4) +#define GO7007_MPEG4_PROFILE_AS_L5 GO7007_MPEG_PROFILE(4, 0xf5) + +struct go7007_md_params { + __u16 region; + __u16 trigger; + __u16 pixel_threshold; + __u16 motion_threshold; + __u32 reserved[8]; +}; + +struct go7007_md_region { + __u16 region; + __u16 flags; + struct v4l2_clip *clips; + __u32 reserved[8]; +}; + +#define GO7007IOC_S_MPEG_PARAMS _IOWR('V', BASE_VIDIOC_PRIVATE + 2, \ + struct go7007_mpeg_params) +#define GO7007IOC_G_MPEG_PARAMS _IOR('V', BASE_VIDIOC_PRIVATE + 3, \ + struct go7007_mpeg_params) +#define GO7007IOC_S_COMP_PARAMS _IOWR('V', BASE_VIDIOC_PRIVATE + 4, \ + struct go7007_comp_params) +#define GO7007IOC_G_COMP_PARAMS _IOR('V', BASE_VIDIOC_PRIVATE + 5, \ + struct go7007_comp_params) +#define GO7007IOC_S_MD_PARAMS _IOWR('V', BASE_VIDIOC_PRIVATE + 6, \ + struct go7007_md_params) +#define GO7007IOC_G_MD_PARAMS _IOR('V', BASE_VIDIOC_PRIVATE + 7, \ + struct go7007_md_params) +#define GO7007IOC_S_MD_REGION _IOW('V', BASE_VIDIOC_PRIVATE + 8, \ + struct go7007_md_region) diff --git a/linux/drivers/staging/go7007/go7007.txt b/linux/drivers/staging/go7007/go7007.txt new file mode 100644 index 000000000..7656c0833 --- /dev/null +++ b/linux/drivers/staging/go7007/go7007.txt @@ -0,0 +1,481 @@ +This is a driver for the WIS GO7007SB multi-format video encoder. + +Pete Eberlein + +The driver was originally released under the GPL and is currently hosted at: +http://nikosapi.org/wiki/index.php/WIS_Go7007_Linux_driver +The go7007 firmware can be acquired from the package on the site above. + +I've modified the driver to support the following Video4Linux2 MPEG +controls, with acceptable values: + +V4L2_CID_MPEG_STREAM_TYPE V4L2_MPEG_STREAM_TYPE_MPEG2_DVD + V4L2_MPEG_STREAM_TYPE_MPEG_ELEM +V4L2_CID_MPEG_VIDEO_ENCODING V4L2_MPEG_VIDEO_ENCODING_MPEG_1 + V4L2_MPEG_VIDEO_ENCODING_MPEG_2 + V4L2_MPEG_VIDEO_ENCODING_MPEG_4 +V4L2_CID_MPEG_VIDEO_ASPECT V4L2_MPEG_VIDEO_ASPECT_1x1 + V4L2_MPEG_VIDEO_ASPECT_4x3 + V4L2_MPEG_VIDEO_ASPECT_16x9 +V4L2_CID_MPEG_VIDEO_GOP_SIZE integer +V4L2_CID_MPEG_VIDEO_BITRATE 64000 .. 10000000 + +These should be used instead of the non-standard GO7007 ioctls described +below. + + +The README files from the original package appears below: + +--------------------------------------------------------------------------- + WIS GO7007SB Public Linux Driver +--------------------------------------------------------------------------- + + +*** Please see the file RELEASE-NOTES for important last-minute updates *** + + + 0. OVERVIEW AND LICENSING/DISCLAIMER + + +This driver kit contains Linux drivers for the WIS GO7007SB multi-format +video encoder. Only kernel version 2.6.x is supported. The video stream +is available through the Video4Linux2 API and the audio stream is available +through the ALSA API (or the OSS emulation layer of the ALSA system). + +The files in kernel/ and hotplug/ are licensed under the GNU General Public +License Version 2 from the Free Software Foundation. A copy of the license +is included in the file COPYING. + +The example applications in apps/ and C header files in include/ are +licensed under a permissive license included in the source files which +allows copying, modification and redistribution for any purpose without +attribution. + +The firmware files included in the firmware/ directory may be freely +redistributed only in conjunction with this document; but modification, +tampering and reverse engineering are prohibited. + +MICRONAS USA, INC., MAKES NO WARRANTIES TO ANY PERSON OR ENTITY WITH +RESPECT TO THE SOFTWARE OR ANY DERIVATIVES THEREOF OR ANY SERVICES OR +LICENSES AND DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT LIMITATION +WARRANTIES OF MERCHANTABILITY, SUPPORT, AND FITNESS FOR A PARTICULAR +PURPOSE AND NON-INFRINGEMENT. + + + 1. SYSTEM REQUIREMENTS + + +This driver requires Linux kernel 2.6. Kernel 2.4 is not supported. Using +kernel 2.6.10 or later is recommended, as earlier kernels are known to have +unstable USB 2.0 support. + +A fully built kernel source tree must be available. Typically this will be +linked from "/lib/modules//build" for convenience. If this +link does not exist, an extra parameter will need to be passed to the +`make` command. + +All vendor-built kernels should already be configured properly. However, +for custom-built kernels, the following options need to be enabled in the +kernel as built-in or modules: + + CONFIG_HOTPLUG - Support for hot-pluggable devices + CONFIG_MODULES - Enable loadable module support + CONFIG_KMOD - Automatic kernel module loading + CONFIG_FW_LOADER - Hotplug firmware loading support + CONFIG_I2C - I2C support + CONFIG_VIDEO_DEV - Video For Linux + CONFIG_SOUND - Sound card support + CONFIG_SND - Advanced Linux Sound Architecture + CONFIG_USB - Support for Host-side USB + CONFIG_USB_DEVICEFS - USB device filesystem + CONFIG_USB_EHCI_HCD - EHCI HCD (USB 2.0) support + +Additionally, to use the example application, the following options need to +be enabled in the ALSA section: + + CONFIG_SND_MIXER_OSS - OSS Mixer API + CONFIG_SND_PCM_OSS - OSS PCM (digital audio) API + +The hotplug scripts, along with the fxload utility, must also be installed. +These scripts can be obtained from . +Hotplugging is used for loading firmware into the Cypruss EZ-USB chip using +fxload and for loading firmware into the driver using the firmware agent. + + + 2. COMPILING AND INSTALLING THE DRIVER + + +Most users should be able to compile the driver by simply running: + + $ make + +in the top-level directory of the driver kit. First the kernel modules +will be built, followed by the example applications. + +If the build system is unable to locate the kernel source tree for the +currently-running kernel, or if the module should be built for a kernel +other than the currently-running kernel, an additional parameter will need +to be passed to make to specify the appropriate kernel source directory: + + $ make KERNELSRC=/usr/src/linux-2.6.10-custom3 + +Once the compile completes, the driver and firmware files should be +installed by running: + + $ make install + +The kernel modules will be placed in "/lib/modules//extra" +and the firmware files will be placed in the appropriate hotplug firmware +directory, usually /lib/firmware. In addition, USB maps and scripts will +be placed in /etc/hotplug/usb to enable fxload to initialize the EZ-USB +control chip when the device is connected. + + + 3. PAL/SECAM TUNER CONFIGURATION (TV402U-EU only) + + +The PAL model of the Plextor ConvertX TV402U may require additional +configuration to correctly select the appropriate TV frequency band and +audio subchannel. + +Users with a device other than the Plextor ConvertX TV402U-EU should skip +this section. + +The wide variety of PAL TV systems used in Europe requires that additional +information about the local TV standards be passed to the driver in order +to properly tune TV channels. The two necessary parameters are (a) the PAL +TV band, and (b) the audio subchannel format in use. + +In many cases, the appropriate TV band selection is passed to the driver +from applications. However, in some cases, the application only specifies +that the driver should use PAL but not the specific information about the +appropriate TV band. To work around this issue, the correct TV band may be +specified in the "force_band" parameter to the wis-sony-tuner module: + + TV band force_band + ------- ---------- + PAL B/G B + PAL I I + PAL D/K D + SECAM L L + +If the "force_band" parameter is specified, the driver will ignore any TV +band specified by applications and will always use the band provided in the +module parameter. + +The other parameter that can be specified is the audio subchannel format. +There are several stereo audio carrier systems in use, including NICAM and +three varieties of A2. To receive audio broadcast on one of these stereo +carriers, the "force_mpx_mode" parameter must be specified to the +wis-sony-tuner module. + + TV band Audio subcarrier force_mpx_mode + ------- ---------------- -------------- + PAL B/G Mono (default) 1 + PAL B/G A2 2 + PAL B/G NICAM 3 + PAL I Mono (default) 4 + PAL I NICAM 5 + PAL D/K Mono (default) 6 + PAL D/K A2 (1) 7 + PAL D/K A2 (2) 8 + PAL D/K A2 (3) 9 + PAL D/K NICAM 10 + SECAM L Mono (default) 11 + SECAM L NICAM 12 + +If the "force_mpx_mode" parameter is not specified, the correct mono-only +mode will be chosen based on the TV band. However, the tuner will not +receive stereo audio or bilingual broadcasts correctly. + +To pass the "force_band" or "force_mpx_mode" parameters to the +wis-sony-tuner module, the following line must be added to the modprobe +configuration file, which varies from one Linux distribution to another. + + options wis-sony-tuner force_band=B force_mpx_mode=2 + +The above example would force the tuner to the PAL B/G TV band and receive +stereo audio broadcasts on the A2 carrier. + +To verify that the configuration has been placed in the correct location, +execute: + + $ modprobe -c | grep wis-sony-tuner + +If the configuration line appears, then modprobe will pass the parameters +correctly the next time the wis-sony-tuner module is loaded into the +kernel. + + + 4. TESTING THE DRIVER + + +Because few Linux applications are able to correctly capture from +Video4Linux2 devices with only compressed formats supported, the new driver +should be tested with the "gorecord" application in the apps/ directory. + +First connect a video source to the device, such as a DVD player or VCR. +This will be captured to a file for testing the driver. If an input source +is unavailable, a test file can still be captured, but the video will be +black and the audio will be silent. + +This application will auto-detect the V4L2 and ALSA/OSS device names of the +hardware and will record video and audio to an AVI file for a specified +number of seconds. For example: + + $ apps/gorecord -duration 60 capture.avi + +If this application does not successfully record an AVI file, the error +messages produced by gorecord and recorded in the system log (usually in +/var/log/messages) should provide information to help resolve the problem. + +Supplying no parameters to gorecord will cause it to probe the available +devices and exit. Use the -help flag for usage information. + + + 5. USING THE DRIVER + + +The V4L2 device implemented by the driver provides a standard compressed +format API, within the following criteria: + + * Applications that only support the original Video4Linux1 API will not + be able to communicate with this driver at all. + + * No raw video modes are supported, so applications like xawtv that + expect only uncompressed video will not function. + + * Supported compression formats are: Motion-JPEG, MPEG1, MPEG2 and MPEG4. + + * MPEG video formats are delivered as Video Elementary Streams only. + Program Stream (PS), Transport Stream (TS) and Packetized Elementary + Stream (PES) formats are not supported. + + * Video parameters such as format and input port may not be changed while + the encoder is active. + + * The audio capture device only functions when the video encoder is + actively capturing video. Attempts to read from the audio device when + the encoder is inactive will result in an I/O error. + + * The native format of the audio device is 48Khz 2-channel 16-bit + little-endian PCM, delivered through the ALSA system. No audio + compression is implemented in the hardware. ALSA may convert to other + uncompressed formats on the fly. + +The include/ directory contains a C header file describing non-standard +features of the GO7007SB encoder, which are described below: + + + GO7007IOC_S_COMP_PARAMS, GO7007IOC_G_COMP_PARAMS + + These ioctls are used to negotiate general compression parameters. + + To query the current parameters, call the GO7007IOC_G_COMP_PARAMS ioctl + with a pointer to a struct go7007_comp_params. If the driver is not + set to MPEG format, the EINVAL error code will be returned. + + To change the current parameters, initialize all fields of a struct + go7007_comp_params and call the GO7007_IOC_S_COMP_PARAMS ioctl with a + pointer to this structure. The driver will return the current + parameters with any necessary changes to conform to the limitations of + the hardware or current compression mode. Any or all fields can be set + to zero to request a reasonable default value. If the driver is not + set to MPEG format, the EINVAL error code will be returned. When I/O + is in progress, the EBUSY error code will be returned. + + Fields in struct go7007_comp_params: + + __u32 The maximum number of frames in each + gop_size Group Of Pictures; i.e. the maximum + number of frames minus one between + each key frame. + + __u32 The maximum number of sequential + max_b_frames bidirectionally-predicted frames. + (B-frames are not yet supported.) + + enum go7007_aspect_ratio The aspect ratio to be encoded in the + aspect_ratio meta-data of the compressed format. + + Choices are: + GO7007_ASPECT_RATIO_1_1 + GO7007_ASPECT_RATIO_4_3_NTSC + GO7007_ASPECT_RATIO_4_3_PAL + GO7007_ASPECT_RATIO_16_9_NTSC + GO7007_ASPECT_RATIO_16_9_PAL + + __u32 Bit-wise OR of control flags (below) + flags + + Flags in struct go7007_comp_params: + + GO7007_COMP_CLOSED_GOP Only produce self-contained GOPs, used + to produce streams appropriate for + random seeking. + + GO7007_COMP_OMIT_SEQ_HEADER Omit the stream sequence header. + + + GO7007IOC_S_MPEG_PARAMS, GO7007IOC_G_MPEG_PARAMS + + These ioctls are used to negotiate MPEG-specific stream parameters when + the pixelformat has been set to V4L2_PIX_FMT_MPEG. + + To query the current parameters, call the GO7007IOC_G_MPEG_PARAMS ioctl + with a pointer to a struct go7007_mpeg_params. If the driver is not + set to MPEG format, the EINVAL error code will be returned. + + To change the current parameters, initialize all fields of a struct + go7007_mpeg_params and call the GO7007_IOC_S_MPEG_PARAMS ioctl with a + pointer to this structure. The driver will return the current + parameters with any necessary changes to conform to the limitations of + the hardware or selected MPEG mode. Any or all fields can be set to + zero to request a reasonable default value. If the driver is not set + to MPEG format, the EINVAL error code will be returned. When I/O is in + progress, the EBUSY error code will be returned. + + Fields in struct go7007_mpeg_params: + + enum go7007_mpeg_video_standard + mpeg_video_standard The MPEG video standard in which to + compress the video. + + Choices are: + GO7007_MPEG_VIDEO_MPEG1 + GO7007_MPEG_VIDEO_MPEG2 + GO7007_MPEG_VIDEO_MPEG4 + + __u32 Bit-wise OR of control flags (below) + flags + + __u32 The profile and level indication to be + pali stored in the sequence header. This + is only used as an indicator to the + decoder, and does not affect the MPEG + features used in the video stream. + Not valid for MPEG1. + + Choices for MPEG2 are: + GO7007_MPEG2_PROFILE_MAIN_MAIN + + Choices for MPEG4 are: + GO7007_MPEG4_PROFILE_S_L0 + GO7007_MPEG4_PROFILE_S_L1 + GO7007_MPEG4_PROFILE_S_L2 + GO7007_MPEG4_PROFILE_S_L3 + GO7007_MPEG4_PROFILE_ARTS_L1 + GO7007_MPEG4_PROFILE_ARTS_L2 + GO7007_MPEG4_PROFILE_ARTS_L3 + GO7007_MPEG4_PROFILE_ARTS_L4 + GO7007_MPEG4_PROFILE_AS_L0 + GO7007_MPEG4_PROFILE_AS_L1 + GO7007_MPEG4_PROFILE_AS_L2 + GO7007_MPEG4_PROFILE_AS_L3 + GO7007_MPEG4_PROFILE_AS_L4 + GO7007_MPEG4_PROFILE_AS_L5 + + Flags in struct go7007_mpeg_params: + + GO7007_MPEG_FORCE_DVD_MODE Force all compression parameters and + bitrate control settings to comply + with DVD MPEG2 stream requirements. + This overrides most compression and + bitrate settings! + + GO7007_MPEG_OMIT_GOP_HEADER Omit the GOP header. + + GO7007_MPEG_REPEAT_SEQHEADER Repeat the MPEG sequence header at + the start of each GOP. + + + GO7007IOC_S_BITRATE, GO7007IOC_G_BITRATE + + These ioctls are used to set and query the target bitrate value for the + compressed video stream. The bitrate may be selected by storing the + target bits per second in an int and calling GO7007IOC_S_BITRATE with a + pointer to the int. The bitrate may be queried by calling + GO7007IOC_G_BITRATE with a pointer to an int where the current bitrate + will be stored. + + Note that this is the primary means of controlling the video quality + for all compression modes, including V4L2_PIX_FMT_MJPEG. The + VIDIOC_S_JPEGCOMP ioctl is not supported. + + +---------------------------------------------------------------------------- + Installing the WIS PCI Voyager Driver +--------------------------------------------------------------------------- + +The WIS PCI Voyager driver requires several patches to the Linux 2.6.11.x +kernel source tree before compiling the driver. These patches update the +in-kernel SAA7134 driver to the newest development version and patch bugs +in the TDA8290/TDA8275 tuner driver. + +The following patches must be downloaded from Gerd Knorr's website and +applied in the order listed: + + http://dl.bytesex.org/patches/2.6.11-2/i2c-tuner + http://dl.bytesex.org/patches/2.6.11-2/i2c-tuner2 + http://dl.bytesex.org/patches/2.6.11-2/v4l2-api-mpeg + http://dl.bytesex.org/patches/2.6.11-2/saa7134-update + +The following patches are included with this SDK and can be applied in any +order: + + patches/2.6.11/saa7134-voyager.diff + patches/2.6.11/tda8275-newaddr.diff + patches/2.6.11/tda8290-ntsc.diff + +Check to make sure the CONFIG_VIDEO_SAA7134 option is enabled in the kernel +configuration, and build and install the kernel. + +After rebooting into the new kernel, the GO7007 driver can be compiled and +installed: + + $ make SAA7134_BUILD=y + $ make install + $ modprobe saa7134-go7007 + +There will be two V4L video devices associated with the PCI Voyager. The +first device (most likely /dev/video0) provides access to the raw video +capture mode of the SAA7133 device and is used to configure the source +video parameters and tune the TV tuner. This device can be used with xawtv +or other V4L(2) video software as a standard uncompressed device. + +The second device (most likely /dev/video1) provides access to the +compression functions of the GO7007. It can be tested using the gorecord +application in the apps/ directory of this SDK: + + $ apps/gorecord -vdevice /dev/video1 -noaudio test.avi + +Currently the frame resolution is fixed at 720x480 (NTSC) or 720x576 (PAL), +and the video standard must be specified to both the raw and the compressed +video devices (xawtv and gorecord, for example). + + +-------------------------------------------------------------------------- +RELEASE NOTES FOR WIS GO7007SB LINUX DRIVER +--------------------------------------------------------------------------- + +Last updated: 5 November 2005 + + - Release 0.9.7 includes new support for using udev to run fxload. The + install script should automatically detect whether the old hotplug + scripts or the new udev rules should be used. To force the use of + hotplug, run "make install USE_UDEV=n". To force the use of udev, run + "make install USE_UDEV=y". + + - Motion detection is supported but undocumented. Try the `modet` app + for a demonstration of how to use the facility. + + - Using USB2.0 devices such as the TV402U with USB1.1 HCDs or hubs can + cause buffer overruns and frame drops, even at low framerates, due to + inconsistency in the bitrate control mechanism. + + - On devices with an SAA7115, including the Plextor ConvertX, video height + values of 96, 128, 160, 192, 256, 320, and 384 do not work in NTSC mode. + All valid heights up to 512 work correctly in PAL mode. + + - The WIS Star Trek and PCI Voyager boards have no support yet for audio + or the TV tuner. diff --git a/linux/drivers/staging/go7007/s2250-board.c b/linux/drivers/staging/go7007/s2250-board.c new file mode 100644 index 000000000..b398db43d --- /dev/null +++ b/linux/drivers/staging/go7007/s2250-board.c @@ -0,0 +1,622 @@ +/* + * Copyright (C) 2008 Sensoray Company Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include "go7007-priv.h" +#include "wis-i2c.h" + +extern int s2250loader_init(void); +extern void s2250loader_cleanup(void); + +#define TLV320_ADDRESS 0x34 +#define VPX322_ADDR_ANALOGCONTROL1 0x02 +#define VPX322_ADDR_BRIGHTNESS0 0x0127 +#define VPX322_ADDR_BRIGHTNESS1 0x0131 +#define VPX322_ADDR_CONTRAST0 0x0128 +#define VPX322_ADDR_CONTRAST1 0x0132 +#define VPX322_ADDR_HUE 0x00dc +#define VPX322_ADDR_SAT 0x0030 + +struct go7007_usb_board { + unsigned int flags; + struct go7007_board_info main_info; +}; + +struct go7007_usb { + struct go7007_usb_board *board; + struct semaphore i2c_lock; + struct usb_device *usbdev; + struct urb *video_urbs[8]; + struct urb *audio_urbs[8]; + struct urb *intr_urb; +}; + +static unsigned char aud_regs[] = { + 0x1e, 0x00, + 0x00, 0x17, + 0x02, 0x17, + 0x04, 0xf9, + 0x06, 0xf9, + 0x08, 0x02, + 0x0a, 0x00, + 0x0c, 0x00, + 0x0a, 0x00, + 0x0c, 0x00, + 0x0e, 0x02, + 0x10, 0x00, + 0x12, 0x01, + 0x00, 0x00, +}; + + +static unsigned char vid_regs[] = { + 0xF2, 0x0f, + 0xAA, 0x00, + 0xF8, 0xff, + 0x00, 0x00, +}; + +static u16 vid_regs_fp[] = { + 0x028, 0x067, + 0x120, 0x016, + 0x121, 0xcF2, + 0x122, 0x0F2, + 0x123, 0x00c, + 0x124, 0x2d0, + 0x125, 0x2e0, + 0x126, 0x004, + 0x128, 0x1E0, + 0x12A, 0x016, + 0x12B, 0x0F2, + 0x12C, 0x0F2, + 0x12D, 0x00c, + 0x12E, 0x2d0, + 0x12F, 0x2e0, + 0x130, 0x004, + 0x132, 0x1E0, + 0x140, 0x060, + 0x153, 0x00C, + 0x154, 0x200, + 0x150, 0x801, + 0x000, 0x000 +}; + +/* PAL specific values */ +static u16 vid_regs_fp_pal[] = +{ + 0x120, 0x017, + 0x121, 0xd22, + 0x122, 0x122, + 0x12A, 0x017, + 0x12B, 0x122, + 0x12C, 0x122, + 0x140, 0x060, + 0x000, 0x000, +}; + +struct s2250 { + int std; + int input; + int brightness; + int contrast; + int saturation; + int hue; + int reg12b_val; + int audio_input; + struct i2c_client *audio; +}; + +/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/ +static int go7007_usb_vendor_request(struct go7007 *go, u16 request, + u16 value, u16 index, void *transfer_buffer, int length, int in) +{ + struct go7007_usb *usb = go->hpi_context; + int timeout = 5000; + + if (in) { + return usb_control_msg(usb->usbdev, + usb_rcvctrlpipe(usb->usbdev, 0), request, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + value, index, transfer_buffer, length, timeout); + } else { + return usb_control_msg(usb->usbdev, + usb_sndctrlpipe(usb->usbdev, 0), request, + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, index, transfer_buffer, length, timeout); + } +} +/* end from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/ + +static int write_reg(struct i2c_client *client, u8 reg, u8 value) +{ + struct go7007 *go = i2c_get_adapdata(client->adapter); + struct go7007_usb *usb; + int rc; + int dev_addr = client->addr; + u8 *buf; + + if (go == NULL) + return -ENODEV; + + if (go->status == STATUS_SHUTDOWN) + return -EBUSY; + + buf = kzalloc(16, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + usb = go->hpi_context; + if (down_interruptible(&usb->i2c_lock) != 0) { + printk(KERN_INFO "i2c lock failed\n"); + kfree(buf); + return -EINTR; + } + rc = go7007_usb_vendor_request(go, 0x55, dev_addr, + (reg<<8 | value), + buf, + 16, 1); + + up(&usb->i2c_lock); + kfree(buf); + return rc; +} + +static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val) +{ + struct go7007 *go = i2c_get_adapdata(client->adapter); + struct go7007_usb *usb; + u8 *buf; + struct s2250 *dec = i2c_get_clientdata(client); + + if (go == NULL) + return -ENODEV; + + if (go->status == STATUS_SHUTDOWN) + return -EBUSY; + + buf = kzalloc(16, GFP_KERNEL); + + if (buf == NULL) + return -ENOMEM; + + + + memset(buf, 0xcd, 6); + + usb = go->hpi_context; + if (down_interruptible(&usb->i2c_lock) != 0) { + printk(KERN_INFO "i2c lock failed\n"); + return -EINTR; + } + if (go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1) < 0) + return -EFAULT; + + up(&usb->i2c_lock); + if (buf[0] == 0) { + unsigned int subaddr, val_read; + + subaddr = (buf[4] << 8) + buf[5]; + val_read = (buf[2] << 8) + buf[3]; + if (val_read != val) { + printk(KERN_INFO "invalid fp write %x %x\n", + val_read, val); + return -EFAULT; + } + if (subaddr != addr) { + printk(KERN_INFO "invalid fp write addr %x %x\n", + subaddr, addr); + return -EFAULT; + } + } else + return -EFAULT; + + /* save last 12b value */ + if (addr == 0x12b) + dec->reg12b_val = val; + + return 0; +} + +static int write_regs(struct i2c_client *client, u8 *regs) +{ + int i; + + for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) { + if (write_reg(client, regs[i], regs[i+1]) < 0) { + printk(KERN_INFO "s2250: failed\n"); + return -1; + } + } + return 0; +} + +static int write_regs_fp(struct i2c_client *client, u16 *regs) +{ + int i; + + for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) { + if (write_reg_fp(client, regs[i], regs[i+1]) < 0) { + printk(KERN_INFO "s2250: failed fp\n"); + return -1; + } + } + return 0; +} + + +static int s2250_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct s2250 *dec = i2c_get_clientdata(client); + + switch (cmd) { + case VIDIOC_S_INPUT: + { + int vidsys; + int *input = arg; + + vidsys = (dec->std == V4L2_STD_NTSC) ? 0x01 : 0x00; + if (*input == 0) { + /* composite */ + write_reg_fp(client, 0x20, 0x020 | vidsys); + write_reg_fp(client, 0x21, 0x662); + write_reg_fp(client, 0x140, 0x060); + } else { + /* S-Video */ + write_reg_fp(client, 0x20, 0x040 | vidsys); + write_reg_fp(client, 0x21, 0x666); + write_reg_fp(client, 0x140, 0x060); + } + dec->input = *input; + break; + } + case VIDIOC_S_STD: + { + v4l2_std_id *std = arg; + u16 vidsource; + + vidsource = (dec->input == 1) ? 0x040 : 0x020; + dec->std = *std; + switch (dec->std) { + case V4L2_STD_NTSC: + write_regs_fp(client, vid_regs_fp); + write_reg_fp(client, 0x20, vidsource | 1); + break; + case V4L2_STD_PAL: + write_regs_fp(client, vid_regs_fp); + write_regs_fp(client, vid_regs_fp_pal); + write_reg_fp(client, 0x20, vidsource); + break; + default: + return -EINVAL; + } + break; + } + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *ctrl = arg; + static const u32 user_ctrls[] = { + V4L2_CID_BRIGHTNESS, + V4L2_CID_CONTRAST, + V4L2_CID_SATURATION, + V4L2_CID_HUE, + 0 + }; + static const u32 *ctrl_classes[] = { + user_ctrls, + NULL + }; + + ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id); + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); + break; + case V4L2_CID_CONTRAST: + v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); + break; + case V4L2_CID_SATURATION: + v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); + break; + case V4L2_CID_HUE: + v4l2_ctrl_query_fill(ctrl, -50, 50, 1, 0); + break; + default: + ctrl->name[0] = '\0'; + return -EINVAL; + } + break; + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + int value1; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + printk(KERN_INFO "s2250: future setting\n"); + return -EINVAL; + case V4L2_CID_CONTRAST: + printk(KERN_INFO "s2250: future setting\n"); + return -EINVAL; + break; + case V4L2_CID_SATURATION: + if (ctrl->value > 127) + dec->saturation = 127; + else if (ctrl->value < 0) + dec->saturation = 0; + else + dec->saturation = ctrl->value; + + value1 = dec->saturation * 4140 / 100; + if (value1 > 4094) + value1 = 4094; + write_reg_fp(client, VPX322_ADDR_SAT, value1); + break; + case V4L2_CID_HUE: + if (ctrl->value > 50) + dec->hue = 50; + else if (ctrl->value < -50) + dec->hue = -50; + else + dec->hue = ctrl->value; + /* clamp the hue range */ + value1 = dec->hue * 280 / 50; + write_reg_fp(client, VPX322_ADDR_HUE, value1); + break; + } + break; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = dec->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = dec->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = dec->saturation; + break; + case V4L2_CID_HUE: + ctrl->value = dec->hue; + break; + } + break; + } + case VIDIOC_S_FMT: + { + struct v4l2_format *fmt = arg; + if (fmt->fmt.pix.height < 640) { + write_reg_fp(client, 0x12b, dec->reg12b_val | 0x400); + write_reg_fp(client, 0x140, 0x060); + } else { + write_reg_fp(client, 0x12b, dec->reg12b_val & ~0x400); + write_reg_fp(client, 0x140, 0x060); + } + return 0; + } + case VIDIOC_G_AUDIO: + { + struct v4l2_audio *audio = arg; + + memset(audio, 0, sizeof(*audio)); + audio->index = dec->audio_input; + /* fall through */ + } + case VIDIOC_ENUMAUDIO: + { + struct v4l2_audio *audio = arg; + + switch (audio->index) { + case 0: + strcpy(audio->name, "Line In"); + break; + case 1: + strcpy(audio->name, "Mic"); + break; + case 2: + strcpy(audio->name, "Mic Boost"); + break; + default: + audio->name[0] = '\0'; + return 0; + } + audio->capability = V4L2_AUDCAP_STEREO; + audio->mode = 0; + return 0; + } + case VIDIOC_S_AUDIO: + { + struct v4l2_audio *audio = arg; + + switch (audio->index) { + case 0: + write_reg(dec->audio, 0x08, 0x02); /* Line In */ + break; + case 1: + write_reg(dec->audio, 0x08, 0x04); /* Mic */ + break; + case 2: + write_reg(dec->audio, 0x08, 0x05); /* Mic Boost */ + break; + default: + return -EINVAL; + } + dec->audio_input = audio->index; + return 0; + } + + default: + printk(KERN_INFO "s2250: unknown command 0x%x\n", cmd); + break; + } + return 0; +} + +static int s2250_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_client *audio; + struct i2c_adapter *adapter = client->adapter; + struct s2250 *dec; + u8 *data; + struct go7007 *go = i2c_get_adapdata(adapter); + struct go7007_usb *usb = go->hpi_context; + + audio = i2c_new_dummy(adapter, TLV320_ADDRESS >> 1); + if (audio == NULL) + return -ENOMEM; + + dec = kmalloc(sizeof(struct s2250), GFP_KERNEL); + if (dec == NULL) { + i2c_unregister_device(audio); + return -ENOMEM; + } + + dec->std = V4L2_STD_NTSC; + dec->brightness = 50; + dec->contrast = 50; + dec->saturation = 50; + dec->hue = 0; + dec->audio = audio; + i2c_set_clientdata(client, dec); + + printk(KERN_DEBUG + "s2250: initializing video decoder on %s\n", + adapter->name); + + /* initialize the audio */ + if (write_regs(audio, aud_regs) < 0) { + printk(KERN_ERR + "s2250: error initializing audio\n"); + i2c_unregister_device(audio); + kfree(dec); + return 0; + } + + if (write_regs(client, vid_regs) < 0) { + printk(KERN_ERR + "s2250: error initializing decoder\n"); + i2c_unregister_device(audio); + kfree(dec); + return 0; + } + if (write_regs_fp(client, vid_regs_fp) < 0) { + printk(KERN_ERR + "s2250: error initializing decoder\n"); + i2c_unregister_device(audio); + kfree(dec); + return 0; + } + /* set default channel */ + /* composite */ + write_reg_fp(client, 0x20, 0x020 | 1); + write_reg_fp(client, 0x21, 0x662); + write_reg_fp(client, 0x140, 0x060); + + /* set default audio input */ + dec->audio_input = 0; + write_reg(client, 0x08, 0x02); /* Line In */ + + if (down_interruptible(&usb->i2c_lock) == 0) { + data = kzalloc(16, GFP_KERNEL); + if (data != NULL) { + int rc; + rc = go7007_usb_vendor_request(go, 0x41, 0, 0, + data, 16, 1); + if (rc > 0) { + u8 mask; + data[0] = 0; + mask = 1<<5; + data[0] &= ~mask; + data[1] |= mask; + go7007_usb_vendor_request(go, 0x40, 0, + (data[1]<<8) + + data[1], + data, 16, 0); + } + kfree(data); + } + up(&usb->i2c_lock); + } + + printk("s2250: initialized successfully\n"); + return 0; +} + +static int s2250_remove(struct i2c_client *client) +{ + struct s2250 *dec = i2c_get_clientdata(client); + + i2c_set_clientdata(client, NULL); + i2c_unregister_device(dec->audio); + kfree(dec); + return 0; +} + +static struct i2c_device_id s2250_id[] = { + { "s2250_board", 0 }, + { } +}; + +static struct i2c_driver s2250_driver = { + .driver = { + .name = "Sensoray 2250 board driver", + }, + .probe = s2250_probe, + .remove = s2250_remove, + .command = s2250_command, + .id_table = s2250_id, +}; + +static int __init s2250_init(void) +{ + int r; + + r = s2250loader_init(); + if (r < 0) + return r; + + r = i2c_add_driver(&s2250_driver); + if (r < 0) + s2250loader_cleanup(); + + return r; +} + +static void __exit s2250_cleanup(void) +{ + i2c_del_driver(&s2250_driver); + + s2250loader_cleanup(); +} + +module_init(s2250_init); +module_exit(s2250_cleanup); + +MODULE_AUTHOR(""); +MODULE_DESCRIPTION("Board driver for Sensoryray 2250"); +MODULE_LICENSE("GPL v2"); diff --git a/linux/drivers/staging/go7007/s2250-loader.c b/linux/drivers/staging/go7007/s2250-loader.c new file mode 100644 index 000000000..bb22347af --- /dev/null +++ b/linux/drivers/staging/go7007/s2250-loader.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2008 Sensoray Company Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#define S2250_LOADER_FIRMWARE "s2250_loader.fw" +#define S2250_FIRMWARE "s2250.fw" + +typedef struct device_extension_s { + struct kref kref; + int minor; + struct usb_device *usbdev; +} device_extension_t, *pdevice_extension_t; + +#define USB_s2250loader_MAJOR 240 +#define USB_s2250loader_MINOR_BASE 0 +#define MAX_DEVICES 256 + +static pdevice_extension_t s2250_dev_table[MAX_DEVICES]; +static DECLARE_MUTEX(s2250_dev_table_mutex); + +#define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref) +static void s2250loader_delete(struct kref *kref) +{ + pdevice_extension_t s = to_s2250loader_dev_common(kref); + s2250_dev_table[s->minor] = NULL; + kfree(s); +} + +static int s2250loader_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *usbdev; + int minor, ret; + pdevice_extension_t s = NULL; + const struct firmware *fw; + + usbdev = usb_get_dev(interface_to_usbdev(interface)); + if (!usbdev) { + printk(KERN_ERR "Enter s2250loader_probe failed\n"); + return -1; + } + printk(KERN_INFO "Enter s2250loader_probe 2.6 kernel\n"); + printk(KERN_INFO "vendor id 0x%x, device id 0x%x devnum:%d\n", + usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, + usbdev->devnum); + + if (usbdev->descriptor.bNumConfigurations != 1) { + printk(KERN_ERR "can't handle multiple config\n"); + return -1; + } + down(&s2250_dev_table_mutex); + + for (minor = 0; minor < MAX_DEVICES; minor++) { + if (s2250_dev_table[minor] == NULL) + break; + } + + if (minor < 0 || minor >= MAX_DEVICES) { + printk(KERN_ERR "Invalid minor: %d\n", minor); + goto failed; + } + + /* Allocate dev data structure */ + s = kmalloc(sizeof(device_extension_t), GFP_KERNEL); + if (s == NULL) { + printk(KERN_ERR "Out of memory\n"); + goto failed; + } + s2250_dev_table[minor] = s; + + printk(KERN_INFO "s2250loader_probe: Device %d on Bus %d Minor %d\n", + usbdev->devnum, usbdev->bus->busnum, minor); + + memset(s, 0, sizeof(device_extension_t)); + s->usbdev = usbdev; + printk(KERN_INFO "loading 2250 loader\n"); + + kref_init(&(s->kref)); + + up(&s2250_dev_table_mutex); + + if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) { + printk(KERN_ERR + "s2250: unable to load firmware from file \"%s\"\n", + S2250_LOADER_FIRMWARE); + goto failed2; + } + ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2); + release_firmware(fw); + if (0 != ret) { + printk(KERN_ERR "loader download failed\n"); + goto failed2; + } + + if (request_firmware(&fw, S2250_FIRMWARE, &usbdev->dev)) { + printk(KERN_ERR + "s2250: unable to load firmware from file \"%s\"\n", + S2250_FIRMWARE); + goto failed2; + } + ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2); + release_firmware(fw); + if (0 != ret) { + printk(KERN_ERR "firmware_s2250 download failed\n"); + goto failed2; + } + + usb_set_intfdata(interface, s); + return 0; + +failed: + up(&s2250_dev_table_mutex); +failed2: + if (s) + kref_put(&(s->kref), s2250loader_delete); + + printk(KERN_ERR "probe failed\n"); + return -1; +} + +static void s2250loader_disconnect(struct usb_interface *interface) +{ + pdevice_extension_t s = usb_get_intfdata(interface); + printk(KERN_INFO "s2250: disconnect\n"); + lock_kernel(); + s = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + kref_put(&(s->kref), s2250loader_delete); + unlock_kernel(); +} + +static struct usb_device_id s2250loader_ids[] = { + {USB_DEVICE(0x1943, 0xa250)}, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, s2250loader_ids); + +static struct usb_driver s2250loader_driver = { + .name = "s2250-loader", + .probe = s2250loader_probe, + .disconnect = s2250loader_disconnect, + .id_table = s2250loader_ids, +}; + +int s2250loader_init(void) +{ + int r; + unsigned i = 0; + + for (i = 0; i < MAX_DEVICES; i++) + s2250_dev_table[i] = NULL; + + r = usb_register(&s2250loader_driver); + if (r) { + printk(KERN_ERR "usb_register failed. Error number %d\n", r); + return -1; + } + + printk(KERN_INFO "s2250loader_init: driver registered\n"); + return 0; +} +EXPORT_SYMBOL(s2250loader_init); + +void s2250loader_cleanup(void) +{ + printk(KERN_INFO "s2250loader_cleanup\n"); + usb_deregister(&s2250loader_driver); +} +EXPORT_SYMBOL(s2250loader_cleanup); diff --git a/linux/drivers/staging/go7007/s2250-loader.h b/linux/drivers/staging/go7007/s2250-loader.h new file mode 100644 index 000000000..b7c301af1 --- /dev/null +++ b/linux/drivers/staging/go7007/s2250-loader.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#ifndef _S2250_LOADER_H_ +#define _S2250_LOADER_H_ + +extern int s2250loader_init(void); +extern void s2250loader_cleanup(void); + +#endif diff --git a/linux/drivers/staging/go7007/saa7134-go7007.c b/linux/drivers/staging/go7007/saa7134-go7007.c new file mode 100644 index 000000000..665bbf59d --- /dev/null +++ b/linux/drivers/staging/go7007/saa7134-go7007.c @@ -0,0 +1,532 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "saa7134-reg.h" +#include "saa7134.h" +#include "go7007-priv.h" + +#define GO7007_HPI_DEBUG + +enum hpi_address { + HPI_ADDR_VIDEO_BUFFER = 0xe4, + HPI_ADDR_INIT_BUFFER = 0xea, + HPI_ADDR_INTR_RET_VALUE = 0xee, + HPI_ADDR_INTR_RET_DATA = 0xec, + HPI_ADDR_INTR_STATUS = 0xf4, + HPI_ADDR_INTR_WR_PARAM = 0xf6, + HPI_ADDR_INTR_WR_INDEX = 0xf8, +}; + +enum gpio_command { + GPIO_COMMAND_RESET = 0x00, /* 000b */ + GPIO_COMMAND_REQ1 = 0x04, /* 001b */ + GPIO_COMMAND_WRITE = 0x20, /* 010b */ + GPIO_COMMAND_REQ2 = 0x24, /* 011b */ + GPIO_COMMAND_READ = 0x80, /* 100b */ + GPIO_COMMAND_VIDEO = 0x84, /* 101b */ + GPIO_COMMAND_IDLE = 0xA0, /* 110b */ + GPIO_COMMAND_ADDR = 0xA4, /* 111b */ +}; + +struct saa7134_go7007 { + struct saa7134_dev *dev; + u8 *top; + u8 *bottom; + dma_addr_t top_dma; + dma_addr_t bottom_dma; +}; + +static struct go7007_board_info board_voyager = { + .firmware = "go7007tv.bin", + .flags = 0, + .sensor_flags = GO7007_SENSOR_656 | + GO7007_SENSOR_VALID_ENABLE | + GO7007_SENSOR_TV | + GO7007_SENSOR_VBI, + .audio_flags = GO7007_AUDIO_I2S_MODE_1 | + GO7007_AUDIO_WORD_16, + .audio_rate = 48000, + .audio_bclk_div = 8, + .audio_main_div = 2, + .hpi_buffer_cap = 7, + .num_inputs = 1, + .inputs = { + { + .name = "SAA7134", + }, + }, +}; + +/********************* Driver for GPIO HPI interface *********************/ + +static int gpio_write(struct saa7134_dev *dev, u8 addr, u16 data) +{ + saa_writeb(SAA7134_GPIO_GPMODE0, 0xff); + + /* Write HPI address */ + saa_writeb(SAA7134_GPIO_GPSTATUS0, addr); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); + + /* Write low byte */ + saa_writeb(SAA7134_GPIO_GPSTATUS0, data & 0xff); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); + + /* Write high byte */ + saa_writeb(SAA7134_GPIO_GPSTATUS0, data >> 8); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); + + return 0; +} + +static int gpio_read(struct saa7134_dev *dev, u8 addr, u16 *data) +{ + saa_writeb(SAA7134_GPIO_GPMODE0, 0xff); + + /* Write HPI address */ + saa_writeb(SAA7134_GPIO_GPSTATUS0, addr); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); + + saa_writeb(SAA7134_GPIO_GPMODE0, 0x00); + + /* Read low byte */ + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ); + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + *data = saa_readb(SAA7134_GPIO_GPSTATUS0); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); + + /* Read high byte */ + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ); + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + *data |= saa_readb(SAA7134_GPIO_GPSTATUS0) << 8; + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); + + return 0; +} + +static int saa7134_go7007_interface_reset(struct go7007 *go) +{ + struct saa7134_go7007 *saa = go->hpi_context; + struct saa7134_dev *dev = saa->dev; + u32 status; + u16 intr_val, intr_data; + int count = 20; + + saa_clearb(SAA7134_TS_PARALLEL, 0x80); /* Disable TS interface */ + saa_writeb(SAA7134_GPIO_GPMODE2, 0xa4); + saa_writeb(SAA7134_GPIO_GPMODE0, 0xff); + + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_RESET); + msleep(1); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2); + msleep(10); + + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + + status = saa_readb(SAA7134_GPIO_GPSTATUS2); + /*printk(KERN_DEBUG "status is %s\n", status & 0x40 ? "OK" : "not OK"); */ + + /* enter command mode...(?) */ + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2); + + do { + saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); + status = saa_readb(SAA7134_GPIO_GPSTATUS2); + /*printk(KERN_INFO "gpio is %08x\n", saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)); */ + } while (--count > 0); + + /* Wait for an interrupt to indicate successful hardware reset */ + if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || + (intr_val & ~0x1) != 0x55aa) { + printk(KERN_ERR + "saa7134-go7007: unable to reset the GO7007\n"); + return -1; + } + return 0; +} + +static int saa7134_go7007_write_interrupt(struct go7007 *go, int addr, int data) +{ + struct saa7134_go7007 *saa = go->hpi_context; + struct saa7134_dev *dev = saa->dev; + int i; + u16 status_reg; + +#ifdef GO7007_HPI_DEBUG + printk(KERN_DEBUG + "saa7134-go7007: WriteInterrupt: %04x %04x\n", addr, data); +#endif + + for (i = 0; i < 100; ++i) { + gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg); + if (!(status_reg & 0x0010)) + break; + msleep(10); + } + if (i == 100) { + printk(KERN_ERR + "saa7134-go7007: device is hung, status reg = 0x%04x\n", + status_reg); + return -1; + } + gpio_write(dev, HPI_ADDR_INTR_WR_PARAM, data); + gpio_write(dev, HPI_ADDR_INTR_WR_INDEX, addr); + + return 0; +} + +static int saa7134_go7007_read_interrupt(struct go7007 *go) +{ + struct saa7134_go7007 *saa = go->hpi_context; + struct saa7134_dev *dev = saa->dev; + + /* XXX we need to wait if there is no interrupt available */ + go->interrupt_available = 1; + gpio_read(dev, HPI_ADDR_INTR_RET_VALUE, &go->interrupt_value); + gpio_read(dev, HPI_ADDR_INTR_RET_DATA, &go->interrupt_data); +#ifdef GO7007_HPI_DEBUG + printk(KERN_DEBUG "saa7134-go7007: ReadInterrupt: %04x %04x\n", + go->interrupt_value, go->interrupt_data); +#endif + return 0; +} + +static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev, + unsigned long status) +{ + struct go7007 *go = video_get_drvdata(dev->empress_dev); + struct saa7134_go7007 *saa = go->hpi_context; + + if (!go->streaming) + return; + if (0 != (status & 0x000f0000)) + printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n", + (status >> 16) & 0x0f); + if (status & 0x100000) { + dma_sync_single(&dev->pci->dev, + saa->bottom_dma, PAGE_SIZE, DMA_FROM_DEVICE); + go7007_parse_video_stream(go, saa->bottom, PAGE_SIZE); + saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma)); + } else { + dma_sync_single(&dev->pci->dev, + saa->top_dma, PAGE_SIZE, DMA_FROM_DEVICE); + go7007_parse_video_stream(go, saa->top, PAGE_SIZE); + saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma)); + } +} + +static int saa7134_go7007_stream_start(struct go7007 *go) +{ + struct saa7134_go7007 *saa = go->hpi_context; + struct saa7134_dev *dev = saa->dev; + + saa->top_dma = dma_map_page(&dev->pci->dev, virt_to_page(saa->top), + 0, PAGE_SIZE, DMA_FROM_DEVICE); + if (!saa->top_dma) + return -ENOMEM; + saa->bottom_dma = dma_map_page(&dev->pci->dev, + virt_to_page(saa->bottom), + 0, PAGE_SIZE, DMA_FROM_DEVICE); + if (!saa->bottom_dma) { + dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE, + DMA_FROM_DEVICE); + return -ENOMEM; + } + + saa_writel(SAA7134_VIDEO_PORT_CTRL0 >> 2, 0xA300B000); + saa_writel(SAA7134_VIDEO_PORT_CTRL4 >> 2, 0x40000200); + + /* Set HPI interface for video */ + saa_writeb(SAA7134_GPIO_GPMODE0, 0xff); + saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_VIDEO_BUFFER); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR); + saa_writeb(SAA7134_GPIO_GPMODE0, 0x00); + + /* Enable TS interface */ + saa_writeb(SAA7134_TS_PARALLEL, 0xe6); + + /* Reset TS interface */ + saa_setb(SAA7134_TS_SERIAL1, 0x01); + saa_clearb(SAA7134_TS_SERIAL1, 0x01); + + /* Set up transfer block size */ + saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 128 - 1); + saa_writeb(SAA7134_TS_DMA0, (PAGE_SIZE >> 7) - 1); + saa_writeb(SAA7134_TS_DMA1, 0); + saa_writeb(SAA7134_TS_DMA2, 0); + + /* Enable video streaming mode */ + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_VIDEO); + + saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma)); + saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma)); + saa_writel(SAA7134_RS_PITCH(5), 128); + saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_MAX); + + /* Enable TS FIFO */ + saa_setl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5); + + /* Enable DMA IRQ */ + saa_setl(SAA7134_IRQ1, + SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0); + + return 0; +} + +static int saa7134_go7007_stream_stop(struct go7007 *go) +{ + struct saa7134_go7007 *saa = go->hpi_context; + struct saa7134_dev *dev; + + if (!saa) + return -EINVAL; + dev = saa->dev; + if (!dev) + return -EINVAL; + + /* Shut down TS FIFO */ + saa_clearl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5); + + /* Disable DMA IRQ */ + saa_clearl(SAA7134_IRQ1, + SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0); + + /* Disable TS interface */ + saa_clearb(SAA7134_TS_PARALLEL, 0x80); + + dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE, + DMA_FROM_DEVICE); + dma_unmap_page(&dev->pci->dev, saa->bottom_dma, PAGE_SIZE, + DMA_FROM_DEVICE); + + return 0; +} + +static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len) +{ + struct saa7134_go7007 *saa = go->hpi_context; + struct saa7134_dev *dev = saa->dev; + u16 status_reg; + int i; + +#ifdef GO7007_HPI_DEBUG + printk(KERN_DEBUG "saa7134-go7007: DownloadBuffer " + "sending %d bytes\n", len); +#endif + + while (len > 0) { + i = len > 64 ? 64 : len; + saa_writeb(SAA7134_GPIO_GPMODE0, 0xff); + saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_INIT_BUFFER); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); + while (i-- > 0) { + saa_writeb(SAA7134_GPIO_GPSTATUS0, *data); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE); + saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE); + ++data; + --len; + } + for (i = 0; i < 100; ++i) { + gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg); + if (!(status_reg & 0x0002)) + break; + } + if (i == 100) { + printk(KERN_ERR "saa7134-go7007: device is hung, " + "status reg = 0x%04x\n", status_reg); + return -1; + } + } + return 0; +} + +static int saa7134_go7007_send_command(struct go7007 *go, unsigned int cmd, + void *arg) +{ + struct saa7134_go7007 *saa = go->hpi_context; + struct saa7134_dev *dev = saa->dev; + + switch (cmd) { + case VIDIOC_S_STD: + { + v4l2_std_id *std = arg; + return saa7134_s_std_internal(dev, NULL, std); + } + case VIDIOC_G_STD: + { + v4l2_std_id *std = arg; + *std = dev->tvnorm->id; + return 0; + } + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *ctrl = arg; + if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER) + return saa7134_queryctrl(NULL, NULL, ctrl); + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER) + return saa7134_g_ctrl_internal(dev, NULL, ctrl); + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER) + return saa7134_s_ctrl_internal(dev, NULL, ctrl); + } + } + return -EINVAL; + +} + +static struct go7007_hpi_ops saa7134_go7007_hpi_ops = { + .interface_reset = saa7134_go7007_interface_reset, + .write_interrupt = saa7134_go7007_write_interrupt, + .read_interrupt = saa7134_go7007_read_interrupt, + .stream_start = saa7134_go7007_stream_start, + .stream_stop = saa7134_go7007_stream_stop, + .send_firmware = saa7134_go7007_send_firmware, + .send_command = saa7134_go7007_send_command, +}; + +/********************* Add/remove functions *********************/ + +static int saa7134_go7007_init(struct saa7134_dev *dev) +{ + struct go7007 *go; + struct saa7134_go7007 *saa; + + printk(KERN_DEBUG "saa7134-go7007: probing new SAA713X board\n"); + + saa = kmalloc(sizeof(struct saa7134_go7007), GFP_KERNEL); + if (saa == NULL) + return -ENOMEM; + memset(saa, 0, sizeof(struct saa7134_go7007)); + + /* Allocate a couple pages for receiving the compressed stream */ + saa->top = (u8 *)get_zeroed_page(GFP_KERNEL); + if (!saa->top) + goto allocfail; + saa->bottom = (u8 *)get_zeroed_page(GFP_KERNEL); + if (!saa->bottom) + goto allocfail; + + go = go7007_alloc(&board_voyager, &dev->pci->dev); + if (go == NULL) + goto allocfail; + go->board_id = GO7007_BOARDID_PCI_VOYAGER; + strncpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name)); + go->hpi_ops = &saa7134_go7007_hpi_ops; + go->hpi_context = saa; + saa->dev = dev; + + /* Boot the GO7007 */ + if (go7007_boot_encoder(go, go->board_info->flags & + GO7007_BOARD_USE_ONBOARD_I2C) < 0) + goto initfail; + + /* Do any final GO7007 initialization, then register the + * V4L2 and ALSA interfaces */ + if (go7007_register_encoder(go) < 0) + goto initfail; + dev->empress_dev = go->video_dev; + video_set_drvdata(dev->empress_dev, go); + + go->status = STATUS_ONLINE; + return 0; + +initfail: + go->status = STATUS_SHUTDOWN; + return 0; + +allocfail: + if (saa->top) + free_page((unsigned long)saa->top); + if (saa->bottom) + free_page((unsigned long)saa->bottom); + kfree(saa); + return -ENOMEM; +} + +static int saa7134_go7007_fini(struct saa7134_dev *dev) +{ + struct go7007 *go; + struct saa7134_go7007 *saa; + + if (NULL == dev->empress_dev) + return 0; + + go = video_get_drvdata(dev->empress_dev); + saa = go->hpi_context; + go->status = STATUS_SHUTDOWN; + free_page((unsigned long)saa->top); + free_page((unsigned long)saa->bottom); + kfree(saa); + go7007_remove(go); + dev->empress_dev = NULL; + + return 0; +} + +static struct saa7134_mpeg_ops saa7134_go7007_ops = { + .type = SAA7134_MPEG_GO7007, + .init = saa7134_go7007_init, + .fini = saa7134_go7007_fini, + .irq_ts_done = saa7134_go7007_irq_ts_done, +}; + +static int __init saa7134_go7007_mod_init(void) +{ + return saa7134_ts_register(&saa7134_go7007_ops); +} + +static void __exit saa7134_go7007_mod_cleanup(void) +{ + saa7134_ts_unregister(&saa7134_go7007_ops); +} + +module_init(saa7134_go7007_mod_init); +module_exit(saa7134_go7007_mod_cleanup); + +MODULE_LICENSE("GPL v2"); diff --git a/linux/drivers/staging/go7007/snd-go7007.c b/linux/drivers/staging/go7007/snd-go7007.c new file mode 100644 index 000000000..cd19be6c0 --- /dev/null +++ b/linux/drivers/staging/go7007/snd-go7007.c @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "go7007-priv.h" + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; + +module_param_array(index, int, NULL, 0444); +module_param_array(id, charp, NULL, 0444); +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for the go7007 audio driver"); +MODULE_PARM_DESC(id, "ID string for the go7007 audio driver"); +MODULE_PARM_DESC(enable, "Enable for the go7007 audio driver"); + +struct go7007_snd { + struct snd_card *card; + struct snd_pcm *pcm; + struct snd_pcm_substream *substream; + spinlock_t lock; + int w_idx; + int hw_ptr; + int avail; + int capturing; +}; + +static struct snd_pcm_hardware go7007_snd_capture_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = (128*1024), + .period_bytes_min = 4096, + .period_bytes_max = (128*1024), + .periods_min = 1, + .periods_max = 32, +}; + +static void parse_audio_stream_data(struct go7007 *go, u8 *buf, int length) +{ + struct go7007_snd *gosnd = go->snd_context; + struct snd_pcm_runtime *runtime = gosnd->substream->runtime; + int frames = bytes_to_frames(runtime, length); + + spin_lock(&gosnd->lock); + gosnd->hw_ptr += frames; + if (gosnd->hw_ptr >= runtime->buffer_size) + gosnd->hw_ptr -= runtime->buffer_size; + gosnd->avail += frames; + spin_unlock(&gosnd->lock); + if (gosnd->w_idx + length > runtime->dma_bytes) { + int cpy = runtime->dma_bytes - gosnd->w_idx; + + memcpy(runtime->dma_area + gosnd->w_idx, buf, cpy); + length -= cpy; + buf += cpy; + gosnd->w_idx = 0; + } + memcpy(runtime->dma_area + gosnd->w_idx, buf, length); + gosnd->w_idx += length; + spin_lock(&gosnd->lock); + if (gosnd->avail < runtime->period_size) { + spin_unlock(&gosnd->lock); + return; + } + gosnd->avail -= runtime->period_size; + spin_unlock(&gosnd->lock); + if (gosnd->capturing) + snd_pcm_period_elapsed(gosnd->substream); +} + +static int go7007_snd_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct go7007 *go = snd_pcm_substream_chip(substream); + unsigned int bytes; + + bytes = params_buffer_bytes(hw_params); + if (substream->runtime->dma_bytes > 0) + vfree(substream->runtime->dma_area); + substream->runtime->dma_bytes = 0; + substream->runtime->dma_area = vmalloc(bytes); + if (substream->runtime->dma_area == NULL) + return -ENOMEM; + substream->runtime->dma_bytes = bytes; + go->audio_deliver = parse_audio_stream_data; + return 0; +} + +static int go7007_snd_hw_free(struct snd_pcm_substream *substream) +{ + struct go7007 *go = snd_pcm_substream_chip(substream); + + go->audio_deliver = NULL; + if (substream->runtime->dma_bytes > 0) + vfree(substream->runtime->dma_area); + substream->runtime->dma_bytes = 0; + return 0; +} + +static int go7007_snd_capture_open(struct snd_pcm_substream *substream) +{ + struct go7007 *go = snd_pcm_substream_chip(substream); + struct go7007_snd *gosnd = go->snd_context; + unsigned long flags; + int r; + + spin_lock_irqsave(&gosnd->lock, flags); + if (gosnd->substream == NULL) { + gosnd->substream = substream; + substream->runtime->hw = go7007_snd_capture_hw; + r = 0; + } else + r = -EBUSY; + spin_unlock_irqrestore(&gosnd->lock, flags); + return r; +} + +static int go7007_snd_capture_close(struct snd_pcm_substream *substream) +{ + struct go7007 *go = snd_pcm_substream_chip(substream); + struct go7007_snd *gosnd = go->snd_context; + + gosnd->substream = NULL; + return 0; +} + +static int go7007_snd_pcm_prepare(struct snd_pcm_substream *substream) +{ + return 0; +} + +static int go7007_snd_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct go7007 *go = snd_pcm_substream_chip(substream); + struct go7007_snd *gosnd = go->snd_context; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + /* Just set a flag to indicate we should signal ALSA when + * sound comes in */ + gosnd->capturing = 1; + return 0; + case SNDRV_PCM_TRIGGER_STOP: + gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0; + gosnd->capturing = 0; + return 0; + default: + return -EINVAL; + } +} + +static snd_pcm_uframes_t go7007_snd_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct go7007 *go = snd_pcm_substream_chip(substream); + struct go7007_snd *gosnd = go->snd_context; + + return gosnd->hw_ptr; +} + +static struct page *go7007_snd_pcm_page(struct snd_pcm_substream *substream, + unsigned long offset) +{ + return vmalloc_to_page(substream->runtime->dma_area + offset); +} + +static struct snd_pcm_ops go7007_snd_capture_ops = { + .open = go7007_snd_capture_open, + .close = go7007_snd_capture_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = go7007_snd_hw_params, + .hw_free = go7007_snd_hw_free, + .prepare = go7007_snd_pcm_prepare, + .trigger = go7007_snd_pcm_trigger, + .pointer = go7007_snd_pcm_pointer, + .page = go7007_snd_pcm_page, +}; + +static int go7007_snd_free(struct snd_device *device) +{ + struct go7007 *go = device->device_data; + + kfree(go->snd_context); + go->snd_context = NULL; + if (--go->ref_count == 0) + kfree(go); + return 0; +} + +static struct snd_device_ops go7007_snd_device_ops = { + .dev_free = go7007_snd_free, +}; + +int go7007_snd_init(struct go7007 *go) +{ + static int dev; + struct go7007_snd *gosnd; + int ret = 0; + + if (dev >= SNDRV_CARDS) + return -ENODEV; + if (!enable[dev]) { + dev++; + return -ENOENT; + } + gosnd = kmalloc(sizeof(struct go7007_snd), GFP_KERNEL); + if (gosnd == NULL) + return -ENOMEM; + spin_lock_init(&gosnd->lock); + gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0; + gosnd->capturing = 0; + ret = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, + &gosnd->card); + if (ret < 0) { + kfree(gosnd); + return ret; + } + ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go, + &go7007_snd_device_ops); + if (ret < 0) { + kfree(gosnd); + return ret; + } + snd_card_set_dev(gosnd->card, go->dev); + ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm); + if (ret < 0) { + snd_card_free(gosnd->card); + kfree(gosnd); + return ret; + } + strncpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver)); + strncpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver)); + strncpy(gosnd->card->longname, gosnd->card->shortname, + sizeof(gosnd->card->longname)); + + gosnd->pcm->private_data = go; + snd_pcm_set_ops(gosnd->pcm, SNDRV_PCM_STREAM_CAPTURE, + &go7007_snd_capture_ops); + + ret = snd_card_register(gosnd->card); + if (ret < 0) { + snd_card_free(gosnd->card); + kfree(gosnd); + return ret; + } + + gosnd->substream = NULL; + go->snd_context = gosnd; + ++dev; + ++go->ref_count; + + return 0; +} +EXPORT_SYMBOL(go7007_snd_init); + +int go7007_snd_remove(struct go7007 *go) +{ + struct go7007_snd *gosnd = go->snd_context; + + snd_card_disconnect(gosnd->card); + snd_card_free_when_closed(gosnd->card); + return 0; +} +EXPORT_SYMBOL(go7007_snd_remove); + +MODULE_LICENSE("GPL v2"); diff --git a/linux/drivers/staging/go7007/wis-i2c.h b/linux/drivers/staging/go7007/wis-i2c.h new file mode 100644 index 000000000..3c2b9be45 --- /dev/null +++ b/linux/drivers/staging/go7007/wis-i2c.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +/* Temporary I2C IDs -- these need to be replaced with real registered IDs */ +#define I2C_DRIVERID_WIS_SAA7115 0xf0f0 +#define I2C_DRIVERID_WIS_UDA1342 0xf0f1 +#define I2C_DRIVERID_WIS_SONY_TUNER 0xf0f2 +#define I2C_DRIVERID_WIS_TW9903 0xf0f3 +#define I2C_DRIVERID_WIS_SAA7113 0xf0f4 +#define I2C_DRIVERID_WIS_OV7640 0xf0f5 +#define I2C_DRIVERID_WIS_TW2804 0xf0f6 +#define I2C_DRIVERID_S2250 0xf0f7 + +/* Flag to indicate that the client needs to be accessed with SCCB semantics */ +/* We re-use the I2C_M_TEN value so the flag passes through the masks in the + * core I2C code. Major kludge, but the I2C layer ain't exactly flexible. */ +#define I2C_CLIENT_SCCB 0x10 + +/* Definitions for new video decoder commands */ + +struct video_decoder_resolution { + unsigned int width; + unsigned int height; +}; + +#define DECODER_SET_RESOLUTION _IOW('d', 200, struct video_decoder_resolution) +#define DECODER_SET_CHANNEL _IOW('d', 201, int) + +/* Sony tuner types */ + +#define TUNER_SONY_BTF_PG472Z 200 +#define TUNER_SONY_BTF_PK467Z 201 +#define TUNER_SONY_BTF_PB463Z 202 diff --git a/linux/drivers/staging/go7007/wis-ov7640.c b/linux/drivers/staging/go7007/wis-ov7640.c new file mode 100644 index 000000000..04d6d3a49 --- /dev/null +++ b/linux/drivers/staging/go7007/wis-ov7640.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include "wis-i2c.h" + +struct wis_ov7640 { + int brightness; + int contrast; + int saturation; + int hue; +}; + +static u8 initial_registers[] = +{ + 0x12, 0x80, + 0x12, 0x54, + 0x14, 0x24, + 0x15, 0x01, + 0x28, 0x20, + 0x75, 0x82, + 0xFF, 0xFF, /* Terminator (reg 0xFF is unused) */ +}; + +static int write_regs(struct i2c_client *client, u8 *regs) +{ + int i; + + for (i = 0; regs[i] != 0xFF; i += 2) + if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0) + return -1; + return 0; +} + +static int wis_ov7640_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + client->flags = I2C_CLIENT_SCCB; + + printk(KERN_DEBUG + "wis-ov7640: initializing OV7640 at address %d on %s\n", + client->addr, adapter->name); + + if (write_regs(client, initial_registers) < 0) { + printk(KERN_ERR "wis-ov7640: error initializing OV7640\n"); + return -ENODEV; + } + + return 0; +} + +static int wis_ov7640_remove(struct i2c_client *client) +{ + return 0; +} + +static struct i2c_device_id wis_ov7640_id[] = { + { "wis_ov7640", 0 }, + { } +}; + +static struct i2c_driver wis_ov7640_driver = { + .driver = { + .name = "WIS OV7640 I2C driver", + }, + .probe = wis_ov7640_probe, + .remove = wis_ov7640_remove, + .id_table = wis_ov7640_id, +}; + +static int __init wis_ov7640_init(void) +{ + return i2c_add_driver(&wis_ov7640_driver); +} + +static void __exit wis_ov7640_cleanup(void) +{ + i2c_del_driver(&wis_ov7640_driver); +} + +module_init(wis_ov7640_init); +module_exit(wis_ov7640_cleanup); + +MODULE_LICENSE("GPL v2"); diff --git a/linux/drivers/staging/go7007/wis-saa7113.c b/linux/drivers/staging/go7007/wis-saa7113.c new file mode 100644 index 000000000..9ab893bd2 --- /dev/null +++ b/linux/drivers/staging/go7007/wis-saa7113.c @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include "wis-i2c.h" + +struct wis_saa7113 { + int norm; + int brightness; + int contrast; + int saturation; + int hue; +}; + +static u8 initial_registers[] = +{ + 0x01, 0x08, + 0x02, 0xc0, + 0x03, 0x33, + 0x04, 0x00, + 0x05, 0x00, + 0x06, 0xe9, + 0x07, 0x0d, + 0x08, 0xd8, + 0x09, 0x40, + 0x0a, 0x80, + 0x0b, 0x47, + 0x0c, 0x40, + 0x0d, 0x00, + 0x0e, 0x01, + 0x0f, 0x2a, + 0x10, 0x40, + 0x11, 0x0c, + 0x12, 0xfe, + 0x13, 0x00, + 0x14, 0x00, + 0x15, 0x04, + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, + 0x1b, 0x00, + 0x1c, 0x00, + 0x1d, 0x00, + 0x1e, 0x00, + 0x1f, 0xc8, + 0x40, 0x00, + 0x41, 0xff, + 0x42, 0xff, + 0x43, 0xff, + 0x44, 0xff, + 0x45, 0xff, + 0x46, 0xff, + 0x47, 0xff, + 0x48, 0xff, + 0x49, 0xff, + 0x4a, 0xff, + 0x4b, 0xff, + 0x4c, 0xff, + 0x4d, 0xff, + 0x4e, 0xff, + 0x4f, 0xff, + 0x50, 0xff, + 0x51, 0xff, + 0x52, 0xff, + 0x53, 0xff, + 0x54, 0xff, + 0x55, 0xff, + 0x56, 0xff, + 0x57, 0xff, + 0x58, 0x00, + 0x59, 0x54, + 0x5a, 0x07, + 0x5b, 0x83, + 0x5c, 0x00, + 0x5d, 0x00, + 0x5e, 0x00, + 0x5f, 0x00, + 0x60, 0x00, + 0x61, 0x00, + 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */ +}; + +static int write_reg(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +static int write_regs(struct i2c_client *client, u8 *regs) +{ + int i; + + for (i = 0; regs[i] != 0x00; i += 2) + if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0) + return -1; + return 0; +} + +static int wis_saa7113_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct wis_saa7113 *dec = i2c_get_clientdata(client); + + switch (cmd) { + case VIDIOC_S_INPUT: + { + int *input = arg; + + i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input); + i2c_smbus_write_byte_data(client, 0x09, + *input < 6 ? 0x40 : 0x80); + break; + } + case VIDIOC_S_STD: + { + v4l2_std_id *input = arg; + dec->norm = *input; + if (dec->norm & V4L2_STD_NTSC) { + write_reg(client, 0x0e, 0x01); + write_reg(client, 0x10, 0x40); + } else if (dec->norm & V4L2_STD_PAL) { + write_reg(client, 0x0e, 0x01); + write_reg(client, 0x10, 0x48); + } else if (dec->norm * V4L2_STD_SECAM) { + write_reg(client, 0x0e, 0x50); + write_reg(client, 0x10, 0x48); + } + break; + } + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 255; + ctrl->step = 1; + ctrl->default_value = 128; + ctrl->flags = 0; + break; + case V4L2_CID_CONTRAST: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 127; + ctrl->step = 1; + ctrl->default_value = 71; + ctrl->flags = 0; + break; + case V4L2_CID_SATURATION: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 127; + ctrl->step = 1; + ctrl->default_value = 64; + ctrl->flags = 0; + break; + case V4L2_CID_HUE: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Hue", sizeof(ctrl->name)); + ctrl->minimum = -128; + ctrl->maximum = 127; + ctrl->step = 1; + ctrl->default_value = 0; + ctrl->flags = 0; + break; + } + break; + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (ctrl->value > 255) + dec->brightness = 255; + else if (ctrl->value < 0) + dec->brightness = 0; + else + dec->brightness = ctrl->value; + write_reg(client, 0x0a, dec->brightness); + break; + case V4L2_CID_CONTRAST: + if (ctrl->value > 127) + dec->contrast = 127; + else if (ctrl->value < 0) + dec->contrast = 0; + else + dec->contrast = ctrl->value; + write_reg(client, 0x0b, dec->contrast); + break; + case V4L2_CID_SATURATION: + if (ctrl->value > 127) + dec->saturation = 127; + else if (ctrl->value < 0) + dec->saturation = 0; + else + dec->saturation = ctrl->value; + write_reg(client, 0x0c, dec->saturation); + break; + case V4L2_CID_HUE: + if (ctrl->value > 127) + dec->hue = 127; + else if (ctrl->value < -128) + dec->hue = -128; + else + dec->hue = ctrl->value; + write_reg(client, 0x0d, dec->hue); + break; + } + break; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = dec->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = dec->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = dec->saturation; + break; + case V4L2_CID_HUE: + ctrl->value = dec->hue; + break; + } + break; + } + default: + break; + } + return 0; +} + +static int wis_saa7113_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct wis_saa7113 *dec; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + dec = kmalloc(sizeof(struct wis_saa7113), GFP_KERNEL); + if (dec == NULL) + return -ENOMEM; + + dec->norm = V4L2_STD_NTSC; + dec->brightness = 128; + dec->contrast = 71; + dec->saturation = 64; + dec->hue = 0; + i2c_set_clientdata(client, dec); + + printk(KERN_DEBUG + "wis-saa7113: initializing SAA7113 at address %d on %s\n", + client->addr, adapter->name); + + if (write_regs(client, initial_registers) < 0) { + printk(KERN_ERR + "wis-saa7113: error initializing SAA7113\n"); + kfree(dec); + return -ENODEV; + } + + return 0; +} + +static int wis_saa7113_remove(struct i2c_client *client) +{ + struct wis_saa7113 *dec = i2c_get_clientdata(client); + + i2c_set_clientdata(client, NULL); + kfree(dec); + return 0; +} + +static struct i2c_device_id wis_saa7113_id[] = { + { "wis_saa7113", 0 }, + { } +}; + +static struct i2c_driver wis_saa7113_driver = { + .driver = { + .name = "WIS SAA7113 I2C driver", + }, + .probe = wis_saa7113_probe, + .remove = wis_saa7113_remove, + .command = wis_saa7113_command, + .id_table = wis_saa7113_id, +}; + +static int __init wis_saa7113_init(void) +{ + return i2c_add_driver(&wis_saa7113_driver); +} + +static void __exit wis_saa7113_cleanup(void) +{ + i2c_del_driver(&wis_saa7113_driver); +} + +module_init(wis_saa7113_init); +module_exit(wis_saa7113_cleanup); + +MODULE_LICENSE("GPL v2"); diff --git a/linux/drivers/staging/go7007/wis-saa7115.c b/linux/drivers/staging/go7007/wis-saa7115.c new file mode 100644 index 000000000..8687ad2de --- /dev/null +++ b/linux/drivers/staging/go7007/wis-saa7115.c @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include "wis-i2c.h" + +struct wis_saa7115 { + int norm; + int brightness; + int contrast; + int saturation; + int hue; +}; + +static u8 initial_registers[] = +{ + 0x01, 0x08, + 0x02, 0xc0, + 0x03, 0x20, + 0x04, 0x80, + 0x05, 0x80, + 0x06, 0xeb, + 0x07, 0xe0, + 0x08, 0xf0, /* always toggle FID */ + 0x09, 0x40, + 0x0a, 0x80, + 0x0b, 0x40, + 0x0c, 0x40, + 0x0d, 0x00, + 0x0e, 0x03, + 0x0f, 0x2a, + 0x10, 0x0e, + 0x11, 0x00, + 0x12, 0x8d, + 0x13, 0x00, + 0x14, 0x00, + 0x15, 0x11, + 0x16, 0x01, + 0x17, 0xda, + 0x18, 0x40, + 0x19, 0x80, + 0x1a, 0x00, + 0x1b, 0x42, + 0x1c, 0xa9, + 0x30, 0x66, + 0x31, 0x90, + 0x32, 0x01, + 0x34, 0x00, + 0x35, 0x00, + 0x36, 0x20, + 0x38, 0x03, + 0x39, 0x20, + 0x3a, 0x88, + 0x40, 0x00, + 0x41, 0xff, + 0x42, 0xff, + 0x43, 0xff, + 0x44, 0xff, + 0x45, 0xff, + 0x46, 0xff, + 0x47, 0xff, + 0x48, 0xff, + 0x49, 0xff, + 0x4a, 0xff, + 0x4b, 0xff, + 0x4c, 0xff, + 0x4d, 0xff, + 0x4e, 0xff, + 0x4f, 0xff, + 0x50, 0xff, + 0x51, 0xff, + 0x52, 0xff, + 0x53, 0xff, + 0x54, 0xf4 /*0xff*/, + 0x55, 0xff, + 0x56, 0xff, + 0x57, 0xff, + 0x58, 0x40, + 0x59, 0x47, + 0x5a, 0x06 /*0x03*/, + 0x5b, 0x83, + 0x5d, 0x06, + 0x5e, 0x00, + 0x80, 0x30, /* window defined scaler operation, task A and B enabled */ + 0x81, 0x03, /* use scaler datapath generated V */ + 0x83, 0x00, + 0x84, 0x00, + 0x85, 0x00, + 0x86, 0x45, + 0x87, 0x31, + 0x88, 0xc0, + 0x90, 0x02, /* task A process top field */ + 0x91, 0x08, + 0x92, 0x09, + 0x93, 0x80, + 0x94, 0x06, + 0x95, 0x00, + 0x96, 0xc0, + 0x97, 0x02, + 0x98, 0x12, + 0x99, 0x00, + 0x9a, 0xf2, + 0x9b, 0x00, + 0x9c, 0xd0, + 0x9d, 0x02, + 0x9e, 0xf2, + 0x9f, 0x00, + 0xa0, 0x01, + 0xa1, 0x01, + 0xa2, 0x01, + 0xa4, 0x80, + 0xa5, 0x40, + 0xa6, 0x40, + 0xa8, 0x00, + 0xa9, 0x04, + 0xaa, 0x00, + 0xac, 0x00, + 0xad, 0x02, + 0xae, 0x00, + 0xb0, 0x00, + 0xb1, 0x04, + 0xb2, 0x00, + 0xb3, 0x04, + 0xb4, 0x00, + 0xb8, 0x00, + 0xbc, 0x00, + 0xc0, 0x03, /* task B process bottom field */ + 0xc1, 0x08, + 0xc2, 0x09, + 0xc3, 0x80, + 0xc4, 0x06, + 0xc5, 0x00, + 0xc6, 0xc0, + 0xc7, 0x02, + 0xc8, 0x12, + 0xc9, 0x00, + 0xca, 0xf2, + 0xcb, 0x00, + 0xcc, 0xd0, + 0xcd, 0x02, + 0xce, 0xf2, + 0xcf, 0x00, + 0xd0, 0x01, + 0xd1, 0x01, + 0xd2, 0x01, + 0xd4, 0x80, + 0xd5, 0x40, + 0xd6, 0x40, + 0xd8, 0x00, + 0xd9, 0x04, + 0xda, 0x00, + 0xdc, 0x00, + 0xdd, 0x02, + 0xde, 0x00, + 0xe0, 0x00, + 0xe1, 0x04, + 0xe2, 0x00, + 0xe3, 0x04, + 0xe4, 0x00, + 0xe8, 0x00, + 0x88, 0xf0, /* End of original static list */ + 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */ +}; + +static int write_reg(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +static int write_regs(struct i2c_client *client, u8 *regs) +{ + int i; + + for (i = 0; regs[i] != 0x00; i += 2) + if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0) + return -1; + return 0; +} + +static int wis_saa7115_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct wis_saa7115 *dec = i2c_get_clientdata(client); + + switch (cmd) { + case VIDIOC_S_INPUT: + { + int *input = arg; + + i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input); + i2c_smbus_write_byte_data(client, 0x09, + *input < 6 ? 0x40 : 0xC0); + break; + } + case DECODER_SET_RESOLUTION: + { + struct video_decoder_resolution *res = arg; + /* Course-grained scaler */ + int h_integer_scaler = res->width < 704 ? 704 / res->width : 1; + /* Fine-grained scaler to take care of remainder */ + int h_scaling_increment = (704 / h_integer_scaler) * + 1024 / res->width; + /* Fine-grained scaler only */ + int v_scaling_increment = (dec->norm & V4L2_STD_NTSC ? + 240 : 288) * 1024 / res->height; + u8 regs[] = { + 0x88, 0xc0, + 0x9c, res->width & 0xff, + 0x9d, res->width >> 8, + 0x9e, res->height & 0xff, + 0x9f, res->height >> 8, + 0xa0, h_integer_scaler, + 0xa1, 1, + 0xa2, 1, + 0xa8, h_scaling_increment & 0xff, + 0xa9, h_scaling_increment >> 8, + 0xac, (h_scaling_increment / 2) & 0xff, + 0xad, (h_scaling_increment / 2) >> 8, + 0xb0, v_scaling_increment & 0xff, + 0xb1, v_scaling_increment >> 8, + 0xb2, v_scaling_increment & 0xff, + 0xb3, v_scaling_increment >> 8, + 0xcc, res->width & 0xff, + 0xcd, res->width >> 8, + 0xce, res->height & 0xff, + 0xcf, res->height >> 8, + 0xd0, h_integer_scaler, + 0xd1, 1, + 0xd2, 1, + 0xd8, h_scaling_increment & 0xff, + 0xd9, h_scaling_increment >> 8, + 0xdc, (h_scaling_increment / 2) & 0xff, + 0xdd, (h_scaling_increment / 2) >> 8, + 0xe0, v_scaling_increment & 0xff, + 0xe1, v_scaling_increment >> 8, + 0xe2, v_scaling_increment & 0xff, + 0xe3, v_scaling_increment >> 8, + 0x88, 0xf0, + 0, 0, + }; + write_regs(client, regs); + break; + } + case VIDIOC_S_STD: + { + v4l2_std_id *input = arg; + u8 regs[] = { + 0x88, 0xc0, + 0x98, *input & V4L2_STD_NTSC ? 0x12 : 0x16, + 0x9a, *input & V4L2_STD_NTSC ? 0xf2 : 0x20, + 0x9b, *input & V4L2_STD_NTSC ? 0x00 : 0x01, + 0xc8, *input & V4L2_STD_NTSC ? 0x12 : 0x16, + 0xca, *input & V4L2_STD_NTSC ? 0xf2 : 0x20, + 0xcb, *input & V4L2_STD_NTSC ? 0x00 : 0x01, + 0x88, 0xf0, + 0x30, *input & V4L2_STD_NTSC ? 0x66 : 0x00, + 0x31, *input & V4L2_STD_NTSC ? 0x90 : 0xe0, + 0, 0, + }; + write_regs(client, regs); + dec->norm = *input; + break; + } + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 255; + ctrl->step = 1; + ctrl->default_value = 128; + ctrl->flags = 0; + break; + case V4L2_CID_CONTRAST: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 127; + ctrl->step = 1; + ctrl->default_value = 64; + ctrl->flags = 0; + break; + case V4L2_CID_SATURATION: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 127; + ctrl->step = 1; + ctrl->default_value = 64; + ctrl->flags = 0; + break; + case V4L2_CID_HUE: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Hue", sizeof(ctrl->name)); + ctrl->minimum = -128; + ctrl->maximum = 127; + ctrl->step = 1; + ctrl->default_value = 0; + ctrl->flags = 0; + break; + } + break; + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (ctrl->value > 255) + dec->brightness = 255; + else if (ctrl->value < 0) + dec->brightness = 0; + else + dec->brightness = ctrl->value; + write_reg(client, 0x0a, dec->brightness); + break; + case V4L2_CID_CONTRAST: + if (ctrl->value > 127) + dec->contrast = 127; + else if (ctrl->value < 0) + dec->contrast = 0; + else + dec->contrast = ctrl->value; + write_reg(client, 0x0b, dec->contrast); + break; + case V4L2_CID_SATURATION: + if (ctrl->value > 127) + dec->saturation = 127; + else if (ctrl->value < 0) + dec->saturation = 0; + else + dec->saturation = ctrl->value; + write_reg(client, 0x0c, dec->saturation); + break; + case V4L2_CID_HUE: + if (ctrl->value > 127) + dec->hue = 127; + else if (ctrl->value < -128) + dec->hue = -128; + else + dec->hue = ctrl->value; + write_reg(client, 0x0d, dec->hue); + break; + } + break; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = dec->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = dec->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = dec->saturation; + break; + case V4L2_CID_HUE: + ctrl->value = dec->hue; + break; + } + break; + } + default: + break; + } + return 0; +} + +static int wis_saa7115_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct wis_saa7115 *dec; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + dec = kmalloc(sizeof(struct wis_saa7115), GFP_KERNEL); + if (dec == NULL) + return -ENOMEM; + + dec->norm = V4L2_STD_NTSC; + dec->brightness = 128; + dec->contrast = 64; + dec->saturation = 64; + dec->hue = 0; + i2c_set_clientdata(client, dec); + + printk(KERN_DEBUG + "wis-saa7115: initializing SAA7115 at address %d on %s\n", + client->addr, adapter->name); + + if (write_regs(client, initial_registers) < 0) { + printk(KERN_ERR + "wis-saa7115: error initializing SAA7115\n"); + kfree(dec); + return -ENODEV; + } + + return 0; +} + +static int wis_saa7115_remove(struct i2c_client *client) +{ + struct wis_saa7115 *dec = i2c_get_clientdata(client); + + i2c_set_clientdata(client, NULL); + kfree(dec); + return 0; +} + +static struct i2c_device_id wis_saa7115_id[] = { + { "wis_saa7115", 0 }, + { } +}; + +static struct i2c_driver wis_saa7115_driver = { + .driver = { + .name = "WIS SAA7115 I2C driver", + }, + .probe = wis_saa7115_probe, + .remove = wis_saa7115_remove, + .command = wis_saa7115_command, + .id_table = wis_saa7115_id, +}; + +static int __init wis_saa7115_init(void) +{ + return i2c_add_driver(&wis_saa7115_driver); +} + +static void __exit wis_saa7115_cleanup(void) +{ + i2c_del_driver(&wis_saa7115_driver); +} + +module_init(wis_saa7115_init); +module_exit(wis_saa7115_cleanup); + +MODULE_LICENSE("GPL v2"); diff --git a/linux/drivers/staging/go7007/wis-sony-tuner.c b/linux/drivers/staging/go7007/wis-sony-tuner.c new file mode 100644 index 000000000..086896cec --- /dev/null +++ b/linux/drivers/staging/go7007/wis-sony-tuner.c @@ -0,0 +1,719 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "wis-i2c.h" + +/* #define MPX_DEBUG */ + +/* AS(IF/MPX) pin: LOW HIGH/OPEN + * IF/MPX address: 0x42/0x40 0x43/0x44 + */ +#define IF_I2C_ADDR 0x43 +#define MPX_I2C_ADDR 0x44 + +static v4l2_std_id force_band; +static char force_band_str[] = "-"; +module_param_string(force_band, force_band_str, sizeof(force_band_str), 0644); +static int force_mpx_mode = -1; +module_param(force_mpx_mode, int, 0644); + +/* Store tuner info in the same format as tuner.c, so maybe we can put the + * Sony tuner support in there. */ +struct sony_tunertype { + char *name; + unsigned char Vendor; /* unused here */ + unsigned char Type; /* unused here */ + + unsigned short thresh1; /* band switch VHF_LO <=> VHF_HI */ + unsigned short thresh2; /* band switch VHF_HI <=> UHF */ + unsigned char VHF_L; + unsigned char VHF_H; + unsigned char UHF; + unsigned char config; + unsigned short IFPCoff; +}; + +/* This array is indexed by (tuner_type - 200) */ +static struct sony_tunertype sony_tuners[] = { + { "Sony PAL+SECAM (BTF-PG472Z)", 0, 0, + 16*144.25, 16*427.25, 0x01, 0x02, 0x04, 0xc6, 623}, + { "Sony NTSC_JP (BTF-PK467Z)", 0, 0, + 16*220.25, 16*467.25, 0x01, 0x02, 0x04, 0xc6, 940}, + { "Sony NTSC (BTF-PB463Z)", 0, 0, + 16*130.25, 16*364.25, 0x01, 0x02, 0x04, 0xc6, 732}, +}; + +struct wis_sony_tuner { + int type; + v4l2_std_id std; + unsigned int freq; + int mpxmode; + u32 audmode; +}; + +/* Basically the same as default_set_tv_freq() in tuner.c */ +static int set_freq(struct i2c_client *client, int freq) +{ + struct wis_sony_tuner *t = i2c_get_clientdata(client); + char *band_name; + int n; + int band_select; + struct sony_tunertype *tun; + u8 buffer[4]; + + tun = &sony_tuners[t->type - 200]; + if (freq < tun->thresh1) { + band_name = "VHF_L"; + band_select = tun->VHF_L; + } else if (freq < tun->thresh2) { + band_name = "VHF_H"; + band_select = tun->VHF_H; + } else { + band_name = "UHF"; + band_select = tun->UHF; + } + printk(KERN_DEBUG "wis-sony-tuner: tuning to frequency %d.%04d (%s)\n", + freq / 16, (freq % 16) * 625, band_name); + n = freq + tun->IFPCoff; + + buffer[0] = n >> 8; + buffer[1] = n & 0xff; + buffer[2] = tun->config; + buffer[3] = band_select; + i2c_master_send(client, buffer, 4); + + return 0; +} + +static int mpx_write(struct i2c_client *client, int dev, int addr, int val) +{ + u8 buffer[5]; + struct i2c_msg msg; + + buffer[0] = dev; + buffer[1] = addr >> 8; + buffer[2] = addr & 0xff; + buffer[3] = val >> 8; + buffer[4] = val & 0xff; + msg.addr = MPX_I2C_ADDR; + msg.flags = 0; + msg.len = 5; + msg.buf = buffer; + i2c_transfer(client->adapter, &msg, 1); + return 0; +} + +/* + * MPX register values for the BTF-PG472Z: + * + * FM_ NICAM_ SCART_ + * MODUS SOURCE ACB PRESCAL PRESCAL PRESCAL SYSTEM VOLUME + * 10/0030 12/0008 12/0013 12/000E 12/0010 12/0000 10/0020 12/0000 + * --------------------------------------------------------------- + * Auto 1003 0020 0100 2603 5000 XXXX 0001 7500 + * + * B/G + * Mono 1003 0020 0100 2603 5000 XXXX 0003 7500 + * A2 1003 0020 0100 2601 5000 XXXX 0003 7500 + * NICAM 1003 0120 0100 2603 5000 XXXX 0008 7500 + * + * I + * Mono 1003 0020 0100 2603 7900 XXXX 000A 7500 + * NICAM 1003 0120 0100 2603 7900 XXXX 000A 7500 + * + * D/K + * Mono 1003 0020 0100 2603 5000 XXXX 0004 7500 + * A2-1 1003 0020 0100 2601 5000 XXXX 0004 7500 + * A2-2 1003 0020 0100 2601 5000 XXXX 0005 7500 + * A2-3 1003 0020 0100 2601 5000 XXXX 0007 7500 + * NICAM 1003 0120 0100 2603 5000 XXXX 000B 7500 + * + * L/L' + * Mono 0003 0200 0100 7C03 5000 2200 0009 7500 + * NICAM 0003 0120 0100 7C03 5000 XXXX 0009 7500 + * + * M + * Mono 1003 0200 0100 2B03 5000 2B00 0002 7500 + * + * For Asia, replace the 0x26XX in FM_PRESCALE with 0x14XX. + * + * Bilingual selection in A2/NICAM: + * + * High byte of SOURCE Left chan Right chan + * 0x01 MAIN SUB + * 0x03 MAIN MAIN + * 0x04 SUB SUB + * + * Force mono in NICAM by setting the high byte of SOURCE to 0x02 (L/L') or + * 0x00 (all other bands). Force mono in A2 with FMONO_A2: + * + * FMONO_A2 + * 10/0022 + * -------- + * Forced mono ON 07F0 + * Forced mono OFF 0190 + */ + +static struct { + enum { AUD_MONO, AUD_A2, AUD_NICAM, AUD_NICAM_L } audio_mode; + u16 modus; + u16 source; + u16 acb; + u16 fm_prescale; + u16 nicam_prescale; + u16 scart_prescale; + u16 system; + u16 volume; +} mpx_audio_modes[] = { + /* Auto */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603, + 0x5000, 0x0000, 0x0001, 0x7500 }, + /* B/G Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603, + 0x5000, 0x0000, 0x0003, 0x7500 }, + /* B/G A2 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601, + 0x5000, 0x0000, 0x0003, 0x7500 }, + /* B/G NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603, + 0x5000, 0x0000, 0x0008, 0x7500 }, + /* I Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603, + 0x7900, 0x0000, 0x000A, 0x7500 }, + /* I NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603, + 0x7900, 0x0000, 0x000A, 0x7500 }, + /* D/K Mono */ { AUD_MONO, 0x1003, 0x0020, 0x0100, 0x2603, + 0x5000, 0x0000, 0x0004, 0x7500 }, + /* D/K A2-1 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601, + 0x5000, 0x0000, 0x0004, 0x7500 }, + /* D/K A2-2 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601, + 0x5000, 0x0000, 0x0005, 0x7500 }, + /* D/K A2-3 */ { AUD_A2, 0x1003, 0x0020, 0x0100, 0x2601, + 0x5000, 0x0000, 0x0007, 0x7500 }, + /* D/K NICAM */ { AUD_NICAM, 0x1003, 0x0120, 0x0100, 0x2603, + 0x5000, 0x0000, 0x000B, 0x7500 }, + /* L/L' Mono */ { AUD_MONO, 0x0003, 0x0200, 0x0100, 0x7C03, + 0x5000, 0x2200, 0x0009, 0x7500 }, + /* L/L' NICAM */{ AUD_NICAM_L, 0x0003, 0x0120, 0x0100, 0x7C03, + 0x5000, 0x0000, 0x0009, 0x7500 }, +}; + +#define MPX_NUM_MODES ARRAY_SIZE(mpx_audio_modes) + +static int mpx_setup(struct i2c_client *client) +{ + struct wis_sony_tuner *t = i2c_get_clientdata(client); + u16 source = 0; + u8 buffer[3]; + struct i2c_msg msg; + + /* reset MPX */ + buffer[0] = 0x00; + buffer[1] = 0x80; + buffer[2] = 0x00; + msg.addr = MPX_I2C_ADDR; + msg.flags = 0; + msg.len = 3; + msg.buf = buffer; + i2c_transfer(client->adapter, &msg, 1); + buffer[1] = 0x00; + i2c_transfer(client->adapter, &msg, 1); + + if (mpx_audio_modes[t->mpxmode].audio_mode != AUD_MONO) { + switch (t->audmode) { + case V4L2_TUNER_MODE_MONO: + switch (mpx_audio_modes[t->mpxmode].audio_mode) { + case AUD_A2: + source = mpx_audio_modes[t->mpxmode].source; + break; + case AUD_NICAM: + source = 0x0000; + break; + case AUD_NICAM_L: + source = 0x0200; + break; + default: + break; + } + break; + case V4L2_TUNER_MODE_STEREO: + source = mpx_audio_modes[t->mpxmode].source; + break; + case V4L2_TUNER_MODE_LANG1: + source = 0x0300; + break; + case V4L2_TUNER_MODE_LANG2: + source = 0x0400; + break; + } + source |= mpx_audio_modes[t->mpxmode].source & 0x00ff; + } else + source = mpx_audio_modes[t->mpxmode].source; + + mpx_write(client, 0x10, 0x0030, mpx_audio_modes[t->mpxmode].modus); + mpx_write(client, 0x12, 0x0008, source); + mpx_write(client, 0x12, 0x0013, mpx_audio_modes[t->mpxmode].acb); + mpx_write(client, 0x12, 0x000e, + mpx_audio_modes[t->mpxmode].fm_prescale); + mpx_write(client, 0x12, 0x0010, + mpx_audio_modes[t->mpxmode].nicam_prescale); + mpx_write(client, 0x12, 0x000d, + mpx_audio_modes[t->mpxmode].scart_prescale); + mpx_write(client, 0x10, 0x0020, mpx_audio_modes[t->mpxmode].system); + mpx_write(client, 0x12, 0x0000, mpx_audio_modes[t->mpxmode].volume); + if (mpx_audio_modes[t->mpxmode].audio_mode == AUD_A2) + mpx_write(client, 0x10, 0x0022, + t->audmode == V4L2_TUNER_MODE_MONO ? 0x07f0 : 0x0190); + +#ifdef MPX_DEBUG + { + u8 buf1[3], buf2[2]; + struct i2c_msg msgs[2]; + + printk(KERN_DEBUG "wis-sony-tuner: MPX registers: %04x %04x " + "%04x %04x %04x %04x %04x %04x\n", + mpx_audio_modes[t->mpxmode].modus, + source, + mpx_audio_modes[t->mpxmode].acb, + mpx_audio_modes[t->mpxmode].fm_prescale, + mpx_audio_modes[t->mpxmode].nicam_prescale, + mpx_audio_modes[t->mpxmode].scart_prescale, + mpx_audio_modes[t->mpxmode].system, + mpx_audio_modes[t->mpxmode].volume); + buf1[0] = 0x11; + buf1[1] = 0x00; + buf1[2] = 0x7e; + msgs[0].addr = MPX_I2C_ADDR; + msgs[0].flags = 0; + msgs[0].len = 3; + msgs[0].buf = buf1; + msgs[1].addr = MPX_I2C_ADDR; + msgs[1].flags = I2C_M_RD; + msgs[1].len = 2; + msgs[1].buf = buf2; + i2c_transfer(client->adapter, msgs, 2); + printk(KERN_DEBUG "wis-sony-tuner: MPX system: %02x%02x\n", + buf2[0], buf2[1]); + buf1[0] = 0x11; + buf1[1] = 0x02; + buf1[2] = 0x00; + i2c_transfer(client->adapter, msgs, 2); + printk(KERN_DEBUG "wis-sony-tuner: MPX status: %02x%02x\n", + buf2[0], buf2[1]); + } +#endif + return 0; +} + +/* + * IF configuration values for the BTF-PG472Z: + * + * B/G: 0x94 0x70 0x49 + * I: 0x14 0x70 0x4a + * D/K: 0x14 0x70 0x4b + * L: 0x04 0x70 0x4b + * L': 0x44 0x70 0x53 + * M: 0x50 0x30 0x4c + */ + +static int set_if(struct i2c_client *client) +{ + struct wis_sony_tuner *t = i2c_get_clientdata(client); + u8 buffer[4]; + struct i2c_msg msg; + int default_mpx_mode = 0; + + /* configure IF */ + buffer[0] = 0; + if (t->std & V4L2_STD_PAL_BG) { + buffer[1] = 0x94; + buffer[2] = 0x70; + buffer[3] = 0x49; + default_mpx_mode = 1; + } else if (t->std & V4L2_STD_PAL_I) { + buffer[1] = 0x14; + buffer[2] = 0x70; + buffer[3] = 0x4a; + default_mpx_mode = 4; + } else if (t->std & V4L2_STD_PAL_DK) { + buffer[1] = 0x14; + buffer[2] = 0x70; + buffer[3] = 0x4b; + default_mpx_mode = 6; + } else if (t->std & V4L2_STD_SECAM_L) { + buffer[1] = 0x04; + buffer[2] = 0x70; + buffer[3] = 0x4b; + default_mpx_mode = 11; + } + msg.addr = IF_I2C_ADDR; + msg.flags = 0; + msg.len = 4; + msg.buf = buffer; + i2c_transfer(client->adapter, &msg, 1); + + /* Select MPX mode if not forced by the user */ + if (force_mpx_mode >= 0 && force_mpx_mode < MPX_NUM_MODES) + t->mpxmode = force_mpx_mode; + else + t->mpxmode = default_mpx_mode; + printk(KERN_DEBUG "wis-sony-tuner: setting MPX to mode %d\n", + t->mpxmode); + mpx_setup(client); + + return 0; +} + +static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + struct wis_sony_tuner *t = i2c_get_clientdata(client); + + switch (cmd) { +#if 0 +#ifdef TUNER_SET_TYPE_ADDR + case TUNER_SET_TYPE_ADDR: + { + struct tuner_setup *tun_setup = arg; + int *type = &tun_setup->type; +#else + case TUNER_SET_TYPE: + { + int *type = arg; +#endif + + if (t->type >= 0) { + if (t->type != *type) + printk(KERN_ERR "wis-sony-tuner: type already " + "set to %d, ignoring request for %d\n", + t->type, *type); + break; + } + t->type = *type; + switch (t->type) { + case TUNER_SONY_BTF_PG472Z: + switch (force_band_str[0]) { + case 'b': + case 'B': + case 'g': + case 'G': + printk(KERN_INFO "wis-sony-tuner: forcing " + "tuner to PAL-B/G bands\n"); + force_band = V4L2_STD_PAL_BG; + break; + case 'i': + case 'I': + printk(KERN_INFO "wis-sony-tuner: forcing " + "tuner to PAL-I band\n"); + force_band = V4L2_STD_PAL_I; + break; + case 'd': + case 'D': + case 'k': + case 'K': + printk(KERN_INFO "wis-sony-tuner: forcing " + "tuner to PAL-D/K bands\n"); + force_band = V4L2_STD_PAL_I; + break; + case 'l': + case 'L': + printk(KERN_INFO "wis-sony-tuner: forcing " + "tuner to SECAM-L band\n"); + force_band = V4L2_STD_SECAM_L; + break; + default: + force_band = 0; + break; + } + if (force_band) + t->std = force_band; + else + t->std = V4L2_STD_PAL_BG; + set_if(client); + break; + case TUNER_SONY_BTF_PK467Z: + t->std = V4L2_STD_NTSC_M_JP; + break; + case TUNER_SONY_BTF_PB463Z: + t->std = V4L2_STD_NTSC_M; + break; + default: + printk(KERN_ERR "wis-sony-tuner: tuner type %d is not " + "supported by this module\n", *type); + break; + } + if (type >= 0) + printk(KERN_INFO + "wis-sony-tuner: type set to %d (%s)\n", + t->type, sony_tuners[t->type - 200].name); + break; + } +#endif + case VIDIOC_G_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + f->frequency = t->freq; + break; + } + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + t->freq = f->frequency; + set_freq(client, t->freq); + break; + } + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *std = arg; + + switch (t->type) { + case TUNER_SONY_BTF_PG472Z: + switch (std->index) { + case 0: + v4l2_video_std_construct(std, + V4L2_STD_PAL_BG, "PAL-B/G"); + break; + case 1: + v4l2_video_std_construct(std, + V4L2_STD_PAL_I, "PAL-I"); + break; + case 2: + v4l2_video_std_construct(std, + V4L2_STD_PAL_DK, "PAL-D/K"); + break; + case 3: + v4l2_video_std_construct(std, + V4L2_STD_SECAM_L, "SECAM-L"); + break; + default: + std->id = 0; /* hack to indicate EINVAL */ + break; + } + break; + case TUNER_SONY_BTF_PK467Z: + if (std->index != 0) { + std->id = 0; /* hack to indicate EINVAL */ + break; + } + v4l2_video_std_construct(std, + V4L2_STD_NTSC_M_JP, "NTSC-J"); + break; + case TUNER_SONY_BTF_PB463Z: + if (std->index != 0) { + std->id = 0; /* hack to indicate EINVAL */ + break; + } + v4l2_video_std_construct(std, V4L2_STD_NTSC_M, "NTSC"); + break; + } + break; + } + case VIDIOC_G_STD: + { + v4l2_std_id *std = arg; + + *std = t->std; + break; + } + case VIDIOC_S_STD: + { + v4l2_std_id *std = arg; + v4l2_std_id old = t->std; + + switch (t->type) { + case TUNER_SONY_BTF_PG472Z: + if (force_band && (*std & force_band) != *std && + *std != V4L2_STD_PAL && + *std != V4L2_STD_SECAM) { + printk(KERN_DEBUG "wis-sony-tuner: ignoring " + "requested TV standard in " + "favor of force_band value\n"); + t->std = force_band; + } else if (*std & V4L2_STD_PAL_BG) { /* default */ + t->std = V4L2_STD_PAL_BG; + } else if (*std & V4L2_STD_PAL_I) { + t->std = V4L2_STD_PAL_I; + } else if (*std & V4L2_STD_PAL_DK) { + t->std = V4L2_STD_PAL_DK; + } else if (*std & V4L2_STD_SECAM_L) { + t->std = V4L2_STD_SECAM_L; + } else { + printk(KERN_ERR "wis-sony-tuner: TV standard " + "not supported\n"); + *std = 0; /* hack to indicate EINVAL */ + break; + } + if (old != t->std) + set_if(client); + break; + case TUNER_SONY_BTF_PK467Z: + if (!(*std & V4L2_STD_NTSC_M_JP)) { + printk(KERN_ERR "wis-sony-tuner: TV standard " + "not supported\n"); + *std = 0; /* hack to indicate EINVAL */ + } + break; + case TUNER_SONY_BTF_PB463Z: + if (!(*std & V4L2_STD_NTSC_M)) { + printk(KERN_ERR "wis-sony-tuner: TV standard " + "not supported\n"); + *std = 0; /* hack to indicate EINVAL */ + } + break; + } + break; + } + case VIDIOC_QUERYSTD: + { + v4l2_std_id *std = arg; + + switch (t->type) { + case TUNER_SONY_BTF_PG472Z: + if (force_band) + *std = force_band; + else + *std = V4L2_STD_PAL_BG | V4L2_STD_PAL_I | + V4L2_STD_PAL_DK | V4L2_STD_SECAM_L; + break; + case TUNER_SONY_BTF_PK467Z: + *std = V4L2_STD_NTSC_M_JP; + break; + case TUNER_SONY_BTF_PB463Z: + *std = V4L2_STD_NTSC_M; + break; + } + break; + } + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *tun = arg; + + memset(tun, 0, sizeof(*tun)); + strcpy(tun->name, "Television"); + tun->type = V4L2_TUNER_ANALOG_TV; + tun->rangelow = 0UL; /* does anything use these? */ + tun->rangehigh = 0xffffffffUL; + switch (t->type) { + case TUNER_SONY_BTF_PG472Z: + tun->capability = V4L2_TUNER_CAP_NORM | + V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | + V4L2_TUNER_CAP_LANG2; + tun->rxsubchans = V4L2_TUNER_SUB_MONO | + V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_LANG1 | + V4L2_TUNER_SUB_LANG2; + break; + case TUNER_SONY_BTF_PK467Z: + case TUNER_SONY_BTF_PB463Z: + tun->capability = V4L2_TUNER_CAP_STEREO; + tun->rxsubchans = V4L2_TUNER_SUB_MONO | + V4L2_TUNER_SUB_STEREO; + break; + } + tun->audmode = t->audmode; + return 0; + } + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *tun = arg; + + switch (t->type) { + case TUNER_SONY_BTF_PG472Z: + if (tun->audmode != t->audmode) { + t->audmode = tun->audmode; + mpx_setup(client); + } + break; + case TUNER_SONY_BTF_PK467Z: + case TUNER_SONY_BTF_PB463Z: + break; + } + return 0; + } + default: + break; + } + return 0; +} + +static int wis_sony_tuner_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct wis_sony_tuner *t; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) + return -ENODEV; + + t = kmalloc(sizeof(struct wis_sony_tuner), GFP_KERNEL); + if (t == NULL) + return -ENOMEM; + + t->type = -1; + t->freq = 0; + t->mpxmode = 0; + t->audmode = V4L2_TUNER_MODE_STEREO; + i2c_set_clientdata(client, t); + + printk(KERN_DEBUG + "wis-sony-tuner: initializing tuner at address %d on %s\n", + client->addr, adapter->name); + + return 0; +} + +static int wis_sony_tuner_remove(struct i2c_client *client) +{ + struct wis_sony_tuner *t = i2c_get_clientdata(client); + + i2c_set_clientdata(client, NULL); + kfree(t); + return 0; +} + +static struct i2c_device_id wis_sony_tuner_id[] = { + { "wis_sony_tuner", 0 }, + { } +}; + +static struct i2c_driver wis_sony_tuner_driver = { + .driver = { + .name = "WIS Sony TV Tuner I2C driver", + }, + .probe = wis_sony_tuner_probe, + .remove = wis_sony_tuner_remove, + .command = tuner_command, + .id_table = wis_sony_tuner_id, +}; + +static int __init wis_sony_tuner_init(void) +{ + return i2c_add_driver(&wis_sony_tuner_driver); +} + +static void __exit wis_sony_tuner_cleanup(void) +{ + i2c_del_driver(&wis_sony_tuner_driver); +} + +module_init(wis_sony_tuner_init); +module_exit(wis_sony_tuner_cleanup); + +MODULE_LICENSE("GPL v2"); diff --git a/linux/drivers/staging/go7007/wis-tw2804.c b/linux/drivers/staging/go7007/wis-tw2804.c new file mode 100644 index 000000000..e15794a2a --- /dev/null +++ b/linux/drivers/staging/go7007/wis-tw2804.c @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include "wis-i2c.h" + +struct wis_tw2804 { + int channel; + int norm; + int brightness; + int contrast; + int saturation; + int hue; +}; + +static u8 global_registers[] = +{ + 0x39, 0x00, + 0x3a, 0xff, + 0x3b, 0x84, + 0x3c, 0x80, + 0x3d, 0x80, + 0x3e, 0x82, + 0x3f, 0x82, + 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ +}; + +static u8 channel_registers[] = +{ + 0x01, 0xc4, + 0x02, 0xa5, + 0x03, 0x20, + 0x04, 0xd0, + 0x05, 0x20, + 0x06, 0xd0, + 0x07, 0x88, + 0x08, 0x20, + 0x09, 0x07, + 0x0a, 0xf0, + 0x0b, 0x07, + 0x0c, 0xf0, + 0x0d, 0x40, + 0x0e, 0xd2, + 0x0f, 0x80, + 0x10, 0x80, + 0x11, 0x80, + 0x12, 0x80, + 0x13, 0x1f, + 0x14, 0x00, + 0x15, 0x00, + 0x16, 0x00, + 0x17, 0x00, + 0x18, 0xff, + 0x19, 0xff, + 0x1a, 0xff, + 0x1b, 0xff, + 0x1c, 0xff, + 0x1d, 0xff, + 0x1e, 0xff, + 0x1f, 0xff, + 0x20, 0x07, + 0x21, 0x07, + 0x22, 0x00, + 0x23, 0x91, + 0x24, 0x51, + 0x25, 0x03, + 0x26, 0x00, + 0x27, 0x00, + 0x28, 0x00, + 0x29, 0x00, + 0x2a, 0x00, + 0x2b, 0x00, + 0x2c, 0x00, + 0x2d, 0x00, + 0x2e, 0x00, + 0x2f, 0x00, + 0x30, 0x00, + 0x31, 0x00, + 0x32, 0x00, + 0x33, 0x00, + 0x34, 0x00, + 0x35, 0x00, + 0x36, 0x00, + 0x37, 0x00, + 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ +}; + +static int write_reg(struct i2c_client *client, u8 reg, u8 value, int channel) +{ + return i2c_smbus_write_byte_data(client, reg | (channel << 6), value); +} + +static int write_regs(struct i2c_client *client, u8 *regs, int channel) +{ + int i; + + for (i = 0; regs[i] != 0xff; i += 2) + if (i2c_smbus_write_byte_data(client, + regs[i] | (channel << 6), regs[i + 1]) < 0) + return -1; + return 0; +} + +static int wis_tw2804_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct wis_tw2804 *dec = i2c_get_clientdata(client); + + if (cmd == DECODER_SET_CHANNEL) { + int *input = arg; + + if (*input < 0 || *input > 3) { + printk(KERN_ERR "wis-tw2804: channel %d is not " + "between 0 and 3!\n", *input); + return 0; + } + dec->channel = *input; + printk(KERN_DEBUG "wis-tw2804: initializing TW2804 " + "channel %d\n", dec->channel); + if (dec->channel == 0 && + write_regs(client, global_registers, 0) < 0) { + printk(KERN_ERR "wis-tw2804: error initializing " + "TW2804 global registers\n"); + return 0; + } + if (write_regs(client, channel_registers, dec->channel) < 0) { + printk(KERN_ERR "wis-tw2804: error initializing " + "TW2804 channel %d\n", dec->channel); + return 0; + } + return 0; + } + + if (dec->channel < 0) { + printk(KERN_DEBUG "wis-tw2804: ignoring command %08x until " + "channel number is set\n", cmd); + return 0; + } + + switch (cmd) { + case VIDIOC_S_STD: + { + v4l2_std_id *input = arg; + u8 regs[] = { + 0x01, *input & V4L2_STD_NTSC ? 0xc4 : 0x84, + 0x09, *input & V4L2_STD_NTSC ? 0x07 : 0x04, + 0x0a, *input & V4L2_STD_NTSC ? 0xf0 : 0x20, + 0x0b, *input & V4L2_STD_NTSC ? 0x07 : 0x04, + 0x0c, *input & V4L2_STD_NTSC ? 0xf0 : 0x20, + 0x0d, *input & V4L2_STD_NTSC ? 0x40 : 0x4a, + 0x16, *input & V4L2_STD_NTSC ? 0x00 : 0x40, + 0x17, *input & V4L2_STD_NTSC ? 0x00 : 0x40, + 0x20, *input & V4L2_STD_NTSC ? 0x07 : 0x0f, + 0x21, *input & V4L2_STD_NTSC ? 0x07 : 0x0f, + 0xff, 0xff, + }; + write_regs(client, regs, dec->channel); + dec->norm = *input; + break; + } + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 255; + ctrl->step = 1; + ctrl->default_value = 128; + ctrl->flags = 0; + break; + case V4L2_CID_CONTRAST: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 255; + ctrl->step = 1; + ctrl->default_value = 128; + ctrl->flags = 0; + break; + case V4L2_CID_SATURATION: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 255; + ctrl->step = 1; + ctrl->default_value = 128; + ctrl->flags = 0; + break; + case V4L2_CID_HUE: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Hue", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 255; + ctrl->step = 1; + ctrl->default_value = 128; + ctrl->flags = 0; + break; + } + break; + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (ctrl->value > 255) + dec->brightness = 255; + else if (ctrl->value < 0) + dec->brightness = 0; + else + dec->brightness = ctrl->value; + write_reg(client, 0x12, dec->brightness, dec->channel); + break; + case V4L2_CID_CONTRAST: + if (ctrl->value > 255) + dec->contrast = 255; + else if (ctrl->value < 0) + dec->contrast = 0; + else + dec->contrast = ctrl->value; + write_reg(client, 0x11, dec->contrast, dec->channel); + break; + case V4L2_CID_SATURATION: + if (ctrl->value > 255) + dec->saturation = 255; + else if (ctrl->value < 0) + dec->saturation = 0; + else + dec->saturation = ctrl->value; + write_reg(client, 0x10, dec->saturation, dec->channel); + break; + case V4L2_CID_HUE: + if (ctrl->value > 255) + dec->hue = 255; + else if (ctrl->value < 0) + dec->hue = 0; + else + dec->hue = ctrl->value; + write_reg(client, 0x0f, dec->hue, dec->channel); + break; + } + break; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = dec->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = dec->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = dec->saturation; + break; + case V4L2_CID_HUE: + ctrl->value = dec->hue; + break; + } + break; + } + default: + break; + } + return 0; +} + +static int wis_tw2804_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct wis_tw2804 *dec; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + dec = kmalloc(sizeof(struct wis_tw2804), GFP_KERNEL); + if (dec == NULL) + return -ENOMEM; + + dec->channel = -1; + dec->norm = V4L2_STD_NTSC; + dec->brightness = 128; + dec->contrast = 128; + dec->saturation = 128; + dec->hue = 128; + i2c_set_clientdata(client, dec); + + printk(KERN_DEBUG "wis-tw2804: creating TW2804 at address %d on %s\n", + client->addr, adapter->name); + + return 0; +} + +static int wis_tw2804_remove(struct i2c_client *client) +{ + struct wis_tw2804 *dec = i2c_get_clientdata(client); + + i2c_set_clientdata(client, NULL); + kfree(dec); + return 0; +} + +static struct i2c_device_id wis_tw2804_id[] = { + { "wis_tw2804", 0 }, + { } +}; + +static struct i2c_driver wis_tw2804_driver = { + .driver = { + .name = "WIS TW2804 I2C driver", + }, + .probe = wis_tw2804_probe, + .remove = wis_tw2804_remove, + .command = wis_tw2804_command, + .id_table = wis_tw2804_id, +}; + +static int __init wis_tw2804_init(void) +{ + return i2c_add_driver(&wis_tw2804_driver); +} + +static void __exit wis_tw2804_cleanup(void) +{ + i2c_del_driver(&wis_tw2804_driver); +} + +module_init(wis_tw2804_init); +module_exit(wis_tw2804_cleanup); + +MODULE_LICENSE("GPL v2"); diff --git a/linux/drivers/staging/go7007/wis-tw9903.c b/linux/drivers/staging/go7007/wis-tw9903.c new file mode 100644 index 000000000..6c3427bb6 --- /dev/null +++ b/linux/drivers/staging/go7007/wis-tw9903.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include "wis-i2c.h" + +struct wis_tw9903 { + int norm; + int brightness; + int contrast; + int hue; +}; + +static u8 initial_registers[] = +{ + 0x02, 0x44, /* input 1, composite */ + 0x03, 0x92, /* correct digital format */ + 0x04, 0x00, + 0x05, 0x80, /* or 0x00 for PAL */ + 0x06, 0x40, /* second internal current reference */ + 0x07, 0x02, /* window */ + 0x08, 0x14, /* window */ + 0x09, 0xf0, /* window */ + 0x0a, 0x81, /* window */ + 0x0b, 0xd0, /* window */ + 0x0c, 0x8c, + 0x0d, 0x00, /* scaling */ + 0x0e, 0x11, /* scaling */ + 0x0f, 0x00, /* scaling */ + 0x10, 0x00, /* brightness */ + 0x11, 0x60, /* contrast */ + 0x12, 0x01, /* sharpness */ + 0x13, 0x7f, /* U gain */ + 0x14, 0x5a, /* V gain */ + 0x15, 0x00, /* hue */ + 0x16, 0xc3, /* sharpness */ + 0x18, 0x00, + 0x19, 0x58, /* vbi */ + 0x1a, 0x80, + 0x1c, 0x0f, /* video norm */ + 0x1d, 0x7f, /* video norm */ + 0x20, 0xa0, /* clamping gain (working 0x50) */ + 0x21, 0x22, + 0x22, 0xf0, + 0x23, 0xfe, + 0x24, 0x3c, + 0x25, 0x38, + 0x26, 0x44, + 0x27, 0x20, + 0x28, 0x00, + 0x29, 0x15, + 0x2a, 0xa0, + 0x2b, 0x44, + 0x2c, 0x37, + 0x2d, 0x00, + 0x2e, 0xa5, /* burst PLL control (working: a9) */ + 0x2f, 0xe0, /* 0xea is blue test frame -- 0xe0 for normal */ + 0x31, 0x00, + 0x33, 0x22, + 0x34, 0x11, + 0x35, 0x35, + 0x3b, 0x05, + 0x06, 0xc0, /* reset device */ + 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */ +}; + +static int write_reg(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +static int write_regs(struct i2c_client *client, u8 *regs) +{ + int i; + + for (i = 0; regs[i] != 0x00; i += 2) + if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0) + return -1; + return 0; +} + +static int wis_tw9903_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct wis_tw9903 *dec = i2c_get_clientdata(client); + + switch (cmd) { + case VIDIOC_S_INPUT: + { + int *input = arg; + + i2c_smbus_write_byte_data(client, 0x02, 0x40 | (*input << 1)); + break; + } +#if 0 /* The scaler on this thing seems to be horribly broken */ + case DECODER_SET_RESOLUTION: + { + struct video_decoder_resolution *res = arg; + /*int hscale = 256 * 720 / res->width;*/ + int hscale = 256 * 720 / (res->width - (res->width > 704 ? 0 : 8)); + int vscale = 256 * (dec->norm & V4L2_STD_NTSC ? 240 : 288) + / res->height; + u8 regs[] = { + 0x0d, vscale & 0xff, + 0x0f, hscale & 0xff, + 0x0e, ((vscale & 0xf00) >> 4) | ((hscale & 0xf00) >> 8), + 0x06, 0xc0, /* reset device */ + 0, 0, + }; + printk(KERN_DEBUG "vscale is %04x, hscale is %04x\n", + vscale, hscale); + /*write_regs(client, regs);*/ + break; + } +#endif + case VIDIOC_S_STD: + { + v4l2_std_id *input = arg; + u8 regs[] = { + 0x05, *input & V4L2_STD_NTSC ? 0x80 : 0x00, + 0x07, *input & V4L2_STD_NTSC ? 0x02 : 0x12, + 0x08, *input & V4L2_STD_NTSC ? 0x14 : 0x18, + 0x09, *input & V4L2_STD_NTSC ? 0xf0 : 0x20, + 0, 0, + }; + write_regs(client, regs); + dec->norm = *input; + break; + } + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)); + ctrl->minimum = -128; + ctrl->maximum = 127; + ctrl->step = 1; + ctrl->default_value = 0x00; + ctrl->flags = 0; + break; + case V4L2_CID_CONTRAST: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 255; + ctrl->step = 1; + ctrl->default_value = 0x60; + ctrl->flags = 0; + break; +#if 0 + /* I don't understand how the Chroma Gain registers work... */ + case V4L2_CID_SATURATION: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)); + ctrl->minimum = 0; + ctrl->maximum = 127; + ctrl->step = 1; + ctrl->default_value = 64; + ctrl->flags = 0; + break; +#endif + case V4L2_CID_HUE: + ctrl->type = V4L2_CTRL_TYPE_INTEGER; + strncpy(ctrl->name, "Hue", sizeof(ctrl->name)); + ctrl->minimum = -128; + ctrl->maximum = 127; + ctrl->step = 1; + ctrl->default_value = 0; + ctrl->flags = 0; + break; + } + break; + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (ctrl->value > 127) + dec->brightness = 127; + else if (ctrl->value < -128) + dec->brightness = -128; + else + dec->brightness = ctrl->value; + write_reg(client, 0x10, dec->brightness); + break; + case V4L2_CID_CONTRAST: + if (ctrl->value > 255) + dec->contrast = 255; + else if (ctrl->value < 0) + dec->contrast = 0; + else + dec->contrast = ctrl->value; + write_reg(client, 0x11, dec->contrast); + break; +#if 0 + case V4L2_CID_SATURATION: + if (ctrl->value > 127) + dec->saturation = 127; + else if (ctrl->value < 0) + dec->saturation = 0; + else + dec->saturation = ctrl->value; + /*write_reg(client, 0x0c, dec->saturation);*/ + break; +#endif + case V4L2_CID_HUE: + if (ctrl->value > 127) + dec->hue = 127; + else if (ctrl->value < -128) + dec->hue = -128; + else + dec->hue = ctrl->value; + write_reg(client, 0x15, dec->hue); + break; + } + break; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl = arg; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = dec->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = dec->contrast; + break; +#if 0 + case V4L2_CID_SATURATION: + ctrl->value = dec->saturation; + break; +#endif + case V4L2_CID_HUE: + ctrl->value = dec->hue; + break; + } + break; + } + default: + break; + } + return 0; +} + +static int wis_tw9903_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + struct wis_tw9903 *dec; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + dec = kmalloc(sizeof(struct wis_tw9903), GFP_KERNEL); + if (dec == NULL) + return -ENOMEM; + + dec->norm = V4L2_STD_NTSC; + dec->brightness = 0; + dec->contrast = 0x60; + dec->hue = 0; + i2c_set_clientdata(client, dec); + + printk(KERN_DEBUG + "wis-tw9903: initializing TW9903 at address %d on %s\n", + client->addr, adapter->name); + + if (write_regs(client, initial_registers) < 0) { + printk(KERN_ERR "wis-tw9903: error initializing TW9903\n"); + kfree(dec); + return -ENODEV; + } + + return 0; +} + +static int wis_tw9903_remove(struct i2c_client *client) +{ + struct wis_tw9903 *dec = i2c_get_clientdata(client); + + i2c_set_clientdata(client, NULL); + kfree(dec); + return 0; +} + +static struct i2c_device_id wis_tw9903_id[] = { + { "wis_tw9903", 0 }, + { } +}; + +static struct i2c_driver wis_tw9903_driver = { + .driver = { + .name = "WIS TW9903 I2C driver", + }, + .probe = wis_tw9903_probe, + .remove = wis_tw9903_remove, + .command = wis_tw9903_command, + .id_table = wis_tw9903_id, +}; + +static int __init wis_tw9903_init(void) +{ + return i2c_add_driver(&wis_tw9903_driver); +} + +static void __exit wis_tw9903_cleanup(void) +{ + i2c_del_driver(&wis_tw9903_driver); +} + +module_init(wis_tw9903_init); +module_exit(wis_tw9903_cleanup); + +MODULE_LICENSE("GPL v2"); diff --git a/linux/drivers/staging/go7007/wis-uda1342.c b/linux/drivers/staging/go7007/wis-uda1342.c new file mode 100644 index 000000000..739c7ae89 --- /dev/null +++ b/linux/drivers/staging/go7007/wis-uda1342.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2005-2006 Micronas USA Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "wis-i2c.h" + +static int write_reg(struct i2c_client *client, int reg, int value) +{ + /* UDA1342 wants MSB first, but SMBus sends LSB first */ + i2c_smbus_write_word_data(client, reg, swab16(value)); + return 0; +} + +static int wis_uda1342_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + switch (cmd) { + case VIDIOC_S_AUDIO: + { + int *inp = arg; + + switch (*inp) { + case TVAUDIO_INPUT_TUNER: + write_reg(client, 0x00, 0x1441); /* select input 2 */ + break; + case TVAUDIO_INPUT_EXTERN: + write_reg(client, 0x00, 0x1241); /* select input 1 */ + break; + default: + printk(KERN_ERR "wis-uda1342: input %d not supported\n", + *inp); + break; + } + break; + } + default: + break; + } + return 0; +} + +static int wis_uda1342_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + printk(KERN_DEBUG + "wis-uda1342: initializing UDA1342 at address %d on %s\n", + client->addr, adapter->name); + + write_reg(client, 0x00, 0x8000); /* reset registers */ + write_reg(client, 0x00, 0x1241); /* select input 1 */ + + return 0; +} + +static int wis_uda1342_remove(struct i2c_client *client) +{ + return 0; +} + +static struct i2c_device_id wis_uda1342_id[] = { + { "wis_uda1342", 0 }, + { } +}; + +static struct i2c_driver wis_uda1342_driver = { + .driver = { + .name = "WIS UDA1342 I2C driver", + }, + .probe = wis_uda1342_probe, + .remove = wis_uda1342_remove, + .command = wis_uda1342_command, + .id_table = wis_uda1342_id, +}; + +static int __init wis_uda1342_init(void) +{ + return i2c_add_driver(&wis_uda1342_driver); +} + +static void __exit wis_uda1342_cleanup(void) +{ + i2c_del_driver(&wis_uda1342_driver); +} + +module_init(wis_uda1342_init); +module_exit(wis_uda1342_cleanup); + +MODULE_LICENSE("GPL v2"); diff --git a/v4l/Kconfig.staging b/v4l/Kconfig.staging new file mode 100644 index 000000000..b8fbc9dcc --- /dev/null +++ b/v4l/Kconfig.staging @@ -0,0 +1,66 @@ +menuconfig STAGING + bool "Staging drivers" + default n + ---help--- + This option allows you to select a number of drivers that are + not of the "normal" Linux kernel quality level. These drivers + are placed here in order to get a wider audience for use of + them. Please note that these drivers are under heavy + development, may or may not work, and may contain userspace + interfaces that most likely will be changed in the near + future. + + Using any of these drivers will taint your kernel which might + affect support options from both the community, and various + commercial support orginizations. + + If you wish to work on these drivers, to help improve them, or + to report problems you have with them, please see the + driver_name.README file in the drivers/staging/ directory to + see what needs to be worked on, and who to contact. + + If in doubt, say N here. + + +if STAGING +menu "Media devices in staging" + +config VIDEO_GO7007 + tristate "Go 7007 support" + depends on VIDEO_DEV && PCI && I2C && INPUT + depends on SND + select VIDEOBUF_DMA_SG + select VIDEO_IR + select VIDEO_TUNER + select VIDEO_TVEEPROM + select SND_PCM + select CRC32 + default N + ---help--- + This is a video4linux driver for some wierd device... + + To compile this driver as a module, choose M here: the + module will be called go7007. + +config VIDEO_GO7007_USB + tristate "Go 7007 USB support" + depends on VIDEO_GO7007 && USB + default N + ---help--- + This is a video4linux driver for some wierd device... + + To compile this driver as a module, choose M here: the + module will be called go7007-usb. + +config VIDEO_GO7007_USB_S2250_BOARD + tristate "Sensoray 2250/2251 support" + depends on VIDEO_GO7007_USB && DVB_USB + default N + ---help--- + This is a video4linux driver for the Sensoray 2250/2251 device + + To compile this driver as a module, choose M here: the + module will be called s2250. +endmenu + +endif # STAGING diff --git a/v4l/Makefile b/v4l/Makefile index 29b9675ae..76d0bdd80 100644 --- a/v4l/Makefile +++ b/v4l/Makefile @@ -106,6 +106,7 @@ endif ifeq ($(makefile-media),1) -include $(obj)/Makefile.media -include $(obj)/Makefile.sound +-include $(obj)/Makefile.staging endif -include $(obj)/.kconfig.dep @@ -278,6 +279,7 @@ links:: @echo creating symbolic links... @find ../linux/drivers/media -name '*.[ch]' -type f -print0 | xargs -0n 255 ln -sf --target-directory=. @find ../linux/sound -name '*.[ch]' -type f -print0 | xargs -0n 255 ln -sf --target-directory=. + @find ../linux/drivers/staging -name '*.[ch]' -type f -print0 | xargs -0n 255 ln -sf --target-directory=. # This link is so code with #include "oss/*.h" will find its header files oss: diff --git a/v4l/Makefile.staging b/v4l/Makefile.staging new file mode 100644 index 000000000..b8dca80f0 --- /dev/null +++ b/v4l/Makefile.staging @@ -0,0 +1,39 @@ +# From drivers/staging/go7007/Makefile + +#obj-m += go7007.o go7007-usb.o snd-go7007.o wis-saa7115.o wis-tw9903.o \ + wis-uda1342.o wis-sony-tuner.o wis-saa7113.o wis-ov7640.o \ + wis-tw2804.o + + +obj-$(CONFIG_VIDEO_GO7007) += go7007.o +obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o +obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o + +go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ + snd-go7007.o wis-saa7113.o + +s2250-objs += s2250-board.o s2250-loader.o + +# Uncompile when the saa7134 patches get into upstream +#ifneq ($(CONFIG_VIDEO_SAA7134),) +#obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o +#EXTRA_CFLAGS += -Idrivers/media/video/saa7134 +#endif + +ifneq ($(CONFIG_VIDEO_GO7007_USB_S2250_BOARD),) +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb +endif + +EXTRA_CFLAGS += -Idrivers/staging/saa7134 +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core + +KDIRA := /lib/modules/$(KERNELRELEASE)/kernel + +staging-install install-staging:: + @dir="drivers/staging/go7007"; \ + files='go7007.ko go7007-usb.ko s2250.ko'; \ + echo -e "\nInstalling $(KDIRA)/$$dir files:"; \ + install -d $(KDIRA)/$$dir; \ + for i in $$files;do if [ -e $$i ]; then echo -n "$$i "; \ + install -m 644 -c $$i $(KDIRA)/$$dir; fi; done; echo; diff --git a/v4l/scripts/make_kconfig.pl b/v4l/scripts/make_kconfig.pl index 4690f6ab4..fd6dbd739 100755 --- a/v4l/scripts/make_kconfig.pl +++ b/v4l/scripts/make_kconfig.pl @@ -585,6 +585,7 @@ EOF open_kconfig('../linux', '../linux/drivers/media/Kconfig'); open_kconfig('.', './Kconfig.sound'); +open_kconfig('.', './Kconfig.staging'); close OUT; # These options should default to off -- cgit v1.2.3 From f9658df799aea9eb278d36bb02246ef4443037d6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 10 Sep 2009 20:03:31 +0200 Subject: go7007: semaphore -> mutex conversion From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/staging/go7007/go7007-driver.c | 12 ++--- linux/drivers/staging/go7007/go7007-i2c.c | 12 ++--- linux/drivers/staging/go7007/go7007-priv.h | 6 +-- linux/drivers/staging/go7007/go7007-usb.c | 10 ++--- linux/drivers/staging/go7007/go7007-v4l2.c | 66 ++++++++++++++-------------- linux/drivers/staging/go7007/go7007.txt | 4 +- linux/drivers/staging/go7007/s2250-board.c | 18 ++++---- linux/drivers/staging/go7007/s2250-loader.c | 8 ++-- linux/drivers/staging/go7007/snd-go7007.c | 2 +- 9 files changed, 68 insertions(+), 70 deletions(-) diff --git a/linux/drivers/staging/go7007/go7007-driver.c b/linux/drivers/staging/go7007/go7007-driver.c index 77b1e769a..359a34f67 100644 --- a/linux/drivers/staging/go7007/go7007-driver.c +++ b/linux/drivers/staging/go7007/go7007-driver.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -140,9 +140,9 @@ int go7007_boot_encoder(struct go7007 *go, int init_i2c) { int ret; - down(&go->hw_lock); + mutex_lock(&go->hw_lock); ret = go7007_load_encoder(go); - up(&go->hw_lock); + mutex_unlock(&go->hw_lock); if (ret < 0) return -1; if (!init_i2c) @@ -257,9 +257,9 @@ int go7007_register_encoder(struct go7007 *go) printk(KERN_INFO "go7007: registering new %s\n", go->name); - down(&go->hw_lock); + mutex_lock(&go->hw_lock); ret = go7007_init_encoder(go); - up(&go->hw_lock); + mutex_unlock(&go->hw_lock); if (ret < 0) return -1; @@ -604,7 +604,7 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev) go->tuner_type = -1; go->channel_number = 0; go->name[0] = 0; - init_MUTEX(&go->hw_lock); + mutex_init(&go->hw_lock); init_waitqueue_head(&go->frame_waitq); spin_lock_init(&go->spinlock); go->video_dev = NULL; diff --git a/linux/drivers/staging/go7007/go7007-i2c.c b/linux/drivers/staging/go7007/go7007-i2c.c index c82867fdd..b8cfa1a6e 100644 --- a/linux/drivers/staging/go7007/go7007-i2c.c +++ b/linux/drivers/staging/go7007/go7007-i2c.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -48,7 +48,7 @@ /* There is only one I2C port on the TW2804 that feeds all four GO7007 VIPs * on the Adlink PCI-MPG24, so access is shared between all of them. */ -static DECLARE_MUTEX(adlink_mpg24_i2c_lock); +static DEFINE_MUTEX(adlink_mpg24_i2c_lock); static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read, u16 command, int flags, u8 *data) @@ -69,11 +69,11 @@ static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read, *data, command, addr); #endif - down(&go->hw_lock); + mutex_lock(&go->hw_lock); if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { /* Bridge the I2C port on this GO7007 to the shared bus */ - down(&adlink_mpg24_i2c_lock); + mutex_lock(&adlink_mpg24_i2c_lock); go7007_write_addr(go, 0x3c82, 0x0020); } @@ -134,9 +134,9 @@ i2c_done: if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { /* Isolate the I2C port on this GO7007 from the shared bus */ go7007_write_addr(go, 0x3c82, 0x0000); - up(&adlink_mpg24_i2c_lock); + mutex_unlock(&adlink_mpg24_i2c_lock); } - up(&go->hw_lock); + mutex_unlock(&go->hw_lock); return ret; } diff --git a/linux/drivers/staging/go7007/go7007-priv.h b/linux/drivers/staging/go7007/go7007-priv.h index 178d18119..ce9307e3e 100644 --- a/linux/drivers/staging/go7007/go7007-priv.h +++ b/linux/drivers/staging/go7007/go7007-priv.h @@ -132,7 +132,7 @@ struct go7007_buffer { struct go7007_file { struct go7007 *go; - struct semaphore lock; + struct mutex lock; int buf_count; struct go7007_buffer *bufs; }; @@ -170,7 +170,7 @@ struct go7007 { int ref_count; enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status; spinlock_t spinlock; - struct semaphore hw_lock; + struct mutex hw_lock; int streaming; int in_use; int audio_enabled; @@ -240,7 +240,7 @@ struct go7007 { unsigned short interrupt_data; }; -/* All of these must be called with the hpi_lock semaphore held! */ +/* All of these must be called with the hpi_lock mutex held! */ #define go7007_interface_reset(go) \ ((go)->hpi_ops->interface_reset(go)) #define go7007_write_interrupt(go, x, y) \ diff --git a/linux/drivers/staging/go7007/go7007-usb.c b/linux/drivers/staging/go7007/go7007-usb.c index aa4a9e0b9..ff4fb36d9 100644 --- a/linux/drivers/staging/go7007/go7007-usb.c +++ b/linux/drivers/staging/go7007/go7007-usb.c @@ -62,7 +62,7 @@ struct go7007_usb_board { struct go7007_usb { struct go7007_usb_board *board; - struct semaphore i2c_lock; + struct mutex i2c_lock; struct usb_device *usbdev; struct urb *video_urbs[8]; struct urb *audio_urbs[8]; @@ -734,7 +734,7 @@ static int go7007_usb_read_interrupt(struct go7007 *go) static void go7007_usb_read_video_pipe_complete(struct urb *urb) { struct go7007 *go = (struct go7007 *)urb->context; - int r, status = urb-> status; + int r, status = urb->status; if (!go->streaming) { wake_up_interruptible(&go->frame_waitq); @@ -877,7 +877,7 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, if (go->status == STATUS_SHUTDOWN) return -1; - down(&usb->i2c_lock); + mutex_lock(&usb->i2c_lock); for (i = 0; i < num; ++i) { /* The hardware command is "write some bytes then read some @@ -935,7 +935,7 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, ret = 0; i2c_done: - up(&usb->i2c_lock); + mutex_unlock(&usb->i2c_lock); return ret; } @@ -1065,7 +1065,7 @@ static int go7007_usb_probe(struct usb_interface *intf, if (board->flags & GO7007_USB_EZUSB_I2C) { memcpy(&go->i2c_adapter, &go7007_usb_adap_templ, sizeof(go7007_usb_adap_templ)); - init_MUTEX(&usb->i2c_lock); + mutex_init(&usb->i2c_lock); go->i2c_adapter.dev.parent = go->dev; i2c_set_adapdata(&go->i2c_adapter, go); if (i2c_add_adapter(&go->i2c_adapter) < 0) { diff --git a/linux/drivers/staging/go7007/go7007-v4l2.c b/linux/drivers/staging/go7007/go7007-v4l2.c index 06cacd37b..1098cffb6 100644 --- a/linux/drivers/staging/go7007/go7007-v4l2.c +++ b/linux/drivers/staging/go7007/go7007-v4l2.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include @@ -75,7 +75,7 @@ static int go7007_streamoff(struct go7007 *go) int retval = -EINVAL; unsigned long flags; - down(&go->hw_lock); + mutex_lock(&go->hw_lock); if (go->streaming) { go->streaming = 0; go7007_stream_stop(go); @@ -85,7 +85,7 @@ static int go7007_streamoff(struct go7007 *go) go7007_reset_encoder(go); retval = 0; } - up(&go->hw_lock); + mutex_unlock(&go->hw_lock); return 0; } @@ -101,7 +101,7 @@ static int go7007_open(struct file *file) return -ENOMEM; ++go->ref_count; gofh->go = go; - init_MUTEX(&gofh->lock); + mutex_init(&gofh->lock); gofh->buf_count = 0; file->private_data = gofh; return 0; @@ -705,14 +705,14 @@ static int vidioc_reqbufs(struct file *file, void *priv, req->memory != V4L2_MEMORY_MMAP) return -EINVAL; - down(&gofh->lock); + mutex_lock(&gofh->lock); for (i = 0; i < gofh->buf_count; ++i) if (gofh->bufs[i].mapped > 0) goto unlock_and_return; - down(&go->hw_lock); + mutex_lock(&go->hw_lock); if (go->in_use > 0 && gofh->buf_count == 0) { - up(&go->hw_lock); + mutex_unlock(&go->hw_lock); goto unlock_and_return; } @@ -731,7 +731,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, GFP_KERNEL); if (!gofh->bufs) { - up(&go->hw_lock); + mutex_unlock(&go->hw_lock); goto unlock_and_return; } @@ -750,8 +750,8 @@ static int vidioc_reqbufs(struct file *file, void *priv, } gofh->buf_count = count; - up(&go->hw_lock); - up(&gofh->lock); + mutex_unlock(&go->hw_lock); + mutex_unlock(&gofh->lock); memset(req, 0, sizeof(*req)); @@ -762,7 +762,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, return 0; unlock_and_return: - up(&gofh->lock); + mutex_unlock(&gofh->lock); return retval; } @@ -778,7 +778,7 @@ static int vidioc_querybuf(struct file *file, void *priv, index = buf->index; - down(&gofh->lock); + mutex_lock(&gofh->lock); if (index >= gofh->buf_count) goto unlock_and_return; @@ -802,12 +802,12 @@ static int vidioc_querybuf(struct file *file, void *priv, buf->memory = V4L2_MEMORY_MMAP; buf->m.offset = index * GO7007_BUF_SIZE; buf->length = GO7007_BUF_SIZE; - up(&gofh->lock); + mutex_unlock(&gofh->lock); return 0; unlock_and_return: - up(&gofh->lock); + mutex_unlock(&gofh->lock); return retval; } @@ -824,7 +824,7 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) buf->memory != V4L2_MEMORY_MMAP) return retval; - down(&gofh->lock); + mutex_lock(&gofh->lock); if (buf->index < 0 || buf->index >= gofh->buf_count) goto unlock_and_return; @@ -865,12 +865,12 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) spin_lock_irqsave(&go->spinlock, flags); list_add_tail(&gobuf->stream, &go->stream); spin_unlock_irqrestore(&go->spinlock, flags); - up(&gofh->lock); + mutex_unlock(&gofh->lock); return 0; unlock_and_return: - up(&gofh->lock); + mutex_unlock(&gofh->lock); return retval; } @@ -890,7 +890,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) if (buf->memory != V4L2_MEMORY_MMAP) return retval; - down(&gofh->lock); + mutex_lock(&gofh->lock); if (list_empty(&go->stream)) goto unlock_and_return; gobuf = list_entry(go->stream.next, @@ -934,11 +934,11 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) buf->length = GO7007_BUF_SIZE; buf->reserved = gobuf->modet_active; - up(&gofh->lock); + mutex_unlock(&gofh->lock); return 0; unlock_and_return: - up(&gofh->lock); + mutex_unlock(&gofh->lock); return retval; } @@ -952,8 +952,8 @@ static int vidioc_streamon(struct file *file, void *priv, if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - down(&gofh->lock); - down(&go->hw_lock); + mutex_lock(&gofh->lock); + mutex_lock(&go->hw_lock); if (!go->streaming) { go->streaming = 1; @@ -964,8 +964,8 @@ static int vidioc_streamon(struct file *file, void *priv, else retval = 0; } - up(&go->hw_lock); - up(&gofh->lock); + mutex_unlock(&go->hw_lock); + mutex_unlock(&gofh->lock); return retval; } @@ -978,9 +978,9 @@ static int vidioc_streamoff(struct file *file, void *priv, if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - down(&gofh->lock); + mutex_lock(&gofh->lock); go7007_streamoff(go); - up(&gofh->lock); + mutex_unlock(&gofh->lock); return 0; } @@ -1734,18 +1734,18 @@ static int go7007_mmap(struct file *file, struct vm_area_struct *vma) return -EINVAL; /* only support VM_SHARED mapping */ if (vma->vm_end - vma->vm_start != GO7007_BUF_SIZE) return -EINVAL; /* must map exactly one full buffer */ - down(&gofh->lock); + mutex_lock(&gofh->lock); index = vma->vm_pgoff / GO7007_BUF_PAGES; if (index >= gofh->buf_count) { - up(&gofh->lock); + mutex_unlock(&gofh->lock); return -EINVAL; /* trying to map beyond requested buffers */ } if (index * GO7007_BUF_PAGES != vma->vm_pgoff) { - up(&gofh->lock); + mutex_unlock(&gofh->lock); return -EINVAL; /* offset is not aligned on buffer boundary */ } if (gofh->bufs[index].mapped > 0) { - up(&gofh->lock); + mutex_unlock(&gofh->lock); return -EBUSY; } gofh->bufs[index].mapped = 1; @@ -1754,7 +1754,7 @@ static int go7007_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_flags |= VM_DONTEXPAND; vma->vm_flags &= ~VM_IO; vma->vm_private_data = &gofh->bufs[index]; - up(&gofh->lock); + mutex_unlock(&gofh->lock); return 0; } @@ -1862,7 +1862,7 @@ void go7007_v4l2_remove(struct go7007 *go) { unsigned long flags; - down(&go->hw_lock); + mutex_lock(&go->hw_lock); if (go->streaming) { go->streaming = 0; go7007_stream_stop(go); @@ -1870,7 +1870,7 @@ void go7007_v4l2_remove(struct go7007 *go) abort_queued(go); spin_unlock_irqrestore(&go->spinlock, flags); } - up(&go->hw_lock); + mutex_unlock(&go->hw_lock); if (go->video_dev) video_unregister_device(go->video_dev); } diff --git a/linux/drivers/staging/go7007/go7007.txt b/linux/drivers/staging/go7007/go7007.txt index 7656c0833..06a76da32 100644 --- a/linux/drivers/staging/go7007/go7007.txt +++ b/linux/drivers/staging/go7007/go7007.txt @@ -2,7 +2,7 @@ This is a driver for the WIS GO7007SB multi-format video encoder. Pete Eberlein -The driver was originally released under the GPL and is currently hosted at: +The driver was orignally released under the GPL and is currently hosted at: http://nikosapi.org/wiki/index.php/WIS_Go7007_Linux_driver The go7007 firmware can be acquired from the package on the site above. @@ -24,7 +24,7 @@ These should be used instead of the non-standard GO7007 ioctls described below. -The README files from the original package appears below: +The README files from the orignal package appear below: --------------------------------------------------------------------------- WIS GO7007SB Public Linux Driver diff --git a/linux/drivers/staging/go7007/s2250-board.c b/linux/drivers/staging/go7007/s2250-board.c index b398db43d..f35f0776c 100644 --- a/linux/drivers/staging/go7007/s2250-board.c +++ b/linux/drivers/staging/go7007/s2250-board.c @@ -21,12 +21,10 @@ #include #include #include +#include "s2250-loader.h" #include "go7007-priv.h" #include "wis-i2c.h" -extern int s2250loader_init(void); -extern void s2250loader_cleanup(void); - #define TLV320_ADDRESS 0x34 #define VPX322_ADDR_ANALOGCONTROL1 0x02 #define VPX322_ADDR_BRIGHTNESS0 0x0127 @@ -43,7 +41,7 @@ struct go7007_usb_board { struct go7007_usb { struct go7007_usb_board *board; - struct semaphore i2c_lock; + struct mutex i2c_lock; struct usb_device *usbdev; struct urb *video_urbs[8]; struct urb *audio_urbs[8]; @@ -165,7 +163,7 @@ static int write_reg(struct i2c_client *client, u8 reg, u8 value) return -ENOMEM; usb = go->hpi_context; - if (down_interruptible(&usb->i2c_lock) != 0) { + if (mutex_lock_interruptible(&usb->i2c_lock) != 0) { printk(KERN_INFO "i2c lock failed\n"); kfree(buf); return -EINTR; @@ -175,7 +173,7 @@ static int write_reg(struct i2c_client *client, u8 reg, u8 value) buf, 16, 1); - up(&usb->i2c_lock); + mutex_unlock(&usb->i2c_lock); kfree(buf); return rc; } @@ -203,14 +201,14 @@ static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val) memset(buf, 0xcd, 6); usb = go->hpi_context; - if (down_interruptible(&usb->i2c_lock) != 0) { + if (mutex_lock_interruptible(&usb->i2c_lock) != 0) { printk(KERN_INFO "i2c lock failed\n"); return -EINTR; } if (go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1) < 0) return -EFAULT; - up(&usb->i2c_lock); + mutex_unlock(&usb->i2c_lock); if (buf[0] == 0) { unsigned int subaddr, val_read; @@ -541,7 +539,7 @@ static int s2250_probe(struct i2c_client *client, dec->audio_input = 0; write_reg(client, 0x08, 0x02); /* Line In */ - if (down_interruptible(&usb->i2c_lock) == 0) { + if (mutex_lock_interruptible(&usb->i2c_lock) == 0) { data = kzalloc(16, GFP_KERNEL); if (data != NULL) { int rc; @@ -560,7 +558,7 @@ static int s2250_probe(struct i2c_client *client, } kfree(data); } - up(&usb->i2c_lock); + mutex_unlock(&usb->i2c_lock); } printk("s2250: initialized successfully\n"); diff --git a/linux/drivers/staging/go7007/s2250-loader.c b/linux/drivers/staging/go7007/s2250-loader.c index bb22347af..d7bf82983 100644 --- a/linux/drivers/staging/go7007/s2250-loader.c +++ b/linux/drivers/staging/go7007/s2250-loader.c @@ -35,7 +35,7 @@ typedef struct device_extension_s { #define MAX_DEVICES 256 static pdevice_extension_t s2250_dev_table[MAX_DEVICES]; -static DECLARE_MUTEX(s2250_dev_table_mutex); +static DEFINE_MUTEX(s2250_dev_table_mutex); #define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref) static void s2250loader_delete(struct kref *kref) @@ -67,7 +67,7 @@ static int s2250loader_probe(struct usb_interface *interface, printk(KERN_ERR "can't handle multiple config\n"); return -1; } - down(&s2250_dev_table_mutex); + mutex_lock(&s2250_dev_table_mutex); for (minor = 0; minor < MAX_DEVICES; minor++) { if (s2250_dev_table[minor] == NULL) @@ -96,7 +96,7 @@ static int s2250loader_probe(struct usb_interface *interface, kref_init(&(s->kref)); - up(&s2250_dev_table_mutex); + mutex_unlock(&s2250_dev_table_mutex); if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) { printk(KERN_ERR @@ -128,7 +128,7 @@ static int s2250loader_probe(struct usb_interface *interface, return 0; failed: - up(&s2250_dev_table_mutex); + mutex_unlock(&s2250_dev_table_mutex); failed2: if (s) kref_put(&(s->kref), s2250loader_delete); diff --git a/linux/drivers/staging/go7007/snd-go7007.c b/linux/drivers/staging/go7007/snd-go7007.c index cd19be6c0..03c4dfc13 100644 --- a/linux/drivers/staging/go7007/snd-go7007.c +++ b/linux/drivers/staging/go7007/snd-go7007.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 833b98d6daa6dfc535249b87dbc021704cdf08e4 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 10 Sep 2009 23:01:06 -0400 Subject: em28xx: do not create /dev/vbiX device if VBI not supported From: Devin Heitmueller Do not create the VBI device in cases where VBI is not supported on the target em28xx chip. This work was sponsored by EyeMagnet Limited. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-core.c | 2 +- linux/drivers/media/video/em28xx/em28xx-video.c | 25 ++++++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 6ae539674..1b9a0953e 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -1140,7 +1140,7 @@ struct em28xx *em28xx_get_device(int minor, list_for_each_entry(h, &em28xx_devlist, devlist) { if (h->vdev->minor == minor) dev = h; - if (h->vbi_dev->minor == minor) { + if (h->vbi_dev && h->vbi_dev->minor == minor) { dev = h; *fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; } diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 773016eb8..920712ae6 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -2557,14 +2557,17 @@ int em28xx_register_analog_devices(struct em28xx *dev) } /* Allocate and fill vbi video_device struct */ - dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi"); + if (em28xx_vbi_supported(dev) == 1) { + dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, + "vbi"); - /* register v4l2 vbi video_device */ - ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, - vbi_nr[dev->devno]); - if (ret < 0) { - em28xx_errdev("unable to register vbi device\n"); - return ret; + /* register v4l2 vbi video_device */ + ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, + vbi_nr[dev->devno]); + if (ret < 0) { + em28xx_errdev("unable to register vbi device\n"); + return ret; + } } if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { @@ -2584,8 +2587,12 @@ int em28xx_register_analog_devices(struct em28xx *dev) dev->radio_dev->num); } - em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", - dev->vdev->num, dev->vbi_dev->num); + em28xx_info("V4L2 video device registered as /dev/video%d\n", + dev->vdev->num); + + if (dev->vbi_dev) + em28xx_info("V4L2 VBI device registered as /dev/vbi%d\n", + dev->vbi_dev->num); return 0; } -- cgit v1.2.3 From 60e9021e45939ad296d3688928ddca19e0ebe65d Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 10 Sep 2009 23:08:44 -0400 Subject: em28xx: only advertise VBI capability if supported From: Devin Heitmueller Change the code so we only claim to support VBI if the underlying chipset actually has the support. This work was sponsored by EyeMagnet Limited. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 920712ae6..a4f09dff3 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1794,11 +1794,13 @@ static int vidioc_querycap(struct file *file, void *priv, cap->version = EM28XX_VERSION_CODE; cap->capabilities = - V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + if (dev->vbi_dev) + cap->capabilities |= V4L2_CAP_VBI_CAPTURE; + if (dev->audio_mode.has_audio) cap->capabilities |= V4L2_CAP_AUDIO; -- cgit v1.2.3 From 2726f365e349962c9a313686a5c0f9b3989d5dbd Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 10 Sep 2009 23:40:18 -0400 Subject: em28xx: implement g_std v4l call From: Devin Heitmueller We need to implement the g_std call, or else the default norm always gets returned, which breaks VBI capturing if you had changed the standard to NTSC using s_std. I had temporarily changed the default norm to NTSC so that zvbi-ntsc-cc wouldn't choke, so now that we are returning the correct value, switch it back to PAL as the default. This work was sponsored by EyeMagnet Limited. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-video.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index a4f09dff3..d00e78659 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1170,6 +1170,22 @@ out: return rc; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) +{ + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + struct v4l2_format f; + int rc; + + rc = check_dev(dev); + if (rc < 0) + return rc; + + *norm = dev->norm; + + return 0; +} + static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) { struct em28xx_fh *fh = priv; @@ -2405,6 +2421,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_g_std = vidioc_g_std, .vidioc_s_std = vidioc_s_std, .vidioc_g_parm = vidioc_g_parm, .vidioc_s_parm = vidioc_s_parm, @@ -2438,9 +2455,7 @@ static const struct video_device em28xx_video_template = { .minor = -1, .tvnorms = V4L2_STD_ALL, - /* FIXME: we need this to be NTSC for VBI to work - it should - be moved to a per-board definition */ - .current_norm = V4L2_STD_NTSC, + .current_norm = V4L2_STD_PAL, }; static const struct v4l2_file_operations radio_fops = { -- cgit v1.2.3 From 4096af2a99f354182f630f03bf2a97c100a14bd8 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 10 Sep 2009 23:51:48 -0400 Subject: em28xx: remove unneeded code that set VINCTRL register From: Devin Heitmueller Remove redundant call to set the vinctrl register. This eliminates any ambiguity as to how the register is configured (since it is now always set in em28xx_set_outfmt). This work was sponsored by EyeMagnet Limited. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-video.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index d00e78659..596e51f90 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -2543,15 +2543,10 @@ int em28xx_register_analog_devices(struct em28xx *dev) dev->mute = 1; dev->volume = 0x1f; -#if 1 - /* enable vbi capturing */ - /* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK); em28xx_write_reg(dev, EM28XX_R0F_XCLK, (EM28XX_XCLK_AUDIO_UNMUTE | val)); - em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); -#endif em28xx_set_outfmt(dev); em28xx_colorlevels_set_default(dev); -- cgit v1.2.3 From 8201f56625ffdc9146ad8eb4525c1b50e6194f5a Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Thu, 10 Sep 2009 23:53:44 -0400 Subject: em28xx: fix unused variable warning From: Devin Heitmueller Remove unused variable from when I introduced the g_std() function. This work was sponsored by EyeMagnet Limited. Priority: normal Signed-off-by: Devin Heitmueller --- linux/drivers/media/video/em28xx/em28xx-video.c | 1 - 1 file changed, 1 deletion(-) diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 596e51f90..bfe57ca82 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1174,7 +1174,6 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; - struct v4l2_format f; int rc; rc = check_dev(dev); -- cgit v1.2.3 From 362fa9c491655630cbcfb6a3704da18abade2a95 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 12 Sep 2009 15:43:25 +0300 Subject: get_dvb_firmware: add af9015 firmware From: Antti Palosaari Add af9015 firmware to get_dvb_firmware script. Firmware version is 4.95.0.0. Priority: normal Signed-off-by: Antti Palosaari --- linux/Documentation/dvb/get_dvb_firmware | 37 +++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/linux/Documentation/dvb/get_dvb_firmware b/linux/Documentation/dvb/get_dvb_firmware index 3d1b0ab70..14b7b5a3b 100755 --- a/linux/Documentation/dvb/get_dvb_firmware +++ b/linux/Documentation/dvb/get_dvb_firmware @@ -25,7 +25,8 @@ use IO::Handle; "tda10046lifeview", "av7110", "dec2000t", "dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004", "or51211", "or51132_qam", "or51132_vsb", "bluebird", - "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718" ); + "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718", + "af9015"); # Check args syntax() if (scalar(@ARGV) != 1); @@ -514,6 +515,40 @@ sub bluebird { $outfile; } +sub af9015 { + my $sourcefile = "download.ashx?file=57"; + my $url = "http://www.ite.com.tw/EN/Services/$sourcefile"; + my $hash = "ff5b096ed47c080870eacdab2de33ad6"; + my $outfile = "dvb-usb-af9015.fw"; + my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); + my $fwoffset = 0x22708; + my $fwlength = 18225; + my ($chunklength, $buf, $rcount); + + checkstandard(); + + wgetfile($sourcefile, $url); + unzip($sourcefile, $tmpdir); + verify("$tmpdir/Driver/Files/AF15BDA.sys", $hash); + + open INFILE, '<', "$tmpdir/Driver/Files/AF15BDA.sys"; + open OUTFILE, '>', $outfile; + + sysseek(INFILE, $fwoffset, SEEK_SET); + while($fwlength > 0) { + $chunklength = 55; + $chunklength = $fwlength if ($chunklength > $fwlength); + $rcount = sysread(INFILE, $buf, $chunklength); + die "Ran out of data\n" if ($rcount != $chunklength); + syswrite(OUTFILE, $buf); + sysread(INFILE, $buf, 8); + $fwlength -= $rcount + 8; + } + + close OUTFILE; + close INFILE; +} + # --------------------------------------------------------------- # Utilities -- cgit v1.2.3 From bf4883355d6f095a2fe03131f766f658203ded79 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 12 Sep 2009 15:51:36 +0300 Subject: af9015: [1/2] fix USB TS configuration From: Jose Alberto Reguero Fix wrongly configured USB2.0 TS EP. Priority: high Signed-off-by: Jose Alberto Reguero Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/af9015.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index aeb10db0b..dd7070821 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -877,7 +877,7 @@ static int af9015_read_config(struct usb_device *udev) af9015_config.dual_mode = 0; } else { af9015_properties[i].adapter[0].stream.u.bulk.buffersize - = TS_USB20_MAX_PACKET_SIZE; + = TS_USB20_FRAME_SIZE; } } @@ -1313,7 +1313,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .u = { .bulk = { .buffersize = - TS_USB20_MAX_PACKET_SIZE, + TS_USB20_FRAME_SIZE, } } }, @@ -1419,7 +1419,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .u = { .bulk = { .buffersize = - TS_USB20_MAX_PACKET_SIZE, + TS_USB20_FRAME_SIZE, } } }, @@ -1525,7 +1525,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .u = { .bulk = { .buffersize = - TS_USB20_MAX_PACKET_SIZE, + TS_USB20_FRAME_SIZE, } } }, -- cgit v1.2.3 From c04ff5d532d9ae99a06936a894a293a3fc806f6a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 12 Sep 2009 13:15:33 -0300 Subject: backport commit 720b17e759a50635c429ccaa2ec3d01edb4f92d6 From: Mauro Carvalho Chehab kernel-sync: Author: Magnus Damm Date: Tue Jun 16 15:32:36 2009 -0700 videobuf-dma-contig: zero copy USERPTR support Since videobuf-dma-contig is designed to handle physically contiguous memory, this patch modifies the videobuf-dma-contig code to only accept a user space pointer to physically contiguous memory. For now only VM_PFNMAP vmas are supported, so forget hotplug. On SuperH Mobile we use this with our sh_mobile_ceu_camera driver together with various multimedia accelerator blocks that are exported to user space using UIO. The UIO kernel code exports physically contiguous memory to user space and lets the user space application mmap() this memory and pass a pointer using the USERPTR interface for V4L2 zero copy operation. With this approach we support zero copy capture, hardware scaling and various forms of hardware encoding and decoding. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/videobuf-dma-contig.c | 94 +++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 5 deletions(-) diff --git a/linux/drivers/media/video/videobuf-dma-contig.c b/linux/drivers/media/video/videobuf-dma-contig.c index 633a124cf..bd1b13e93 100644 --- a/linux/drivers/media/video/videobuf-dma-contig.c +++ b/linux/drivers/media/video/videobuf-dma-contig.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include "compat.h" @@ -26,6 +27,7 @@ struct videobuf_dma_contig_memory { void *vaddr; dma_addr_t dma_handle; unsigned long size; + int is_userptr; }; #define MAGIC_DC_MEM 0x0733ac61 @@ -109,6 +111,82 @@ static struct vm_operations_struct videobuf_vm_ops = { .close = videobuf_vm_close, }; +/** + * videobuf_dma_contig_user_put() - reset pointer to user space buffer + * @mem: per-buffer private videobuf-dma-contig data + * + * This function resets the user space pointer + */ +static void videobuf_dma_contig_user_put(struct videobuf_dma_contig_memory *mem) +{ + mem->is_userptr = 0; + mem->dma_handle = 0; + mem->size = 0; +} + +/** + * videobuf_dma_contig_user_get() - setup user space memory pointer + * @mem: per-buffer private videobuf-dma-contig data + * @vb: video buffer to map + * + * This function validates and sets up a pointer to user space memory. + * Only physically contiguous pfn-mapped memory is accepted. + * + * Returns 0 if successful. + */ +static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem, + struct videobuf_buffer *vb) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long prev_pfn, this_pfn; + unsigned long pages_done, user_address; + int ret; + + mem->size = PAGE_ALIGN(vb->size); + mem->is_userptr = 0; + ret = -EINVAL; + + down_read(&mm->mmap_sem); + + vma = find_vma(mm, vb->baddr); + if (!vma) + goto out_up; + + if ((vb->baddr + mem->size) > vma->vm_end) + goto out_up; + + pages_done = 0; + prev_pfn = 0; /* kill warning */ + user_address = vb->baddr; + + while (pages_done < (mem->size >> PAGE_SHIFT)) { + ret = follow_pfn(vma, user_address, &this_pfn); + if (ret) + break; + + if (pages_done == 0) + mem->dma_handle = this_pfn << PAGE_SHIFT; + else if (this_pfn != (prev_pfn + 1)) + ret = -EFAULT; + + if (ret) + break; + + prev_pfn = this_pfn; + user_address += PAGE_SIZE; + pages_done++; + } + + if (!ret) + mem->is_userptr = 1; + + out_up: + up_read(¤t->mm->mmap_sem); + + return ret; +} + static void *__videobuf_alloc(size_t size) { struct videobuf_dma_contig_memory *mem; @@ -155,12 +233,11 @@ static int __videobuf_iolock(struct videobuf_queue *q, case V4L2_MEMORY_USERPTR: dev_dbg(q->dev, "%s memory method USERPTR\n", __func__); - /* The only USERPTR currently supported is the one needed for - read() method. - */ + /* handle pointer from user space */ if (vb->baddr) - return -EINVAL; + return videobuf_dma_contig_user_get(mem, vb); + /* allocate memory for the read() method */ mem->size = PAGE_ALIGN(vb->size); mem->vaddr = dma_alloc_coherent(q->dev, mem->size, &mem->dma_handle, GFP_KERNEL); @@ -387,7 +464,7 @@ void videobuf_dma_contig_free(struct videobuf_queue *q, So, it should free memory only if the memory were allocated for read() operation. */ - if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr) + if (buf->memory != V4L2_MEMORY_USERPTR) return; if (!mem) @@ -395,6 +472,13 @@ void videobuf_dma_contig_free(struct videobuf_queue *q, MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); + /* handle user space pointer case */ + if (buf->baddr) { + videobuf_dma_contig_user_put(mem); + return; + } + + /* read() method */ dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle); mem->vaddr = NULL; } -- cgit v1.2.3 From ea5644051e25a55f6a8a02e5c9d22e06dc318307 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 12 Sep 2009 13:32:57 -0300 Subject: backport upstream changes for arch From: Mauro Carvalho Chehab It also backports a needed change at vpif_display, applied at -git to fix compilation against the arm drivers. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/arch/arm/mach-pxa/pcm990-baseboard.c | 54 +++++------------------- linux/arch/sh/boards/board-ap325rxa.c | 2 +- linux/arch/sh/boards/mach-migor/setup.c | 2 +- linux/drivers/media/video/davinci/vpif_display.c | 2 +- 4 files changed, 13 insertions(+), 47 deletions(-) diff --git a/linux/arch/arm/mach-pxa/pcm990-baseboard.c b/linux/arch/arm/mach-pxa/pcm990-baseboard.c index 713f24c94..01791d74e 100644 --- a/linux/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/linux/arch/arm/mach-pxa/pcm990-baseboard.c @@ -427,56 +427,25 @@ static void pcm990_camera_free_bus(struct soc_camera_link *link) gpio_bus_switch = -EINVAL; } +static struct soc_camera_link iclink = { + .bus_id = 0, /* Must match with the camera ID above */ + .query_bus_param = pcm990_camera_query_bus_param, + .set_bus_param = pcm990_camera_set_bus_param, + .free_bus = pcm990_camera_free_bus, +}; + /* Board I2C devices. */ static struct i2c_board_info __initdata pcm990_i2c_devices[] = { { /* Must initialize before the camera(s) */ I2C_BOARD_INFO("pca9536", 0x41), .platform_data = &pca9536_data, - }, -}; - -static struct i2c_board_info pcm990_camera_i2c[] = { - { + }, { I2C_BOARD_INFO("mt9v022", 0x48), + .platform_data = &iclink, /* With extender */ }, { I2C_BOARD_INFO("mt9m001", 0x5d), - }, -}; - -static struct soc_camera_link iclink[] = { - { - .bus_id = 0, /* Must match with the camera ID */ - .board_info = &pcm990_camera_i2c[0], - .i2c_adapter_id = 0, - .query_bus_param = pcm990_camera_query_bus_param, - .set_bus_param = pcm990_camera_set_bus_param, - .free_bus = pcm990_camera_free_bus, - .module_name = "mt9v022", - }, { - .bus_id = 0, /* Must match with the camera ID */ - .board_info = &pcm990_camera_i2c[1], - .i2c_adapter_id = 0, - .query_bus_param = pcm990_camera_query_bus_param, - .set_bus_param = pcm990_camera_set_bus_param, - .free_bus = pcm990_camera_free_bus, - .module_name = "mt9m001", - }, -}; - -static struct platform_device pcm990_camera[] = { - { - .name = "soc-camera-pdrv", - .id = 0, - .dev = { - .platform_data = &iclink[0], - }, - }, { - .name = "soc-camera-pdrv", - .id = 1, - .dev = { - .platform_data = &iclink[1], - }, + .platform_data = &iclink, /* With extender */ }, }; #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */ @@ -532,9 +501,6 @@ void __init pcm990_baseboard_init(void) pxa_set_camera_info(&pcm990_pxacamera_platform_data); i2c_register_board_info(0, ARRAY_AND_SIZE(pcm990_i2c_devices)); - - platform_device_register(&pcm990_camera[0]); - platform_device_register(&pcm990_camera[1]); #endif printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n"); diff --git a/linux/arch/sh/boards/board-ap325rxa.c b/linux/arch/sh/boards/board-ap325rxa.c index 96e5bae1c..48ab77ea0 100644 --- a/linux/arch/sh/boards/board-ap325rxa.c +++ b/linux/arch/sh/boards/board-ap325rxa.c @@ -581,7 +581,7 @@ static int __init ap325rxa_devices_setup(void) return platform_add_devices(ap325rxa_devices, ARRAY_SIZE(ap325rxa_devices)); } -device_initcall(ap325rxa_devices_setup); +arch_initcall(ap325rxa_devices_setup); /* Return the board specific boot mode pin configuration */ static int ap325rxa_mode_pins(void) diff --git a/linux/arch/sh/boards/mach-migor/setup.c b/linux/arch/sh/boards/mach-migor/setup.c index f70f4644d..f9b2e4df3 100644 --- a/linux/arch/sh/boards/mach-migor/setup.c +++ b/linux/arch/sh/boards/mach-migor/setup.c @@ -608,7 +608,7 @@ static int __init migor_devices_setup(void) return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices)); } -__initcall(migor_devices_setup); +arch_initcall(migor_devices_setup); /* Return the board specific boot mode pin configuration */ static int migor_mode_pins(void) diff --git a/linux/drivers/media/video/davinci/vpif_display.c b/linux/drivers/media/video/davinci/vpif_display.c index 0f0ec8dc6..a125a452d 100644 --- a/linux/drivers/media/video/davinci/vpif_display.c +++ b/linux/drivers/media/video/davinci/vpif_display.c @@ -1422,7 +1422,7 @@ vpif_init_free_channel_objects: */ static __init int vpif_probe(struct platform_device *pdev) { - const struct subdev_info *subdevdata; + const struct vpif_subdev_info *subdevdata; int i, j = 0, k, q, m, err = 0; struct i2c_adapter *i2c_adap; struct vpif_config *config; -- cgit v1.2.3 From ff680464a0d27db7be8755753e6b52bfa03d0035 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sat, 12 Sep 2009 19:35:29 +0300 Subject: af9015: [2/2] fix USB TS configuration From: Antti Palosaari Fix wrongly configured USB1.1 TS EP. Patch serie also increases USB URB size to reduce wakeups. USB1.1 URB size from 64 to 940 bytes USB2.0 URB size from 512 to 16356 bytes Priority: high Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/af9015.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index dd7070821..723253c59 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -372,12 +372,14 @@ static int af9015_init_endpoint(struct dvb_usb_device *d) u8 packet_size; deb_info("%s: USB speed:%d\n", __func__, d->udev->speed); + /* Windows driver uses packet count 21 for USB1.1 and 348 for USB2.0. + We use smaller - about 1/4 from the original, 5 and 87. */ #define TS_PACKET_SIZE 188 -#define TS_USB20_PACKET_COUNT 348 +#define TS_USB20_PACKET_COUNT 87 #define TS_USB20_FRAME_SIZE (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT) -#define TS_USB11_PACKET_COUNT 21 +#define TS_USB11_PACKET_COUNT 5 #define TS_USB11_FRAME_SIZE (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT) #define TS_USB20_MAX_PACKET_SIZE 512 @@ -871,7 +873,7 @@ static int af9015_read_config(struct usb_device *udev) /* USB1.1 set smaller buffersize and disable 2nd adapter */ if (udev->speed == USB_SPEED_FULL) { af9015_properties[i].adapter[0].stream.u.bulk.buffersize - = TS_USB11_MAX_PACKET_SIZE; + = TS_USB11_FRAME_SIZE; /* disable 2nd adapter because we don't have PID-filters */ af9015_config.dual_mode = 0; -- cgit v1.2.3 From 391254f7fc7cf4b47428973d700410f37b3f1a2e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 12 Sep 2009 14:16:11 -0300 Subject: backport changeset f7a386c5b8ff34cd84ae922603d1c6f9d234edee From: Mauro Carvalho Chehab kernel-sync: Author: Kay Sievers Date: Thu Apr 30 15:23:42 2009 +0200 Driver Core: usb: add nodename support for usb drivers. This adds support for USB drivers to report their requested nodename to userspace. It also updates a number of USB drivers to provide the needed subdirectory and device name to be used for them. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/dabusb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/linux/drivers/media/video/dabusb.c b/linux/drivers/media/video/dabusb.c index cb0a41c45..a0812ce91 100644 --- a/linux/drivers/media/video/dabusb.c +++ b/linux/drivers/media/video/dabusb.c @@ -813,8 +813,18 @@ static struct file_operations dabusb_fops = .release = dabusb_release, }; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) +static char *dabusb_nodename(struct device *dev) +{ + return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev)); +} + +#endif static struct usb_class_driver dabusb_class = { .name = "dabusb%d", +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) + .nodename = dabusb_nodename, +#endif .fops = &dabusb_fops, .minor_base = DABUSB_MINOR, }; -- cgit v1.2.3 From 74c8a615523ef5d42b617ab521fa1c6a01da0cd9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 12 Sep 2009 14:18:18 -0300 Subject: backport commit 8a8bdcc7533b104d789d9bb3ed90da9352515e21 From: Mauro Carvalho Chehab kernel-sync: Author: Kay Sievers Date: Thu Apr 30 15:23:42 2009 +0200 Driver Core: dvb: add nodename for dvb drivers This adds support to the dvb core to report the proper device name to userspace for their devices. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dvbdev.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c index f6084e19d..2028be23d 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.c +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c @@ -472,6 +472,17 @@ static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env) } #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) +static char *dvb_nodename(struct device *dev) +{ + struct dvb_device *dvbdev = dev_get_drvdata(dev); + + return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d", + dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); +} + + +#endif static int __init init_dvbdev(void) { int retval; @@ -500,6 +511,9 @@ static int __init init_dvbdev(void) } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) dvb_class->dev_uevent = dvb_uevent; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) + dvb_class->nodename = dvb_nodename; #endif return 0; -- cgit v1.2.3 From 89522ac35d478d8c4f06e6ae1723925d20e3eca7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 12 Sep 2009 14:26:01 -0300 Subject: siano/Kconfig: a driver shouldn't be selected by default From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/siano/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/linux/drivers/media/dvb/siano/Kconfig b/linux/drivers/media/dvb/siano/Kconfig index ff297ceaf..8c1aed77e 100644 --- a/linux/drivers/media/dvb/siano/Kconfig +++ b/linux/drivers/media/dvb/siano/Kconfig @@ -28,7 +28,6 @@ config SMS_USB_DRV config SMS_SDIO_DRV tristate "SDIO interface support" depends on DVB_CORE && MMC - default m ---help--- Choose if you would like to have Siano's support for SDIO interface endmenu -- cgit v1.2.3 From 75bdd4882db874690382f633b28f5b3f7d5ff54c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 12 Sep 2009 14:28:58 -0300 Subject: af9015: revert changeset: 12588:184e9d1d8707 From: Mauro Carvalho Chehab Revert this patch as requested by the patch author. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-usb/af9015.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index aeb10db0b..69a00d610 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -108,7 +108,7 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) } /* write requested */ - if (write && req->data_len) { + if (write) { memcpy(&buf[8], req->data, req->data_len); msg_len += req->data_len; } -- cgit v1.2.3 From f919ed55d0ece48afb66100dce56494c346879c5 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Sep 2009 02:46:30 +0300 Subject: af9015: improve usb control message function slightly From: Antti Palosaari * define names for few values * decrease buffer len by one byte which was not used * add check for buffer overflow for sure * indentation fixes * remove useless 0 len check from memcpy It should not happen and if it happens memcpy should not do anything. Priority: normal Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/af9015.c | 34 +++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 723253c59..44eb7e46f 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -61,10 +61,13 @@ static struct af9013_config af9015_af9013_config[] = { static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) { +#define BUF_LEN 63 +#define REQ_HDR_LEN 8 /* send header size */ +#define ACK_HDR_LEN 2 /* rece header size */ int act_len, ret; - u8 buf[64]; + u8 buf[BUF_LEN]; u8 write = 1; - u8 msg_len = 8; + u8 msg_len = REQ_HDR_LEN; static u8 seq; /* packet sequence number */ if (mutex_lock_interruptible(&af9015_usb_mutex) < 0) @@ -107,17 +110,26 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) goto error_unlock; } + /* buffer overflow check */ + if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) || + (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) { + err("too much data; cmd:%d len:%d", req->cmd, req->data_len); + ret = -EINVAL; + goto error_unlock; + } + /* write requested */ - if (write && req->data_len) { - memcpy(&buf[8], req->data, req->data_len); + if (write) { + memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len); msg_len += req->data_len; } + deb_xfer(">>> "); debug_dump(buf, msg_len, deb_xfer); /* send req */ ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, - &act_len, AF9015_USB_TIMEOUT); + &act_len, AF9015_USB_TIMEOUT); if (ret) err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len); else @@ -130,10 +142,14 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) goto exit_unlock; - /* receive ack and data if read req */ - msg_len = 1 + 1 + req->data_len; /* seq + status + data len */ + /* write receives seq + status = 2 bytes + read receives seq + status + data = 2 + N bytes */ + msg_len = ACK_HDR_LEN; + if (!write) + msg_len += req->data_len; + ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, - &act_len, AF9015_USB_TIMEOUT); + &act_len, AF9015_USB_TIMEOUT); if (ret) { err("recv bulk message failed:%d", ret); ret = -1; @@ -159,7 +175,7 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) /* read request, copy returned data to return buf */ if (!write) - memcpy(req->data, &buf[2], req->data_len); + memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len); error_unlock: exit_unlock: -- cgit v1.2.3 From d65762ce274a5e3cfe393763b41e518ec26a5974 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 13 Sep 2009 03:25:59 +0300 Subject: af9015: fix typo in register compare From: Antti Palosaari And mask should be 0xff00 instead of 0xae00. Thanks to Jochen Friedrich for pointing this. Priority: normal Signed-off-by: Antti Palosaari Cc: Jochen Friedrich --- linux/drivers/media/dvb/dvb-usb/af9015.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index 44eb7e46f..ab505a268 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -97,7 +97,7 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) break; case WRITE_MEMORY: if (((req->addr & 0xff00) == 0xff00) || - ((req->addr & 0xae00) == 0xae00)) + ((req->addr & 0xff00) == 0xae00)) buf[0] = WRITE_VIRTUAL_MEMORY; case WRITE_VIRTUAL_MEMORY: case COPY_FIRMWARE: -- cgit v1.2.3 From f829cbff5c8f7aa1ea51da3f9e5a834d24734a22 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Sep 2009 11:13:59 -0300 Subject: Add conexant cx25821 driver From: Palash Bandyopadhyay Add conexant cx25821 driver release v106 of the Athena driver. Priority: normal Signed-off-by: Palash Bandyopadhyay Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/staging/cx25821/Kconfig | 34 + linux/drivers/staging/cx25821/Makefile | 15 + linux/drivers/staging/cx25821/cx25821-alsa.c | 814 ++++++++++ .../staging/cx25821/cx25821-audio-upstream.c | 825 ++++++++++ .../staging/cx25821/cx25821-audio-upstream.h | 63 + linux/drivers/staging/cx25821/cx25821-audio.h | 60 + linux/drivers/staging/cx25821/cx25821-audups11.c | 441 ++++++ linux/drivers/staging/cx25821/cx25821-biffuncs.h | 45 + linux/drivers/staging/cx25821/cx25821-cards.c | 73 + linux/drivers/staging/cx25821/cx25821-core.c | 1586 +++++++++++++++++++ linux/drivers/staging/cx25821/cx25821-gpio.c | 116 ++ linux/drivers/staging/cx25821/cx25821-gpio.h | 3 + linux/drivers/staging/cx25821/cx25821-i2c.c | 485 ++++++ .../staging/cx25821/cx25821-medusa-defines.h | 51 + linux/drivers/staging/cx25821/cx25821-medusa-reg.h | 456 ++++++ .../drivers/staging/cx25821/cx25821-medusa-video.c | 769 ++++++++++ .../drivers/staging/cx25821/cx25821-medusa-video.h | 51 + linux/drivers/staging/cx25821/cx25821-reg.h | 1609 ++++++++++++++++++++ linux/drivers/staging/cx25821/cx25821-sram.h | 266 ++++ .../staging/cx25821/cx25821-video-upstream-ch2.c | 847 +++++++++++ .../staging/cx25821/cx25821-video-upstream-ch2.h | 108 ++ .../staging/cx25821/cx25821-video-upstream.c | 923 +++++++++++ .../staging/cx25821/cx25821-video-upstream.h | 114 ++ linux/drivers/staging/cx25821/cx25821-video.c | 1337 ++++++++++++++++ linux/drivers/staging/cx25821/cx25821-video.h | 173 +++ linux/drivers/staging/cx25821/cx25821-video0.c | 457 ++++++ linux/drivers/staging/cx25821/cx25821-video1.c | 456 ++++++ linux/drivers/staging/cx25821/cx25821-video2.c | 459 ++++++ linux/drivers/staging/cx25821/cx25821-video3.c | 458 ++++++ linux/drivers/staging/cx25821/cx25821-video4.c | 456 ++++++ linux/drivers/staging/cx25821/cx25821-video5.c | 455 ++++++ linux/drivers/staging/cx25821/cx25821-video6.c | 455 ++++++ linux/drivers/staging/cx25821/cx25821-video7.c | 454 ++++++ linux/drivers/staging/cx25821/cx25821-videoioctl.c | 500 ++++++ linux/drivers/staging/cx25821/cx25821-vidups10.c | 443 ++++++ linux/drivers/staging/cx25821/cx25821-vidups9.c | 441 ++++++ linux/drivers/staging/cx25821/cx25821.h | 590 +++++++ v4l2-apps/util/cx25821/audioplayback | 1 + v4l2-apps/util/cx25821/audiorecord | 1 + v4l2-apps/util/cx25821/cx25821-medusa-decoder.c | 106 ++ v4l2-apps/util/cx25821/medusaReadWrite.c | 158 ++ v4l2-apps/util/cx25821/mencode_av | 1 + v4l2-apps/util/cx25821/mencode_video | 1 + v4l2-apps/util/cx25821/mplay_av | 1 + v4l2-apps/util/cx25821/mplay_cifNTSC | 1 + v4l2-apps/util/cx25821/mplay_cifPAL | 1 + v4l2-apps/util/cx25821/mplay_video | 1 + v4l2-apps/util/cx25821/regReadWrite.c | 158 ++ v4l2-apps/util/cx25821/setAlsaVolume | 2 + v4l2-apps/util/cx25821/setvideosetting.c | 187 +++ v4l2-apps/util/cx25821/upstream_app.c | 221 +++ 51 files changed, 17728 insertions(+) create mode 100644 linux/drivers/staging/cx25821/Kconfig create mode 100644 linux/drivers/staging/cx25821/Makefile create mode 100644 linux/drivers/staging/cx25821/cx25821-alsa.c create mode 100644 linux/drivers/staging/cx25821/cx25821-audio-upstream.c create mode 100644 linux/drivers/staging/cx25821/cx25821-audio-upstream.h create mode 100644 linux/drivers/staging/cx25821/cx25821-audio.h create mode 100644 linux/drivers/staging/cx25821/cx25821-audups11.c create mode 100644 linux/drivers/staging/cx25821/cx25821-biffuncs.h create mode 100644 linux/drivers/staging/cx25821/cx25821-cards.c create mode 100644 linux/drivers/staging/cx25821/cx25821-core.c create mode 100644 linux/drivers/staging/cx25821/cx25821-gpio.c create mode 100644 linux/drivers/staging/cx25821/cx25821-gpio.h create mode 100644 linux/drivers/staging/cx25821/cx25821-i2c.c create mode 100644 linux/drivers/staging/cx25821/cx25821-medusa-defines.h create mode 100644 linux/drivers/staging/cx25821/cx25821-medusa-reg.h create mode 100644 linux/drivers/staging/cx25821/cx25821-medusa-video.c create mode 100644 linux/drivers/staging/cx25821/cx25821-medusa-video.h create mode 100644 linux/drivers/staging/cx25821/cx25821-reg.h create mode 100644 linux/drivers/staging/cx25821/cx25821-sram.h create mode 100644 linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c create mode 100644 linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h create mode 100644 linux/drivers/staging/cx25821/cx25821-video-upstream.c create mode 100644 linux/drivers/staging/cx25821/cx25821-video-upstream.h create mode 100644 linux/drivers/staging/cx25821/cx25821-video.c create mode 100644 linux/drivers/staging/cx25821/cx25821-video.h create mode 100644 linux/drivers/staging/cx25821/cx25821-video0.c create mode 100644 linux/drivers/staging/cx25821/cx25821-video1.c create mode 100644 linux/drivers/staging/cx25821/cx25821-video2.c create mode 100644 linux/drivers/staging/cx25821/cx25821-video3.c create mode 100644 linux/drivers/staging/cx25821/cx25821-video4.c create mode 100644 linux/drivers/staging/cx25821/cx25821-video5.c create mode 100644 linux/drivers/staging/cx25821/cx25821-video6.c create mode 100644 linux/drivers/staging/cx25821/cx25821-video7.c create mode 100644 linux/drivers/staging/cx25821/cx25821-videoioctl.c create mode 100644 linux/drivers/staging/cx25821/cx25821-vidups10.c create mode 100644 linux/drivers/staging/cx25821/cx25821-vidups9.c create mode 100644 linux/drivers/staging/cx25821/cx25821.h create mode 100644 v4l2-apps/util/cx25821/audioplayback create mode 100644 v4l2-apps/util/cx25821/audiorecord create mode 100644 v4l2-apps/util/cx25821/cx25821-medusa-decoder.c create mode 100644 v4l2-apps/util/cx25821/medusaReadWrite.c create mode 100644 v4l2-apps/util/cx25821/mencode_av create mode 100644 v4l2-apps/util/cx25821/mencode_video create mode 100644 v4l2-apps/util/cx25821/mplay_av create mode 100644 v4l2-apps/util/cx25821/mplay_cifNTSC create mode 100644 v4l2-apps/util/cx25821/mplay_cifPAL create mode 100644 v4l2-apps/util/cx25821/mplay_video create mode 100644 v4l2-apps/util/cx25821/regReadWrite.c create mode 100644 v4l2-apps/util/cx25821/setAlsaVolume create mode 100644 v4l2-apps/util/cx25821/setvideosetting.c create mode 100644 v4l2-apps/util/cx25821/upstream_app.c diff --git a/linux/drivers/staging/cx25821/Kconfig b/linux/drivers/staging/cx25821/Kconfig new file mode 100644 index 000000000..88871156c --- /dev/null +++ b/linux/drivers/staging/cx25821/Kconfig @@ -0,0 +1,34 @@ +config VIDEO_CX25821 + tristate "Conexant cx25821 support" + depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT + select I2C_ALGOBIT + select VIDEO_BTCX + select VIDEO_TVEEPROM + select VIDEO_IR + select VIDEOBUF_DVB + select VIDEOBUF_DMA_SG + select VIDEO_CX25840 + select VIDEO_CX2341X + ---help--- + This is a video4linux driver for Conexant 25821 based + TV cards. + + To compile this driver as a module, choose M here: the + module will be called cx25821 + +config VIDEO_CX25821_ALSA + tristate "Conexant 25821 DMA audio support" + depends on VIDEO_CX25821 && SND && EXPERIMENTAL + select SND_PCM + ---help--- + This is a video4linux driver for direct (DMA) audio on + Conexant 25821 based capture cards using ALSA. + + It only works with boards with function 01 enabled. + To check if your board supports, use lspci -n. + If supported, you should see 14f1:8801 or 14f1:8811 + PCI device. + + To compile this driver as a module, choose M here: the + module will be called cx25821-alsa. + diff --git a/linux/drivers/staging/cx25821/Makefile b/linux/drivers/staging/cx25821/Makefile new file mode 100644 index 000000000..020d84404 --- /dev/null +++ b/linux/drivers/staging/cx25821/Makefile @@ -0,0 +1,15 @@ +cx25821-objs := cx25821-core.o cx25821-cards.o cx25821-i2c.o cx25821-gpio.o \ + cx25821-medusa-video.o cx25821-video.o cx25821-video0.o cx25821-video1.o \ + cx25821-video2.o cx25821-video3.o cx25821-video4.o cx25821-video5.o \ + cx25821-video6.o cx25821-video7.o cx25821-vidups9.o cx25821-vidups10.o \ + cx25821-audups11.o cx25821-video-upstream.o cx25821-video-upstream-ch2.o \ + cx25821-audio-upstream.o cx25821-videoioctl.o + +obj-$(CONFIG_VIDEO_CX25821) += cx25821.o +obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o + +EXTRA_CFLAGS += -Idrivers/media/video +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends + +EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) diff --git a/linux/drivers/staging/cx25821/cx25821-alsa.c b/linux/drivers/staging/cx25821/cx25821-alsa.c new file mode 100644 index 000000000..438f3da4b --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-alsa.c @@ -0,0 +1,814 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on SAA713x ALSA driver and CX88 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "compat.h" +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) +#include +#endif + + +#include "cx25821.h" +#include "cx25821-reg.h" + +#define AUDIO_SRAM_CHANNEL SRAM_CH08 + +#define dprintk(level,fmt, arg...) if (debug >= level) \ + printk(KERN_INFO "%s/1: " fmt, chip->dev->name , ## arg) + +#define dprintk_core(level,fmt, arg...) if (debug >= level) \ + printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name , ## arg) + + +/**************************************************************************** + Data type declarations - Can be moded to a header file later + ****************************************************************************/ + + +static struct snd_card *snd_cx25821_cards[SNDRV_CARDS]; +static int devno; + +struct cx25821_audio_dev { + struct cx25821_dev *dev; + struct cx25821_dmaqueue q; +#if 0 + u64 starttime; +#endif + + /* pci i/o */ + struct pci_dev *pci; + + /* audio controls */ + int irq; + + struct snd_card *card; + + unsigned long iobase; + spinlock_t reg_lock; + atomic_t count; + + unsigned int dma_size; + unsigned int period_size; + unsigned int num_periods; + + struct videobuf_dmabuf *dma_risc; + + struct cx25821_buffer *buf; + + struct snd_pcm_substream *substream; +}; +typedef struct cx25821_audio_dev snd_cx25821_card_t; + + +#ifdef COMPAT_SND_CTL_BOOLEAN_MONO +static int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} +#endif + +/**************************************************************************** + Module global static vars + ****************************************************************************/ + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ +static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; + +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled."); + +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s)."); + + +/**************************************************************************** + Module macros + ****************************************************************************/ + +MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards"); +MODULE_AUTHOR("Hiep Huynh"); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE("{{Conexant,25821}");//"{{Conexant,23881}," + +static unsigned int debug; +module_param(debug,int,0644); +MODULE_PARM_DESC(debug,"enable debug messages"); + +/**************************************************************************** + Module specific funtions + ****************************************************************************/ +/* Constants taken from cx88-reg.h */ +#define AUD_INT_DN_RISCI1 (1 << 0) +#define AUD_INT_UP_RISCI1 (1 << 1) +#define AUD_INT_RDS_DN_RISCI1 (1 << 2) +#define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */ +#define AUD_INT_UP_RISCI2 (1 << 5) +#define AUD_INT_RDS_DN_RISCI2 (1 << 6) +#define AUD_INT_DN_SYNC (1 << 12) +#define AUD_INT_UP_SYNC (1 << 13) +#define AUD_INT_RDS_DN_SYNC (1 << 14) +#define AUD_INT_OPC_ERR (1 << 16) +#define AUD_INT_BER_IRQ (1 << 20) +#define AUD_INT_MCHG_IRQ (1 << 21) +#define GP_COUNT_CONTROL_RESET 0x3 + +#define PCI_MSK_AUD_EXT (1 << 4) +#define PCI_MSK_AUD_INT (1 << 3) +/* + * BOARD Specific: Sets audio DMA + */ + +static int _cx25821_start_audio_dma(snd_cx25821_card_t *chip) +{ + struct cx25821_buffer *buf = chip->buf; + struct cx25821_dev * dev = chip->dev; + struct sram_channel *audio_ch = &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]; + u32 tmp = 0; + + // enable output on the GPIO 0 for the MCLK ADC (Audio) + cx25821_set_gpiopin_direction( chip->dev, 0, 0 ); + + /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ + cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN ); + + /* setup fifo + format - out channel */ + cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl, buf->risc.dma); + + /* sets bpl size */ + cx_write(AUD_A_LNGTH, buf->bpl); + + /* reset counter */ + cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); //GP_COUNT_CONTROL_RESET = 0x3 + atomic_set(&chip->count, 0); + + //Set the input mode to 16-bit + tmp = cx_read(AUD_A_CFG); + cx_write(AUD_A_CFG, tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | FLD_AUD_CLK_ENABLE); + + //printk(KERN_INFO "DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d " + // "byte buffer\n", buf->bpl, audio_ch->cmds_start, cx_read(audio_ch->cmds_start + 12)>>1, + // chip->num_periods, buf->bpl * chip->num_periods); + + + /* Enables corresponding bits at AUD_INT_STAT */ + cx_write(AUD_A_INT_MSK, FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC | FLD_AUD_DST_OPC_ERR ); + + /* Clean any pending interrupt bits already set */ + cx_write(AUD_A_INT_STAT, ~0); + + /* enable audio irqs */ + cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT); + + // Turn on audio downstream fifo and risc enable 0x101 + tmp = cx_read(AUD_INT_DMA_CTL); + cx_set(AUD_INT_DMA_CTL, tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN) ); + + mdelay(100); + return 0; +} + +/* + * BOARD Specific: Resets audio DMA + */ +static int _cx25821_stop_audio_dma(snd_cx25821_card_t *chip) +{ + struct cx25821_dev *dev = chip->dev; + + /* stop dma */ + cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN ); + + /* disable irqs */ + cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT); + cx_clear(AUD_A_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); + + return 0; +} + +#define MAX_IRQ_LOOP 50 + +/* + * BOARD Specific: IRQ dma bits + */ +static char *cx25821_aud_irqs[32] = { + "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ + NULL, /* reserved */ + "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ + NULL, /* reserved */ + "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ + NULL, /* reserved */ + "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ + NULL, /* reserved */ + "opc_err", "par_err", "rip_err", /* 16-18 */ + "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ +}; + +/* + * BOARD Specific: Threats IRQ audio specific calls + */ +static void cx25821_aud_irq(snd_cx25821_card_t *chip, u32 status, u32 mask) +{ + struct cx25821_dev *dev = chip->dev; + + if (0 == (status & mask)) + { + return; + } + + cx_write(AUD_A_INT_STAT, status); + if (debug > 1 || (status & mask & ~0xff)) + cx25821_print_irqbits(dev->name, "irq aud", + cx25821_aud_irqs, ARRAY_SIZE(cx25821_aud_irqs), + status, mask); + + /* risc op code error */ + if (status & AUD_INT_OPC_ERR) { + printk(KERN_WARNING "WARNING %s/1: Audio risc op code error\n",dev->name); + + cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN ); + cx25821_sram_channel_dump_audio(dev, &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]); + } + if (status & AUD_INT_DN_SYNC) { + printk(KERN_WARNING "WARNING %s: Downstream sync error!\n",dev->name); + cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); + return; + } + + + /* risc1 downstream */ + if (status & AUD_INT_DN_RISCI1) { + atomic_set(&chip->count, cx_read(AUD_A_GPCNT)); + snd_pcm_period_elapsed(chip->substream); + } +} + + +/* + * BOARD Specific: Handles IRQ calls + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +static irqreturn_t cx25821_irq(int irq, void *dev_id, struct pt_regs *regs) +#else +static irqreturn_t cx25821_irq(int irq, void *dev_id) +#endif +{ + snd_cx25821_card_t *chip = dev_id; + struct cx25821_dev *dev = chip->dev; + u32 status, pci_status; + u32 audint_status, audint_mask; + int loop, handled = 0; + int audint_count = 0; + + + audint_status = cx_read(AUD_A_INT_STAT); + audint_mask = cx_read(AUD_A_INT_MSK); + audint_count = cx_read(AUD_A_GPCNT); + status = cx_read(PCI_INT_STAT); + + for (loop = 0; loop < 1; loop++) + { + status = cx_read(PCI_INT_STAT); + if (0 == status) + { + status = cx_read(PCI_INT_STAT); + audint_status = cx_read(AUD_A_INT_STAT); + audint_mask = cx_read(AUD_A_INT_MSK); + + if (status) + { + handled = 1; + cx_write(PCI_INT_STAT, status); + + cx25821_aud_irq(chip, audint_status, audint_mask); + break; + } + else + goto out; + } + + handled = 1; + cx_write(PCI_INT_STAT, status); + + cx25821_aud_irq(chip, audint_status, audint_mask); + } + + pci_status = cx_read(PCI_INT_STAT); + + if (handled) + cx_write(PCI_INT_STAT, pci_status); + + out: + return IRQ_RETVAL(handled); +} + + +static int dsp_buffer_free(snd_cx25821_card_t *chip) +{ + BUG_ON(!chip->dma_size); + + dprintk(2,"Freeing buffer\n"); + videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc); + videobuf_dma_free(chip->dma_risc); + btcx_riscmem_free(chip->pci,&chip->buf->risc); + kfree(chip->buf); + + chip->dma_risc = NULL; + chip->dma_size = 0; + + return 0; +} + +/**************************************************************************** + ALSA PCM Interface + ****************************************************************************/ + +/* + * Digital hardware definition + */ +#if 1 +#define DEFAULT_FIFO_SIZE 384 +static struct snd_pcm_hardware snd_cx25821_digital_hw = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + /* Analog audio output will be full of clicks and pops if there + are not exactly four lines in the SRAM FIFO buffer. */ + .period_bytes_min = DEFAULT_FIFO_SIZE/3, + .period_bytes_max = DEFAULT_FIFO_SIZE/3, + .periods_min = 1, + .periods_max = AUDIO_LINE_SIZE, + .buffer_bytes_max = (AUDIO_LINE_SIZE*AUDIO_LINE_SIZE), //128*128 = 16384 = 1024 * 16 +}; +#endif + + + +/* + * audio pcm capture open callback + */ +static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) +{ + snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int err; + unsigned int bpl = 0; + + if (!chip) { + printk(KERN_ERR "DEBUG: cx25821 can't find device struct." + " Can't proceed with open\n"); + return -ENODEV; + } + + err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) + goto _error; + + chip->substream = substream; + + runtime->hw = snd_cx25821_digital_hw; + + if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size != DEFAULT_FIFO_SIZE) + { + bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3; //since there are 3 audio Clusters + bpl &= ~7; /* must be multiple of 8 */ + + if( bpl > AUDIO_LINE_SIZE ) + { + bpl = AUDIO_LINE_SIZE; + } + runtime->hw.period_bytes_min = bpl; + runtime->hw.period_bytes_max = bpl; + } + + return 0; +_error: + dprintk(1,"Error opening PCM!\n"); + return err; +} + +/* + * audio close callback + */ +static int snd_cx25821_close(struct snd_pcm_substream *substream) +{ + return 0; +} + +/* + * hw_params callback + */ +static int snd_cx25821_hw_params(struct snd_pcm_substream * substream, + struct snd_pcm_hw_params * hw_params) +{ + snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); + struct videobuf_dmabuf *dma; + + struct cx25821_buffer *buf; + int ret; + + if (substream->runtime->dma_area) { + dsp_buffer_free(chip); + substream->runtime->dma_area = NULL; + } + + + chip->period_size = params_period_bytes(hw_params); + chip->num_periods = params_periods(hw_params); + chip->dma_size = chip->period_size * params_periods(hw_params); + + BUG_ON(!chip->dma_size); + BUG_ON(chip->num_periods & (chip->num_periods-1)); + + buf = videobuf_sg_alloc(sizeof(*buf)); + if (NULL == buf) + return -ENOMEM; + + + if( chip->period_size > AUDIO_LINE_SIZE ) + { + chip->period_size = AUDIO_LINE_SIZE; + } + + + buf->vb.memory = V4L2_MEMORY_MMAP; + buf->vb.field = V4L2_FIELD_NONE; + buf->vb.width = chip->period_size; + buf->bpl = chip->period_size; + buf->vb.height = chip->num_periods; + buf->vb.size = chip->dma_size; + + dma = videobuf_to_dma(&buf->vb); + videobuf_dma_init(dma); + + ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, + (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); + if (ret < 0) + goto error; + + ret = videobuf_sg_dma_map(&chip->pci->dev, dma); + if (ret < 0) + goto error; + + + ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist, buf->vb.width, buf->vb.height, 1); + if (ret < 0) + { + printk(KERN_INFO "DEBUG: ERROR after cx25821_risc_databuffer_audio() \n"); + goto error; + } + + + /* Loop back to start of program */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + buf->vb.state = VIDEOBUF_PREPARED; + + chip->buf = buf; + chip->dma_risc = dma; + + substream->runtime->dma_area = chip->dma_risc->vmalloc; + substream->runtime->dma_bytes = chip->dma_size; + substream->runtime->dma_addr = 0; + + return 0; + +error: + kfree(buf); + return ret; +} + +/* + * hw free callback + */ +static int snd_cx25821_hw_free(struct snd_pcm_substream * substream) +{ + snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); + + if (substream->runtime->dma_area) { + dsp_buffer_free(chip); + substream->runtime->dma_area = NULL; + } + + return 0; +} + +/* + * prepare callback + */ +static int snd_cx25821_prepare(struct snd_pcm_substream *substream) +{ + return 0; +} + +/* + * trigger callback + */ +static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream, int cmd) +{ + snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); + int err = 0; + + /* Local interrupts are already disabled by ALSA */ + spin_lock(&chip->reg_lock); + + switch (cmd) + { + case SNDRV_PCM_TRIGGER_START: + err = _cx25821_start_audio_dma(chip); + break; + case SNDRV_PCM_TRIGGER_STOP: + err = _cx25821_stop_audio_dma(chip); + break; + default: + err = -EINVAL; + break; + } + + spin_unlock(&chip->reg_lock); + + return err; +} + +/* + * pointer callback + */ +static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream *substream) +{ + snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + u16 count; + + count = atomic_read(&chip->count); + + return runtime->period_size * (count & (runtime->periods-1)); +} + +/* + * page callback (needed for mmap) + */ +static struct page *snd_cx25821_page(struct snd_pcm_substream *substream, + unsigned long offset) +{ + void *pageptr = substream->runtime->dma_area + offset; + + return vmalloc_to_page(pageptr); +} + +/* + * operators + */ +static struct snd_pcm_ops snd_cx25821_pcm_ops = { + .open = snd_cx25821_pcm_open, + .close = snd_cx25821_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_cx25821_hw_params, + .hw_free = snd_cx25821_hw_free, + .prepare = snd_cx25821_prepare, + .trigger = snd_cx25821_card_trigger, + .pointer = snd_cx25821_pointer, + .page = snd_cx25821_page, +}; + + +/* + * ALSA create a PCM device: Called when initializing the board. Sets up the name and hooks up + * the callbacks + */ +static int snd_cx25821_pcm(snd_cx25821_card_t *chip, int device, char *name) +{ + struct snd_pcm *pcm; + int err; + + err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); + if (err < 0) + { + printk(KERN_INFO "ERROR: FAILED snd_pcm_new() in %s\n", __func__); + return err; + } + pcm->private_data = chip; + pcm->info_flags = 0; + strcpy(pcm->name, name); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops); + + return 0; +} + + +/**************************************************************************** + Basic Flow for Sound Devices + ****************************************************************************/ + +/* + * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio + * Only boards with eeprom and byte 1 at eeprom=1 have it + */ + +static struct pci_device_id cx25821_audio_pci_tbl[] __devinitdata = { + {0x14f1,0x0920,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, + {0, } +}; +MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl); + +/* + * Not used in the function snd_cx25821_dev_free so removing + * from the file. + */ +/* +static int snd_cx25821_free(snd_cx25821_card_t *chip) +{ + if (chip->irq >= 0) + free_irq(chip->irq, chip); + + cx25821_dev_unregister(chip->dev); + pci_disable_device(chip->pci); + + return 0; +} +*/ + +/* + * Component Destructor + */ +static void snd_cx25821_dev_free(struct snd_card * card) +{ + snd_cx25821_card_t *chip = card->private_data; + + //snd_cx25821_free(chip); + snd_card_free(chip->card); +} + + +/* + * Alsa Constructor - Component probe + */ +static int cx25821_audio_initdev(struct cx25821_dev *dev) +{ + struct snd_card *card; + snd_cx25821_card_t *chip; + int err; + + if (devno >= SNDRV_CARDS) + { + printk(KERN_INFO "DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__); + return (-ENODEV); + } + + if (!enable[devno]) { + ++devno; + printk(KERN_INFO "DEBUG ERROR: !enable[devno] %s\n", __func__); + return (-ENOENT); + } + + card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx25821_card_t)); + if (!card) + { + printk(KERN_INFO "DEBUG ERROR: cannot create snd_card_new in %s\n", __func__); + return (-ENOMEM); + } + + strcpy(card->driver, "cx25821"); + + /* Card "creation" */ + card->private_free = snd_cx25821_dev_free; + chip = (snd_cx25821_card_t *) card->private_data; + spin_lock_init(&chip->reg_lock); + + chip->dev = dev; + chip->card = card; + chip->pci = dev->pci; + chip->iobase = pci_resource_start(dev->pci, 0); + + + chip->irq = dev->pci->irq; + + err = request_irq(dev->pci->irq, cx25821_irq, + IRQF_SHARED | IRQF_DISABLED, chip->dev->name, chip); + + if (err < 0) { + printk(KERN_ERR "ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name, dev->pci->irq); + goto error; + } + + + if ((err = snd_cx25821_pcm(chip, 0, "cx25821 Digital")) < 0) + { + printk(KERN_INFO "DEBUG ERROR: cannot create snd_cx25821_pcm %s\n", __func__); + goto error; + } + + snd_card_set_dev(card, &chip->pci->dev); + + + strcpy(card->shortname, "cx25821"); + sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name, chip->iobase, chip->irq); + strcpy (card->mixername, "CX25821"); + + printk(KERN_INFO "%s/%i: ALSA support for cx25821 boards\n", card->driver, devno); + + err = snd_card_register(card); + if (err < 0) + { + printk(KERN_INFO "DEBUG ERROR: cannot register sound card %s\n", __func__); + goto error; + } + + snd_cx25821_cards[devno] = card; + + devno++; + return 0; + +error: + snd_card_free(card); + return err; +} + + +/**************************************************************************** + LINUX MODULE INIT + ****************************************************************************/ +static void cx25821_audio_fini(void) +{ + snd_card_free(snd_cx25821_cards[0]); +} + +/* + * Module initializer + * + * Loops through present saa7134 cards, and assigns an ALSA device + * to each one + * + */ +static int cx25821_alsa_init(void) +{ + struct cx25821_dev *dev = NULL; + struct list_head *list; + + list_for_each(list,&cx25821_devlist) { + dev = list_entry(list, struct cx25821_dev, devlist); + cx25821_audio_initdev(dev); + } + + if (dev == NULL) + printk(KERN_INFO "cx25821 ERROR ALSA: no cx25821 cards found\n"); + + return 0; + +} + +late_initcall(cx25821_alsa_init); +module_exit(cx25821_audio_fini); + +/* ----------------------------------------------------------- */ +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/linux/drivers/staging/cx25821/cx25821-audio-upstream.c b/linux/drivers/staging/cx25821/cx25821-audio-upstream.c new file mode 100644 index 000000000..fa9057f8b --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-audio-upstream.c @@ -0,0 +1,825 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "cx25821-video.h" +#include "cx25821-audio-upstream.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); +MODULE_AUTHOR("Hiep Huynh "); +MODULE_LICENSE("GPL"); + + +static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR; + + +int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, + struct sram_channel *ch, + unsigned int bpl, u32 risc) +{ + unsigned int i, lines; + u32 cdt; + + + if (ch->cmds_start == 0) { + cx_write(ch->ptr1_reg, 0); + cx_write(ch->ptr2_reg, 0); + cx_write(ch->cnt2_reg, 0); + cx_write(ch->cnt1_reg, 0); + return 0; + } + + bpl = (bpl + 7) & ~7; /* alignment */ + cdt = ch->cdt; + lines = ch->fifo_size / bpl; + + if (lines > 3) + { + lines = 3; + } + + BUG_ON(lines < 2); + + + /* write CDT */ + for (i = 0; i < lines; i++) { + cx_write(cdt + 16*i, ch->fifo_start + bpl*i); + cx_write(cdt + 16*i + 4, 0); + cx_write(cdt + 16*i + 8, 0); + cx_write(cdt + 16*i + 12, 0); + } + + /* write CMDS */ + cx_write(ch->cmds_start + 0, risc); + + cx_write(ch->cmds_start + 4, 0); + cx_write(ch->cmds_start + 8, cdt); + cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW); + cx_write(ch->cmds_start + 16, ch->ctrl_start); + + //IQ size + cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW); + + for (i = 24; i < 80; i += 4) + cx_write(ch->cmds_start + i, 0); + + /* fill registers */ + cx_write(ch->ptr1_reg, ch->fifo_start); + cx_write(ch->ptr2_reg, cdt); + cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW); + cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1); + + return 0; +} + + +static __le32 *cx25821_risc_field_upstream_audio( struct cx25821_dev *dev, __le32 *rp, + dma_addr_t databuf_phys_addr, + unsigned int bpl, int fifo_enable) +{ + unsigned int line; + struct sram_channel *sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select]; + int offset = 0; + + + /* scan lines */ + for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) + { + *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); + *(rp++) = cpu_to_le32(databuf_phys_addr + offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + // Check if we need to enable the FIFO after the first 3 lines + // For the upstream audio channel, the risc engine will enable the FIFO. + if ( fifo_enable && line == 2 ) + { + *(rp++) = RISC_WRITECR; + *(rp++) = sram_ch->dma_ctl; + *(rp++) = sram_ch->fld_aud_fifo_en; + *(rp++) = 0x00000020; + } + + offset += AUDIO_LINE_SIZE; + } + + return rp; +} + +int cx25821_risc_buffer_upstream_audio( struct cx25821_dev *dev, + struct pci_dev *pci, + unsigned int bpl, unsigned int lines) +{ + __le32 *rp; + int fifo_enable = 0; + int frame = 0, i = 0; + int frame_size = AUDIO_DATA_BUF_SZ; + int databuf_offset = 0; + int risc_flag = RISC_CNT_INC; + dma_addr_t risc_phys_jump_addr; + + + /* Virtual address of Risc buffer program */ + rp = dev->_risc_virt_addr; + + /* sync instruction */ + *(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE); + + + for( frame = 0; frame < NUM_AUDIO_FRAMES; frame++ ) + { + databuf_offset = frame_size * frame; + + if( frame == 0 ) + { + fifo_enable = 1; + risc_flag = RISC_CNT_RESET; + } + else + { + fifo_enable = 0; + risc_flag = RISC_CNT_INC; + } + + //Calculate physical jump address + if( (frame+1) == NUM_AUDIO_FRAMES ) + { + risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE; + } + else + { + risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE*(frame+1); + } + + rp = cx25821_risc_field_upstream_audio(dev, rp, dev->_audiodata_buf_phys_addr+databuf_offset, bpl, fifo_enable); + + + if( USE_RISC_NOOP_AUDIO ) + { + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + + // Loop to (Nth)FrameRISC or to Start of Risc program & generate IRQ + *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + + //Recalculate virtual address based on frame index + rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE/4 + (AUDIO_RISC_DMA_BUF_SIZE*(frame+1)/4 ) ; + } + + return 0; +} + + +void cx25821_free_memory_audio(struct cx25821_dev *dev) +{ + if (dev->_risc_virt_addr) + { + pci_free_consistent(dev->pci, dev->_audiorisc_size, dev->_risc_virt_addr, dev->_risc_phys_addr); + dev->_risc_virt_addr = NULL; + } + + if (dev->_audiodata_buf_virt_addr) + { + pci_free_consistent(dev->pci, dev->_audiodata_buf_size, dev->_audiodata_buf_virt_addr, dev->_audiodata_buf_phys_addr); + dev->_audiodata_buf_virt_addr = NULL; + } +} + +void cx25821_stop_upstream_audio(struct cx25821_dev *dev) +{ + struct sram_channel *sram_ch = &dev->sram_channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B]; + u32 tmp = 0; + + if( !dev->_audio_is_running ) + { + printk("cx25821: No audio file is currently running so return!\n"); + return; + } + + //Disable RISC interrupts + cx_write( sram_ch->int_msk, 0 ); + + //Turn OFF risc and fifo enable in AUD_DMA_CNTRL + tmp = cx_read( sram_ch->dma_ctl ); + cx_write( sram_ch->dma_ctl, tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en) ); + + //Clear data buffer memory + if( dev->_audiodata_buf_virt_addr ) + memset( dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size ); + + dev->_audio_is_running = 0; + dev->_is_first_audio_frame = 0; + dev->_audioframe_count = 0; + dev->_audiofile_status = END_OF_FILE; + + if( dev->_irq_audio_queues ) + { + kfree(dev->_irq_audio_queues); + dev->_irq_audio_queues = NULL; + } + + if( dev->_audiofilename != NULL ) + kfree(dev->_audiofilename); +} + + +void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev) +{ + if( dev->_audio_is_running ) + { + cx25821_stop_upstream_audio(dev); + } + + cx25821_free_memory_audio(dev); +} + + +int cx25821_get_audio_data(struct cx25821_dev *dev, struct sram_channel *sram_ch ) +{ + struct file * myfile; + int frame_index_temp = dev->_audioframe_index; + int i = 0; + int line_size = AUDIO_LINE_SIZE; + int frame_size = AUDIO_DATA_BUF_SZ; + int frame_offset = frame_size * frame_index_temp; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t file_offset = dev->_audioframe_count * frame_size; + loff_t pos; + mm_segment_t old_fs; + + + if( dev->_audiofile_status == END_OF_FILE ) + return 0; + + myfile = filp_open( dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0 ); + + + if (IS_ERR(myfile)) + { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno); + return PTR_ERR(myfile); + } + else + { + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered!\n", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered! \n", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( i = 0; i < dev->_audio_lines_count; i++ ) + { + pos = file_offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL ) + { + memcpy( (void*)(dev->_audiodata_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval); + } + + file_offset += vfs_read_retval; + frame_offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + dev->_audioframe_count++; + + dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + + set_fs(old_fs); + filp_close(myfile, NULL); + } + + return 0; +} + +static void cx25821_audioups_handler(struct work_struct *work) +{ + struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _audio_work_entry); + + if( !dev ) + { + printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); + return; + } + + cx25821_get_audio_data( dev, &dev->sram_channels[dev->_audio_upstream_channel_select] ); +} + +int cx25821_openfile_audio(struct cx25821_dev *dev, struct sram_channel *sram_ch) +{ + struct file * myfile; + int i = 0, j = 0; + int line_size = AUDIO_LINE_SIZE; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t pos; + loff_t offset = (unsigned long)0; + mm_segment_t old_fs; + + + myfile = filp_open( dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0 ); + + + if (IS_ERR(myfile)) + { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno); + return PTR_ERR(myfile); + } + else + { + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered! \n", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered! \n", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( j = 0; j < NUM_AUDIO_FRAMES; j++ ) + { + for( i = 0; i < dev->_audio_lines_count; i++ ) + { + pos = offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL ) + { + memcpy( (void*)(dev->_audiodata_buf_virt_addr+offset/4), mybuf, vfs_read_retval); + } + + offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + { + dev->_audioframe_count++; + } + + if( vfs_read_retval < line_size ) + { + break; + } + } + + dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + myfile->f_pos = 0; + filp_close(myfile, NULL); + } + + return 0; +} + +static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, + struct sram_channel *sram_ch, + int bpl) +{ + int ret = 0; + dma_addr_t dma_addr; + dma_addr_t data_dma_addr; + + + cx25821_free_memory_audio(dev); + + dev->_risc_virt_addr = pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size, &dma_addr); + dev->_risc_virt_start_addr = dev->_risc_virt_addr; + dev->_risc_phys_start_addr = dma_addr; + dev->_risc_phys_addr = dma_addr; + dev->_audiorisc_size = dev->audio_upstream_riscbuf_size; + + + if (!dev->_risc_virt_addr) + { + printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n"); + return -ENOMEM; + } + + //Clear out memory at address + memset( dev->_risc_virt_addr, 0, dev->_audiorisc_size ); + + + //For Audio Data buffer allocation + dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size, &data_dma_addr); + dev->_audiodata_buf_phys_addr = data_dma_addr; + dev->_audiodata_buf_size = dev->audio_upstream_databuf_size; + + if (!dev->_audiodata_buf_virt_addr) + { + printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning. \n"); + return -ENOMEM; + } + + //Clear out memory at address + memset( dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size ); + + + ret = cx25821_openfile_audio(dev, sram_ch); + if( ret < 0 ) + return ret; + + + //Creating RISC programs + ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, dev->_audio_lines_count ); + if (ret < 0) + { + printk(KERN_DEBUG "cx25821 ERROR creating audio upstream RISC programs! \n"); + goto error; + } + + return 0; + +error: + return ret; +} + +int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, u32 status) +{ + int i = 0; + u32 int_msk_tmp; + struct sram_channel *channel = &dev->sram_channels[chan_num]; + dma_addr_t risc_phys_jump_addr; + __le32 * rp; + + + if (status & FLD_AUD_SRC_RISCI1) + { + //Get interrupt_index of the program that interrupted + u32 prog_cnt = cx_read( channel->gpcnt ); + + //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers + cx_write(channel->int_msk, 0); + cx_write(channel->int_stat, cx_read(channel->int_stat) ); + + spin_lock(&dev->slock); + + + while(prog_cnt != dev->_last_index_irq) + { + //Update _last_index_irq + if(dev->_last_index_irq < (NUMBER_OF_PROGRAMS-1)) + { + dev->_last_index_irq++; + } + else + { + dev->_last_index_irq = 0; + } + + dev->_audioframe_index = dev->_last_index_irq; + + queue_work(dev->_irq_audio_queues, &dev->_audio_work_entry); + } + + + if ( dev->_is_first_audio_frame ) + { + dev->_is_first_audio_frame = 0; + + if( dev->_risc_virt_start_addr != NULL ) + { + risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE; + + rp = cx25821_risc_field_upstream_audio(dev, dev->_risc_virt_start_addr+1, dev->_audiodata_buf_phys_addr, AUDIO_LINE_SIZE, FIFO_DISABLE); + + if( USE_RISC_NOOP_AUDIO ) + { + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + // Jump to 2nd Audio Frame + *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_RESET); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + } + + spin_unlock(&dev->slock); + } + else + { + if(status & FLD_AUD_SRC_OF) + printk("%s: Audio Received Overflow Error Interrupt!\n", __func__); + + if(status & FLD_AUD_SRC_SYNC) + printk("%s: Audio Received Sync Error Interrupt!\n", __func__); + + if(status & FLD_AUD_SRC_OPC_ERR) + printk("%s: Audio Received OpCode Error Interrupt!\n", __func__); + + // Read and write back the interrupt status register to clear our bits + cx_write(channel->int_stat, cx_read(channel->int_stat) ); + } + + + if( dev->_audiofile_status == END_OF_FILE ) + { + printk("cx25821: EOF Channel Audio Framecount = %d\n", dev->_audioframe_count ); + return -1; + } + + //ElSE, set the interrupt mask register, re-enable irq. + int_msk_tmp = cx_read( channel->int_msk ); + cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); + + return 0; +} + +static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) +{ + struct cx25821_dev *dev = dev_id; + u32 msk_stat, audio_status; + int handled = 0; + struct sram_channel *sram_ch; + + + if( !dev ) + return -1; + + + sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select]; + + msk_stat = cx_read(sram_ch->int_mstat); + audio_status = cx_read(sram_ch->int_stat); + + // Only deal with our interrupt + if(audio_status) + { + handled = cx25821_audio_upstream_irq(dev, dev->_audio_upstream_channel_select, audio_status); + } + + + if( handled < 0 ) + { + cx25821_stop_upstream_audio(dev); + } + else + { + handled += handled; + } + + return IRQ_RETVAL(handled); +} + + +static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, struct sram_channel *sram_ch) +{ + int count = 0; + u32 tmp; + + do + { + //Wait 10 microsecond before checking to see if the FIFO is turned ON. + udelay(10); + + tmp = cx_read( sram_ch->dma_ctl ); + + if(count++ > 1000) //10 millisecond timeout + { + printk("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", __func__); + return; + } + + } while( !(tmp & sram_ch->fld_aud_fifo_en) ); + +} + + +int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, + struct sram_channel *sram_ch) +{ + u32 tmp = 0; + int err = 0; + + + // Set the physical start address of the RISC program in the initial program counter(IPC) member of the CMDS. + cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr); + cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ + + + /* reset counter */ + cx_write(sram_ch->gpcnt_ctl, 3); + + //Set the line length (It looks like we do not need to set the line length) + cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH); + + //Set the input mode to 16-bit + tmp = cx_read( sram_ch->aud_cfg ); + tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE; + cx_write( sram_ch->aud_cfg, tmp ); + + // Read and write back the interrupt status register to clear it + tmp = cx_read( sram_ch->int_stat); + cx_write( sram_ch->int_stat, tmp); + + // Clear our bits from the interrupt status register. + cx_write( sram_ch->int_stat, _intr_msk ); + + + //Set the interrupt mask register, enable irq. + cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); + tmp = cx_read( sram_ch->int_msk ); + cx_write( sram_ch->int_msk, tmp |= _intr_msk ); + + + err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); + if (err < 0) + { + printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); + goto fail_irq; + } + + + // Start the DMA engine + tmp = cx_read( sram_ch->dma_ctl ); + cx_set( sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en ); + + dev->_audio_is_running = 1; + dev->_is_first_audio_frame = 1; + + // The fifo_en bit turns on by the first Risc program + cx25821_wait_fifo_enable(dev, sram_ch); + + return 0; + + +fail_irq: + cx25821_dev_unregister(dev); + return err; +} + + +int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) +{ + struct sram_channel *sram_ch; + int retval = 0; + int err = 0; + int str_length = 0; + + if( dev->_audio_is_running ) + { + printk("Audio Channel is still running so return!\n"); + return 0; + } + + dev->_audio_upstream_channel_select = channel_select; + sram_ch = &dev->sram_channels[channel_select]; + + //Work queue + INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler); + dev->_irq_audio_queues = create_singlethread_workqueue("cx25821_audioworkqueue"); + + if(!dev->_irq_audio_queues) + { + printk("cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n"); + return -ENOMEM; + } + + + dev->_last_index_irq = 0; + dev->_audio_is_running = 0; + dev->_audioframe_count = 0; + dev->_audiofile_status = RESET_STATUS; + dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER; + _line_size = AUDIO_LINE_SIZE; + + + if( dev->input_audiofilename ) + { + str_length = strlen(dev->input_audiofilename); + dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_audiofilename ) + goto error; + + memcpy(dev->_audiofilename, dev->input_audiofilename, str_length + 1); + + //Default if filename is empty string + if( strcmp(dev->input_audiofilename,"") == 0) + { + dev->_audiofilename = "/root/audioGOOD.wav"; + } + } + else + { + str_length = strlen(_defaultAudioName); + dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_audiofilename ) + goto error; + + memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1); + } + + + retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch, _line_size, 0); + + dev->audio_upstream_riscbuf_size = AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS + RISC_SYNC_INSTRUCTION_SIZE; + dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS; + + + //Allocating buffers and prepare RISC program + retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch, _line_size); + if (retval < 0) + { + printk(KERN_ERR "%s: Failed to set up Audio upstream buffers!\n", dev->name); + goto error; + } + + //Start RISC engine + cx25821_start_audio_dma_upstream(dev, sram_ch); + + return 0; + +error: + cx25821_dev_unregister(dev); + + return err; +} + \ No newline at end of file diff --git a/linux/drivers/staging/cx25821/cx25821-audio-upstream.h b/linux/drivers/staging/cx25821/cx25821-audio-upstream.h new file mode 100644 index 000000000..a7120ee48 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-audio-upstream.h @@ -0,0 +1,63 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "compat.h" +#include +#include + + +#define NUM_AUDIO_PROGS 8 +#define NUM_AUDIO_FRAMES 8 +#define END_OF_FILE 0 +#define IN_PROGRESS 1 +#define RESET_STATUS -1 +#define FIFO_DISABLE 0 +#define FIFO_ENABLE 1 +#define NUM_NO_OPS 4 + + +#define RISC_READ_INSTRUCTION_SIZE 12 +#define RISC_JUMP_INSTRUCTION_SIZE 12 +#define RISC_WRITECR_INSTRUCTION_SIZE 16 +#define RISC_SYNC_INSTRUCTION_SIZE 4 +#define DWORD_SIZE 4 +#define AUDIO_SYNC_LINE 4 + + +#define LINES_PER_AUDIO_BUFFER 15 +#define AUDIO_LINE_SIZE 128 +#define AUDIO_DATA_BUF_SZ (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER) + +#define USE_RISC_NOOP_AUDIO 1 + +#ifdef USE_RISC_NOOP_AUDIO +#define AUDIO_RISC_DMA_BUF_SIZE ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE + RISC_JUMP_INSTRUCTION_SIZE) +#endif + + +#ifndef USE_RISC_NOOP_AUDIO +#define AUDIO_RISC_DMA_BUF_SIZE ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE) +#endif + +static int _line_size; +char * _defaultAudioName = "/root/audioGOOD.wav"; + diff --git a/linux/drivers/staging/cx25821/cx25821-audio.h b/linux/drivers/staging/cx25821/cx25821-audio.h new file mode 100644 index 000000000..1e1351800 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-audio.h @@ -0,0 +1,60 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __CX25821_AUDIO_H__ +#define __CX25821_AUDIO_H__ + + +#define USE_RISC_NOOP 1 +#define LINES_PER_BUFFER 15 +#define AUDIO_LINE_SIZE 128 + +//Number of buffer programs to use at once. +#define NUMBER_OF_PROGRAMS 8 + +//Max size of the RISC program for a buffer. - worst case is 2 writes per line +// Space is also added for the 4 no-op instructions added on the end. + +#ifndef USE_RISC_NOOP +#define MAX_BUFFER_PROGRAM_SIZE \ + (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE*4) +#endif + +// MAE 12 July 2005 Try to use NOOP RISC instruction instead +#ifdef USE_RISC_NOOP +#define MAX_BUFFER_PROGRAM_SIZE \ + (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_NOOP_INSTRUCTION_SIZE*4) +#endif + + +//Sizes of various instructions in bytes. Used when adding instructions. +#define RISC_WRITE_INSTRUCTION_SIZE 12 +#define RISC_JUMP_INSTRUCTION_SIZE 12 +#define RISC_SKIP_INSTRUCTION_SIZE 4 +#define RISC_SYNC_INSTRUCTION_SIZE 4 +#define RISC_WRITECR_INSTRUCTION_SIZE 16 +#define RISC_NOOP_INSTRUCTION_SIZE 4 + +#define MAX_AUDIO_DMA_BUFFER_SIZE (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE) + +#endif + diff --git a/linux/drivers/staging/cx25821/cx25821-audups11.c b/linux/drivers/staging/cx25821/cx25821-audups11.c new file mode 100644 index 000000000..a8e4dce88 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-audups11.c @@ -0,0 +1,441 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH11]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH11]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH11] && h->video_dev[SRAM_CH11]->minor == minor) + { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = 10; + fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); + + v4l2_prio_open(&dev->prio,&fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO11)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO11)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + return POLLIN|POLLRDNORM; + return 0; +} + + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + //stop the risc engine and fifo + //cx_write(channel11->dma_ctl, 0); + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO11)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO11); + } + + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO11)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO11); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vidq.field = f->fmt.pix.field; + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + return 0; +} + +static long video_ioctl_upstream11(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + int command = 0; + struct upstream_user_struct *data_from_user; + + + data_from_user = (struct upstream_user_struct *)arg; + + if( !data_from_user ) + { + printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); + return 0; + } + + command = data_from_user->command; + + if( command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO ) + { + return 0; + } + + + dev->input_filename = data_from_user->input_filename; + dev->input_audiofilename = data_from_user->input_filename; + dev->vid_stdname = data_from_user->vid_stdname; + dev->pixel_format = data_from_user->pixel_format; + dev->channel_select = data_from_user->channel_select; + dev->command = data_from_user->command; + + + switch(command) + { + case UPSTREAM_START_AUDIO: + cx25821_start_upstream_audio(dev, data_from_user); + break; + + case UPSTREAM_STOP_AUDIO: + cx25821_stop_upstream_audio(dev); + break; + } + + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct cx25821_fh *fh = priv; + return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); +} + +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + return 0; +} +// exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl_upstream11, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_video_template11 = { + .name = "cx25821-audioupstream", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821-biffuncs.h b/linux/drivers/staging/cx25821/cx25821-biffuncs.h new file mode 100644 index 000000000..da826cb34 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-biffuncs.h @@ -0,0 +1,45 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _BITFUNCS_H +#define _BITFUNCS_H + +#define SetBit(Bit) (1 << Bit) + +inline u8 getBit(u32 sample, u8 index) +{ + return (u8) ((sample >> index) & 1); +} + +inline u32 clearBitAtPos(u32 value, u8 bit) +{ + return value & ~(1 << bit); +} + +inline u32 setBitAtPos(u32 sample, u8 bit) +{ + sample |= (1 << bit); + return sample; + +} + +#endif \ No newline at end of file diff --git a/linux/drivers/staging/cx25821/cx25821-cards.c b/linux/drivers/staging/cx25821/cx25821-cards.c new file mode 100644 index 000000000..accd7d53a --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-cards.c @@ -0,0 +1,73 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "compat.h" +#include "cx25821.h" +#include "tuner-xc2028.h" + +// board config info + +struct cx25821_board cx25821_boards[] = { + [UNKNOWN_BOARD] = { + .name = "UNKNOWN/GENERIC", + // Ensure safe default for unknown boards + .clk_freq = 0, + }, + + [CX25821_BOARD] = { + .name = "CX25821", + .portb = CX25821_RAW, + .portc = CX25821_264, + .input[0].type = CX25821_VMUX_COMPOSITE, + }, + +}; + +const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards); + +struct cx25821_subid cx25821_subids[]={ + { + .subvendor = 0x14f1, + .subdevice = 0x0920, + .card = CX25821_BOARD, + }, +}; + + +void cx25821_card_setup(struct cx25821_dev *dev) +{ + static u8 eeprom[256]; + + if (dev->i2c_bus[0].i2c_rc == 0) + { + dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; + tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); + } +} + diff --git a/linux/drivers/staging/cx25821/cx25821-core.c b/linux/drivers/staging/cx25821/cx25821-core.c new file mode 100644 index 000000000..084bbb42c --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-core.c @@ -0,0 +1,1586 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include "cx25821.h" +#include "cx25821-sram.h" +#include "cx25821-video.h" + +MODULE_DESCRIPTION("Driver for Athena cards"); +MODULE_AUTHOR("Shu Lin - Hiep Huynh"); +MODULE_LICENSE("GPL"); + +struct list_head cx25821_devlist; + +static unsigned int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "enable debug messages"); + +static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; +module_param_array(card, int, NULL, 0444); +MODULE_PARM_DESC(card, "card type"); + + +static unsigned int cx25821_devcount = 0; + +static DEFINE_MUTEX(devlist); +LIST_HEAD(cx25821_devlist); + + +struct sram_channel cx25821_sram_channels[] = { + [SRAM_CH00] = { + .i = SRAM_CH00, + .name = "VID A", + .cmds_start = VID_A_DOWN_CMDS, + .ctrl_start = VID_A_IQ, + .cdt = VID_A_CDT, + .fifo_start = VID_A_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA1_PTR1, + .ptr2_reg = DMA1_PTR2, + .cnt1_reg = DMA1_CNT1, + .cnt2_reg = DMA1_CNT2, + .int_msk = VID_A_INT_MSK, + .int_stat = VID_A_INT_STAT, + .int_mstat = VID_A_INT_MSTAT, + .dma_ctl = VID_DST_A_DMA_CTL, + .gpcnt_ctl = VID_DST_A_GPCNT_CTL, + .gpcnt = VID_DST_A_GPCNT, + .vip_ctl = VID_DST_A_VIP_CTL, + .pix_frmt = VID_DST_A_PIX_FRMT, + }, + + [SRAM_CH01] = { + .i = SRAM_CH01, + .name = "VID B", + .cmds_start = VID_B_DOWN_CMDS, + .ctrl_start = VID_B_IQ, + .cdt = VID_B_CDT, + .fifo_start = VID_B_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA2_PTR1, + .ptr2_reg = DMA2_PTR2, + .cnt1_reg = DMA2_CNT1, + .cnt2_reg = DMA2_CNT2, + .int_msk = VID_B_INT_MSK, + .int_stat = VID_B_INT_STAT, + .int_mstat = VID_B_INT_MSTAT, + .dma_ctl = VID_DST_B_DMA_CTL, + .gpcnt_ctl = VID_DST_B_GPCNT_CTL, + .gpcnt = VID_DST_B_GPCNT, + .vip_ctl = VID_DST_B_VIP_CTL, + .pix_frmt = VID_DST_B_PIX_FRMT, + }, + + [SRAM_CH02] = { + .i = SRAM_CH02, + .name = "VID C", + .cmds_start = VID_C_DOWN_CMDS, + .ctrl_start = VID_C_IQ, + .cdt = VID_C_CDT, + .fifo_start = VID_C_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA3_PTR1, + .ptr2_reg = DMA3_PTR2, + .cnt1_reg = DMA3_CNT1, + .cnt2_reg = DMA3_CNT2, + .int_msk = VID_C_INT_MSK, + .int_stat = VID_C_INT_STAT, + .int_mstat = VID_C_INT_MSTAT, + .dma_ctl = VID_DST_C_DMA_CTL, + .gpcnt_ctl = VID_DST_C_GPCNT_CTL, + .gpcnt = VID_DST_C_GPCNT, + .vip_ctl = VID_DST_C_VIP_CTL, + .pix_frmt = VID_DST_C_PIX_FRMT, + }, + + [SRAM_CH03] = { + .i = SRAM_CH03, + .name = "VID D", + .cmds_start = VID_D_DOWN_CMDS, + .ctrl_start = VID_D_IQ, + .cdt = VID_D_CDT, + .fifo_start = VID_D_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA4_PTR1, + .ptr2_reg = DMA4_PTR2, + .cnt1_reg = DMA4_CNT1, + .cnt2_reg = DMA4_CNT2, + .int_msk = VID_D_INT_MSK, + .int_stat = VID_D_INT_STAT, + .int_mstat = VID_D_INT_MSTAT, + .dma_ctl = VID_DST_D_DMA_CTL, + .gpcnt_ctl = VID_DST_D_GPCNT_CTL, + .gpcnt = VID_DST_D_GPCNT, + .vip_ctl = VID_DST_D_VIP_CTL, + .pix_frmt = VID_DST_D_PIX_FRMT, + }, + + [SRAM_CH04] = { + .i = SRAM_CH04, + .name = "VID E", + .cmds_start = VID_E_DOWN_CMDS, + .ctrl_start = VID_E_IQ, + .cdt = VID_E_CDT, + .fifo_start = VID_E_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA5_PTR1, + .ptr2_reg = DMA5_PTR2, + .cnt1_reg = DMA5_CNT1, + .cnt2_reg = DMA5_CNT2, + .int_msk = VID_E_INT_MSK, + .int_stat = VID_E_INT_STAT, + .int_mstat = VID_E_INT_MSTAT, + .dma_ctl = VID_DST_E_DMA_CTL, + .gpcnt_ctl = VID_DST_E_GPCNT_CTL, + .gpcnt = VID_DST_E_GPCNT, + .vip_ctl = VID_DST_E_VIP_CTL, + .pix_frmt = VID_DST_E_PIX_FRMT, + }, + + [SRAM_CH05] = { + .i = SRAM_CH05, + .name = "VID F", + .cmds_start = VID_F_DOWN_CMDS, + .ctrl_start = VID_F_IQ, + .cdt = VID_F_CDT, + .fifo_start = VID_F_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA6_PTR1, + .ptr2_reg = DMA6_PTR2, + .cnt1_reg = DMA6_CNT1, + .cnt2_reg = DMA6_CNT2, + .int_msk = VID_F_INT_MSK, + .int_stat = VID_F_INT_STAT, + .int_mstat = VID_F_INT_MSTAT, + .dma_ctl = VID_DST_F_DMA_CTL, + .gpcnt_ctl = VID_DST_F_GPCNT_CTL, + .gpcnt = VID_DST_F_GPCNT, + .vip_ctl = VID_DST_F_VIP_CTL, + .pix_frmt = VID_DST_F_PIX_FRMT, + }, + + [SRAM_CH06] = { + .i = SRAM_CH06, + .name = "VID G", + .cmds_start = VID_G_DOWN_CMDS, + .ctrl_start = VID_G_IQ, + .cdt = VID_G_CDT, + .fifo_start = VID_G_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA7_PTR1, + .ptr2_reg = DMA7_PTR2, + .cnt1_reg = DMA7_CNT1, + .cnt2_reg = DMA7_CNT2, + .int_msk = VID_G_INT_MSK, + .int_stat = VID_G_INT_STAT, + .int_mstat = VID_G_INT_MSTAT, + .dma_ctl = VID_DST_G_DMA_CTL, + .gpcnt_ctl = VID_DST_G_GPCNT_CTL, + .gpcnt = VID_DST_G_GPCNT, + .vip_ctl = VID_DST_G_VIP_CTL, + .pix_frmt = VID_DST_G_PIX_FRMT, + }, + + [SRAM_CH07] = { + .i = SRAM_CH07, + .name = "VID H", + .cmds_start = VID_H_DOWN_CMDS, + .ctrl_start = VID_H_IQ, + .cdt = VID_H_CDT, + .fifo_start = VID_H_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA8_PTR1, + .ptr2_reg = DMA8_PTR2, + .cnt1_reg = DMA8_CNT1, + .cnt2_reg = DMA8_CNT2, + .int_msk = VID_H_INT_MSK, + .int_stat = VID_H_INT_STAT, + .int_mstat = VID_H_INT_MSTAT, + .dma_ctl = VID_DST_H_DMA_CTL, + .gpcnt_ctl = VID_DST_H_GPCNT_CTL, + .gpcnt = VID_DST_H_GPCNT, + .vip_ctl = VID_DST_H_VIP_CTL, + .pix_frmt = VID_DST_H_PIX_FRMT, + }, + + [SRAM_CH08] = { + .name = "audio from", + .cmds_start = AUD_A_DOWN_CMDS, + .ctrl_start = AUD_A_IQ, + .cdt = AUD_A_CDT, + .fifo_start = AUD_A_DOWN_CLUSTER_1, + .fifo_size = AUDIO_CLUSTER_SIZE * 3, + .ptr1_reg = DMA17_PTR1, + .ptr2_reg = DMA17_PTR2, + .cnt1_reg = DMA17_CNT1, + .cnt2_reg = DMA17_CNT2, + }, + + [SRAM_CH09] = { + .i = SRAM_CH09, + .name = "VID Upstream I", + .cmds_start = VID_I_UP_CMDS, + .ctrl_start = VID_I_IQ, + .cdt = VID_I_CDT, + .fifo_start = VID_I_UP_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA15_PTR1, + .ptr2_reg = DMA15_PTR2, + .cnt1_reg = DMA15_CNT1, + .cnt2_reg = DMA15_CNT2, + .int_msk = VID_I_INT_MSK, + .int_stat = VID_I_INT_STAT, + .int_mstat = VID_I_INT_MSTAT, + .dma_ctl = VID_SRC_I_DMA_CTL, + .gpcnt_ctl = VID_SRC_I_GPCNT_CTL, + .gpcnt = VID_SRC_I_GPCNT, + + .vid_fmt_ctl = VID_SRC_I_FMT_CTL, + .vid_active_ctl1= VID_SRC_I_ACTIVE_CTL1, + .vid_active_ctl2= VID_SRC_I_ACTIVE_CTL2, + .vid_cdt_size = VID_SRC_I_CDT_SZ, + .irq_bit = 8, + }, + + [SRAM_CH10] = { + .i = SRAM_CH10, + .name = "VID Upstream J", + .cmds_start = VID_J_UP_CMDS, + .ctrl_start = VID_J_IQ, + .cdt = VID_J_CDT, + .fifo_start = VID_J_UP_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA16_PTR1, + .ptr2_reg = DMA16_PTR2, + .cnt1_reg = DMA16_CNT1, + .cnt2_reg = DMA16_CNT2, + .int_msk = VID_J_INT_MSK, + .int_stat = VID_J_INT_STAT, + .int_mstat = VID_J_INT_MSTAT, + .dma_ctl = VID_SRC_J_DMA_CTL, + .gpcnt_ctl = VID_SRC_J_GPCNT_CTL, + .gpcnt = VID_SRC_J_GPCNT, + + .vid_fmt_ctl = VID_SRC_J_FMT_CTL, + .vid_active_ctl1= VID_SRC_J_ACTIVE_CTL1, + .vid_active_ctl2= VID_SRC_J_ACTIVE_CTL2, + .vid_cdt_size = VID_SRC_J_CDT_SZ, + .irq_bit = 9, + }, + + + [SRAM_CH11] = { + .i = SRAM_CH11, + .name = "Audio Upstream Channel B", + .cmds_start = AUD_B_UP_CMDS, + .ctrl_start = AUD_B_IQ, + .cdt = AUD_B_CDT, + .fifo_start = AUD_B_UP_CLUSTER_1, + .fifo_size = (AUDIO_CLUSTER_SIZE*3), + .ptr1_reg = DMA22_PTR1, + .ptr2_reg = DMA22_PTR2, + .cnt1_reg = DMA22_CNT1, + .cnt2_reg = DMA22_CNT2, + .int_msk = AUD_B_INT_MSK, + .int_stat = AUD_B_INT_STAT, + .int_mstat = AUD_B_INT_MSTAT, + .dma_ctl = AUD_INT_DMA_CTL, + .gpcnt_ctl = AUD_B_GPCNT_CTL, + .gpcnt = AUD_B_GPCNT, + .aud_length = AUD_B_LNGTH, + .aud_cfg = AUD_B_CFG, + .fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN, + .fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN, + .irq_bit = 11, + }, +}; + + +struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00]; +struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01]; +struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02]; +struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03]; +struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04]; +struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05]; +struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06]; +struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07]; +struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09]; +struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10]; +struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11]; + +struct cx25821_dmaqueue mpegq; + +static int cx25821_risc_decode(u32 risc) +{ + static char *instr[16] = { + [RISC_SYNC >> 28] = "sync", + [RISC_WRITE >> 28] = "write", + [RISC_WRITEC >> 28] = "writec", + [RISC_READ >> 28] = "read", + [RISC_READC >> 28] = "readc", + [RISC_JUMP >> 28] = "jump", + [RISC_SKIP >> 28] = "skip", + [RISC_WRITERM >> 28] = "writerm", + [RISC_WRITECM >> 28] = "writecm", + [RISC_WRITECR >> 28] = "writecr", + }; + static int incr[16] = { + [RISC_WRITE >> 28] = 3, + [RISC_JUMP >> 28] = 3, + [RISC_SKIP >> 28] = 1, + [RISC_SYNC >> 28] = 1, + [RISC_WRITERM >> 28] = 3, + [RISC_WRITECM >> 28] = 3, + [RISC_WRITECR >> 28] = 4, + }; + static char *bits[] = { + "12", "13", "14", "resync", + "cnt0", "cnt1", "18", "19", + "20", "21", "22", "23", + "irq1", "irq2", "eol", "sol", + }; + int i; + + printk("0x%08x [ %s", risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); + for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) + { + if (risc & (1 << (i + 12))) + printk(" %s", bits[i]); + } + printk(" count=%d ]\n", risc & 0xfff); + return incr[risc >> 28] ? incr[risc >> 28] : 1; +} + +static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap) +{ + struct cx25821_i2c *bus = i2c_adap->algo_data; + struct cx25821_dev *dev = bus->dev; + return cx_read(bus->reg_stat) & 0x01; +} + + +void cx_i2c_read_print(struct cx25821_dev *dev, u32 reg, const char* reg_string) +{ + int tmp = 0; + u32 value = 0; + + value = cx25821_i2c_read(&dev->i2c_bus[0], reg, &tmp); +} + +static void cx25821_registers_init(struct cx25821_dev *dev) +{ + u32 tmp; + + // enable RUN_RISC in Pecos + cx_write( DEV_CNTRL2, 0x20 ); + + // Set the master PCI interrupt masks to enable video, audio, MBIF, and GPIO interrupts + // I2C interrupt masking is handled by the I2C objects themselves. + cx_write( PCI_INT_MSK, 0x2001FFFF ); + + tmp = cx_read( RDR_TLCTL0 ); + tmp &= ~FLD_CFG_RCB_CK_EN; // Clear the RCB_CK_EN bit + cx_write( RDR_TLCTL0, tmp); + + // PLL-A setting for the Audio Master Clock + cx_write( PLL_A_INT_FRAC, 0x9807A58B ); + + // PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 + cx_write( PLL_A_POST_STAT_BIST, 0x8000019C); + + // clear reset bit [31] + tmp = cx_read( PLL_A_INT_FRAC ); + cx_write( PLL_A_INT_FRAC, tmp & 0x7FFFFFFF); + + // PLL-B setting for Mobilygen Host Bus Interface + cx_write( PLL_B_INT_FRAC, 0x9883A86F); + + // PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 + cx_write( PLL_B_POST_STAT_BIST, 0x8000018D); + + // clear reset bit [31] + tmp = cx_read( PLL_B_INT_FRAC ); + cx_write( PLL_B_INT_FRAC, tmp & 0x7FFFFFFF); + + // PLL-C setting for video upstream channel + cx_write( PLL_C_INT_FRAC, 0x96A0EA3F); + + // PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 + cx_write( PLL_C_POST_STAT_BIST, 0x80000103); + + // clear reset bit [31] + tmp = cx_read( PLL_C_INT_FRAC ); + cx_write( PLL_C_INT_FRAC, tmp & 0x7FFFFFFF); + + // PLL-D setting for audio upstream channel + cx_write( PLL_D_INT_FRAC, 0x98757F5B); + + // PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 + cx_write( PLL_D_POST_STAT_BIST, 0x80000113); + + // clear reset bit [31] + tmp = cx_read( PLL_D_INT_FRAC ); + cx_write( PLL_D_INT_FRAC, tmp & 0x7FFFFFFF); + + + // This selects the PLL C clock source for the video upstream channel I and J + tmp = cx_read( VID_CH_CLK_SEL ); + cx_write( VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000); + + + // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + //select 656/VIP DST for downstream Channel A - C + tmp = cx_read( VID_CH_MODE_SEL ); + //cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); + cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); + + + // enables 656 port I and J as output + tmp = cx_read( CLK_RST ); + tmp |= FLD_USE_ALT_PLL_REF; // use external ALT_PLL_REF pin as its reference clock instead + cx_write( CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE) ); + + mdelay(100); +} + + +int cx25821_sram_channel_setup(struct cx25821_dev *dev, + struct sram_channel *ch, + unsigned int bpl, u32 risc) +{ + unsigned int i, lines; + u32 cdt; + + if (ch->cmds_start == 0) { + cx_write(ch->ptr1_reg, 0); + cx_write(ch->ptr2_reg, 0); + cx_write(ch->cnt2_reg, 0); + cx_write(ch->cnt1_reg, 0); + return 0; + } + + bpl = (bpl + 7) & ~7; /* alignment */ + cdt = ch->cdt; + lines = ch->fifo_size / bpl; + + if (lines > 4) + { + lines = 4; + } + + BUG_ON(lines < 2); + + cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + cx_write(8 + 4, 8); + cx_write(8 + 8, 0); + + /* write CDT */ + for (i = 0; i < lines; i++) { + cx_write(cdt + 16*i, ch->fifo_start + bpl*i); + cx_write(cdt + 16*i + 4, 0); + cx_write(cdt + 16*i + 8, 0); + cx_write(cdt + 16*i + 12, 0); + } + + //init the first cdt buffer + for(i=0; i<128; i++) + cx_write(ch->fifo_start+4*i, i); + + /* write CMDS */ + if (ch->jumponly) + { + cx_write(ch->cmds_start + 0, 8); + } + else + { + cx_write(ch->cmds_start + 0, risc); + } + + cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ + cx_write(ch->cmds_start + 8, cdt); + cx_write(ch->cmds_start + 12, (lines*16) >> 3); + cx_write(ch->cmds_start + 16, ch->ctrl_start); + + if (ch->jumponly) + cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); + else + cx_write(ch->cmds_start + 20, 64 >> 2); + + for (i = 24; i < 80; i += 4) + cx_write(ch->cmds_start + i, 0); + + /* fill registers */ + cx_write(ch->ptr1_reg, ch->fifo_start); + cx_write(ch->ptr2_reg, cdt); + cx_write(ch->cnt2_reg, (lines*16) >> 3); + cx_write(ch->cnt1_reg, (bpl >> 3) - 1); + + return 0; +} + +int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, + struct sram_channel *ch, + unsigned int bpl, u32 risc) +{ + unsigned int i, lines; + u32 cdt; + + + if (ch->cmds_start == 0) { + cx_write(ch->ptr1_reg, 0); + cx_write(ch->ptr2_reg, 0); + cx_write(ch->cnt2_reg, 0); + cx_write(ch->cnt1_reg, 0); + return 0; + } + + bpl = (bpl + 7) & ~7; /* alignment */ + cdt = ch->cdt; + lines = ch->fifo_size / bpl; + + if (lines > 3) + { + lines = 3; //for AUDIO + } + + BUG_ON(lines < 2); + + + cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + cx_write(8 + 4, 8); + cx_write(8 + 8, 0); + + /* write CDT */ + for (i = 0; i < lines; i++) { + cx_write(cdt + 16*i, ch->fifo_start + bpl*i); + cx_write(cdt + 16*i + 4, 0); + cx_write(cdt + 16*i + 8, 0); + cx_write(cdt + 16*i + 12, 0); + } + + /* write CMDS */ + if (ch->jumponly) + { + cx_write(ch->cmds_start + 0, 8); + } + else + { + cx_write(ch->cmds_start + 0, risc); + } + + cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ + cx_write(ch->cmds_start + 8, cdt); + cx_write(ch->cmds_start + 12, (lines*16) >> 3); + cx_write(ch->cmds_start + 16, ch->ctrl_start); + + //IQ size + if (ch->jumponly) + { + cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); + } + else + { + cx_write(ch->cmds_start + 20, 64 >> 2); + } + + //zero out + for (i = 24; i < 80; i += 4) + cx_write(ch->cmds_start + i, 0); + + /* fill registers */ + cx_write(ch->ptr1_reg, ch->fifo_start); + cx_write(ch->ptr2_reg, cdt); + cx_write(ch->cnt2_reg, (lines*16) >> 3); + cx_write(ch->cnt1_reg, (bpl >> 3) - 1); + + return 0; +} + + +void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) +{ + static char *name[] = { + "init risc lo", + "init risc hi", + "cdt base", + "cdt size", + "iq base", + "iq size", + "risc pc lo", + "risc pc hi", + "iq wr ptr", + "iq rd ptr", + "cdt current", + "pci target lo", + "pci target hi", + "line / byte", + }; + u32 risc; + unsigned int i, j, n; + + printk(KERN_WARNING "%s: %s - dma channel status dump\n", dev->name, ch->name); + for (i = 0; i < ARRAY_SIZE(name); i++) + printk(KERN_WARNING "cmds + 0x%2x: %-15s: 0x%08x\n", i*4, name[i], + cx_read(ch->cmds_start + 4*i)); + + j=i*4; + for (i = 0; i < 4; ) { + risc = cx_read(ch->cmds_start + 4 * (i + 14)); + printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j+i*4, i); + i +=cx25821_risc_decode(risc); + } + + for (i = 0; i < (64 >> 2); i += n) { + risc = cx_read(ch->ctrl_start + 4 * i); + /* No consideration for bits 63-32 */ + + printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i); + n = cx25821_risc_decode(risc); + for (j = 1; j < n; j++) { + risc = cx_read(ch->ctrl_start + 4 * (i + j)); + printk(KERN_WARNING "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j); + } + } + + printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", ch->fifo_start, ch->fifo_start+ch->fifo_size); + printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", ch->ctrl_start, ch->ctrl_start + 6*16); + printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", cx_read(ch->ptr1_reg)); + printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", cx_read(ch->ptr2_reg)); + printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", cx_read(ch->cnt1_reg)); + printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", cx_read(ch->cnt2_reg)); +} + +void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channel *ch) +{ + static char *name[] = { + "init risc lo", + "init risc hi", + "cdt base", + "cdt size", + "iq base", + "iq size", + "risc pc lo", + "risc pc hi", + "iq wr ptr", + "iq rd ptr", + "cdt current", + "pci target lo", + "pci target hi", + "line / byte", + }; + + u32 risc, value, tmp; + unsigned int i, j, n; + + + printk(KERN_INFO "\n%s: %s - dma Audio channel status dump\n", dev->name, ch->name); + + for (i = 0; i < ARRAY_SIZE(name); i++) + printk(KERN_INFO "%s: cmds + 0x%2x: %-15s: 0x%08x\n", dev->name, i*4, name[i], cx_read(ch->cmds_start + 4*i)); + + + j=i*4; + for (i = 0; i < 4; ) { + risc = cx_read(ch->cmds_start + 4 * (i + 14)); + printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j+i*4, i); + i += cx25821_risc_decode(risc); + } + + for (i = 0; i < (64 >> 2); i += n) { + risc = cx_read(ch->ctrl_start + 4 * i); + /* No consideration for bits 63-32 */ + + printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i); + n = cx25821_risc_decode(risc); + + for (j = 1; j < n; j++) { + risc = cx_read(ch->ctrl_start + 4 * (i + j)); + printk(KERN_WARNING "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j); + } + } + + printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", ch->fifo_start, ch->fifo_start+ch->fifo_size); + printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", ch->ctrl_start, ch->ctrl_start + 6*16); + printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", cx_read(ch->ptr1_reg)); + printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", cx_read(ch->ptr2_reg)); + printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", cx_read(ch->cnt1_reg)); + printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", cx_read(ch->cnt2_reg)); + + for( i=0; i < 4; i++) + { + risc = cx_read(ch->cmds_start + 56 + (i*4)); + printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc); + } + + //read data from the first cdt buffer + risc = cx_read(AUD_A_CDT); + printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc); + for(i=0; i<8; i++) + { + n = cx_read(risc+i*4); + printk(KERN_WARNING "0x%x ", n); + } + printk(KERN_WARNING "\n\n"); + + + value = cx_read(CLK_RST); + CX25821_INFO(" CLK_RST = 0x%x \n\n", value); + + value = cx_read(PLL_A_POST_STAT_BIST); + CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x \n\n", value); + value = cx_read(PLL_A_INT_FRAC); + CX25821_INFO(" PLL_A_INT_FRAC = 0x%x \n\n", value); + + value = cx_read(PLL_B_POST_STAT_BIST); + CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x \n\n", value); + value = cx_read(PLL_B_INT_FRAC); + CX25821_INFO(" PLL_B_INT_FRAC = 0x%x \n\n", value); + + value = cx_read(PLL_C_POST_STAT_BIST); + CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x \n\n", value); + value = cx_read(PLL_C_INT_FRAC); + CX25821_INFO(" PLL_C_INT_FRAC = 0x%x \n\n", value); + + value = cx_read(PLL_D_POST_STAT_BIST); + CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x \n\n", value); + value = cx_read(PLL_D_INT_FRAC); + CX25821_INFO(" PLL_D_INT_FRAC = 0x%x \n\n", value); + + value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); + CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x \n\n", value); +} + +static void cx25821_shutdown(struct cx25821_dev *dev) +{ + int i; + + /* disable RISC controller */ + cx_write(DEV_CNTRL2, 0); + + /* Disable Video A/B activity */ + for(i=0; isram_channels[i].dma_ctl, 0); + cx_write(dev->sram_channels[i].int_msk, 0); + } + + for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) + { + cx_write(dev->sram_channels[i].dma_ctl, 0); + cx_write(dev->sram_channels[i].int_msk, 0); + } + + /* Disable Audio activity */ + cx_write(AUD_INT_DMA_CTL, 0); + + /* Disable Serial port */ + cx_write(UART_CTL, 0); + + /* Disable Interrupts */ + cx_write(PCI_INT_MSK, 0); + cx_write(AUD_A_INT_MSK, 0); +} + +void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, u32 format) +{ + struct sram_channel *ch; + + if( channel_select <= 7 && channel_select >= 0 ) + { + ch = &cx25821_sram_channels[channel_select]; + cx_write(ch->pix_frmt, format); + dev->pixel_formats[channel_select] = format; + } +} + +static void cx25821_set_vip_mode(struct cx25821_dev *dev, struct sram_channel *ch) +{ + cx_write(ch->pix_frmt, PIXEL_FRMT_422); + cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1); +} + +static void cx25821_initialize(struct cx25821_dev *dev) +{ + int i; + + dprintk(1, "%s()\n", __func__); + + cx25821_shutdown(dev); + cx_write(PCI_INT_STAT, 0xffffffff); + + for(i=0; isram_channels[i].int_stat, 0xffffffff); + + + cx_write(AUD_A_INT_STAT, 0xffffffff); + cx_write(AUD_B_INT_STAT, 0xffffffff); + cx_write(AUD_C_INT_STAT, 0xffffffff); + cx_write(AUD_D_INT_STAT, 0xffffffff); + cx_write(AUD_E_INT_STAT, 0xffffffff); + + cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000); + cx_write(PAD_CTRL, 0x12); //for I2C + cx25821_registers_init(dev); //init Pecos registers + mdelay(100); + + + for(i=0; isram_channels[i]); + cx25821_sram_channel_setup(dev, &dev->sram_channels[i], 1440, 0); + dev->pixel_formats[i] = PIXEL_FRMT_422; + dev->use_cif_resolution[i] = FALSE; + } + + //Probably only affect Downstream + for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) + { + cx25821_set_vip_mode(dev, &dev->sram_channels[i]); + } + + cx25821_sram_channel_setup_audio(dev, &dev->sram_channels[SRAM_CH08], 128, 0); + + cx25821_gpio_init(dev); +} + +static int get_resources(struct cx25821_dev *dev) +{ + if (request_mem_region(pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0), dev->name)) + return 0; + + printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n", + dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); + + return -EBUSY; +} + + +static void cx25821_dev_checkrevision(struct cx25821_dev *dev) +{ + dev->hwrevision = cx_read(RDR_CFG2) & 0xff; + + printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", __func__, dev->hwrevision); +} + +static void cx25821_iounmap(struct cx25821_dev *dev) +{ + if (dev == NULL) + return; + + /* Releasing IO memory */ + if (dev->lmmio != NULL) + { + CX25821_INFO("Releasing lmmio.\n"); + iounmap(dev->lmmio); + dev->lmmio = NULL; + } +} + + +static int cx25821_dev_setup(struct cx25821_dev *dev) +{ + int io_size = 0, i; + + struct video_device *video_template[] = { + &cx25821_video_template0, + &cx25821_video_template1, + &cx25821_video_template2, + &cx25821_video_template3, + &cx25821_video_template4, + &cx25821_video_template5, + &cx25821_video_template6, + &cx25821_video_template7, + &cx25821_video_template9, + &cx25821_video_template10, + &cx25821_video_template11, + &cx25821_videoioctl_template, + }; + + printk(KERN_INFO "\n***********************************\n"); + printk(KERN_INFO "cx25821 set up\n"); + printk(KERN_INFO "***********************************\n\n"); + + mutex_init(&dev->lock); + + atomic_inc(&dev->refcount); + + dev->nr = ++cx25821_devcount; + sprintf(dev->name, "cx25821[%d]", dev->nr); + + mutex_lock(&devlist); + list_add_tail(&dev->devlist, &cx25821_devlist); + mutex_unlock(&devlist); + + strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown"); + strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); + + + if( dev->pci->device != 0x8210 ) + { + printk(KERN_INFO "%s() Exiting. Incorrect Hardware device = 0x%02x\n", + __func__, dev->pci->device); + return -1; + } + else + { + printk(KERN_INFO "Athena Hardware device = 0x%02x\n", dev->pci->device); + } + + /* Apply a sensible clock frequency for the PCIe bridge */ + dev->clk_freq = 28000000; + dev->sram_channels = cx25821_sram_channels; + + if(dev->nr > 1) + { + CX25821_INFO("dev->nr > 1!"); + } + + /* board config */ + dev->board = 1; //card[dev->nr]; + dev->_max_num_decoders = MAX_DECODERS; + + + dev->pci_bus = dev->pci->bus->number; + dev->pci_slot = PCI_SLOT(dev->pci->devfn); + dev->pci_irqmask = 0x001f00; + + /* External Master 1 Bus */ + dev->i2c_bus[0].nr = 0; + dev->i2c_bus[0].dev = dev; + dev->i2c_bus[0].reg_stat = I2C1_STAT; + dev->i2c_bus[0].reg_ctrl = I2C1_CTRL; + dev->i2c_bus[0].reg_addr = I2C1_ADDR; + dev->i2c_bus[0].reg_rdata = I2C1_RDATA; + dev->i2c_bus[0].reg_wdata = I2C1_WDATA; + dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */ + + +#if 0 + /* External Master 2 Bus */ + dev->i2c_bus[1].nr = 1; + dev->i2c_bus[1].dev = dev; + dev->i2c_bus[1].reg_stat = I2C2_STAT; + dev->i2c_bus[1].reg_ctrl = I2C2_CTRL; + dev->i2c_bus[1].reg_addr = I2C2_ADDR; + dev->i2c_bus[1].reg_rdata = I2C2_RDATA; + dev->i2c_bus[1].reg_wdata = I2C2_WDATA; + dev->i2c_bus[1].i2c_period = (0x27 << 24); /* 100kHz */ + + /* Internal Master 3 Bus */ + dev->i2c_bus[2].nr = 2; + dev->i2c_bus[2].dev = dev; + dev->i2c_bus[2].reg_stat = I2C3_STAT; + dev->i2c_bus[2].reg_ctrl = I2C3_CTRL; + dev->i2c_bus[2].reg_addr = I2C3_ADDR; + dev->i2c_bus[2].reg_rdata = I2C3_RDATA; + dev->i2c_bus[2].reg_wdata = I2C3_WDATA; + dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */ +#endif + + if (get_resources(dev) < 0) + { + printk(KERN_ERR "%s No more PCIe resources for " + "subsystem: %04x:%04x\n", + dev->name, dev->pci->subsystem_vendor, + dev->pci->subsystem_device); + + cx25821_devcount--; + return -ENODEV; + } + + /* PCIe stuff */ + dev->base_io_addr = pci_resource_start(dev->pci, 0); + io_size = pci_resource_len(dev->pci, 0); + + if (!dev->base_io_addr) { + CX25821_ERR("No PCI Memory resources, exiting!\n"); + return -ENODEV; + } + + dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0)); + + if (!dev->lmmio) { + CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); + cx25821_iounmap(dev); + return -ENOMEM; + } + + + dev->bmmio = (u8 __iomem *)dev->lmmio; + + printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + dev->name, dev->pci->subsystem_vendor, + dev->pci->subsystem_device, cx25821_boards[dev->board].name, + dev->board, card[dev->nr] == dev->board ? + "insmod option" : "autodetected"); + + /* init hardware */ + cx25821_initialize(dev); + + cx25821_i2c_register(&dev->i2c_bus[0]); +// cx25821_i2c_register(&dev->i2c_bus[1]); +// cx25821_i2c_register(&dev->i2c_bus[2]); + + CX25821_INFO("i2c register! bus->i2c_rc = %d\n", dev->i2c_bus[0].i2c_rc); + + cx25821_card_setup(dev); + medusa_video_init(dev); + + for(i = 0; i < VID_CHANNEL_NUM; i++) + { + if (cx25821_video_register(dev, i, video_template[i]) < 0) { + printk(KERN_ERR "%s() Failed to register analog video adapters on VID channel %d\n", __func__, i); + } + } + + + for(i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) + { + //Since we don't have template8 for Audio Downstream + if (cx25821_video_register(dev, i, video_template[i-1]) < 0) { + printk(KERN_ERR "%s() Failed to register analog video adapters for Upstream channel %d.\n", __func__, i); + } + } + + // register IOCTL device + dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH], "video"); + + if( video_register_device(dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0 ) + { + cx25821_videoioctl_unregister(dev); + printk(KERN_ERR "%s() Failed to register video adapter for IOCTL so releasing.\n", __func__); + } + + cx25821_dev_checkrevision(dev); + CX25821_INFO("cx25821 setup done!\n"); + + return 0; +} + + +void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, struct upstream_user_struct *up_data) +{ + dev->_isNTSC = !strcmp(dev->vid_stdname,"NTSC") ? 1 : 0; + + dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; + medusa_set_videostandard(dev); + + cx25821_vidupstream_init_ch1(dev, dev->channel_select, dev->pixel_format); +} + + +void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, struct upstream_user_struct *up_data) +{ + dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2,"NTSC") ? 1 : 0; + + dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; + medusa_set_videostandard(dev); + + cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2, dev->pixel_format_ch2); +} + + +void cx25821_start_upstream_audio(struct cx25821_dev *dev, struct upstream_user_struct *up_data) +{ + cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B); +} + +void cx25821_dev_unregister(struct cx25821_dev *dev) +{ + int i; + + if (!dev->base_io_addr) + return; + + cx25821_free_mem_upstream_ch1(dev); + cx25821_free_mem_upstream_ch2(dev); + cx25821_free_mem_upstream_audio(dev); + + release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); + + if (!atomic_dec_and_test(&dev->refcount)) + return; + + for(i=0; i < VID_CHANNEL_NUM; i++) + cx25821_video_unregister(dev, i); + + + for(i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) + { + cx25821_video_unregister(dev, i); + } + + cx25821_videoioctl_unregister(dev); + + cx25821_i2c_unregister( &dev->i2c_bus[0] ); + cx25821_iounmap(dev); +} + + + +static __le32 *cx25821_risc_field(__le32 *rp, struct scatterlist *sglist, + unsigned int offset, u32 sync_line, + unsigned int bpl, unsigned int padding, + unsigned int lines) +{ + struct scatterlist *sg; + unsigned int line, todo; + + /* sync instruction */ + if (sync_line != NO_SYNC_LINE) + { + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + } + + /* scan lines */ + sg = sglist; + for (line = 0; line < lines; line++) { + while (offset && offset >= sg_dma_len(sg)) { + offset -= sg_dma_len(sg); + sg++; + } + if (bpl <= sg_dma_len(sg)-offset) { + /* fits into current chunk */ + *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); + *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + offset += bpl; + } else { + /* scanline needs to be split */ + todo = bpl; + *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|(sg_dma_len(sg)-offset)); + *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + todo -= (sg_dma_len(sg)-offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++) = cpu_to_le32(RISC_WRITE|sg_dma_len(sg)); + *(rp++) = cpu_to_le32(sg_dma_address(sg)); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + todo -= sg_dma_len(sg); + sg++; + } + *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo); + *(rp++) = cpu_to_le32(sg_dma_address(sg)); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + offset += todo; + } + + offset += padding; + } + + return rp; +} + +int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, + struct scatterlist *sglist, unsigned int top_offset, + unsigned int bottom_offset, unsigned int bpl, + unsigned int padding, unsigned int lines) +{ + u32 instructions; + u32 fields; + __le32 *rp; + int rc; + + fields = 0; + if (UNSET != top_offset) + fields++; + if (UNSET != bottom_offset) + fields++; + + /* estimate risc mem: worst case is one write per page border + + one write per scan line + syncs + jump (all 2 dwords). Padding + can cause next bpl to start close to a page border. First DMA + region may be smaller than PAGE_SIZE */ + /* write and jump need and extra dword */ + instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); + instructions += 2; + rc = btcx_riscmem_alloc(pci, risc, instructions*12); + + if (rc < 0) + return rc; + + /* write risc instructions */ + rp = risc->cpu; + + if (UNSET != top_offset) + { + rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding, lines); + } + + if (UNSET != bottom_offset) + { + rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl, padding, lines); + } + + /* save pointer to jmp instruction address */ + risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); + + return 0; +} + + +static __le32* cx25821_risc_field_audio(__le32 *rp, struct scatterlist *sglist, + unsigned int offset, u32 sync_line, + unsigned int bpl, unsigned int padding, + unsigned int lines, unsigned int lpi) +{ + struct scatterlist *sg; + unsigned int line, todo, sol; + + /* sync instruction */ + if (sync_line != NO_SYNC_LINE) + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + + /* scan lines */ + sg = sglist; + for (line = 0; line < lines; line++) { + while (offset && offset >= sg_dma_len(sg)) { + offset -= sg_dma_len(sg); + sg++; + } + + if (lpi && line > 0 && !(line % lpi)) + sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; + else + sol = RISC_SOL; + + if (bpl <= sg_dma_len(sg)-offset) { + /* fits into current chunk */ + *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl); + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + *(rp++)=cpu_to_le32(0); /* bits 63-32 */ + offset+=bpl; + } else { + /* scanline needs to be split */ + todo = bpl; + *(rp++) = cpu_to_le32(RISC_WRITE|sol| + (sg_dma_len(sg)-offset)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + *(rp++)=cpu_to_le32(0); /* bits 63-32 */ + todo -= (sg_dma_len(sg)-offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++)=cpu_to_le32(RISC_WRITE| + sg_dma_len(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(0); /* bits 63-32 */ + todo -= sg_dma_len(sg); + sg++; + } + *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(0); /* bits 63-32 */ + offset += todo; + } + offset += padding; + } + + return rp; +} + +int cx25821_risc_databuffer_audio(struct pci_dev *pci, + struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int bpl, + unsigned int lines, + unsigned int lpi) +{ + u32 instructions; + __le32 *rp; + int rc; + + /* estimate risc mem: worst case is one write per page border + + one write per scan line + syncs + jump (all 2 dwords). Here + there is no padding and no sync. First DMA region may be smaller + than PAGE_SIZE */ + /* Jump and write need an extra dword */ + instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; + instructions += 1; + + if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0) + return rc; + + + /* write risc instructions */ + rp = risc->cpu; + rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi); + + /* save pointer to jmp instruction address */ + risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); + return 0; +} + + +int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,u32 reg, u32 mask, u32 value) +{ + __le32 *rp; + int rc; + + rc = btcx_riscmem_alloc(pci, risc, 4*16); + + if (rc < 0) + return rc; + + /* write risc instructions */ + rp = risc->cpu; + + *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1); + *(rp++) = cpu_to_le32(reg); + *(rp++) = cpu_to_le32(value); + *(rp++) = cpu_to_le32(mask); + *(rp++) = cpu_to_le32(RISC_JUMP); + *(rp++) = cpu_to_le32(risc->dma); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + return 0; +} + +void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf) +{ + struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); + + BUG_ON(in_interrupt()); + videobuf_waiton(&buf->vb, 0, 0); + videobuf_dma_unmap(q, dma); + videobuf_dma_free(dma); + btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); + buf->vb.state = VIDEOBUF_NEEDS_INIT; +} + + +static irqreturn_t cx25821_irq(int irq, void *dev_id) +{ + struct cx25821_dev *dev = dev_id; + u32 pci_status, pci_mask; + u32 vid_status; + int i, handled = 0; + u32 mask[8] = {1, 2, 4, 8, 16, 32, 64, 128}; + + pci_status = cx_read(PCI_INT_STAT); + pci_mask = cx_read(PCI_INT_MSK); + + + if (pci_status == 0) + goto out; + + for(i = 0; i < VID_CHANNEL_NUM; i++) + { + if(pci_status & mask[i]) + { + vid_status = cx_read(dev->sram_channels[i].int_stat); + + if(vid_status) + handled += cx25821_video_irq(dev, i, vid_status); + + cx_write(PCI_INT_STAT, mask[i]); + } + } + +out: + return IRQ_RETVAL(handled); +} + +void cx25821_print_irqbits(char *name, char *tag, char **strings, + int len, u32 bits, u32 mask) +{ + unsigned int i; + + printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits); + + for (i = 0; i < len; i++) { + if (!(bits & (1 << i))) + continue; + if (strings[i]) + printk(" %s", strings[i]); + else + printk(" %d", i); + if (!(mask & (1 << i))) + continue; + printk("*"); + } + printk("\n"); +} + +struct cx25821_dev* cx25821_dev_get(struct pci_dev *pci) +{ + struct cx25821_dev *dev = pci_get_drvdata(pci); + return dev; +} + +static int __devinit cx25821_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) +{ + struct cx25821_dev *dev; + int err = 0; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (NULL == dev) + return -ENOMEM; + + + err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); + if (err < 0) + goto fail_free; + + /* pci init */ + dev->pci = pci_dev; + if (pci_enable_device(pci_dev)) + { + err = -EIO; + + printk(KERN_INFO "pci enable failed! "); + + goto fail_unregister_device; + } + + printk(KERN_INFO "cx25821 Athena pci enable ! \n"); + + if (cx25821_dev_setup(dev) < 0) + { + err = -EINVAL; + goto fail_unregister_device; + } + + /* print pci info */ + pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); + pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); + printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " + "latency: %d, mmio: 0x%llx\n", dev->name, + pci_name(pci_dev), dev->pci_rev, pci_dev->irq, + dev->pci_lat, + (unsigned long long)dev->base_io_addr ); + + + pci_set_master(pci_dev); + if (!pci_dma_supported(pci_dev, 0xffffffff)) + { + printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); + err = -EIO; + goto fail_irq; + } + + err = request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); + + if (err < 0) + { + printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name, pci_dev->irq); + goto fail_irq; + } + + return 0; + +fail_irq: + printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ ! \n"); + cx25821_dev_unregister(dev); + +fail_unregister_device: + v4l2_device_unregister(&dev->v4l2_dev); + +fail_free: + kfree(dev); + return err; +} + +static void __devexit cx25821_finidev(struct pci_dev *pci_dev) +{ + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct cx25821_dev *dev = get_cx25821(v4l2_dev); + + cx25821_shutdown(dev); + pci_disable_device(pci_dev); + + /* unregister stuff */ + if( pci_dev->irq ) + free_irq(pci_dev->irq, dev); + + + mutex_lock(&devlist); + list_del(&dev->devlist); + mutex_unlock(&devlist); + + cx25821_dev_unregister(dev); + v4l2_device_unregister(v4l2_dev); + kfree(dev); +} + +static struct pci_device_id cx25821_pci_tbl[] = { + { + /* CX25821 Athena*/ + .vendor = 0x14f1, + .device = 0x8210, + .subvendor = 0x14f1, + .subdevice = 0x0920, + }, + { + /* --- end of list --- */ + } +}; + +MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl); + +static struct pci_driver cx25821_pci_driver = +{ + .name = "cx25821", + .id_table = cx25821_pci_tbl, + .probe = cx25821_initdev, + .remove = __devexit_p(cx25821_finidev), + /* TODO */ + .suspend = NULL, + .resume = NULL, +}; + +static int cx25821_init(void) +{ + INIT_LIST_HEAD(&cx25821_devlist); + printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n", + (CX25821_VERSION_CODE >> 16) & 0xff, + (CX25821_VERSION_CODE >> 8) & 0xff, + CX25821_VERSION_CODE & 0xff); + return pci_register_driver(&cx25821_pci_driver); +} + +static void cx25821_fini(void) +{ + pci_unregister_driver(&cx25821_pci_driver); +} + + +EXPORT_SYMBOL(cx25821_devlist); +EXPORT_SYMBOL(cx25821_sram_channels); +EXPORT_SYMBOL(cx25821_print_irqbits); +EXPORT_SYMBOL(cx25821_dev_get); +EXPORT_SYMBOL(cx25821_dev_unregister); +EXPORT_SYMBOL(cx25821_sram_channel_setup); +EXPORT_SYMBOL(cx25821_sram_channel_dump); +EXPORT_SYMBOL(cx25821_sram_channel_setup_audio); +EXPORT_SYMBOL(cx25821_sram_channel_dump_audio); +EXPORT_SYMBOL(cx25821_risc_databuffer_audio); +EXPORT_SYMBOL(cx25821_set_gpiopin_direction); + +module_init(cx25821_init); +module_exit(cx25821_fini); + diff --git a/linux/drivers/staging/cx25821/cx25821-gpio.c b/linux/drivers/staging/cx25821/cx25821-gpio.c new file mode 100644 index 000000000..aa029fe34 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-gpio.c @@ -0,0 +1,116 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821.h" + + +/********************* GPIO stuffs *********************/ +void cx25821_set_gpiopin_direction( struct cx25821_dev *dev, + int pin_number, + int pin_logic_value) +{ + int bit = pin_number; + u32 gpio_oe_reg = GPIO_LO_OE; + u32 gpio_register = 0; + u32 value = 0; + + // Check for valid pinNumber + if ( pin_number >= 47 ) + return; + + + if ( pin_number > 31 ) + { + bit = pin_number - 31; + gpio_oe_reg = GPIO_HI_OE; + } + + // Here we will make sure that the GPIOs 0 and 1 are output. keep the rest as is + gpio_register = cx_read( gpio_oe_reg ); + + if (pin_logic_value == 1) + { + value = gpio_register | Set_GPIO_Bit(bit) ; + } + else + { + value = gpio_register & Clear_GPIO_Bit(bit) ; + } + + cx_write( gpio_oe_reg, value ); +} + +static void cx25821_set_gpiopin_logicvalue( struct cx25821_dev *dev, + int pin_number, + int pin_logic_value) +{ + int bit = pin_number; + u32 gpio_reg = GPIO_LO; + u32 value = 0; + + + // Check for valid pinNumber + if (pin_number >= 47) + return; + + cx25821_set_gpiopin_direction(dev, pin_number, 0); // change to output direction + + + if ( pin_number > 31 ) + { + bit = pin_number - 31; + gpio_reg = GPIO_HI; + } + + value = cx_read( gpio_reg ); + + + if (pin_logic_value == 0) + { + value &= Clear_GPIO_Bit(bit); + } + else + { + value |= Set_GPIO_Bit(bit); + } + + cx_write( gpio_reg, value); +} + +void cx25821_gpio_init(struct cx25821_dev *dev) +{ + if( dev == NULL ) + { + return; + } + + switch (dev->board) + { + case CX25821_BOARD_CONEXANT_ATHENA10: + default: + //set GPIO 5 to select the path for Medusa/Athena + cx25821_set_gpiopin_logicvalue(dev, 5, 1); + mdelay(20); + break; + } + +} diff --git a/linux/drivers/staging/cx25821/cx25821-gpio.h b/linux/drivers/staging/cx25821/cx25821-gpio.h new file mode 100644 index 000000000..2dd938dbd --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-gpio.h @@ -0,0 +1,3 @@ + +void cx25821_gpio_init(struct athena_dev *dev); + diff --git a/linux/drivers/staging/cx25821/cx25821-i2c.c b/linux/drivers/staging/cx25821/cx25821-i2c.c new file mode 100644 index 000000000..de1a9a8b9 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-i2c.c @@ -0,0 +1,485 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821.h" +#include + + +static unsigned int i2c_debug; +module_param(i2c_debug, int, 0644); +MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); + +static unsigned int i2c_scan=0; +module_param(i2c_scan, int, 0444); +MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); + +#define dprintk(level, fmt, arg...)\ + do { if (i2c_debug >= level)\ + printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ + } while (0) + +#define I2C_WAIT_DELAY 32 +#define I2C_WAIT_RETRY 64 + +#define I2C_EXTEND (1 << 3) +#define I2C_NOSTOP (1 << 4) + + +static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap) +{ + struct cx25821_i2c *bus = i2c_adap->algo_data; + struct cx25821_dev *dev = bus->dev; + return cx_read(bus->reg_stat) & 0x01; +} + +static inline int i2c_is_busy(struct i2c_adapter *i2c_adap) +{ + struct cx25821_i2c *bus = i2c_adap->algo_data; + struct cx25821_dev *dev = bus->dev; + return cx_read(bus->reg_stat) & 0x02 ? 1 : 0; +} + +static int i2c_wait_done(struct i2c_adapter *i2c_adap) +{ + int count; + + for (count = 0; count < I2C_WAIT_RETRY; count++) { + if (!i2c_is_busy(i2c_adap)) + break; + udelay(I2C_WAIT_DELAY); + } + + if (I2C_WAIT_RETRY == count) + return 0; + + return 1; +} + +static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg, int joined_rlen) +{ + struct cx25821_i2c *bus = i2c_adap->algo_data; + struct cx25821_dev *dev = bus->dev; + u32 wdata, addr, ctrl; + int retval, cnt; + + if (joined_rlen) + dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__, msg->len, joined_rlen); + else + dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len); + + /* Deal with i2c probe functions with zero payload */ + if (msg->len == 0) + { + cx_write(bus->reg_addr, msg->addr << 25); + cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2)); + + if (!i2c_wait_done(i2c_adap)) + return -EIO; + + if (!i2c_slave_did_ack(i2c_adap)) + return -EIO; + + dprintk(1, "%s() returns 0\n", __func__); + return 0; + } + + /* dev, reg + first byte */ + addr = (msg->addr << 25) | msg->buf[0]; + wdata = msg->buf[0]; + + ctrl = bus->i2c_period | (1 << 12) | (1 << 2); + + if (msg->len > 1) + ctrl |= I2C_NOSTOP | I2C_EXTEND; + else if (joined_rlen) + ctrl |= I2C_NOSTOP; + + cx_write(bus->reg_addr, addr); + cx_write(bus->reg_wdata, wdata); + cx_write(bus->reg_ctrl, ctrl); + + retval = i2c_wait_done(i2c_adap); + if (retval < 0) + goto err; + + if (retval == 0) + goto eio; + + if (i2c_debug) + { + if (!(ctrl & I2C_NOSTOP)) + printk(" >\n"); + } + + for (cnt = 1; cnt < msg->len; cnt++) { + /* following bytes */ + wdata = msg->buf[cnt]; + ctrl = bus->i2c_period | (1 << 12) | (1 << 2); + + if (cnt < msg->len - 1) + ctrl |= I2C_NOSTOP | I2C_EXTEND; + else if (joined_rlen) + ctrl |= I2C_NOSTOP; + + cx_write(bus->reg_addr, addr); + cx_write(bus->reg_wdata, wdata); + cx_write(bus->reg_ctrl, ctrl); + + retval = i2c_wait_done(i2c_adap); + if (retval < 0) + goto err; + + if (retval == 0) + goto eio; + + if (i2c_debug) + { + dprintk(1, " %02x", msg->buf[cnt]); + if (!(ctrl & I2C_NOSTOP)) + dprintk(1, " >\n"); + } + } + + return msg->len; + + eio: + retval = -EIO; + err: + if (i2c_debug) + printk(KERN_ERR " ERR: %d\n", retval); + return retval; +} + +static int i2c_readbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg, int joined) +{ + struct cx25821_i2c *bus = i2c_adap->algo_data; + struct cx25821_dev *dev = bus->dev; + u32 ctrl, cnt; + int retval; + + + if (i2c_debug && !joined) + dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len); + + /* Deal with i2c probe functions with zero payload */ + if (msg->len == 0) { + cx_write(bus->reg_addr, msg->addr << 25); + cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1); + if (!i2c_wait_done(i2c_adap)) + return -EIO; + if (!i2c_slave_did_ack(i2c_adap)) + return -EIO; + + + dprintk(1, "%s() returns 0\n", __func__); + return 0; + } + + if (i2c_debug) { + if (joined) + dprintk(1, " R"); + else + dprintk(1, " addr << 1) + 1); + } + + for (cnt = 0; cnt < msg->len; cnt++) { + + ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1; + + if (cnt < msg->len - 1) + ctrl |= I2C_NOSTOP | I2C_EXTEND; + + + cx_write(bus->reg_addr, msg->addr << 25); + cx_write(bus->reg_ctrl, ctrl); + + retval = i2c_wait_done(i2c_adap); + if (retval < 0) + goto err; + if (retval == 0) + goto eio; + msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff; + + if (i2c_debug) { + dprintk(1, " %02x", msg->buf[cnt]); + if (!(ctrl & I2C_NOSTOP)) + dprintk(1, " >\n"); + } + } + + return msg->len; + eio: + retval = -EIO; + err: + if (i2c_debug) + printk(KERN_ERR " ERR: %d\n", retval); + return retval; +} + +static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) +{ + struct cx25821_i2c *bus = i2c_adap->algo_data; + struct cx25821_dev *dev = bus->dev; + int i, retval = 0; + + dprintk(1, "%s(num = %d)\n", __func__, num); + + for (i = 0 ; i < num; i++) + { + dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n", + __func__, num, msgs[i].addr, msgs[i].len); + + if (msgs[i].flags & I2C_M_RD) + { + /* read */ + retval = i2c_readbytes(i2c_adap, &msgs[i], 0); + } + else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && + msgs[i].addr == msgs[i + 1].addr) + { + /* write then read from same address */ + retval = i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len); + + if (retval < 0) + goto err; + i++; + retval = i2c_readbytes(i2c_adap, &msgs[i], 1); + } + else + { + /* write */ + retval = i2c_sendbytes(i2c_adap, &msgs[i], 0); + } + + if (retval < 0) + goto err; + } + return num; + + err: + return retval; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) +static int attach_inform(struct i2c_client *client) +{ + struct cx25821_i2c *bus = i2c_get_adapdata(client->adapter); + struct cx25821_dev *dev = bus->dev; + + printk(KERN_INFO "attach: %s i2c attach [addr=0x%x,client=%s]\n", + client->driver->driver.name, client->addr, client->name); + + if (!client->driver->command) + return 0; + + if (dev->videc_type != UNSET) { + + printk(KERN_INFO "%s i2c attach [addr=0x%x,client=%s]\n", + client->driver->driver.name, client->addr, client->name); + + } + + + printk(KERN_INFO "attach done!\n"); + + return 0; +} + +static int detach_inform(struct i2c_client *client) +{ + struct cx25821_dev *dev = i2c_get_adapdata(client->adapter); + + dprintk(1, "i2c detach [client=%s]\n", client->name); + + return 0; +} + +void cx25821_call_i2c_clients(struct cx25821_i2c *bus, unsigned int cmd, void *arg) +{ + if (bus->i2c_rc != 0) + return; + + i2c_clients_command(&bus->i2c_adap, cmd, arg); +} +#endif + +static u32 cx25821_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL | + I2C_FUNC_I2C | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_READ_WORD_DATA | + I2C_FUNC_SMBUS_WRITE_WORD_DATA; +} + +static struct i2c_algorithm cx25821_i2c_algo_template = { + .master_xfer = i2c_xfer, + .functionality = cx25821_functionality, +#ifdef NEED_ALGO_CONTROL + .algo_control = dummy_algo_control, +#endif +}; + + +static struct i2c_adapter cx25821_i2c_adap_template = { + .name = "cx25821", + .owner = THIS_MODULE, + .id = I2C_HW_B_CX25821, + .algo = &cx25821_i2c_algo_template, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + .class = I2C_CLASS_TV_ANALOG, +#endif +}; + +static struct i2c_client cx25821_i2c_client_template = { + .name = "cx25821 internal", +}; + +/* init + register i2c algo-bit adapter */ +int cx25821_i2c_register(struct cx25821_i2c *bus) +{ + struct cx25821_dev *dev = bus->dev; + + dprintk(1, "%s(bus = %d)\n", __func__, bus->nr); + + memcpy(&bus->i2c_adap, &cx25821_i2c_adap_template, + sizeof(bus->i2c_adap)); + memcpy(&bus->i2c_algo, &cx25821_i2c_algo_template, + sizeof(bus->i2c_algo)); + memcpy(&bus->i2c_client, &cx25821_i2c_client_template, + sizeof(bus->i2c_client)); + + bus->i2c_adap.dev.parent = &dev->pci->dev; + + strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); + + bus->i2c_algo.data = bus; + bus->i2c_adap.algo_data = bus; + i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); + i2c_add_adapter(&bus->i2c_adap); + + bus->i2c_client.adapter = &bus->i2c_adap; + + //set up the I2c + bus->i2c_client.addr = (0x88>>1); + + return bus->i2c_rc; +} + +int cx25821_i2c_unregister(struct cx25821_i2c *bus) +{ + i2c_del_adapter(&bus->i2c_adap); + return 0; +} + +void cx25821_av_clk(struct cx25821_dev *dev, int enable) +{ + /* write 0 to bus 2 addr 0x144 via i2x_xfer() */ + char buffer[3]; + struct i2c_msg msg; + dprintk(1, "%s(enabled = %d)\n", __func__, enable); + + /* Register 0x144 */ + buffer[0] = 0x01; + buffer[1] = 0x44; + if (enable == 1) + buffer[2] = 0x05; + else + buffer[2] = 0x00; + + msg.addr = 0x44; + msg.flags = I2C_M_TEN; + msg.len = 3; + msg.buf = buffer; + + i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1); +} + + +int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value) +{ + struct i2c_client *client = &bus->i2c_client; + int retval = 0; + int v = 0; + u8 addr[2] = {0, 0}; + u8 buf[4] = {0,0,0,0}; + + struct i2c_msg msgs[2]={ + { + .addr = client->addr, + .flags = 0, + .len = 2, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 4, + .buf = buf, + } + }; + + + addr[0] = (reg_addr>>8); + addr[1] = (reg_addr & 0xff); + msgs[0].addr = 0x44; + msgs[1].addr = 0x44; + + retval = i2c_xfer(client->adapter, msgs, 2); + + v = (buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0]; + *value = v; + + return v; +} + + +int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value) +{ + struct i2c_client *client = &bus->i2c_client; + int retval = 0; + u8 buf[6] = {0, 0, 0, 0, 0, 0}; + + struct i2c_msg msgs[1]={ + { + .addr = client->addr, + .flags = 0, + .len = 6, + .buf = buf, + } + }; + + + buf[0] = reg_addr>>8; + buf[1] = reg_addr & 0xff; + buf[5] = (value>>24) & 0xff; + buf[4] = (value>>16) & 0xff; + buf[3] = (value>>8) & 0xff; + buf[2] = value & 0xff; + client->flags = 0; + msgs[0].addr = 0x44; + + retval = i2c_xfer(client->adapter, msgs, 1); + + return retval; +} + diff --git a/linux/drivers/staging/cx25821/cx25821-medusa-defines.h b/linux/drivers/staging/cx25821/cx25821-medusa-defines.h new file mode 100644 index 000000000..75161e488 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-medusa-defines.h @@ -0,0 +1,51 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _MEDUSA_DEF_H_ +#define _MEDUSA_DEF_H_ + +// Video deocder that we supported +#define VDEC_A 0 +#define VDEC_B 1 +#define VDEC_C 2 +#define VDEC_D 3 +#define VDEC_E 4 +#define VDEC_F 5 +#define VDEC_G 6 +#define VDEC_H 7 + +//#define AUTO_SWITCH_BIT[] = { 8, 9, 10, 11, 12, 13, 14, 15 }; + +// The following bit position enables automatic source switching for decoder A-H. +// Display index per camera. +//#define VDEC_INDEX[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}; + +// Select input bit to video decoder A-H. +//#define CH_SRC_SEL_BIT[] = {24, 25, 26, 27, 28, 29, 30, 31}; + +// end of display sequence +#define END_OF_SEQ 0xF; + +// registry string size +#define MAX_REGISTRY_SZ 40; + +#endif diff --git a/linux/drivers/staging/cx25821/cx25821-medusa-reg.h b/linux/drivers/staging/cx25821/cx25821-medusa-reg.h new file mode 100644 index 000000000..1ddf781ac --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-medusa-reg.h @@ -0,0 +1,456 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MEDUSA_REGISTERS__ +#define __MEDUSA_REGISTERS__ + +// Serial Slave Registers +#define HOST_REGISTER1 0x0000 +#define HOST_REGISTER2 0x0001 + +// Chip Configuration Registers +#define CHIP_CTRL 0x0100 +#define AFE_AB_CTRL 0x0104 +#define AFE_CD_CTRL 0x0108 +#define AFE_EF_CTRL 0x010C +#define AFE_GH_CTRL 0x0110 +#define DENC_AB_CTRL 0x0114 +#define BYP_AB_CTRL 0x0118 +#define MON_A_CTRL 0x011C +#define DISP_SEQ_A 0x0120 +#define DISP_SEQ_B 0x0124 +#define DISP_AB_CNT 0x0128 +#define DISP_CD_CNT 0x012C +#define DISP_EF_CNT 0x0130 +#define DISP_GH_CNT 0x0134 +#define DISP_IJ_CNT 0x0138 +#define PIN_OE_CTRL 0x013C +#define PIN_SPD_CTRL 0x0140 +#define PIN_SPD_CTRL2 0x0144 +#define IRQ_STAT_CTRL 0x0148 +#define POWER_CTRL_AB 0x014C +#define POWER_CTRL_CD 0x0150 +#define POWER_CTRL_EF 0x0154 +#define POWER_CTRL_GH 0x0158 +#define TUNE_CTRL 0x015C +#define BIAS_CTRL 0x0160 +#define AFE_AB_DIAG_CTRL 0x0164 +#define AFE_CD_DIAG_CTRL 0x0168 +#define AFE_EF_DIAG_CTRL 0x016C +#define AFE_GH_DIAG_CTRL 0x0170 +#define PLL_AB_DIAG_CTRL 0x0174 +#define PLL_CD_DIAG_CTRL 0x0178 +#define PLL_EF_DIAG_CTRL 0x017C +#define PLL_GH_DIAG_CTRL 0x0180 +#define TEST_CTRL 0x0184 +#define BIST_STAT 0x0188 +#define BIST_STAT2 0x018C +#define BIST_VID_PLL_AB_STAT 0x0190 +#define BIST_VID_PLL_CD_STAT 0x0194 +#define BIST_VID_PLL_EF_STAT 0x0198 +#define BIST_VID_PLL_GH_STAT 0x019C +#define DLL_DIAG_CTRL 0x01A0 +#define DEV_CH_ID_CTRL 0x01A4 +#define ABIST_CTRL_STATUS 0x01A8 +#define ABIST_FREQ 0x01AC +#define ABIST_GOERT_SHIFT 0x01B0 +#define ABIST_COEF12 0x01B4 +#define ABIST_COEF34 0x01B8 +#define ABIST_COEF56 0x01BC +#define ABIST_COEF7_SNR 0x01C0 +#define ABIST_ADC_CAL 0x01C4 +#define ABIST_BIN1_VGA0 0x01C8 +#define ABIST_BIN2_VGA1 0x01CC +#define ABIST_BIN3_VGA2 0x01D0 +#define ABIST_BIN4_VGA3 0x01D4 +#define ABIST_BIN5_VGA4 0x01D8 +#define ABIST_BIN6_VGA5 0x01DC +#define ABIST_BIN7_VGA6 0x0x1E0 +#define ABIST_CLAMP_A 0x0x1E4 +#define ABIST_CLAMP_B 0x0x1E8 +#define ABIST_CLAMP_C 0x01EC +#define ABIST_CLAMP_D 0x01F0 +#define ABIST_CLAMP_E 0x01F4 +#define ABIST_CLAMP_F 0x01F8 + +// Digital Video Encoder A Registers +#define DENC_A_REG_1 0x0200 +#define DENC_A_REG_2 0x0204 +#define DENC_A_REG_3 0x0208 +#define DENC_A_REG_4 0x020C +#define DENC_A_REG_5 0x0210 +#define DENC_A_REG_6 0x0214 +#define DENC_A_REG_7 0x0218 +#define DENC_A_REG_8 0x021C + +// Digital Video Encoder B Registers +#define DENC_B_REG_1 0x0300 +#define DENC_B_REG_2 0x0304 +#define DENC_B_REG_3 0x0308 +#define DENC_B_REG_4 0x030C +#define DENC_B_REG_5 0x0310 +#define DENC_B_REG_6 0x0314 +#define DENC_B_REG_7 0x0318 +#define DENC_B_REG_8 0x031C + +// Video Decoder A Registers +#define MODE_CTRL 0x1000 +#define OUT_CTRL1 0x1004 +#define OUT_CTRL_NS 0x1008 +#define GEN_STAT 0x100C +#define INT_STAT_MASK 0x1010 +#define LUMA_CTRL 0x1014 +#define CHROMA_CTRL 0x1018 +#define CRUSH_CTRL 0x101C +#define HORIZ_TIM_CTRL 0x1020 +#define VERT_TIM_CTRL 0x1024 +#define MISC_TIM_CTRL 0x1028 +#define FIELD_COUNT 0x102C +#define HSCALE_CTRL 0x1030 +#define VSCALE_CTRL 0x1034 +#define MAN_VGA_CTRL 0x1038 +#define MAN_AGC_CTRL 0x103C +#define DFE_CTRL1 0x1040 +#define DFE_CTRL2 0x1044 +#define DFE_CTRL3 0x1048 +#define PLL_CTRL 0x104C +#define PLL_CTRL_FAST 0x1050 +#define HTL_CTRL 0x1054 +#define SRC_CFG 0x1058 +#define SC_STEP_SIZE 0x105C +#define SC_CONVERGE_CTRL 0x1060 +#define SC_LOOP_CTRL 0x1064 +#define COMB_2D_HFS_CFG 0x1068 +#define COMB_2D_HFD_CFG 0x106C +#define COMB_2D_LF_CFG 0x1070 +#define COMB_2D_BLEND 0x1074 +#define COMB_MISC_CTRL 0x1078 +#define COMB_FLAT_THRESH_CTRL 0x107C +#define COMB_TEST 0x1080 +#define BP_MISC_CTRL 0x1084 +#define VCR_DET_CTRL 0x1088 +#define NOISE_DET_CTRL 0x108C +#define COMB_FLAT_NOISE_CTRL 0x1090 +#define VERSION 0x11F8 +#define SOFT_RST_CTRL 0x11FC + +// Video Decoder B Registers +#define VDEC_B_MODE_CTRL 0x1200 +#define VDEC_B_OUT_CTRL1 0x1204 +#define VDEC_B_OUT_CTRL_NS 0x1208 +#define VDEC_B_GEN_STAT 0x120C +#define VDEC_B_INT_STAT_MASK 0x1210 +#define VDEC_B_LUMA_CTRL 0x1214 +#define VDEC_B_CHROMA_CTRL 0x1218 +#define VDEC_B_CRUSH_CTRL 0x121C +#define VDEC_B_HORIZ_TIM_CTRL 0x1220 +#define VDEC_B_VERT_TIM_CTRL 0x1224 +#define VDEC_B_MISC_TIM_CTRL 0x1228 +#define VDEC_B_FIELD_COUNT 0x122C +#define VDEC_B_HSCALE_CTRL 0x1230 +#define VDEC_B_VSCALE_CTRL 0x1234 +#define VDEC_B_MAN_VGA_CTRL 0x1238 +#define VDEC_B_MAN_AGC_CTRL 0x123C +#define VDEC_B_DFE_CTRL1 0x1240 +#define VDEC_B_DFE_CTRL2 0x1244 +#define VDEC_B_DFE_CTRL3 0x1248 +#define VDEC_B_PLL_CTRL 0x124C +#define VDEC_B_PLL_CTRL_FAST 0x1250 +#define VDEC_B_HTL_CTRL 0x1254 +#define VDEC_B_SRC_CFG 0x1258 +#define VDEC_B_SC_STEP_SIZE 0x125C +#define VDEC_B_SC_CONVERGE_CTRL 0x1260 +#define VDEC_B_SC_LOOP_CTRL 0x1264 +#define VDEC_B_COMB_2D_HFS_CFG 0x1268 +#define VDEC_B_COMB_2D_HFD_CFG 0x126C +#define VDEC_B_COMB_2D_LF_CFG 0x1270 +#define VDEC_B_COMB_2D_BLEND 0x1274 +#define VDEC_B_COMB_MISC_CTRL 0x1278 +#define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C +#define VDEC_B_COMB_TEST 0x1280 +#define VDEC_B_BP_MISC_CTRL 0x1284 +#define VDEC_B_VCR_DET_CTRL 0x1288 +#define VDEC_B_NOISE_DET_CTRL 0x128C +#define VDEC_B_COMB_FLAT_NOISE_CTRL 0x1290 +#define VDEC_B_VERSION 0x13F8 +#define VDEC_B_SOFT_RST_CTRL 0x13FC + +// Video Decoder C Registers +#define VDEC_C_MODE_CTRL 0x1400 +#define VDEC_C_OUT_CTRL1 0x1404 +#define VDEC_C_OUT_CTRL_NS 0x1408 +#define VDEC_C_GEN_STAT 0x140C +#define VDEC_C_INT_STAT_MASK 0x1410 +#define VDEC_C_LUMA_CTRL 0x1414 +#define VDEC_C_CHROMA_CTRL 0x1418 +#define VDEC_C_CRUSH_CTRL 0x141C +#define VDEC_C_HORIZ_TIM_CTRL 0x1420 +#define VDEC_C_VERT_TIM_CTRL 0x1424 +#define VDEC_C_MISC_TIM_CTRL 0x1428 +#define VDEC_C_FIELD_COUNT 0x142C +#define VDEC_C_HSCALE_CTRL 0x1430 +#define VDEC_C_VSCALE_CTRL 0x1434 +#define VDEC_C_MAN_VGA_CTRL 0x1438 +#define VDEC_C_MAN_AGC_CTRL 0x143C +#define VDEC_C_DFE_CTRL1 0x1440 +#define VDEC_C_DFE_CTRL2 0x1444 +#define VDEC_C_DFE_CTRL3 0x1448 +#define VDEC_C_PLL_CTRL 0x144C +#define VDEC_C_PLL_CTRL_FAST 0x1450 +#define VDEC_C_HTL_CTRL 0x1454 +#define VDEC_C_SRC_CFG 0x1458 +#define VDEC_C_SC_STEP_SIZE 0x145C +#define VDEC_C_SC_CONVERGE_CTRL 0x1460 +#define VDEC_C_SC_LOOP_CTRL 0x1464 +#define VDEC_C_COMB_2D_HFS_CFG 0x1468 +#define VDEC_C_COMB_2D_HFD_CFG 0x146C +#define VDEC_C_COMB_2D_LF_CFG 0x1470 +#define VDEC_C_COMB_2D_BLEND 0x1474 +#define VDEC_C_COMB_MISC_CTRL 0x1478 +#define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C +#define VDEC_C_COMB_TEST 0x1480 +#define VDEC_C_BP_MISC_CTRL 0x1484 +#define VDEC_C_VCR_DET_CTRL 0x1488 +#define VDEC_C_NOISE_DET_CTRL 0x148C +#define VDEC_C_COMB_FLAT_NOISE_CTRL 0x1490 +#define VDEC_C_VERSION 0x15F8 +#define VDEC_C_SOFT_RST_CTRL 0x15FC + +// Video Decoder D Registers +#define VDEC_D_MODE_CTRL 0x1600 +#define VDEC_D_OUT_CTRL1 0x1604 +#define VDEC_D_OUT_CTRL_NS 0x1608 +#define VDEC_D_GEN_STAT 0x160C +#define VDEC_D_INT_STAT_MASK 0x1610 +#define VDEC_D_LUMA_CTRL 0x1614 +#define VDEC_D_CHROMA_CTRL 0x1618 +#define VDEC_D_CRUSH_CTRL 0x161C +#define VDEC_D_HORIZ_TIM_CTRL 0x1620 +#define VDEC_D_VERT_TIM_CTRL 0x1624 +#define VDEC_D_MISC_TIM_CTRL 0x1628 +#define VDEC_D_FIELD_COUNT 0x162C +#define VDEC_D_HSCALE_CTRL 0x1630 +#define VDEC_D_VSCALE_CTRL 0x1634 +#define VDEC_D_MAN_VGA_CTRL 0x1638 +#define VDEC_D_MAN_AGC_CTRL 0x163C +#define VDEC_D_DFE_CTRL1 0x1640 +#define VDEC_D_DFE_CTRL2 0x1644 +#define VDEC_D_DFE_CTRL3 0x1648 +#define VDEC_D_PLL_CTRL 0x164C +#define VDEC_D_PLL_CTRL_FAST 0x1650 +#define VDEC_D_HTL_CTRL 0x1654 +#define VDEC_D_SRC_CFG 0x1658 +#define VDEC_D_SC_STEP_SIZE 0x165C +#define VDEC_D_SC_CONVERGE_CTRL 0x1660 +#define VDEC_D_SC_LOOP_CTRL 0x1664 +#define VDEC_D_COMB_2D_HFS_CFG 0x1668 +#define VDEC_D_COMB_2D_HFD_CFG 0x166C +#define VDEC_D_COMB_2D_LF_CFG 0x1670 +#define VDEC_D_COMB_2D_BLEND 0x1674 +#define VDEC_D_COMB_MISC_CTRL 0x1678 +#define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C +#define VDEC_D_COMB_TEST 0x1680 +#define VDEC_D_BP_MISC_CTRL 0x1684 +#define VDEC_D_VCR_DET_CTRL 0x1688 +#define VDEC_D_NOISE_DET_CTRL 0x168C +#define VDEC_D_COMB_FLAT_NOISE_CTRL 0x1690 +#define VDEC_D_VERSION 0x17F8 +#define VDEC_D_SOFT_RST_CTRL 0x17FC + +// Video Decoder E Registers +#define VDEC_E_MODE_CTRL 0x1800 +#define VDEC_E_OUT_CTRL1 0x1804 +#define VDEC_E_OUT_CTRL_NS 0x1808 +#define VDEC_E_GEN_STAT 0x180C +#define VDEC_E_INT_STAT_MASK 0x1810 +#define VDEC_E_LUMA_CTRL 0x1814 +#define VDEC_E_CHROMA_CTRL 0x1818 +#define VDEC_E_CRUSH_CTRL 0x181C +#define VDEC_E_HORIZ_TIM_CTRL 0x1820 +#define VDEC_E_VERT_TIM_CTRL 0x1824 +#define VDEC_E_MISC_TIM_CTRL 0x1828 +#define VDEC_E_FIELD_COUNT 0x182C +#define VDEC_E_HSCALE_CTRL 0x1830 +#define VDEC_E_VSCALE_CTRL 0x1834 +#define VDEC_E_MAN_VGA_CTRL 0x1838 +#define VDEC_E_MAN_AGC_CTRL 0x183C +#define VDEC_E_DFE_CTRL1 0x1840 +#define VDEC_E_DFE_CTRL2 0x1844 +#define VDEC_E_DFE_CTRL3 0x1848 +#define VDEC_E_PLL_CTRL 0x184C +#define VDEC_E_PLL_CTRL_FAST 0x1850 +#define VDEC_E_HTL_CTRL 0x1854 +#define VDEC_E_SRC_CFG 0x1858 +#define VDEC_E_SC_STEP_SIZE 0x185C +#define VDEC_E_SC_CONVERGE_CTRL 0x1860 +#define VDEC_E_SC_LOOP_CTRL 0x1864 +#define VDEC_E_COMB_2D_HFS_CFG 0x1868 +#define VDEC_E_COMB_2D_HFD_CFG 0x186C +#define VDEC_E_COMB_2D_LF_CFG 0x1870 +#define VDEC_E_COMB_2D_BLEND 0x1874 +#define VDEC_E_COMB_MISC_CTRL 0x1878 +#define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C +#define VDEC_E_COMB_TEST 0x1880 +#define VDEC_E_BP_MISC_CTRL 0x1884 +#define VDEC_E_VCR_DET_CTRL 0x1888 +#define VDEC_E_NOISE_DET_CTRL 0x188C +#define VDEC_E_COMB_FLAT_NOISE_CTRL 0x1890 +#define VDEC_E_VERSION 0x19F8 +#define VDEC_E_SOFT_RST_CTRL 0x19FC + +// Video Decoder F Registers +#define VDEC_F_MODE_CTRL 0x1A00 +#define VDEC_F_OUT_CTRL1 0x1A04 +#define VDEC_F_OUT_CTRL_NS 0x1A08 +#define VDEC_F_GEN_STAT 0x1A0C +#define VDEC_F_INT_STAT_MASK 0x1A10 +#define VDEC_F_LUMA_CTRL 0x1A14 +#define VDEC_F_CHROMA_CTRL 0x1A18 +#define VDEC_F_CRUSH_CTRL 0x1A1C +#define VDEC_F_HORIZ_TIM_CTRL 0x1A20 +#define VDEC_F_VERT_TIM_CTRL 0x1A24 +#define VDEC_F_MISC_TIM_CTRL 0x1A28 +#define VDEC_F_FIELD_COUNT 0x1A2C +#define VDEC_F_HSCALE_CTRL 0x1A30 +#define VDEC_F_VSCALE_CTRL 0x1A34 +#define VDEC_F_MAN_VGA_CTRL 0x1A38 +#define VDEC_F_MAN_AGC_CTRL 0x1A3C +#define VDEC_F_DFE_CTRL1 0x1A40 +#define VDEC_F_DFE_CTRL2 0x1A44 +#define VDEC_F_DFE_CTRL3 0x1A48 +#define VDEC_F_PLL_CTRL 0x1A4C +#define VDEC_F_PLL_CTRL_FAST 0x1A50 +#define VDEC_F_HTL_CTRL 0x1A54 +#define VDEC_F_SRC_CFG 0x1A58 +#define VDEC_F_SC_STEP_SIZE 0x1A5C +#define VDEC_F_SC_CONVERGE_CTRL 0x1A60 +#define VDEC_F_SC_LOOP_CTRL 0x1A64 +#define VDEC_F_COMB_2D_HFS_CFG 0x1A68 +#define VDEC_F_COMB_2D_HFD_CFG 0x1A6C +#define VDEC_F_COMB_2D_LF_CFG 0x1A70 +#define VDEC_F_COMB_2D_BLEND 0x1A74 +#define VDEC_F_COMB_MISC_CTRL 0x1A78 +#define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C +#define VDEC_F_COMB_TEST 0x1A80 +#define VDEC_F_BP_MISC_CTRL 0x1A84 +#define VDEC_F_VCR_DET_CTRL 0x1A88 +#define VDEC_F_NOISE_DET_CTRL 0x1A8C +#define VDEC_F_COMB_FLAT_NOISE_CTRL 0x1A90 +#define VDEC_F_VERSION 0x1BF8 +#define VDEC_F_SOFT_RST_CTRL 0x1BFC + +// Video Decoder G Registers +#define VDEC_G_MODE_CTRL 0x1C00 +#define VDEC_G_OUT_CTRL1 0x1C04 +#define VDEC_G_OUT_CTRL_NS 0x1C08 +#define VDEC_G_GEN_STAT 0x1C0C +#define VDEC_G_INT_STAT_MASK 0x1C10 +#define VDEC_G_LUMA_CTRL 0x1C14 +#define VDEC_G_CHROMA_CTRL 0x1C18 +#define VDEC_G_CRUSH_CTRL 0x1C1C +#define VDEC_G_HORIZ_TIM_CTRL 0x1C20 +#define VDEC_G_VERT_TIM_CTRL 0x1C24 +#define VDEC_G_MISC_TIM_CTRL 0x1C28 +#define VDEC_G_FIELD_COUNT 0x1C2C +#define VDEC_G_HSCALE_CTRL 0x1C30 +#define VDEC_G_VSCALE_CTRL 0x1C34 +#define VDEC_G_MAN_VGA_CTRL 0x1C38 +#define VDEC_G_MAN_AGC_CTRL 0x1C3C +#define VDEC_G_DFE_CTRL1 0x1C40 +#define VDEC_G_DFE_CTRL2 0x1C44 +#define VDEC_G_DFE_CTRL3 0x1C48 +#define VDEC_G_PLL_CTRL 0x1C4C +#define VDEC_G_PLL_CTRL_FAST 0x1C50 +#define VDEC_G_HTL_CTRL 0x1C54 +#define VDEC_G_SRC_CFG 0x1C58 +#define VDEC_G_SC_STEP_SIZE 0x1C5C +#define VDEC_G_SC_CONVERGE_CTRL 0x1C60 +#define VDEC_G_SC_LOOP_CTRL 0x1C64 +#define VDEC_G_COMB_2D_HFS_CFG 0x1C68 +#define VDEC_G_COMB_2D_HFD_CFG 0x1C6C +#define VDEC_G_COMB_2D_LF_CFG 0x1C70 +#define VDEC_G_COMB_2D_BLEND 0x1C74 +#define VDEC_G_COMB_MISC_CTRL 0x1C78 +#define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C +#define VDEC_G_COMB_TEST 0x1C80 +#define VDEC_G_BP_MISC_CTRL 0x1C84 +#define VDEC_G_VCR_DET_CTRL 0x1C88 +#define VDEC_G_NOISE_DET_CTRL 0x1C8C +#define VDEC_G_COMB_FLAT_NOISE_CTRL 0x1C90 +#define VDEC_G_VERSION 0x1DF8 +#define VDEC_G_SOFT_RST_CTRL 0x1DFC + +// Video Decoder H Registers +#define VDEC_H_MODE_CTRL 0x1E00 +#define VDEC_H_OUT_CTRL1 0x1E04 +#define VDEC_H_OUT_CTRL_NS 0x1E08 +#define VDEC_H_GEN_STAT 0x1E0C +#define VDEC_H_INT_STAT_MASK 0x1E1E +#define VDEC_H_LUMA_CTRL 0x1E14 +#define VDEC_H_CHROMA_CTRL 0x1E18 +#define VDEC_H_CRUSH_CTRL 0x1E1C +#define VDEC_H_HORIZ_TIM_CTRL 0x1E20 +#define VDEC_H_VERT_TIM_CTRL 0x1E24 +#define VDEC_H_MISC_TIM_CTRL 0x1E28 +#define VDEC_H_FIELD_COUNT 0x1E2C +#define VDEC_H_HSCALE_CTRL 0x1E30 +#define VDEC_H_VSCALE_CTRL 0x1E34 +#define VDEC_H_MAN_VGA_CTRL 0x1E38 +#define VDEC_H_MAN_AGC_CTRL 0x1E3C +#define VDEC_H_DFE_CTRL1 0x1E40 +#define VDEC_H_DFE_CTRL2 0x1E44 +#define VDEC_H_DFE_CTRL3 0x1E48 +#define VDEC_H_PLL_CTRL 0x1E4C +#define VDEC_H_PLL_CTRL_FAST 0x1E50 +#define VDEC_H_HTL_CTRL 0x1E54 +#define VDEC_H_SRC_CFG 0x1E58 +#define VDEC_H_SC_STEP_SIZE 0x1E5C +#define VDEC_H_SC_CONVERGE_CTRL 0x1E60 +#define VDEC_H_SC_LOOP_CTRL 0x1E64 +#define VDEC_H_COMB_2D_HFS_CFG 0x1E68 +#define VDEC_H_COMB_2D_HFD_CFG 0x1E6C +#define VDEC_H_COMB_2D_LF_CFG 0x1E70 +#define VDEC_H_COMB_2D_BLEND 0x1E74 +#define VDEC_H_COMB_MISC_CTRL 0x1E78 +#define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C +#define VDEC_H_COMB_TEST 0x1E80 +#define VDEC_H_BP_MISC_CTRL 0x1E84 +#define VDEC_H_VCR_DET_CTRL 0x1E88 +#define VDEC_H_NOISE_DET_CTRL 0x1E8C +#define VDEC_H_COMB_FLAT_NOISE_CTRL 0x1E90 +#define VDEC_H_VERSION 0x1FF8 +#define VDEC_H_SOFT_RST_CTRL 0x1FFC + +//***************************************************************************** +// LUMA_CTRL register fields +#define VDEC_A_BRITE_CTRL 0x1014 +#define VDEC_A_CNTRST_CTRL 0x1015 +#define VDEC_A_PEAK_SEL 0x1016 + +//***************************************************************************** +// CHROMA_CTRL register fields +#define VDEC_A_USAT_CTRL 0x1018 +#define VDEC_A_VSAT_CTRL 0x1019 +#define VDEC_A_HUE_CTRL 0x101A + + +#endif \ No newline at end of file diff --git a/linux/drivers/staging/cx25821/cx25821-medusa-video.c b/linux/drivers/staging/cx25821/cx25821-medusa-video.c new file mode 100644 index 000000000..6225f1079 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-medusa-video.c @@ -0,0 +1,769 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821.h" +#include "cx25821-medusa-video.h" +#include "cx25821-biffuncs.h" + + +///////////////////////////////////////////////////////////////////////////////////////// +//medusa_enable_bluefield_output() +// +// Enable the generation of blue filed output if no video +// +static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel, int enable) +{ + int ret_val = 1; + u32 value = 0; + u32 tmp = 0; + int out_ctrl = OUT_CTRL1; + int out_ctrl_ns = OUT_CTRL_NS; + + + switch (channel) + { + default: + case VDEC_A: + break; + case VDEC_B: + out_ctrl = VDEC_B_OUT_CTRL1; + out_ctrl_ns = VDEC_B_OUT_CTRL_NS; + break; + case VDEC_C: + out_ctrl = VDEC_C_OUT_CTRL1; + out_ctrl_ns = VDEC_C_OUT_CTRL_NS; + break; + case VDEC_D: + out_ctrl = VDEC_D_OUT_CTRL1; + out_ctrl_ns = VDEC_D_OUT_CTRL_NS; + break; + case VDEC_E: + out_ctrl = VDEC_E_OUT_CTRL1; + out_ctrl_ns = VDEC_E_OUT_CTRL_NS; + return; + case VDEC_F: + out_ctrl = VDEC_F_OUT_CTRL1; + out_ctrl_ns = VDEC_F_OUT_CTRL_NS; + return; + case VDEC_G: + out_ctrl = VDEC_G_OUT_CTRL1; + out_ctrl_ns = VDEC_G_OUT_CTRL_NS; + return; + case VDEC_H: + out_ctrl = VDEC_H_OUT_CTRL1; + out_ctrl_ns = VDEC_H_OUT_CTRL_NS; + return; + } + + value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp); + value &= 0xFFFFFF7F; // clear BLUE_FIELD_EN + if (enable) + value |= 0x00000080; // set BLUE_FIELD_EN + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value); + + value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp); + value &= 0xFFFFFF7F; + if (enable) + value |= 0x00000080; // set BLUE_FIELD_EN + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value); +} + + +static int medusa_initialize_ntsc(struct cx25821_dev *dev) +{ + int ret_val = 0; + int i = 0; + u32 value = 0; + u32 tmp = 0; + + mutex_lock(&dev->lock); + + + for (i=0; i < MAX_DECODERS; i++) + { + // set video format NTSC-M + value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp); + value &= 0xFFFFFFF0; + value |= 0x10001; // enable the fast locking mode bit[16] + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value); + + // resolution NTSC 720x480 + value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp); + value &= 0x00C00C00; + value |= 0x612D0074; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value); + + value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp); + value &= 0x00C00C00; + value |= 0x1C1E001A; // vblank_cnt + 2 to get camera ID + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value); + + // chroma subcarrier step size + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x43E00000); + + // enable VIP optional active + value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value); + + // enable VIP optional active (VIP_OPT_AL) for direct output. + value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value); + + // clear VPRES_VERT_EN bit, fixes the chroma run away problem + // when the input switching rate < 16 fields + // + value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp); + value = setBitAtPos(value, 14); // disable special play detection + value = clearBitAtPos(value, 15); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value); + + // set vbi_gate_en to 0 + value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp); + value = clearBitAtPos(value, 29); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value); + + // Enable the generation of blue field output if no video + medusa_enable_bluefield_output(dev, i, 1); + } + + + for (i=0; i < MAX_ENCODERS; i++) + { + // NTSC hclock + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp); + value &= 0xF000FC00; + value |= 0x06B402D0; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value); + + // burst begin and burst end + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp); + value &= 0xFF000000; + value |= 0x007E9054; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value); + + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp); + value &= 0xFC00FE00; + value |= 0x00EC00F0; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value); + + // set NTSC vblank, no phase alternation, 7.5 IRE pedestal + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp); + value &= 0x00FCFFFF; + value |= 0x13020000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value); + + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp); + value &= 0xFFFF0000; + value |= 0x0000E575; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value); + + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x009A89C1); + + // Subcarrier Increment + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x21F07C1F); + } + + + //set picture resolutions + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 480 + + // set Bypass input format to NTSC 525 lines + value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); + value |= 0x00080200; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); + + mutex_unlock(&dev->lock); + + return ret_val; +} + + +static int medusa_PALCombInit(struct cx25821_dev *dev, int dec) +{ + int ret_val = -1; + u32 value = 0, tmp = 0; + + // Setup for 2D threshold + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG+(0x200*dec), 0x20002861); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG+(0x200*dec), 0x20002861); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG+(0x200*dec), 0x200A1023); + + // Setup flat chroma and luma thresholds + value = cx25821_i2c_read(&dev->i2c_bus[0], COMB_FLAT_THRESH_CTRL+(0x200*dec), &tmp); + value &= 0x06230000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_FLAT_THRESH_CTRL+(0x200*dec), value); + + // set comb 2D blend + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND+(0x200*dec), 0x210F0F0F); + + // COMB MISC CONTROL + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL+(0x200*dec), 0x41120A7F); + + return ret_val; +} + + +static int medusa_initialize_pal(struct cx25821_dev *dev) +{ + int ret_val = 0; + int i = 0; + u32 value = 0; + u32 tmp = 0; + + mutex_lock(&dev->lock); + + for (i=0; i < MAX_DECODERS; i++) + { + // set video format PAL-BDGHI + value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp); + value &= 0xFFFFFFF0; + value |= 0x10004; // enable the fast locking mode bit[16] + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value); + + + // resolution PAL 720x576 + value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp); + value &= 0x00C00C00; + value |= 0x632D007D; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value); + + // vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 + value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp); + value &= 0x00C00C00; + value |= 0x28240026; // vblank_cnt + 2 to get camera ID + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value); + + // chroma subcarrier step size + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x5411E2D0); + + // enable VIP optional active + value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value); + + // enable VIP optional active (VIP_OPT_AL) for direct output. + value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value); + + // clear VPRES_VERT_EN bit, fixes the chroma run away problem + // when the input switching rate < 16 fields + value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp); + value = setBitAtPos(value, 14); // disable special play detection + value = clearBitAtPos(value, 15); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value); + + // set vbi_gate_en to 0 + value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp); + value = clearBitAtPos(value, 29); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value); + + medusa_PALCombInit(dev, i); + + // Enable the generation of blue field output if no video + medusa_enable_bluefield_output(dev, i, 1); + } + + + for (i=0; i < MAX_ENCODERS; i++) + { + // PAL hclock + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp); + value &= 0xF000FC00; + value |= 0x06C002D0; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value); + + // burst begin and burst end + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp); + value &= 0xFF000000; + value |= 0x007E9754; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value); + + // hblank and vactive + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp); + value &= 0xFC00FE00; + value |= 0x00FC0120; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value); + + // set PAL vblank, phase alternation, 0 IRE pedestal + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp); + value &= 0x00FCFFFF; + value |= 0x14010000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value); + + + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp); + value &= 0xFFFF0000; + value |= 0x0000F078; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value); + + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x00A493CF); + + // Subcarrier Increment + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x2A098ACB); + } + + + //set picture resolutions + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 576 + + // set Bypass input format to PAL 625 lines + value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); + value &= 0xFFF7FDFF; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); + + mutex_unlock(&dev->lock); + + return ret_val; +} + + +int medusa_set_videostandard(struct cx25821_dev *dev) +{ + int status = STATUS_SUCCESS; + u32 value = 0, tmp = 0; + + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + { + status = medusa_initialize_pal(dev); + } + else + { + status = medusa_initialize_ntsc(dev); + } + + // Enable DENC_A output + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp); + value = setBitAtPos(value, 4); + status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value); + + // Enable DENC_B output + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp); + value = setBitAtPos(value, 4); + status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value); + + return status; +} + + +void medusa_set_resolution(struct cx25821_dev *dev, int width, int decoder_select) +{ + int decoder = 0; + int decoder_count = 0; + int ret_val = 0; + u32 hscale = 0x0; + u32 vscale = 0x0; + const int MAX_WIDTH = 720; + + mutex_lock(&dev->lock); + + // validate the width - cannot be negative + if (width > MAX_WIDTH) + { + printk("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH \n", __func__, width, MAX_WIDTH); + width = MAX_WIDTH; + } + + if( decoder_select <= 7 && decoder_select >= 0 ) + { + decoder = decoder_select; + decoder_count = decoder_select + 1; + } + else + { + decoder = 0; + decoder_count = _num_decoders; + } + + + switch( width ) + { + case 320: + hscale = 0x13E34B; + vscale = 0x0; + break; + + case 352: + hscale = 0x10A273; + vscale = 0x0; + break; + + case 176: + hscale = 0x3115B2; + vscale = 0x1E00; + break; + + case 160: + hscale = 0x378D84; + vscale = 0x1E00; + break; + + default: //720 + hscale = 0x0; + vscale = 0x0; + break; + } + + for( ; decoder < decoder_count; decoder++) + { + // write scaling values for each decoder + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL+(0x200*decoder), hscale); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL+(0x200*decoder), vscale); + } + + mutex_unlock(&dev->lock); +} + +static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, int duration) +{ + int ret_val = 0; + u32 fld_cnt = 0; + u32 tmp = 0; + u32 disp_cnt_reg = DISP_AB_CNT; + + mutex_lock(&dev->lock); + + // no support + if (decoder < VDEC_A && decoder > VDEC_H) + { + mutex_unlock(&dev->lock); + return; + } + + switch (decoder) + { + default: + break; + case VDEC_C: + case VDEC_D: + disp_cnt_reg = DISP_CD_CNT; + break; + case VDEC_E: + case VDEC_F: + disp_cnt_reg = DISP_EF_CNT; + break; + case VDEC_G: + case VDEC_H: + disp_cnt_reg = DISP_GH_CNT; + break; + } + + _display_field_cnt[decoder] = duration; + + // update hardware + fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp); + + if (!(decoder % 2)) // EVEN decoder + { + fld_cnt &= 0xFFFF0000; + fld_cnt |= duration; + } + else + { + fld_cnt &= 0x0000FFFF; + fld_cnt |= ((u32)duration) << 16; + } + + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt); + + mutex_unlock(&dev->lock); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Map to Medusa register setting +static int mapM( + int srcMin, + int srcMax, + int srcVal, + int dstMin, + int dstMax, + int* dstVal +) +{ + int numerator; + int denominator; + int quotient; + + if((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax)) + { + return -1; + } + + // This is the overall expression used: + // *dstVal = (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin; + // but we need to account for rounding so below we use the modulus + // operator to find the remainder and increment if necessary. + numerator = (srcVal - srcMin)*(dstMax - dstMin); + denominator = srcMax - srcMin; + quotient = numerator/denominator; + + if(2 * ( numerator % denominator ) >= denominator) + { + quotient++; + } + + *dstVal = quotient + dstMin; + + return 0; +} + +static unsigned long convert_to_twos(long numeric, unsigned long bits_len) +{ + unsigned char temp; + + if (numeric >= 0) + return numeric; + else + { + temp = ~(abs(numeric) & 0xFF); + temp += 1; + return temp; + } +} +///////////////////////////////////////////////////////////////////////////////////////// +int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) +{ + int ret_val = 0; + int value = 0; + u32 val = 0, tmp = 0; + + mutex_lock(&dev->lock); + if((brightness > VIDEO_PROCAMP_MAX) || (brightness < VIDEO_PROCAMP_MIN)) + { + mutex_unlock(&dev->lock); + return -1; + } + ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); + value = convert_to_twos(value, 8); + val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_BRITE_CTRL+(0x200*decoder), &tmp); + val &= 0xFFFFFF00; + ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_BRITE_CTRL+(0x200*decoder), val | value); + mutex_unlock(&dev->lock); + return ret_val; +} + +///////////////////////////////////////////////////////////////////////////////////////// +int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) +{ + int ret_val = 0; + int value = 0; + u32 val = 0, tmp = 0; + + mutex_lock(&dev->lock); + + if((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) + { + mutex_unlock(&dev->lock); + return -1; + } + + ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); + val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_CNTRST_CTRL+(0x200*decoder), &tmp); + val &= 0xFFFFFF00; + ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_CNTRST_CTRL+(0x200*decoder), val | value); + + mutex_unlock(&dev->lock); + return ret_val; +} + +///////////////////////////////////////////////////////////////////////////////////////// +int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) +{ + int ret_val = 0; + int value = 0; + u32 val = 0, tmp = 0; + + mutex_lock(&dev->lock); + + if((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) + { + mutex_unlock(&dev->lock); + return -1; + } + + ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); + + value = convert_to_twos(value, 8); + val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_HUE_CTRL+(0x200*decoder), &tmp); + val &= 0xFFFFFF00; + + ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_HUE_CTRL+(0x200*decoder), val | value); + + mutex_unlock(&dev->lock); + return ret_val; +} + + +///////////////////////////////////////////////////////////////////////////////////////// +int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) +{ + int ret_val = 0; + int value = 0; + u32 val = 0, tmp = 0; + + mutex_lock(&dev->lock); + + if((saturation > VIDEO_PROCAMP_MAX) || (saturation < VIDEO_PROCAMP_MIN)) + { + mutex_unlock(&dev->lock); + return -1; + } + + ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); + + val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_USAT_CTRL+(0x200*decoder), &tmp); + val &= 0xFFFFFF00; + ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_USAT_CTRL+(0x200*decoder), val | value); + + val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_VSAT_CTRL+(0x200*decoder), &tmp); + val &= 0xFFFFFF00; + ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_VSAT_CTRL+(0x200*decoder), val | value); + + mutex_unlock(&dev->lock); + return ret_val; +} + + +///////////////////////////////////////////////////////////////////////////////////////// +// Program the display sequence and monitor output. +// +int medusa_video_init(struct cx25821_dev *dev) +{ + u32 value = 0, tmp = 0; + int ret_val = 0; + int i=0; + + mutex_lock(&dev->lock); + + _num_decoders = dev->_max_num_decoders; + + + // disable Auto source selection on all video decoders + value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); + value &= 0xFFFFF0FF; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); + + if (ret_val < 0) + { + mutex_unlock(&dev->lock); + return -EINVAL; + } + + // Turn off Master source switch enable + value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); + value &= 0xFFFFFFDF; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); + + if (ret_val < 0) + { + mutex_unlock(&dev->lock); + return -EINVAL; + } + + mutex_unlock(&dev->lock); + + for (i=0; i < _num_decoders; i++) + { + medusa_set_decoderduration(dev, i, _display_field_cnt[i]); + } + + mutex_lock(&dev->lock); + + // Select monitor as DENC A input, power up the DAC + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp); + value &= 0xFF70FF70; + value |= 0x00090008; // set en_active + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value); + + if (ret_val < 0) + { + mutex_unlock(&dev->lock); + return -EINVAL; + } + + // enable input is VIP/656 + value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); + value |= 0x00040100; // enable VIP + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); + + if (ret_val < 0) + { + mutex_unlock(&dev->lock); + return -EINVAL; + } + + // select AFE clock to output mode + value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); + value &= 0x83FFFFFF; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, value | 0x10000000); + + if (ret_val < 0) + { + mutex_unlock(&dev->lock); + return -EINVAL; + } + + // Turn on all of the data out and control output pins. + value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp); + value &= 0xFEF0FE00; + if (_num_decoders == MAX_DECODERS) + { + // Note: The octal board does not support control pins(bit16-19). + // These bits are ignored in the octal board. + value |= 0x010001F8; // disable VDEC A-C port, default to Mobilygen Interface + } + else + { + value |= 0x010F0108; // disable VDEC A-C port, default to Mobilygen Interface + } + + value |= 7; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value); + if (ret_val < 0) + { + mutex_unlock(&dev->lock); + return -EINVAL; + } + + mutex_unlock(&dev->lock); + + + ret_val = medusa_set_videostandard(dev); + + + if (ret_val < 0) + { + mutex_unlock(&dev->lock); + return -EINVAL; + } + + return 1; +} diff --git a/linux/drivers/staging/cx25821/cx25821-medusa-video.h b/linux/drivers/staging/cx25821/cx25821-medusa-video.h new file mode 100644 index 000000000..3651b23c0 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-medusa-video.h @@ -0,0 +1,51 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _MEDUSA_VIDEO_H +#define _MEDUSA_VIDEO_H + +#include "cx25821-medusa-defines.h" + + +// Color control constants +#define VIDEO_PROCAMP_MIN 0 +#define VIDEO_PROCAMP_MAX 10000 +#define UNSIGNED_BYTE_MIN 0 +#define UNSIGNED_BYTE_MAX 0xFF +#define SIGNED_BYTE_MIN -128 +#define SIGNED_BYTE_MAX 127 + +// Default video color settings +#define SHARPNESS_DEFAULT 50 +#define SATURATION_DEFAULT 5000 +#define BRIGHTNESS_DEFAULT 6200 +#define CONTRAST_DEFAULT 5000 +#define HUE_DEFAULT 5000 + + +unsigned short _num_decoders; +unsigned short _num_cameras; + +unsigned int _video_standard; +int _display_field_cnt[MAX_DECODERS]; + +#endif \ No newline at end of file diff --git a/linux/drivers/staging/cx25821/cx25821-reg.h b/linux/drivers/staging/cx25821/cx25821-reg.h new file mode 100644 index 000000000..82f4f16b8 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-reg.h @@ -0,0 +1,1609 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __CX25821_REGISTERS__ +#define __CX25821_REGISTERS__ + +/* Risc Instructions */ +#define RISC_CNT_INC 0x00010000 +#define RISC_CNT_RESET 0x00030000 +#define RISC_IRQ1 0x01000000 +#define RISC_IRQ2 0x02000000 +#define RISC_EOL 0x04000000 +#define RISC_SOL 0x08000000 +#define RISC_WRITE 0x10000000 +#define RISC_SKIP 0x20000000 +#define RISC_JUMP 0x70000000 +#define RISC_SYNC 0x80000000 +#define RISC_RESYNC 0x80008000 +#define RISC_READ 0x90000000 +#define RISC_WRITERM 0xB0000000 +#define RISC_WRITECM 0xC0000000 +#define RISC_WRITECR 0xD0000000 +#define RISC_WRITEC 0x50000000 +#define RISC_READC 0xA0000000 + +#define RISC_SYNC_ODD 0x00000000 +#define RISC_SYNC_EVEN 0x00000200 +#define RISC_SYNC_ODD_VBI 0x00000006 +#define RISC_SYNC_EVEN_VBI 0x00000207 +#define RISC_NOOP 0xF0000000 + +//***************************************************************************** +// ASB SRAM +//***************************************************************************** +#define TX_SRAM 0x000000 // Transmit SRAM + +//***************************************************************************** +#define RX_RAM 0x010000 // Receive SRAM + +//***************************************************************************** +// Application Layer (AL) +//***************************************************************************** +#define DEV_CNTRL2 0x040000 // Device control +#define FLD_RUN_RISC 0x00000020 + +//***************************************************************************** +#define PCI_INT_MSK 0x040010 // PCI interrupt mask +#define PCI_INT_STAT 0x040014 // PCI interrupt status +#define PCI_INT_MSTAT 0x040018 // PCI interrupt masked status +#define FLD_HAMMERHEAD_INT (1 << 27) +#define FLD_UART_INT (1 << 26) +#define FLD_IRQN_INT (1 << 25) +#define FLD_TM_INT (1 << 28) +#define FLD_I2C_3_RACK (1 << 27) +#define FLD_I2C_3_INT (1 << 26) +#define FLD_I2C_2_RACK (1 << 25) +#define FLD_I2C_2_INT (1 << 24) +#define FLD_I2C_1_RACK (1 << 23) +#define FLD_I2C_1_INT (1 << 22) + +#define FLD_APB_DMA_BERR_INT (1 << 21) +#define FLD_AL_WR_BERR_INT (1 << 20) +#define FLD_AL_RD_BERR_INT (1 << 19) +#define FLD_RISC_WR_BERR_INT (1 << 18) +#define FLD_RISC_RD_BERR_INT (1 << 17) + +#define FLD_VID_I_INT (1 << 8) +#define FLD_VID_H_INT (1 << 7) +#define FLD_VID_G_INT (1 << 6) +#define FLD_VID_F_INT (1 << 5) +#define FLD_VID_E_INT (1 << 4) +#define FLD_VID_D_INT (1 << 3) +#define FLD_VID_C_INT (1 << 2) +#define FLD_VID_B_INT (1 << 1) +#define FLD_VID_A_INT (1 << 0) + +//***************************************************************************** +#define VID_A_INT_MSK 0x040020 // Video A interrupt mask +#define VID_A_INT_STAT 0x040024 // Video A interrupt status +#define VID_A_INT_MSTAT 0x040028 // Video A interrupt masked status +#define VID_A_INT_SSTAT 0x04002C // Video A interrupt set status + +//***************************************************************************** +#define VID_B_INT_MSK 0x040030 // Video B interrupt mask +#define VID_B_INT_STAT 0x040034 // Video B interrupt status +#define VID_B_INT_MSTAT 0x040038 // Video B interrupt masked status +#define VID_B_INT_SSTAT 0x04003C // Video B interrupt set status + +//***************************************************************************** +#define VID_C_INT_MSK 0x040040 // Video C interrupt mask +#define VID_C_INT_STAT 0x040044 // Video C interrupt status +#define VID_C_INT_MSTAT 0x040048 // Video C interrupt masked status +#define VID_C_INT_SSTAT 0x04004C // Video C interrupt set status + +//***************************************************************************** +#define VID_D_INT_MSK 0x040050 // Video D interrupt mask +#define VID_D_INT_STAT 0x040054 // Video D interrupt status +#define VID_D_INT_MSTAT 0x040058 // Video D interrupt masked status +#define VID_D_INT_SSTAT 0x04005C // Video D interrupt set status + +//***************************************************************************** +#define VID_E_INT_MSK 0x040060 // Video E interrupt mask +#define VID_E_INT_STAT 0x040064 // Video E interrupt status +#define VID_E_INT_MSTAT 0x040068 // Video E interrupt masked status +#define VID_E_INT_SSTAT 0x04006C // Video E interrupt set status + +//***************************************************************************** +#define VID_F_INT_MSK 0x040070 // Video F interrupt mask +#define VID_F_INT_STAT 0x040074 // Video F interrupt status +#define VID_F_INT_MSTAT 0x040078 // Video F interrupt masked status +#define VID_F_INT_SSTAT 0x04007C // Video F interrupt set status + +//***************************************************************************** +#define VID_G_INT_MSK 0x040080 // Video G interrupt mask +#define VID_G_INT_STAT 0x040084 // Video G interrupt status +#define VID_G_INT_MSTAT 0x040088 // Video G interrupt masked status +#define VID_G_INT_SSTAT 0x04008C // Video G interrupt set status + +//***************************************************************************** +#define VID_H_INT_MSK 0x040090 // Video H interrupt mask +#define VID_H_INT_STAT 0x040094 // Video H interrupt status +#define VID_H_INT_MSTAT 0x040098 // Video H interrupt masked status +#define VID_H_INT_SSTAT 0x04009C // Video H interrupt set status + +//***************************************************************************** +#define VID_I_INT_MSK 0x0400A0 // Video I interrupt mask +#define VID_I_INT_STAT 0x0400A4 // Video I interrupt status +#define VID_I_INT_MSTAT 0x0400A8 // Video I interrupt masked status +#define VID_I_INT_SSTAT 0x0400AC // Video I interrupt set status + +//***************************************************************************** +#define VID_J_INT_MSK 0x0400B0 // Video J interrupt mask +#define VID_J_INT_STAT 0x0400B4 // Video J interrupt status +#define VID_J_INT_MSTAT 0x0400B8 // Video J interrupt masked status +#define VID_J_INT_SSTAT 0x0400BC // Video J interrupt set status + +#define FLD_VID_SRC_OPC_ERR 0x00020000 +#define FLD_VID_DST_OPC_ERR 0x00010000 +#define FLD_VID_SRC_SYNC 0x00002000 +#define FLD_VID_DST_SYNC 0x00001000 +#define FLD_VID_SRC_UF 0x00000200 +#define FLD_VID_DST_OF 0x00000100 +#define FLD_VID_SRC_RISC2 0x00000020 +#define FLD_VID_DST_RISC2 0x00000010 +#define FLD_VID_SRC_RISC1 0x00000002 +#define FLD_VID_DST_RISC1 0x00000001 +#define FLD_VID_SRC_ERRORS FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF +#define FLD_VID_DST_ERRORS FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF + + +//***************************************************************************** +#define AUD_A_INT_MSK 0x0400C0 // Audio Int interrupt mask +#define AUD_A_INT_STAT 0x0400C4 // Audio Int interrupt status +#define AUD_A_INT_MSTAT 0x0400C8 // Audio Int interrupt masked status +#define AUD_A_INT_SSTAT 0x0400CC // Audio Int interrupt set status + +//***************************************************************************** +#define AUD_B_INT_MSK 0x0400D0 // Audio Int interrupt mask +#define AUD_B_INT_STAT 0x0400D4 // Audio Int interrupt status +#define AUD_B_INT_MSTAT 0x0400D8 // Audio Int interrupt masked status +#define AUD_B_INT_SSTAT 0x0400DC // Audio Int interrupt set status + +//***************************************************************************** +#define AUD_C_INT_MSK 0x0400E0 // Audio Int interrupt mask +#define AUD_C_INT_STAT 0x0400E4 // Audio Int interrupt status +#define AUD_C_INT_MSTAT 0x0400E8 // Audio Int interrupt masked status +#define AUD_C_INT_SSTAT 0x0400EC // Audio Int interrupt set status + +//***************************************************************************** +#define AUD_D_INT_MSK 0x0400F0 // Audio Int interrupt mask +#define AUD_D_INT_STAT 0x0400F4 // Audio Int interrupt status +#define AUD_D_INT_MSTAT 0x0400F8 // Audio Int interrupt masked status +#define AUD_D_INT_SSTAT 0x0400FC // Audio Int interrupt set status + +//***************************************************************************** +#define AUD_E_INT_MSK 0x040100 // Audio Int interrupt mask +#define AUD_E_INT_STAT 0x040104 // Audio Int interrupt status +#define AUD_E_INT_MSTAT 0x040108 // Audio Int interrupt masked status +#define AUD_E_INT_SSTAT 0x04010C // Audio Int interrupt set status + +#define FLD_AUD_SRC_OPC_ERR 0x00020000 +#define FLD_AUD_DST_OPC_ERR 0x00010000 +#define FLD_AUD_SRC_SYNC 0x00002000 +#define FLD_AUD_DST_SYNC 0x00001000 +#define FLD_AUD_SRC_OF 0x00000200 +#define FLD_AUD_DST_OF 0x00000100 +#define FLD_AUD_SRC_RISCI2 0x00000020 +#define FLD_AUD_DST_RISCI2 0x00000010 +#define FLD_AUD_SRC_RISCI1 0x00000002 +#define FLD_AUD_DST_RISCI1 0x00000001 + +//***************************************************************************** +#define MBIF_A_INT_MSK 0x040110 // MBIF Int interrupt mask +#define MBIF_A_INT_STAT 0x040114 // MBIF Int interrupt status +#define MBIF_A_INT_MSTAT 0x040118 // MBIF Int interrupt masked status +#define MBIF_A_INT_SSTAT 0x04011C // MBIF Int interrupt set status + +//***************************************************************************** +#define MBIF_B_INT_MSK 0x040120 // MBIF Int interrupt mask +#define MBIF_B_INT_STAT 0x040124 // MBIF Int interrupt status +#define MBIF_B_INT_MSTAT 0x040128 // MBIF Int interrupt masked status +#define MBIF_B_INT_SSTAT 0x04012C // MBIF Int interrupt set status + +#define FLD_MBIF_DST_OPC_ERR 0x00010000 +#define FLD_MBIF_DST_SYNC 0x00001000 +#define FLD_MBIF_DST_OF 0x00000100 +#define FLD_MBIF_DST_RISCI2 0x00000010 +#define FLD_MBIF_DST_RISCI1 0x00000001 + +//***************************************************************************** +#define AUD_EXT_INT_MSK 0x040060 // Audio Ext interrupt mask +#define AUD_EXT_INT_STAT 0x040064 // Audio Ext interrupt status +#define AUD_EXT_INT_MSTAT 0x040068 // Audio Ext interrupt masked status +#define AUD_EXT_INT_SSTAT 0x04006C // Audio Ext interrupt set status +#define FLD_AUD_EXT_OPC_ERR 0x00010000 +#define FLD_AUD_EXT_SYNC 0x00001000 +#define FLD_AUD_EXT_OF 0x00000100 +#define FLD_AUD_EXT_RISCI2 0x00000010 +#define FLD_AUD_EXT_RISCI1 0x00000001 + + +//***************************************************************************** +#define GPIO_LO 0x110010 // Lower of GPIO pins [31:0] +#define GPIO_HI 0x110014 // Upper WORD of GPIO pins [47:31] + +#define GPIO_LO_OE 0x110018 // Lower of GPIO output enable [31:0] +#define GPIO_HI_OE 0x11001C // Upper word of GPIO output enable [47:32] + +#define GPIO_LO_INT_MSK 0x11003C // GPIO interrupt mask +#define GPIO_LO_INT_STAT 0x110044 // GPIO interrupt status +#define GPIO_LO_INT_MSTAT 0x11004C // GPIO interrupt masked status +#define GPIO_LO_ISM_SNS 0x110054 // GPIO interrupt sensitivity +#define GPIO_LO_ISM_POL 0x11005C // GPIO interrupt polarity + +#define GPIO_HI_INT_MSK 0x110040 // GPIO interrupt mask +#define GPIO_HI_INT_STAT 0x110048 // GPIO interrupt status +#define GPIO_HI_INT_MSTAT 0x110050 // GPIO interrupt masked status +#define GPIO_HI_ISM_SNS 0x110058 // GPIO interrupt sensitivity +#define GPIO_HI_ISM_POL 0x110060 // GPIO interrupt polarity + +#define FLD_GPIO43_INT (1 << 11) +#define FLD_GPIO42_INT (1 << 10) +#define FLD_GPIO41_INT (1 << 9) +#define FLD_GPIO40_INT (1 << 8) + +#define FLD_GPIO9_INT (1 << 9) +#define FLD_GPIO8_INT (1 << 8) +#define FLD_GPIO7_INT (1 << 7) +#define FLD_GPIO6_INT (1 << 6) +#define FLD_GPIO5_INT (1 << 5) +#define FLD_GPIO4_INT (1 << 4) +#define FLD_GPIO3_INT (1 << 3) +#define FLD_GPIO2_INT (1 << 2) +#define FLD_GPIO1_INT (1 << 1) +#define FLD_GPIO0_INT (1 << 0) + +//***************************************************************************** +#define TC_REQ 0x040090 // Rider PCI Express traFFic class request + +//***************************************************************************** +#define TC_REQ_SET 0x040094 // Rider PCI Express traFFic class request set + + +//***************************************************************************** +// Rider +//***************************************************************************** + +// PCI Compatible Header +//***************************************************************************** +#define RDR_CFG0 0x050000 +#define RDR_VENDOR_DEVICE_ID_CFG 0x050000 + +//***************************************************************************** +#define RDR_CFG1 0x050004 + +//***************************************************************************** +#define RDR_CFG2 0x050008 + +//***************************************************************************** +#define RDR_CFG3 0x05000C + +//***************************************************************************** +#define RDR_CFG4 0x050010 + +//***************************************************************************** +#define RDR_CFG5 0x050014 + +//***************************************************************************** +#define RDR_CFG6 0x050018 + +//***************************************************************************** +#define RDR_CFG7 0x05001C + +//***************************************************************************** +#define RDR_CFG8 0x050020 + +//***************************************************************************** +#define RDR_CFG9 0x050024 + +//***************************************************************************** +#define RDR_CFGA 0x050028 + +//***************************************************************************** +#define RDR_CFGB 0x05002C +#define RDR_SUSSYSTEM_ID_CFG 0x05002C + +//***************************************************************************** +#define RDR_CFGC 0x050030 + +//***************************************************************************** +#define RDR_CFGD 0x050034 + +//***************************************************************************** +#define RDR_CFGE 0x050038 + +//***************************************************************************** +#define RDR_CFGF 0x05003C + +//***************************************************************************** +// PCI-Express Capabilities +//***************************************************************************** +#define RDR_PECAP 0x050040 + +//***************************************************************************** +#define RDR_PEDEVCAP 0x050044 + +//***************************************************************************** +#define RDR_PEDEVSC 0x050048 + +//***************************************************************************** +#define RDR_PELINKCAP 0x05004C + +//***************************************************************************** +#define RDR_PELINKSC 0x050050 + +//***************************************************************************** +#define RDR_PMICAP 0x050080 + +//***************************************************************************** +#define RDR_PMCSR 0x050084 + +//***************************************************************************** +#define RDR_VPDCAP 0x050090 + +//***************************************************************************** +#define RDR_VPDDATA 0x050094 + +//***************************************************************************** +#define RDR_MSICAP 0x0500A0 + +//***************************************************************************** +#define RDR_MSIARL 0x0500A4 + +//***************************************************************************** +#define RDR_MSIARU 0x0500A8 + +//***************************************************************************** +#define RDR_MSIDATA 0x0500AC + +//***************************************************************************** +// PCI Express Extended Capabilities +//***************************************************************************** +#define RDR_AERXCAP 0x050100 + +//***************************************************************************** +#define RDR_AERUESTA 0x050104 + +//***************************************************************************** +#define RDR_AERUEMSK 0x050108 + +//***************************************************************************** +#define RDR_AERUESEV 0x05010C + +//***************************************************************************** +#define RDR_AERCESTA 0x050110 + +//***************************************************************************** +#define RDR_AERCEMSK 0x050114 + +//***************************************************************************** +#define RDR_AERCC 0x050118 + +//***************************************************************************** +#define RDR_AERHL0 0x05011C + +//***************************************************************************** +#define RDR_AERHL1 0x050120 + +//***************************************************************************** +#define RDR_AERHL2 0x050124 + +//***************************************************************************** +#define RDR_AERHL3 0x050128 + +//***************************************************************************** +#define RDR_VCXCAP 0x050200 + +//***************************************************************************** +#define RDR_VCCAP1 0x050204 + +//***************************************************************************** +#define RDR_VCCAP2 0x050208 + +//***************************************************************************** +#define RDR_VCSC 0x05020C + +//***************************************************************************** +#define RDR_VCR0_CAP 0x050210 + +//***************************************************************************** +#define RDR_VCR0_CTRL 0x050214 + +//***************************************************************************** +#define RDR_VCR0_STAT 0x050218 + +//***************************************************************************** +#define RDR_VCR1_CAP 0x05021C + +//***************************************************************************** +#define RDR_VCR1_CTRL 0x050220 + +//***************************************************************************** +#define RDR_VCR1_STAT 0x050224 + +//***************************************************************************** +#define RDR_VCR2_CAP 0x050228 + +//***************************************************************************** +#define RDR_VCR2_CTRL 0x05022C + +//***************************************************************************** +#define RDR_VCR2_STAT 0x050230 + +//***************************************************************************** +#define RDR_VCR3_CAP 0x050234 + +//***************************************************************************** +#define RDR_VCR3_CTRL 0x050238 + +//***************************************************************************** +#define RDR_VCR3_STAT 0x05023C + +//***************************************************************************** +#define RDR_VCARB0 0x050240 + +//***************************************************************************** +#define RDR_VCARB1 0x050244 + +//***************************************************************************** +#define RDR_VCARB2 0x050248 + +//***************************************************************************** +#define RDR_VCARB3 0x05024C + +//***************************************************************************** +#define RDR_VCARB4 0x050250 + +//***************************************************************************** +#define RDR_VCARB5 0x050254 + +//***************************************************************************** +#define RDR_VCARB6 0x050258 + +//***************************************************************************** +#define RDR_VCARB7 0x05025C + +//***************************************************************************** +#define RDR_RDRSTAT0 0x050300 + +//***************************************************************************** +#define RDR_RDRSTAT1 0x050304 + +//***************************************************************************** +#define RDR_RDRCTL0 0x050308 + +//***************************************************************************** +#define RDR_RDRCTL1 0x05030C + +//***************************************************************************** +// Transaction Layer Registers +//***************************************************************************** +#define RDR_TLSTAT0 0x050310 + +//***************************************************************************** +#define RDR_TLSTAT1 0x050314 + +//***************************************************************************** +#define RDR_TLCTL0 0x050318 +#define FLD_CFG_UR_CPL_MODE 0x00000040 +#define FLD_CFG_CORR_ERR_QUITE 0x00000020 +#define FLD_CFG_RCB_CK_EN 0x00000010 +#define FLD_CFG_BNDRY_CK_EN 0x00000008 +#define FLD_CFG_BYTE_EN_CK_EN 0x00000004 +#define FLD_CFG_RELAX_ORDER_MSK 0x00000002 +#define FLD_CFG_TAG_ORDER_EN 0x00000001 + +//***************************************************************************** +#define RDR_TLCTL1 0x05031C + +//***************************************************************************** +#define RDR_REQRCAL 0x050320 + +//***************************************************************************** +#define RDR_REQRCAU 0x050324 + +//***************************************************************************** +#define RDR_REQEPA 0x050328 + +//***************************************************************************** +#define RDR_REQCTRL 0x05032C + +//***************************************************************************** +#define RDR_REQSTAT 0x050330 + +//***************************************************************************** +#define RDR_TL_TEST 0x050334 + +//***************************************************************************** +#define RDR_VCR01_CTL 0x050348 + +//***************************************************************************** +#define RDR_VCR23_CTL 0x05034C + +//***************************************************************************** +#define RDR_RX_VCR0_FC 0x050350 + +//***************************************************************************** +#define RDR_RX_VCR1_FC 0x050354 + +//***************************************************************************** +#define RDR_RX_VCR2_FC 0x050358 + +//***************************************************************************** +#define RDR_RX_VCR3_FC 0x05035C + +//***************************************************************************** +// Data Link Layer Registers +//***************************************************************************** +#define RDR_DLLSTAT 0x050360 + +//***************************************************************************** +#define RDR_DLLCTRL 0x050364 + +//***************************************************************************** +#define RDR_REPLAYTO 0x050368 + +//***************************************************************************** +#define RDR_ACKLATTO 0x05036C + +//***************************************************************************** +// MAC Layer Registers +//***************************************************************************** +#define RDR_MACSTAT0 0x050380 + +//***************************************************************************** +#define RDR_MACSTAT1 0x050384 + +//***************************************************************************** +#define RDR_MACCTRL0 0x050388 + +//***************************************************************************** +#define RDR_MACCTRL1 0x05038C + +//***************************************************************************** +#define RDR_MACCTRL2 0x050390 + +//***************************************************************************** +#define RDR_MAC_LB_DATA 0x050394 + +//***************************************************************************** +#define RDR_L0S_EXIT_LAT 0x050398 + +//***************************************************************************** +// DMAC +//***************************************************************************** +#define DMA1_PTR1 0x100000 // DMA Current Ptr : Ch#1 + +//***************************************************************************** +#define DMA2_PTR1 0x100004 // DMA Current Ptr : Ch#2 + +//***************************************************************************** +#define DMA3_PTR1 0x100008 // DMA Current Ptr : Ch#3 + +//***************************************************************************** +#define DMA4_PTR1 0x10000C // DMA Current Ptr : Ch#4 + +//***************************************************************************** +#define DMA5_PTR1 0x100010 // DMA Current Ptr : Ch#5 + +//***************************************************************************** +#define DMA6_PTR1 0x100014 // DMA Current Ptr : Ch#6 + +//***************************************************************************** +#define DMA7_PTR1 0x100018 // DMA Current Ptr : Ch#7 + +//***************************************************************************** +#define DMA8_PTR1 0x10001C // DMA Current Ptr : Ch#8 + +//***************************************************************************** +#define DMA9_PTR1 0x100020 // DMA Current Ptr : Ch#9 + +//***************************************************************************** +#define DMA10_PTR1 0x100024 // DMA Current Ptr : Ch#10 + +//***************************************************************************** +#define DMA11_PTR1 0x100028 // DMA Current Ptr : Ch#11 + +//***************************************************************************** +#define DMA12_PTR1 0x10002C // DMA Current Ptr : Ch#12 + +//***************************************************************************** +#define DMA13_PTR1 0x100030 // DMA Current Ptr : Ch#13 + +//***************************************************************************** +#define DMA14_PTR1 0x100034 // DMA Current Ptr : Ch#14 + +//***************************************************************************** +#define DMA15_PTR1 0x100038 // DMA Current Ptr : Ch#15 + +//***************************************************************************** +#define DMA16_PTR1 0x10003C // DMA Current Ptr : Ch#16 + +//***************************************************************************** +#define DMA17_PTR1 0x100040 // DMA Current Ptr : Ch#17 + +//***************************************************************************** +#define DMA18_PTR1 0x100044 // DMA Current Ptr : Ch#18 + +//***************************************************************************** +#define DMA19_PTR1 0x100048 // DMA Current Ptr : Ch#19 + +//***************************************************************************** +#define DMA20_PTR1 0x10004C // DMA Current Ptr : Ch#20 + +//***************************************************************************** +#define DMA21_PTR1 0x100050 // DMA Current Ptr : Ch#21 + +//***************************************************************************** +#define DMA22_PTR1 0x100054 // DMA Current Ptr : Ch#22 + +//***************************************************************************** +#define DMA23_PTR1 0x100058 // DMA Current Ptr : Ch#23 + +//***************************************************************************** +#define DMA24_PTR1 0x10005C // DMA Current Ptr : Ch#24 + +//***************************************************************************** +#define DMA25_PTR1 0x100060 // DMA Current Ptr : Ch#25 + +//***************************************************************************** +#define DMA26_PTR1 0x100064 // DMA Current Ptr : Ch#26 + + +//***************************************************************************** +#define DMA1_PTR2 0x100080 // DMA Tab Ptr : Ch#1 + +//***************************************************************************** +#define DMA2_PTR2 0x100084 // DMA Tab Ptr : Ch#2 + +//***************************************************************************** +#define DMA3_PTR2 0x100088 // DMA Tab Ptr : Ch#3 + +//***************************************************************************** +#define DMA4_PTR2 0x10008C // DMA Tab Ptr : Ch#4 + +//***************************************************************************** +#define DMA5_PTR2 0x100090 // DMA Tab Ptr : Ch#5 + +//***************************************************************************** +#define DMA6_PTR2 0x100094 // DMA Tab Ptr : Ch#6 + +//***************************************************************************** +#define DMA7_PTR2 0x100098 // DMA Tab Ptr : Ch#7 + +//***************************************************************************** +#define DMA8_PTR2 0x10009C // DMA Tab Ptr : Ch#8 + +//***************************************************************************** +#define DMA9_PTR2 0x1000A0 // DMA Tab Ptr : Ch#9 + +//***************************************************************************** +#define DMA10_PTR2 0x1000A4 // DMA Tab Ptr : Ch#10 + +//***************************************************************************** +#define DMA11_PTR2 0x1000A8 // DMA Tab Ptr : Ch#11 + +//***************************************************************************** +#define DMA12_PTR2 0x1000AC // DMA Tab Ptr : Ch#12 + +//***************************************************************************** +#define DMA13_PTR2 0x1000B0 // DMA Tab Ptr : Ch#13 + +//***************************************************************************** +#define DMA14_PTR2 0x1000B4 // DMA Tab Ptr : Ch#14 + +//***************************************************************************** +#define DMA15_PTR2 0x1000B8 // DMA Tab Ptr : Ch#15 + +//***************************************************************************** +#define DMA16_PTR2 0x1000BC // DMA Tab Ptr : Ch#16 + +//***************************************************************************** +#define DMA17_PTR2 0x1000C0 // DMA Tab Ptr : Ch#17 + +//***************************************************************************** +#define DMA18_PTR2 0x1000C4 // DMA Tab Ptr : Ch#18 + +//***************************************************************************** +#define DMA19_PTR2 0x1000C8 // DMA Tab Ptr : Ch#19 + +//***************************************************************************** +#define DMA20_PTR2 0x1000CC // DMA Tab Ptr : Ch#20 + +//***************************************************************************** +#define DMA21_PTR2 0x1000D0 // DMA Tab Ptr : Ch#21 + +//***************************************************************************** +#define DMA22_PTR2 0x1000D4 // DMA Tab Ptr : Ch#22 + +//***************************************************************************** +#define DMA23_PTR2 0x1000D8 // DMA Tab Ptr : Ch#23 + +//***************************************************************************** +#define DMA24_PTR2 0x1000DC // DMA Tab Ptr : Ch#24 + +//***************************************************************************** +#define DMA25_PTR2 0x1000E0 // DMA Tab Ptr : Ch#25 + +//***************************************************************************** +#define DMA26_PTR2 0x1000E4 // DMA Tab Ptr : Ch#26 + + + +//***************************************************************************** +#define DMA1_CNT1 0x100100 // DMA BuFFer Size : Ch#1 + +//***************************************************************************** +#define DMA2_CNT1 0x100104 // DMA BuFFer Size : Ch#2 + +//***************************************************************************** +#define DMA3_CNT1 0x100108 // DMA BuFFer Size : Ch#3 + +//***************************************************************************** +#define DMA4_CNT1 0x10010C // DMA BuFFer Size : Ch#4 + +//***************************************************************************** +#define DMA5_CNT1 0x100110 // DMA BuFFer Size : Ch#5 + +//***************************************************************************** +#define DMA6_CNT1 0x100114 // DMA BuFFer Size : Ch#6 + +//***************************************************************************** +#define DMA7_CNT1 0x100118 // DMA BuFFer Size : Ch#7 + +//***************************************************************************** +#define DMA8_CNT1 0x10011C // DMA BuFFer Size : Ch#8 + +//***************************************************************************** +#define DMA9_CNT1 0x100120 // DMA BuFFer Size : Ch#9 + +//***************************************************************************** +#define DMA10_CNT1 0x100124 // DMA BuFFer Size : Ch#10 + +//***************************************************************************** +#define DMA11_CNT1 0x100128 // DMA BuFFer Size : Ch#11 + +//***************************************************************************** +#define DMA12_CNT1 0x10012C // DMA BuFFer Size : Ch#12 + +//***************************************************************************** +#define DMA13_CNT1 0x100130 // DMA BuFFer Size : Ch#13 + +//***************************************************************************** +#define DMA14_CNT1 0x100134 // DMA BuFFer Size : Ch#14 + +//***************************************************************************** +#define DMA15_CNT1 0x100138 // DMA BuFFer Size : Ch#15 + +//***************************************************************************** +#define DMA16_CNT1 0x10013C // DMA BuFFer Size : Ch#16 + +//***************************************************************************** +#define DMA17_CNT1 0x100140 // DMA BuFFer Size : Ch#17 + +//***************************************************************************** +#define DMA18_CNT1 0x100144 // DMA BuFFer Size : Ch#18 + +//***************************************************************************** +#define DMA19_CNT1 0x100148 // DMA BuFFer Size : Ch#19 + +//***************************************************************************** +#define DMA20_CNT1 0x10014C // DMA BuFFer Size : Ch#20 + +//***************************************************************************** +#define DMA21_CNT1 0x100150 // DMA BuFFer Size : Ch#21 + +//***************************************************************************** +#define DMA22_CNT1 0x100154 // DMA BuFFer Size : Ch#22 + +//***************************************************************************** +#define DMA23_CNT1 0x100158 // DMA BuFFer Size : Ch#23 + +//***************************************************************************** +#define DMA24_CNT1 0x10015C // DMA BuFFer Size : Ch#24 + +//***************************************************************************** +#define DMA25_CNT1 0x100160 // DMA BuFFer Size : Ch#25 + +//***************************************************************************** +#define DMA26_CNT1 0x100164 // DMA BuFFer Size : Ch#26 + + +//***************************************************************************** +#define DMA1_CNT2 0x100180 // DMA Table Size : Ch#1 + +//***************************************************************************** +#define DMA2_CNT2 0x100184 // DMA Table Size : Ch#2 + +//***************************************************************************** +#define DMA3_CNT2 0x100188 // DMA Table Size : Ch#3 + +//***************************************************************************** +#define DMA4_CNT2 0x10018C // DMA Table Size : Ch#4 + +//***************************************************************************** +#define DMA5_CNT2 0x100190 // DMA Table Size : Ch#5 + +//***************************************************************************** +#define DMA6_CNT2 0x100194 // DMA Table Size : Ch#6 + +//***************************************************************************** +#define DMA7_CNT2 0x100198 // DMA Table Size : Ch#7 + +//***************************************************************************** +#define DMA8_CNT2 0x10019C // DMA Table Size : Ch#8 + +//***************************************************************************** +#define DMA9_CNT2 0x1001A0 // DMA Table Size : Ch#9 + +//***************************************************************************** +#define DMA10_CNT2 0x1001A4 // DMA Table Size : Ch#10 + +//***************************************************************************** +#define DMA11_CNT2 0x1001A8 // DMA Table Size : Ch#11 + +//***************************************************************************** +#define DMA12_CNT2 0x1001AC // DMA Table Size : Ch#12 + +//***************************************************************************** +#define DMA13_CNT2 0x1001B0 // DMA Table Size : Ch#13 + +//***************************************************************************** +#define DMA14_CNT2 0x1001B4 // DMA Table Size : Ch#14 + +//***************************************************************************** +#define DMA15_CNT2 0x1001B8 // DMA Table Size : Ch#15 + +//***************************************************************************** +#define DMA16_CNT2 0x1001BC // DMA Table Size : Ch#16 + +//***************************************************************************** +#define DMA17_CNT2 0x1001C0 // DMA Table Size : Ch#17 + +//***************************************************************************** +#define DMA18_CNT2 0x1001C4 // DMA Table Size : Ch#18 + +//***************************************************************************** +#define DMA19_CNT2 0x1001C8 // DMA Table Size : Ch#19 + +//***************************************************************************** +#define DMA20_CNT2 0x1001CC // DMA Table Size : Ch#20 + +//***************************************************************************** +#define DMA21_CNT2 0x1001D0 // DMA Table Size : Ch#21 + +//***************************************************************************** +#define DMA22_CNT2 0x1001D4 // DMA Table Size : Ch#22 + +//***************************************************************************** +#define DMA23_CNT2 0x1001D8 // DMA Table Size : Ch#23 + +//***************************************************************************** +#define DMA24_CNT2 0x1001DC // DMA Table Size : Ch#24 + +//***************************************************************************** +#define DMA25_CNT2 0x1001E0 // DMA Table Size : Ch#25 + +//***************************************************************************** +#define DMA26_CNT2 0x1001E4 // DMA Table Size : Ch#26 + + + +//***************************************************************************** + // ITG +//***************************************************************************** +#define TM_CNT_LDW 0x110000 // Timer : Counter low + +//***************************************************************************** +#define TM_CNT_UW 0x110004 // Timer : Counter high word + +//***************************************************************************** +#define TM_LMT_LDW 0x110008 // Timer : Limit low + +//***************************************************************************** +#define TM_LMT_UW 0x11000C // Timer : Limit high word + +//***************************************************************************** +#define GP0_IO 0x110010 // GPIO output enables data I/O +#define FLD_GP_OE 0x00FF0000 // GPIO: GP_OE output enable +#define FLD_GP_IN 0x0000FF00 // GPIO: GP_IN status +#define FLD_GP_OUT 0x000000FF // GPIO: GP_OUT control + +//***************************************************************************** +#define GPIO_ISM 0x110014 // GPIO interrupt sensitivity mode +#define FLD_GP_ISM_SNS 0x00000070 +#define FLD_GP_ISM_POL 0x00000007 + +//***************************************************************************** +#define SOFT_RESET 0x11001C // Output system reset reg +#define FLD_PECOS_SOFT_RESET 0x00000001 + +//***************************************************************************** +#define MC416_RWD 0x110020 // MC416 GPIO[18:3] pin +#define MC416_OEN 0x110024 // Output enable of GPIO[18:3] +#define MC416_CTL 0x110028 + +//***************************************************************************** +#define ALT_PIN_OUT_SEL 0x11002C // Alternate GPIO output select + +#define FLD_ALT_GPIO_OUT_SEL 0xF0000000 +// 0 Disabled <-- default +// 1 GPIO[0] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] +// 8 ATT_IF + +#define FLD_AUX_PLL_CLK_ALT_SEL 0x0F000000 +// 0 AUX_PLL_CLK<-- default +// 1 GPIO[2] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_IR_TX_ALT_SEL 0x00F00000 +// 0 IR_TX <-- default +// 1 GPIO[1] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_IR_RX_ALT_SEL 0x000F0000 +// 0 IR_RX <-- default +// 1 GPIO[0] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_GPIO10_ALT_SEL 0x0000F000 +// 0 GPIO[10] <-- default +// 1 GPIO[0] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_GPIO2_ALT_SEL 0x00000F00 +// 0 GPIO[2] <-- default +// 1 GPIO[1] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_GPIO1_ALT_SEL 0x000000F0 +// 0 GPIO[1] <-- default +// 1 GPIO[0] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_GPIO0_ALT_SEL 0x0000000F +// 0 GPIO[0] <-- default +// 1 GPIO[1] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define ALT_PIN_IN_SEL 0x110030 // Alternate GPIO input select + +#define FLD_GPIO10_ALT_IN_SEL 0x0000F000 +// 0 GPIO[10] <-- default +// 1 IR_RX +// 2 IR_TX +// 3 AUX_PLL_CLK +// 4 IF_ATT_SEL +// 5 GPIO[0] +// 6 GPIO[1] +// 7 GPIO[2] + +#define FLD_GPIO2_ALT_IN_SEL 0x00000F00 +// 0 GPIO[2] <-- default +// 1 IR_RX +// 2 IR_TX +// 3 AUX_PLL_CLK +// 4 IF_ATT_SEL + +#define FLD_GPIO1_ALT_IN_SEL 0x000000F0 +// 0 GPIO[1] <-- default +// 1 IR_RX +// 2 IR_TX +// 3 AUX_PLL_CLK +// 4 IF_ATT_SEL + +#define FLD_GPIO0_ALT_IN_SEL 0x0000000F +// 0 GPIO[0] <-- default +// 1 IR_RX +// 2 IR_TX +// 3 AUX_PLL_CLK +// 4 IF_ATT_SEL + +//***************************************************************************** +#define TEST_BUS_CTL1 0x110040 // Test bus control register #1 + +//***************************************************************************** +#define TEST_BUS_CTL2 0x110044 // Test bus control register #2 + +//***************************************************************************** +#define CLK_DELAY 0x110048 // Clock delay +#define FLD_MOE_CLK_DIS 0x80000000 // Disable MoE clock + + +//***************************************************************************** +#define PAD_CTRL 0x110068 // Pad drive strength control + +//***************************************************************************** +#define MBIST_CTRL 0x110050 // SRAM memory built-in self test control + +//***************************************************************************** +#define MBIST_STAT 0x110054 // SRAM memory built-in self test status + +//***************************************************************************** +// PLL registers +//***************************************************************************** +#define PLL_A_INT_FRAC 0x110088 +#define PLL_A_POST_STAT_BIST 0x11008C +#define PLL_B_INT_FRAC 0x110090 +#define PLL_B_POST_STAT_BIST 0x110094 +#define PLL_C_INT_FRAC 0x110098 +#define PLL_C_POST_STAT_BIST 0x11009C +#define PLL_D_INT_FRAC 0x1100A0 +#define PLL_D_POST_STAT_BIST 0x1100A4 + +#define CLK_RST 0x11002C +#define FLD_VID_I_CLK_NOE 0x00001000 +#define FLD_VID_J_CLK_NOE 0x00002000 +#define FLD_USE_ALT_PLL_REF 0x00004000 + +#define VID_CH_MODE_SEL 0x110078 +#define VID_CH_CLK_SEL 0x11007C + + +//***************************************************************************** +#define VBI_A_DMA 0x130008 // VBI A DMA data port + +//***************************************************************************** +#define VID_A_VIP_CTL 0x130080 // Video A VIP format control +#define FLD_VIP_MODE 0x00000001 + +//***************************************************************************** +#define VID_A_PIXEL_FRMT 0x130084 // Video A pixel format +#define FLD_VID_A_GAMMA_DIS 0x00000008 +#define FLD_VID_A_FORMAT 0x00000007 +#define FLD_VID_A_GAMMA_FACTOR 0x00000010 + +//***************************************************************************** +#define VID_A_VBI_CTL 0x130088 // Video A VBI miscellaneous control +#define FLD_VID_A_VIP_EXT 0x00000003 + +//***************************************************************************** +#define VID_B_DMA 0x130100 // Video B DMA data port + +//***************************************************************************** +#define VBI_B_DMA 0x130108 // VBI B DMA data port + +//***************************************************************************** +#define VID_B_SRC_SEL 0x130144 // Video B source select +#define FLD_VID_B_SRC_SEL 0x00000000 + +//***************************************************************************** +#define VID_B_LNGTH 0x130150 // Video B line length +#define FLD_VID_B_LN_LNGTH 0x00000FFF + +//***************************************************************************** +#define VID_B_VIP_CTL 0x130180 // Video B VIP format control + +//***************************************************************************** +#define VID_B_PIXEL_FRMT 0x130184 // Video B pixel format +#define FLD_VID_B_GAMMA_DIS 0x00000008 +#define FLD_VID_B_FORMAT 0x00000007 +#define FLD_VID_B_GAMMA_FACTOR 0x00000010 + +//***************************************************************************** +#define VID_C_DMA 0x130200 // Video C DMA data port + +//***************************************************************************** +#define VID_C_LNGTH 0x130250 // Video C line length +#define FLD_VID_C_LN_LNGTH 0x00000FFF + + +//***************************************************************************** +// Video Destination Channels +//***************************************************************************** + +#define VID_DST_A_GPCNT 0x130020 // Video A general purpose counter +#define VID_DST_B_GPCNT 0x130120 // Video B general purpose counter +#define VID_DST_C_GPCNT 0x130220 // Video C general purpose counter +#define VID_DST_D_GPCNT 0x130320 // Video D general purpose counter +#define VID_DST_E_GPCNT 0x130420 // Video E general purpose counter +#define VID_DST_F_GPCNT 0x130520 // Video F general purpose counter +#define VID_DST_G_GPCNT 0x130620 // Video G general purpose counter +#define VID_DST_H_GPCNT 0x130720 // Video H general purpose counter + +//***************************************************************************** + +#define VID_DST_A_GPCNT_CTL 0x130030 // Video A general purpose control +#define VID_DST_B_GPCNT_CTL 0x130130 // Video B general purpose control +#define VID_DST_C_GPCNT_CTL 0x130230 // Video C general purpose control +#define VID_DST_D_GPCNT_CTL 0x130330 // Video D general purpose control +#define VID_DST_E_GPCNT_CTL 0x130430 // Video E general purpose control +#define VID_DST_F_GPCNT_CTL 0x130530 // Video F general purpose control +#define VID_DST_G_GPCNT_CTL 0x130630 // Video G general purpose control +#define VID_DST_H_GPCNT_CTL 0x130730 // Video H general purpose control + + +//***************************************************************************** + +#define VID_DST_A_DMA_CTL 0x130040 // Video A DMA control +#define VID_DST_B_DMA_CTL 0x130140 // Video B DMA control +#define VID_DST_C_DMA_CTL 0x130240 // Video C DMA control +#define VID_DST_D_DMA_CTL 0x130340 // Video D DMA control +#define VID_DST_E_DMA_CTL 0x130440 // Video E DMA control +#define VID_DST_F_DMA_CTL 0x130540 // Video F DMA control +#define VID_DST_G_DMA_CTL 0x130640 // Video G DMA control +#define VID_DST_H_DMA_CTL 0x130740 // Video H DMA control + +#define FLD_VID_RISC_EN 0x00000010 +#define FLD_VID_FIFO_EN 0x00000001 + +//***************************************************************************** + +#define VID_DST_A_VIP_CTL 0x130080 // Video A VIP control +#define VID_DST_B_VIP_CTL 0x130180 // Video B VIP control +#define VID_DST_C_VIP_CTL 0x130280 // Video C VIP control +#define VID_DST_D_VIP_CTL 0x130380 // Video D VIP control +#define VID_DST_E_VIP_CTL 0x130480 // Video E VIP control +#define VID_DST_F_VIP_CTL 0x130580 // Video F VIP control +#define VID_DST_G_VIP_CTL 0x130680 // Video G VIP control +#define VID_DST_H_VIP_CTL 0x130780 // Video H VIP control + +//***************************************************************************** + +#define VID_DST_A_PIX_FRMT 0x130084 // Video A Pixel format +#define VID_DST_B_PIX_FRMT 0x130184 // Video B Pixel format +#define VID_DST_C_PIX_FRMT 0x130284 // Video C Pixel format +#define VID_DST_D_PIX_FRMT 0x130384 // Video D Pixel format +#define VID_DST_E_PIX_FRMT 0x130484 // Video E Pixel format +#define VID_DST_F_PIX_FRMT 0x130584 // Video F Pixel format +#define VID_DST_G_PIX_FRMT 0x130684 // Video G Pixel format +#define VID_DST_H_PIX_FRMT 0x130784 // Video H Pixel format + +//***************************************************************************** +// Video Source Channels +//***************************************************************************** + +#define VID_SRC_A_GPCNT_CTL 0x130804 // Video A general purpose control +#define VID_SRC_B_GPCNT_CTL 0x130904 // Video B general purpose control +#define VID_SRC_C_GPCNT_CTL 0x130A04 // Video C general purpose control +#define VID_SRC_D_GPCNT_CTL 0x130B04 // Video D general purpose control +#define VID_SRC_E_GPCNT_CTL 0x130C04 // Video E general purpose control +#define VID_SRC_F_GPCNT_CTL 0x130D04 // Video F general purpose control +#define VID_SRC_I_GPCNT_CTL 0x130E04 // Video I general purpose control +#define VID_SRC_J_GPCNT_CTL 0x130F04 // Video J general purpose control + +//***************************************************************************** + +#define VID_SRC_A_GPCNT 0x130808 // Video A general purpose counter +#define VID_SRC_B_GPCNT 0x130908 // Video B general purpose counter +#define VID_SRC_C_GPCNT 0x130A08 // Video C general purpose counter +#define VID_SRC_D_GPCNT 0x130B08 // Video D general purpose counter +#define VID_SRC_E_GPCNT 0x130C08 // Video E general purpose counter +#define VID_SRC_F_GPCNT 0x130D08 // Video F general purpose counter +#define VID_SRC_I_GPCNT 0x130E08 // Video I general purpose counter +#define VID_SRC_J_GPCNT 0x130F08 // Video J general purpose counter + +//***************************************************************************** + +#define VID_SRC_A_DMA_CTL 0x13080C // Video A DMA control +#define VID_SRC_B_DMA_CTL 0x13090C // Video B DMA control +#define VID_SRC_C_DMA_CTL 0x130A0C // Video C DMA control +#define VID_SRC_D_DMA_CTL 0x130B0C // Video D DMA control +#define VID_SRC_E_DMA_CTL 0x130C0C // Video E DMA control +#define VID_SRC_F_DMA_CTL 0x130D0C // Video F DMA control +#define VID_SRC_I_DMA_CTL 0x130E0C // Video I DMA control +#define VID_SRC_J_DMA_CTL 0x130F0C // Video J DMA control + +#define FLD_APB_RISC_EN 0x00000010 +#define FLD_APB_FIFO_EN 0x00000001 + +//***************************************************************************** + +#define VID_SRC_A_FMT_CTL 0x130810 // Video A format control +#define VID_SRC_B_FMT_CTL 0x130910 // Video B format control +#define VID_SRC_C_FMT_CTL 0x130A10 // Video C format control +#define VID_SRC_D_FMT_CTL 0x130B10 // Video D format control +#define VID_SRC_E_FMT_CTL 0x130C10 // Video E format control +#define VID_SRC_F_FMT_CTL 0x130D10 // Video F format control +#define VID_SRC_I_FMT_CTL 0x130E10 // Video I format control +#define VID_SRC_J_FMT_CTL 0x130F10 // Video J format control + +//***************************************************************************** + +#define VID_SRC_A_ACTIVE_CTL1 0x130814 // Video A active control 1 +#define VID_SRC_B_ACTIVE_CTL1 0x130914 // Video B active control 1 +#define VID_SRC_C_ACTIVE_CTL1 0x130A14 // Video C active control 1 +#define VID_SRC_D_ACTIVE_CTL1 0x130B14 // Video D active control 1 +#define VID_SRC_E_ACTIVE_CTL1 0x130C14 // Video E active control 1 +#define VID_SRC_F_ACTIVE_CTL1 0x130D14 // Video F active control 1 +#define VID_SRC_I_ACTIVE_CTL1 0x130E14 // Video I active control 1 +#define VID_SRC_J_ACTIVE_CTL1 0x130F14 // Video J active control 1 + +//***************************************************************************** + +#define VID_SRC_A_ACTIVE_CTL2 0x130818 // Video A active control 2 +#define VID_SRC_B_ACTIVE_CTL2 0x130918 // Video B active control 2 +#define VID_SRC_C_ACTIVE_CTL2 0x130A18 // Video C active control 2 +#define VID_SRC_D_ACTIVE_CTL2 0x130B18 // Video D active control 2 +#define VID_SRC_E_ACTIVE_CTL2 0x130C18 // Video E active control 2 +#define VID_SRC_F_ACTIVE_CTL2 0x130D18 // Video F active control 2 +#define VID_SRC_I_ACTIVE_CTL2 0x130E18 // Video I active control 2 +#define VID_SRC_J_ACTIVE_CTL2 0x130F18 // Video J active control 2 + +//***************************************************************************** + +#define VID_SRC_A_CDT_SZ 0x13081C // Video A CDT size +#define VID_SRC_B_CDT_SZ 0x13091C // Video B CDT size +#define VID_SRC_C_CDT_SZ 0x130A1C // Video C CDT size +#define VID_SRC_D_CDT_SZ 0x130B1C // Video D CDT size +#define VID_SRC_E_CDT_SZ 0x130C1C // Video E CDT size +#define VID_SRC_F_CDT_SZ 0x130D1C // Video F CDT size +#define VID_SRC_I_CDT_SZ 0x130E1C // Video I CDT size +#define VID_SRC_J_CDT_SZ 0x130F1C // Video J CDT size + +//***************************************************************************** +// Audio I/F +//***************************************************************************** +#define AUD_DST_A_DMA 0x140000 // Audio Int A DMA data port +#define AUD_SRC_A_DMA 0x140008 // Audio Int A DMA data port + +#define AUD_A_GPCNT 0x140010 // Audio Int A gp counter +#define FLD_AUD_A_GP_CNT 0x0000FFFF + +#define AUD_A_GPCNT_CTL 0x140014 // Audio Int A gp control + +#define AUD_A_LNGTH 0x140018 // Audio Int A line length + +#define AUD_A_CFG 0x14001C // Audio Int A configuration + +//***************************************************************************** +#define AUD_DST_B_DMA 0x140100 // Audio Int B DMA data port +#define AUD_SRC_B_DMA 0x140108 // Audio Int B DMA data port + +#define AUD_B_GPCNT 0x140110 // Audio Int B gp counter +#define FLD_AUD_B_GP_CNT 0x0000FFFF + +#define AUD_B_GPCNT_CTL 0x140114 // Audio Int B gp control + +#define AUD_B_LNGTH 0x140118 // Audio Int B line length + +#define AUD_B_CFG 0x14011C // Audio Int B configuration + +//***************************************************************************** +#define AUD_DST_C_DMA 0x140200 // Audio Int C DMA data port +#define AUD_SRC_C_DMA 0x140208 // Audio Int C DMA data port + +#define AUD_C_GPCNT 0x140210 // Audio Int C gp counter +#define FLD_AUD_C_GP_CNT 0x0000FFFF + +#define AUD_C_GPCNT_CTL 0x140214 // Audio Int C gp control + +#define AUD_C_LNGTH 0x140218 // Audio Int C line length + +#define AUD_C_CFG 0x14021C // Audio Int C configuration + +//***************************************************************************** +#define AUD_DST_D_DMA 0x140300 // Audio Int D DMA data port +#define AUD_SRC_D_DMA 0x140308 // Audio Int D DMA data port + +#define AUD_D_GPCNT 0x140310 // Audio Int D gp counter +#define FLD_AUD_D_GP_CNT 0x0000FFFF + +#define AUD_D_GPCNT_CTL 0x140314 // Audio Int D gp control + +#define AUD_D_LNGTH 0x140318 // Audio Int D line length + +#define AUD_D_CFG 0x14031C // Audio Int D configuration + +//***************************************************************************** +#define AUD_SRC_E_DMA 0x140400 // Audio Int E DMA data port + +#define AUD_E_GPCNT 0x140410 // Audio Int E gp counter +#define FLD_AUD_E_GP_CNT 0x0000FFFF + +#define AUD_E_GPCNT_CTL 0x140414 // Audio Int E gp control + +#define AUD_E_CFG 0x14041C // Audio Int E configuration + +//***************************************************************************** + +#define FLD_AUD_DST_LN_LNGTH 0x00000FFF + +#define FLD_AUD_DST_PK_MODE 0x00004000 + +#define FLD_AUD_CLK_ENABLE 0x00000200 + +#define FLD_AUD_MASTER_MODE 0x00000002 + +#define FLD_AUD_SONY_MODE 0x00000001 + +#define FLD_AUD_CLK_SELECT_PLL_D 0x00001800 + +#define FLD_AUD_DST_ENABLE 0x00020000 + +#define FLD_AUD_SRC_ENABLE 0x00010000 + +//***************************************************************************** +#define AUD_INT_DMA_CTL 0x140500 // Audio Int DMA control + +#define FLD_AUD_SRC_E_RISC_EN 0x00008000 +#define FLD_AUD_SRC_C_RISC_EN 0x00004000 +#define FLD_AUD_SRC_B_RISC_EN 0x00002000 +#define FLD_AUD_SRC_A_RISC_EN 0x00001000 + +#define FLD_AUD_DST_D_RISC_EN 0x00000800 +#define FLD_AUD_DST_C_RISC_EN 0x00000400 +#define FLD_AUD_DST_B_RISC_EN 0x00000200 +#define FLD_AUD_DST_A_RISC_EN 0x00000100 + +#define FLD_AUD_SRC_E_FIFO_EN 0x00000080 +#define FLD_AUD_SRC_C_FIFO_EN 0x00000040 +#define FLD_AUD_SRC_B_FIFO_EN 0x00000020 +#define FLD_AUD_SRC_A_FIFO_EN 0x00000010 + +#define FLD_AUD_DST_D_FIFO_EN 0x00000008 +#define FLD_AUD_DST_C_FIFO_EN 0x00000004 +#define FLD_AUD_DST_B_FIFO_EN 0x00000002 +#define FLD_AUD_DST_A_FIFO_EN 0x00000001 + + +//***************************************************************************** +// +// Mobilygen Interface Registers +// +//***************************************************************************** +// Mobilygen Interface A +//***************************************************************************** +#define MB_IF_A_DMA 0x150000 // MBIF A DMA data port +#define MB_IF_A_GPCN 0x150008 // MBIF A GP counter +#define MB_IF_A_GPCN_CTRL 0x15000C +#define MB_IF_A_DMA_CTRL 0x150010 +#define MB_IF_A_LENGTH 0x150014 +#define MB_IF_A_HDMA_XFER_SZ 0x150018 +#define MB_IF_A_HCMD 0x15001C +#define MB_IF_A_HCONFIG 0x150020 +#define MB_IF_A_DATA_STRUCT_0 0x150024 +#define MB_IF_A_DATA_STRUCT_1 0x150028 +#define MB_IF_A_DATA_STRUCT_2 0x15002C +#define MB_IF_A_DATA_STRUCT_3 0x150030 +#define MB_IF_A_DATA_STRUCT_4 0x150034 +#define MB_IF_A_DATA_STRUCT_5 0x150038 +#define MB_IF_A_DATA_STRUCT_6 0x15003C +#define MB_IF_A_DATA_STRUCT_7 0x150040 +#define MB_IF_A_DATA_STRUCT_8 0x150044 +#define MB_IF_A_DATA_STRUCT_9 0x150048 +#define MB_IF_A_DATA_STRUCT_A 0x15004C +#define MB_IF_A_DATA_STRUCT_B 0x150050 +#define MB_IF_A_DATA_STRUCT_C 0x150054 +#define MB_IF_A_DATA_STRUCT_D 0x150058 +#define MB_IF_A_DATA_STRUCT_E 0x15005C +#define MB_IF_A_DATA_STRUCT_F 0x150060 +//***************************************************************************** +// Mobilygen Interface B +//***************************************************************************** +#define MB_IF_B_DMA 0x160000 // MBIF A DMA data port +#define MB_IF_B_GPCN 0x160008 // MBIF A GP counter +#define MB_IF_B_GPCN_CTRL 0x16000C +#define MB_IF_B_DMA_CTRL 0x160010 +#define MB_IF_B_LENGTH 0x160014 +#define MB_IF_B_HDMA_XFER_SZ 0x160018 +#define MB_IF_B_HCMD 0x16001C +#define MB_IF_B_HCONFIG 0x160020 +#define MB_IF_B_DATA_STRUCT_0 0x160024 +#define MB_IF_B_DATA_STRUCT_1 0x160028 +#define MB_IF_B_DATA_STRUCT_2 0x16002C +#define MB_IF_B_DATA_STRUCT_3 0x160030 +#define MB_IF_B_DATA_STRUCT_4 0x160034 +#define MB_IF_B_DATA_STRUCT_5 0x160038 +#define MB_IF_B_DATA_STRUCT_6 0x16003C +#define MB_IF_B_DATA_STRUCT_7 0x160040 +#define MB_IF_B_DATA_STRUCT_8 0x160044 +#define MB_IF_B_DATA_STRUCT_9 0x160048 +#define MB_IF_B_DATA_STRUCT_A 0x16004C +#define MB_IF_B_DATA_STRUCT_B 0x160050 +#define MB_IF_B_DATA_STRUCT_C 0x160054 +#define MB_IF_B_DATA_STRUCT_D 0x160058 +#define MB_IF_B_DATA_STRUCT_E 0x16005C +#define MB_IF_B_DATA_STRUCT_F 0x160060 + +// MB_DMA_CTRL +#define FLD_MB_IF_RISC_EN 0x00000010 +#define FLD_MB_IF_FIFO_EN 0x00000001 + +// MB_LENGTH +#define FLD_MB_IF_LN_LNGTH 0x00000FFF + +// MB_HCMD register +#define FLD_MB_HCMD_H_GO 0x80000000 +#define FLD_MB_HCMD_H_BUSY 0x40000000 +#define FLD_MB_HCMD_H_DMA_HOLD 0x10000000 +#define FLD_MB_HCMD_H_DMA_BUSY 0x08000000 +#define FLD_MB_HCMD_H_DMA_TYPE 0x04000000 +#define FLD_MB_HCMD_H_DMA_XACT 0x02000000 +#define FLD_MB_HCMD_H_RW_N 0x01000000 +#define FLD_MB_HCMD_H_ADDR 0x00FF0000 +#define FLD_MB_HCMD_H_DATA 0x0000FFFF + + +//***************************************************************************** +// I2C #1 +//***************************************************************************** +#define I2C1_ADDR 0x180000 // I2C #1 address +#define FLD_I2C_DADDR 0xfe000000 // RW [31:25] I2C Device Address + // RO [24] reserved +//***************************************************************************** +#define FLD_I2C_SADDR 0x00FFFFFF // RW [23:0] I2C Sub-address + +//***************************************************************************** +#define I2C1_WDATA 0x180004 // I2C #1 write data +#define FLD_I2C_WDATA 0xFFFFFFFF // RW [31:0] + +//***************************************************************************** +#define I2C1_CTRL 0x180008 // I2C #1 control +#define FLD_I2C_PERIOD 0xFF000000 // RW [31:24] +#define FLD_I2C_SCL_IN 0x00200000 // RW [21] +#define FLD_I2C_SDA_IN 0x00100000 // RW [20] + // RO [19:18] reserved +#define FLD_I2C_SCL_OUT 0x00020000 // RW [17] +#define FLD_I2C_SDA_OUT 0x00010000 // RW [16] + // RO [15] reserved +#define FLD_I2C_DATA_LEN 0x00007000 // RW [14:12] +#define FLD_I2C_SADDR_INC 0x00000800 // RW [11] + // RO [10:9] reserved +#define FLD_I2C_SADDR_LEN 0x00000300 // RW [9:8] + // RO [7:6] reserved +#define FLD_I2C_SOFT 0x00000020 // RW [5] +#define FLD_I2C_NOSTOP 0x00000010 // RW [4] +#define FLD_I2C_EXTEND 0x00000008 // RW [3] +#define FLD_I2C_SYNC 0x00000004 // RW [2] +#define FLD_I2C_READ_SA 0x00000002 // RW [1] +#define FLD_I2C_READ_WRN 0x00000001 // RW [0] + +//***************************************************************************** +#define I2C1_RDATA 0x18000C // I2C #1 read data +#define FLD_I2C_RDATA 0xFFFFFFFF // RO [31:0] + +//***************************************************************************** +#define I2C1_STAT 0x180010 // I2C #1 status +#define FLD_I2C_XFER_IN_PROG 0x00000002 // RO [1] +#define FLD_I2C_RACK 0x00000001 // RO [0] + +//***************************************************************************** +// I2C #2 +//***************************************************************************** +#define I2C2_ADDR 0x190000 // I2C #2 address + +//***************************************************************************** +#define I2C2_WDATA 0x190004 // I2C #2 write data + +//***************************************************************************** +#define I2C2_CTRL 0x190008 // I2C #2 control + +//***************************************************************************** +#define I2C2_RDATA 0x19000C // I2C #2 read data + +//***************************************************************************** +#define I2C2_STAT 0x190010 // I2C #2 status + +//***************************************************************************** +// I2C #3 +//***************************************************************************** +#define I2C3_ADDR 0x1A0000 // I2C #3 address + +//***************************************************************************** +#define I2C3_WDATA 0x1A0004 // I2C #3 write data + +//***************************************************************************** +#define I2C3_CTRL 0x1A0008 // I2C #3 control + +//***************************************************************************** +#define I2C3_RDATA 0x1A000C // I2C #3 read data + +//***************************************************************************** +#define I2C3_STAT 0x1A0010 // I2C #3 status + +//***************************************************************************** +// UART +//***************************************************************************** +#define UART_CTL 0x1B0000 // UART Control Register +#define FLD_LOOP_BACK_EN (1 << 7) // RW field - default 0 +#define FLD_RX_TRG_SZ (3 << 2) // RW field - default 0 +#define FLD_RX_EN (1 << 1) // RW field - default 0 +#define FLD_TX_EN (1 << 0) // RW field - default 0 + +//***************************************************************************** +#define UART_BRD 0x1B0004 // UART Baud Rate Divisor +#define FLD_BRD 0x0000FFFF // RW field - default 0x197 + +//***************************************************************************** +#define UART_DBUF 0x1B0008 // UART Tx/Rx Data BuFFer +#define FLD_DB 0xFFFFFFFF // RW field - default 0 + +//***************************************************************************** +#define UART_ISR 0x1B000C // UART Interrupt Status +#define FLD_RXD_TIMEOUT_EN (1 << 7) // RW field - default 0 +#define FLD_FRM_ERR_EN (1 << 6) // RW field - default 0 +#define FLD_RXD_RDY_EN (1 << 5) // RW field - default 0 +#define FLD_TXD_EMPTY_EN (1 << 4) // RW field - default 0 +#define FLD_RXD_OVERFLOW (1 << 3) // RW field - default 0 +#define FLD_FRM_ERR (1 << 2) // RW field - default 0 +#define FLD_RXD_RDY (1 << 1) // RW field - default 0 +#define FLD_TXD_EMPTY (1 << 0) // RW field - default 0 + +//***************************************************************************** +#define UART_CNT 0x1B0010 // UART Tx/Rx FIFO Byte Count +#define FLD_TXD_CNT (0x1F << 8) // RW field - default 0 +#define FLD_RXD_CNT (0x1F << 0) // RW field - default 0 + +//***************************************************************************** +// Motion Detection +#define MD_CH0_GRID_BLOCK_YCNT 0x170014 +#define MD_CH1_GRID_BLOCK_YCNT 0x170094 +#define MD_CH2_GRID_BLOCK_YCNT 0x170114 +#define MD_CH3_GRID_BLOCK_YCNT 0x170194 +#define MD_CH4_GRID_BLOCK_YCNT 0x170214 +#define MD_CH5_GRID_BLOCK_YCNT 0x170294 +#define MD_CH6_GRID_BLOCK_YCNT 0x170314 +#define MD_CH7_GRID_BLOCK_YCNT 0x170394 + +#define PIXEL_FRMT_422 4 +#define PIXEL_FRMT_411 5 +#define PIXEL_FRMT_Y8 6 + +#define PIXEL_ENGINE_VIP1 0 +#define PIXEL_ENGINE_VIP2 1 + +#endif //Athena_REGISTERS + + diff --git a/linux/drivers/staging/cx25821/cx25821-sram.h b/linux/drivers/staging/cx25821/cx25821-sram.h new file mode 100644 index 000000000..813063582 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-sram.h @@ -0,0 +1,266 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ATHENA_SRAM_H__ +#define __ATHENA_SRAM_H__ + +//#define RX_SRAM_START_SIZE = 0; // Start of reserved SRAM +#define VID_CMDS_SIZE 80 // Video CMDS size in bytes +#define AUDIO_CMDS_SIZE 80 // AUDIO CMDS size in bytes +#define MBIF_CMDS_SIZE 80 // MBIF CMDS size in bytes + +//#define RX_SRAM_POOL_START_SIZE = 0; // Start of useable RX SRAM for buffers +#define VID_IQ_SIZE 64 // VID instruction queue size in bytes +#define MBIF_IQ_SIZE 64 +#define AUDIO_IQ_SIZE 64 // AUD instruction queue size in bytes + +#define VID_CDT_SIZE 64 // VID cluster descriptor table size in bytes +#define MBIF_CDT_SIZE 64 // MBIF/HBI cluster descriptor table size in bytes +#define AUDIO_CDT_SIZE 48 // AUD cluster descriptor table size in bytes + +//#define RX_SRAM_POOL_FREE_SIZE = 16; // Start of available RX SRAM +//#define RX_SRAM_END_SIZE = 0; // End of RX SRAM + +//#define TX_SRAM_POOL_START_SIZE = 0; // Start of transmit pool SRAM +//#define MSI_DATA_SIZE = 64; // Reserved (MSI Data, RISC working stora + +#define VID_CLUSTER_SIZE 1440 // VID cluster data line +#define AUDIO_CLUSTER_SIZE 128 // AUDIO cluster data line +#define MBIF_CLUSTER_SIZE 1440 // MBIF/HBI cluster data line + + +//#define TX_SRAM_POOL_FREE_SIZE = 704; // Start of available TX SRAM +//#define TX_SRAM_END_SIZE = 0; // End of TX SRAM + +// Receive SRAM +#define RX_SRAM_START 0x10000 +#define VID_A_DOWN_CMDS 0x10000 +#define VID_B_DOWN_CMDS 0x10050 +#define VID_C_DOWN_CMDS 0x100A0 +#define VID_D_DOWN_CMDS 0x100F0 +#define VID_E_DOWN_CMDS 0x10140 +#define VID_F_DOWN_CMDS 0x10190 +#define VID_G_DOWN_CMDS 0x101E0 +#define VID_H_DOWN_CMDS 0x10230 +#define VID_A_UP_CMDS 0x10280 +#define VID_B_UP_CMDS 0x102D0 +#define VID_C_UP_CMDS 0x10320 +#define VID_D_UP_CMDS 0x10370 +#define VID_E_UP_CMDS 0x103C0 +#define VID_F_UP_CMDS 0x10410 +#define VID_I_UP_CMDS 0x10460 +#define VID_J_UP_CMDS 0x104B0 +#define AUD_A_DOWN_CMDS 0x10500 +#define AUD_B_DOWN_CMDS 0x10550 +#define AUD_C_DOWN_CMDS 0x105A0 +#define AUD_D_DOWN_CMDS 0x105F0 +#define AUD_A_UP_CMDS 0x10640 +#define AUD_B_UP_CMDS 0x10690 +#define AUD_C_UP_CMDS 0x106E0 +#define AUD_E_UP_CMDS 0x10730 +#define MBIF_A_DOWN_CMDS 0x10780 +#define MBIF_B_DOWN_CMDS 0x107D0 +#define DMA_SCRATCH_PAD 0x10820 // Scratch pad area from 0x10820 to 0x10B40 + +//#define RX_SRAM_POOL_START = 0x105B0; + +#define VID_A_IQ 0x11000 +#define VID_B_IQ 0x11040 +#define VID_C_IQ 0x11080 +#define VID_D_IQ 0x110C0 +#define VID_E_IQ 0x11100 +#define VID_F_IQ 0x11140 +#define VID_G_IQ 0x11180 +#define VID_H_IQ 0x111C0 +#define VID_I_IQ 0x11200 +#define VID_J_IQ 0x11240 +#define AUD_A_IQ 0x11280 +#define AUD_B_IQ 0x112C0 +#define AUD_C_IQ 0x11300 +#define AUD_D_IQ 0x11340 +#define AUD_E_IQ 0x11380 +#define MBIF_A_IQ 0x11000 +#define MBIF_B_IQ 0x110C0 + +#define VID_A_CDT 0x10C00 +#define VID_B_CDT 0x10C40 +#define VID_C_CDT 0x10C80 +#define VID_D_CDT 0x10CC0 +#define VID_E_CDT 0x10D00 +#define VID_F_CDT 0x10D40 +#define VID_G_CDT 0x10D80 +#define VID_H_CDT 0x10DC0 +#define VID_I_CDT 0x10E00 +#define VID_J_CDT 0x10E40 +#define AUD_A_CDT 0x10E80 +#define AUD_B_CDT 0x10EB0 +#define AUD_C_CDT 0x10EE0 +#define AUD_D_CDT 0x10F10 +#define AUD_E_CDT 0x10F40 +#define MBIF_A_CDT 0x10C00 +#define MBIF_B_CDT 0x10CC0 + +// Cluster Buffer for RX +#define VID_A_UP_CLUSTER_1 0x11400 +#define VID_A_UP_CLUSTER_2 0x119A0 +#define VID_A_UP_CLUSTER_3 0x11F40 +#define VID_A_UP_CLUSTER_4 0x124E0 + +#define VID_B_UP_CLUSTER_1 0x12A80 +#define VID_B_UP_CLUSTER_2 0x13020 +#define VID_B_UP_CLUSTER_3 0x135C0 +#define VID_B_UP_CLUSTER_4 0x13B60 + +#define VID_C_UP_CLUSTER_1 0x14100 +#define VID_C_UP_CLUSTER_2 0x146A0 +#define VID_C_UP_CLUSTER_3 0x14C40 +#define VID_C_UP_CLUSTER_4 0x151E0 + +#define VID_D_UP_CLUSTER_1 0x15780 +#define VID_D_UP_CLUSTER_2 0x15D20 +#define VID_D_UP_CLUSTER_3 0x162C0 +#define VID_D_UP_CLUSTER_4 0x16860 + +#define VID_E_UP_CLUSTER_1 0x16E00 +#define VID_E_UP_CLUSTER_2 0x173A0 +#define VID_E_UP_CLUSTER_3 0x17940 +#define VID_E_UP_CLUSTER_4 0x17EE0 + +#define VID_F_UP_CLUSTER_1 0x18480 +#define VID_F_UP_CLUSTER_2 0x18A20 +#define VID_F_UP_CLUSTER_3 0x18FC0 +#define VID_F_UP_CLUSTER_4 0x19560 + +#define VID_I_UP_CLUSTER_1 0x19B00 +#define VID_I_UP_CLUSTER_2 0x1A0A0 +#define VID_I_UP_CLUSTER_3 0x1A640 +#define VID_I_UP_CLUSTER_4 0x1ABE0 + +#define VID_J_UP_CLUSTER_1 0x1B180 +#define VID_J_UP_CLUSTER_2 0x1B720 +#define VID_J_UP_CLUSTER_3 0x1BCC0 +#define VID_J_UP_CLUSTER_4 0x1C260 + +#define AUD_A_UP_CLUSTER_1 0x1C800 +#define AUD_A_UP_CLUSTER_2 0x1C880 +#define AUD_A_UP_CLUSTER_3 0x1C900 + +#define AUD_B_UP_CLUSTER_1 0x1C980 +#define AUD_B_UP_CLUSTER_2 0x1CA00 +#define AUD_B_UP_CLUSTER_3 0x1CA80 + +#define AUD_C_UP_CLUSTER_1 0x1CB00 +#define AUD_C_UP_CLUSTER_2 0x1CB80 +#define AUD_C_UP_CLUSTER_3 0x1CC00 + +#define AUD_E_UP_CLUSTER_1 0x1CC80 +#define AUD_E_UP_CLUSTER_2 0x1CD00 +#define AUD_E_UP_CLUSTER_3 0x1CD80 + +#define RX_SRAM_POOL_FREE 0x1CE00 +#define RX_SRAM_END 0x1D000 + +// Free Receive SRAM 144 Bytes + + +// Transmit SRAM +#define TX_SRAM_POOL_START 0x00000 + +#define VID_A_DOWN_CLUSTER_1 0x00040 +#define VID_A_DOWN_CLUSTER_2 0x005E0 +#define VID_A_DOWN_CLUSTER_3 0x00B80 +#define VID_A_DOWN_CLUSTER_4 0x01120 + +#define VID_B_DOWN_CLUSTER_1 0x016C0 +#define VID_B_DOWN_CLUSTER_2 0x01C60 +#define VID_B_DOWN_CLUSTER_3 0x02200 +#define VID_B_DOWN_CLUSTER_4 0x027A0 + +#define VID_C_DOWN_CLUSTER_1 0x02D40 +#define VID_C_DOWN_CLUSTER_2 0x032E0 +#define VID_C_DOWN_CLUSTER_3 0x03880 +#define VID_C_DOWN_CLUSTER_4 0x03E20 + +#define VID_D_DOWN_CLUSTER_1 0x043C0 +#define VID_D_DOWN_CLUSTER_2 0x04960 +#define VID_D_DOWN_CLUSTER_3 0x04F00 +#define VID_D_DOWN_CLUSTER_4 0x054A0 + +#define VID_E_DOWN_CLUSTER_1 0x05a40 +#define VID_E_DOWN_CLUSTER_2 0x05FE0 +#define VID_E_DOWN_CLUSTER_3 0x06580 +#define VID_E_DOWN_CLUSTER_4 0x06B20 + +#define VID_F_DOWN_CLUSTER_1 0x070C0 +#define VID_F_DOWN_CLUSTER_2 0x07660 +#define VID_F_DOWN_CLUSTER_3 0x07C00 +#define VID_F_DOWN_CLUSTER_4 0x081A0 + +#define VID_G_DOWN_CLUSTER_1 0x08740 +#define VID_G_DOWN_CLUSTER_2 0x08CE0 +#define VID_G_DOWN_CLUSTER_3 0x09280 +#define VID_G_DOWN_CLUSTER_4 0x09820 + +#define VID_H_DOWN_CLUSTER_1 0x09DC0 +#define VID_H_DOWN_CLUSTER_2 0x0A360 +#define VID_H_DOWN_CLUSTER_3 0x0A900 +#define VID_H_DOWN_CLUSTER_4 0x0AEA0 + +#define AUD_A_DOWN_CLUSTER_1 0x0B500 +#define AUD_A_DOWN_CLUSTER_2 0x0B580 +#define AUD_A_DOWN_CLUSTER_3 0x0B600 + +#define AUD_B_DOWN_CLUSTER_1 0x0B680 +#define AUD_B_DOWN_CLUSTER_2 0x0B700 +#define AUD_B_DOWN_CLUSTER_3 0x0B780 + +#define AUD_C_DOWN_CLUSTER_1 0x0B800 +#define AUD_C_DOWN_CLUSTER_2 0x0B880 +#define AUD_C_DOWN_CLUSTER_3 0x0B900 + +#define AUD_D_DOWN_CLUSTER_1 0x0B980 +#define AUD_D_DOWN_CLUSTER_2 0x0BA00 +#define AUD_D_DOWN_CLUSTER_3 0x0BA80 + +#define TX_SRAM_POOL_FREE 0x0BB00 +#define TX_SRAM_END 0x0C000 + + +#define BYTES_TO_DWORDS(bcount) ((bcount) >> 2) +#define BYTES_TO_QWORDS(bcount) ((bcount) >> 3) +#define BYTES_TO_OWORDS(bcount) ((bcount) >> 4) + +#define VID_IQ_SIZE_DW BYTES_TO_DWORDS(VID_IQ_SIZE) +#define VID_CDT_SIZE_QW BYTES_TO_QWORDS(VID_CDT_SIZE) +#define VID_CLUSTER_SIZE_OW BYTES_TO_OWORDS(VID_CLUSTER_SIZE) + +#define AUDIO_IQ_SIZE_DW BYTES_TO_DWORDS(AUDIO_IQ_SIZE) +#define AUDIO_CDT_SIZE_QW BYTES_TO_QWORDS(AUDIO_CDT_SIZE) +#define AUDIO_CLUSTER_SIZE_QW BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE) + +#define MBIF_IQ_SIZE_DW BYTES_TO_DWORDS(MBIF_IQ_SIZE) +#define MBIF_CDT_SIZE_QW BYTES_TO_QWORDS(MBIF_CDT_SIZE) +#define MBIF_CLUSTER_SIZE_OW BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE) + + +#endif + diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c new file mode 100644 index 000000000..ca91b832b --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c @@ -0,0 +1,847 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "cx25821-video.h" +#include "cx25821-video-upstream-ch2.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); +MODULE_AUTHOR("Hiep Huynh "); +MODULE_LICENSE("GPL"); + + +static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; + + +static __le32 *cx25821_update_riscprogram_ch2( struct cx25821_dev *dev, + __le32 *rp, unsigned int offset, unsigned int bpl, + u32 sync_line, unsigned int lines, int fifo_enable, int field_type) +{ + unsigned int line, i; + int dist_betwn_starts = bpl * 2; + + + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + + + if( USE_RISC_NOOP_VIDEO ) + { + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + /* scan lines */ + for (line = 0; line < lines; line++) + { + *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); + *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) ) + { + offset += dist_betwn_starts; + } + } + + return rp; +} + +static __le32 *cx25821_risc_field_upstream_ch2( struct cx25821_dev *dev, + __le32 *rp, + dma_addr_t databuf_phys_addr, + unsigned int offset, u32 sync_line, unsigned int bpl, + unsigned int lines, int fifo_enable, int field_type) +{ + unsigned int line, i; + struct sram_channel *sram_ch = &dev->sram_channels[dev->_channel2_upstream_select]; + int dist_betwn_starts = bpl * 2; + + + /* sync instruction */ + if (sync_line != NO_SYNC_LINE) + { + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + } + + + if( USE_RISC_NOOP_VIDEO ) + { + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + /* scan lines */ + for (line = 0; line < lines; line++) + { + *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); + *(rp++) = cpu_to_le32(databuf_phys_addr+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + + if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) ) + { + offset += dist_betwn_starts; + } + + + // check if we need to enable the FIFO after the first 4 lines + // For the upstream video channel, the risc engine will enable the FIFO. + if ( fifo_enable && line == 3 ) + { + *(rp++) = RISC_WRITECR; + *(rp++) = sram_ch->dma_ctl; + *(rp++) = FLD_VID_FIFO_EN; + *(rp++) = 0x00000001; + } + } + + return rp; +} + +int cx25821_risc_buffer_upstream_ch2( struct cx25821_dev *dev, struct pci_dev *pci, + unsigned int top_offset, + unsigned int bpl, unsigned int lines) +{ + __le32 *rp; + int fifo_enable = 0; + int singlefield_lines = lines >> 1; //get line count for single field + int odd_num_lines = singlefield_lines; + int frame = 0; + int frame_size = 0; + int databuf_offset = 0; + int risc_program_size = 0; + int risc_flag = RISC_CNT_RESET; + unsigned int bottom_offset = bpl; + dma_addr_t risc_phys_jump_addr; + + + if( dev->_isNTSC_ch2 ) + { + odd_num_lines = singlefield_lines + 1; + risc_program_size = FRAME1_VID_PROG_SIZE; + frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; + } + else + { + risc_program_size = PAL_VID_PROG_SIZE; + frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + } + + + /* Virtual address of Risc buffer program */ + rp = dev->_dma_virt_addr_ch2; + + for( frame = 0; frame < NUM_FRAMES; frame++ ) + { + databuf_offset = frame_size * frame; + + + if (UNSET != top_offset) + { + fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; + rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD); + } + + fifo_enable = FIFO_DISABLE; + + + //Even field + rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD); + + + if( frame == 0 ) + { + risc_flag = RISC_CNT_RESET; + risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + risc_program_size; + } + else + { + risc_flag = RISC_CNT_INC; + risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2; + } + + + // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ + *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + + return 0; +} + + +void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) +{ + struct sram_channel *sram_ch = &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_J]; + u32 tmp = 0; + + if( !dev->_is_running_ch2 ) + { + printk("cx25821: No video file is currently running so return!\n"); + return; + } + + //Disable RISC interrupts + tmp = cx_read( sram_ch->int_msk ); + cx_write( sram_ch->int_msk, tmp & ~_intr_msk); + + //Turn OFF risc and fifo + tmp = cx_read( sram_ch->dma_ctl ); + cx_write( sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN) ); + + //Clear data buffer memory + if( dev->_data_buf_virt_addr_ch2 ) + memset( dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2 ); + + dev->_is_running_ch2 = 0; + dev->_is_first_frame_ch2 = 0; + dev->_frame_count_ch2 = 0; + dev->_file_status_ch2 = END_OF_FILE; + + if( dev->_irq_queues_ch2 ) + { + kfree(dev->_irq_queues_ch2); + dev->_irq_queues_ch2 = NULL; + } + + if( dev->_filename_ch2 != NULL ) + kfree(dev->_filename_ch2); + + tmp = cx_read( VID_CH_MODE_SEL ); + cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); +} + +void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev) +{ + if( dev->_is_running_ch2 ) + { + cx25821_stop_upstream_video_ch2(dev); + } + + if (dev->_dma_virt_addr_ch2) + { + pci_free_consistent(dev->pci, dev->_risc_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2); + dev->_dma_virt_addr_ch2 = NULL; + } + + if (dev->_data_buf_virt_addr_ch2) + { + pci_free_consistent(dev->pci, dev->_data_buf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2); + dev->_data_buf_virt_addr_ch2 = NULL; + } +} + + +int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch ) +{ + struct file * myfile; + int frame_index_temp = dev->_frame_index_ch2; + int i = 0; + int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + int frame_size = 0; + int frame_offset = 0; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t file_offset; + loff_t pos; + mm_segment_t old_fs; + + + if( dev->_file_status_ch2 == END_OF_FILE ) + return 0; + + if( dev->_isNTSC_ch2 ) + { + frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; + } + else + { + frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + } + + frame_offset = (frame_index_temp > 0) ? frame_size : 0; + file_offset = dev->_frame_count_ch2 * frame_size; + + + myfile = filp_open( dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0 ); + + + if (IS_ERR(myfile)) + { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno); + return PTR_ERR(myfile); + } + else + { + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( i = 0; i < dev->_lines_count_ch2; i++ ) + { + pos = file_offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL ) + { + memcpy( (void*)(dev->_data_buf_virt_addr_ch2+frame_offset/4), mybuf, vfs_read_retval); + } + + file_offset += vfs_read_retval; + frame_offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + dev->_frame_count_ch2++; + + dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + + set_fs(old_fs); + filp_close(myfile, NULL); + } + + return 0; +} + +static void cx25821_vidups_handler_ch2(struct work_struct *work) +{ + struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _irq_work_entry_ch2); + + if( !dev ) + { + printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); + return; + } + + cx25821_get_frame_ch2( dev, &dev->sram_channels[dev->_channel2_upstream_select] ); +} + + +int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) +{ + struct file * myfile; + int i = 0, j = 0; + int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t pos; + loff_t offset = (unsigned long)0; + mm_segment_t old_fs; + + + myfile = filp_open( dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0 ); + + + if (IS_ERR(myfile)) + { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno); + return PTR_ERR(myfile); + } + else + { + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered! Returning.", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( j = 0; j < NUM_FRAMES; j++ ) + { + for( i = 0; i < dev->_lines_count_ch2; i++ ) + { + pos = offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL ) + { + memcpy( (void*)(dev->_data_buf_virt_addr_ch2+offset/4), mybuf, vfs_read_retval); + } + + + offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + dev->_frame_count_ch2++; + + if( vfs_read_retval < line_size ) + { + break; + } + } + + dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + myfile->f_pos = 0; + filp_close(myfile, NULL); + } + + return 0; +} + + +static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, + struct sram_channel *sram_ch, + int bpl) +{ + int ret = 0; + dma_addr_t dma_addr; + dma_addr_t data_dma_addr; + + + if( dev->_dma_virt_addr_ch2 != NULL ) + { + pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2); + } + + dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, &dma_addr); + dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2; + dev->_dma_phys_start_addr_ch2 = dma_addr; + dev->_dma_phys_addr_ch2 = dma_addr; + dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2; + + + if (!dev->_dma_virt_addr_ch2) + { + printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); + return -ENOMEM; + } + + + //Iniitize at this address until n bytes to 0 + memset( dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2 ); + + + if( dev->_data_buf_virt_addr_ch2 != NULL ) + { + pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2); + } + + //For Video Data buffer allocation + dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2, &data_dma_addr); + dev->_data_buf_phys_addr_ch2 = data_dma_addr; + dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2; + + if (!dev->_data_buf_virt_addr_ch2) + { + printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); + return -ENOMEM; + } + + + //Initialize at this address until n bytes to 0 + memset( dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2 ); + + + ret = cx25821_openfile_ch2(dev, sram_ch); + if( ret < 0 ) + return ret; + + + //Creating RISC programs + ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl, dev->_lines_count_ch2 ); + if (ret < 0) + { + printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n"); + goto error; + } + + return 0; + +error: + return ret; +} + +int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, u32 status) +{ + u32 int_msk_tmp; + struct sram_channel *channel = &dev->sram_channels[chan_num]; + int singlefield_lines = NTSC_FIELD_HEIGHT; + int line_size_in_bytes = Y422_LINE_SZ; + int odd_risc_prog_size = 0; + dma_addr_t risc_phys_jump_addr; + __le32 * rp; + + + + if (status & FLD_VID_SRC_RISC1) + { + // We should only process one program per call + u32 prog_cnt = cx_read( channel->gpcnt ); + + //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers + int_msk_tmp = cx_read(channel->int_msk); + cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); + cx_write( channel->int_stat, _intr_msk ); + + spin_lock(&dev->slock); + + dev->_frame_index_ch2 = prog_cnt; + + queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2); + + + if ( dev->_is_first_frame_ch2 ) + { + dev->_is_first_frame_ch2 = 0; + + if( dev->_isNTSC_ch2 ) + { + singlefield_lines += 1; + odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; + } + else + { + singlefield_lines = PAL_FIELD_HEIGHT; + odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; + } + + + if( dev->_dma_virt_start_addr_ch2 != NULL ) + { + line_size_in_bytes = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + odd_risc_prog_size; + + rp = cx25821_update_riscprogram_ch2(dev, dev->_dma_virt_start_addr_ch2, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD); + + // Jump to Even Risc program of 1st Frame + *(rp++) = cpu_to_le32(RISC_JUMP); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + } + + spin_unlock(&dev->slock); + } + + + if( dev->_file_status_ch2 == END_OF_FILE ) + { + printk("cx25821: EOF Channel 2 Framecount = %d\n", dev->_frame_count_ch2 ); + return -1; + } + + //ElSE, set the interrupt mask register, re-enable irq. + int_msk_tmp = cx_read( channel->int_msk ); + cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); + + return 0; +} + +static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) +{ + struct cx25821_dev *dev = dev_id; + u32 msk_stat, vid_status; + int handled = 0; + int channel_num = 0; + struct sram_channel *sram_ch; + + + if( !dev ) + return -1; + + channel_num = VID_UPSTREAM_SRAM_CHANNEL_J; + + sram_ch = &dev->sram_channels[channel_num]; + + msk_stat = cx_read(sram_ch->int_mstat); + vid_status = cx_read(sram_ch->int_stat); + + // Only deal with our interrupt + if(vid_status) + { + handled = cx25821_video_upstream_irq_ch2(dev, channel_num, vid_status); + } + + + if( handled < 0 ) + { + cx25821_stop_upstream_video_ch2(dev); + } + else + { + handled += handled; + } + + return IRQ_RETVAL(handled); +} + + +static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, struct sram_channel *ch, int pix_format) +{ + int width = WIDTH_D1; + int height = dev->_lines_count_ch2; + int num_lines, odd_num_lines; + u32 value; + int vip_mode = PIXEL_ENGINE_VIP1; + + + value = ( (pix_format & 0x3) << 12 ) | ( vip_mode & 0x7 ); + value &= 0xFFFFFFEF; + value |= dev->_isNTSC_ch2 ? 0 : 0x10; + cx_write( ch->vid_fmt_ctl, value ); + + // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format + cx_write( ch->vid_active_ctl1, width ); + + num_lines = (height / 2) & 0x3FF; + odd_num_lines = num_lines; + + if(dev->_isNTSC_ch2) + { + odd_num_lines += 1; + } + + value = (num_lines << 16) | odd_num_lines; + + // set number of active lines in field 0 (top) and field 1 (bottom) + cx_write( ch->vid_active_ctl2, value ); + + cx_write( ch->vid_cdt_size, VID_CDT_SIZE >> 3 ); +} + + +int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, + struct sram_channel *sram_ch) +{ + u32 tmp = 0; + int err = 0; + + + // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + tmp = cx_read( VID_CH_MODE_SEL ); + cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); + + + // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. + cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2); + cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ + + /* reset counter */ + cx_write(sram_ch->gpcnt_ctl, 3); + + // Clear our bits from the interrupt status register. + cx_write( sram_ch->int_stat, _intr_msk ); + + + //Set the interrupt mask register, enable irq. + cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); + tmp = cx_read( sram_ch->int_msk ); + cx_write( sram_ch->int_msk, tmp |= _intr_msk ); + + + err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); + if (err < 0) + { + printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); + goto fail_irq; + } + + // Start the DMA engine + tmp = cx_read( sram_ch->dma_ctl ); + cx_set( sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN ); + + dev->_is_running_ch2 = 1; + dev->_is_first_frame_ch2 = 1; + + return 0; + + +fail_irq: + cx25821_dev_unregister(dev); + return err; +} + + +int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, int pixel_format) +{ + struct sram_channel *sram_ch; + u32 tmp; + int retval = 0; + int err = 0; + int data_frame_size = 0; + int risc_buffer_size = 0; + int str_length = 0; + + if( dev->_is_running_ch2 ) + { + printk("Video Channel is still running so return!\n"); + return 0; + } + + dev->_channel2_upstream_select = channel_select; + sram_ch = &dev->sram_channels[channel_select]; + + + INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2); + dev->_irq_queues_ch2 = create_singlethread_workqueue("cx25821_workqueue2"); + + if(!dev->_irq_queues_ch2) + { + printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); + return -ENOMEM; + } + + // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + tmp = cx_read( VID_CH_MODE_SEL ); + cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); + + + dev->_is_running_ch2 = 0; + dev->_frame_count_ch2 = 0; + dev->_file_status_ch2 = RESET_STATUS; + dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576; + dev->_pixel_format_ch2 = pixel_format; + dev->_line_size_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; + data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; + risc_buffer_size = dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; + + + if( dev->input_filename_ch2 ) + { + str_length = strlen(dev->input_filename_ch2); + dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_filename_ch2 ) + goto error; + + memcpy(dev->_filename_ch2, dev->input_filename_ch2, str_length + 1); + } + else + { + str_length = strlen(dev->_defaultname_ch2); + dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_filename_ch2 ) + goto error; + + memcpy(dev->_filename_ch2, dev->_defaultname_ch2, str_length + 1); + } + + + //Default if filename is empty string + if( strcmp(dev->input_filename_ch2,"") == 0) + { + if( dev->_isNTSC_ch2 ) + { + dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv"; + } + else + { + dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv"; + } + } + + + retval = cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size_ch2, 0); + + + /* setup fifo + format */ + cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2); + + dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2; + dev->upstream_databuf_size_ch2 = data_frame_size * 2; + + + //Allocating buffers and prepare RISC program + retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch, dev->_line_size_ch2); + if (retval < 0) + { + printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name); + goto error; + } + + + cx25821_start_video_dma_upstream_ch2(dev, sram_ch); + + return 0; + +error: + cx25821_dev_unregister(dev); + + return err; +} + diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h new file mode 100644 index 000000000..4c5bd04fd --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h @@ -0,0 +1,108 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "compat.h" +#include +#include + + +#define OPEN_FILE_1 0 +#define NUM_PROGS 8 +#define NUM_FRAMES 2 +#define ODD_FIELD 0 +#define EVEN_FIELD 1 +#define TOP_OFFSET 0 +#define FIFO_DISABLE 0 +#define FIFO_ENABLE 1 +#define TEST_FRAMES 5 +#define END_OF_FILE 0 +#define IN_PROGRESS 1 +#define RESET_STATUS -1 +#define NUM_NO_OPS 5 + + + +// PAL and NTSC line sizes and number of lines. +#define WIDTH_D1 720 +#define NTSC_LINES_PER_FRAME 480 +#define PAL_LINES_PER_FRAME 576 +#define PAL_LINE_SZ 1440 +#define Y422_LINE_SZ 1440 +#define Y411_LINE_SZ 1080 +#define NTSC_FIELD_HEIGHT 240 +#define NTSC_ODD_FLD_LINES 241 +#define PAL_FIELD_HEIGHT 288 + +#define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) +#define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) +#define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) +#define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) + +#define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) +#define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) + +#define RISC_WRITECR_INSTRUCTION_SIZE 16 +#define RISC_SYNC_INSTRUCTION_SIZE 4 +#define JUMP_INSTRUCTION_SIZE 12 +#define MAXSIZE_NO_OPS 36 +#define DWORD_SIZE 4 + + + +#define USE_RISC_NOOP_VIDEO 1 + +#ifdef USE_RISC_NOOP_VIDEO +#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ + RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) + +#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) + +#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ + JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) + +#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) +#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) +#endif + + +#ifndef USE_RISC_NOOP_VIDEO +#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) +#define PAL_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE) ) +#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) +#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) +#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) +#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) +#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) +#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) +#endif diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream.c b/linux/drivers/staging/cx25821/cx25821-video-upstream.c new file mode 100644 index 000000000..14d204aaa --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream.c @@ -0,0 +1,923 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "cx25821-video.h" +#include "cx25821-video-upstream.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); +MODULE_AUTHOR("Hiep Huynh "); +MODULE_LICENSE("GPL"); + + +static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; + +int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, + struct sram_channel *ch, + unsigned int bpl, u32 risc) +{ + unsigned int i, lines; + u32 cdt; + + + if (ch->cmds_start == 0) { + cx_write(ch->ptr1_reg, 0); + cx_write(ch->ptr2_reg, 0); + cx_write(ch->cnt2_reg, 0); + cx_write(ch->cnt1_reg, 0); + return 0; + } + + bpl = (bpl + 7) & ~7; /* alignment */ + cdt = ch->cdt; + lines = ch->fifo_size / bpl; + + if (lines > 4) + { + lines = 4; + } + + BUG_ON(lines < 2); + + + /* write CDT */ + for (i = 0; i < lines; i++) { + cx_write(cdt + 16*i, ch->fifo_start + bpl*i); + cx_write(cdt + 16*i + 4, 0); + cx_write(cdt + 16*i + 8, 0); + cx_write(cdt + 16*i + 12, 0); + } + + /* write CMDS */ + cx_write(ch->cmds_start + 0, risc); + + cx_write(ch->cmds_start + 4, 0); + cx_write(ch->cmds_start + 8, cdt); + cx_write(ch->cmds_start + 12, (lines*16) >> 3); + cx_write(ch->cmds_start + 16, ch->ctrl_start); + + + cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW); + + for (i = 24; i < 80; i += 4) + cx_write(ch->cmds_start + i, 0); + + /* fill registers */ + cx_write(ch->ptr1_reg, ch->fifo_start); + cx_write(ch->ptr2_reg, cdt); + cx_write(ch->cnt2_reg, (lines*16) >> 3); + cx_write(ch->cnt1_reg, (bpl >> 3) - 1); + + return 0; +} + +static __le32 *cx25821_update_riscprogram( struct cx25821_dev *dev, + __le32 *rp, unsigned int offset, unsigned int bpl, + u32 sync_line, unsigned int lines, int fifo_enable, int field_type) +{ + unsigned int line, i; + int dist_betwn_starts = bpl * 2; + + + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + + + if( USE_RISC_NOOP_VIDEO ) + { + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + /* scan lines */ + for (line = 0; line < lines; line++) + { + *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); + *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) ) + { + offset += dist_betwn_starts; + } + } + + return rp; +} + +static __le32 *cx25821_risc_field_upstream( struct cx25821_dev *dev, __le32 *rp, + dma_addr_t databuf_phys_addr, + unsigned int offset, u32 sync_line, + unsigned int bpl, unsigned int lines, int fifo_enable, int field_type) +{ + unsigned int line, i; + struct sram_channel *sram_ch = &dev->sram_channels[dev->_channel_upstream_select]; + int dist_betwn_starts = bpl * 2; + + + /* sync instruction */ + if (sync_line != NO_SYNC_LINE) + { + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + } + + + if( USE_RISC_NOOP_VIDEO ) + { + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + /* scan lines */ + for (line = 0; line < lines; line++) + { + *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); + *(rp++) = cpu_to_le32(databuf_phys_addr+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + + if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) ) + { + offset += dist_betwn_starts; //to skip the other field line + } + + + // check if we need to enable the FIFO after the first 4 lines + // For the upstream video channel, the risc engine will enable the FIFO. + if ( fifo_enable && line == 3 ) + { + *(rp++) = RISC_WRITECR; + *(rp++) = sram_ch->dma_ctl; + *(rp++) = FLD_VID_FIFO_EN; + *(rp++) = 0x00000001; + } + } + + return rp; +} + +int cx25821_risc_buffer_upstream( struct cx25821_dev *dev, + struct pci_dev *pci, + unsigned int top_offset, + unsigned int bpl, unsigned int lines) +{ + __le32 *rp; + int fifo_enable = 0; + int singlefield_lines = lines >> 1; //get line count for single field + int odd_num_lines = singlefield_lines; + int frame = 0; + int frame_size = 0; + int databuf_offset = 0; + int risc_program_size = 0; + int risc_flag = RISC_CNT_RESET; + unsigned int bottom_offset = bpl; + dma_addr_t risc_phys_jump_addr; + + if( dev->_isNTSC ) + { + odd_num_lines = singlefield_lines + 1; + risc_program_size = FRAME1_VID_PROG_SIZE; + frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; + } + else + { + risc_program_size = PAL_VID_PROG_SIZE; + frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + } + + + /* Virtual address of Risc buffer program */ + rp = dev->_dma_virt_addr; + + for( frame = 0; frame < NUM_FRAMES; frame++ ) + { + databuf_offset = frame_size * frame; + + if (UNSET != top_offset) + { + fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; + rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD); + } + + + fifo_enable = FIFO_DISABLE; + + + //Even Field + rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD); + + + if( frame == 0 ) + { + risc_flag = RISC_CNT_RESET; + risc_phys_jump_addr = dev->_dma_phys_start_addr + risc_program_size; + } + else + { + risc_phys_jump_addr = dev->_dma_phys_start_addr; + risc_flag = RISC_CNT_INC; + } + + + // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ + *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + + return 0; +} + + +void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) +{ + struct sram_channel *sram_ch = &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_I]; + u32 tmp = 0; + + if( !dev->_is_running ) + { + printk("cx25821: No video file is currently running so return!\n"); + return; + } + + //Disable RISC interrupts + tmp = cx_read( sram_ch->int_msk ); + cx_write( sram_ch->int_msk, tmp & ~_intr_msk); + + //Turn OFF risc and fifo enable + tmp = cx_read( sram_ch->dma_ctl ); + cx_write( sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN) ); + + //Clear data buffer memory + if( dev->_data_buf_virt_addr ) + memset( dev->_data_buf_virt_addr, 0, dev->_data_buf_size ); + + dev->_is_running = 0; + dev->_is_first_frame = 0; + dev->_frame_count = 0; + dev->_file_status = END_OF_FILE; + + if( dev->_irq_queues ) + { + kfree(dev->_irq_queues); + dev->_irq_queues = NULL; + } + + if( dev->_filename != NULL ) + kfree(dev->_filename); + + tmp = cx_read( VID_CH_MODE_SEL ); + cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); +} + +void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev) +{ + if( dev->_is_running ) + { + cx25821_stop_upstream_video_ch1(dev); + } + + if (dev->_dma_virt_addr) + { + pci_free_consistent(dev->pci, dev->_risc_size, dev->_dma_virt_addr, dev->_dma_phys_addr); + dev->_dma_virt_addr = NULL; + } + + if (dev->_data_buf_virt_addr) + { + pci_free_consistent(dev->pci, dev->_data_buf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr); + dev->_data_buf_virt_addr = NULL; + } +} + + +int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch ) +{ + struct file * myfile; + int frame_index_temp = dev->_frame_index; + int i = 0; + int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + int frame_size = 0; + int frame_offset = 0; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t file_offset; + loff_t pos; + mm_segment_t old_fs; + + + if( dev->_file_status == END_OF_FILE ) + return 0; + + if( dev->_isNTSC ) + { + frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; + } + else + { + frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + } + + frame_offset = (frame_index_temp > 0) ? frame_size : 0; + file_offset = dev->_frame_count * frame_size; + + + myfile = filp_open( dev->_filename, O_RDONLY | O_LARGEFILE, 0 ); + + + if (IS_ERR(myfile)) + { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno); + return PTR_ERR(myfile); + } + else + { + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( i = 0; i < dev->_lines_count; i++ ) + { + pos = file_offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL ) + { + memcpy( (void*)(dev->_data_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval); + } + + file_offset += vfs_read_retval; + frame_offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + dev->_frame_count++; + + dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + + set_fs(old_fs); + filp_close(myfile, NULL); + } + + return 0; +} + +static void cx25821_vidups_handler(struct work_struct *work) +{ + struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _irq_work_entry); + + if( !dev ) + { + printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); + return; + } + + cx25821_get_frame( dev, &dev->sram_channels[dev->_channel_upstream_select] ); +} + + +int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) +{ + struct file * myfile; + int i = 0, j = 0; + int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t pos; + loff_t offset = (unsigned long)0; + mm_segment_t old_fs; + + + myfile = filp_open( dev->_filename, O_RDONLY | O_LARGEFILE, 0 ); + + + if (IS_ERR(myfile)) + { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno); + return PTR_ERR(myfile); + } + else + { + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered! Returning.", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( j = 0; j < NUM_FRAMES; j++ ) + { + for( i = 0; i < dev->_lines_count; i++ ) + { + pos = offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL ) + { + memcpy( (void*)(dev->_data_buf_virt_addr+offset/4), mybuf, vfs_read_retval); + } + + + offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + dev->_frame_count++; + + if( vfs_read_retval < line_size ) + { + break; + } + } + + + dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + myfile->f_pos = 0; + filp_close(myfile, NULL); + } + + return 0; +} + + +int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, + struct sram_channel *sram_ch, + int bpl) +{ + int ret = 0; + dma_addr_t dma_addr; + dma_addr_t data_dma_addr; + + if( dev->_dma_virt_addr != NULL ) + { + pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, dev->_dma_virt_addr, dev->_dma_phys_addr); + } + + + dev->_dma_virt_addr = pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size, &dma_addr); + dev->_dma_virt_start_addr = dev->_dma_virt_addr; + dev->_dma_phys_start_addr = dma_addr; + dev->_dma_phys_addr = dma_addr; + dev->_risc_size = dev->upstream_riscbuf_size; + + + if (!dev->_dma_virt_addr) + { + printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); + return -ENOMEM; + } + + + //Clear memory at address + memset( dev->_dma_virt_addr, 0, dev->_risc_size ); + + + if( dev->_data_buf_virt_addr != NULL ) + { + pci_free_consistent(dev->pci, dev->upstream_databuf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr); + } + + //For Video Data buffer allocation + dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci, dev->upstream_databuf_size, &data_dma_addr); + dev->_data_buf_phys_addr = data_dma_addr; + dev->_data_buf_size = dev->upstream_databuf_size; + + if (!dev->_data_buf_virt_addr) + { + printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); + return -ENOMEM; + } + + + //Clear memory at address + memset( dev->_data_buf_virt_addr, 0, dev->_data_buf_size ); + + + ret = cx25821_openfile(dev, sram_ch); + if( ret < 0 ) + return ret; + + + //Create RISC programs + ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, dev->_lines_count ); + if (ret < 0) + { + printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n"); + goto error; + } + + return 0; + +error: + return ret; +} + +int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, u32 status) +{ + u32 int_msk_tmp; + struct sram_channel *channel = &dev->sram_channels[chan_num]; + int singlefield_lines = NTSC_FIELD_HEIGHT; + int line_size_in_bytes = Y422_LINE_SZ; + int odd_risc_prog_size = 0; + dma_addr_t risc_phys_jump_addr; + __le32 * rp; + + + + if (status & FLD_VID_SRC_RISC1) + { + // We should only process one program per call + u32 prog_cnt = cx_read( channel->gpcnt ); + + //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers + int_msk_tmp = cx_read(channel->int_msk); + cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); + cx_write( channel->int_stat, _intr_msk ); + + spin_lock(&dev->slock); + + dev->_frame_index = prog_cnt; + + queue_work(dev->_irq_queues, &dev->_irq_work_entry); + + + if ( dev->_is_first_frame ) + { + dev->_is_first_frame = 0; + + if( dev->_isNTSC ) + { + singlefield_lines += 1; + odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; + } + else + { + singlefield_lines = PAL_FIELD_HEIGHT; + odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; + } + + + if( dev->_dma_virt_start_addr != NULL ) + { + line_size_in_bytes = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + risc_phys_jump_addr = dev->_dma_phys_start_addr + odd_risc_prog_size; + + rp = cx25821_update_riscprogram(dev, dev->_dma_virt_start_addr, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD); + + // Jump to Even Risc program of 1st Frame + *(rp++) = cpu_to_le32(RISC_JUMP); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + } + + spin_unlock(&dev->slock); + } + else + { + if(status & FLD_VID_SRC_UF) + printk("%s: Video Received Underflow Error Interrupt!\n", __func__); + + if(status & FLD_VID_SRC_SYNC) + printk("%s: Video Received Sync Error Interrupt!\n", __func__); + + if(status & FLD_VID_SRC_OPC_ERR) + printk("%s: Video Received OpCode Error Interrupt!\n", __func__); + } + + + if( dev->_file_status == END_OF_FILE ) + { + printk("cx25821: EOF Channel 1 Framecount = %d\n", dev->_frame_count ); + return -1; + } + + //ElSE, set the interrupt mask register, re-enable irq. + int_msk_tmp = cx_read( channel->int_msk ); + cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); + + return 0; +} + +static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) +{ + struct cx25821_dev *dev = dev_id; + u32 msk_stat, vid_status; + int handled = 0; + int channel_num = 0; + struct sram_channel *sram_ch; + + + if( !dev ) + return -1; + + channel_num = VID_UPSTREAM_SRAM_CHANNEL_I; + + sram_ch = &dev->sram_channels[channel_num]; + + msk_stat = cx_read(sram_ch->int_mstat); + vid_status = cx_read(sram_ch->int_stat); + + // Only deal with our interrupt + if(vid_status) + { + handled = cx25821_video_upstream_irq(dev, channel_num, vid_status); + } + + if( handled < 0 ) + { + cx25821_stop_upstream_video_ch1(dev); + } + else + { + handled += handled; + } + + return IRQ_RETVAL(handled); +} + + +void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch, int pix_format) +{ + int width = WIDTH_D1; + int height = dev->_lines_count; + int num_lines, odd_num_lines; + u32 value; + int vip_mode = OUTPUT_FRMT_656; + + + value = ( (pix_format & 0x3) << 12 ) | ( vip_mode & 0x7 ); + value &= 0xFFFFFFEF; + value |= dev->_isNTSC ? 0 : 0x10; + cx_write( ch->vid_fmt_ctl, value ); + + + // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format + cx_write( ch->vid_active_ctl1, width ); + + num_lines = (height / 2) & 0x3FF; + odd_num_lines = num_lines; + + if(dev->_isNTSC) + { + odd_num_lines += 1; + } + + value = (num_lines << 16) | odd_num_lines; + + // set number of active lines in field 0 (top) and field 1 (bottom) + cx_write( ch->vid_active_ctl2, value ); + + cx_write( ch->vid_cdt_size, VID_CDT_SIZE >> 3 ); +} + + +int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, + struct sram_channel *sram_ch) +{ + u32 tmp = 0; + int err = 0; + + + // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + tmp = cx_read( VID_CH_MODE_SEL ); + cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); + + + // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. + cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr); + cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ + + /* reset counter */ + cx_write(sram_ch->gpcnt_ctl, 3); + + // Clear our bits from the interrupt status register. + cx_write( sram_ch->int_stat, _intr_msk ); + + + //Set the interrupt mask register, enable irq. + cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); + tmp = cx_read( sram_ch->int_msk ); + cx_write( sram_ch->int_msk, tmp |= _intr_msk ); + + + err = request_irq(dev->pci->irq, cx25821_upstream_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); + if (err < 0) + { + printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); + goto fail_irq; + } + + + // Start the DMA engine + tmp = cx_read( sram_ch->dma_ctl ); + cx_set( sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN ); + + dev->_is_running = 1; + dev->_is_first_frame = 1; + + return 0; + +fail_irq: + cx25821_dev_unregister(dev); + return err; +} + + +int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, int pixel_format) +{ + struct sram_channel *sram_ch; + u32 tmp; + int retval = 0; + int err = 0; + int data_frame_size = 0; + int risc_buffer_size = 0; + int str_length = 0; + + + if( dev->_is_running ) + { + printk("Video Channel is still running so return!\n"); + return 0; + } + + + dev->_channel_upstream_select = channel_select; + sram_ch = &dev->sram_channels[channel_select]; + + + INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler); + dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue"); + + if(!dev->_irq_queues) + { + printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); + return -ENOMEM; + } + + // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + tmp = cx_read( VID_CH_MODE_SEL ); + cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); + + + dev->_is_running = 0; + dev->_frame_count = 0; + dev->_file_status = RESET_STATUS; + dev->_lines_count = dev->_isNTSC ? 480 : 576; + dev->_pixel_format = pixel_format; + dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; + data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; + risc_buffer_size = dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; + + + if( dev->input_filename ) + { + str_length = strlen(dev->input_filename); + dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_filename ) + goto error; + + memcpy(dev->_filename, dev->input_filename, str_length + 1); + } + else + { + str_length = strlen(dev->_defaultname); + dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_filename ) + goto error; + + memcpy(dev->_filename, dev->_defaultname, str_length + 1); + } + + + //Default if filename is empty string + if( strcmp(dev->input_filename,"") == 0) + { + if( dev->_isNTSC ) + { + dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv"; + } + else + { + dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv"; + } + } + + dev->_is_running = 0; + dev->_frame_count = 0; + dev->_file_status = RESET_STATUS; + dev->_lines_count = dev->_isNTSC ? 480 : 576; + dev->_pixel_format = pixel_format; + dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; + + retval = cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size, 0); + + /* setup fifo + format */ + cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format); + + dev->upstream_riscbuf_size = risc_buffer_size * 2; + dev->upstream_databuf_size = data_frame_size * 2; + + + //Allocating buffers and prepare RISC program + retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size); + if (retval < 0) + { + printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name); + goto error; + } + + + cx25821_start_video_dma_upstream(dev, sram_ch); + + return 0; + +error: + cx25821_dev_unregister(dev); + + return err; +} + diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream.h b/linux/drivers/staging/cx25821/cx25821-video-upstream.h new file mode 100644 index 000000000..aa6eb6463 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream.h @@ -0,0 +1,114 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "compat.h" +#include +#include + +#define OUTPUT_FRMT_656 0 +#define OPEN_FILE_1 0 +#define NUM_PROGS 8 +#define NUM_FRAMES 2 +#define ODD_FIELD 0 +#define EVEN_FIELD 1 +#define TOP_OFFSET 0 +#define FIFO_DISABLE 0 +#define FIFO_ENABLE 1 +#define TEST_FRAMES 5 +#define END_OF_FILE 0 +#define IN_PROGRESS 1 +#define RESET_STATUS -1 +#define NUM_NO_OPS 5 + + + +// PAL and NTSC line sizes and number of lines. +#define WIDTH_D1 720 +#define NTSC_LINES_PER_FRAME 480 +#define PAL_LINES_PER_FRAME 576 +#define PAL_LINE_SZ 1440 +#define Y422_LINE_SZ 1440 +#define Y411_LINE_SZ 1080 +#define NTSC_FIELD_HEIGHT 240 +#define NTSC_ODD_FLD_LINES 241 +#define PAL_FIELD_HEIGHT 288 + +#define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) +#define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) +#define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) +#define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) + +#define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) +#define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) + +#define RISC_WRITECR_INSTRUCTION_SIZE 16 +#define RISC_SYNC_INSTRUCTION_SIZE 4 +#define JUMP_INSTRUCTION_SIZE 12 +#define MAXSIZE_NO_OPS 36 +#define DWORD_SIZE 4 + + +#define USE_RISC_NOOP_VIDEO 1 + +#ifdef USE_RISC_NOOP_VIDEO +#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ + RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) + +#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) + +#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ + JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) + +#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) + +#endif + + +#ifndef USE_RISC_NOOP_VIDEO +#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ + RISC_SYNC_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) + +#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) + +#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) + +#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) +#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) + +#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) +#define NTSC_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) +#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) +#endif diff --git a/linux/drivers/staging/cx25821/cx25821-video.c b/linux/drivers/staging/cx25821/cx25821-video.c new file mode 100644 index 000000000..512cbe3ba --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video.c @@ -0,0 +1,1337 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + +MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); +MODULE_AUTHOR("Steven Toth "); +MODULE_LICENSE("GPL"); + +static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; +static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; + +module_param_array(video_nr, int, NULL, 0444); +module_param_array(radio_nr, int, NULL, 0444); + +MODULE_PARM_DESC(video_nr, "video device numbers"); +MODULE_PARM_DESC(radio_nr, "radio device numbers"); + +static unsigned int video_debug=VIDEO_DEBUG; +module_param(video_debug, int, 0644); +MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); + +static unsigned int irq_debug; +module_param(irq_debug, int, 0644); +MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]"); + +unsigned int vid_limit = 16; +module_param(vid_limit, int, 0644); +MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); + +static void init_controls(struct cx25821_dev *dev, int chan_num); + +#define FORMAT_FLAGS_PACKED 0x01 + +struct cx25821_fmt formats[] = { + { + .name = "8 bpp, gray", + .fourcc = V4L2_PIX_FMT_GREY, + .depth = 8, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "4:1:1, packed, Y41P", + .fourcc = V4L2_PIX_FMT_Y41P, + .depth = 12, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "4:2:2, packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "4:2:2, packed, UYVY", + .fourcc = V4L2_PIX_FMT_UYVY, + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + },{ + .name = "4:2:0, YUV", + .fourcc = V4L2_PIX_FMT_YUV420, + .depth = 12, + .flags = FORMAT_FLAGS_PACKED, + }, +}; + + +int get_format_size(void) +{ + return ARRAY_SIZE(formats); +} + + +struct cx25821_fmt *format_by_fourcc(unsigned int fourcc) +{ + unsigned int i; + + if( fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P ) + { + return formats+1; + } + + for (i = 0; i < ARRAY_SIZE(formats); i++) + if (formats[i].fourcc == fourcc) + return formats+i; + + printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc); + return NULL; +} + +void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q) +{ + struct cx25821_buffer *buf; + struct list_head *item; + dprintk(1, "%s()\n", __func__); + + if (!list_empty(&q->active)) { + list_for_each(item, &q->active) + buf = list_entry(item, struct cx25821_buffer, vb.queue); + } + + if (!list_empty(&q->queued)) + { + list_for_each(item, &q->queued) + buf = list_entry(item, struct cx25821_buffer, vb.queue); + } + +} + + +void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, u32 count) +{ + struct cx25821_buffer *buf; + int bc; + + for (bc = 0;; bc++) { + if (list_empty(&q->active)) + { + dprintk(1, "bc=%d (=0: active empty)\n", bc); + break; + } + + buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); + + /* count comes from the hw and it is 16bit wide -- + * this trick handles wrap-arounds correctly for + * up to 32767 buffers in flight... */ + if ((s16) (count - buf->count) < 0) + { + break; + } + + do_gettimeofday(&buf->vb.ts); + buf->vb.state = VIDEOBUF_DONE; + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); + } + + if (list_empty(&q->active)) + del_timer(&q->timeout); + else + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + if (bc != 1) + printk(KERN_ERR "%s: %d buffers handled (should be 1)\n", __func__, bc); +} + +#ifdef TUNER_FLAG +int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm) +{ + dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__, + (unsigned int)norm, + v4l2_norm_to_name(norm)); + + dev->tvnorm = norm; + + /* Tell the internal A/V decoder */ + cx25821_call_all(dev, core, s_std, norm); + + return 0; +} +#endif + +struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, + struct pci_dev *pci, + struct video_device *template, + char *type) +{ + struct video_device *vfd; + dprintk(1, "%s()\n", __func__); + + vfd = video_device_alloc(); + if (NULL == vfd) + return NULL; + *vfd = *template; + vfd->minor = -1; + vfd->v4l2_dev = &dev->v4l2_dev; + vfd->release = video_device_release; + snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, cx25821_boards[dev->board].name); + return vfd; +} + +/* +static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) +{ + int i; + + if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) + return -EINVAL; + for (i = 0; i < CX25821_CTLS; i++) + if (cx25821_ctls[i].v.id == qctrl->id) + break; + if (i == CX25821_CTLS) { + *qctrl = no_ctl; + return 0; + } + *qctrl = cx25821_ctls[i].v; + return 0; +} +*/ + +// resource management +int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit) +{ + dprintk(1, "%s()\n", __func__); + if (fh->resources & bit) + /* have it already allocated */ + return 1; + + /* is it free? */ + mutex_lock(&dev->lock); + if (dev->resources & bit) { + /* no, someone else uses it */ + mutex_unlock(&dev->lock); + return 0; + } + /* it's free, grab it */ + fh->resources |= bit; + dev->resources |= bit; + dprintk(1, "res: get %d\n", bit); + mutex_unlock(&dev->lock); + return 1; +} + +int res_check(struct cx25821_fh *fh, unsigned int bit) +{ + return fh->resources & bit; +} + +int res_locked(struct cx25821_dev *dev, unsigned int bit) +{ + return dev->resources & bit; +} + +void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits) +{ + BUG_ON((fh->resources & bits) != bits); + dprintk(1, "%s()\n", __func__); + + mutex_lock(&dev->lock); + fh->resources &= ~bits; + dev->resources &= ~bits; + dprintk(1, "res: put %d\n", bits); + mutex_unlock(&dev->lock); +} + +int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input) +{ + struct v4l2_routing route; + memset(&route, 0, sizeof(route)); + + dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", __func__, + input, INPUT(input)->vmux, + INPUT(input)->gpio0, INPUT(input)->gpio1, + INPUT(input)->gpio2, INPUT(input)->gpio3); + dev->input = input; + + route.input = INPUT(input)->vmux; + + /* Tell the internal A/V decoder */ + cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0); + + return 0; +} + +int cx25821_start_video_dma(struct cx25821_dev *dev, + struct cx25821_dmaqueue *q, + struct cx25821_buffer *buf, + struct sram_channel *channel) +{ + int tmp = 0; + + /* setup fifo + format */ + cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma); + + /* reset counter */ + cx_write(channel->gpcnt_ctl, 3); + q->count = 1; + + /* enable irq */ + cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1<i)); + cx_set(channel->int_msk, 0x11); + + /* start dma */ + cx_write(channel->dma_ctl, 0x11); /* FIFO and RISC enable */ + + /* make sure upstream setting if any is reversed */ + tmp = cx_read( VID_CH_MODE_SEL ); + cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); + + return 0; +} + + +int cx25821_restart_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, struct sram_channel *channel) +{ + struct cx25821_buffer *buf, *prev; + struct list_head *item; + + if (!list_empty(&q->active)) { + buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); + + cx25821_start_video_dma(dev, q, buf, channel); + + list_for_each(item, &q->active) { + buf = list_entry(item, struct cx25821_buffer, vb.queue); + buf->count = q->count++; + } + + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + return 0; + } + + prev = NULL; + for (;;) { + if (list_empty(&q->queued)) + return 0; + + buf = list_entry(q->queued.next, struct cx25821_buffer, vb.queue); + + if (NULL == prev) { + list_move_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, channel); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + } else if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_move_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */ + } else { + return 0; + } + prev = buf; + } +} + +void cx25821_vid_timeout(unsigned long data) +{ + struct cx25821_data *timeout_data = (struct cx25821_data *)data; + struct cx25821_dev *dev = timeout_data->dev; + struct sram_channel *channel = timeout_data->channel; + struct cx25821_dmaqueue *q = &dev->vidq[channel->i]; + struct cx25821_buffer *buf; + unsigned long flags; + + //cx25821_sram_channel_dump(dev, channel); + cx_clear(channel->dma_ctl, 0x11); + + spin_lock_irqsave(&dev->slock, flags); + while (!list_empty(&q->active)) { + buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); + list_del(&buf->vb.queue); + + buf->vb.state = VIDEOBUF_ERROR; + wake_up(&buf->vb.done); + } + + cx25821_restart_video_queue(dev, q, channel); + spin_unlock_irqrestore(&dev->slock, flags); +} + +int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) +{ + u32 count=0; + int handled = 0; + u32 mask; + struct sram_channel *channel = &dev->sram_channels[chan_num]; + + mask = cx_read(channel->int_msk); + if (0 == (status & mask)) + return handled; + + cx_write(channel->int_stat, status); + + /* risc op code error */ + if (status & (1 << 16)) { + printk(KERN_WARNING "%s, %s: video risc op code error\n", dev->name, channel->name); + cx_clear(channel->dma_ctl, 0x11); + cx25821_sram_channel_dump(dev, channel); + } + + /* risc1 y */ + if (status & FLD_VID_DST_RISC1) { + spin_lock(&dev->slock); + count = cx_read(channel->gpcnt); + cx25821_video_wakeup(dev, &dev->vidq[channel->i], count); + spin_unlock(&dev->slock); + handled++; + } + + /* risc2 y */ + if (status & 0x10) { + dprintk(2, "stopper video\n"); + spin_lock(&dev->slock); + cx25821_restart_video_queue(dev, &dev->vidq[channel->i], channel); + spin_unlock(&dev->slock); + handled++; + } + return handled; +} + +void cx25821_videoioctl_unregister(struct cx25821_dev *dev) +{ + if( dev->ioctl_dev ) + { + if (dev->ioctl_dev->minor != -1) + video_unregister_device(dev->ioctl_dev); + else + video_device_release(dev->ioctl_dev); + + dev->ioctl_dev = NULL; + } +} + +void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) +{ + cx_clear(PCI_INT_MSK, 1); + + if (dev->video_dev[chan_num]) { + if (-1 != dev->video_dev[chan_num]->minor) + video_unregister_device(dev->video_dev[chan_num]); + else + video_device_release(dev->video_dev[chan_num]); + + dev->video_dev[chan_num] = NULL; + + btcx_riscmem_free(dev->pci, &dev->vidq[chan_num].stopper); + + printk(KERN_WARNING "device %d released!\n", chan_num); + } + +} + + +int cx25821_video_register(struct cx25821_dev *dev, int chan_num, struct video_device *video_template) +{ + int err; + + spin_lock_init(&dev->slock); + + //printk(KERN_WARNING "Channel %d\n", chan_num); + +#ifdef TUNER_FLAG + dev->tvnorm = video_template->current_norm; +#endif + + /* init video dma queues */ + dev->timeout_data[chan_num].dev = dev; + dev->timeout_data[chan_num].channel = &dev->sram_channels[chan_num]; + INIT_LIST_HEAD(&dev->vidq[chan_num].active); + INIT_LIST_HEAD(&dev->vidq[chan_num].queued); + dev->vidq[chan_num].timeout.function = cx25821_vid_timeout; + dev->vidq[chan_num].timeout.data = (unsigned long)&dev->timeout_data[chan_num]; + init_timer(&dev->vidq[chan_num].timeout); + cx25821_risc_stopper(dev->pci, &dev->vidq[chan_num].stopper, dev->sram_channels[chan_num].dma_ctl, 0x11, 0); + + + /* register v4l devices */ + dev->video_dev[chan_num] = cx25821_vdev_init(dev, dev->pci, video_template, "video"); + err = video_register_device(dev->video_dev[chan_num], VFL_TYPE_GRABBER, video_nr[dev->nr]); + + if (err < 0) { + goto fail_unreg; + } + + //set PCI interrupt + cx_set(PCI_INT_MSK, 0xff); + + + /* initial device configuration */ + mutex_lock(&dev->lock); +#ifdef TUNER_FLAG + cx25821_set_tvnorm(dev, dev->tvnorm); +#endif + mutex_unlock(&dev->lock); + + init_controls(dev, chan_num); + + return 0; + +fail_unreg: + cx25821_video_unregister(dev, chan_num); + return err; +} + +int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) +{ + struct cx25821_fh *fh = q->priv_data; + + *size = fh->fmt->depth*fh->width*fh->height >> 3; + + + if (0 == *count) + *count = 32; + + while (*size * *count > vid_limit * 1024 * 1024) + (*count)--; + + return 0; +} + +int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) +{ + struct cx25821_fh *fh = q->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + int rc, init_buffer = 0; + u32 line0_offset, line1_offset; + struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); + int bpl_local = LINE_SIZE_D1; + int channel_opened = 0; + + + BUG_ON(NULL == fh->fmt); + if (fh->width < 48 || fh->width > 720 || + fh->height < 32 || fh->height > 576) + return -EINVAL; + + buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; + + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; + + + if (buf->fmt != fh->fmt || + buf->vb.width != fh->width || + buf->vb.height != fh->height || + buf->vb.field != field) { + buf->fmt = fh->fmt; + buf->vb.width = fh->width; + buf->vb.height = fh->height; + buf->vb.field = field; + init_buffer = 1; + } + + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { + init_buffer = 1; + rc = videobuf_iolock(q, &buf->vb, NULL); + if (0 != rc) + { + printk(KERN_DEBUG "videobuf_iolock failed!\n"); + goto fail; + } + } + + dprintk(1, "init_buffer=%d\n", init_buffer); + + if (init_buffer) { + + channel_opened = dev->channel_opened; + channel_opened = (channel_opened < 0 || channel_opened > 7) ? 7 : channel_opened; + + if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 ) + buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; + else + buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); + + + if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 ) + { + bpl_local = buf->bpl; + } + else + { + bpl_local = buf->bpl; //Default + + if( channel_opened >= 0 && channel_opened <= 7 ) + { + if( dev->use_cif_resolution[channel_opened] ) + { + if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK ) + bpl_local = 352 << 1; + else + bpl_local = dev->cif_width[channel_opened] << 1; + } + } + } + + + switch (buf->vb.field) { + case V4L2_FIELD_TOP: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, 0, UNSET, + buf->bpl, 0, buf->vb.height); + break; + case V4L2_FIELD_BOTTOM: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, UNSET, 0, + buf->bpl, 0, buf->vb.height); + break; + case V4L2_FIELD_INTERLACED: + /* All other formats are top field first */ + line0_offset = 0; + line1_offset = buf->bpl; + dprintk(1, "top field first\n"); + + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, line0_offset, + bpl_local, bpl_local, bpl_local, + buf->vb.height >> 1); + break; + case V4L2_FIELD_SEQ_TB: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, + 0, buf->bpl * (buf->vb.height >> 1), + buf->bpl, 0, + buf->vb.height >> 1); + break; + case V4L2_FIELD_SEQ_BT: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, + buf->bpl * (buf->vb.height >> 1), 0, + buf->bpl, 0, + buf->vb.height >> 1); + break; + default: + BUG(); + } + } + + dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", + buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth, fh->fmt->name, + (unsigned long)buf->risc.dma); + + buf->vb.state = VIDEOBUF_PREPARED; + + return 0; + + fail: + cx25821_free_buffer(q, buf); + return rc; +} + + +void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + + cx25821_free_buffer(q, buf); +} + + +struct videobuf_queue *get_queue(struct cx25821_fh *fh) +{ + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return &fh->vidq; + default: + BUG(); + return NULL; + } +} + +int get_resource(struct cx25821_fh *fh, int resource) +{ + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return resource; + default: + BUG(); + return 0; + } +} + + +int video_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct cx25821_fh *fh = file->private_data; + + return videobuf_mmap_mapper(get_queue(fh), vma); +} + +/* VIDEO IOCTLS */ +int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + + f->fmt.pix.width = fh->width; + f->fmt.pix.height = fh->height; + f->fmt.pix.field = fh->vidq.field; + f->fmt.pix.pixelformat = fh->fmt->fourcc; + f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; +} + +int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fmt *fmt; + enum v4l2_field field; + unsigned int maxw, maxh; + + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (NULL == fmt) + return -EINVAL; + + field = f->fmt.pix.field; + maxw = 720; + maxh = 576; + + if (V4L2_FIELD_ANY == field) { + field = (f->fmt.pix.height > maxh/2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_TOP; + } + + switch (field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + maxh = maxh / 2; + break; + case V4L2_FIELD_INTERLACED: + break; + default: + return -EINVAL; + } + + f->fmt.pix.field = field; + if (f->fmt.pix.height < 32) + f->fmt.pix.height = 32; + if (f->fmt.pix.height > maxh) + f->fmt.pix.height = maxh; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > maxw) + f->fmt.pix.width = maxw; + f->fmt.pix.width &= ~0x03; + f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + + return 0; +} + + + +int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + strcpy(cap->driver, "cx25821"); + strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); + sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); + cap->version = CX25821_VERSION_CODE; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; + if (UNSET != dev->tuner_type) + cap->capabilities |= V4L2_CAP_TUNER; + return 0; +} + +int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) +{ + if (unlikely(f->index >= ARRAY_SIZE(formats))) + return -EINVAL; + + strlcpy(f->description, formats[f->index].name, sizeof(f->description)); + f->pixelformat = formats[f->index].fourcc; + + return 0; +} + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) +{ + struct cx25821_fh *fh = priv; + struct videobuf_queue *q; + struct v4l2_requestbuffers req; + unsigned int i; + int err; + + q = get_queue(fh); + memset(&req, 0, sizeof(req)); + req.type = q->type; + req.count = 8; + req.memory = V4L2_MEMORY_MMAP; + err = videobuf_reqbufs(q, &req); + if (err < 0) + return err; + + mbuf->frames = req.count; + mbuf->size = 0; + for (i = 0; i < mbuf->frames; i++) { + mbuf->offsets[i] = q->bufs[i]->boff; + mbuf->size += q->bufs[i]->bsize; + } + return 0; +} +#endif + +int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) +{ + struct cx25821_fh *fh = priv; + return videobuf_reqbufs(get_queue(fh), p); +} + +int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct cx25821_fh *fh = priv; + return videobuf_querybuf(get_queue(fh), p); +} + +int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct cx25821_fh *fh = priv; + return videobuf_qbuf(get_queue(fh), p); +} + +int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; + + *p = v4l2_prio_max(&dev->prio); + + return 0; +} + +int vidioc_s_priority(struct file *file, void *f, + enum v4l2_priority prio) +{ + struct cx25821_fh *fh = f; + struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; + + return v4l2_prio_change(&dev->prio, &fh->prio, prio); +} + + +#ifdef TUNER_FLAG +int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + dprintk(1, "%s()\n", __func__); + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + if( dev->tvnorm == *tvnorms ) + { + return 0; + } + + mutex_lock(&dev->lock); + cx25821_set_tvnorm(dev, *tvnorms); + mutex_unlock(&dev->lock); + + medusa_set_videostandard(dev); + + return 0; +} +#endif + +int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i) +{ + static const char *iname[] = { + [CX25821_VMUX_COMPOSITE] = "Composite", + [CX25821_VMUX_SVIDEO] = "S-Video", + [CX25821_VMUX_DEBUG] = "for debug only", + }; + unsigned int n; + dprintk(1, "%s()\n", __func__); + + n = i->index; + if (n > 2) + return -EINVAL; + + if (0 == INPUT(n)->type) + return -EINVAL; + + memset(i, 0, sizeof(*i)); + i->index = n; + i->type = V4L2_INPUT_TYPE_CAMERA; + strcpy(i->name, iname[INPUT(n)->type]); + + i->std = CX25821_NORMS; + return 0; +} + +int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + dprintk(1, "%s()\n", __func__); + return cx25821_enum_input(dev, i); +} + +int vidioc_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + *i = dev->input; + dprintk(1, "%s() returns %d\n", __func__, *i); + return 0; +} + + +int vidioc_s_input(struct file *file, void *priv, unsigned int i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + dprintk(1, "%s(%d)\n", __func__, i); + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + if (i > 2) { + dprintk(1, "%s() -EINVAL\n", __func__); + return -EINVAL; + } + + mutex_lock(&dev->lock); + cx25821_video_mux(dev, i); + mutex_unlock(&dev->lock); + return 0; +} + +#ifdef TUNER_FLAG +int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + f->frequency = dev->freq; + + cx25821_call_all(dev, tuner, g_frequency, f); + + return 0; +} + +int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f) +{ + mutex_lock(&dev->lock); + dev->freq = f->frequency; + + cx25821_call_all(dev, tuner, s_frequency, f); + + /* When changing channels it is required to reset TVAUDIO */ + msleep(10); + + mutex_unlock(&dev->lock); + + return 0; +} + +int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return cx25821_set_freq(dev, f); +} +#endif + +#ifdef CONFIG_VIDEO_ADV_DEBUG +int vidioc_g_register(struct file *file, void *fh, + struct v4l2_dbg_register *reg) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; + + if (!v4l2_chip_match_host(®->match)) + return -EINVAL; + + cx25821_call_all(dev, core, g_register, reg); + + return 0; +} + +int vidioc_s_register(struct file *file, void *fh, + struct v4l2_dbg_register *reg) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; + + if (!v4l2_chip_match_host(®->match)) + return -EINVAL; + + cx25821_call_all(dev, core, s_register, reg); + + return 0; +} + +#endif + + +#ifdef TUNER_FLAG +int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + if (unlikely(UNSET == dev->tuner_type)) + return -EINVAL; + if (0 != t->index) + return -EINVAL; + + strcpy(t->name, "Television"); + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM; + t->rangehigh = 0xffffffffUL; + + t->signal = 0xffff ; /* LOCKED */ + return 0; +} + +int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + struct cx25821_fh *fh = priv; + int err; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(1, "%s()\n", __func__); + if (UNSET == dev->tuner_type) + return -EINVAL; + if (0 != t->index) + return -EINVAL; + + return 0; +} + +#endif +// ****************************************************************************************** +static const struct v4l2_queryctrl no_ctl = { + .name = "42", + .flags = V4L2_CTRL_FLAG_DISABLED, +}; + +static struct v4l2_queryctrl cx25821_ctls[] = { + /* --- video --- */ + { + .id = V4L2_CID_BRIGHTNESS, + .name = "Brightness", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 6200, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_CONTRAST, + .name = "Contrast", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 5000, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_SATURATION, + .name = "Saturation", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 5000, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_HUE, + .name = "Hue", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 5000, + .type = V4L2_CTRL_TYPE_INTEGER, + } +}; +static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls); + +static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) +{ + int i; + + if (qctrl->id < V4L2_CID_BASE || + qctrl->id >= V4L2_CID_LASTP1) + return -EINVAL; + for (i = 0; i < CX25821_CTLS; i++) + if (cx25821_ctls[i].id == qctrl->id) + break; + if (i == CX25821_CTLS) { + *qctrl = no_ctl; + return 0; + } + *qctrl = cx25821_ctls[i]; + return 0; +} + +int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qctrl) +{ + return cx25821_ctrl_query(qctrl); +} + +/* ------------------------------------------------------------------ */ +/* VIDEO CTRL IOCTLS */ + +static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id) +{ + unsigned int i; + + for (i = 0; i < CX25821_CTLS; i++) + if (cx25821_ctls[i].id == id) + return cx25821_ctls+i; + return NULL; +} + +int vidioc_g_ctrl(struct file *file, + void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + const struct v4l2_queryctrl* ctrl; + + ctrl = ctrl_by_id(ctl->id); + + if (NULL == ctrl) + return -EINVAL; + switch (ctl->id) + { + case V4L2_CID_BRIGHTNESS: + ctl->value = dev->ctl_bright; + break; + case V4L2_CID_HUE: + ctl->value = dev->ctl_hue; + break; + case V4L2_CID_CONTRAST: + ctl->value = dev->ctl_contrast; + break; + case V4L2_CID_SATURATION: + ctl->value = dev->ctl_saturation; + break; + } + return 0; +} + +int cx25821_set_control(struct cx25821_dev *dev, + struct v4l2_control *ctl, int chan_num) +{ + int err; + const struct v4l2_queryctrl* ctrl; + + err = -EINVAL; + + ctrl = ctrl_by_id(ctl->id); + + if (NULL == ctrl) + return err; + + switch (ctrl->type) + { + case V4L2_CTRL_TYPE_BOOLEAN: + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_INTEGER: + if (ctl->value < ctrl->minimum) + ctl->value = ctrl->minimum; + if (ctl->value > ctrl->maximum) + ctl->value = ctrl->maximum; + break; + default: + /* nothing */; + }; + + switch (ctl->id) + { + case V4L2_CID_BRIGHTNESS: + dev->ctl_bright = ctl->value; + medusa_set_brightness(dev, ctl->value, chan_num); + break; + case V4L2_CID_HUE: + dev->ctl_hue = ctl->value; + medusa_set_hue(dev, ctl->value, chan_num); + break; + case V4L2_CID_CONTRAST: + dev->ctl_contrast = ctl->value; + medusa_set_contrast(dev, ctl->value, chan_num); + break; + case V4L2_CID_SATURATION: + dev->ctl_saturation = ctl->value; + medusa_set_saturation(dev, ctl->value, chan_num); + break; + } + + err = 0; + + return err; +} + +static void init_controls(struct cx25821_dev *dev, int chan_num) +{ + struct v4l2_control ctrl; + int i; + for (i = 0; i < CX25821_CTLS; i++) { + ctrl.id = cx25821_ctls[i].id; + ctrl.value = cx25821_ctls[i].default_value; + + cx25821_set_control(dev, &ctrl, chan_num); + } +} + +int vidioc_cropcap(struct file *file, + void *priv, + struct v4l2_cropcap *cropcap) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + cropcap->bounds.top = cropcap->bounds.left = 0; + cropcap->bounds.width = 720; + cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480; + cropcap->pixelaspect.numerator = dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10; + cropcap->pixelaspect.denominator = dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11; + cropcap->defrect = cropcap->bounds; + return 0; +} + +int vidioc_s_crop(struct file *file, + void *priv, + struct v4l2_crop *crop) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + struct cx25821_fh *fh = priv; + int err; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + // vidioc_s_crop not supported + return -EINVAL; +} + +int vidioc_g_crop(struct file *file, + void *priv, + struct v4l2_crop *crop) +{ + // vidioc_g_crop not supported + return -EINVAL; +} + +int vidioc_querystd(struct file *file, + void *priv, + v4l2_std_id *norm) +{ + // medusa does not support video standard sensing of current input + *norm = CX25821_NORMS; + + return 0; +} + +int is_valid_width(u32 width, v4l2_std_id tvnorm) +{ + if(tvnorm == V4L2_STD_PAL_BG) + { + if (width == 352 || width == 720) + return 1; + else + return 0; + } + + if(tvnorm == V4L2_STD_NTSC_M) + { + if (width == 320 || width == 352 || width == 720) + return 1; + else + return 0; + } + return 0; +} + +int is_valid_height(u32 height, v4l2_std_id tvnorm) +{ + if(tvnorm == V4L2_STD_PAL_BG) + { + if (height == 576 || height == 288) + return 1; + else + return 0; + } + + if(tvnorm == V4L2_STD_NTSC_M) + { + if (height == 480 || height == 240) + return 1; + else + return 0; + } + + return 0; +} + diff --git a/linux/drivers/staging/cx25821/cx25821-video.h b/linux/drivers/staging/cx25821/cx25821-video.h new file mode 100644 index 000000000..d43e93282 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video.h @@ -0,0 +1,173 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef CX25821_VIDEO_H_ +#define CX25821_VIDEO_H_ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "compat.h" +#include +#include + +#include "cx25821.h" +#include +#include + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +/* Include V4L1 specific functions. Should be removed soon */ +#include +#endif + +#define TUNER_FLAG + +#define VIDEO_DEBUG 0 + +#define dprintk(level, fmt, arg...)\ + do { if (VIDEO_DEBUG >= level)\ + printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ + } while (0) + + +//For IOCTL to identify running upstream +#define UPSTREAM_START_VIDEO 700 +#define UPSTREAM_STOP_VIDEO 701 +#define UPSTREAM_START_AUDIO 702 +#define UPSTREAM_STOP_AUDIO 703 +#define UPSTREAM_DUMP_REGISTERS 702 +#define SET_VIDEO_STD 800 +#define SET_PIXEL_FORMAT 1000 +#define ENABLE_CIF_RESOLUTION 1001 + +#define REG_READ 900 +#define REG_WRITE 901 +#define MEDUSA_READ 910 +#define MEDUSA_WRITE 911 + +extern struct sram_channel *channel0; +extern struct sram_channel *channel1; +extern struct sram_channel *channel2; +extern struct sram_channel *channel3; +extern struct sram_channel *channel4; +extern struct sram_channel *channel5; +extern struct sram_channel *channel6; +extern struct sram_channel *channel7; +extern struct sram_channel *channel9; +extern struct sram_channel *channel10; +extern struct sram_channel *channel11; +extern struct video_device cx25821_video_template0; +extern struct video_device cx25821_video_template1; +extern struct video_device cx25821_video_template2; +extern struct video_device cx25821_video_template3; +extern struct video_device cx25821_video_template4; +extern struct video_device cx25821_video_template5; +extern struct video_device cx25821_video_template6; +extern struct video_device cx25821_video_template7; +extern struct video_device cx25821_video_template9; +extern struct video_device cx25821_video_template10; +extern struct video_device cx25821_video_template11; +extern struct video_device cx25821_videoioctl_template; +//extern const u32 *ctrl_classes[]; + +extern unsigned int vid_limit; + +#define FORMAT_FLAGS_PACKED 0x01 +extern struct cx25821_fmt formats[]; +extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc); +extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; + +extern void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q); +extern void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, u32 count); + +#ifdef TUNER_FLAG +extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm); +#endif + + +extern int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit); +extern int res_check(struct cx25821_fh *fh, unsigned int bit); +extern int res_locked(struct cx25821_dev *dev, unsigned int bit); +extern void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits); +extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input); +extern int cx25821_start_video_dma(struct cx25821_dev *dev, + struct cx25821_dmaqueue *q, + struct cx25821_buffer *buf, + struct sram_channel *channel); + +extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width, unsigned int height, enum v4l2_field field); +extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status); +extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num); +extern int cx25821_video_register(struct cx25821_dev *dev, int chan_num, struct video_device *video_template); +extern int get_format_size(void); + +extern int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size); +extern int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field); +extern void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb); +extern struct videobuf_queue *get_queue(struct cx25821_fh *fh); +extern int get_resource(struct cx25821_fh *fh, int resource); +extern int video_mmap(struct file *file, struct vm_area_struct *vma); +extern int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f); +extern int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap); +extern int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f); +extern int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf); +extern int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p); +extern int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p); +extern int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p); +extern int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms); +extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i); +extern int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i); +extern int vidioc_g_input(struct file *file, void *priv, unsigned int *i); +extern int vidioc_s_input(struct file *file, void *priv, unsigned int i); +extern int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctl); +extern int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f); +extern int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f); +extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f); +extern int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f); +extern int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg); +extern int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg); +extern int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t); +extern int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t); + +extern int is_valid_width(u32 width, v4l2_std_id tvnorm); +extern int is_valid_height(u32 height, v4l2_std_id tvnorm); + +extern int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p); +extern int vidioc_s_priority(struct file *file, void *f, enum v4l2_priority prio); + +extern int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qctrl); +extern int cx25821_set_control(struct cx25821_dev *dev, struct v4l2_control *ctrl, int chan_num); + +extern int vidioc_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap); +extern int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop); +extern int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop); + +extern int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm); +#endif diff --git a/linux/drivers/staging/cx25821/cx25821-video0.c b/linux/drivers/staging/cx25821/cx25821-video0.c new file mode 100644 index 000000000..9dbd740f1 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video0.c @@ -0,0 +1,457 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH00]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH00]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH00] && h->video_dev[SRAM_CH00]->minor == minor) + { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH00; + pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio,&fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO0)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO0)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH00] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; + } + + return 0; +} + + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + //stop the risc engine and fifo + cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO0)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO0); + } + + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO0)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO0); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = PIXEL_FRMT_422; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) + { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) + { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH00, pix_format ); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) + { + dev->use_cif_resolution[SRAM_CH00] = 1; + }else + { + dev->use_cif_resolution[SRAM_CH00] = 0; + } + dev->cif_width[SRAM_CH00] = fh->width; + medusa_set_resolution( dev, fh->width, SRAM_CH00 ); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + + p->sequence = dev->vidq[SRAM_CH00].count; + + return ret_val; +} + +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH00]; + u32 tmp = 0; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 0 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return cx25821_set_control(dev, ctl, SRAM_CH00); +} + +// exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_video_template0 = { + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821-video1.c b/linux/drivers/staging/cx25821/cx25821-video1.c new file mode 100644 index 000000000..44db11940 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video1.c @@ -0,0 +1,456 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH01]; + + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH01]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH01] && h->video_dev[SRAM_CH01]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH01; + pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio,&fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO1)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO1)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH01] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; + } + + return 0; +} + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + //stop the risc engine and fifo + cx_write(channel1->dma_ctl, 0); /* FIFO and RISC disable */ + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO1)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO1); + } + + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO1)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO1); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) + { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) + { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH01, pix_format ); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) + { + dev->use_cif_resolution[SRAM_CH01] = 1; + }else + { + dev->use_cif_resolution[SRAM_CH01] = 0; + } + dev->cif_width[SRAM_CH01] = fh->width; + medusa_set_resolution( dev, fh->width, SRAM_CH01 ); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + + p->sequence = dev->vidq[SRAM_CH01].count; + + return ret_val; +} + +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH01]; + u32 tmp = 0; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 1 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return cx25821_set_control(dev, ctl, SRAM_CH01); +} +//exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_video_template1 = { + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821-video2.c b/linux/drivers/staging/cx25821/cx25821-video2.c new file mode 100644 index 000000000..98db1488d --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video2.c @@ -0,0 +1,459 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH02]; + + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH02]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH02] && h->video_dev[SRAM_CH02]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH02; + pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio,&fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO2)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO2)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH02] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; + } + + return 0; +} + + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + //stop the risc engine and fifo + cx_write(channel2->dma_ctl, 0); /* FIFO and RISC disable */ + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO2)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO2); + } + + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO2)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO2); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) + { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) + { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH02, pix_format ); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) + { + dev->use_cif_resolution[SRAM_CH02] = 1; + }else + { + dev->use_cif_resolution[SRAM_CH02] = 0; + } + dev->cif_width[SRAM_CH02] = fh->width; + medusa_set_resolution( dev, fh->width, SRAM_CH02 ); + + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + + p->sequence = dev->vidq[SRAM_CH02].count; + + return ret_val; +} + +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH02]; + u32 tmp = 0; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + + cx25821_call_all(dev, core, log_status); + + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 2 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return cx25821_set_control(dev, ctl, SRAM_CH02); +} +// exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_video_template2 = { + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821-video3.c b/linux/drivers/staging/cx25821/cx25821-video3.c new file mode 100644 index 000000000..3dcecd264 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video3.c @@ -0,0 +1,458 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH03]; + + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH03]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH03] && h->video_dev[SRAM_CH03]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH03; + pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio,&fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO3)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO3)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH03] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; + } + + return 0; +} + + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + //stop the risc engine and fifo + cx_write(channel3->dma_ctl, 0); /* FIFO and RISC disable */ + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO3)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO3); + } + + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO3)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO3); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) + { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) + { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH03, pix_format ); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) + { + dev->use_cif_resolution[SRAM_CH03] = 1; + }else + { + dev->use_cif_resolution[SRAM_CH03] = 0; + } + dev->cif_width[SRAM_CH03] = fh->width; + medusa_set_resolution( dev, fh->width, SRAM_CH03 ); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + + p->sequence = dev->vidq[SRAM_CH03].count; + + return ret_val; +} + +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH03]; + u32 tmp = 0; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 3 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return cx25821_set_control(dev, ctl, SRAM_CH03); +} + +// exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_video_template3 = { + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821-video4.c b/linux/drivers/staging/cx25821/cx25821-video4.c new file mode 100644 index 000000000..03da3642c --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video4.c @@ -0,0 +1,456 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH04]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH04]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH04] && h->video_dev[SRAM_CH04]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH04; + pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio,&fh->prio); + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO4)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO4)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH04] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; + } + + return 0; +} + + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + //stop the risc engine and fifo + cx_write(channel4->dma_ctl, 0); /* FIFO and RISC disable */ + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO4)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO4); + } + + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO4)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO4); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + + // check priority + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) + { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) + { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH04, pix_format ); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) + { + dev->use_cif_resolution[SRAM_CH04] = 1; + }else + { + dev->use_cif_resolution[SRAM_CH04] = 0; + } + dev->cif_width[SRAM_CH04] = fh->width; + medusa_set_resolution( dev, fh->width, SRAM_CH04); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + + p->sequence = dev->vidq[SRAM_CH04].count; + + return ret_val; +} + +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH04]; + u32 tmp = 0; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 4 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return cx25821_set_control(dev, ctl, SRAM_CH04); +} + +// exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_video_template4 = { + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821-video5.c b/linux/drivers/staging/cx25821/cx25821-video5.c new file mode 100644 index 000000000..1d4754392 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video5.c @@ -0,0 +1,455 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH05]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH05]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH05] && h->video_dev[SRAM_CH05]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH05; + pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio,&fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO5)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO5)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH05] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; + } + + return 0; +} + + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + //stop the risc engine and fifo + cx_write(channel5->dma_ctl, 0); /* FIFO and RISC disable */ + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO5)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO5); + } + + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO5)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO5); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) + { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) + { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH05, pix_format ); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) + { + dev->use_cif_resolution[SRAM_CH05] = 1; + }else + { + dev->use_cif_resolution[SRAM_CH05] = 0; + } + dev->cif_width[SRAM_CH05] = fh->width; + medusa_set_resolution( dev, fh->width, SRAM_CH05 ); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + + p->sequence = dev->vidq[SRAM_CH05].count; + + return ret_val; +} +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH05]; + u32 tmp = 0; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 5 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return cx25821_set_control(dev, ctl, SRAM_CH05); +} + +// exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_video_template5 = { + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821-video6.c b/linux/drivers/staging/cx25821/cx25821-video6.c new file mode 100644 index 000000000..980565af5 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video6.c @@ -0,0 +1,455 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH06]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH06]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH06] && h->video_dev[SRAM_CH06]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH06; + pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio,&fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO6)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO6)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH06] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; + } + + return 0; +} + + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + //stop the risc engine and fifo + cx_write(channel6->dma_ctl, 0); /* FIFO and RISC disable */ + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO6)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO6); + } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO6)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO6); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) + { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) + { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH06, pix_format ); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) + { + dev->use_cif_resolution[SRAM_CH06] = 1; + }else + { + dev->use_cif_resolution[SRAM_CH06] = 0; + } + dev->cif_width[SRAM_CH06] = fh->width; + medusa_set_resolution( dev, fh->width, SRAM_CH06 ); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + + p->sequence = dev->vidq[SRAM_CH06].count; + + return ret_val; +} + +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH06]; + u32 tmp = 0; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 6 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return cx25821_set_control(dev, ctl, SRAM_CH06); +} + +// exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_video_template6 = { + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821-video7.c b/linux/drivers/staging/cx25821/cx25821-video7.c new file mode 100644 index 000000000..966e369a4 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-video7.c @@ -0,0 +1,454 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH07]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH07]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH07] && h->video_dev[SRAM_CH07]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH07; + pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio,&fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO7)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO7)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH07] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; + } + + return 0; +} + + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + //stop the risc engine and fifo + cx_write(channel7->dma_ctl, 0); /* FIFO and RISC disable */ + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO7)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO7); + } + + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO7)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO7); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) + { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) + { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH07, pix_format ); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) + { + dev->use_cif_resolution[SRAM_CH07] = 1; + }else + { + dev->use_cif_resolution[SRAM_CH07] = 0; + } + dev->cif_width[SRAM_CH07] = fh->width; + medusa_set_resolution( dev, fh->width, SRAM_CH07 ); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + + p->sequence = dev->vidq[SRAM_CH07].count; + + return ret_val; +} +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH07]; + u32 tmp = 0; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 7 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return cx25821_set_control(dev, ctl, SRAM_CH07); +} + +// exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_video_template7 = { + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821-videoioctl.c b/linux/drivers/staging/cx25821/cx25821-videoioctl.c new file mode 100644 index 000000000..a5363e486 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-videoioctl.c @@ -0,0 +1,500 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[VIDEO_IOCTL_CH]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[VIDEO_IOCTL_CH]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->ioctl_dev && h->ioctl_dev->minor == minor) + { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = VIDEO_IOCTL_CH; + pix_format = V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio,&fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO_IOCTL)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + return POLLIN|POLLRDNORM; + + return 0; +} + + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO_IOCTL); + } + + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO_IOCTL)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO_IOCTL); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vidq.field = f->fmt.pix.field; + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct cx25821_fh *fh = priv; + return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); +} + +static long video_ioctl_set(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + struct downstream_user_struct *data_from_user; + int command; + int width = 720; + int selected_channel = 0, pix_format = 0, i = 0; + int cif_enable = 0, cif_width = 0; + u32 value = 0; + + + data_from_user = (struct downstream_user_struct *)arg; + + if( !data_from_user ) + { + printk("cx25821 in %s(): User data is INVALID. Returning.\n", __func__); + return 0; + } + + command = data_from_user->command; + + if( command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT && command != ENABLE_CIF_RESOLUTION && + command != REG_READ && command != REG_WRITE && command != MEDUSA_READ && command != MEDUSA_WRITE) + { + return 0; + } + + + switch(command) + { + case SET_VIDEO_STD: + dev->tvnorm = !strcmp(data_from_user->vid_stdname,"PAL") ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; + medusa_set_videostandard(dev); + break; + + case SET_PIXEL_FORMAT: + selected_channel = data_from_user->decoder_select; + pix_format = data_from_user->pixel_format; + + if( !(selected_channel <= 7 && selected_channel >= 0) ) + { + selected_channel -= 4; + selected_channel = selected_channel % 8; + } + + if( selected_channel >= 0 ) + cx25821_set_pixel_format( dev, selected_channel, pix_format ); + + break; + + case ENABLE_CIF_RESOLUTION: + selected_channel = data_from_user->decoder_select; + cif_enable = data_from_user->cif_resolution_enable; + cif_width = data_from_user->cif_width; + + if( cif_enable ) + { + if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK ) + width = 352; + else + width = (cif_width == 320 || cif_width == 352) ? cif_width : 320; + } + + if( !(selected_channel <= 7 && selected_channel >= 0) ) + { + selected_channel -= 4; + selected_channel = selected_channel % 8; + } + + + if( selected_channel <= 7 && selected_channel >= 0 ) + { + dev->use_cif_resolution[selected_channel] = cif_enable; + dev->cif_width[selected_channel] = width; + } + else + { + for( i=0; i < VID_CHANNEL_NUM; i++ ) + { + dev->use_cif_resolution[i] = cif_enable; + dev->cif_width[i] = width; + } + } + + medusa_set_resolution( dev, width, selected_channel ); + break; + case REG_READ: + data_from_user->reg_data = cx_read(data_from_user->reg_address); + break; + case REG_WRITE: + cx_write(data_from_user->reg_address, data_from_user->reg_data); + break; + case MEDUSA_READ: + value = cx25821_i2c_read(&dev->i2c_bus[0], (u16)data_from_user->reg_address, &data_from_user->reg_data); + break; + case MEDUSA_WRITE: + cx25821_i2c_write(&dev->i2c_bus[0], (u16)data_from_user->reg_address, data_from_user->reg_data); + break; + } + + return 0; +} + +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return 0; +} +// exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl_set, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_videoioctl_template = { + .name = "cx25821-videoioctl", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821-vidups10.c b/linux/drivers/staging/cx25821/cx25821-vidups10.c new file mode 100644 index 000000000..4738e9184 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-vidups10.c @@ -0,0 +1,443 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH10]; + + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH10]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH10] && h->video_dev[SRAM_CH10]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + + dev->channel_opened = 9; + fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); + + v4l2_prio_open(&dev->prio,&fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO10)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO10)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + return POLLIN|POLLRDNORM; + return 0; +} + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + //stop the risc engine and fifo + //cx_write(channel10->dma_ctl, 0); + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO10)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO10); + } + + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO10)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO10); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + +static long video_ioctl_upstream10(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + int command = 0; + struct upstream_user_struct *data_from_user; + + + data_from_user = (struct upstream_user_struct *)arg; + + if( !data_from_user ) + { + printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); + return 0; + } + + command = data_from_user->command; + + if( command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO ) + { + return 0; + } + + dev->input_filename_ch2 = data_from_user->input_filename; + dev->input_audiofilename = data_from_user->input_filename; + dev->vid_stdname_ch2 = data_from_user->vid_stdname; + dev->pixel_format_ch2 = data_from_user->pixel_format; + dev->channel_select_ch2 = data_from_user->channel_select; + dev->command_ch2 = data_from_user->command; + + + switch(command) + { + case UPSTREAM_START_VIDEO: + cx25821_start_upstream_video_ch2(dev, data_from_user); + break; + + case UPSTREAM_STOP_VIDEO: + cx25821_stop_upstream_video_ch2(dev); + break; + } + + return 0; +} + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vidq.field = f->fmt.pix.field; + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct cx25821_fh *fh = priv; + return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); +} + +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return 0; +} + +//exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl_upstream10, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_video_template10 = { + .name = "cx25821-upstream10", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821-vidups9.c b/linux/drivers/staging/cx25821/cx25821-vidups9.c new file mode 100644 index 000000000..7832fd160 --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821-vidups9.c @@ -0,0 +1,441 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" + + +static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) +{ + struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH09]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH09]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); + } else { + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } + } + + if (list_empty(&q->active)) + { + dprintk(2, "active queue empty!\n"); + } +} + + +static struct videobuf_queue_ops cx25821_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; + + +static int video_open(struct file *file) +{ + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) + { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH09] && h->video_dev[SRAM_CH09]->minor == minor) + { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + } + + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } + + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = 8; + fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); + + v4l2_prio_open(&dev->prio,&fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); + + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); + + return 0; +} + +static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +{ + struct cx25821_fh *fh = file->private_data; + + switch (fh->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO9)) + return -EBUSY; + + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + + default: + BUG(); + return 0; + } +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO9)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + return POLLIN|POLLRDNORM; + return 0; +} + + +static int video_release(struct file *file) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + + //stop the risc engine and fifo + //cx_write(channel9->dma_ctl, 0); + + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO9)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO9); + } + + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } + + videobuf_mmap_free(&fh->vidq); + + v4l2_prio_close(&dev->prio,&fh->prio); + + file->private_data = NULL; + kfree(fh); + + return 0; +} + + +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + { + return -EINVAL; + } + + if (unlikely(i != fh->type)) + { + return -EINVAL; + } + + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO9)))) + { + return -EBUSY; + } + + return videobuf_streamon(get_queue(fh)); +} + +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO9); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; +} + + +static long video_ioctl_upstream9(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + int command = 0; + struct upstream_user_struct *data_from_user; + + + data_from_user = (struct upstream_user_struct *)arg; + + if( !data_from_user ) + { + printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); + return 0; + } + + command = data_from_user->command; + + if( command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO ) + { + return 0; + } + + + dev->input_filename = data_from_user->input_filename; + dev->input_audiofilename = data_from_user->input_filename; + dev->vid_stdname = data_from_user->vid_stdname; + dev->pixel_format = data_from_user->pixel_format; + dev->channel_select = data_from_user->channel_select; + dev->command = data_from_user->command; + + + switch(command) + { + case UPSTREAM_START_VIDEO: + cx25821_start_upstream_video_ch1(dev, data_from_user); + break; + + case UPSTREAM_STOP_VIDEO: + cx25821_stop_upstream_video_ch1(dev); + break; + } + + return 0; +} + + +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + + if (0 != err) + return err; + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vidq.field = f->fmt.pix.field; + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + return 0; +} + +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) +{ + struct cx25821_fh *fh = priv; + return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); +} +static int vidioc_log_status (struct file *file, void *priv) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; + + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + dev->name); + cx25821_call_all(dev, core, log_status); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl) +{ + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + struct cx25821_fh *fh = priv; + int err; + if (fh) + { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return 0; +} +// exported stuff +static const struct v4l2_file_operations video_fops = { + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl_upstream9, +}; + +static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, +#ifdef TUNER_FLAG + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, +#endif + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif +#ifdef TUNER_FLAG + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, +#endif +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif +}; + +struct video_device cx25821_video_template9 = { + .name = "cx25821-upstream9", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, +}; + + + diff --git a/linux/drivers/staging/cx25821/cx25821.h b/linux/drivers/staging/cx25821/cx25821.h new file mode 100644 index 000000000..04beeb91f --- /dev/null +++ b/linux/drivers/staging/cx25821/cx25821.h @@ -0,0 +1,590 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef CX25821_H_ +#define CX25821_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "compat.h" + +#include "btcx-risc.h" +#include "cx25821-reg.h" +#include "cx25821-medusa-reg.h" +#include "cx25821-sram.h" +#include "cx25821-audio.h" +#include "media/cx2341x.h" + +#include +#include + +#define CX25821_VERSION_CODE KERNEL_VERSION(0, 0, 106) + +#define UNSET (-1U) +#define NO_SYNC_LINE (-1U) + +#define CX25821_MAXBOARDS 2 + +#define TRUE 1 +#define FALSE 0 +#define LINE_SIZE_D1 1440 + +// Number of decoders and encoders +#define MAX_DECODERS 8 +#define MAX_ENCODERS 2 +#define QUAD_DECODERS 4 +#define MAX_CAMERAS 16 + +/* Max number of inputs by card */ +#define MAX_CX25821_INPUT 8 +#define INPUT(nr) (&cx25821_boards[dev->board].input[nr]) +#define RESOURCE_VIDEO0 1 +#define RESOURCE_VIDEO1 2 +#define RESOURCE_VIDEO2 4 +#define RESOURCE_VIDEO3 8 +#define RESOURCE_VIDEO4 16 +#define RESOURCE_VIDEO5 32 +#define RESOURCE_VIDEO6 64 +#define RESOURCE_VIDEO7 128 +#define RESOURCE_VIDEO8 256 +#define RESOURCE_VIDEO9 512 +#define RESOURCE_VIDEO10 1024 +#define RESOURCE_VIDEO11 2048 +#define RESOURCE_VIDEO_IOCTL 4096 + + +#define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ + +#define UNKNOWN_BOARD 0 +#define CX25821_BOARD 1 + +/* Currently supported by the driver */ +#define CX25821_NORMS (\ + V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \ + V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \ + V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_H | \ + V4L2_STD_PAL_Nc ) + +#define CX25821_BOARD_CONEXANT_ATHENA10 1 +#define MAX_VID_CHANNEL_NUM 12 +#define VID_CHANNEL_NUM 8 + +struct cx25821_fmt { + char *name; + u32 fourcc; /* v4l2 format id */ + int depth; + int flags; + u32 cxformat; +}; + +struct cx25821_ctrl { + struct v4l2_queryctrl v; + u32 off; + u32 reg; + u32 mask; + u32 shift; +}; + +struct cx25821_tvnorm { + char *name; + v4l2_std_id id; + u32 cxiformat; + u32 cxoformat; +}; + +struct cx25821_fh { + struct cx25821_dev *dev; + enum v4l2_buf_type type; + int radio; + u32 resources; + + enum v4l2_priority prio; + + /* video overlay */ + struct v4l2_window win; + struct v4l2_clip *clips; + unsigned int nclips; + + /* video capture */ + struct cx25821_fmt *fmt; + unsigned int width, height; + + /* vbi capture */ + struct videobuf_queue vidq; + struct videobuf_queue vbiq; + + /* H264 Encoder specifics ONLY */ + struct videobuf_queue mpegq; + atomic_t v4l_reading; +}; + +enum cx25821_itype { + CX25821_VMUX_COMPOSITE = 1, + CX25821_VMUX_SVIDEO, + CX25821_VMUX_DEBUG, + CX25821_RADIO, +}; + +enum cx25821_src_sel_type { + CX25821_SRC_SEL_EXT_656_VIDEO = 0, + CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO +}; + +/* buffer for one video frame */ +struct cx25821_buffer { + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + /* cx25821 specific */ + unsigned int bpl; + struct btcx_riscmem risc; + struct cx25821_fmt *fmt; + u32 count; +}; + +struct cx25821_input { + enum cx25821_itype type; + unsigned int vmux; + u32 gpio0, gpio1, gpio2, gpio3; +}; + +typedef enum { + CX25821_UNDEFINED = 0, + CX25821_RAW, + CX25821_264 +} port_t; + +struct cx25821_board { + char *name; + port_t porta, portb, portc; + unsigned int tuner_type; + unsigned int radio_type; + unsigned char tuner_addr; + unsigned char radio_addr; + + u32 clk_freq; + struct cx25821_input input[2]; +}; + +struct cx25821_subid { + u16 subvendor; + u16 subdevice; + u32 card; +}; + +struct cx25821_i2c { + struct cx25821_dev *dev; + + int nr; + + /* i2c i/o */ + struct i2c_adapter i2c_adap; + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + u32 i2c_rc; + + /* cx25821 registers used for raw addess */ + u32 i2c_period; + u32 reg_ctrl; + u32 reg_stat; + u32 reg_addr; + u32 reg_rdata; + u32 reg_wdata; +}; + +struct cx25821_dmaqueue { + struct list_head active; + struct list_head queued; + struct timer_list timeout; + struct btcx_riscmem stopper; + u32 count; +}; + +struct cx25821_data { + struct cx25821_dev *dev; + struct sram_channel *channel; +}; + +struct cx25821_dev { + struct list_head devlist; + atomic_t refcount; + struct v4l2_device v4l2_dev; + + struct v4l2_prio_state prio; + + /* pci stuff */ + struct pci_dev *pci; + unsigned char pci_rev, pci_lat; + int pci_bus, pci_slot; + u32 base_io_addr; + u32 __iomem *lmmio; + u8 __iomem *bmmio; + int pci_irqmask; + int hwrevision; + + u32 clk_freq; + + /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ + struct cx25821_i2c i2c_bus[3]; + + int nr; + struct mutex lock; + + /* board details */ + unsigned int board; + char name[32]; + + /* sram configuration */ + struct sram_channel *sram_channels; + + /* Analog video */ + u32 resources; + unsigned int input; + u32 tvaudio; + v4l2_std_id tvnorm; + unsigned int tuner_type; + unsigned char tuner_addr; + unsigned int radio_type; + unsigned char radio_addr; + unsigned int has_radio; + unsigned int videc_type; + unsigned char videc_addr; + unsigned short _max_num_decoders; + + int ctl_bright; + int ctl_contrast; + int ctl_hue; + int ctl_saturation; + + struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; + + /* Analog Audio Upstream */ + int _audio_is_running; + int _audiopixel_format; + int _is_first_audio_frame; + int _audiofile_status; + int _audio_lines_count; + int _audioframe_count; + int _audio_upstream_channel_select; + int _last_index_irq; //The last interrupt index processed. + + __le32 * _risc_audio_jmp_addr; + __le32 * _risc_virt_start_addr; + __le32 * _risc_virt_addr; + dma_addr_t _risc_phys_addr; + dma_addr_t _risc_phys_start_addr; + + unsigned int _audiorisc_size; + unsigned int _audiodata_buf_size; + __le32 * _audiodata_buf_virt_addr; + dma_addr_t _audiodata_buf_phys_addr; + char *_audiofilename; + + /* V4l */ + u32 freq; + struct video_device *video_dev[MAX_VID_CHANNEL_NUM]; + struct video_device *vbi_dev; + struct video_device *radio_dev; + struct video_device *ioctl_dev; + + struct cx25821_dmaqueue vidq[MAX_VID_CHANNEL_NUM]; + spinlock_t slock; + + /* Video Upstream */ + int _line_size; + int _prog_cnt; + int _pixel_format; + int _is_first_frame; + int _is_running; + int _file_status; + int _lines_count; + int _frame_count; + int _channel_upstream_select; + unsigned int _risc_size; + + __le32 * _dma_virt_start_addr; + __le32 * _dma_virt_addr; + dma_addr_t _dma_phys_addr; + dma_addr_t _dma_phys_start_addr; + + unsigned int _data_buf_size; + __le32 * _data_buf_virt_addr; + dma_addr_t _data_buf_phys_addr; + char * _filename; + char * _defaultname; + + + int _line_size_ch2; + int _prog_cnt_ch2; + int _pixel_format_ch2; + int _is_first_frame_ch2; + int _is_running_ch2; + int _file_status_ch2; + int _lines_count_ch2; + int _frame_count_ch2; + int _channel2_upstream_select; + unsigned int _risc_size_ch2; + + __le32 * _dma_virt_start_addr_ch2; + __le32 * _dma_virt_addr_ch2; + dma_addr_t _dma_phys_addr_ch2; + dma_addr_t _dma_phys_start_addr_ch2; + + unsigned int _data_buf_size_ch2; + __le32 * _data_buf_virt_addr_ch2; + dma_addr_t _data_buf_phys_addr_ch2; + char * _filename_ch2; + char * _defaultname_ch2; + + /* MPEG Encoder ONLY settings */ + u32 cx23417_mailbox; + struct cx2341x_mpeg_params mpeg_params; + struct video_device *v4l_device; + atomic_t v4l_reader_count; + struct cx25821_tvnorm encodernorm; + + u32 upstream_riscbuf_size; + u32 upstream_databuf_size; + u32 upstream_riscbuf_size_ch2; + u32 upstream_databuf_size_ch2; + u32 audio_upstream_riscbuf_size; + u32 audio_upstream_databuf_size; + int _isNTSC; + int _frame_index; + int _audioframe_index; + struct workqueue_struct * _irq_queues; + struct work_struct _irq_work_entry; + struct workqueue_struct * _irq_queues_ch2; + struct work_struct _irq_work_entry_ch2; + struct workqueue_struct * _irq_audio_queues; + struct work_struct _audio_work_entry; + char *input_filename; + char *input_filename_ch2; + int _frame_index_ch2; + int _isNTSC_ch2; + char *vid_stdname_ch2; + int pixel_format_ch2; + int channel_select_ch2; + int command_ch2; + char *input_audiofilename; + char *vid_stdname; + int pixel_format; + int channel_select; + int command; + int pixel_formats[VID_CHANNEL_NUM]; + int use_cif_resolution[VID_CHANNEL_NUM]; + int cif_width[VID_CHANNEL_NUM]; + int channel_opened; +}; + + +struct upstream_user_struct { + char *input_filename; + char *vid_stdname; + int pixel_format; + int channel_select; + int command; +}; + +struct downstream_user_struct { + char *vid_stdname; + int pixel_format; + int cif_resolution_enable; + int cif_width; + int decoder_select; + int command; + int reg_address; + int reg_data; +}; + +extern struct upstream_user_struct *up_data; + +static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev); +} + +#define cx25821_call_all(dev, o, f, args...) \ + v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) + +extern struct list_head cx25821_devlist; +extern struct cx25821_board cx25821_boards[]; +extern struct cx25821_subid cx25821_subids[]; + +#define SRAM_CH00 0 /* Video A */ +#define SRAM_CH01 1 /* Video B */ +#define SRAM_CH02 2 /* Video C */ +#define SRAM_CH03 3 /* Video D */ +#define SRAM_CH04 4 /* Video E */ +#define SRAM_CH05 5 /* Video F */ +#define SRAM_CH06 6 /* Video G */ +#define SRAM_CH07 7 /* Video H */ + +#define SRAM_CH08 8 /* Audio A */ +#define SRAM_CH09 9 /* Video Upstream I */ +#define SRAM_CH10 10 /* Video Upstream J */ +#define SRAM_CH11 11 /* Audio Upstream AUD_CHANNEL_B */ + + + +#define VID_UPSTREAM_SRAM_CHANNEL_I SRAM_CH09 +#define VID_UPSTREAM_SRAM_CHANNEL_J SRAM_CH10 +#define AUDIO_UPSTREAM_SRAM_CHANNEL_B SRAM_CH11 +#define VIDEO_IOCTL_CH 11 + +struct sram_channel { + char *name; + u32 i; + u32 cmds_start; + u32 ctrl_start; + u32 cdt; + u32 fifo_start; + u32 fifo_size; + u32 ptr1_reg; + u32 ptr2_reg; + u32 cnt1_reg; + u32 cnt2_reg; + u32 int_msk; + u32 int_stat; + u32 int_mstat; + u32 dma_ctl; + u32 gpcnt_ctl; + u32 gpcnt; + u32 aud_length; + u32 aud_cfg; + u32 fld_aud_fifo_en; + u32 fld_aud_risc_en; + + //For Upstream Video + u32 vid_fmt_ctl; + u32 vid_active_ctl1; + u32 vid_active_ctl2; + u32 vid_cdt_size; + + u32 vip_ctl; + u32 pix_frmt; + u32 jumponly; + u32 irq_bit; +}; +extern struct sram_channel cx25821_sram_channels[]; + +#define STATUS_SUCCESS 0 +#define STATUS_UNSUCCESSFUL -1 + +#define cx_read(reg) readl(dev->lmmio + ((reg)>>2)) +#define cx_write(reg, value) writel((value), dev->lmmio + ((reg)>>2)) + +#define cx_andor(reg, mask, value) \ + writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\ + ((value) & (mask)), dev->lmmio+((reg)>>2)) + +#define cx_set(reg, bit) cx_andor((reg), (bit), (bit)) +#define cx_clear(reg, bit) cx_andor((reg), (bit), 0) + +#define Set_GPIO_Bit(Bit) (1 << Bit) +#define Clear_GPIO_Bit(Bit) (~(1 << Bit)) + +#define CX25821_ERR(fmt, args...) printk(KERN_ERR "cx25821(%d): " fmt, dev->board, ## args) +#define CX25821_WARN(fmt, args...) printk(KERN_WARNING "cx25821(%d): " fmt, dev->board , ## args) +#define CX25821_INFO(fmt, args...) printk(KERN_INFO "cx25821(%d): " fmt, dev->board , ## args) + +extern int cx25821_i2c_register(struct cx25821_i2c *bus); +extern void cx25821_card_setup(struct cx25821_dev *dev); +extern int cx25821_ir_init(struct cx25821_dev *dev); +extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value); +extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value); +extern int cx25821_i2c_unregister(struct cx25821_i2c *bus); +extern void cx25821_gpio_init(struct cx25821_dev *dev); +extern void cx25821_set_gpiopin_direction( struct cx25821_dev *dev, + int pin_number, + int pin_logic_value); + +extern int medusa_video_init(struct cx25821_dev *dev); +extern int medusa_set_videostandard(struct cx25821_dev *dev); +extern void medusa_set_resolution(struct cx25821_dev *dev, int width, int decoder_select); +extern int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder); +extern int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder); +extern int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder); +extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder); + +extern int cx25821_sram_channel_setup(struct cx25821_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc); + +extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int top_offset, + unsigned int bottom_offset, + unsigned int bpl, + unsigned int padding, + unsigned int lines); +extern int cx25821_risc_databuffer_audio(struct pci_dev *pci, + struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int bpl, + unsigned int lines, + unsigned int lpi); +extern void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf); +extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,u32 reg, u32 mask, u32 value); +extern void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch); +extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channel *ch); + + +extern struct cx25821_dev* cx25821_dev_get(struct pci_dev *pci); +extern void cx25821_print_irqbits(char *name, char *tag, char **strings, int len, u32 bits, u32 mask); +extern void cx25821_dev_unregister(struct cx25821_dev *dev); +extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, + struct sram_channel *ch, + unsigned int bpl, u32 risc); + +extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, int pixel_format); +extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, int pixel_format); +extern int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select); +extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev); +extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev); +extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev); +extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, struct upstream_user_struct *up_data); +extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, struct upstream_user_struct *up_data); +extern void cx25821_start_upstream_audio(struct cx25821_dev *dev, struct upstream_user_struct *up_data); +extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev); +extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev); +extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev); +extern int cx25821_sram_channel_setup_upstream( struct cx25821_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc); +extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel, u32 format); +extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev); +extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, + struct pci_dev *pci, + struct video_device *template, + char *type); +#endif diff --git a/v4l2-apps/util/cx25821/audioplayback b/v4l2-apps/util/cx25821/audioplayback new file mode 100644 index 000000000..1b09da915 --- /dev/null +++ b/v4l2-apps/util/cx25821/audioplayback @@ -0,0 +1 @@ +aplay -c 2 -r 48000 -f S16_LE $1 diff --git a/v4l2-apps/util/cx25821/audiorecord b/v4l2-apps/util/cx25821/audiorecord new file mode 100644 index 000000000..ee2c46650 --- /dev/null +++ b/v4l2-apps/util/cx25821/audiorecord @@ -0,0 +1 @@ +arecord -D hw:1,0 -d $2 -c 2 -r 48000 -f S16_LE > $1 diff --git a/v4l2-apps/util/cx25821/cx25821-medusa-decoder.c b/v4l2-apps/util/cx25821/cx25821-medusa-decoder.c new file mode 100644 index 000000000..7bd35ed43 --- /dev/null +++ b/v4l2-apps/util/cx25821/cx25821-medusa-decoder.c @@ -0,0 +1,106 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821.h" + + +// Array for GPIO selected bits for a specific decoder. + +enum GPIO_DEF { DECA_SEL = 0, + DECB_SEL, + DECC_SEL, + DECD_SEL, + MON_SEL = 4}; + +enum GPIO_OCTAL_DEF { OCTAL_DECA_SEL = 0, + OCTAL_DECB_SEL, + OCTAL_DECC_SEL, + OCTAL_DECD_SEL, + OCTAL_DECE_SEL, + OCTAL_DECF_SEL, + OCTAL_DECG_SEL, + OCTAL_DECH_SEL, + OCTAL_MON_SEL = 8 }; + + +// Direction bits are at offset 23:16 +#define Set_GPIO_Direction_Bit_To_OUTPUT(Bit) ((1 << Bit) << 16) + +struct medusa_decoder { + int _cur_dec; + unsigned short _num_vdec; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +// Selects Medusa Decoder Channel. +//////////////////////////////////////////////////////////////////////////////////////// +void medusa_decoder_select(struct cx25821_dev *dev, struct medusa_decoder *dec, int decoder) +{ + + if (decoder < DECA_SEL && decoder > MON_SEL ) + return; + + dec->_cur_dec = decoder; + + u32 gpioRegister = cx_read(GP0_IO); + u32 value = (gpioRegister & 0xFFFFFFF0) | dec->_cur_dec; + cx_write( GP0_IO, value ); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// Sets the GPIO pin directions +// Parameters: +// +//////////////////////////////////////////////////////////////////////////////////////// +void medusa_video_set_gpiopin_directions_to_output(struct cx25821_dev *dev, struct medusa_decoder *dec ) +{ + // Here we will make sure that the GPIOs 0-3 are output. keep the rest as is + u32 gpioRegister = cx_read( GP0_IO ); + + // This operation will set the GPIO bits below. + if (dec->_num_vdec == 4) + { + cx_write( GP0_IO, + gpioRegister + | (Set_GPIO_Direction_Bit_To_OUTPUT(DECA_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(DECB_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(DECC_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(DECD_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(MON_SEL)) ); + medusa_decoder_select(dev, dec, MON_SEL); + } + else + { + cx_write( GP0_IO, + gpioRegister + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECA_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECB_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECC_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECD_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECE_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECF_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECG_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECH_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_MON_SEL)) ); + medusa_decoder_select(dev, dec, OCTAL_MON_SEL); + } +} diff --git a/v4l2-apps/util/cx25821/medusaReadWrite.c b/v4l2-apps/util/cx25821/medusaReadWrite.c new file mode 100644 index 000000000..cf4a1a5e6 --- /dev/null +++ b/v4l2-apps/util/cx25821/medusaReadWrite.c @@ -0,0 +1,158 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + + +#define MEDUSA_READ 910 +#define MEDUSA_WRITE 911 + +typedef struct{ + char *vid_stdname; + int pixel_format; + int cif_resolution_enable; + int cif_width; + int decoder_select; + int command; + int reg_address; + int reg_data; +}downstream_user_struct; + + +void print_usage() +{ + printf("\n*********************************\n"); + printf("Sample Usage: ./medusa d 1 r 0x01\n"); + printf("Sample Usage: ./medusa d 1 w 0x0 0x2\n"); + printf(" d device_id Device ID (1 and above) for MultiCard\n"); + printf(" r Read Medusa register\n"); + printf(" w Write Medusa register\n"); +} + +int main(int argc, char** argv) +{ + unsigned int cmd= 0 ; + int fp; + int i = 1, j = 0, k = 0, len = 0; + int mode = 0; + + int register_addr = 0; + int write_value = 0; + + int device_id = 0, video_id = 11; + char * temp2; + char *device_str[4] = {"/dev/video11", "/dev/video23", "/dev/video35", "/dev/video47"}; + + char mode_temp = 's'; + char *param_temp; + + + if(argc < 5 || (tolower(*(argv[1])) != 'd') ) + { + print_usage(); + return -EINVAL; + } + + sscanf(argv[2], "%d", &device_id ); + i += 2; + + if( device_id <= 0 || device_id > 4 ) + { + print_usage(); + return -EINVAL; + } + + printf("\n********************************* \n"); + + if((fp = open(device_str[device_id-1], O_RDWR)) == -1) + { + printf("Error: cannot open device file %s !\n", device_str[device_id-1]); + return -EINVAL; + } + + printf("Device %s open for IOCTL successfully!\n", device_str[device_id-1]); + + + for( ; i < argc; i++) + { + temp2 = argv[i]; + mode_temp = tolower(temp2[0]); + param_temp = argv[i+1]; + + + switch(mode_temp) + { + case 'r': + { + downstream_user_struct arguments; + + sscanf(param_temp, "%x", ®ister_addr ); + + arguments.reg_address = register_addr; + arguments.command = MEDUSA_READ; + + printf("Read parameters: read register = 0x%x, command = %d \n", arguments.reg_address, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + printf("Reg 0x%x = 0x%x\n", arguments.reg_address, arguments.reg_data); + } + break; + + case 'w': + { + downstream_user_struct arguments; + + sscanf(param_temp, "%x", ®ister_addr ); + sscanf(argv[i+2], "%x", &write_value ); + i++; + + arguments.command = MEDUSA_WRITE; + arguments.reg_address = register_addr; + arguments.reg_data = write_value; + + printf("Write parameters: write register = 0x%x, write_value = 0x%x, command = %d \n", arguments.reg_address, arguments.reg_data, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + default: + printf("Please verify the options are correct!\n"); + break; + } + + i++; + } + + + printf("********************************* \n\n"); + close(fp); + return 0; +} + diff --git a/v4l2-apps/util/cx25821/mencode_av b/v4l2-apps/util/cx25821/mencode_av new file mode 100644 index 000000000..6533cb4d8 --- /dev/null +++ b/v4l2-apps/util/cx25821/mencode_av @@ -0,0 +1 @@ +mencoder tv:// -tv driver=v4l2:input=0:norm=ntsc:width=720:height=480:outfmt=yuy2:device=/dev/video$1:forceaudio:alsa=1:adevice=hw.1:audiorate=48000:immediatemode=0:amode=1 buffersize=64 -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=5000:keyint=30 -oac mp3lame -lameopts br=128:cbr:mode=3 -ffourcc divx -o $2 \ No newline at end of file diff --git a/v4l2-apps/util/cx25821/mencode_video b/v4l2-apps/util/cx25821/mencode_video new file mode 100644 index 000000000..9f0c29ebd --- /dev/null +++ b/v4l2-apps/util/cx25821/mencode_video @@ -0,0 +1 @@ +mencoder tv:// -tv driver=v4l2:input=0:norm=ntsc:width=720:height=480:outfmt=yuy2:device=/dev/video$1 -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=5000:keyint=30 -nosound -ffourcc divx -o $2 diff --git a/v4l2-apps/util/cx25821/mplay_av b/v4l2-apps/util/cx25821/mplay_av new file mode 100644 index 000000000..0b11e7af6 --- /dev/null +++ b/v4l2-apps/util/cx25821/mplay_av @@ -0,0 +1 @@ +mplayer -vo x11 -tv driver=v4l2:device=/dev/video$1:input=1:norm=NTSC-M:width=720:height=480:outfmt=yuy2:alsa=1:adevice=hw.1:audiorate=48000:immediatemode=0:amode=1 tv:///0 diff --git a/v4l2-apps/util/cx25821/mplay_cifNTSC b/v4l2-apps/util/cx25821/mplay_cifNTSC new file mode 100644 index 000000000..ba3c34ec2 --- /dev/null +++ b/v4l2-apps/util/cx25821/mplay_cifNTSC @@ -0,0 +1 @@ +mplayer -vo x11 -tv driver=v4l2:device=/dev/video$1:input=1:norm=NTSC-M:width=320:height=240:outfmt=yuy2: tv:///0 diff --git a/v4l2-apps/util/cx25821/mplay_cifPAL b/v4l2-apps/util/cx25821/mplay_cifPAL new file mode 100644 index 000000000..2139ffb0a --- /dev/null +++ b/v4l2-apps/util/cx25821/mplay_cifPAL @@ -0,0 +1 @@ +mplayer -vo x11 -tv driver=v4l2:device=/dev/video$1:input=1:norm=PAL-BG:width=352:height=288:outfmt=yuy2: tv:///0 diff --git a/v4l2-apps/util/cx25821/mplay_video b/v4l2-apps/util/cx25821/mplay_video new file mode 100644 index 000000000..7d9567662 --- /dev/null +++ b/v4l2-apps/util/cx25821/mplay_video @@ -0,0 +1 @@ +mplayer -vo x11 -tv driver=v4l2:device=/dev/video$1:input=1:norm=NTSC-M:width=720:height=480:outfmt=yuy2: tv:///0 diff --git a/v4l2-apps/util/cx25821/regReadWrite.c b/v4l2-apps/util/cx25821/regReadWrite.c new file mode 100644 index 000000000..2d506183d --- /dev/null +++ b/v4l2-apps/util/cx25821/regReadWrite.c @@ -0,0 +1,158 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + + +#define REG_READ 900 +#define REG_WRITE 901 + +typedef struct{ + char *vid_stdname; + int pixel_format; + int cif_resolution_enable; + int cif_width; + int decoder_select; + int command; + int reg_address; + int reg_data; +}downstream_user_struct; + + +void print_usage() +{ + printf("\n*********************************\n"); + printf("Sample Usage: ./reg d 1 r 0x01\n"); + printf("Sample Usage: ./reg d 1 w 0x0 0x2\n"); + printf(" d device_id Device ID (1 and above) for MultiCard\n"); + printf(" r Read Athena register\n"); + printf(" w Write Athena register\n"); +} + +int main(int argc, char** argv) +{ + unsigned int cmd= 0 ; + int fp; + int i = 1, j = 0, k = 0, len = 0; + int mode = 0; + + int register_addr = 0; + int write_value = 0; + + int device_id = 0, video_id = 11; + char * temp2; + char *device_str[4] = {"/dev/video11", "/dev/video23", "/dev/video35", "/dev/video47"}; + + char mode_temp = 's'; + char *param_temp; + + + if(argc < 5 || (tolower(*(argv[1])) != 'd') ) + { + print_usage(); + return -EINVAL; + } + + sscanf(argv[2], "%d", &device_id ); + i += 2; + + if( device_id <= 0 || device_id > 4 ) + { + print_usage(); + return -EINVAL; + } + + printf("\n********************************* \n"); + + if((fp = open(device_str[device_id-1], O_RDWR)) == -1) + { + printf("Error: cannot open device file %s !\n", device_str[device_id-1]); + return -EINVAL; + } + + printf("Device %s open for IOCTL successfully!\n", device_str[device_id-1]); + + + for( ; i < argc; i++) + { + temp2 = argv[i]; + mode_temp = tolower(temp2[0]); + param_temp = argv[i+1]; + + + switch(mode_temp) + { + case 'r': + { + downstream_user_struct arguments; + + sscanf(param_temp, "%x", ®ister_addr ); + + arguments.reg_address = register_addr; + arguments.command = REG_READ; + + printf("Read parameters: read register = 0x%x, command = %d \n", arguments.reg_address, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + printf("Reg 0x%x = 0x%x\n", arguments.reg_address, arguments.reg_data); + } + break; + + case 'w': + { + downstream_user_struct arguments; + + sscanf(param_temp, "%x", ®ister_addr ); + sscanf(argv[i+2], "%x", &write_value ); + i++; + + arguments.command = REG_WRITE; + arguments.reg_address = register_addr; + arguments.reg_data = write_value; + + printf("Write parameters: write register = 0x%x, write_value = 0x%x, command = %d \n", arguments.reg_address, arguments.reg_data, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + default: + printf("Please verify the options are correct!\n"); + break; + } + + i++; + } + + + printf("********************************* \n\n"); + close(fp); + return 0; +} + diff --git a/v4l2-apps/util/cx25821/setAlsaVolume b/v4l2-apps/util/cx25821/setAlsaVolume new file mode 100644 index 000000000..55dd3dc89 --- /dev/null +++ b/v4l2-apps/util/cx25821/setAlsaVolume @@ -0,0 +1,2 @@ +amixer set Master,0 100% unmute +amixer set Capture,0 90% captur diff --git a/v4l2-apps/util/cx25821/setvideosetting.c b/v4l2-apps/util/cx25821/setvideosetting.c new file mode 100644 index 000000000..87e36045d --- /dev/null +++ b/v4l2-apps/util/cx25821/setvideosetting.c @@ -0,0 +1,187 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + + +#define SET_VIDEO_STD 800 +#define SET_PIXEL_FORMAT 1000 +#define ENABLE_CIF_RESOLUTION 1001 + + +#define PIXEL_FRMT_422 4 +#define PIXEL_FRMT_411 5 +#define PIXEL_FRMT_Y8 6 +#define ALL_DECODERS 752 + +typedef struct { + char *vid_stdname; + int pixel_format; + int cif_resolution_enable; + int cif_width; + int decoder_select; + int command; +} downstream_user_struct; + + +void print_usage() +{ + printf("\n*********************************\n"); + printf("Sample Usage: ./set d 1 standard NTSC format 422 7 resolution 320 7\n"); + printf(" device_id Device ID (1 and above) for MultiCard\n"); + printf(" standard Video Standard (PAL/NTSC)\n"); + printf(" format Output Pixel Format (422 or 411) for specific decoder (e.g. 7)\n"); + printf(" resolution 352/320 for CIF and 720 for D1 resolution for specific decoder (e.g. 7)\n"); +} + +int main(int argc, char** argv) +{ + unsigned int cmd= 0 ; + int fp; + int i = 1, j = 0, k = 0, len = 0; + int mode = 0; + int pixel_format = 0; + int width_input = 0; + int decoder_input = 0; + int device_id = 0, video_id = 11; + char * temp2; + char *device_str[4] = {"/dev/video11", "/dev/video23", "/dev/video35", "/dev/video47"}; + + char mode_temp = 's'; + char *param_temp; + + + if(argc < 3 || (tolower(*(argv[1])) != 'd') ) + { + print_usage(); + return -EINVAL; + } + + sscanf(argv[2], "%d", &device_id ); + i += 2; + + if( device_id <= 0 || device_id > 4 ) + { + print_usage(); + return -EINVAL; + } + + printf("\n********************************* \n"); + + if((fp = open(device_str[device_id-1], O_RDWR)) == -1) + { + printf("Error: cannot open device file %s !\n", device_str[device_id-1]); + return -EINVAL; + } + + printf("Device %s open for IOCTL successfully!\n", device_str[device_id-1]); + + + for( ; i < argc; i++) + { + temp2 = argv[i]; + mode_temp = tolower(temp2[0]); + param_temp = argv[i+1]; + + + switch(mode_temp) + { + case 's': + { + downstream_user_struct arguments; + char * temp = param_temp; + arguments.vid_stdname = (tolower(temp[0]) == 'p') ? "PAL" : "NTSC"; + arguments.command = SET_VIDEO_STD; + + printf("User parameters: vid_stdname = %s, command = %d \n", arguments.vid_stdname, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + case 'f': + { + sscanf(param_temp, "%d", &pixel_format ); + sscanf(argv[i+2], "%d", &decoder_input ); i++; + + if( pixel_format < 411 || pixel_format > 422) + pixel_format = 422; + + if( decoder_input < 0 ) + decoder_input = ALL_DECODERS; + + downstream_user_struct arguments; + arguments.pixel_format = (pixel_format == 411) ? PIXEL_FRMT_411 : PIXEL_FRMT_422; + arguments.decoder_select = decoder_input; + arguments.command = SET_PIXEL_FORMAT; + + printf("User parameters: pixel_format = %d, decoder_input = %d, command = %d \n", arguments.pixel_format, arguments.decoder_select, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + case 'r': + { + sscanf(param_temp, "%d", &width_input ); + sscanf(argv[i+2], "%d", &decoder_input ); i++; + + if( width_input < 320 || width_input > 352 ) + width_input = 720; + + if( decoder_input < 0 ) + decoder_input = ALL_DECODERS; + + downstream_user_struct arguments; + arguments.cif_resolution_enable = (width_input == 320 || width_input == 352) ? 1 : 0; + arguments.cif_width = width_input; + arguments.decoder_select = decoder_input; + arguments.command = ENABLE_CIF_RESOLUTION; + + printf("User parameters: cif_resolution_enable = %d, decoder_input = %d, command = %d \n", arguments.cif_resolution_enable, arguments.decoder_select, arguments.command); + + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + default: + printf("Please verify the options are correct!\n"); + break; + } + + i++; + } + + + printf("********************************* \n\n"); + close(fp); + return 0; +} diff --git a/v4l2-apps/util/cx25821/upstream_app.c b/v4l2-apps/util/cx25821/upstream_app.c new file mode 100644 index 000000000..97f7b84aa --- /dev/null +++ b/v4l2-apps/util/cx25821/upstream_app.c @@ -0,0 +1,221 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#define VID_UPSTREAM_SRAM_CHANNEL_I 9 +#define VID_UPSTREAM_SRAM_CHANNEL_J 10 +#define AUDIO_UPSTREAM_SRAM_CHANNEL_B 11 +#define PIXEL_FRMT_422 4 +#define PIXEL_FRMT_411 5 +#define UPSTREAM_START_VIDEO 700 +#define UPSTREAM_STOP_VIDEO 701 +#define UPSTREAM_START_AUDIO 702 +#define UPSTREAM_STOP_AUDIO 703 +#define UPSTREAM_DUMP_REGISTERS 702 + + +typedef struct { + char *input_filename; + char *vid_stdname; + int pixel_format; + int channel_select; + int command; +} upstream_user_struct; + +void print_video_usage() +{ + printf("\n************************************************************************ \n"); + printf("Video Sample Usage: ./upstream_app d 1 v /root/filename.yuv NTSC 422 1 start \n"); + printf("Argument 0: ./upstream_app \n"); + printf("Argument 1: Device ID (1 and above)\n"); + printf("Argument 2: v for video\n"); + printf("Argument 3: input file name \n"); + printf("Argument 4: Video Standard \n"); + printf("Argument 5: Pixel Format (Y422 or Y411) \n"); + printf("Argument 6: Upstream Channel Number\n"); + printf("Argument 7: start/stop command\n\n"); +} + +void print_audio_usage() +{ + printf("\n************************************************************************ \n"); + printf("Audio Sample Usage: ./upstream_app d 1 a /root/audio.wav start\n"); + printf("Argument 0: ./upstream_app \n"); + printf("Argument 1: Device ID (1 and above)\n"); + printf("Argument 2: a for audio \n"); + printf("Argument 3: input file name \n"); + printf("Argument 4: start/stop command\n\n"); +} + +int main(int argc, char** argv) +{ + int fp; + unsigned int cmd= 0 ; + int i = 1; + int mode = 0; + int pixel_format = 422; + int channel_select = 1; + int device_id = 0, video_id = 11; + char * temp2; + char *video_device_str[4][2] = {{"/dev/video8", "/dev/video9"}, {"/dev/video20", "/dev/video21"}, + {"/dev/video32", "/dev/video33"}, {"/dev/video44", "/dev/video45"} }; + char *audio_device_str[4] = {"/dev/video10", "/dev/video22", "/dev/video34", "/dev/video46"}; + char mode_temp = 'v'; + + if(argc < 2 || (tolower(*(argv[1])) != 'd') ) + { + print_video_usage(); + print_audio_usage(); + return -EINVAL; + } + else + { + sscanf(argv[2], "%d", &device_id ); + i += 2; + + if( device_id <= 0 || device_id > 4 ) + { + print_video_usage(); + print_audio_usage(); + return -EINVAL; + } + + temp2 = argv[i]; + mode_temp = tolower(temp2[0]); + switch(mode_temp) + { + case 'v': + if( argc < 9 ) + { + print_video_usage(); + return -EINVAL; + } + break; + + case 'a': + if( argc < 6 ) + { + print_audio_usage(); + return -EINVAL; + } + break; + } + } + + if( mode_temp == 'v' || mode_temp == 'a' ) + { + FILE* file_ptr = fopen(argv[4], "r"); + + if( !file_ptr ) + { + printf("\nERROR: %s file does NOT exist!!! \n\n", argv[4]); + return -EINVAL; + } + + fclose(file_ptr); + } + else + { + print_video_usage(); + print_audio_usage(); + return -EINVAL; + } + + printf("\n*************************************************************** \n"); + + switch(mode_temp) + { + case 'v': + { + char * temp = argv[5]; + upstream_user_struct arguments; + arguments.input_filename = argv[4]; + arguments.vid_stdname = (tolower(temp[0]) == 'p') ? "PAL" : "NTSC"; + sscanf(argv[6], "%d", &pixel_format); + sscanf(argv[7], "%d", &channel_select); + arguments.pixel_format = (pixel_format == 422) ? PIXEL_FRMT_422 : PIXEL_FRMT_411; + arguments.channel_select = (channel_select==1) ? VID_UPSTREAM_SRAM_CHANNEL_I : VID_UPSTREAM_SRAM_CHANNEL_J; + temp = argv[8]; + arguments.command = (strcasecmp("STOP", temp) == 0) ? UPSTREAM_STOP_VIDEO : UPSTREAM_START_VIDEO; + + + if( channel_select >= 1 && channel_select <= 2 ) + { + if((fp = open(video_device_str[device_id-1][channel_select-1], O_RDWR)) == -1) + { + printf("Error: cannot open device file %s !\n", video_device_str[device_id-1][channel_select-1]); + return -EINVAL; + } + + printf("Device %s open for IOCTL successfully!\n", video_device_str[device_id-1][channel_select-1]); + printf("UPSTREAM parameters: filename = %s, channel_select(I=1) = %d \n", arguments.input_filename, channel_select); + + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + { + printf("Error: ioctl FAILED!\n"); + } + } + } + break; + + case 'a': + { + char * temp = argv[5]; + upstream_user_struct arguments; + arguments.input_filename = argv[4]; + arguments.vid_stdname = "NTSC"; + arguments.pixel_format = PIXEL_FRMT_422; + arguments.channel_select = AUDIO_UPSTREAM_SRAM_CHANNEL_B; + arguments.command = (strcasecmp("STOP", temp) == 0) ? UPSTREAM_STOP_AUDIO : UPSTREAM_START_AUDIO; + + + if((fp = open(audio_device_str[device_id-1], O_RDWR)) == -1) + { + printf("Error: cannot open device file %s !\n", audio_device_str[device_id-1]); + return -EINVAL; + } + + printf("Device %s open for IOCTL successfully!\n", audio_device_str[device_id-1]); + printf("UPSTREAM parameters: filename = %s, audio channel = %d \n", arguments.input_filename, arguments.channel_select); + + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + default: + printf("ERROR: INVALID ioctl command!\n"); + return -EINVAL; + } + + printf("*************************************************************** \n\n"); + close(fp); + return 0; +} -- cgit v1.2.3 From 10e915b9906d789549e8e8d8b8a53f81368f5380 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Sep 2009 11:24:22 -0300 Subject: cx25821: Add missing include From: Mauro Carvalho Chehab /home/v4l/master/v4l/cx25821-audups11.c:99: error: implicit declaration of function 'lock_kernel' /home/v4l/master/v4l/cx25821-audups11.c:112: error: implicit declaration of function 'unlock_kernel' Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/staging/cx25821/cx25821.h | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/drivers/staging/cx25821/cx25821.h b/linux/drivers/staging/cx25821/cx25821.h index 04beeb91f..ee21fa100 100644 --- a/linux/drivers/staging/cx25821/cx25821.h +++ b/linux/drivers/staging/cx25821/cx25821.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From d494aaee63ab3aa0c87d705e5c1b31baafb257bc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Sep 2009 11:25:45 -0300 Subject: cx25821: fix bad whitespacing From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/staging/cx25821/Kconfig | 4 +- linux/drivers/staging/cx25821/cx25821-alsa.c | 2 +- .../staging/cx25821/cx25821-audio-upstream.c | 607 +++++---- linux/drivers/staging/cx25821/cx25821-audups11.c | 212 +-- linux/drivers/staging/cx25821/cx25821-cards.c | 10 +- linux/drivers/staging/cx25821/cx25821-core.c | 1436 ++++++++++---------- linux/drivers/staging/cx25821/cx25821-gpio.c | 50 +- linux/drivers/staging/cx25821/cx25821-i2c.c | 74 +- .../drivers/staging/cx25821/cx25821-medusa-video.c | 710 +++++----- .../drivers/staging/cx25821/cx25821-medusa-video.h | 2 +- linux/drivers/staging/cx25821/cx25821-reg.h | 24 +- .../staging/cx25821/cx25821-video-upstream-ch2.c | 658 ++++----- .../staging/cx25821/cx25821-video-upstream-ch2.h | 20 +- .../staging/cx25821/cx25821-video-upstream.c | 688 +++++----- .../staging/cx25821/cx25821-video-upstream.h | 30 +- linux/drivers/staging/cx25821/cx25821-video.c | 694 +++++----- linux/drivers/staging/cx25821/cx25821-video.h | 10 +- linux/drivers/staging/cx25821/cx25821-video0.c | 220 +-- linux/drivers/staging/cx25821/cx25821-video1.c | 214 +-- linux/drivers/staging/cx25821/cx25821-video2.c | 218 +-- linux/drivers/staging/cx25821/cx25821-video3.c | 216 +-- linux/drivers/staging/cx25821/cx25821-video4.c | 210 +-- linux/drivers/staging/cx25821/cx25821-video5.c | 214 +-- linux/drivers/staging/cx25821/cx25821-video6.c | 216 +-- linux/drivers/staging/cx25821/cx25821-video7.c | 214 +-- linux/drivers/staging/cx25821/cx25821-videoioctl.c | 340 ++--- linux/drivers/staging/cx25821/cx25821-vidups10.c | 212 +-- linux/drivers/staging/cx25821/cx25821-vidups9.c | 218 +-- linux/drivers/staging/cx25821/cx25821.h | 112 +- v4l/Kconfig.staging | 36 + v4l/Makefile.staging | 19 + 31 files changed, 3972 insertions(+), 3918 deletions(-) diff --git a/linux/drivers/staging/cx25821/Kconfig b/linux/drivers/staging/cx25821/Kconfig index 88871156c..df7756a95 100644 --- a/linux/drivers/staging/cx25821/Kconfig +++ b/linux/drivers/staging/cx25821/Kconfig @@ -15,7 +15,7 @@ config VIDEO_CX25821 To compile this driver as a module, choose M here: the module will be called cx25821 - + config VIDEO_CX25821_ALSA tristate "Conexant 25821 DMA audio support" depends on VIDEO_CX25821 && SND && EXPERIMENTAL @@ -30,5 +30,5 @@ config VIDEO_CX25821_ALSA PCI device. To compile this driver as a module, choose M here: the - module will be called cx25821-alsa. + module will be called cx25821-alsa. diff --git a/linux/drivers/staging/cx25821/cx25821-alsa.c b/linux/drivers/staging/cx25821/cx25821-alsa.c index 438f3da4b..ee92e8286 100644 --- a/linux/drivers/staging/cx25821/cx25821-alsa.c +++ b/linux/drivers/staging/cx25821/cx25821-alsa.c @@ -78,7 +78,7 @@ struct cx25821_audio_dev { unsigned long iobase; spinlock_t reg_lock; - atomic_t count; + atomic_t count; unsigned int dma_size; unsigned int period_size; diff --git a/linux/drivers/staging/cx25821/cx25821-audio-upstream.c b/linux/drivers/staging/cx25821/cx25821-audio-upstream.c index fa9057f8b..376c953a8 100644 --- a/linux/drivers/staging/cx25821/cx25821-audio-upstream.c +++ b/linux/drivers/staging/cx25821/cx25821-audio-upstream.c @@ -45,8 +45,8 @@ static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | FLD_AUD_SRC_SYNC | int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, - struct sram_channel *ch, - unsigned int bpl, u32 risc) + struct sram_channel *ch, + unsigned int bpl, u32 risc) { unsigned int i, lines; u32 cdt; @@ -66,7 +66,7 @@ int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, if (lines > 3) { - lines = 3; + lines = 3; } BUG_ON(lines < 2); @@ -87,7 +87,7 @@ int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, cx_write(ch->cmds_start + 8, cdt); cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW); cx_write(ch->cmds_start + 16, ch->ctrl_start); - + //IQ size cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW); @@ -105,40 +105,40 @@ int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, static __le32 *cx25821_risc_field_upstream_audio( struct cx25821_dev *dev, __le32 *rp, - dma_addr_t databuf_phys_addr, - unsigned int bpl, int fifo_enable) + dma_addr_t databuf_phys_addr, + unsigned int bpl, int fifo_enable) { unsigned int line; struct sram_channel *sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select]; int offset = 0; - + /* scan lines */ for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) { *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(databuf_phys_addr + offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + *(rp++) = cpu_to_le32(databuf_phys_addr + offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - // Check if we need to enable the FIFO after the first 3 lines - // For the upstream audio channel, the risc engine will enable the FIFO. - if ( fifo_enable && line == 2 ) + // Check if we need to enable the FIFO after the first 3 lines + // For the upstream audio channel, the risc engine will enable the FIFO. + if ( fifo_enable && line == 2 ) { *(rp++) = RISC_WRITECR; *(rp++) = sram_ch->dma_ctl; *(rp++) = sram_ch->fld_aud_fifo_en; *(rp++) = 0x00000020; - } - - offset += AUDIO_LINE_SIZE; + } + + offset += AUDIO_LINE_SIZE; } - + return rp; } int cx25821_risc_buffer_upstream_audio( struct cx25821_dev *dev, - struct pci_dev *pci, - unsigned int bpl, unsigned int lines) + struct pci_dev *pci, + unsigned int bpl, unsigned int lines) { __le32 *rp; int fifo_enable = 0; @@ -148,7 +148,7 @@ int cx25821_risc_buffer_upstream_audio( struct cx25821_dev *dev, int risc_flag = RISC_CNT_INC; dma_addr_t risc_phys_jump_addr; - + /* Virtual address of Risc buffer program */ rp = dev->_risc_virt_addr; @@ -158,48 +158,48 @@ int cx25821_risc_buffer_upstream_audio( struct cx25821_dev *dev, for( frame = 0; frame < NUM_AUDIO_FRAMES; frame++ ) { - databuf_offset = frame_size * frame; - - if( frame == 0 ) - { - fifo_enable = 1; - risc_flag = RISC_CNT_RESET; - } - else - { - fifo_enable = 0; - risc_flag = RISC_CNT_INC; - } - - //Calculate physical jump address - if( (frame+1) == NUM_AUDIO_FRAMES ) - { - risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE; - } - else - { - risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE*(frame+1); - } - - rp = cx25821_risc_field_upstream_audio(dev, rp, dev->_audiodata_buf_phys_addr+databuf_offset, bpl, fifo_enable); - - - if( USE_RISC_NOOP_AUDIO ) - { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } - } - - - // Loop to (Nth)FrameRISC or to Start of Risc program & generate IRQ - *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - - //Recalculate virtual address based on frame index - rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE/4 + (AUDIO_RISC_DMA_BUF_SIZE*(frame+1)/4 ) ; + databuf_offset = frame_size * frame; + + if( frame == 0 ) + { + fifo_enable = 1; + risc_flag = RISC_CNT_RESET; + } + else + { + fifo_enable = 0; + risc_flag = RISC_CNT_INC; + } + + //Calculate physical jump address + if( (frame+1) == NUM_AUDIO_FRAMES ) + { + risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE; + } + else + { + risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE*(frame+1); + } + + rp = cx25821_risc_field_upstream_audio(dev, rp, dev->_audiodata_buf_phys_addr+databuf_offset, bpl, fifo_enable); + + + if( USE_RISC_NOOP_AUDIO ) + { + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + + // Loop to (Nth)FrameRISC or to Start of Risc program & generate IRQ + *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + + //Recalculate virtual address based on frame index + rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE/4 + (AUDIO_RISC_DMA_BUF_SIZE*(frame+1)/4 ) ; } return 0; @@ -228,10 +228,10 @@ void cx25821_stop_upstream_audio(struct cx25821_dev *dev) if( !dev->_audio_is_running ) { - printk("cx25821: No audio file is currently running so return!\n"); - return; + printk("cx25821: No audio file is currently running so return!\n"); + return; } - + //Disable RISC interrupts cx_write( sram_ch->int_msk, 0 ); @@ -241,8 +241,8 @@ void cx25821_stop_upstream_audio(struct cx25821_dev *dev) //Clear data buffer memory if( dev->_audiodata_buf_virt_addr ) - memset( dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size ); - + memset( dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size ); + dev->_audio_is_running = 0; dev->_is_first_audio_frame = 0; dev->_audioframe_count = 0; @@ -250,12 +250,12 @@ void cx25821_stop_upstream_audio(struct cx25821_dev *dev) if( dev->_irq_audio_queues ) { - kfree(dev->_irq_audio_queues); - dev->_irq_audio_queues = NULL; + kfree(dev->_irq_audio_queues); + dev->_irq_audio_queues = NULL; } if( dev->_audiofilename != NULL ) - kfree(dev->_audiofilename); + kfree(dev->_audiofilename); } @@ -263,7 +263,7 @@ void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev) { if( dev->_audio_is_running ) { - cx25821_stop_upstream_audio(dev); + cx25821_stop_upstream_audio(dev); } cx25821_free_memory_audio(dev); @@ -286,69 +286,69 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, struct sram_channel *sram_ch if( dev->_audiofile_status == END_OF_FILE ) - return 0; - + return 0; + myfile = filp_open( dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0 ); if (IS_ERR(myfile)) { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno); - return PTR_ERR(myfile); + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno); + return PTR_ERR(myfile); } else { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered!\n", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered! \n", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( i = 0; i < dev->_audio_lines_count; i++ ) - { - pos = file_offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL ) - { - memcpy( (void*)(dev->_audiodata_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval); - } - - file_offset += vfs_read_retval; - frame_offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - dev->_audioframe_count++; - - dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - - set_fs(old_fs); - filp_close(myfile, NULL); + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered!\n", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered! \n", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( i = 0; i < dev->_audio_lines_count; i++ ) + { + pos = file_offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL ) + { + memcpy( (void*)(dev->_audiodata_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval); + } + + file_offset += vfs_read_retval; + frame_offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + dev->_audioframe_count++; + + dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + + set_fs(old_fs); + filp_close(myfile, NULL); } return 0; @@ -360,8 +360,8 @@ static void cx25821_audioups_handler(struct work_struct *work) if( !dev ) { - printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); - return; + printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); + return; } cx25821_get_audio_data( dev, &dev->sram_channels[dev->_audio_upstream_channel_select] ); @@ -377,91 +377,91 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, struct sram_channel *sram_ch loff_t pos; loff_t offset = (unsigned long)0; mm_segment_t old_fs; - + myfile = filp_open( dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0 ); if (IS_ERR(myfile)) { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno); - return PTR_ERR(myfile); + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno); + return PTR_ERR(myfile); } else { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered! \n", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered! \n", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( j = 0; j < NUM_AUDIO_FRAMES; j++ ) - { - for( i = 0; i < dev->_audio_lines_count; i++ ) - { - pos = offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL ) - { - memcpy( (void*)(dev->_audiodata_buf_virt_addr+offset/4), mybuf, vfs_read_retval); - } - - offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - { - dev->_audioframe_count++; - } - - if( vfs_read_retval < line_size ) - { - break; - } - } - - dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - set_fs(old_fs); - myfile->f_pos = 0; - filp_close(myfile, NULL); + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered! \n", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered! \n", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( j = 0; j < NUM_AUDIO_FRAMES; j++ ) + { + for( i = 0; i < dev->_audio_lines_count; i++ ) + { + pos = offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL ) + { + memcpy( (void*)(dev->_audiodata_buf_virt_addr+offset/4), mybuf, vfs_read_retval); + } + + offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + { + dev->_audioframe_count++; + } + + if( vfs_read_retval < line_size ) + { + break; + } + } + + dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + myfile->f_pos = 0; + filp_close(myfile, NULL); } return 0; } static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, - struct sram_channel *sram_ch, - int bpl) + struct sram_channel *sram_ch, + int bpl) { int ret = 0; dma_addr_t dma_addr; dma_addr_t data_dma_addr; - + cx25821_free_memory_audio(dev); @@ -474,7 +474,7 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, if (!dev->_risc_virt_addr) { - printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n"); + printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n"); return -ENOMEM; } @@ -489,7 +489,7 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, if (!dev->_audiodata_buf_virt_addr) { - printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning. \n"); + printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning. \n"); return -ENOMEM; } @@ -499,8 +499,8 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, ret = cx25821_openfile_audio(dev, sram_ch); if( ret < 0 ) - return ret; - + return ret; + //Creating RISC programs ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, dev->_audio_lines_count ); @@ -528,86 +528,86 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, u32 status if (status & FLD_AUD_SRC_RISCI1) { //Get interrupt_index of the program that interrupted - u32 prog_cnt = cx_read( channel->gpcnt ); + u32 prog_cnt = cx_read( channel->gpcnt ); - //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers - cx_write(channel->int_msk, 0); - cx_write(channel->int_stat, cx_read(channel->int_stat) ); + //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers + cx_write(channel->int_msk, 0); + cx_write(channel->int_stat, cx_read(channel->int_stat) ); spin_lock(&dev->slock); - - - while(prog_cnt != dev->_last_index_irq) - { - //Update _last_index_irq - if(dev->_last_index_irq < (NUMBER_OF_PROGRAMS-1)) - { - dev->_last_index_irq++; - } - else - { - dev->_last_index_irq = 0; - } - - dev->_audioframe_index = dev->_last_index_irq; - - queue_work(dev->_irq_audio_queues, &dev->_audio_work_entry); - } - - - if ( dev->_is_first_audio_frame ) - { - dev->_is_first_audio_frame = 0; - - if( dev->_risc_virt_start_addr != NULL ) - { - risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE; - - rp = cx25821_risc_field_upstream_audio(dev, dev->_risc_virt_start_addr+1, dev->_audiodata_buf_phys_addr, AUDIO_LINE_SIZE, FIFO_DISABLE); - - if( USE_RISC_NOOP_AUDIO ) - { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } - } - - // Jump to 2nd Audio Frame - *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_RESET); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - } - } - + + + while(prog_cnt != dev->_last_index_irq) + { + //Update _last_index_irq + if(dev->_last_index_irq < (NUMBER_OF_PROGRAMS-1)) + { + dev->_last_index_irq++; + } + else + { + dev->_last_index_irq = 0; + } + + dev->_audioframe_index = dev->_last_index_irq; + + queue_work(dev->_irq_audio_queues, &dev->_audio_work_entry); + } + + + if ( dev->_is_first_audio_frame ) + { + dev->_is_first_audio_frame = 0; + + if( dev->_risc_virt_start_addr != NULL ) + { + risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE; + + rp = cx25821_risc_field_upstream_audio(dev, dev->_risc_virt_start_addr+1, dev->_audiodata_buf_phys_addr, AUDIO_LINE_SIZE, FIFO_DISABLE); + + if( USE_RISC_NOOP_AUDIO ) + { + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + // Jump to 2nd Audio Frame + *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_RESET); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + } + spin_unlock(&dev->slock); } else { - if(status & FLD_AUD_SRC_OF) - printk("%s: Audio Received Overflow Error Interrupt!\n", __func__); + if(status & FLD_AUD_SRC_OF) + printk("%s: Audio Received Overflow Error Interrupt!\n", __func__); - if(status & FLD_AUD_SRC_SYNC) - printk("%s: Audio Received Sync Error Interrupt!\n", __func__); + if(status & FLD_AUD_SRC_SYNC) + printk("%s: Audio Received Sync Error Interrupt!\n", __func__); - if(status & FLD_AUD_SRC_OPC_ERR) - printk("%s: Audio Received OpCode Error Interrupt!\n", __func__); - - // Read and write back the interrupt status register to clear our bits - cx_write(channel->int_stat, cx_read(channel->int_stat) ); + if(status & FLD_AUD_SRC_OPC_ERR) + printk("%s: Audio Received OpCode Error Interrupt!\n", __func__); + + // Read and write back the interrupt status register to clear our bits + cx_write(channel->int_stat, cx_read(channel->int_stat) ); } - + if( dev->_audiofile_status == END_OF_FILE ) { - printk("cx25821: EOF Channel Audio Framecount = %d\n", dev->_audioframe_count ); - return -1; + printk("cx25821: EOF Channel Audio Framecount = %d\n", dev->_audioframe_count ); + return -1; } //ElSE, set the interrupt mask register, re-enable irq. int_msk_tmp = cx_read( channel->int_msk ); cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); - + return 0; } @@ -620,8 +620,8 @@ static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) if( !dev ) - return -1; - + return -1; + sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select]; @@ -631,17 +631,17 @@ static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) // Only deal with our interrupt if(audio_status) { - handled = cx25821_audio_upstream_irq(dev, dev->_audio_upstream_channel_select, audio_status); + handled = cx25821_audio_upstream_irq(dev, dev->_audio_upstream_channel_select, audio_status); } if( handled < 0 ) { - cx25821_stop_upstream_audio(dev); + cx25821_stop_upstream_audio(dev); } else { - handled += handled; + handled += handled; } return IRQ_RETVAL(handled); @@ -655,24 +655,24 @@ static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, struct sram_channe do { - //Wait 10 microsecond before checking to see if the FIFO is turned ON. - udelay(10); - - tmp = cx_read( sram_ch->dma_ctl ); - - if(count++ > 1000) //10 millisecond timeout - { - printk("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", __func__); - return; - } - + //Wait 10 microsecond before checking to see if the FIFO is turned ON. + udelay(10); + + tmp = cx_read( sram_ch->dma_ctl ); + + if(count++ > 1000) //10 millisecond timeout + { + printk("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", __func__); + return; + } + } while( !(tmp & sram_ch->fld_aud_fifo_en) ); - + } int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, - struct sram_channel *sram_ch) + struct sram_channel *sram_ch) { u32 tmp = 0; int err = 0; @@ -744,10 +744,10 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) if( dev->_audio_is_running ) { - printk("Audio Channel is still running so return!\n"); - return 0; + printk("Audio Channel is still running so return!\n"); + return 0; } - + dev->_audio_upstream_channel_select = channel_select; sram_ch = &dev->sram_channels[channel_select]; @@ -757,10 +757,10 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) if(!dev->_irq_audio_queues) { - printk("cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n"); + printk("cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n"); return -ENOMEM; } - + dev->_last_index_irq = 0; dev->_audio_is_running = 0; @@ -769,32 +769,32 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER; _line_size = AUDIO_LINE_SIZE; - + if( dev->input_audiofilename ) { - str_length = strlen(dev->input_audiofilename); - dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_audiofilename ) - goto error; - - memcpy(dev->_audiofilename, dev->input_audiofilename, str_length + 1); - - //Default if filename is empty string - if( strcmp(dev->input_audiofilename,"") == 0) - { - dev->_audiofilename = "/root/audioGOOD.wav"; - } + str_length = strlen(dev->input_audiofilename); + dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_audiofilename ) + goto error; + + memcpy(dev->_audiofilename, dev->input_audiofilename, str_length + 1); + + //Default if filename is empty string + if( strcmp(dev->input_audiofilename,"") == 0) + { + dev->_audiofilename = "/root/audioGOOD.wav"; + } } else { - str_length = strlen(_defaultAudioName); - dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_audiofilename ) - goto error; - - memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1); + str_length = strlen(_defaultAudioName); + dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_audiofilename ) + goto error; + + memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1); } @@ -822,4 +822,3 @@ error: return err; } - \ No newline at end of file diff --git a/linux/drivers/staging/cx25821/cx25821-audups11.c b/linux/drivers/staging/cx25821/cx25821-audups11.c index a8e4dce88..4a60be2f6 100644 --- a/linux/drivers/staging/cx25821/cx25821-audups11.c +++ b/linux/drivers/staging/cx25821/cx25821-audups11.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -40,37 +40,37 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH11]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH11]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -99,18 +99,18 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->video_dev[SRAM_CH11] && h->video_dev[SRAM_CH11]->minor == minor) - { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->video_dev[SRAM_CH11] && h->video_dev[SRAM_CH11]->minor == minor) + { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -118,8 +118,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; @@ -128,21 +128,21 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; - + fh->height = 480; + dev->channel_opened = 10; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -156,15 +156,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO11)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO11)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -174,21 +174,21 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO11)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; + return POLLIN|POLLRDNORM; return 0; } @@ -199,17 +199,17 @@ static int video_release(struct file *file) struct cx25821_dev *dev = fh->dev; //stop the risc engine and fifo - //cx_write(channel11->dma_ctl, 0); + //cx_write(channel11->dma_ctl, 0); /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO11)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO11); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO11); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -230,17 +230,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO11)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -253,14 +253,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO11); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } @@ -272,18 +272,18 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; int err; - if (fh) + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->width = f->fmt.pix.width; fh->height = f->fmt.pix.height; @@ -293,30 +293,30 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma return 0; } -static long video_ioctl_upstream11(struct file *file, unsigned int cmd, unsigned long arg) -{ +static long video_ioctl_upstream11(struct file *file, unsigned int cmd, unsigned long arg) +{ struct cx25821_fh *fh = file->private_data; struct cx25821_dev *dev = fh->dev; int command = 0; struct upstream_user_struct *data_from_user; - + data_from_user = (struct upstream_user_struct *)arg; - + if( !data_from_user ) { - printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); - return 0; + printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); + return 0; } - + command = data_from_user->command; - + if( command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO ) { - return 0; + return 0; } - - + + dev->input_filename = data_from_user->input_filename; dev->input_audiofilename = data_from_user->input_filename; dev->vid_stdname = data_from_user->vid_stdname; @@ -324,18 +324,18 @@ static long video_ioctl_upstream11(struct file *file, unsigned int cmd, unsigned dev->channel_select = data_from_user->channel_select; dev->command = data_from_user->command; - + switch(command) - { - case UPSTREAM_START_AUDIO: - cx25821_start_upstream_audio(dev, data_from_user); - break; - - case UPSTREAM_STOP_AUDIO: - cx25821_stop_upstream_audio(dev); - break; + { + case UPSTREAM_START_AUDIO: + cx25821_start_upstream_audio(dev, data_from_user); + break; + + case UPSTREAM_STOP_AUDIO: + cx25821_stop_upstream_audio(dev); + break; } - + return 0; } @@ -366,11 +366,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct cx25821_dev *dev = fh->dev; int err; - if (fh) + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } return 0; } @@ -382,7 +382,7 @@ static const struct v4l2_file_operations video_fops = { .read = video_read, .poll = video_poll, .mmap = video_mmap, - .ioctl = video_ioctl_upstream11, + .ioctl = video_ioctl_upstream11, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { diff --git a/linux/drivers/staging/cx25821/cx25821-cards.c b/linux/drivers/staging/cx25821/cx25821-cards.c index accd7d53a..9eeed2d95 100644 --- a/linux/drivers/staging/cx25821/cx25821-cards.c +++ b/linux/drivers/staging/cx25821/cx25821-cards.c @@ -31,12 +31,12 @@ #include "cx25821.h" #include "tuner-xc2028.h" -// board config info +// board config info struct cx25821_board cx25821_boards[] = { [UNKNOWN_BOARD] = { .name = "UNKNOWN/GENERIC", - // Ensure safe default for unknown boards + // Ensure safe default for unknown boards .clk_freq = 0, }, @@ -44,8 +44,8 @@ struct cx25821_board cx25821_boards[] = { .name = "CX25821", .portb = CX25821_RAW, .portc = CX25821_264, - .input[0].type = CX25821_VMUX_COMPOSITE, - }, + .input[0].type = CX25821_VMUX_COMPOSITE, + }, }; @@ -64,7 +64,7 @@ void cx25821_card_setup(struct cx25821_dev *dev) { static u8 eeprom[256]; - if (dev->i2c_bus[0].i2c_rc == 0) + if (dev->i2c_bus[0].i2c_rc == 0) { dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); diff --git a/linux/drivers/staging/cx25821/cx25821-core.c b/linux/drivers/staging/cx25821/cx25821-core.c index 084bbb42c..175ac3fa0 100644 --- a/linux/drivers/staging/cx25821/cx25821-core.c +++ b/linux/drivers/staging/cx25821/cx25821-core.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -49,271 +49,271 @@ LIST_HEAD(cx25821_devlist); struct sram_channel cx25821_sram_channels[] = { [SRAM_CH00] = { - .i = SRAM_CH00, - .name = "VID A", - .cmds_start = VID_A_DOWN_CMDS, - .ctrl_start = VID_A_IQ, - .cdt = VID_A_CDT, - .fifo_start = VID_A_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA1_PTR1, - .ptr2_reg = DMA1_PTR2, - .cnt1_reg = DMA1_CNT1, - .cnt2_reg = DMA1_CNT2, - .int_msk = VID_A_INT_MSK, - .int_stat = VID_A_INT_STAT, - .int_mstat = VID_A_INT_MSTAT, - .dma_ctl = VID_DST_A_DMA_CTL, - .gpcnt_ctl = VID_DST_A_GPCNT_CTL, - .gpcnt = VID_DST_A_GPCNT, - .vip_ctl = VID_DST_A_VIP_CTL, - .pix_frmt = VID_DST_A_PIX_FRMT, + .i = SRAM_CH00, + .name = "VID A", + .cmds_start = VID_A_DOWN_CMDS, + .ctrl_start = VID_A_IQ, + .cdt = VID_A_CDT, + .fifo_start = VID_A_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA1_PTR1, + .ptr2_reg = DMA1_PTR2, + .cnt1_reg = DMA1_CNT1, + .cnt2_reg = DMA1_CNT2, + .int_msk = VID_A_INT_MSK, + .int_stat = VID_A_INT_STAT, + .int_mstat = VID_A_INT_MSTAT, + .dma_ctl = VID_DST_A_DMA_CTL, + .gpcnt_ctl = VID_DST_A_GPCNT_CTL, + .gpcnt = VID_DST_A_GPCNT, + .vip_ctl = VID_DST_A_VIP_CTL, + .pix_frmt = VID_DST_A_PIX_FRMT, }, [SRAM_CH01] = { - .i = SRAM_CH01, - .name = "VID B", - .cmds_start = VID_B_DOWN_CMDS, - .ctrl_start = VID_B_IQ, - .cdt = VID_B_CDT, - .fifo_start = VID_B_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA2_PTR1, - .ptr2_reg = DMA2_PTR2, - .cnt1_reg = DMA2_CNT1, - .cnt2_reg = DMA2_CNT2, - .int_msk = VID_B_INT_MSK, - .int_stat = VID_B_INT_STAT, - .int_mstat = VID_B_INT_MSTAT, - .dma_ctl = VID_DST_B_DMA_CTL, - .gpcnt_ctl = VID_DST_B_GPCNT_CTL, - .gpcnt = VID_DST_B_GPCNT, - .vip_ctl = VID_DST_B_VIP_CTL, - .pix_frmt = VID_DST_B_PIX_FRMT, + .i = SRAM_CH01, + .name = "VID B", + .cmds_start = VID_B_DOWN_CMDS, + .ctrl_start = VID_B_IQ, + .cdt = VID_B_CDT, + .fifo_start = VID_B_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA2_PTR1, + .ptr2_reg = DMA2_PTR2, + .cnt1_reg = DMA2_CNT1, + .cnt2_reg = DMA2_CNT2, + .int_msk = VID_B_INT_MSK, + .int_stat = VID_B_INT_STAT, + .int_mstat = VID_B_INT_MSTAT, + .dma_ctl = VID_DST_B_DMA_CTL, + .gpcnt_ctl = VID_DST_B_GPCNT_CTL, + .gpcnt = VID_DST_B_GPCNT, + .vip_ctl = VID_DST_B_VIP_CTL, + .pix_frmt = VID_DST_B_PIX_FRMT, }, - + [SRAM_CH02] = { - .i = SRAM_CH02, - .name = "VID C", - .cmds_start = VID_C_DOWN_CMDS, - .ctrl_start = VID_C_IQ, - .cdt = VID_C_CDT, - .fifo_start = VID_C_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA3_PTR1, - .ptr2_reg = DMA3_PTR2, - .cnt1_reg = DMA3_CNT1, - .cnt2_reg = DMA3_CNT2, - .int_msk = VID_C_INT_MSK, - .int_stat = VID_C_INT_STAT, - .int_mstat = VID_C_INT_MSTAT, - .dma_ctl = VID_DST_C_DMA_CTL, - .gpcnt_ctl = VID_DST_C_GPCNT_CTL, - .gpcnt = VID_DST_C_GPCNT, - .vip_ctl = VID_DST_C_VIP_CTL, - .pix_frmt = VID_DST_C_PIX_FRMT, + .i = SRAM_CH02, + .name = "VID C", + .cmds_start = VID_C_DOWN_CMDS, + .ctrl_start = VID_C_IQ, + .cdt = VID_C_CDT, + .fifo_start = VID_C_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA3_PTR1, + .ptr2_reg = DMA3_PTR2, + .cnt1_reg = DMA3_CNT1, + .cnt2_reg = DMA3_CNT2, + .int_msk = VID_C_INT_MSK, + .int_stat = VID_C_INT_STAT, + .int_mstat = VID_C_INT_MSTAT, + .dma_ctl = VID_DST_C_DMA_CTL, + .gpcnt_ctl = VID_DST_C_GPCNT_CTL, + .gpcnt = VID_DST_C_GPCNT, + .vip_ctl = VID_DST_C_VIP_CTL, + .pix_frmt = VID_DST_C_PIX_FRMT, }, - + [SRAM_CH03] = { - .i = SRAM_CH03, - .name = "VID D", - .cmds_start = VID_D_DOWN_CMDS, - .ctrl_start = VID_D_IQ, - .cdt = VID_D_CDT, - .fifo_start = VID_D_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA4_PTR1, - .ptr2_reg = DMA4_PTR2, - .cnt1_reg = DMA4_CNT1, - .cnt2_reg = DMA4_CNT2, - .int_msk = VID_D_INT_MSK, - .int_stat = VID_D_INT_STAT, - .int_mstat = VID_D_INT_MSTAT, - .dma_ctl = VID_DST_D_DMA_CTL, - .gpcnt_ctl = VID_DST_D_GPCNT_CTL, - .gpcnt = VID_DST_D_GPCNT, - .vip_ctl = VID_DST_D_VIP_CTL, - .pix_frmt = VID_DST_D_PIX_FRMT, + .i = SRAM_CH03, + .name = "VID D", + .cmds_start = VID_D_DOWN_CMDS, + .ctrl_start = VID_D_IQ, + .cdt = VID_D_CDT, + .fifo_start = VID_D_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA4_PTR1, + .ptr2_reg = DMA4_PTR2, + .cnt1_reg = DMA4_CNT1, + .cnt2_reg = DMA4_CNT2, + .int_msk = VID_D_INT_MSK, + .int_stat = VID_D_INT_STAT, + .int_mstat = VID_D_INT_MSTAT, + .dma_ctl = VID_DST_D_DMA_CTL, + .gpcnt_ctl = VID_DST_D_GPCNT_CTL, + .gpcnt = VID_DST_D_GPCNT, + .vip_ctl = VID_DST_D_VIP_CTL, + .pix_frmt = VID_DST_D_PIX_FRMT, }, - + [SRAM_CH04] = { - .i = SRAM_CH04, - .name = "VID E", - .cmds_start = VID_E_DOWN_CMDS, - .ctrl_start = VID_E_IQ, - .cdt = VID_E_CDT, - .fifo_start = VID_E_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA5_PTR1, - .ptr2_reg = DMA5_PTR2, - .cnt1_reg = DMA5_CNT1, - .cnt2_reg = DMA5_CNT2, - .int_msk = VID_E_INT_MSK, - .int_stat = VID_E_INT_STAT, - .int_mstat = VID_E_INT_MSTAT, - .dma_ctl = VID_DST_E_DMA_CTL, - .gpcnt_ctl = VID_DST_E_GPCNT_CTL, - .gpcnt = VID_DST_E_GPCNT, - .vip_ctl = VID_DST_E_VIP_CTL, - .pix_frmt = VID_DST_E_PIX_FRMT, + .i = SRAM_CH04, + .name = "VID E", + .cmds_start = VID_E_DOWN_CMDS, + .ctrl_start = VID_E_IQ, + .cdt = VID_E_CDT, + .fifo_start = VID_E_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA5_PTR1, + .ptr2_reg = DMA5_PTR2, + .cnt1_reg = DMA5_CNT1, + .cnt2_reg = DMA5_CNT2, + .int_msk = VID_E_INT_MSK, + .int_stat = VID_E_INT_STAT, + .int_mstat = VID_E_INT_MSTAT, + .dma_ctl = VID_DST_E_DMA_CTL, + .gpcnt_ctl = VID_DST_E_GPCNT_CTL, + .gpcnt = VID_DST_E_GPCNT, + .vip_ctl = VID_DST_E_VIP_CTL, + .pix_frmt = VID_DST_E_PIX_FRMT, }, - + [SRAM_CH05] = { - .i = SRAM_CH05, - .name = "VID F", - .cmds_start = VID_F_DOWN_CMDS, - .ctrl_start = VID_F_IQ, - .cdt = VID_F_CDT, - .fifo_start = VID_F_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA6_PTR1, - .ptr2_reg = DMA6_PTR2, - .cnt1_reg = DMA6_CNT1, - .cnt2_reg = DMA6_CNT2, - .int_msk = VID_F_INT_MSK, - .int_stat = VID_F_INT_STAT, - .int_mstat = VID_F_INT_MSTAT, - .dma_ctl = VID_DST_F_DMA_CTL, - .gpcnt_ctl = VID_DST_F_GPCNT_CTL, - .gpcnt = VID_DST_F_GPCNT, - .vip_ctl = VID_DST_F_VIP_CTL, - .pix_frmt = VID_DST_F_PIX_FRMT, + .i = SRAM_CH05, + .name = "VID F", + .cmds_start = VID_F_DOWN_CMDS, + .ctrl_start = VID_F_IQ, + .cdt = VID_F_CDT, + .fifo_start = VID_F_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA6_PTR1, + .ptr2_reg = DMA6_PTR2, + .cnt1_reg = DMA6_CNT1, + .cnt2_reg = DMA6_CNT2, + .int_msk = VID_F_INT_MSK, + .int_stat = VID_F_INT_STAT, + .int_mstat = VID_F_INT_MSTAT, + .dma_ctl = VID_DST_F_DMA_CTL, + .gpcnt_ctl = VID_DST_F_GPCNT_CTL, + .gpcnt = VID_DST_F_GPCNT, + .vip_ctl = VID_DST_F_VIP_CTL, + .pix_frmt = VID_DST_F_PIX_FRMT, }, - + [SRAM_CH06] = { - .i = SRAM_CH06, - .name = "VID G", - .cmds_start = VID_G_DOWN_CMDS, - .ctrl_start = VID_G_IQ, - .cdt = VID_G_CDT, - .fifo_start = VID_G_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA7_PTR1, - .ptr2_reg = DMA7_PTR2, - .cnt1_reg = DMA7_CNT1, - .cnt2_reg = DMA7_CNT2, - .int_msk = VID_G_INT_MSK, - .int_stat = VID_G_INT_STAT, - .int_mstat = VID_G_INT_MSTAT, - .dma_ctl = VID_DST_G_DMA_CTL, - .gpcnt_ctl = VID_DST_G_GPCNT_CTL, - .gpcnt = VID_DST_G_GPCNT, - .vip_ctl = VID_DST_G_VIP_CTL, - .pix_frmt = VID_DST_G_PIX_FRMT, + .i = SRAM_CH06, + .name = "VID G", + .cmds_start = VID_G_DOWN_CMDS, + .ctrl_start = VID_G_IQ, + .cdt = VID_G_CDT, + .fifo_start = VID_G_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA7_PTR1, + .ptr2_reg = DMA7_PTR2, + .cnt1_reg = DMA7_CNT1, + .cnt2_reg = DMA7_CNT2, + .int_msk = VID_G_INT_MSK, + .int_stat = VID_G_INT_STAT, + .int_mstat = VID_G_INT_MSTAT, + .dma_ctl = VID_DST_G_DMA_CTL, + .gpcnt_ctl = VID_DST_G_GPCNT_CTL, + .gpcnt = VID_DST_G_GPCNT, + .vip_ctl = VID_DST_G_VIP_CTL, + .pix_frmt = VID_DST_G_PIX_FRMT, }, - + [SRAM_CH07] = { - .i = SRAM_CH07, - .name = "VID H", - .cmds_start = VID_H_DOWN_CMDS, - .ctrl_start = VID_H_IQ, - .cdt = VID_H_CDT, - .fifo_start = VID_H_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA8_PTR1, - .ptr2_reg = DMA8_PTR2, - .cnt1_reg = DMA8_CNT1, - .cnt2_reg = DMA8_CNT2, - .int_msk = VID_H_INT_MSK, - .int_stat = VID_H_INT_STAT, - .int_mstat = VID_H_INT_MSTAT, - .dma_ctl = VID_DST_H_DMA_CTL, - .gpcnt_ctl = VID_DST_H_GPCNT_CTL, - .gpcnt = VID_DST_H_GPCNT, - .vip_ctl = VID_DST_H_VIP_CTL, - .pix_frmt = VID_DST_H_PIX_FRMT, + .i = SRAM_CH07, + .name = "VID H", + .cmds_start = VID_H_DOWN_CMDS, + .ctrl_start = VID_H_IQ, + .cdt = VID_H_CDT, + .fifo_start = VID_H_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA8_PTR1, + .ptr2_reg = DMA8_PTR2, + .cnt1_reg = DMA8_CNT1, + .cnt2_reg = DMA8_CNT2, + .int_msk = VID_H_INT_MSK, + .int_stat = VID_H_INT_STAT, + .int_mstat = VID_H_INT_MSTAT, + .dma_ctl = VID_DST_H_DMA_CTL, + .gpcnt_ctl = VID_DST_H_GPCNT_CTL, + .gpcnt = VID_DST_H_GPCNT, + .vip_ctl = VID_DST_H_VIP_CTL, + .pix_frmt = VID_DST_H_PIX_FRMT, }, - + [SRAM_CH08] = { - .name = "audio from", - .cmds_start = AUD_A_DOWN_CMDS, - .ctrl_start = AUD_A_IQ, - .cdt = AUD_A_CDT, - .fifo_start = AUD_A_DOWN_CLUSTER_1, - .fifo_size = AUDIO_CLUSTER_SIZE * 3, - .ptr1_reg = DMA17_PTR1, - .ptr2_reg = DMA17_PTR2, - .cnt1_reg = DMA17_CNT1, - .cnt2_reg = DMA17_CNT2, - }, - + .name = "audio from", + .cmds_start = AUD_A_DOWN_CMDS, + .ctrl_start = AUD_A_IQ, + .cdt = AUD_A_CDT, + .fifo_start = AUD_A_DOWN_CLUSTER_1, + .fifo_size = AUDIO_CLUSTER_SIZE * 3, + .ptr1_reg = DMA17_PTR1, + .ptr2_reg = DMA17_PTR2, + .cnt1_reg = DMA17_CNT1, + .cnt2_reg = DMA17_CNT2, + }, + [SRAM_CH09] = { - .i = SRAM_CH09, - .name = "VID Upstream I", - .cmds_start = VID_I_UP_CMDS, - .ctrl_start = VID_I_IQ, - .cdt = VID_I_CDT, - .fifo_start = VID_I_UP_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA15_PTR1, - .ptr2_reg = DMA15_PTR2, - .cnt1_reg = DMA15_CNT1, - .cnt2_reg = DMA15_CNT2, - .int_msk = VID_I_INT_MSK, - .int_stat = VID_I_INT_STAT, - .int_mstat = VID_I_INT_MSTAT, - .dma_ctl = VID_SRC_I_DMA_CTL, - .gpcnt_ctl = VID_SRC_I_GPCNT_CTL, - .gpcnt = VID_SRC_I_GPCNT, - - .vid_fmt_ctl = VID_SRC_I_FMT_CTL, - .vid_active_ctl1= VID_SRC_I_ACTIVE_CTL1, - .vid_active_ctl2= VID_SRC_I_ACTIVE_CTL2, - .vid_cdt_size = VID_SRC_I_CDT_SZ, - .irq_bit = 8, - }, + .i = SRAM_CH09, + .name = "VID Upstream I", + .cmds_start = VID_I_UP_CMDS, + .ctrl_start = VID_I_IQ, + .cdt = VID_I_CDT, + .fifo_start = VID_I_UP_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA15_PTR1, + .ptr2_reg = DMA15_PTR2, + .cnt1_reg = DMA15_CNT1, + .cnt2_reg = DMA15_CNT2, + .int_msk = VID_I_INT_MSK, + .int_stat = VID_I_INT_STAT, + .int_mstat = VID_I_INT_MSTAT, + .dma_ctl = VID_SRC_I_DMA_CTL, + .gpcnt_ctl = VID_SRC_I_GPCNT_CTL, + .gpcnt = VID_SRC_I_GPCNT, + + .vid_fmt_ctl = VID_SRC_I_FMT_CTL, + .vid_active_ctl1= VID_SRC_I_ACTIVE_CTL1, + .vid_active_ctl2= VID_SRC_I_ACTIVE_CTL2, + .vid_cdt_size = VID_SRC_I_CDT_SZ, + .irq_bit = 8, + }, [SRAM_CH10] = { - .i = SRAM_CH10, - .name = "VID Upstream J", - .cmds_start = VID_J_UP_CMDS, - .ctrl_start = VID_J_IQ, - .cdt = VID_J_CDT, - .fifo_start = VID_J_UP_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA16_PTR1, - .ptr2_reg = DMA16_PTR2, - .cnt1_reg = DMA16_CNT1, - .cnt2_reg = DMA16_CNT2, - .int_msk = VID_J_INT_MSK, - .int_stat = VID_J_INT_STAT, - .int_mstat = VID_J_INT_MSTAT, - .dma_ctl = VID_SRC_J_DMA_CTL, - .gpcnt_ctl = VID_SRC_J_GPCNT_CTL, - .gpcnt = VID_SRC_J_GPCNT, - - .vid_fmt_ctl = VID_SRC_J_FMT_CTL, - .vid_active_ctl1= VID_SRC_J_ACTIVE_CTL1, - .vid_active_ctl2= VID_SRC_J_ACTIVE_CTL2, - .vid_cdt_size = VID_SRC_J_CDT_SZ, - .irq_bit = 9, + .i = SRAM_CH10, + .name = "VID Upstream J", + .cmds_start = VID_J_UP_CMDS, + .ctrl_start = VID_J_IQ, + .cdt = VID_J_CDT, + .fifo_start = VID_J_UP_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE<<2), + .ptr1_reg = DMA16_PTR1, + .ptr2_reg = DMA16_PTR2, + .cnt1_reg = DMA16_CNT1, + .cnt2_reg = DMA16_CNT2, + .int_msk = VID_J_INT_MSK, + .int_stat = VID_J_INT_STAT, + .int_mstat = VID_J_INT_MSTAT, + .dma_ctl = VID_SRC_J_DMA_CTL, + .gpcnt_ctl = VID_SRC_J_GPCNT_CTL, + .gpcnt = VID_SRC_J_GPCNT, + + .vid_fmt_ctl = VID_SRC_J_FMT_CTL, + .vid_active_ctl1= VID_SRC_J_ACTIVE_CTL1, + .vid_active_ctl2= VID_SRC_J_ACTIVE_CTL2, + .vid_cdt_size = VID_SRC_J_CDT_SZ, + .irq_bit = 9, }, [SRAM_CH11] = { - .i = SRAM_CH11, - .name = "Audio Upstream Channel B", - .cmds_start = AUD_B_UP_CMDS, - .ctrl_start = AUD_B_IQ, - .cdt = AUD_B_CDT, - .fifo_start = AUD_B_UP_CLUSTER_1, - .fifo_size = (AUDIO_CLUSTER_SIZE*3), - .ptr1_reg = DMA22_PTR1, - .ptr2_reg = DMA22_PTR2, - .cnt1_reg = DMA22_CNT1, - .cnt2_reg = DMA22_CNT2, - .int_msk = AUD_B_INT_MSK, - .int_stat = AUD_B_INT_STAT, - .int_mstat = AUD_B_INT_MSTAT, - .dma_ctl = AUD_INT_DMA_CTL, - .gpcnt_ctl = AUD_B_GPCNT_CTL, - .gpcnt = AUD_B_GPCNT, - .aud_length = AUD_B_LNGTH, - .aud_cfg = AUD_B_CFG, - .fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN, - .fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN, - .irq_bit = 11, - }, + .i = SRAM_CH11, + .name = "Audio Upstream Channel B", + .cmds_start = AUD_B_UP_CMDS, + .ctrl_start = AUD_B_IQ, + .cdt = AUD_B_CDT, + .fifo_start = AUD_B_UP_CLUSTER_1, + .fifo_size = (AUDIO_CLUSTER_SIZE*3), + .ptr1_reg = DMA22_PTR1, + .ptr2_reg = DMA22_PTR2, + .cnt1_reg = DMA22_CNT1, + .cnt2_reg = DMA22_CNT2, + .int_msk = AUD_B_INT_MSK, + .int_stat = AUD_B_INT_STAT, + .int_mstat = AUD_B_INT_MSTAT, + .dma_ctl = AUD_INT_DMA_CTL, + .gpcnt_ctl = AUD_B_GPCNT_CTL, + .gpcnt = AUD_B_GPCNT, + .aud_length = AUD_B_LNGTH, + .aud_cfg = AUD_B_CFG, + .fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN, + .fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN, + .irq_bit = 11, + }, }; @@ -325,7 +325,7 @@ struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04]; struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05]; struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06]; struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07]; -struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09]; +struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09]; struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10]; struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11]; @@ -334,40 +334,40 @@ struct cx25821_dmaqueue mpegq; static int cx25821_risc_decode(u32 risc) { static char *instr[16] = { - [RISC_SYNC >> 28] = "sync", - [RISC_WRITE >> 28] = "write", - [RISC_WRITEC >> 28] = "writec", - [RISC_READ >> 28] = "read", - [RISC_READC >> 28] = "readc", - [RISC_JUMP >> 28] = "jump", - [RISC_SKIP >> 28] = "skip", - [RISC_WRITERM >> 28] = "writerm", - [RISC_WRITECM >> 28] = "writecm", - [RISC_WRITECR >> 28] = "writecr", + [RISC_SYNC >> 28] = "sync", + [RISC_WRITE >> 28] = "write", + [RISC_WRITEC >> 28] = "writec", + [RISC_READ >> 28] = "read", + [RISC_READC >> 28] = "readc", + [RISC_JUMP >> 28] = "jump", + [RISC_SKIP >> 28] = "skip", + [RISC_WRITERM >> 28] = "writerm", + [RISC_WRITECM >> 28] = "writecm", + [RISC_WRITECR >> 28] = "writecr", }; static int incr[16] = { - [RISC_WRITE >> 28] = 3, - [RISC_JUMP >> 28] = 3, - [RISC_SKIP >> 28] = 1, - [RISC_SYNC >> 28] = 1, - [RISC_WRITERM >> 28] = 3, - [RISC_WRITECM >> 28] = 3, - [RISC_WRITECR >> 28] = 4, + [RISC_WRITE >> 28] = 3, + [RISC_JUMP >> 28] = 3, + [RISC_SKIP >> 28] = 1, + [RISC_SYNC >> 28] = 1, + [RISC_WRITERM >> 28] = 3, + [RISC_WRITECM >> 28] = 3, + [RISC_WRITECR >> 28] = 4, }; static char *bits[] = { - "12", "13", "14", "resync", - "cnt0", "cnt1", "18", "19", - "20", "21", "22", "23", - "irq1", "irq2", "eol", "sol", + "12", "13", "14", "resync", + "cnt0", "cnt1", "18", "19", + "20", "21", "22", "23", + "irq1", "irq2", "eol", "sol", }; int i; printk("0x%08x [ %s", risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) - { - if (risc & (1 << (i + 12))) - printk(" %s", bits[i]); - } + { + if (risc & (1 << (i + 12))) + printk(" %s", bits[i]); + } printk(" count=%d ]\n", risc & 0xfff); return incr[risc >> 28] ? incr[risc >> 28] : 1; } @@ -384,17 +384,17 @@ void cx_i2c_read_print(struct cx25821_dev *dev, u32 reg, const char* reg_string) { int tmp = 0; u32 value = 0; - + value = cx25821_i2c_read(&dev->i2c_bus[0], reg, &tmp); } static void cx25821_registers_init(struct cx25821_dev *dev) { u32 tmp; - + // enable RUN_RISC in Pecos cx_write( DEV_CNTRL2, 0x20 ); - + // Set the master PCI interrupt masks to enable video, audio, MBIF, and GPIO interrupts // I2C interrupt masking is handled by the I2C objects themselves. cx_write( PCI_INT_MSK, 0x2001FFFF ); @@ -408,7 +408,7 @@ static void cx25821_registers_init(struct cx25821_dev *dev) // PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 cx_write( PLL_A_POST_STAT_BIST, 0x8000019C); - + // clear reset bit [31] tmp = cx_read( PLL_A_INT_FRAC ); cx_write( PLL_A_INT_FRAC, tmp & 0x7FFFFFFF); @@ -443,52 +443,52 @@ static void cx25821_registers_init(struct cx25821_dev *dev) tmp = cx_read( PLL_D_INT_FRAC ); cx_write( PLL_D_INT_FRAC, tmp & 0x7FFFFFFF); - + // This selects the PLL C clock source for the video upstream channel I and J tmp = cx_read( VID_CH_CLK_SEL ); cx_write( VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000); - + // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C //select 656/VIP DST for downstream Channel A - C tmp = cx_read( VID_CH_MODE_SEL ); //cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); - + // enables 656 port I and J as output tmp = cx_read( CLK_RST ); tmp |= FLD_USE_ALT_PLL_REF; // use external ALT_PLL_REF pin as its reference clock instead cx_write( CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE) ); - + mdelay(100); } int cx25821_sram_channel_setup(struct cx25821_dev *dev, - struct sram_channel *ch, - unsigned int bpl, u32 risc) + struct sram_channel *ch, + unsigned int bpl, u32 risc) { unsigned int i, lines; u32 cdt; if (ch->cmds_start == 0) { - cx_write(ch->ptr1_reg, 0); - cx_write(ch->ptr2_reg, 0); - cx_write(ch->cnt2_reg, 0); - cx_write(ch->cnt1_reg, 0); - return 0; - } + cx_write(ch->ptr1_reg, 0); + cx_write(ch->ptr2_reg, 0); + cx_write(ch->cnt2_reg, 0); + cx_write(ch->cnt1_reg, 0); + return 0; + } bpl = (bpl + 7) & ~7; /* alignment */ cdt = ch->cdt; lines = ch->fifo_size / bpl; - - if (lines > 4) + + if (lines > 4) { - lines = 4; + lines = 4; } - + BUG_ON(lines < 2); cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); @@ -497,75 +497,75 @@ int cx25821_sram_channel_setup(struct cx25821_dev *dev, /* write CDT */ for (i = 0; i < lines; i++) { - cx_write(cdt + 16*i, ch->fifo_start + bpl*i); - cx_write(cdt + 16*i + 4, 0); - cx_write(cdt + 16*i + 8, 0); - cx_write(cdt + 16*i + 12, 0); + cx_write(cdt + 16*i, ch->fifo_start + bpl*i); + cx_write(cdt + 16*i + 4, 0); + cx_write(cdt + 16*i + 8, 0); + cx_write(cdt + 16*i + 12, 0); } //init the first cdt buffer for(i=0; i<128; i++) - cx_write(ch->fifo_start+4*i, i); + cx_write(ch->fifo_start+4*i, i); /* write CMDS */ if (ch->jumponly) - { - cx_write(ch->cmds_start + 0, 8); + { + cx_write(ch->cmds_start + 0, 8); } else - { - cx_write(ch->cmds_start + 0, risc); + { + cx_write(ch->cmds_start + 0, risc); } - + cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ - cx_write(ch->cmds_start + 8, cdt); - cx_write(ch->cmds_start + 12, (lines*16) >> 3); - cx_write(ch->cmds_start + 16, ch->ctrl_start); - + cx_write(ch->cmds_start + 8, cdt); + cx_write(ch->cmds_start + 12, (lines*16) >> 3); + cx_write(ch->cmds_start + 16, ch->ctrl_start); + if (ch->jumponly) - cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); + cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); else - cx_write(ch->cmds_start + 20, 64 >> 2); + cx_write(ch->cmds_start + 20, 64 >> 2); for (i = 24; i < 80; i += 4) - cx_write(ch->cmds_start + i, 0); + cx_write(ch->cmds_start + i, 0); /* fill registers */ cx_write(ch->ptr1_reg, ch->fifo_start); cx_write(ch->ptr2_reg, cdt); cx_write(ch->cnt2_reg, (lines*16) >> 3); - cx_write(ch->cnt1_reg, (bpl >> 3) - 1); + cx_write(ch->cnt1_reg, (bpl >> 3) - 1); return 0; } int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, - struct sram_channel *ch, - unsigned int bpl, u32 risc) + struct sram_channel *ch, + unsigned int bpl, u32 risc) { unsigned int i, lines; u32 cdt; if (ch->cmds_start == 0) { - cx_write(ch->ptr1_reg, 0); - cx_write(ch->ptr2_reg, 0); - cx_write(ch->cnt2_reg, 0); - cx_write(ch->cnt1_reg, 0); - return 0; + cx_write(ch->ptr1_reg, 0); + cx_write(ch->ptr2_reg, 0); + cx_write(ch->cnt2_reg, 0); + cx_write(ch->cnt1_reg, 0); + return 0; } bpl = (bpl + 7) & ~7; /* alignment */ cdt = ch->cdt; lines = ch->fifo_size / bpl; - - if (lines > 3) - { - lines = 3; //for AUDIO + + if (lines > 3) + { + lines = 3; //for AUDIO } - + BUG_ON(lines < 2); - + cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); cx_write(8 + 4, 8); @@ -573,47 +573,47 @@ int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, /* write CDT */ for (i = 0; i < lines; i++) { - cx_write(cdt + 16*i, ch->fifo_start + bpl*i); - cx_write(cdt + 16*i + 4, 0); - cx_write(cdt + 16*i + 8, 0); - cx_write(cdt + 16*i + 12, 0); + cx_write(cdt + 16*i, ch->fifo_start + bpl*i); + cx_write(cdt + 16*i + 4, 0); + cx_write(cdt + 16*i + 8, 0); + cx_write(cdt + 16*i + 12, 0); } /* write CMDS */ if (ch->jumponly) - { - cx_write(ch->cmds_start + 0, 8); + { + cx_write(ch->cmds_start + 0, 8); } else - { - cx_write(ch->cmds_start + 0, risc); + { + cx_write(ch->cmds_start + 0, risc); } - + cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ - cx_write(ch->cmds_start + 8, cdt); - cx_write(ch->cmds_start + 12, (lines*16) >> 3); - cx_write(ch->cmds_start + 16, ch->ctrl_start); + cx_write(ch->cmds_start + 8, cdt); + cx_write(ch->cmds_start + 12, (lines*16) >> 3); + cx_write(ch->cmds_start + 16, ch->ctrl_start); //IQ size if (ch->jumponly) - { - cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); + { + cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); } else - { - cx_write(ch->cmds_start + 20, 64 >> 2); + { + cx_write(ch->cmds_start + 20, 64 >> 2); } //zero out for (i = 24; i < 80; i += 4) - cx_write(ch->cmds_start + i, 0); + cx_write(ch->cmds_start + i, 0); /* fill registers */ cx_write(ch->ptr1_reg, ch->fifo_start); - cx_write(ch->ptr2_reg, cdt); - cx_write(ch->cnt2_reg, (lines*16) >> 3); - cx_write(ch->cnt1_reg, (bpl >> 3) - 1); - + cx_write(ch->ptr2_reg, cdt); + cx_write(ch->cnt2_reg, (lines*16) >> 3); + cx_write(ch->cnt1_reg, (bpl >> 3) - 1); + return 0; } @@ -621,46 +621,46 @@ int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) { static char *name[] = { - "init risc lo", - "init risc hi", - "cdt base", - "cdt size", - "iq base", - "iq size", - "risc pc lo", - "risc pc hi", - "iq wr ptr", - "iq rd ptr", - "cdt current", - "pci target lo", - "pci target hi", - "line / byte", + "init risc lo", + "init risc hi", + "cdt base", + "cdt size", + "iq base", + "iq size", + "risc pc lo", + "risc pc hi", + "iq wr ptr", + "iq rd ptr", + "cdt current", + "pci target lo", + "pci target hi", + "line / byte", }; u32 risc; unsigned int i, j, n; - + printk(KERN_WARNING "%s: %s - dma channel status dump\n", dev->name, ch->name); for (i = 0; i < ARRAY_SIZE(name); i++) - printk(KERN_WARNING "cmds + 0x%2x: %-15s: 0x%08x\n", i*4, name[i], - cx_read(ch->cmds_start + 4*i)); + printk(KERN_WARNING "cmds + 0x%2x: %-15s: 0x%08x\n", i*4, name[i], + cx_read(ch->cmds_start + 4*i)); j=i*4; for (i = 0; i < 4; ) { - risc = cx_read(ch->cmds_start + 4 * (i + 14)); - printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j+i*4, i); - i +=cx25821_risc_decode(risc); + risc = cx_read(ch->cmds_start + 4 * (i + 14)); + printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j+i*4, i); + i +=cx25821_risc_decode(risc); } for (i = 0; i < (64 >> 2); i += n) { - risc = cx_read(ch->ctrl_start + 4 * i); - /* No consideration for bits 63-32 */ - - printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i); - n = cx25821_risc_decode(risc); - for (j = 1; j < n; j++) { - risc = cx_read(ch->ctrl_start + 4 * (i + j)); - printk(KERN_WARNING "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j); - } + risc = cx_read(ch->ctrl_start + 4 * i); + /* No consideration for bits 63-32 */ + + printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i); + n = cx25821_risc_decode(risc); + for (j = 1; j < n; j++) { + risc = cx_read(ch->ctrl_start + 4 * (i + j)); + printk(KERN_WARNING "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j); + } } printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", ch->fifo_start, ch->fifo_start+ch->fifo_size); @@ -674,50 +674,50 @@ void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channel *ch) { static char *name[] = { - "init risc lo", - "init risc hi", - "cdt base", - "cdt size", - "iq base", - "iq size", - "risc pc lo", - "risc pc hi", - "iq wr ptr", - "iq rd ptr", - "cdt current", - "pci target lo", - "pci target hi", - "line / byte", + "init risc lo", + "init risc hi", + "cdt base", + "cdt size", + "iq base", + "iq size", + "risc pc lo", + "risc pc hi", + "iq wr ptr", + "iq rd ptr", + "cdt current", + "pci target lo", + "pci target hi", + "line / byte", }; - - u32 risc, value, tmp; + + u32 risc, value, tmp; unsigned int i, j, n; printk(KERN_INFO "\n%s: %s - dma Audio channel status dump\n", dev->name, ch->name); - + for (i = 0; i < ARRAY_SIZE(name); i++) - printk(KERN_INFO "%s: cmds + 0x%2x: %-15s: 0x%08x\n", dev->name, i*4, name[i], cx_read(ch->cmds_start + 4*i)); + printk(KERN_INFO "%s: cmds + 0x%2x: %-15s: 0x%08x\n", dev->name, i*4, name[i], cx_read(ch->cmds_start + 4*i)); - j=i*4; + j=i*4; for (i = 0; i < 4; ) { - risc = cx_read(ch->cmds_start + 4 * (i + 14)); - printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j+i*4, i); - i += cx25821_risc_decode(risc); + risc = cx_read(ch->cmds_start + 4 * (i + 14)); + printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j+i*4, i); + i += cx25821_risc_decode(risc); } - + for (i = 0; i < (64 >> 2); i += n) { - risc = cx_read(ch->ctrl_start + 4 * i); - /* No consideration for bits 63-32 */ - - printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i); - n = cx25821_risc_decode(risc); - - for (j = 1; j < n; j++) { - risc = cx_read(ch->ctrl_start + 4 * (i + j)); - printk(KERN_WARNING "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j); - } + risc = cx_read(ch->ctrl_start + 4 * i); + /* No consideration for bits 63-32 */ + + printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i); + n = cx25821_risc_decode(risc); + + for (j = 1; j < n; j++) { + risc = cx_read(ch->ctrl_start + 4 * (i + j)); + printk(KERN_WARNING "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j); + } } printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", ch->fifo_start, ch->fifo_start+ch->fifo_size); @@ -726,24 +726,24 @@ void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channe printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", cx_read(ch->ptr2_reg)); printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", cx_read(ch->cnt1_reg)); printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", cx_read(ch->cnt2_reg)); - + for( i=0; i < 4; i++) { - risc = cx_read(ch->cmds_start + 56 + (i*4)); - printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc); + risc = cx_read(ch->cmds_start + 56 + (i*4)); + printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc); } //read data from the first cdt buffer - risc = cx_read(AUD_A_CDT); + risc = cx_read(AUD_A_CDT); printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc); for(i=0; i<8; i++) { - n = cx_read(risc+i*4); - printk(KERN_WARNING "0x%x ", n); - } + n = cx_read(risc+i*4); + printk(KERN_WARNING "0x%x ", n); + } printk(KERN_WARNING "\n\n"); - - + + value = cx_read(CLK_RST); CX25821_INFO(" CLK_RST = 0x%x \n\n", value); @@ -751,22 +751,22 @@ void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channe CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x \n\n", value); value = cx_read(PLL_A_INT_FRAC); CX25821_INFO(" PLL_A_INT_FRAC = 0x%x \n\n", value); - + value = cx_read(PLL_B_POST_STAT_BIST); CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x \n\n", value); value = cx_read(PLL_B_INT_FRAC); CX25821_INFO(" PLL_B_INT_FRAC = 0x%x \n\n", value); - + value = cx_read(PLL_C_POST_STAT_BIST); CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x \n\n", value); value = cx_read(PLL_C_INT_FRAC); CX25821_INFO(" PLL_C_INT_FRAC = 0x%x \n\n", value); - + value = cx_read(PLL_D_POST_STAT_BIST); CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x \n\n", value); value = cx_read(PLL_D_INT_FRAC); CX25821_INFO(" PLL_D_INT_FRAC = 0x%x \n\n", value); - + value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x \n\n", value); } @@ -781,16 +781,16 @@ static void cx25821_shutdown(struct cx25821_dev *dev) /* Disable Video A/B activity */ for(i=0; isram_channels[i].dma_ctl, 0); - cx_write(dev->sram_channels[i].int_msk, 0); + cx_write(dev->sram_channels[i].dma_ctl, 0); + cx_write(dev->sram_channels[i].int_msk, 0); } - for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) + for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) { - cx_write(dev->sram_channels[i].dma_ctl, 0); - cx_write(dev->sram_channels[i].int_msk, 0); + cx_write(dev->sram_channels[i].dma_ctl, 0); + cx_write(dev->sram_channels[i].int_msk, 0); } - + /* Disable Audio activity */ cx_write(AUD_INT_DMA_CTL, 0); @@ -803,14 +803,14 @@ static void cx25821_shutdown(struct cx25821_dev *dev) } void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, u32 format) -{ - struct sram_channel *ch; - +{ + struct sram_channel *ch; + if( channel_select <= 7 && channel_select >= 0 ) { - ch = &cx25821_sram_channels[channel_select]; - cx_write(ch->pix_frmt, format); - dev->pixel_formats[channel_select] = format; + ch = &cx25821_sram_channels[channel_select]; + cx_write(ch->pix_frmt, format); + dev->pixel_formats[channel_select] = format; } } @@ -825,12 +825,12 @@ static void cx25821_initialize(struct cx25821_dev *dev) int i; dprintk(1, "%s()\n", __func__); - + cx25821_shutdown(dev); cx_write(PCI_INT_STAT, 0xffffffff); - + for(i=0; isram_channels[i].int_stat, 0xffffffff); + cx_write(dev->sram_channels[i].int_stat, 0xffffffff); cx_write(AUD_A_INT_STAT, 0xffffffff); @@ -840,26 +840,26 @@ static void cx25821_initialize(struct cx25821_dev *dev) cx_write(AUD_E_INT_STAT, 0xffffffff); cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000); - cx_write(PAD_CTRL, 0x12); //for I2C + cx_write(PAD_CTRL, 0x12); //for I2C cx25821_registers_init(dev); //init Pecos registers mdelay(100); - - + + for(i=0; isram_channels[i]); - cx25821_sram_channel_setup(dev, &dev->sram_channels[i], 1440, 0); - dev->pixel_formats[i] = PIXEL_FRMT_422; - dev->use_cif_resolution[i] = FALSE; + cx25821_set_vip_mode(dev, &dev->sram_channels[i]); + cx25821_sram_channel_setup(dev, &dev->sram_channels[i], 1440, 0); + dev->pixel_formats[i] = PIXEL_FRMT_422; + dev->use_cif_resolution[i] = FALSE; } //Probably only affect Downstream - for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) + for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) { - cx25821_set_vip_mode(dev, &dev->sram_channels[i]); + cx25821_set_vip_mode(dev, &dev->sram_channels[i]); } - - cx25821_sram_channel_setup_audio(dev, &dev->sram_channels[SRAM_CH08], 128, 0); + + cx25821_sram_channel_setup_audio(dev, &dev->sram_channels[SRAM_CH08], 128, 0); cx25821_gpio_init(dev); } @@ -867,10 +867,10 @@ static void cx25821_initialize(struct cx25821_dev *dev) static int get_resources(struct cx25821_dev *dev) { if (request_mem_region(pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0), dev->name)) - return 0; + return 0; printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n", - dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); + dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); return -EBUSY; } @@ -878,7 +878,7 @@ static int get_resources(struct cx25821_dev *dev) static void cx25821_dev_checkrevision(struct cx25821_dev *dev) { - dev->hwrevision = cx_read(RDR_CFG2) & 0xff; + dev->hwrevision = cx_read(RDR_CFG2) & 0xff; printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", __func__, dev->hwrevision); } @@ -886,41 +886,41 @@ static void cx25821_dev_checkrevision(struct cx25821_dev *dev) static void cx25821_iounmap(struct cx25821_dev *dev) { if (dev == NULL) - return; + return; /* Releasing IO memory */ - if (dev->lmmio != NULL) + if (dev->lmmio != NULL) { - CX25821_INFO("Releasing lmmio.\n"); - iounmap(dev->lmmio); - dev->lmmio = NULL; + CX25821_INFO("Releasing lmmio.\n"); + iounmap(dev->lmmio); + dev->lmmio = NULL; } } static int cx25821_dev_setup(struct cx25821_dev *dev) -{ +{ int io_size = 0, i; - + struct video_device *video_template[] = { - &cx25821_video_template0, - &cx25821_video_template1, - &cx25821_video_template2, - &cx25821_video_template3, - &cx25821_video_template4, - &cx25821_video_template5, - &cx25821_video_template6, - &cx25821_video_template7, - &cx25821_video_template9, - &cx25821_video_template10, - &cx25821_video_template11, - &cx25821_videoioctl_template, - }; + &cx25821_video_template0, + &cx25821_video_template1, + &cx25821_video_template2, + &cx25821_video_template3, + &cx25821_video_template4, + &cx25821_video_template5, + &cx25821_video_template6, + &cx25821_video_template7, + &cx25821_video_template9, + &cx25821_video_template10, + &cx25821_video_template11, + &cx25821_videoioctl_template, + }; printk(KERN_INFO "\n***********************************\n"); printk(KERN_INFO "cx25821 set up\n"); printk(KERN_INFO "***********************************\n\n"); - + mutex_init(&dev->lock); atomic_inc(&dev->refcount); @@ -934,30 +934,30 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown"); strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); - - + + if( dev->pci->device != 0x8210 ) { - printk(KERN_INFO "%s() Exiting. Incorrect Hardware device = 0x%02x\n", - __func__, dev->pci->device); - return -1; + printk(KERN_INFO "%s() Exiting. Incorrect Hardware device = 0x%02x\n", + __func__, dev->pci->device); + return -1; } else - { - printk(KERN_INFO "Athena Hardware device = 0x%02x\n", dev->pci->device); + { + printk(KERN_INFO "Athena Hardware device = 0x%02x\n", dev->pci->device); } - + /* Apply a sensible clock frequency for the PCIe bridge */ dev->clk_freq = 28000000; dev->sram_channels = cx25821_sram_channels; if(dev->nr > 1) { - CX25821_INFO("dev->nr > 1!"); + CX25821_INFO("dev->nr > 1!"); } /* board config */ - dev->board = 1; //card[dev->nr]; + dev->board = 1; //card[dev->nr]; dev->_max_num_decoders = MAX_DECODERS; @@ -976,7 +976,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */ -#if 0 +#if 0 /* External Master 2 Bus */ dev->i2c_bus[1].nr = 1; dev->i2c_bus[1].dev = dev; @@ -996,143 +996,143 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) dev->i2c_bus[2].reg_rdata = I2C3_RDATA; dev->i2c_bus[2].reg_wdata = I2C3_WDATA; dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */ -#endif +#endif - if (get_resources(dev) < 0) + if (get_resources(dev) < 0) { - printk(KERN_ERR "%s No more PCIe resources for " - "subsystem: %04x:%04x\n", - dev->name, dev->pci->subsystem_vendor, - dev->pci->subsystem_device); + printk(KERN_ERR "%s No more PCIe resources for " + "subsystem: %04x:%04x\n", + dev->name, dev->pci->subsystem_vendor, + dev->pci->subsystem_device); - cx25821_devcount--; - return -ENODEV; + cx25821_devcount--; + return -ENODEV; } - /* PCIe stuff */ + /* PCIe stuff */ dev->base_io_addr = pci_resource_start(dev->pci, 0); io_size = pci_resource_len(dev->pci, 0); - + if (!dev->base_io_addr) { - CX25821_ERR("No PCI Memory resources, exiting!\n"); - return -ENODEV; + CX25821_ERR("No PCI Memory resources, exiting!\n"); + return -ENODEV; } - + dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0)); if (!dev->lmmio) { - CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); - cx25821_iounmap(dev); - return -ENOMEM; + CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); + cx25821_iounmap(dev); + return -ENOMEM; } - + dev->bmmio = (u8 __iomem *)dev->lmmio; printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", - dev->name, dev->pci->subsystem_vendor, - dev->pci->subsystem_device, cx25821_boards[dev->board].name, - dev->board, card[dev->nr] == dev->board ? - "insmod option" : "autodetected"); + dev->name, dev->pci->subsystem_vendor, + dev->pci->subsystem_device, cx25821_boards[dev->board].name, + dev->board, card[dev->nr] == dev->board ? + "insmod option" : "autodetected"); /* init hardware */ cx25821_initialize(dev); - + cx25821_i2c_register(&dev->i2c_bus[0]); // cx25821_i2c_register(&dev->i2c_bus[1]); // cx25821_i2c_register(&dev->i2c_bus[2]); CX25821_INFO("i2c register! bus->i2c_rc = %d\n", dev->i2c_bus[0].i2c_rc); - cx25821_card_setup(dev); + cx25821_card_setup(dev); medusa_video_init(dev); - + for(i = 0; i < VID_CHANNEL_NUM; i++) { - if (cx25821_video_register(dev, i, video_template[i]) < 0) { - printk(KERN_ERR "%s() Failed to register analog video adapters on VID channel %d\n", __func__, i); - } + if (cx25821_video_register(dev, i, video_template[i]) < 0) { + printk(KERN_ERR "%s() Failed to register analog video adapters on VID channel %d\n", __func__, i); + } } - - + + for(i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) { - //Since we don't have template8 for Audio Downstream - if (cx25821_video_register(dev, i, video_template[i-1]) < 0) { - printk(KERN_ERR "%s() Failed to register analog video adapters for Upstream channel %d.\n", __func__, i); - } + //Since we don't have template8 for Audio Downstream + if (cx25821_video_register(dev, i, video_template[i-1]) < 0) { + printk(KERN_ERR "%s() Failed to register analog video adapters for Upstream channel %d.\n", __func__, i); + } } - - // register IOCTL device + + // register IOCTL device dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH], "video"); - + if( video_register_device(dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0 ) - { - cx25821_videoioctl_unregister(dev); - printk(KERN_ERR "%s() Failed to register video adapter for IOCTL so releasing.\n", __func__); + { + cx25821_videoioctl_unregister(dev); + printk(KERN_ERR "%s() Failed to register video adapter for IOCTL so releasing.\n", __func__); } - + cx25821_dev_checkrevision(dev); CX25821_INFO("cx25821 setup done!\n"); - + return 0; -} +} void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, struct upstream_user_struct *up_data) { - dev->_isNTSC = !strcmp(dev->vid_stdname,"NTSC") ? 1 : 0; - - dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; + dev->_isNTSC = !strcmp(dev->vid_stdname,"NTSC") ? 1 : 0; + + dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; medusa_set_videostandard(dev); - - cx25821_vidupstream_init_ch1(dev, dev->channel_select, dev->pixel_format); + + cx25821_vidupstream_init_ch1(dev, dev->channel_select, dev->pixel_format); } void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, struct upstream_user_struct *up_data) { - dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2,"NTSC") ? 1 : 0; + dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2,"NTSC") ? 1 : 0; + + dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; + medusa_set_videostandard(dev); - dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; - medusa_set_videostandard(dev); - - cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2, dev->pixel_format_ch2); + cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2, dev->pixel_format_ch2); } void cx25821_start_upstream_audio(struct cx25821_dev *dev, struct upstream_user_struct *up_data) { - cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B); + cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B); } - + void cx25821_dev_unregister(struct cx25821_dev *dev) { int i; - if (!dev->base_io_addr) - return; - + if (!dev->base_io_addr) + return; + cx25821_free_mem_upstream_ch1(dev); - cx25821_free_mem_upstream_ch2(dev); - cx25821_free_mem_upstream_audio(dev); - + cx25821_free_mem_upstream_ch2(dev); + cx25821_free_mem_upstream_audio(dev); + release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); if (!atomic_dec_and_test(&dev->refcount)) - return; + return; for(i=0; i < VID_CHANNEL_NUM; i++) - cx25821_video_unregister(dev, i); + cx25821_video_unregister(dev, i); + - for(i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) { - cx25821_video_unregister(dev, i); + cx25821_video_unregister(dev, i); } - + cx25821_videoioctl_unregister(dev); - + cx25821_i2c_unregister( &dev->i2c_bus[0] ); cx25821_iounmap(dev); } @@ -1140,9 +1140,9 @@ void cx25821_dev_unregister(struct cx25821_dev *dev) static __le32 *cx25821_risc_field(__le32 *rp, struct scatterlist *sglist, - unsigned int offset, u32 sync_line, - unsigned int bpl, unsigned int padding, - unsigned int lines) + unsigned int offset, u32 sync_line, + unsigned int bpl, unsigned int padding, + unsigned int lines) { struct scatterlist *sg; unsigned int line, todo; @@ -1150,65 +1150,65 @@ static __le32 *cx25821_risc_field(__le32 *rp, struct scatterlist *sglist, /* sync instruction */ if (sync_line != NO_SYNC_LINE) { - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); } /* scan lines */ sg = sglist; for (line = 0; line < lines; line++) { - while (offset && offset >= sg_dma_len(sg)) { - offset -= sg_dma_len(sg); - sg++; - } - if (bpl <= sg_dma_len(sg)-offset) { - /* fits into current chunk */ - *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - offset += bpl; - } else { - /* scanline needs to be split */ - todo = bpl; - *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|(sg_dma_len(sg)-offset)); - *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++) = cpu_to_le32(RISC_WRITE|sg_dma_len(sg)); - *(rp++) = cpu_to_le32(sg_dma_address(sg)); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - todo -= sg_dma_len(sg); - sg++; - } - *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo); - *(rp++) = cpu_to_le32(sg_dma_address(sg)); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - offset += todo; - } - - offset += padding; + while (offset && offset >= sg_dma_len(sg)) { + offset -= sg_dma_len(sg); + sg++; + } + if (bpl <= sg_dma_len(sg)-offset) { + /* fits into current chunk */ + *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); + *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + offset += bpl; + } else { + /* scanline needs to be split */ + todo = bpl; + *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|(sg_dma_len(sg)-offset)); + *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + todo -= (sg_dma_len(sg)-offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++) = cpu_to_le32(RISC_WRITE|sg_dma_len(sg)); + *(rp++) = cpu_to_le32(sg_dma_address(sg)); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + todo -= sg_dma_len(sg); + sg++; + } + *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo); + *(rp++) = cpu_to_le32(sg_dma_address(sg)); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + offset += todo; + } + + offset += padding; } return rp; } int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, - struct scatterlist *sglist, unsigned int top_offset, - unsigned int bottom_offset, unsigned int bpl, - unsigned int padding, unsigned int lines) + struct scatterlist *sglist, unsigned int top_offset, + unsigned int bottom_offset, unsigned int bpl, + unsigned int padding, unsigned int lines) { u32 instructions; - u32 fields; + u32 fields; __le32 *rp; int rc; fields = 0; if (UNSET != top_offset) - fields++; + fields++; if (UNSET != bottom_offset) - fields++; + fields++; /* estimate risc mem: worst case is one write per page border + one write per scan line + syncs + jump (all 2 dwords). Padding @@ -1220,19 +1220,19 @@ int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, rc = btcx_riscmem_alloc(pci, risc, instructions*12); if (rc < 0) - return rc; + return rc; /* write risc instructions */ rp = risc->cpu; - + if (UNSET != top_offset) { - rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding, lines); + rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding, lines); } if (UNSET != bottom_offset) { - rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl, padding, lines); + rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl, padding, lines); } /* save pointer to jmp instruction address */ @@ -1244,71 +1244,71 @@ int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, static __le32* cx25821_risc_field_audio(__le32 *rp, struct scatterlist *sglist, - unsigned int offset, u32 sync_line, - unsigned int bpl, unsigned int padding, - unsigned int lines, unsigned int lpi) + unsigned int offset, u32 sync_line, + unsigned int bpl, unsigned int padding, + unsigned int lines, unsigned int lpi) { struct scatterlist *sg; unsigned int line, todo, sol; /* sync instruction */ if (sync_line != NO_SYNC_LINE) - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); /* scan lines */ sg = sglist; for (line = 0; line < lines; line++) { - while (offset && offset >= sg_dma_len(sg)) { - offset -= sg_dma_len(sg); - sg++; - } - - if (lpi && line > 0 && !(line % lpi)) - sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; - else - sol = RISC_SOL; - - if (bpl <= sg_dma_len(sg)-offset) { - /* fits into current chunk */ - *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - *(rp++)=cpu_to_le32(0); /* bits 63-32 */ - offset+=bpl; - } else { - /* scanline needs to be split */ - todo = bpl; - *(rp++) = cpu_to_le32(RISC_WRITE|sol| - (sg_dma_len(sg)-offset)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - *(rp++)=cpu_to_le32(0); /* bits 63-32 */ - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(RISC_WRITE| - sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); - *(rp++)=cpu_to_le32(0); /* bits 63-32 */ - todo -= sg_dma_len(sg); - sg++; - } - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); - *(rp++)=cpu_to_le32(0); /* bits 63-32 */ - offset += todo; - } - offset += padding; + while (offset && offset >= sg_dma_len(sg)) { + offset -= sg_dma_len(sg); + sg++; + } + + if (lpi && line > 0 && !(line % lpi)) + sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; + else + sol = RISC_SOL; + + if (bpl <= sg_dma_len(sg)-offset) { + /* fits into current chunk */ + *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl); + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + *(rp++)=cpu_to_le32(0); /* bits 63-32 */ + offset+=bpl; + } else { + /* scanline needs to be split */ + todo = bpl; + *(rp++) = cpu_to_le32(RISC_WRITE|sol| + (sg_dma_len(sg)-offset)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + *(rp++)=cpu_to_le32(0); /* bits 63-32 */ + todo -= (sg_dma_len(sg)-offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++)=cpu_to_le32(RISC_WRITE| + sg_dma_len(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(0); /* bits 63-32 */ + todo -= sg_dma_len(sg); + sg++; + } + *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(0); /* bits 63-32 */ + offset += todo; + } + offset += padding; } return rp; } int cx25821_risc_databuffer_audio(struct pci_dev *pci, - struct btcx_riscmem *risc, - struct scatterlist *sglist, - unsigned int bpl, - unsigned int lines, - unsigned int lpi) + struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int bpl, + unsigned int lines, + unsigned int lpi) { u32 instructions; __le32 *rp; @@ -1323,13 +1323,13 @@ int cx25821_risc_databuffer_audio(struct pci_dev *pci, instructions += 1; if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0) - return rc; + return rc; /* write risc instructions */ rp = risc->cpu; rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi); - + /* save pointer to jmp instruction address */ risc->jmp = rp; BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); @@ -1345,18 +1345,18 @@ int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,u32 reg, rc = btcx_riscmem_alloc(pci, risc, 4*16); if (rc < 0) - return rc; + return rc; /* write risc instructions */ rp = risc->cpu; - *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1); - *(rp++) = cpu_to_le32(reg); - *(rp++) = cpu_to_le32(value); - *(rp++) = cpu_to_le32(mask); - *(rp++) = cpu_to_le32(RISC_JUMP); - *(rp++) = cpu_to_le32(risc->dma); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1); + *(rp++) = cpu_to_le32(reg); + *(rp++) = cpu_to_le32(value); + *(rp++) = cpu_to_le32(mask); + *(rp++) = cpu_to_le32(RISC_JUMP); + *(rp++) = cpu_to_le32(risc->dma); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ return 0; } @@ -1384,111 +1384,111 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id) pci_status = cx_read(PCI_INT_STAT); pci_mask = cx_read(PCI_INT_MSK); - - if (pci_status == 0) - goto out; + + if (pci_status == 0) + goto out; for(i = 0; i < VID_CHANNEL_NUM; i++) { - if(pci_status & mask[i]) - { - vid_status = cx_read(dev->sram_channels[i].int_stat); + if(pci_status & mask[i]) + { + vid_status = cx_read(dev->sram_channels[i].int_stat); - if(vid_status) - handled += cx25821_video_irq(dev, i, vid_status); + if(vid_status) + handled += cx25821_video_irq(dev, i, vid_status); - cx_write(PCI_INT_STAT, mask[i]); - } + cx_write(PCI_INT_STAT, mask[i]); + } } - + out: return IRQ_RETVAL(handled); } void cx25821_print_irqbits(char *name, char *tag, char **strings, - int len, u32 bits, u32 mask) + int len, u32 bits, u32 mask) { unsigned int i; printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits); - + for (i = 0; i < len; i++) { - if (!(bits & (1 << i))) - continue; - if (strings[i]) - printk(" %s", strings[i]); - else - printk(" %d", i); - if (!(mask & (1 << i))) - continue; - printk("*"); + if (!(bits & (1 << i))) + continue; + if (strings[i]) + printk(" %s", strings[i]); + else + printk(" %d", i); + if (!(mask & (1 << i))) + continue; + printk("*"); } printk("\n"); } struct cx25821_dev* cx25821_dev_get(struct pci_dev *pci) { - struct cx25821_dev *dev = pci_get_drvdata(pci); + struct cx25821_dev *dev = pci_get_drvdata(pci); return dev; } static int __devinit cx25821_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { - struct cx25821_dev *dev; + struct cx25821_dev *dev; int err = 0; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (NULL == dev) - return -ENOMEM; - - + return -ENOMEM; + + err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); if (err < 0) - goto fail_free; - + goto fail_free; + /* pci init */ dev->pci = pci_dev; - if (pci_enable_device(pci_dev)) + if (pci_enable_device(pci_dev)) { - err = -EIO; + err = -EIO; - printk(KERN_INFO "pci enable failed! "); + printk(KERN_INFO "pci enable failed! "); - goto fail_unregister_device; + goto fail_unregister_device; } printk(KERN_INFO "cx25821 Athena pci enable ! \n"); - if (cx25821_dev_setup(dev) < 0) + if (cx25821_dev_setup(dev) < 0) { - err = -EINVAL; - goto fail_unregister_device; + err = -EINVAL; + goto fail_unregister_device; } /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " - "latency: %d, mmio: 0x%llx\n", dev->name, - pci_name(pci_dev), dev->pci_rev, pci_dev->irq, - dev->pci_lat, - (unsigned long long)dev->base_io_addr ); - + "latency: %d, mmio: 0x%llx\n", dev->name, + pci_name(pci_dev), dev->pci_rev, pci_dev->irq, + dev->pci_lat, + (unsigned long long)dev->base_io_addr ); + pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev, 0xffffffff)) + if (!pci_dma_supported(pci_dev, 0xffffffff)) { - printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); - err = -EIO; - goto fail_irq; + printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); + err = -EIO; + goto fail_irq; } err = request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); - if (err < 0) + if (err < 0) { - printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name, pci_dev->irq); - goto fail_irq; + printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name, pci_dev->irq); + goto fail_irq; } return 0; @@ -1496,10 +1496,10 @@ static int __devinit cx25821_initdev(struct pci_dev *pci_dev, const struct pci_d fail_irq: printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ ! \n"); cx25821_dev_unregister(dev); - -fail_unregister_device: + +fail_unregister_device: v4l2_device_unregister(&dev->v4l2_dev); - + fail_free: kfree(dev); return err; @@ -1509,40 +1509,40 @@ static void __devexit cx25821_finidev(struct pci_dev *pci_dev) { struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); struct cx25821_dev *dev = get_cx25821(v4l2_dev); - - cx25821_shutdown(dev); + + cx25821_shutdown(dev); pci_disable_device(pci_dev); /* unregister stuff */ - if( pci_dev->irq ) - free_irq(pci_dev->irq, dev); - - + if( pci_dev->irq ) + free_irq(pci_dev->irq, dev); + + mutex_lock(&devlist); list_del(&dev->devlist); mutex_unlock(&devlist); cx25821_dev_unregister(dev); - v4l2_device_unregister(v4l2_dev); + v4l2_device_unregister(v4l2_dev); kfree(dev); } static struct pci_device_id cx25821_pci_tbl[] = { { - /* CX25821 Athena*/ - .vendor = 0x14f1, - .device = 0x8210, - .subvendor = 0x14f1, - .subdevice = 0x0920, - }, + /* CX25821 Athena*/ + .vendor = 0x14f1, + .device = 0x8210, + .subvendor = 0x14f1, + .subdevice = 0x0920, + }, { - /* --- end of list --- */ + /* --- end of list --- */ } }; MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl); -static struct pci_driver cx25821_pci_driver = +static struct pci_driver cx25821_pci_driver = { .name = "cx25821", .id_table = cx25821_pci_tbl, @@ -1555,11 +1555,11 @@ static struct pci_driver cx25821_pci_driver = static int cx25821_init(void) { - INIT_LIST_HEAD(&cx25821_devlist); + INIT_LIST_HEAD(&cx25821_devlist); printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n", - (CX25821_VERSION_CODE >> 16) & 0xff, - (CX25821_VERSION_CODE >> 8) & 0xff, - CX25821_VERSION_CODE & 0xff); + (CX25821_VERSION_CODE >> 16) & 0xff, + (CX25821_VERSION_CODE >> 8) & 0xff, + CX25821_VERSION_CODE & 0xff); return pci_register_driver(&cx25821_pci_driver); } diff --git a/linux/drivers/staging/cx25821/cx25821-gpio.c b/linux/drivers/staging/cx25821/cx25821-gpio.c index aa029fe34..074c19682 100644 --- a/linux/drivers/staging/cx25821/cx25821-gpio.c +++ b/linux/drivers/staging/cx25821/cx25821-gpio.c @@ -25,17 +25,17 @@ /********************* GPIO stuffs *********************/ void cx25821_set_gpiopin_direction( struct cx25821_dev *dev, - int pin_number, - int pin_logic_value) + int pin_number, + int pin_logic_value) { int bit = pin_number; u32 gpio_oe_reg = GPIO_LO_OE; u32 gpio_register = 0; u32 value = 0; - + // Check for valid pinNumber if ( pin_number >= 47 ) - return; + return; if ( pin_number > 31 ) @@ -46,32 +46,32 @@ void cx25821_set_gpiopin_direction( struct cx25821_dev *dev, // Here we will make sure that the GPIOs 0 and 1 are output. keep the rest as is gpio_register = cx_read( gpio_oe_reg ); - + if (pin_logic_value == 1) { - value = gpio_register | Set_GPIO_Bit(bit) ; + value = gpio_register | Set_GPIO_Bit(bit) ; } else { - value = gpio_register & Clear_GPIO_Bit(bit) ; + value = gpio_register & Clear_GPIO_Bit(bit) ; } cx_write( gpio_oe_reg, value ); } static void cx25821_set_gpiopin_logicvalue( struct cx25821_dev *dev, - int pin_number, - int pin_logic_value) -{ + int pin_number, + int pin_logic_value) +{ int bit = pin_number; u32 gpio_reg = GPIO_LO; u32 value = 0; - - + + // Check for valid pinNumber if (pin_number >= 47) - return; - + return; + cx25821_set_gpiopin_direction(dev, pin_number, 0); // change to output direction @@ -82,15 +82,15 @@ static void cx25821_set_gpiopin_logicvalue( struct cx25821_dev *dev, } value = cx_read( gpio_reg ); - - + + if (pin_logic_value == 0) { - value &= Clear_GPIO_Bit(bit); + value &= Clear_GPIO_Bit(bit); } else { - value |= Set_GPIO_Bit(bit); + value |= Set_GPIO_Bit(bit); } cx_write( gpio_reg, value); @@ -102,15 +102,15 @@ void cx25821_gpio_init(struct cx25821_dev *dev) { return; } - - switch (dev->board) + + switch (dev->board) { - case CX25821_BOARD_CONEXANT_ATHENA10: - default: - //set GPIO 5 to select the path for Medusa/Athena - cx25821_set_gpiopin_logicvalue(dev, 5, 1); + case CX25821_BOARD_CONEXANT_ATHENA10: + default: + //set GPIO 5 to select the path for Medusa/Athena + cx25821_set_gpiopin_logicvalue(dev, 5, 1); mdelay(20); break; } - + } diff --git a/linux/drivers/staging/cx25821/cx25821-i2c.c b/linux/drivers/staging/cx25821/cx25821-i2c.c index de1a9a8b9..441edf823 100644 --- a/linux/drivers/staging/cx25821/cx25821-i2c.c +++ b/linux/drivers/staging/cx25821/cx25821-i2c.c @@ -88,9 +88,9 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len); /* Deal with i2c probe functions with zero payload */ - if (msg->len == 0) + if (msg->len == 0) { - cx_write(bus->reg_addr, msg->addr << 25); + cx_write(bus->reg_addr, msg->addr << 25); cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2)); if (!i2c_wait_done(i2c_adap)) @@ -106,7 +106,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg /* dev, reg + first byte */ addr = (msg->addr << 25) | msg->buf[0]; wdata = msg->buf[0]; - + ctrl = bus->i2c_period | (1 << 12) | (1 << 2); if (msg->len > 1) @@ -125,7 +125,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg if (retval == 0) goto eio; - if (i2c_debug) + if (i2c_debug) { if (!(ctrl & I2C_NOSTOP)) printk(" >\n"); @@ -152,14 +152,14 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg if (retval == 0) goto eio; - if (i2c_debug) + if (i2c_debug) { dprintk(1, " %02x", msg->buf[cnt]); if (!(ctrl & I2C_NOSTOP)) dprintk(1, " >\n"); } } - + return msg->len; eio: @@ -244,18 +244,18 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) dprintk(1, "%s(num = %d)\n", __func__, num); - for (i = 0 ; i < num; i++) + for (i = 0 ; i < num; i++) { dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n", __func__, num, msgs[i].addr, msgs[i].len); - if (msgs[i].flags & I2C_M_RD) + if (msgs[i].flags & I2C_M_RD) { /* read */ retval = i2c_readbytes(i2c_adap, &msgs[i], 0); - } + } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && - msgs[i].addr == msgs[i + 1].addr) + msgs[i].addr == msgs[i + 1].addr) { /* write then read from same address */ retval = i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len); @@ -264,13 +264,13 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) goto err; i++; retval = i2c_readbytes(i2c_adap, &msgs[i], 1); - } - else + } + else { /* write */ retval = i2c_sendbytes(i2c_adap, &msgs[i], 0); } - + if (retval < 0) goto err; } @@ -300,7 +300,7 @@ static int attach_inform(struct i2c_client *client) } - printk(KERN_INFO "attach done!\n"); + printk(KERN_INFO "attach done!\n"); return 0; } @@ -325,9 +325,9 @@ void cx25821_call_i2c_clients(struct cx25821_i2c *bus, unsigned int cmd, void *a static u32 cx25821_functionality(struct i2c_adapter *adap) { - return I2C_FUNC_SMBUS_EMUL | + return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | - I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA; } @@ -382,7 +382,7 @@ int cx25821_i2c_register(struct cx25821_i2c *bus) //set up the I2c bus->i2c_client.addr = (0x88>>1); - + return bus->i2c_rc; } @@ -423,19 +423,19 @@ int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value) int v = 0; u8 addr[2] = {0, 0}; u8 buf[4] = {0,0,0,0}; - + struct i2c_msg msgs[2]={ - { - .addr = client->addr, - .flags = 0, - .len = 2, - .buf = addr, - }, { - .addr = client->addr, - .flags = I2C_M_RD, - .len = 4, - .buf = buf, - } + { + .addr = client->addr, + .flags = 0, + .len = 2, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 4, + .buf = buf, + } }; @@ -449,23 +449,23 @@ int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value) v = (buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0]; *value = v; - return v; + return v; } int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value) { struct i2c_client *client = &bus->i2c_client; - int retval = 0; + int retval = 0; u8 buf[6] = {0, 0, 0, 0, 0, 0}; struct i2c_msg msgs[1]={ - { - .addr = client->addr, - .flags = 0, - .len = 6, - .buf = buf, - } + { + .addr = client->addr, + .flags = 0, + .len = 6, + .buf = buf, + } }; diff --git a/linux/drivers/staging/cx25821/cx25821-medusa-video.c b/linux/drivers/staging/cx25821/cx25821-medusa-video.c index 6225f1079..84c68b3c5 100644 --- a/linux/drivers/staging/cx25821/cx25821-medusa-video.c +++ b/linux/drivers/staging/cx25821/cx25821-medusa-video.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * * This program is free software; you can redistribute it and/or modify @@ -38,52 +38,52 @@ static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel, int out_ctrl = OUT_CTRL1; int out_ctrl_ns = OUT_CTRL_NS; - + switch (channel) { - default: - case VDEC_A: - break; - case VDEC_B: - out_ctrl = VDEC_B_OUT_CTRL1; - out_ctrl_ns = VDEC_B_OUT_CTRL_NS; - break; - case VDEC_C: - out_ctrl = VDEC_C_OUT_CTRL1; - out_ctrl_ns = VDEC_C_OUT_CTRL_NS; - break; - case VDEC_D: - out_ctrl = VDEC_D_OUT_CTRL1; - out_ctrl_ns = VDEC_D_OUT_CTRL_NS; - break; - case VDEC_E: - out_ctrl = VDEC_E_OUT_CTRL1; - out_ctrl_ns = VDEC_E_OUT_CTRL_NS; - return; - case VDEC_F: - out_ctrl = VDEC_F_OUT_CTRL1; - out_ctrl_ns = VDEC_F_OUT_CTRL_NS; - return; - case VDEC_G: - out_ctrl = VDEC_G_OUT_CTRL1; - out_ctrl_ns = VDEC_G_OUT_CTRL_NS; - return; - case VDEC_H: - out_ctrl = VDEC_H_OUT_CTRL1; - out_ctrl_ns = VDEC_H_OUT_CTRL_NS; - return; + default: + case VDEC_A: + break; + case VDEC_B: + out_ctrl = VDEC_B_OUT_CTRL1; + out_ctrl_ns = VDEC_B_OUT_CTRL_NS; + break; + case VDEC_C: + out_ctrl = VDEC_C_OUT_CTRL1; + out_ctrl_ns = VDEC_C_OUT_CTRL_NS; + break; + case VDEC_D: + out_ctrl = VDEC_D_OUT_CTRL1; + out_ctrl_ns = VDEC_D_OUT_CTRL_NS; + break; + case VDEC_E: + out_ctrl = VDEC_E_OUT_CTRL1; + out_ctrl_ns = VDEC_E_OUT_CTRL_NS; + return; + case VDEC_F: + out_ctrl = VDEC_F_OUT_CTRL1; + out_ctrl_ns = VDEC_F_OUT_CTRL_NS; + return; + case VDEC_G: + out_ctrl = VDEC_G_OUT_CTRL1; + out_ctrl_ns = VDEC_G_OUT_CTRL_NS; + return; + case VDEC_H: + out_ctrl = VDEC_H_OUT_CTRL1; + out_ctrl_ns = VDEC_H_OUT_CTRL_NS; + return; } value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp); value &= 0xFFFFFF7F; // clear BLUE_FIELD_EN if (enable) - value |= 0x00000080; // set BLUE_FIELD_EN + value |= 0x00000080; // set BLUE_FIELD_EN ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value); value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp); value &= 0xFFFFFF7F; if (enable) - value |= 0x00000080; // set BLUE_FIELD_EN + value |= 0x00000080; // set BLUE_FIELD_EN ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value); } @@ -97,93 +97,93 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) mutex_lock(&dev->lock); - + for (i=0; i < MAX_DECODERS; i++) { - // set video format NTSC-M - value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp); - value &= 0xFFFFFFF0; - value |= 0x10001; // enable the fast locking mode bit[16] - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value); - - // resolution NTSC 720x480 - value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp); - value &= 0x00C00C00; - value |= 0x612D0074; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value); - - value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp); - value &= 0x00C00C00; - value |= 0x1C1E001A; // vblank_cnt + 2 to get camera ID - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value); - - // chroma subcarrier step size - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x43E00000); - - // enable VIP optional active - value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp); - value &= 0xFFFBFFFF; - value |= 0x00040000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value); - - // enable VIP optional active (VIP_OPT_AL) for direct output. - value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp); - value &= 0xFFFBFFFF; - value |= 0x00040000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value); - - // clear VPRES_VERT_EN bit, fixes the chroma run away problem - // when the input switching rate < 16 fields - // - value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp); - value = setBitAtPos(value, 14); // disable special play detection - value = clearBitAtPos(value, 15); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value); - - // set vbi_gate_en to 0 - value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp); - value = clearBitAtPos(value, 29); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value); - - // Enable the generation of blue field output if no video - medusa_enable_bluefield_output(dev, i, 1); + // set video format NTSC-M + value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp); + value &= 0xFFFFFFF0; + value |= 0x10001; // enable the fast locking mode bit[16] + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value); + + // resolution NTSC 720x480 + value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp); + value &= 0x00C00C00; + value |= 0x612D0074; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value); + + value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp); + value &= 0x00C00C00; + value |= 0x1C1E001A; // vblank_cnt + 2 to get camera ID + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value); + + // chroma subcarrier step size + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x43E00000); + + // enable VIP optional active + value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value); + + // enable VIP optional active (VIP_OPT_AL) for direct output. + value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value); + + // clear VPRES_VERT_EN bit, fixes the chroma run away problem + // when the input switching rate < 16 fields + // + value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp); + value = setBitAtPos(value, 14); // disable special play detection + value = clearBitAtPos(value, 15); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value); + + // set vbi_gate_en to 0 + value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp); + value = clearBitAtPos(value, 29); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value); + + // Enable the generation of blue field output if no video + medusa_enable_bluefield_output(dev, i, 1); } for (i=0; i < MAX_ENCODERS; i++) { - // NTSC hclock - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp); - value &= 0xF000FC00; - value |= 0x06B402D0; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value); - - // burst begin and burst end - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp); - value &= 0xFF000000; - value |= 0x007E9054; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value); - - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp); - value &= 0xFC00FE00; - value |= 0x00EC00F0; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value); - - // set NTSC vblank, no phase alternation, 7.5 IRE pedestal - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp); - value &= 0x00FCFFFF; - value |= 0x13020000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value); - - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp); - value &= 0xFFFF0000; - value |= 0x0000E575; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value); - - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x009A89C1); - - // Subcarrier Increment - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x21F07C1F); + // NTSC hclock + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp); + value &= 0xF000FC00; + value |= 0x06B402D0; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value); + + // burst begin and burst end + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp); + value &= 0xFF000000; + value |= 0x007E9054; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value); + + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp); + value &= 0xFC00FE00; + value |= 0x00EC00F0; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value); + + // set NTSC vblank, no phase alternation, 7.5 IRE pedestal + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp); + value &= 0x00FCFFFF; + value |= 0x13020000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value); + + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp); + value &= 0xFFFF0000; + value |= 0x0000E575; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value); + + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x009A89C1); + + // Subcarrier Increment + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x21F07C1F); } @@ -206,23 +206,23 @@ static int medusa_PALCombInit(struct cx25821_dev *dev, int dec) { int ret_val = -1; u32 value = 0, tmp = 0; - + // Setup for 2D threshold ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG+(0x200*dec), 0x20002861); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG+(0x200*dec), 0x20002861); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG+(0x200*dec), 0x200A1023); - - // Setup flat chroma and luma thresholds + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG+(0x200*dec), 0x20002861); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG+(0x200*dec), 0x200A1023); + + // Setup flat chroma and luma thresholds value = cx25821_i2c_read(&dev->i2c_bus[0], COMB_FLAT_THRESH_CTRL+(0x200*dec), &tmp); - value &= 0x06230000; + value &= 0x06230000; ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_FLAT_THRESH_CTRL+(0x200*dec), value); - - // set comb 2D blend + + // set comb 2D blend ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND+(0x200*dec), 0x210F0F0F); - - // COMB MISC CONTROL + + // COMB MISC CONTROL ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL+(0x200*dec), 0x41120A7F); - + return ret_val; } @@ -235,110 +235,110 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) u32 tmp = 0; mutex_lock(&dev->lock); - + for (i=0; i < MAX_DECODERS; i++) { - // set video format PAL-BDGHI - value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp); - value &= 0xFFFFFFF0; - value |= 0x10004; // enable the fast locking mode bit[16] - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value); - - - // resolution PAL 720x576 - value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp); - value &= 0x00C00C00; - value |= 0x632D007D; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value); - - // vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 - value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp); - value &= 0x00C00C00; - value |= 0x28240026; // vblank_cnt + 2 to get camera ID - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value); - - // chroma subcarrier step size - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x5411E2D0); - - // enable VIP optional active - value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp); - value &= 0xFFFBFFFF; - value |= 0x00040000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value); - - // enable VIP optional active (VIP_OPT_AL) for direct output. - value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp); - value &= 0xFFFBFFFF; - value |= 0x00040000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value); - - // clear VPRES_VERT_EN bit, fixes the chroma run away problem - // when the input switching rate < 16 fields - value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp); - value = setBitAtPos(value, 14); // disable special play detection - value = clearBitAtPos(value, 15); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value); - - // set vbi_gate_en to 0 - value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp); - value = clearBitAtPos(value, 29); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value); - - medusa_PALCombInit(dev, i); - - // Enable the generation of blue field output if no video - medusa_enable_bluefield_output(dev, i, 1); - } - - - for (i=0; i < MAX_ENCODERS; i++) - { - // PAL hclock - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp); - value &= 0xF000FC00; - value |= 0x06C002D0; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value); - - // burst begin and burst end - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp); - value &= 0xFF000000; - value |= 0x007E9754; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value); - - // hblank and vactive - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp); - value &= 0xFC00FE00; - value |= 0x00FC0120; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value); - - // set PAL vblank, phase alternation, 0 IRE pedestal - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp); - value &= 0x00FCFFFF; - value |= 0x14010000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value); - - - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp); - value &= 0xFFFF0000; - value |= 0x0000F078; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value); - - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x00A493CF); - - // Subcarrier Increment - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x2A098ACB); - } - - - //set picture resolutions + // set video format PAL-BDGHI + value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp); + value &= 0xFFFFFFF0; + value |= 0x10004; // enable the fast locking mode bit[16] + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value); + + + // resolution PAL 720x576 + value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp); + value &= 0x00C00C00; + value |= 0x632D007D; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value); + + // vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 + value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp); + value &= 0x00C00C00; + value |= 0x28240026; // vblank_cnt + 2 to get camera ID + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value); + + // chroma subcarrier step size + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x5411E2D0); + + // enable VIP optional active + value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value); + + // enable VIP optional active (VIP_OPT_AL) for direct output. + value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value); + + // clear VPRES_VERT_EN bit, fixes the chroma run away problem + // when the input switching rate < 16 fields + value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp); + value = setBitAtPos(value, 14); // disable special play detection + value = clearBitAtPos(value, 15); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value); + + // set vbi_gate_en to 0 + value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp); + value = clearBitAtPos(value, 29); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value); + + medusa_PALCombInit(dev, i); + + // Enable the generation of blue field output if no video + medusa_enable_bluefield_output(dev, i, 1); + } + + + for (i=0; i < MAX_ENCODERS; i++) + { + // PAL hclock + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp); + value &= 0xF000FC00; + value |= 0x06C002D0; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value); + + // burst begin and burst end + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp); + value &= 0xFF000000; + value |= 0x007E9754; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value); + + // hblank and vactive + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp); + value &= 0xFC00FE00; + value |= 0x00FC0120; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value); + + // set PAL vblank, phase alternation, 0 IRE pedestal + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp); + value &= 0x00FCFFFF; + value |= 0x14010000; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value); + + + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp); + value &= 0xFFFF0000; + value |= 0x0000F078; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value); + + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x00A493CF); + + // Subcarrier Increment + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x2A098ACB); + } + + + //set picture resolutions ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 576 - - // set Bypass input format to PAL 625 lines + + // set Bypass input format to PAL 625 lines value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); value &= 0xFFF7FDFF; ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); - + mutex_unlock(&dev->lock); return ret_val; @@ -350,26 +350,26 @@ int medusa_set_videostandard(struct cx25821_dev *dev) int status = STATUS_SUCCESS; u32 value = 0, tmp = 0; - + if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) { - status = medusa_initialize_pal(dev); + status = medusa_initialize_pal(dev); } else { - status = medusa_initialize_ntsc(dev); + status = medusa_initialize_ntsc(dev); } - + // Enable DENC_A output value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp); value = setBitAtPos(value, 4); status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value); - + // Enable DENC_B output value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp); value = setBitAtPos(value, 4); status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value); - + return status; } @@ -380,7 +380,7 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width, int decoder_selec int decoder_count = 0; int ret_val = 0; u32 hscale = 0x0; - u32 vscale = 0x0; + u32 vscale = 0x0; const int MAX_WIDTH = 720; mutex_lock(&dev->lock); @@ -388,55 +388,55 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width, int decoder_selec // validate the width - cannot be negative if (width > MAX_WIDTH) { - printk("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH \n", __func__, width, MAX_WIDTH); - width = MAX_WIDTH; - } - + printk("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH \n", __func__, width, MAX_WIDTH); + width = MAX_WIDTH; + } + if( decoder_select <= 7 && decoder_select >= 0 ) { - decoder = decoder_select; - decoder_count = decoder_select + 1; + decoder = decoder_select; + decoder_count = decoder_select + 1; } else { - decoder = 0; - decoder_count = _num_decoders; + decoder = 0; + decoder_count = _num_decoders; } - - - switch( width ) - { - case 320: - hscale = 0x13E34B; - vscale = 0x0; - break; - - case 352: - hscale = 0x10A273; - vscale = 0x0; - break; - - case 176: - hscale = 0x3115B2; - vscale = 0x1E00; - break; - case 160: - hscale = 0x378D84; - vscale = 0x1E00; - break; - default: //720 - hscale = 0x0; - vscale = 0x0; - break; - } + switch( width ) + { + case 320: + hscale = 0x13E34B; + vscale = 0x0; + break; + + case 352: + hscale = 0x10A273; + vscale = 0x0; + break; + + case 176: + hscale = 0x3115B2; + vscale = 0x1E00; + break; + + case 160: + hscale = 0x378D84; + vscale = 0x1E00; + break; + + default: //720 + hscale = 0x0; + vscale = 0x0; + break; + } for( ; decoder < decoder_count; decoder++) { - // write scaling values for each decoder - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL+(0x200*decoder), hscale); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL+(0x200*decoder), vscale); + // write scaling values for each decoder + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL+(0x200*decoder), hscale); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL+(0x200*decoder), vscale); } mutex_unlock(&dev->lock); @@ -448,52 +448,52 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, int u32 fld_cnt = 0; u32 tmp = 0; u32 disp_cnt_reg = DISP_AB_CNT; - + mutex_lock(&dev->lock); - // no support + // no support if (decoder < VDEC_A && decoder > VDEC_H) { - mutex_unlock(&dev->lock); - return; + mutex_unlock(&dev->lock); + return; } switch (decoder) { - default: - break; - case VDEC_C: - case VDEC_D: - disp_cnt_reg = DISP_CD_CNT; - break; - case VDEC_E: - case VDEC_F: - disp_cnt_reg = DISP_EF_CNT; - break; - case VDEC_G: - case VDEC_H: - disp_cnt_reg = DISP_GH_CNT; - break; + default: + break; + case VDEC_C: + case VDEC_D: + disp_cnt_reg = DISP_CD_CNT; + break; + case VDEC_E: + case VDEC_F: + disp_cnt_reg = DISP_EF_CNT; + break; + case VDEC_G: + case VDEC_H: + disp_cnt_reg = DISP_GH_CNT; + break; } _display_field_cnt[decoder] = duration; // update hardware fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp); - + if (!(decoder % 2)) // EVEN decoder { - fld_cnt &= 0xFFFF0000; - fld_cnt |= duration; + fld_cnt &= 0xFFFF0000; + fld_cnt |= duration; } else { - fld_cnt &= 0x0000FFFF; - fld_cnt |= ((u32)duration) << 16; + fld_cnt &= 0x0000FFFF; + fld_cnt |= ((u32)duration) << 16; } ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt); - + mutex_unlock(&dev->lock); } @@ -514,7 +514,7 @@ static int mapM( if((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax)) { - return -1; + return -1; } // This is the overall expression used: @@ -527,7 +527,7 @@ static int mapM( if(2 * ( numerator % denominator ) >= denominator) { - quotient++; + quotient++; } *dstVal = quotient + dstMin; @@ -540,12 +540,12 @@ static unsigned long convert_to_twos(long numeric, unsigned long bits_len) unsigned char temp; if (numeric >= 0) - return numeric; + return numeric; else { - temp = ~(abs(numeric) & 0xFF); - temp += 1; - return temp; + temp = ~(abs(numeric) & 0xFF); + temp += 1; + return temp; } } ///////////////////////////////////////////////////////////////////////////////////////// @@ -558,8 +558,8 @@ int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) mutex_lock(&dev->lock); if((brightness > VIDEO_PROCAMP_MAX) || (brightness < VIDEO_PROCAMP_MIN)) { - mutex_unlock(&dev->lock); - return -1; + mutex_unlock(&dev->lock); + return -1; } ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); value = convert_to_twos(value, 8); @@ -578,11 +578,11 @@ int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) u32 val = 0, tmp = 0; mutex_lock(&dev->lock); - + if((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) { - mutex_unlock(&dev->lock); - return -1; + mutex_unlock(&dev->lock); + return -1; } ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); @@ -602,15 +602,15 @@ int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) u32 val = 0, tmp = 0; mutex_lock(&dev->lock); - + if((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) { - mutex_unlock(&dev->lock); - return -1; + mutex_unlock(&dev->lock); + return -1; } ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); - + value = convert_to_twos(value, 8); val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_HUE_CTRL+(0x200*decoder), &tmp); val &= 0xFFFFFF00; @@ -628,25 +628,25 @@ int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) int ret_val = 0; int value = 0; u32 val = 0, tmp = 0; - + mutex_lock(&dev->lock); - + if((saturation > VIDEO_PROCAMP_MAX) || (saturation < VIDEO_PROCAMP_MIN)) { - mutex_unlock(&dev->lock); - return -1; + mutex_unlock(&dev->lock); + return -1; } ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); - + val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_USAT_CTRL+(0x200*decoder), &tmp); - val &= 0xFFFFFF00; + val &= 0xFFFFFF00; ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_USAT_CTRL+(0x200*decoder), val | value); val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_VSAT_CTRL+(0x200*decoder), &tmp); - val &= 0xFFFFFF00; + val &= 0xFFFFFF00; ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_VSAT_CTRL+(0x200*decoder), val | value); - + mutex_unlock(&dev->lock); return ret_val; } @@ -660,75 +660,75 @@ int medusa_video_init(struct cx25821_dev *dev) u32 value = 0, tmp = 0; int ret_val = 0; int i=0; - + mutex_lock(&dev->lock); - + _num_decoders = dev->_max_num_decoders; - - - // disable Auto source selection on all video decoders + + + // disable Auto source selection on all video decoders value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); value &= 0xFFFFF0FF; ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); - + if (ret_val < 0) { - mutex_unlock(&dev->lock); - return -EINVAL; + mutex_unlock(&dev->lock); + return -EINVAL; } - + // Turn off Master source switch enable value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); value &= 0xFFFFFFDF; ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); - + if (ret_val < 0) { - mutex_unlock(&dev->lock); - return -EINVAL; + mutex_unlock(&dev->lock); + return -EINVAL; } mutex_unlock(&dev->lock); for (i=0; i < _num_decoders; i++) { - medusa_set_decoderduration(dev, i, _display_field_cnt[i]); + medusa_set_decoderduration(dev, i, _display_field_cnt[i]); } - + mutex_lock(&dev->lock); - // Select monitor as DENC A input, power up the DAC + // Select monitor as DENC A input, power up the DAC value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp); value &= 0xFF70FF70; - value |= 0x00090008; // set en_active + value |= 0x00090008; // set en_active ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value); - + if (ret_val < 0) { - mutex_unlock(&dev->lock); - return -EINVAL; + mutex_unlock(&dev->lock); + return -EINVAL; } // enable input is VIP/656 value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); value |= 0x00040100; // enable VIP ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); - + if (ret_val < 0) { - mutex_unlock(&dev->lock); - return -EINVAL; + mutex_unlock(&dev->lock); + return -EINVAL; } - // select AFE clock to output mode + // select AFE clock to output mode value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); value &= 0x83FFFFFF; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, value | 0x10000000); - + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, value | 0x10000000); + if (ret_val < 0) { - mutex_unlock(&dev->lock); - return -EINVAL; + mutex_unlock(&dev->lock); + return -EINVAL; } // Turn on all of the data out and control output pins. @@ -736,34 +736,34 @@ int medusa_video_init(struct cx25821_dev *dev) value &= 0xFEF0FE00; if (_num_decoders == MAX_DECODERS) { - // Note: The octal board does not support control pins(bit16-19). - // These bits are ignored in the octal board. - value |= 0x010001F8; // disable VDEC A-C port, default to Mobilygen Interface + // Note: The octal board does not support control pins(bit16-19). + // These bits are ignored in the octal board. + value |= 0x010001F8; // disable VDEC A-C port, default to Mobilygen Interface } else { - value |= 0x010F0108; // disable VDEC A-C port, default to Mobilygen Interface + value |= 0x010F0108; // disable VDEC A-C port, default to Mobilygen Interface } - + value |= 7; ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value); if (ret_val < 0) { - mutex_unlock(&dev->lock); - return -EINVAL; + mutex_unlock(&dev->lock); + return -EINVAL; } mutex_unlock(&dev->lock); - + ret_val = medusa_set_videostandard(dev); - + if (ret_val < 0) { - mutex_unlock(&dev->lock); - return -EINVAL; - } - + mutex_unlock(&dev->lock); + return -EINVAL; + } + return 1; } diff --git a/linux/drivers/staging/cx25821/cx25821-medusa-video.h b/linux/drivers/staging/cx25821/cx25821-medusa-video.h index 3651b23c0..92fcd7a7b 100644 --- a/linux/drivers/staging/cx25821/cx25821-medusa-video.h +++ b/linux/drivers/staging/cx25821/cx25821-medusa-video.h @@ -26,7 +26,7 @@ #include "cx25821-medusa-defines.h" -// Color control constants +// Color control constants #define VIDEO_PROCAMP_MIN 0 #define VIDEO_PROCAMP_MAX 10000 #define UNSIGNED_BYTE_MIN 0 diff --git a/linux/drivers/staging/cx25821/cx25821-reg.h b/linux/drivers/staging/cx25821/cx25821-reg.h index 82f4f16b8..3d9812465 100644 --- a/linux/drivers/staging/cx25821/cx25821-reg.h +++ b/linux/drivers/staging/cx25821/cx25821-reg.h @@ -1481,7 +1481,7 @@ //***************************************************************************** #define I2C1_ADDR 0x180000 // I2C #1 address #define FLD_I2C_DADDR 0xfe000000 // RW [31:25] I2C Device Address - // RO [24] reserved + // RO [24] reserved //***************************************************************************** #define FLD_I2C_SADDR 0x00FFFFFF // RW [23:0] I2C Sub-address @@ -1494,15 +1494,15 @@ #define FLD_I2C_PERIOD 0xFF000000 // RW [31:24] #define FLD_I2C_SCL_IN 0x00200000 // RW [21] #define FLD_I2C_SDA_IN 0x00100000 // RW [20] - // RO [19:18] reserved + // RO [19:18] reserved #define FLD_I2C_SCL_OUT 0x00020000 // RW [17] #define FLD_I2C_SDA_OUT 0x00010000 // RW [16] - // RO [15] reserved + // RO [15] reserved #define FLD_I2C_DATA_LEN 0x00007000 // RW [14:12] #define FLD_I2C_SADDR_INC 0x00000800 // RW [11] - // RO [10:9] reserved + // RO [10:9] reserved #define FLD_I2C_SADDR_LEN 0x00000300 // RW [9:8] - // RO [7:6] reserved + // RO [7:6] reserved #define FLD_I2C_SOFT 0x00000020 // RW [5] #define FLD_I2C_NOSTOP 0x00000010 // RW [4] #define FLD_I2C_EXTEND 0x00000008 // RW [3] @@ -1588,13 +1588,13 @@ //***************************************************************************** // Motion Detection -#define MD_CH0_GRID_BLOCK_YCNT 0x170014 -#define MD_CH1_GRID_BLOCK_YCNT 0x170094 -#define MD_CH2_GRID_BLOCK_YCNT 0x170114 -#define MD_CH3_GRID_BLOCK_YCNT 0x170194 -#define MD_CH4_GRID_BLOCK_YCNT 0x170214 -#define MD_CH5_GRID_BLOCK_YCNT 0x170294 -#define MD_CH6_GRID_BLOCK_YCNT 0x170314 +#define MD_CH0_GRID_BLOCK_YCNT 0x170014 +#define MD_CH1_GRID_BLOCK_YCNT 0x170094 +#define MD_CH2_GRID_BLOCK_YCNT 0x170114 +#define MD_CH3_GRID_BLOCK_YCNT 0x170194 +#define MD_CH4_GRID_BLOCK_YCNT 0x170214 +#define MD_CH5_GRID_BLOCK_YCNT 0x170294 +#define MD_CH6_GRID_BLOCK_YCNT 0x170314 #define MD_CH7_GRID_BLOCK_YCNT 0x170394 #define PIXEL_FRMT_422 4 diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c index ca91b832b..720729efc 100644 --- a/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c @@ -44,97 +44,97 @@ static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | F static __le32 *cx25821_update_riscprogram_ch2( struct cx25821_dev *dev, - __le32 *rp, unsigned int offset, unsigned int bpl, - u32 sync_line, unsigned int lines, int fifo_enable, int field_type) + __le32 *rp, unsigned int offset, unsigned int bpl, + u32 sync_line, unsigned int lines, int fifo_enable, int field_type) { unsigned int line, i; int dist_betwn_starts = bpl * 2; - + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); if( USE_RISC_NOOP_VIDEO ) { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } } /* scan lines */ for (line = 0; line < lines; line++) { - *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) ) - { - offset += dist_betwn_starts; - } + *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); + *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) ) + { + offset += dist_betwn_starts; + } } return rp; } static __le32 *cx25821_risc_field_upstream_ch2( struct cx25821_dev *dev, - __le32 *rp, - dma_addr_t databuf_phys_addr, - unsigned int offset, u32 sync_line, unsigned int bpl, - unsigned int lines, int fifo_enable, int field_type) + __le32 *rp, + dma_addr_t databuf_phys_addr, + unsigned int offset, u32 sync_line, unsigned int bpl, + unsigned int lines, int fifo_enable, int field_type) { unsigned int line, i; struct sram_channel *sram_ch = &dev->sram_channels[dev->_channel2_upstream_select]; int dist_betwn_starts = bpl * 2; - + /* sync instruction */ if (sync_line != NO_SYNC_LINE) { - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); } if( USE_RISC_NOOP_VIDEO ) { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } } /* scan lines */ for (line = 0; line < lines; line++) { - *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(databuf_phys_addr+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - - if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) ) - { - offset += dist_betwn_starts; - } - - - // check if we need to enable the FIFO after the first 4 lines - // For the upstream video channel, the risc engine will enable the FIFO. - if ( fifo_enable && line == 3 ) - { - *(rp++) = RISC_WRITECR; - *(rp++) = sram_ch->dma_ctl; - *(rp++) = FLD_VID_FIFO_EN; - *(rp++) = 0x00000001; - } - } - + *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); + *(rp++) = cpu_to_le32(databuf_phys_addr+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + + if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) ) + { + offset += dist_betwn_starts; + } + + + // check if we need to enable the FIFO after the first 4 lines + // For the upstream video channel, the risc engine will enable the FIFO. + if ( fifo_enable && line == 3 ) + { + *(rp++) = RISC_WRITECR; + *(rp++) = sram_ch->dma_ctl; + *(rp++) = FLD_VID_FIFO_EN; + *(rp++) = 0x00000001; + } + } + return rp; } int cx25821_risc_buffer_upstream_ch2( struct cx25821_dev *dev, struct pci_dev *pci, - unsigned int top_offset, - unsigned int bpl, unsigned int lines) + unsigned int top_offset, + unsigned int bpl, unsigned int lines) { __le32 *rp; int fifo_enable = 0; @@ -148,57 +148,57 @@ int cx25821_risc_buffer_upstream_ch2( struct cx25821_dev *dev, struct pci_dev *p unsigned int bottom_offset = bpl; dma_addr_t risc_phys_jump_addr; - + if( dev->_isNTSC_ch2 ) { - odd_num_lines = singlefield_lines + 1; - risc_program_size = FRAME1_VID_PROG_SIZE; - frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; + odd_num_lines = singlefield_lines + 1; + risc_program_size = FRAME1_VID_PROG_SIZE; + frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; } else { - risc_program_size = PAL_VID_PROG_SIZE; - frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + risc_program_size = PAL_VID_PROG_SIZE; + frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; } - + /* Virtual address of Risc buffer program */ rp = dev->_dma_virt_addr_ch2; for( frame = 0; frame < NUM_FRAMES; frame++ ) { - databuf_offset = frame_size * frame; - - - if (UNSET != top_offset) - { - fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; - rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD); - } - - fifo_enable = FIFO_DISABLE; - - - //Even field - rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD); - - - if( frame == 0 ) - { - risc_flag = RISC_CNT_RESET; - risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + risc_program_size; - } - else - { - risc_flag = RISC_CNT_INC; - risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2; - } - - - // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ - *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); + databuf_offset = frame_size * frame; + + + if (UNSET != top_offset) + { + fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; + rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD); + } + + fifo_enable = FIFO_DISABLE; + + + //Even field + rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD); + + + if( frame == 0 ) + { + risc_flag = RISC_CNT_RESET; + risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + risc_program_size; + } + else + { + risc_flag = RISC_CNT_INC; + risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2; + } + + + // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ + *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); } return 0; @@ -212,8 +212,8 @@ void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) if( !dev->_is_running_ch2 ) { - printk("cx25821: No video file is currently running so return!\n"); - return; + printk("cx25821: No video file is currently running so return!\n"); + return; } //Disable RISC interrupts @@ -226,8 +226,8 @@ void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) //Clear data buffer memory if( dev->_data_buf_virt_addr_ch2 ) - memset( dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2 ); - + memset( dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2 ); + dev->_is_running_ch2 = 0; dev->_is_first_frame_ch2 = 0; dev->_frame_count_ch2 = 0; @@ -235,12 +235,12 @@ void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) if( dev->_irq_queues_ch2 ) { - kfree(dev->_irq_queues_ch2); - dev->_irq_queues_ch2 = NULL; + kfree(dev->_irq_queues_ch2); + dev->_irq_queues_ch2 = NULL; } if( dev->_filename_ch2 != NULL ) - kfree(dev->_filename_ch2); + kfree(dev->_filename_ch2); tmp = cx_read( VID_CH_MODE_SEL ); cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); @@ -250,19 +250,19 @@ void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev) { if( dev->_is_running_ch2 ) { - cx25821_stop_upstream_video_ch2(dev); + cx25821_stop_upstream_video_ch2(dev); } if (dev->_dma_virt_addr_ch2) { - pci_free_consistent(dev->pci, dev->_risc_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2); - dev->_dma_virt_addr_ch2 = NULL; + pci_free_consistent(dev->pci, dev->_risc_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2); + dev->_dma_virt_addr_ch2 = NULL; } if (dev->_data_buf_virt_addr_ch2) { - pci_free_consistent(dev->pci, dev->_data_buf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2); - dev->_data_buf_virt_addr_ch2 = NULL; + pci_free_consistent(dev->pci, dev->_data_buf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2); + dev->_data_buf_virt_addr_ch2 = NULL; } } @@ -280,84 +280,84 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch loff_t file_offset; loff_t pos; mm_segment_t old_fs; - + if( dev->_file_status_ch2 == END_OF_FILE ) - return 0; - + return 0; + if( dev->_isNTSC_ch2 ) { - frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; + frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; } else { - frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; } frame_offset = (frame_index_temp > 0) ? frame_size : 0; file_offset = dev->_frame_count_ch2 * frame_size; - + myfile = filp_open( dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0 ); if (IS_ERR(myfile)) { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno); - return PTR_ERR(myfile); + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno); + return PTR_ERR(myfile); } else { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( i = 0; i < dev->_lines_count_ch2; i++ ) - { - pos = file_offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL ) - { - memcpy( (void*)(dev->_data_buf_virt_addr_ch2+frame_offset/4), mybuf, vfs_read_retval); - } - - file_offset += vfs_read_retval; - frame_offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - dev->_frame_count_ch2++; - - dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - - set_fs(old_fs); - filp_close(myfile, NULL); + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( i = 0; i < dev->_lines_count_ch2; i++ ) + { + pos = file_offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL ) + { + memcpy( (void*)(dev->_data_buf_virt_addr_ch2+frame_offset/4), mybuf, vfs_read_retval); + } + + file_offset += vfs_read_retval; + frame_offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + dev->_frame_count_ch2++; + + dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + + set_fs(old_fs); + filp_close(myfile, NULL); } return 0; @@ -369,8 +369,8 @@ static void cx25821_vidups_handler_ch2(struct work_struct *work) if( !dev ) { - printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); - return; + printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); + return; } cx25821_get_frame_ch2( dev, &dev->sram_channels[dev->_channel2_upstream_select] ); @@ -387,76 +387,76 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) loff_t pos; loff_t offset = (unsigned long)0; mm_segment_t old_fs; - + myfile = filp_open( dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0 ); if (IS_ERR(myfile)) { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno); - return PTR_ERR(myfile); + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno); + return PTR_ERR(myfile); } else { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered! Returning.", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( j = 0; j < NUM_FRAMES; j++ ) - { - for( i = 0; i < dev->_lines_count_ch2; i++ ) - { - pos = offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL ) - { - memcpy( (void*)(dev->_data_buf_virt_addr_ch2+offset/4), mybuf, vfs_read_retval); - } - - - offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - dev->_frame_count_ch2++; - - if( vfs_read_retval < line_size ) - { - break; - } - } - - dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - set_fs(old_fs); - myfile->f_pos = 0; - filp_close(myfile, NULL); + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered! Returning.", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( j = 0; j < NUM_FRAMES; j++ ) + { + for( i = 0; i < dev->_lines_count_ch2; i++ ) + { + pos = offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL ) + { + memcpy( (void*)(dev->_data_buf_virt_addr_ch2+offset/4), mybuf, vfs_read_retval); + } + + + offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + dev->_frame_count_ch2++; + + if( vfs_read_retval < line_size ) + { + break; + } + } + + dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + myfile->f_pos = 0; + filp_close(myfile, NULL); } return 0; @@ -464,17 +464,17 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, - struct sram_channel *sram_ch, - int bpl) + struct sram_channel *sram_ch, + int bpl) { int ret = 0; dma_addr_t dma_addr; dma_addr_t data_dma_addr; - + if( dev->_dma_virt_addr_ch2 != NULL ) { - pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2); + pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2); } dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, &dma_addr); @@ -486,8 +486,8 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, if (!dev->_dma_virt_addr_ch2) { - printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); - return -ENOMEM; + printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); + return -ENOMEM; } @@ -497,7 +497,7 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, if( dev->_data_buf_virt_addr_ch2 != NULL ) { - pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2); + pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2); } //For Video Data buffer allocation @@ -507,8 +507,8 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, if (!dev->_data_buf_virt_addr_ch2) { - printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); - return -ENOMEM; + printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); + return -ENOMEM; } @@ -518,15 +518,15 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, ret = cx25821_openfile_ch2(dev, sram_ch); if( ret < 0 ) - return ret; - + return ret; + //Creating RISC programs ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl, dev->_lines_count_ch2 ); if (ret < 0) { - printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n"); - goto error; + printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n"); + goto error; } return 0; @@ -549,59 +549,59 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, u32 st if (status & FLD_VID_SRC_RISC1) { - // We should only process one program per call - u32 prog_cnt = cx_read( channel->gpcnt ); - - //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers - int_msk_tmp = cx_read(channel->int_msk); - cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); - cx_write( channel->int_stat, _intr_msk ); - - spin_lock(&dev->slock); - - dev->_frame_index_ch2 = prog_cnt; - - queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2); - - - if ( dev->_is_first_frame_ch2 ) - { - dev->_is_first_frame_ch2 = 0; - - if( dev->_isNTSC_ch2 ) - { - singlefield_lines += 1; - odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; - } - else - { - singlefield_lines = PAL_FIELD_HEIGHT; - odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; - } - - - if( dev->_dma_virt_start_addr_ch2 != NULL ) - { - line_size_in_bytes = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; - risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + odd_risc_prog_size; - - rp = cx25821_update_riscprogram_ch2(dev, dev->_dma_virt_start_addr_ch2, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD); - - // Jump to Even Risc program of 1st Frame - *(rp++) = cpu_to_le32(RISC_JUMP); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - } - } - - spin_unlock(&dev->slock); - } - - + // We should only process one program per call + u32 prog_cnt = cx_read( channel->gpcnt ); + + //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers + int_msk_tmp = cx_read(channel->int_msk); + cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); + cx_write( channel->int_stat, _intr_msk ); + + spin_lock(&dev->slock); + + dev->_frame_index_ch2 = prog_cnt; + + queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2); + + + if ( dev->_is_first_frame_ch2 ) + { + dev->_is_first_frame_ch2 = 0; + + if( dev->_isNTSC_ch2 ) + { + singlefield_lines += 1; + odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; + } + else + { + singlefield_lines = PAL_FIELD_HEIGHT; + odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; + } + + + if( dev->_dma_virt_start_addr_ch2 != NULL ) + { + line_size_in_bytes = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + odd_risc_prog_size; + + rp = cx25821_update_riscprogram_ch2(dev, dev->_dma_virt_start_addr_ch2, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD); + + // Jump to Even Risc program of 1st Frame + *(rp++) = cpu_to_le32(RISC_JUMP); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + } + + spin_unlock(&dev->slock); + } + + if( dev->_file_status_ch2 == END_OF_FILE ) { - printk("cx25821: EOF Channel 2 Framecount = %d\n", dev->_frame_count_ch2 ); - return -1; + printk("cx25821: EOF Channel 2 Framecount = %d\n", dev->_frame_count_ch2 ); + return -1; } //ElSE, set the interrupt mask register, re-enable irq. @@ -621,10 +621,10 @@ static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) if( !dev ) - return -1; + return -1; channel_num = VID_UPSTREAM_SRAM_CHANNEL_J; - + sram_ch = &dev->sram_channels[channel_num]; msk_stat = cx_read(sram_ch->int_mstat); @@ -633,17 +633,17 @@ static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) // Only deal with our interrupt if(vid_status) { - handled = cx25821_video_upstream_irq_ch2(dev, channel_num, vid_status); + handled = cx25821_video_upstream_irq_ch2(dev, channel_num, vid_status); } if( handled < 0 ) { - cx25821_stop_upstream_video_ch2(dev); + cx25821_stop_upstream_video_ch2(dev); } else { - handled += handled; + handled += handled; } return IRQ_RETVAL(handled); @@ -658,7 +658,7 @@ static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, struct sram_cha u32 value; int vip_mode = PIXEL_ENGINE_VIP1; - + value = ( (pix_format & 0x3) << 12 ) | ( vip_mode & 0x7 ); value &= 0xFFFFFFEF; value |= dev->_isNTSC_ch2 ? 0 : 0x10; @@ -672,7 +672,7 @@ static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, struct sram_cha if(dev->_isNTSC_ch2) { - odd_num_lines += 1; + odd_num_lines += 1; } value = (num_lines << 16) | odd_num_lines; @@ -685,7 +685,7 @@ static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, struct sram_cha int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, - struct sram_channel *sram_ch) + struct sram_channel *sram_ch) { u32 tmp = 0; int err = 0; @@ -716,8 +716,8 @@ int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); if (err < 0) { - printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); - goto fail_irq; + printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); + goto fail_irq; } // Start the DMA engine @@ -748,8 +748,8 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, in if( dev->_is_running_ch2 ) { - printk("Video Channel is still running so return!\n"); - return 0; + printk("Video Channel is still running so return!\n"); + return 0; } dev->_channel2_upstream_select = channel_select; @@ -761,15 +761,15 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, in if(!dev->_irq_queues_ch2) { - printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); - return -ENOMEM; + printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); + return -ENOMEM; } // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C tmp = cx_read( VID_CH_MODE_SEL ); cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); - + dev->_is_running_ch2 = 0; dev->_frame_count_ch2 = 0; dev->_file_status_ch2 = RESET_STATUS; @@ -779,43 +779,43 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, in data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; risc_buffer_size = dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; - + if( dev->input_filename_ch2 ) { - str_length = strlen(dev->input_filename_ch2); - dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_filename_ch2 ) - goto error; - - memcpy(dev->_filename_ch2, dev->input_filename_ch2, str_length + 1); + str_length = strlen(dev->input_filename_ch2); + dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_filename_ch2 ) + goto error; + + memcpy(dev->_filename_ch2, dev->input_filename_ch2, str_length + 1); } else { - str_length = strlen(dev->_defaultname_ch2); - dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_filename_ch2 ) - goto error; - - memcpy(dev->_filename_ch2, dev->_defaultname_ch2, str_length + 1); + str_length = strlen(dev->_defaultname_ch2); + dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_filename_ch2 ) + goto error; + + memcpy(dev->_filename_ch2, dev->_defaultname_ch2, str_length + 1); } - + //Default if filename is empty string if( strcmp(dev->input_filename_ch2,"") == 0) { - if( dev->_isNTSC_ch2 ) - { - dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv"; - } - else - { - dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv"; - } - } - - + if( dev->_isNTSC_ch2 ) + { + dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv"; + } + else + { + dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv"; + } + } + + retval = cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size_ch2, 0); @@ -830,8 +830,8 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, in retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch, dev->_line_size_ch2); if (retval < 0) { - printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name); - goto error; + printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name); + goto error; } diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h index 4c5bd04fd..372d4e515 100644 --- a/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h @@ -72,25 +72,25 @@ #ifdef USE_RISC_NOOP_VIDEO #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - + RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + #define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - + JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + #define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) #endif @@ -98,11 +98,11 @@ #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) #define PAL_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE) ) #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) #define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) #endif diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream.c b/linux/drivers/staging/cx25821/cx25821-video-upstream.c index 14d204aaa..0f7a6c5bb 100644 --- a/linux/drivers/staging/cx25821/cx25821-video-upstream.c +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream.c @@ -43,19 +43,19 @@ MODULE_LICENSE("GPL"); static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, - struct sram_channel *ch, - unsigned int bpl, u32 risc) + struct sram_channel *ch, + unsigned int bpl, u32 risc) { unsigned int i, lines; u32 cdt; if (ch->cmds_start == 0) { - cx_write(ch->ptr1_reg, 0); - cx_write(ch->ptr2_reg, 0); - cx_write(ch->cnt2_reg, 0); - cx_write(ch->cnt1_reg, 0); - return 0; + cx_write(ch->ptr1_reg, 0); + cx_write(ch->ptr2_reg, 0); + cx_write(ch->cnt2_reg, 0); + cx_write(ch->cnt1_reg, 0); + return 0; } bpl = (bpl + 7) & ~7; /* alignment */ @@ -64,7 +64,7 @@ int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, if (lines > 4) { - lines = 4; + lines = 4; } BUG_ON(lines < 2); @@ -72,10 +72,10 @@ int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, /* write CDT */ for (i = 0; i < lines; i++) { - cx_write(cdt + 16*i, ch->fifo_start + bpl*i); - cx_write(cdt + 16*i + 4, 0); - cx_write(cdt + 16*i + 8, 0); - cx_write(cdt + 16*i + 12, 0); + cx_write(cdt + 16*i, ch->fifo_start + bpl*i); + cx_write(cdt + 16*i + 4, 0); + cx_write(cdt + 16*i + 8, 0); + cx_write(cdt + 16*i + 12, 0); } /* write CMDS */ @@ -85,12 +85,12 @@ int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, cx_write(ch->cmds_start + 8, cdt); cx_write(ch->cmds_start + 12, (lines*16) >> 3); cx_write(ch->cmds_start + 16, ch->ctrl_start); - + cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW); for (i = 24; i < 80; i += 4) - cx_write(ch->cmds_start + i, 0); + cx_write(ch->cmds_start + i, 0); /* fill registers */ cx_write(ch->ptr1_reg, ch->fifo_start); @@ -102,8 +102,8 @@ int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, } static __le32 *cx25821_update_riscprogram( struct cx25821_dev *dev, - __le32 *rp, unsigned int offset, unsigned int bpl, - u32 sync_line, unsigned int lines, int fifo_enable, int field_type) + __le32 *rp, unsigned int offset, unsigned int bpl, + u32 sync_line, unsigned int lines, int fifo_enable, int field_type) { unsigned int line, i; int dist_betwn_starts = bpl * 2; @@ -114,85 +114,85 @@ static __le32 *cx25821_update_riscprogram( struct cx25821_dev *dev, if( USE_RISC_NOOP_VIDEO ) { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } } /* scan lines */ for (line = 0; line < lines; line++) { - *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) ) - { - offset += dist_betwn_starts; - } + *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); + *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) ) + { + offset += dist_betwn_starts; + } } return rp; } static __le32 *cx25821_risc_field_upstream( struct cx25821_dev *dev, __le32 *rp, - dma_addr_t databuf_phys_addr, - unsigned int offset, u32 sync_line, - unsigned int bpl, unsigned int lines, int fifo_enable, int field_type) + dma_addr_t databuf_phys_addr, + unsigned int offset, u32 sync_line, + unsigned int bpl, unsigned int lines, int fifo_enable, int field_type) { unsigned int line, i; struct sram_channel *sram_ch = &dev->sram_channels[dev->_channel_upstream_select]; int dist_betwn_starts = bpl * 2; - + /* sync instruction */ if (sync_line != NO_SYNC_LINE) { - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); } if( USE_RISC_NOOP_VIDEO ) { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } + for( i = 0; i < NUM_NO_OPS; i++ ) + { + *(rp++) = cpu_to_le32(RISC_NOOP); + } } /* scan lines */ for (line = 0; line < lines; line++) { - *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(databuf_phys_addr+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - - if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) ) - { - offset += dist_betwn_starts; //to skip the other field line - } - - - // check if we need to enable the FIFO after the first 4 lines - // For the upstream video channel, the risc engine will enable the FIFO. - if ( fifo_enable && line == 3 ) - { - *(rp++) = RISC_WRITECR; - *(rp++) = sram_ch->dma_ctl; - *(rp++) = FLD_VID_FIFO_EN; - *(rp++) = 0x00000001; - } - } - + *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); + *(rp++) = cpu_to_le32(databuf_phys_addr+offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + + if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) ) + { + offset += dist_betwn_starts; //to skip the other field line + } + + + // check if we need to enable the FIFO after the first 4 lines + // For the upstream video channel, the risc engine will enable the FIFO. + if ( fifo_enable && line == 3 ) + { + *(rp++) = RISC_WRITECR; + *(rp++) = sram_ch->dma_ctl; + *(rp++) = FLD_VID_FIFO_EN; + *(rp++) = 0x00000001; + } + } + return rp; } int cx25821_risc_buffer_upstream( struct cx25821_dev *dev, - struct pci_dev *pci, - unsigned int top_offset, - unsigned int bpl, unsigned int lines) + struct pci_dev *pci, + unsigned int top_offset, + unsigned int bpl, unsigned int lines) { __le32 *rp; int fifo_enable = 0; @@ -205,57 +205,57 @@ int cx25821_risc_buffer_upstream( struct cx25821_dev *dev, int risc_flag = RISC_CNT_RESET; unsigned int bottom_offset = bpl; dma_addr_t risc_phys_jump_addr; - + if( dev->_isNTSC ) { - odd_num_lines = singlefield_lines + 1; - risc_program_size = FRAME1_VID_PROG_SIZE; - frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; + odd_num_lines = singlefield_lines + 1; + risc_program_size = FRAME1_VID_PROG_SIZE; + frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; } else { - risc_program_size = PAL_VID_PROG_SIZE; - frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + risc_program_size = PAL_VID_PROG_SIZE; + frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; } - + /* Virtual address of Risc buffer program */ rp = dev->_dma_virt_addr; for( frame = 0; frame < NUM_FRAMES; frame++ ) { - databuf_offset = frame_size * frame; - - if (UNSET != top_offset) - { - fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; - rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD); - } - - - fifo_enable = FIFO_DISABLE; - - - //Even Field - rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD); - - - if( frame == 0 ) - { - risc_flag = RISC_CNT_RESET; - risc_phys_jump_addr = dev->_dma_phys_start_addr + risc_program_size; - } - else - { - risc_phys_jump_addr = dev->_dma_phys_start_addr; - risc_flag = RISC_CNT_INC; - } - - - // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ - *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); + databuf_offset = frame_size * frame; + + if (UNSET != top_offset) + { + fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; + rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD); + } + + + fifo_enable = FIFO_DISABLE; + + + //Even Field + rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD); + + + if( frame == 0 ) + { + risc_flag = RISC_CNT_RESET; + risc_phys_jump_addr = dev->_dma_phys_start_addr + risc_program_size; + } + else + { + risc_phys_jump_addr = dev->_dma_phys_start_addr; + risc_flag = RISC_CNT_INC; + } + + + // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ + *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); } return 0; @@ -269,10 +269,10 @@ void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) if( !dev->_is_running ) { - printk("cx25821: No video file is currently running so return!\n"); - return; + printk("cx25821: No video file is currently running so return!\n"); + return; } - + //Disable RISC interrupts tmp = cx_read( sram_ch->int_msk ); cx_write( sram_ch->int_msk, tmp & ~_intr_msk); @@ -283,8 +283,8 @@ void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) //Clear data buffer memory if( dev->_data_buf_virt_addr ) - memset( dev->_data_buf_virt_addr, 0, dev->_data_buf_size ); - + memset( dev->_data_buf_virt_addr, 0, dev->_data_buf_size ); + dev->_is_running = 0; dev->_is_first_frame = 0; dev->_frame_count = 0; @@ -292,12 +292,12 @@ void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) if( dev->_irq_queues ) { - kfree(dev->_irq_queues); - dev->_irq_queues = NULL; + kfree(dev->_irq_queues); + dev->_irq_queues = NULL; } if( dev->_filename != NULL ) - kfree(dev->_filename); + kfree(dev->_filename); tmp = cx_read( VID_CH_MODE_SEL ); cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); @@ -307,19 +307,19 @@ void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev) { if( dev->_is_running ) { - cx25821_stop_upstream_video_ch1(dev); + cx25821_stop_upstream_video_ch1(dev); } if (dev->_dma_virt_addr) { - pci_free_consistent(dev->pci, dev->_risc_size, dev->_dma_virt_addr, dev->_dma_phys_addr); - dev->_dma_virt_addr = NULL; + pci_free_consistent(dev->pci, dev->_risc_size, dev->_dma_virt_addr, dev->_dma_phys_addr); + dev->_dma_virt_addr = NULL; } if (dev->_data_buf_virt_addr) { - pci_free_consistent(dev->pci, dev->_data_buf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr); - dev->_data_buf_virt_addr = NULL; + pci_free_consistent(dev->pci, dev->_data_buf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr); + dev->_data_buf_virt_addr = NULL; } } @@ -337,84 +337,84 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch ) loff_t file_offset; loff_t pos; mm_segment_t old_fs; - + if( dev->_file_status == END_OF_FILE ) - return 0; - + return 0; + if( dev->_isNTSC ) { - frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; + frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; } else { - frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; } frame_offset = (frame_index_temp > 0) ? frame_size : 0; file_offset = dev->_frame_count * frame_size; - + myfile = filp_open( dev->_filename, O_RDONLY | O_LARGEFILE, 0 ); if (IS_ERR(myfile)) { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno); - return PTR_ERR(myfile); + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno); + return PTR_ERR(myfile); } else { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( i = 0; i < dev->_lines_count; i++ ) - { - pos = file_offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL ) - { - memcpy( (void*)(dev->_data_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval); - } - - file_offset += vfs_read_retval; - frame_offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - dev->_frame_count++; - - dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - - set_fs(old_fs); - filp_close(myfile, NULL); + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( i = 0; i < dev->_lines_count; i++ ) + { + pos = file_offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL ) + { + memcpy( (void*)(dev->_data_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval); + } + + file_offset += vfs_read_retval; + frame_offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + dev->_frame_count++; + + dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + + set_fs(old_fs); + filp_close(myfile, NULL); } return 0; @@ -426,8 +426,8 @@ static void cx25821_vidups_handler(struct work_struct *work) if( !dev ) { - printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); - return; + printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); + return; } cx25821_get_frame( dev, &dev->sram_channels[dev->_channel_upstream_select] ); @@ -444,77 +444,77 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) loff_t pos; loff_t offset = (unsigned long)0; mm_segment_t old_fs; - + myfile = filp_open( dev->_filename, O_RDONLY | O_LARGEFILE, 0 ); if (IS_ERR(myfile)) { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno); - return PTR_ERR(myfile); + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno); + return PTR_ERR(myfile); } else { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered! Returning.", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( j = 0; j < NUM_FRAMES; j++ ) - { - for( i = 0; i < dev->_lines_count; i++ ) - { - pos = offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL ) - { - memcpy( (void*)(dev->_data_buf_virt_addr+offset/4), mybuf, vfs_read_retval); - } - - - offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - dev->_frame_count++; - - if( vfs_read_retval < line_size ) - { - break; - } - } - - - dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - set_fs(old_fs); - myfile->f_pos = 0; - filp_close(myfile, NULL); + if( !(myfile->f_op) ) + { + printk("%s: File has no file operations registered!", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + + if( !myfile->f_op->read ) + { + printk("%s: File has no READ operations registered! Returning.", __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + + for( j = 0; j < NUM_FRAMES; j++ ) + { + for( i = 0; i < dev->_lines_count; i++ ) + { + pos = offset; + + vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); + + if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL ) + { + memcpy( (void*)(dev->_data_buf_virt_addr+offset/4), mybuf, vfs_read_retval); + } + + + offset += vfs_read_retval; + + if( vfs_read_retval < line_size ) + { + printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); + break; + } + } + + if( i > 0 ) + dev->_frame_count++; + + if( vfs_read_retval < line_size ) + { + break; + } + } + + + dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + myfile->f_pos = 0; + filp_close(myfile, NULL); } return 0; @@ -522,8 +522,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, - struct sram_channel *sram_ch, - int bpl) + struct sram_channel *sram_ch, + int bpl) { int ret = 0; dma_addr_t dma_addr; @@ -531,7 +531,7 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, if( dev->_dma_virt_addr != NULL ) { - pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, dev->_dma_virt_addr, dev->_dma_phys_addr); + pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, dev->_dma_virt_addr, dev->_dma_phys_addr); } @@ -544,8 +544,8 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, if (!dev->_dma_virt_addr) { - printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); - return -ENOMEM; + printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); + return -ENOMEM; } @@ -555,7 +555,7 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, if( dev->_data_buf_virt_addr != NULL ) { - pci_free_consistent(dev->pci, dev->upstream_databuf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr); + pci_free_consistent(dev->pci, dev->upstream_databuf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr); } //For Video Data buffer allocation @@ -565,8 +565,8 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, if (!dev->_data_buf_virt_addr) { - printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); - return -ENOMEM; + printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); + return -ENOMEM; } @@ -576,15 +576,15 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, ret = cx25821_openfile(dev, sram_ch); if( ret < 0 ) - return ret; - + return ret; + //Create RISC programs ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, dev->_lines_count ); if (ret < 0) { - printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n"); - goto error; + printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n"); + goto error; } return 0; @@ -607,70 +607,70 @@ int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, u32 status if (status & FLD_VID_SRC_RISC1) { - // We should only process one program per call - u32 prog_cnt = cx_read( channel->gpcnt ); - - //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers - int_msk_tmp = cx_read(channel->int_msk); - cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); - cx_write( channel->int_stat, _intr_msk ); - - spin_lock(&dev->slock); - - dev->_frame_index = prog_cnt; - - queue_work(dev->_irq_queues, &dev->_irq_work_entry); - - - if ( dev->_is_first_frame ) - { - dev->_is_first_frame = 0; - - if( dev->_isNTSC ) - { - singlefield_lines += 1; - odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; - } - else - { - singlefield_lines = PAL_FIELD_HEIGHT; - odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; - } - - - if( dev->_dma_virt_start_addr != NULL ) - { - line_size_in_bytes = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; - risc_phys_jump_addr = dev->_dma_phys_start_addr + odd_risc_prog_size; - - rp = cx25821_update_riscprogram(dev, dev->_dma_virt_start_addr, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD); - - // Jump to Even Risc program of 1st Frame - *(rp++) = cpu_to_le32(RISC_JUMP); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - } - } - - spin_unlock(&dev->slock); + // We should only process one program per call + u32 prog_cnt = cx_read( channel->gpcnt ); + + //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers + int_msk_tmp = cx_read(channel->int_msk); + cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); + cx_write( channel->int_stat, _intr_msk ); + + spin_lock(&dev->slock); + + dev->_frame_index = prog_cnt; + + queue_work(dev->_irq_queues, &dev->_irq_work_entry); + + + if ( dev->_is_first_frame ) + { + dev->_is_first_frame = 0; + + if( dev->_isNTSC ) + { + singlefield_lines += 1; + odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; + } + else + { + singlefield_lines = PAL_FIELD_HEIGHT; + odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; + } + + + if( dev->_dma_virt_start_addr != NULL ) + { + line_size_in_bytes = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + risc_phys_jump_addr = dev->_dma_phys_start_addr + odd_risc_prog_size; + + rp = cx25821_update_riscprogram(dev, dev->_dma_virt_start_addr, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD); + + // Jump to Even Risc program of 1st Frame + *(rp++) = cpu_to_le32(RISC_JUMP); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + } + + spin_unlock(&dev->slock); } else { - if(status & FLD_VID_SRC_UF) - printk("%s: Video Received Underflow Error Interrupt!\n", __func__); + if(status & FLD_VID_SRC_UF) + printk("%s: Video Received Underflow Error Interrupt!\n", __func__); - if(status & FLD_VID_SRC_SYNC) - printk("%s: Video Received Sync Error Interrupt!\n", __func__); + if(status & FLD_VID_SRC_SYNC) + printk("%s: Video Received Sync Error Interrupt!\n", __func__); - if(status & FLD_VID_SRC_OPC_ERR) - printk("%s: Video Received OpCode Error Interrupt!\n", __func__); + if(status & FLD_VID_SRC_OPC_ERR) + printk("%s: Video Received OpCode Error Interrupt!\n", __func__); } - - + + if( dev->_file_status == END_OF_FILE ) { - printk("cx25821: EOF Channel 1 Framecount = %d\n", dev->_frame_count ); - return -1; + printk("cx25821: EOF Channel 1 Framecount = %d\n", dev->_frame_count ); + return -1; } //ElSE, set the interrupt mask register, re-enable irq. @@ -690,8 +690,8 @@ static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) if( !dev ) - return -1; - + return -1; + channel_num = VID_UPSTREAM_SRAM_CHANNEL_I; sram_ch = &dev->sram_channels[channel_num]; @@ -702,16 +702,16 @@ static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) // Only deal with our interrupt if(vid_status) { - handled = cx25821_video_upstream_irq(dev, channel_num, vid_status); + handled = cx25821_video_upstream_irq(dev, channel_num, vid_status); } if( handled < 0 ) { - cx25821_stop_upstream_video_ch1(dev); + cx25821_stop_upstream_video_ch1(dev); } else { - handled += handled; + handled += handled; } return IRQ_RETVAL(handled); @@ -725,7 +725,7 @@ void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch, i int num_lines, odd_num_lines; u32 value; int vip_mode = OUTPUT_FRMT_656; - + value = ( (pix_format & 0x3) << 12 ) | ( vip_mode & 0x7 ); value &= 0xFFFFFFEF; @@ -741,7 +741,7 @@ void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch, i if(dev->_isNTSC) { - odd_num_lines += 1; + odd_num_lines += 1; } value = (num_lines << 16) | odd_num_lines; @@ -754,7 +754,7 @@ void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch, i int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, - struct sram_channel *sram_ch) + struct sram_channel *sram_ch) { u32 tmp = 0; int err = 0; @@ -785,8 +785,8 @@ int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, err = request_irq(dev->pci->irq, cx25821_upstream_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); if (err < 0) { - printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); - goto fail_irq; + printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); + goto fail_irq; } @@ -818,8 +818,8 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, in if( dev->_is_running ) { - printk("Video Channel is still running so return!\n"); - return 0; + printk("Video Channel is still running so return!\n"); + return 0; } @@ -832,15 +832,15 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, in if(!dev->_irq_queues) { - printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); - return -ENOMEM; + printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); + return -ENOMEM; } // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C tmp = cx_read( VID_CH_MODE_SEL ); cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); - + dev->_is_running = 0; dev->_frame_count = 0; dev->_file_status = RESET_STATUS; @@ -850,40 +850,40 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, in data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; risc_buffer_size = dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; - + if( dev->input_filename ) { - str_length = strlen(dev->input_filename); - dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_filename ) - goto error; - - memcpy(dev->_filename, dev->input_filename, str_length + 1); + str_length = strlen(dev->input_filename); + dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_filename ) + goto error; + + memcpy(dev->_filename, dev->input_filename, str_length + 1); } else { - str_length = strlen(dev->_defaultname); - dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_filename ) - goto error; - - memcpy(dev->_filename, dev->_defaultname, str_length + 1); + str_length = strlen(dev->_defaultname); + dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL); + + if( !dev->_filename ) + goto error; + + memcpy(dev->_filename, dev->_defaultname, str_length + 1); } //Default if filename is empty string if( strcmp(dev->input_filename,"") == 0) { - if( dev->_isNTSC ) - { - dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv"; - } - else - { - dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv"; - } + if( dev->_isNTSC ) + { + dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv"; + } + else + { + dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv"; + } } dev->_is_running = 0; @@ -906,8 +906,8 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, in retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size); if (retval < 0) { - printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name); - goto error; + printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name); + goto error; } diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream.h b/linux/drivers/staging/cx25821/cx25821-video-upstream.h index aa6eb6463..71c3dfb39 100644 --- a/linux/drivers/staging/cx25821/cx25821-video-upstream.h +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream.h @@ -71,38 +71,38 @@ #ifdef USE_RISC_NOOP_VIDEO #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - + RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + #define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - + JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + #define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) - + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) + #endif #ifndef USE_RISC_NOOP_VIDEO #define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - RISC_SYNC_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) - + RISC_SYNC_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) + #define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) #define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) #define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) @@ -110,5 +110,5 @@ #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) #define NTSC_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) #endif diff --git a/linux/drivers/staging/cx25821/cx25821-video.c b/linux/drivers/staging/cx25821/cx25821-video.c index 512cbe3ba..ba8115b6e 100644 --- a/linux/drivers/staging/cx25821/cx25821-video.c +++ b/linux/drivers/staging/cx25821/cx25821-video.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -54,30 +54,30 @@ static void init_controls(struct cx25821_dev *dev, int chan_num); struct cx25821_fmt formats[] = { { - .name = "8 bpp, gray", - .fourcc = V4L2_PIX_FMT_GREY, - .depth = 8, - .flags = FORMAT_FLAGS_PACKED, + .name = "8 bpp, gray", + .fourcc = V4L2_PIX_FMT_GREY, + .depth = 8, + .flags = FORMAT_FLAGS_PACKED, }, { - .name = "4:1:1, packed, Y41P", - .fourcc = V4L2_PIX_FMT_Y41P, - .depth = 12, - .flags = FORMAT_FLAGS_PACKED, + .name = "4:1:1, packed, Y41P", + .fourcc = V4L2_PIX_FMT_Y41P, + .depth = 12, + .flags = FORMAT_FLAGS_PACKED, }, { - .name = "4:2:2, packed, YUYV", - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, + .name = "4:2:2, packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, }, { - .name = "4:2:2, packed, UYVY", - .fourcc = V4L2_PIX_FMT_UYVY, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, + .name = "4:2:2, packed, UYVY", + .fourcc = V4L2_PIX_FMT_UYVY, + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, },{ - .name = "4:2:0, YUV", - .fourcc = V4L2_PIX_FMT_YUV420, - .depth = 12, - .flags = FORMAT_FLAGS_PACKED, + .name = "4:2:0, YUV", + .fourcc = V4L2_PIX_FMT_YUV420, + .depth = 12, + .flags = FORMAT_FLAGS_PACKED, }, }; @@ -94,12 +94,12 @@ struct cx25821_fmt *format_by_fourcc(unsigned int fourcc) if( fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P ) { - return formats+1; + return formats+1; } - + for (i = 0; i < ARRAY_SIZE(formats); i++) - if (formats[i].fourcc == fourcc) - return formats+i; + if (formats[i].fourcc == fourcc) + return formats+i; printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc); return NULL; @@ -112,14 +112,14 @@ void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q) dprintk(1, "%s()\n", __func__); if (!list_empty(&q->active)) { - list_for_each(item, &q->active) - buf = list_entry(item, struct cx25821_buffer, vb.queue); + list_for_each(item, &q->active) + buf = list_entry(item, struct cx25821_buffer, vb.queue); } if (!list_empty(&q->queued)) { - list_for_each(item, &q->queued) - buf = list_entry(item, struct cx25821_buffer, vb.queue); + list_for_each(item, &q->queued) + buf = list_entry(item, struct cx25821_buffer, vb.queue); } } @@ -131,63 +131,63 @@ void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, u int bc; for (bc = 0;; bc++) { - if (list_empty(&q->active)) - { - dprintk(1, "bc=%d (=0: active empty)\n", bc); - break; - } - - buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); - - /* count comes from the hw and it is 16bit wide -- - * this trick handles wrap-arounds correctly for - * up to 32767 buffers in flight... */ - if ((s16) (count - buf->count) < 0) - { - break; - } - - do_gettimeofday(&buf->vb.ts); - buf->vb.state = VIDEOBUF_DONE; - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); + if (list_empty(&q->active)) + { + dprintk(1, "bc=%d (=0: active empty)\n", bc); + break; + } + + buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); + + /* count comes from the hw and it is 16bit wide -- + * this trick handles wrap-arounds correctly for + * up to 32767 buffers in flight... */ + if ((s16) (count - buf->count) < 0) + { + break; + } + + do_gettimeofday(&buf->vb.ts); + buf->vb.state = VIDEOBUF_DONE; + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); } if (list_empty(&q->active)) - del_timer(&q->timeout); + del_timer(&q->timeout); else - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); if (bc != 1) - printk(KERN_ERR "%s: %d buffers handled (should be 1)\n", __func__, bc); + printk(KERN_ERR "%s: %d buffers handled (should be 1)\n", __func__, bc); } #ifdef TUNER_FLAG int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm) { dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__, - (unsigned int)norm, - v4l2_norm_to_name(norm)); - + (unsigned int)norm, + v4l2_norm_to_name(norm)); + dev->tvnorm = norm; - /* Tell the internal A/V decoder */ + /* Tell the internal A/V decoder */ cx25821_call_all(dev, core, s_std, norm); - + return 0; } #endif struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, - struct pci_dev *pci, - struct video_device *template, - char *type) + struct pci_dev *pci, + struct video_device *template, + char *type) { struct video_device *vfd; dprintk(1, "%s()\n", __func__); vfd = video_device_alloc(); if (NULL == vfd) - return NULL; + return NULL; *vfd = *template; vfd->minor = -1; vfd->v4l2_dev = &dev->v4l2_dev; @@ -202,13 +202,13 @@ static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) int i; if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) - return -EINVAL; + return -EINVAL; for (i = 0; i < CX25821_CTLS; i++) - if (cx25821_ctls[i].v.id == qctrl->id) - break; + if (cx25821_ctls[i].v.id == qctrl->id) + break; if (i == CX25821_CTLS) { - *qctrl = no_ctl; - return 0; + *qctrl = no_ctl; + return 0; } *qctrl = cx25821_ctls[i].v; return 0; @@ -220,15 +220,15 @@ int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit) { dprintk(1, "%s()\n", __func__); if (fh->resources & bit) - /* have it already allocated */ - return 1; + /* have it already allocated */ + return 1; /* is it free? */ mutex_lock(&dev->lock); if (dev->resources & bit) { - /* no, someone else uses it */ - mutex_unlock(&dev->lock); - return 0; + /* no, someone else uses it */ + mutex_unlock(&dev->lock); + return 0; } /* it's free, grab it */ fh->resources |= bit; @@ -266,23 +266,23 @@ int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input) memset(&route, 0, sizeof(route)); dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", __func__, - input, INPUT(input)->vmux, - INPUT(input)->gpio0, INPUT(input)->gpio1, - INPUT(input)->gpio2, INPUT(input)->gpio3); + input, INPUT(input)->vmux, + INPUT(input)->gpio0, INPUT(input)->gpio1, + INPUT(input)->gpio2, INPUT(input)->gpio3); dev->input = input; route.input = INPUT(input)->vmux; - + /* Tell the internal A/V decoder */ - cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0); - + cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0); + return 0; } int cx25821_start_video_dma(struct cx25821_dev *dev, - struct cx25821_dmaqueue *q, - struct cx25821_buffer *buf, - struct sram_channel *channel) + struct cx25821_dmaqueue *q, + struct cx25821_buffer *buf, + struct sram_channel *channel) { int tmp = 0; @@ -302,7 +302,7 @@ int cx25821_start_video_dma(struct cx25821_dev *dev, /* make sure upstream setting if any is reversed */ tmp = cx_read( VID_CH_MODE_SEL ); - cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); + cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); return 0; } @@ -314,44 +314,44 @@ int cx25821_restart_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue struct list_head *item; if (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); + buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); - cx25821_start_video_dma(dev, q, buf, channel); + cx25821_start_video_dma(dev, q, buf, channel); - list_for_each(item, &q->active) { - buf = list_entry(item, struct cx25821_buffer, vb.queue); - buf->count = q->count++; - } + list_for_each(item, &q->active) { + buf = list_entry(item, struct cx25821_buffer, vb.queue); + buf->count = q->count++; + } - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - return 0; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + return 0; } prev = NULL; for (;;) { - if (list_empty(&q->queued)) - return 0; - - buf = list_entry(q->queued.next, struct cx25821_buffer, vb.queue); - - if (NULL == prev) { - list_move_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, channel); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - } else if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_move_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */ - } else { - return 0; - } - prev = buf; + if (list_empty(&q->queued)) + return 0; + + buf = list_entry(q->queued.next, struct cx25821_buffer, vb.queue); + + if (NULL == prev) { + list_move_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, channel); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + } else if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_move_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */ + } else { + return 0; + } + prev = buf; } } @@ -369,11 +369,11 @@ void cx25821_vid_timeout(unsigned long data) spin_lock_irqsave(&dev->slock, flags); while (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); - list_del(&buf->vb.queue); + buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); + list_del(&buf->vb.queue); - buf->vb.state = VIDEOBUF_ERROR; - wake_up(&buf->vb.done); + buf->vb.state = VIDEOBUF_ERROR; + wake_up(&buf->vb.done); } cx25821_restart_video_queue(dev, q, channel); @@ -389,33 +389,33 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) mask = cx_read(channel->int_msk); if (0 == (status & mask)) - return handled; + return handled; cx_write(channel->int_stat, status); /* risc op code error */ if (status & (1 << 16)) { - printk(KERN_WARNING "%s, %s: video risc op code error\n", dev->name, channel->name); - cx_clear(channel->dma_ctl, 0x11); - cx25821_sram_channel_dump(dev, channel); + printk(KERN_WARNING "%s, %s: video risc op code error\n", dev->name, channel->name); + cx_clear(channel->dma_ctl, 0x11); + cx25821_sram_channel_dump(dev, channel); } /* risc1 y */ if (status & FLD_VID_DST_RISC1) { - spin_lock(&dev->slock); - count = cx_read(channel->gpcnt); - cx25821_video_wakeup(dev, &dev->vidq[channel->i], count); - spin_unlock(&dev->slock); - handled++; + spin_lock(&dev->slock); + count = cx_read(channel->gpcnt); + cx25821_video_wakeup(dev, &dev->vidq[channel->i], count); + spin_unlock(&dev->slock); + handled++; } /* risc2 y */ if (status & 0x10) { - dprintk(2, "stopper video\n"); - spin_lock(&dev->slock); - cx25821_restart_video_queue(dev, &dev->vidq[channel->i], channel); - spin_unlock(&dev->slock); - handled++; + dprintk(2, "stopper video\n"); + spin_lock(&dev->slock); + cx25821_restart_video_queue(dev, &dev->vidq[channel->i], channel); + spin_unlock(&dev->slock); + handled++; } return handled; } @@ -424,30 +424,30 @@ void cx25821_videoioctl_unregister(struct cx25821_dev *dev) { if( dev->ioctl_dev ) { - if (dev->ioctl_dev->minor != -1) - video_unregister_device(dev->ioctl_dev); - else - video_device_release(dev->ioctl_dev); + if (dev->ioctl_dev->minor != -1) + video_unregister_device(dev->ioctl_dev); + else + video_device_release(dev->ioctl_dev); - dev->ioctl_dev = NULL; + dev->ioctl_dev = NULL; } } - + void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) { cx_clear(PCI_INT_MSK, 1); if (dev->video_dev[chan_num]) { - if (-1 != dev->video_dev[chan_num]->minor) - video_unregister_device(dev->video_dev[chan_num]); - else - video_device_release(dev->video_dev[chan_num]); + if (-1 != dev->video_dev[chan_num]->minor) + video_unregister_device(dev->video_dev[chan_num]); + else + video_device_release(dev->video_dev[chan_num]); - dev->video_dev[chan_num] = NULL; + dev->video_dev[chan_num] = NULL; - btcx_riscmem_free(dev->pci, &dev->vidq[chan_num].stopper); + btcx_riscmem_free(dev->pci, &dev->vidq[chan_num].stopper); - printk(KERN_WARNING "device %d released!\n", chan_num); + printk(KERN_WARNING "device %d released!\n", chan_num); } } @@ -475,13 +475,13 @@ int cx25821_video_register(struct cx25821_dev *dev, int chan_num, struct video_d init_timer(&dev->vidq[chan_num].timeout); cx25821_risc_stopper(dev->pci, &dev->vidq[chan_num].stopper, dev->sram_channels[chan_num].dma_ctl, 0x11, 0); - + /* register v4l devices */ dev->video_dev[chan_num] = cx25821_vdev_init(dev, dev->pci, video_template, "video"); err = video_register_device(dev->video_dev[chan_num], VFL_TYPE_GRABBER, video_nr[dev->nr]); if (err < 0) { - goto fail_unreg; + goto fail_unreg; } //set PCI interrupt @@ -512,10 +512,10 @@ int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *si if (0 == *count) - *count = 32; + *count = 32; while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; + (*count)--; return 0; } @@ -534,114 +534,114 @@ int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4 BUG_ON(NULL == fh->fmt); if (fh->width < 48 || fh->width > 720 || - fh->height < 32 || fh->height > 576) - return -EINVAL; + fh->height < 32 || fh->height > 576) + return -EINVAL; buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; + return -EINVAL; if (buf->fmt != fh->fmt || - buf->vb.width != fh->width || - buf->vb.height != fh->height || - buf->vb.field != field) { - buf->fmt = fh->fmt; - buf->vb.width = fh->width; - buf->vb.height = fh->height; - buf->vb.field = field; - init_buffer = 1; + buf->vb.width != fh->width || + buf->vb.height != fh->height || + buf->vb.field != field) { + buf->fmt = fh->fmt; + buf->vb.width = fh->width; + buf->vb.height = fh->height; + buf->vb.field = field; + init_buffer = 1; } if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - init_buffer = 1; - rc = videobuf_iolock(q, &buf->vb, NULL); - if (0 != rc) - { - printk(KERN_DEBUG "videobuf_iolock failed!\n"); - goto fail; - } + init_buffer = 1; + rc = videobuf_iolock(q, &buf->vb, NULL); + if (0 != rc) + { + printk(KERN_DEBUG "videobuf_iolock failed!\n"); + goto fail; + } } dprintk(1, "init_buffer=%d\n", init_buffer); if (init_buffer) { - - channel_opened = dev->channel_opened; - channel_opened = (channel_opened < 0 || channel_opened > 7) ? 7 : channel_opened; - - if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 ) - buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; - else - buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); - - - if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 ) - { - bpl_local = buf->bpl; - } - else - { - bpl_local = buf->bpl; //Default - - if( channel_opened >= 0 && channel_opened <= 7 ) - { - if( dev->use_cif_resolution[channel_opened] ) - { - if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK ) - bpl_local = 352 << 1; - else - bpl_local = dev->cif_width[channel_opened] << 1; - } - } - } - - - switch (buf->vb.field) { - case V4L2_FIELD_TOP: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, 0, UNSET, - buf->bpl, 0, buf->vb.height); - break; - case V4L2_FIELD_BOTTOM: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, UNSET, 0, - buf->bpl, 0, buf->vb.height); - break; - case V4L2_FIELD_INTERLACED: - /* All other formats are top field first */ - line0_offset = 0; - line1_offset = buf->bpl; - dprintk(1, "top field first\n"); - - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, line0_offset, - bpl_local, bpl_local, bpl_local, - buf->vb.height >> 1); - break; - case V4L2_FIELD_SEQ_TB: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, - 0, buf->bpl * (buf->vb.height >> 1), - buf->bpl, 0, - buf->vb.height >> 1); - break; - case V4L2_FIELD_SEQ_BT: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, - buf->bpl * (buf->vb.height >> 1), 0, - buf->bpl, 0, - buf->vb.height >> 1); - break; - default: - BUG(); - } + + channel_opened = dev->channel_opened; + channel_opened = (channel_opened < 0 || channel_opened > 7) ? 7 : channel_opened; + + if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 ) + buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; + else + buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); + + + if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 ) + { + bpl_local = buf->bpl; + } + else + { + bpl_local = buf->bpl; //Default + + if( channel_opened >= 0 && channel_opened <= 7 ) + { + if( dev->use_cif_resolution[channel_opened] ) + { + if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK ) + bpl_local = 352 << 1; + else + bpl_local = dev->cif_width[channel_opened] << 1; + } + } + } + + + switch (buf->vb.field) { + case V4L2_FIELD_TOP: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, 0, UNSET, + buf->bpl, 0, buf->vb.height); + break; + case V4L2_FIELD_BOTTOM: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, UNSET, 0, + buf->bpl, 0, buf->vb.height); + break; + case V4L2_FIELD_INTERLACED: + /* All other formats are top field first */ + line0_offset = 0; + line1_offset = buf->bpl; + dprintk(1, "top field first\n"); + + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, line0_offset, + bpl_local, bpl_local, bpl_local, + buf->vb.height >> 1); + break; + case V4L2_FIELD_SEQ_TB: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, + 0, buf->bpl * (buf->vb.height >> 1), + buf->bpl, 0, + buf->vb.height >> 1); + break; + case V4L2_FIELD_SEQ_BT: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, + buf->bpl * (buf->vb.height >> 1), 0, + buf->bpl, 0, + buf->vb.height >> 1); + break; + default: + BUG(); + } } dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", - buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth, fh->fmt->name, - (unsigned long)buf->risc.dma); + buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth, fh->fmt->name, + (unsigned long)buf->risc.dma); buf->vb.state = VIDEOBUF_PREPARED; @@ -665,10 +665,10 @@ struct videobuf_queue *get_queue(struct cx25821_fh *fh) { switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - return &fh->vidq; + return &fh->vidq; default: - BUG(); - return NULL; + BUG(); + return NULL; } } @@ -676,10 +676,10 @@ int get_resource(struct cx25821_fh *fh, int resource) { switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - return resource; + return resource; default: - BUG(); - return 0; + BUG(); + return 0; } } @@ -714,38 +714,38 @@ int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (NULL == fmt) - return -EINVAL; + return -EINVAL; field = f->fmt.pix.field; maxw = 720; maxh = 576; if (V4L2_FIELD_ANY == field) { - field = (f->fmt.pix.height > maxh/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_TOP; + field = (f->fmt.pix.height > maxh/2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_TOP; } switch (field) { case V4L2_FIELD_TOP: case V4L2_FIELD_BOTTOM: - maxh = maxh / 2; - break; + maxh = maxh / 2; + break; case V4L2_FIELD_INTERLACED: - break; + break; default: - return -EINVAL; + return -EINVAL; } f->fmt.pix.field = field; if (f->fmt.pix.height < 32) - f->fmt.pix.height = 32; + f->fmt.pix.height = 32; if (f->fmt.pix.height > maxh) - f->fmt.pix.height = maxh; + f->fmt.pix.height = maxh; if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; + f->fmt.pix.width = 48; if (f->fmt.pix.width > maxw) - f->fmt.pix.width = maxw; + f->fmt.pix.width = maxw; f->fmt.pix.width &= ~0x03; f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; @@ -764,18 +764,18 @@ int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); cap->version = CX25821_VERSION_CODE; cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; if (UNSET != dev->tuner_type) - cap->capabilities |= V4L2_CAP_TUNER; + cap->capabilities |= V4L2_CAP_TUNER; return 0; } int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { if (unlikely(f->index >= ARRAY_SIZE(formats))) - return -EINVAL; + return -EINVAL; strlcpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; @@ -799,13 +799,13 @@ int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) req.memory = V4L2_MEMORY_MMAP; err = videobuf_reqbufs(q, &req); if (err < 0) - return err; + return err; mbuf->frames = req.count; mbuf->size = 0; for (i = 0; i < mbuf->frames; i++) { - mbuf->offsets[i] = q->bufs[i]->boff; - mbuf->size += q->bufs[i]->bsize; + mbuf->offsets[i] = q->bufs[i]->boff; + mbuf->size += q->bufs[i]->bsize; } return 0; } @@ -856,17 +856,17 @@ int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) int err; dprintk(1, "%s()\n", __func__); - - if (fh) + + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } if( dev->tvnorm == *tvnorms ) { - return 0; + return 0; } mutex_lock(&dev->lock); @@ -882,19 +882,19 @@ int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i) { static const char *iname[] = { - [CX25821_VMUX_COMPOSITE] = "Composite", - [CX25821_VMUX_SVIDEO] = "S-Video", - [CX25821_VMUX_DEBUG] = "for debug only", + [CX25821_VMUX_COMPOSITE] = "Composite", + [CX25821_VMUX_SVIDEO] = "S-Video", + [CX25821_VMUX_DEBUG] = "for debug only", }; unsigned int n; dprintk(1, "%s()\n", __func__); n = i->index; if (n > 2) - return -EINVAL; + return -EINVAL; if (0 == INPUT(n)->type) - return -EINVAL; + return -EINVAL; memset(i, 0, sizeof(*i)); i->index = n; @@ -913,9 +913,9 @@ int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) } int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ +{ struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - + *i = dev->input; dprintk(1, "%s() returns %d\n", __func__, *i); return 0; @@ -930,16 +930,16 @@ int vidioc_s_input(struct file *file, void *priv, unsigned int i) dprintk(1, "%s(%d)\n", __func__, i); - if (fh) + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } if (i > 2) { - dprintk(1, "%s() -EINVAL\n", __func__); - return -EINVAL; + dprintk(1, "%s() -EINVAL\n", __func__); + return -EINVAL; } mutex_lock(&dev->lock); @@ -982,11 +982,11 @@ int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) struct cx25821_dev *dev = fh->dev; int err; - if (fh) + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } return cx25821_set_freq(dev, f); @@ -995,12 +995,12 @@ int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) #ifdef CONFIG_VIDEO_ADV_DEBUG int vidioc_g_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) + struct v4l2_dbg_register *reg) { struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; if (!v4l2_chip_match_host(®->match)) - return -EINVAL; + return -EINVAL; cx25821_call_all(dev, core, g_register, reg); @@ -1008,12 +1008,12 @@ int vidioc_g_register(struct file *file, void *fh, } int vidioc_s_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) + struct v4l2_dbg_register *reg) { struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; if (!v4l2_chip_match_host(®->match)) - return -EINVAL; + return -EINVAL; cx25821_call_all(dev, core, s_register, reg); @@ -1029,9 +1029,9 @@ int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; if (unlikely(UNSET == dev->tuner_type)) - return -EINVAL; + return -EINVAL; if (0 != t->index) - return -EINVAL; + return -EINVAL; strcpy(t->name, "Television"); t->type = V4L2_TUNER_ANALOG_TV; @@ -1043,24 +1043,24 @@ int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) } int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) + struct v4l2_tuner *t) { struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; struct cx25821_fh *fh = priv; int err; - if (fh) + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(1, "%s()\n", __func__); if (UNSET == dev->tuner_type) - return -EINVAL; + return -EINVAL; if (0 != t->index) - return -EINVAL; + return -EINVAL; return 0; } @@ -1130,7 +1130,7 @@ static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qctrl) -{ +{ return cx25821_ctrl_query(qctrl); } @@ -1147,20 +1147,20 @@ static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id) return NULL; } -int vidioc_g_ctrl(struct file *file, - void *priv, +int vidioc_g_ctrl(struct file *file, + void *priv, struct v4l2_control *ctl) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - const struct v4l2_queryctrl* ctrl; + const struct v4l2_queryctrl* ctrl; ctrl = ctrl_by_id(ctl->id); if (NULL == ctrl) return -EINVAL; - switch (ctl->id) - { + switch (ctl->id) + { case V4L2_CID_BRIGHTNESS: ctl->value = dev->ctl_bright; break; @@ -1173,25 +1173,25 @@ int vidioc_g_ctrl(struct file *file, case V4L2_CID_SATURATION: ctl->value = dev->ctl_saturation; break; - } + } return 0; } int cx25821_set_control(struct cx25821_dev *dev, struct v4l2_control *ctl, int chan_num) { - int err; - const struct v4l2_queryctrl* ctrl; + int err; + const struct v4l2_queryctrl* ctrl; - err = -EINVAL; + err = -EINVAL; ctrl = ctrl_by_id(ctl->id); - if (NULL == ctrl) + if (NULL == ctrl) return err; - switch (ctrl->type) - { + switch (ctrl->type) + { case V4L2_CTRL_TYPE_BOOLEAN: case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_INTEGER: @@ -1204,8 +1204,8 @@ int cx25821_set_control(struct cx25821_dev *dev, /* nothing */; }; - switch (ctl->id) - { + switch (ctl->id) + { case V4L2_CID_BRIGHTNESS: dev->ctl_bright = ctl->value; medusa_set_brightness(dev, ctl->value, chan_num); @@ -1222,9 +1222,9 @@ int cx25821_set_control(struct cx25821_dev *dev, dev->ctl_saturation = ctl->value; medusa_set_saturation(dev, ctl->value, chan_num); break; - } + } - err = 0; + err = 0; return err; } @@ -1241,12 +1241,12 @@ static void init_controls(struct cx25821_dev *dev, int chan_num) } } -int vidioc_cropcap(struct file *file, - void *priv, +int vidioc_cropcap(struct file *file, + void *priv, struct v4l2_cropcap *cropcap) { struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - + if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; cropcap->bounds.top = cropcap->bounds.left = 0; @@ -1258,34 +1258,34 @@ int vidioc_cropcap(struct file *file, return 0; } -int vidioc_s_crop(struct file *file, - void *priv, +int vidioc_s_crop(struct file *file, + void *priv, struct v4l2_crop *crop) { struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; struct cx25821_fh *fh = priv; int err; - if (fh) + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } // vidioc_s_crop not supported return -EINVAL; } -int vidioc_g_crop(struct file *file, - void *priv, +int vidioc_g_crop(struct file *file, + void *priv, struct v4l2_crop *crop) { // vidioc_g_crop not supported return -EINVAL; } -int vidioc_querystd(struct file *file, - void *priv, +int vidioc_querystd(struct file *file, + void *priv, v4l2_std_id *norm) { // medusa does not support video standard sensing of current input @@ -1299,17 +1299,17 @@ int is_valid_width(u32 width, v4l2_std_id tvnorm) if(tvnorm == V4L2_STD_PAL_BG) { if (width == 352 || width == 720) - return 1; - else - return 0; + return 1; + else + return 0; } - + if(tvnorm == V4L2_STD_NTSC_M) { - if (width == 320 || width == 352 || width == 720) - return 1; - else - return 0; + if (width == 320 || width == 352 || width == 720) + return 1; + else + return 0; } return 0; } @@ -1317,19 +1317,19 @@ int is_valid_width(u32 width, v4l2_std_id tvnorm) int is_valid_height(u32 height, v4l2_std_id tvnorm) { if(tvnorm == V4L2_STD_PAL_BG) - { - if (height == 576 || height == 288) - return 1; - else - return 0; + { + if (height == 576 || height == 288) + return 1; + else + return 0; } if(tvnorm == V4L2_STD_NTSC_M) { - if (height == 480 || height == 240) - return 1; - else - return 0; + if (height == 480 || height == 240) + return 1; + else + return 0; } return 0; diff --git a/linux/drivers/staging/cx25821/cx25821-video.h b/linux/drivers/staging/cx25821/cx25821-video.h index d43e93282..cef846ccb 100644 --- a/linux/drivers/staging/cx25821/cx25821-video.h +++ b/linux/drivers/staging/cx25821/cx25821-video.h @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -53,7 +53,7 @@ #define dprintk(level, fmt, arg...)\ do { if (VIDEO_DEBUG >= level)\ - printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ + printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ } while (0) @@ -118,9 +118,9 @@ extern int res_locked(struct cx25821_dev *dev, unsigned int bit); extern void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits); extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input); extern int cx25821_start_video_dma(struct cx25821_dev *dev, - struct cx25821_dmaqueue *q, - struct cx25821_buffer *buf, - struct sram_channel *channel); + struct cx25821_dmaqueue *q, + struct cx25821_buffer *buf, + struct sram_channel *channel); extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width, unsigned int height, enum v4l2_field field); extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status); diff --git a/linux/drivers/staging/cx25821/cx25821-video0.c b/linux/drivers/staging/cx25821/cx25821-video0.c index 9dbd740f1..92b5eb937 100644 --- a/linux/drivers/staging/cx25821/cx25821-video0.c +++ b/linux/drivers/staging/cx25821/cx25821-video0.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -40,37 +40,37 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH00]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH00]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -100,18 +100,18 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->video_dev[SRAM_CH00] && h->video_dev[SRAM_CH00]->minor == minor) - { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->video_dev[SRAM_CH00] && h->video_dev[SRAM_CH00]->minor == minor) + { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -119,8 +119,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; @@ -129,22 +129,22 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; + fh->height = 480; dev->channel_opened = SRAM_CH00; pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; fh->fmt = format_by_fourcc(pix_format); - + v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -158,15 +158,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO0)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO0)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -176,36 +176,36 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO0)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH00] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } - } - - return POLLIN|POLLRDNORM; + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH00] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; } - + return 0; } @@ -220,13 +220,13 @@ static int video_release(struct file *file) /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO0)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO0); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO0); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -246,17 +246,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO0)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -269,14 +269,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO0); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } @@ -286,21 +286,21 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + int err; int pix_format = PIXEL_FRMT_422; - - if (fh) + + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->vidq.field = f->fmt.pix.field; @@ -308,33 +308,33 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma // check if width and height is valid based on set standard if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; + fh->width = f->fmt.pix.width; } if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; + fh->height = f->fmt.pix.height; } if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) pix_format = PIXEL_FRMT_411; else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; + pix_format = PIXEL_FRMT_422; else - return -EINVAL; + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH00, pix_format ); - cx25821_set_pixel_format( dev, SRAM_CH00, pix_format ); - // check if cif resolution if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH00] = 1; + dev->use_cif_resolution[SRAM_CH00] = 1; }else { - dev->use_cif_resolution[SRAM_CH00] = 0; + dev->use_cif_resolution[SRAM_CH00] = 0; } dev->cif_width[SRAM_CH00] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH00 ); + medusa_set_resolution( dev, fh->width, SRAM_CH00 ); dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); cx25821_call_all(dev, video, s_fmt, f); @@ -348,7 +348,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); p->sequence = dev->vidq[SRAM_CH00].count; @@ -360,7 +360,7 @@ static int vidioc_log_status (struct file *file, void *priv) struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH00]; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH00]; u32 tmp = 0; snprintf(name, sizeof(name), "%s/2", dev->name); @@ -378,10 +378,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; - if (fh) { + if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; @@ -398,7 +398,7 @@ static const struct v4l2_file_operations video_fops = { .read = video_read, .poll = video_poll, .mmap = video_mmap, - .ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { diff --git a/linux/drivers/staging/cx25821/cx25821-video1.c b/linux/drivers/staging/cx25821/cx25821-video1.c index 44db11940..c36f664f6 100644 --- a/linux/drivers/staging/cx25821/cx25821-video1.c +++ b/linux/drivers/staging/cx25821/cx25821-video1.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -41,37 +41,37 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH01]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH01]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -101,17 +101,17 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->video_dev[SRAM_CH01] && h->video_dev[SRAM_CH01]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->video_dev[SRAM_CH01] && h->video_dev[SRAM_CH01]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -119,8 +119,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; @@ -129,9 +129,9 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; + fh->height = 480; dev->channel_opened = SRAM_CH01; pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; @@ -140,11 +140,11 @@ static int video_open(struct file *file) v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -158,15 +158,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO1)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO1)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -176,36 +176,36 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO1)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH01] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } - } - - return POLLIN|POLLRDNORM; + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH01] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; } - + return 0; } @@ -219,13 +219,13 @@ static int video_release(struct file *file) /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO1)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO1); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO1); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -245,17 +245,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO1)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -268,14 +268,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO1); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } @@ -286,21 +286,21 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + int err; int pix_format = 0; - - if (fh) + + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->vidq.field = f->fmt.pix.field; @@ -308,33 +308,33 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma // check if width and height is valid based on set standard if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; + fh->width = f->fmt.pix.width; } if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; + fh->height = f->fmt.pix.height; } if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) pix_format = PIXEL_FRMT_411; else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; + pix_format = PIXEL_FRMT_422; else - return -EINVAL; + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH01, pix_format ); - cx25821_set_pixel_format( dev, SRAM_CH01, pix_format ); - // check if cif resolution if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH01] = 1; + dev->use_cif_resolution[SRAM_CH01] = 1; }else { dev->use_cif_resolution[SRAM_CH01] = 0; } dev->cif_width[SRAM_CH01] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH01 ); + medusa_set_resolution( dev, fh->width, SRAM_CH01 ); dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); cx25821_call_all(dev, video, s_fmt, f); @@ -348,7 +348,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); p->sequence = dev->vidq[SRAM_CH01].count; @@ -360,7 +360,7 @@ static int vidioc_log_status (struct file *file, void *priv) struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH01]; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH01]; u32 tmp = 0; snprintf(name, sizeof(name), "%s/2", dev->name); @@ -378,10 +378,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; - if (fh) { + if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; @@ -397,7 +397,7 @@ static const struct v4l2_file_operations video_fops = { .read = video_read, .poll = video_poll, .mmap = video_mmap, - .ioctl = video_ioctl2, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { diff --git a/linux/drivers/staging/cx25821/cx25821-video2.c b/linux/drivers/staging/cx25821/cx25821-video2.c index 98db1488d..10df4f981 100644 --- a/linux/drivers/staging/cx25821/cx25821-video2.c +++ b/linux/drivers/staging/cx25821/cx25821-video2.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -41,37 +41,37 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH02]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH02]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -101,17 +101,17 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->video_dev[SRAM_CH02] && h->video_dev[SRAM_CH02]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->video_dev[SRAM_CH02] && h->video_dev[SRAM_CH02]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -119,8 +119,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; fh->dev = dev; @@ -128,9 +128,9 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; + fh->height = 480; dev->channel_opened = SRAM_CH02; pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; @@ -139,11 +139,11 @@ static int video_open(struct file *file) v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -157,15 +157,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO2)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO2)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -175,36 +175,36 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO2)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH02] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } - } - - return POLLIN|POLLRDNORM; + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH02] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; } - + return 0; } @@ -219,13 +219,13 @@ static int video_release(struct file *file) /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO2)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO2); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO2); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -245,17 +245,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO2)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -268,14 +268,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO2); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } @@ -286,21 +286,21 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + int err; int pix_format = 0; - - if (fh) + + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->vidq.field = f->fmt.pix.field; @@ -308,33 +308,33 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma // check if width and height is valid based on set standard if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; + fh->width = f->fmt.pix.width; } if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; + fh->height = f->fmt.pix.height; } if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; + pix_format = PIXEL_FRMT_411; else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; + pix_format = PIXEL_FRMT_422; else - return -EINVAL; + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH02, pix_format ); - cx25821_set_pixel_format( dev, SRAM_CH02, pix_format ); - // check if cif resolution if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH02] = 1; + dev->use_cif_resolution[SRAM_CH02] = 1; }else { dev->use_cif_resolution[SRAM_CH02] = 0; } dev->cif_width[SRAM_CH02] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH02 ); + medusa_set_resolution( dev, fh->width, SRAM_CH02 ); dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); @@ -349,7 +349,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); p->sequence = dev->vidq[SRAM_CH02].count; @@ -361,15 +361,15 @@ static int vidioc_log_status (struct file *file, void *priv) struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH02]; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH02]; u32 tmp = 0; snprintf(name, sizeof(name), "%s/2", dev->name); printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - + cx25821_call_all(dev, core, log_status); - + tmp = cx_read(sram_ch->dma_ctl); printk(KERN_INFO "Video input 2 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", @@ -381,10 +381,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; - if (fh) { + if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; diff --git a/linux/drivers/staging/cx25821/cx25821-video3.c b/linux/drivers/staging/cx25821/cx25821-video3.c index 3dcecd264..2191152d7 100644 --- a/linux/drivers/staging/cx25821/cx25821-video3.c +++ b/linux/drivers/staging/cx25821/cx25821-video3.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -41,37 +41,37 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH03]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH03]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -101,17 +101,17 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->video_dev[SRAM_CH03] && h->video_dev[SRAM_CH03]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->video_dev[SRAM_CH03] && h->video_dev[SRAM_CH03]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -119,8 +119,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; fh->dev = dev; @@ -128,9 +128,9 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; + fh->height = 480; dev->channel_opened = SRAM_CH03; pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; @@ -139,11 +139,11 @@ static int video_open(struct file *file) v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -157,15 +157,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO3)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO3)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -175,36 +175,36 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO3)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH03] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } - } - - return POLLIN|POLLRDNORM; + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH03] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; } - + return 0; } @@ -219,13 +219,13 @@ static int video_release(struct file *file) /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO3)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO3); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO3); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -245,17 +245,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO3)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -268,14 +268,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO3); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } @@ -286,21 +286,21 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + int err; int pix_format = 0; - - if (fh) + + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->vidq.field = f->fmt.pix.field; @@ -308,33 +308,33 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma // check if width and height is valid based on set standard if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; + fh->width = f->fmt.pix.width; } if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; + fh->height = f->fmt.pix.height; } if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; + pix_format = PIXEL_FRMT_411; else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; + pix_format = PIXEL_FRMT_422; else - return -EINVAL; + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH03, pix_format ); - cx25821_set_pixel_format( dev, SRAM_CH03, pix_format ); - // check if cif resolution if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH03] = 1; + dev->use_cif_resolution[SRAM_CH03] = 1; }else { - dev->use_cif_resolution[SRAM_CH03] = 0; + dev->use_cif_resolution[SRAM_CH03] = 0; } dev->cif_width[SRAM_CH03] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH03 ); + medusa_set_resolution( dev, fh->width, SRAM_CH03 ); dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); cx25821_call_all(dev, video, s_fmt, f); @@ -348,7 +348,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); p->sequence = dev->vidq[SRAM_CH03].count; @@ -360,7 +360,7 @@ static int vidioc_log_status (struct file *file, void *priv) struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH03]; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH03]; u32 tmp = 0; snprintf(name, sizeof(name), "%s/2", dev->name); @@ -379,10 +379,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; - if (fh) { + if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; diff --git a/linux/drivers/staging/cx25821/cx25821-video4.c b/linux/drivers/staging/cx25821/cx25821-video4.c index 03da3642c..c1799d981 100644 --- a/linux/drivers/staging/cx25821/cx25821-video4.c +++ b/linux/drivers/staging/cx25821/cx25821-video4.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -40,37 +40,37 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH04]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH04]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -100,17 +100,17 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->video_dev[SRAM_CH04] && h->video_dev[SRAM_CH04]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->video_dev[SRAM_CH04] && h->video_dev[SRAM_CH04]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -118,8 +118,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; fh->dev = dev; @@ -127,9 +127,9 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; + fh->height = 480; dev->channel_opened = SRAM_CH04; pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; @@ -137,11 +137,11 @@ static int video_open(struct file *file) v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -155,15 +155,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO4)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO4)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -173,36 +173,36 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO4)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH04] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } - } - - return POLLIN|POLLRDNORM; + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH04] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; } - + return 0; } @@ -217,13 +217,13 @@ static int video_release(struct file *file) /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO4)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO4); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO4); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -243,17 +243,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO4)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -266,14 +266,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO4); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } @@ -284,21 +284,21 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + int err; int pix_format = 0; // check priority if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->vidq.field = f->fmt.pix.field; @@ -306,33 +306,33 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma // check if width and height is valid based on set standard if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; + fh->width = f->fmt.pix.width; } if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; + fh->height = f->fmt.pix.height; } if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; + pix_format = PIXEL_FRMT_411; else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; + pix_format = PIXEL_FRMT_422; else - return -EINVAL; + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH04, pix_format ); - cx25821_set_pixel_format( dev, SRAM_CH04, pix_format ); - // check if cif resolution if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH04] = 1; + dev->use_cif_resolution[SRAM_CH04] = 1; }else { dev->use_cif_resolution[SRAM_CH04] = 0; } dev->cif_width[SRAM_CH04] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH04); + medusa_set_resolution( dev, fh->width, SRAM_CH04); dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); cx25821_call_all(dev, video, s_fmt, f); @@ -346,7 +346,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); p->sequence = dev->vidq[SRAM_CH04].count; @@ -358,7 +358,7 @@ static int vidioc_log_status (struct file *file, void *priv) struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH04]; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH04]; u32 tmp = 0; snprintf(name, sizeof(name), "%s/2", dev->name); @@ -377,10 +377,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; - if (fh) { + if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; diff --git a/linux/drivers/staging/cx25821/cx25821-video5.c b/linux/drivers/staging/cx25821/cx25821-video5.c index 1d4754392..f1b474258 100644 --- a/linux/drivers/staging/cx25821/cx25821-video5.c +++ b/linux/drivers/staging/cx25821/cx25821-video5.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -40,37 +40,37 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH05]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH05]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -100,17 +100,17 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->video_dev[SRAM_CH05] && h->video_dev[SRAM_CH05]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->video_dev[SRAM_CH05] && h->video_dev[SRAM_CH05]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -118,8 +118,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; fh->dev = dev; @@ -127,9 +127,9 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; + fh->height = 480; dev->channel_opened = SRAM_CH05; pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; @@ -138,11 +138,11 @@ static int video_open(struct file *file) v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -156,15 +156,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO5)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO5)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -174,34 +174,34 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO5)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH05] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } - } - - return POLLIN|POLLRDNORM; + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH05] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; } return 0; @@ -218,13 +218,13 @@ static int video_release(struct file *file) /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO5)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO5); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO5); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -244,17 +244,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO5)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -267,14 +267,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO5); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } @@ -284,21 +284,21 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + int err; int pix_format = 0; - - if (fh) + + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->vidq.field = f->fmt.pix.field; @@ -306,33 +306,33 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma // check if width and height is valid based on set standard if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; + fh->width = f->fmt.pix.width; } if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; + fh->height = f->fmt.pix.height; } if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; + pix_format = PIXEL_FRMT_411; else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; + pix_format = PIXEL_FRMT_422; else - return -EINVAL; + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH05, pix_format ); - cx25821_set_pixel_format( dev, SRAM_CH05, pix_format ); - // check if cif resolution if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH05] = 1; + dev->use_cif_resolution[SRAM_CH05] = 1; }else { dev->use_cif_resolution[SRAM_CH05] = 0; } dev->cif_width[SRAM_CH05] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH05 ); + medusa_set_resolution( dev, fh->width, SRAM_CH05 ); dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); cx25821_call_all(dev, video, s_fmt, f); @@ -346,7 +346,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); p->sequence = dev->vidq[SRAM_CH05].count; @@ -357,14 +357,14 @@ static int vidioc_log_status (struct file *file, void *priv) struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH05]; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH05]; u32 tmp = 0; snprintf(name, sizeof(name), "%s/2", dev->name); printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); cx25821_call_all(dev, core, log_status); - + tmp = cx_read(sram_ch->dma_ctl); printk(KERN_INFO "Video input 5 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", @@ -376,10 +376,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; - if (fh) { + if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; diff --git a/linux/drivers/staging/cx25821/cx25821-video6.c b/linux/drivers/staging/cx25821/cx25821-video6.c index 980565af5..1c0319c7a 100644 --- a/linux/drivers/staging/cx25821/cx25821-video6.c +++ b/linux/drivers/staging/cx25821/cx25821-video6.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -40,37 +40,37 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH06]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH06]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -100,17 +100,17 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->video_dev[SRAM_CH06] && h->video_dev[SRAM_CH06]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->video_dev[SRAM_CH06] && h->video_dev[SRAM_CH06]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -118,8 +118,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; fh->dev = dev; @@ -127,9 +127,9 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; + fh->height = 480; dev->channel_opened = SRAM_CH06; pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; @@ -138,11 +138,11 @@ static int video_open(struct file *file) v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -156,15 +156,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO6)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO6)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -174,36 +174,36 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO6)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH06] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } - } - - return POLLIN|POLLRDNORM; + { + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH06] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; } - + return 0; } @@ -218,12 +218,12 @@ static int video_release(struct file *file) /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO6)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO6); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO6); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -243,17 +243,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO6)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -266,14 +266,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO6); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } @@ -283,21 +283,21 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + int err; int pix_format = 0; - - if (fh) + + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->vidq.field = f->fmt.pix.field; @@ -305,33 +305,33 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma // check if width and height is valid based on set standard if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; + fh->width = f->fmt.pix.width; } if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; + fh->height = f->fmt.pix.height; } if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; + pix_format = PIXEL_FRMT_411; else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; + pix_format = PIXEL_FRMT_422; else - return -EINVAL; + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH06, pix_format ); - cx25821_set_pixel_format( dev, SRAM_CH06, pix_format ); - // check if cif resolution if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH06] = 1; + dev->use_cif_resolution[SRAM_CH06] = 1; }else { dev->use_cif_resolution[SRAM_CH06] = 0; } dev->cif_width[SRAM_CH06] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH06 ); + medusa_set_resolution( dev, fh->width, SRAM_CH06 ); dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); cx25821_call_all(dev, video, s_fmt, f); @@ -345,7 +345,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); p->sequence = dev->vidq[SRAM_CH06].count; @@ -357,14 +357,14 @@ static int vidioc_log_status (struct file *file, void *priv) struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH06]; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH06]; u32 tmp = 0; snprintf(name, sizeof(name), "%s/2", dev->name); printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); cx25821_call_all(dev, core, log_status); - + tmp = cx_read(sram_ch->dma_ctl); printk(KERN_INFO "Video input 6 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", @@ -376,10 +376,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; - if (fh) { + if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; diff --git a/linux/drivers/staging/cx25821/cx25821-video7.c b/linux/drivers/staging/cx25821/cx25821-video7.c index 966e369a4..71da80992 100644 --- a/linux/drivers/staging/cx25821/cx25821-video7.c +++ b/linux/drivers/staging/cx25821/cx25821-video7.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -37,39 +37,39 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH07]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH07]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -99,17 +99,17 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->video_dev[SRAM_CH07] && h->video_dev[SRAM_CH07]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->video_dev[SRAM_CH07] && h->video_dev[SRAM_CH07]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -117,8 +117,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; fh->dev = dev; @@ -126,22 +126,22 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; + fh->height = 480; - dev->channel_opened = SRAM_CH07; + dev->channel_opened = SRAM_CH07; pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; fh->fmt = format_by_fourcc(pix_format); v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -155,15 +155,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO7)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO7)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -173,34 +173,34 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO7)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH07] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } - } - - return POLLIN|POLLRDNORM; + if( buf->vb.state == VIDEOBUF_DONE ) + { + struct cx25821_dev *dev = fh->dev; + + if( dev && dev->use_cif_resolution[SRAM_CH07] ) + { + u8 cam_id = *((char*)buf->vb.baddr+3); + memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); + *((char*)buf->vb.baddr+3) = cam_id; + } + } + + return POLLIN|POLLRDNORM; } return 0; @@ -217,13 +217,13 @@ static int video_release(struct file *file) /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO7)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO7); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO7); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -243,17 +243,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO7)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -266,14 +266,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO7); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } @@ -283,13 +283,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + int err; int pix_format = 0; - - if (fh) + + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) return err; } @@ -297,7 +297,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->vidq.field = f->fmt.pix.field; @@ -305,33 +305,33 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma // check if width and height is valid based on set standard if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { - fh->width = f->fmt.pix.width; + fh->width = f->fmt.pix.width; } if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { - fh->height = f->fmt.pix.height; + fh->height = f->fmt.pix.height; } if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; + pix_format = PIXEL_FRMT_411; else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; + pix_format = PIXEL_FRMT_422; else - return -EINVAL; + return -EINVAL; + + cx25821_set_pixel_format( dev, SRAM_CH07, pix_format ); - cx25821_set_pixel_format( dev, SRAM_CH07, pix_format ); - // check if cif resolution if (fh->width == 320 || fh->width == 352) { - dev->use_cif_resolution[SRAM_CH07] = 1; + dev->use_cif_resolution[SRAM_CH07] = 1; }else { dev->use_cif_resolution[SRAM_CH07] = 0; } dev->cif_width[SRAM_CH07] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH07 ); + medusa_set_resolution( dev, fh->width, SRAM_CH07 ); dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); cx25821_call_all(dev, video, s_fmt, f); @@ -345,7 +345,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); p->sequence = dev->vidq[SRAM_CH07].count; @@ -356,14 +356,14 @@ static int vidioc_log_status (struct file *file, void *priv) struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH07]; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH07]; u32 tmp = 0; snprintf(name, sizeof(name), "%s/2", dev->name); printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); cx25821_call_all(dev, core, log_status); - + tmp = cx_read(sram_ch->dma_ctl); printk(KERN_INFO "Video input 7 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", @@ -375,10 +375,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; - if (fh) { + if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; diff --git a/linux/drivers/staging/cx25821/cx25821-videoioctl.c b/linux/drivers/staging/cx25821/cx25821-videoioctl.c index a5363e486..ca93cd2af 100644 --- a/linux/drivers/staging/cx25821/cx25821-videoioctl.c +++ b/linux/drivers/staging/cx25821/cx25821-videoioctl.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -40,37 +40,37 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[VIDEO_IOCTL_CH]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[VIDEO_IOCTL_CH]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -100,18 +100,18 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->ioctl_dev && h->ioctl_dev->minor == minor) - { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->ioctl_dev && h->ioctl_dev->minor == minor) + { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -119,8 +119,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; @@ -129,22 +129,22 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; + fh->height = 480; dev->channel_opened = VIDEO_IOCTL_CH; pix_format = V4L2_PIX_FMT_YUYV; fh->fmt = format_by_fourcc(pix_format); - + v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -158,15 +158,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO_IOCTL)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO_IOCTL)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -176,22 +176,22 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; - + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + return POLLIN|POLLRDNORM; + return 0; } @@ -199,17 +199,17 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait static int video_release(struct file *file) { struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_dev *dev = fh->dev; /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO_IOCTL); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO_IOCTL); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -230,17 +230,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO_IOCTL)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -253,14 +253,14 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO_IOCTL); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } @@ -272,18 +272,18 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; int err; - if (fh) + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->width = f->fmt.pix.width; fh->height = f->fmt.pix.height; @@ -299,8 +299,8 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); } -static long video_ioctl_set(struct file *file, unsigned int cmd, unsigned long arg) -{ +static long video_ioctl_set(struct file *file, unsigned int cmd, unsigned long arg) +{ struct cx25821_fh *fh = file->private_data; struct cx25821_dev *dev = fh->dev; struct downstream_user_struct *data_from_user; @@ -310,96 +310,96 @@ static long video_ioctl_set(struct file *file, unsigned int cmd, unsigned long a int cif_enable = 0, cif_width = 0; u32 value = 0; - + data_from_user = (struct downstream_user_struct *)arg; - + if( !data_from_user ) { - printk("cx25821 in %s(): User data is INVALID. Returning.\n", __func__); - return 0; + printk("cx25821 in %s(): User data is INVALID. Returning.\n", __func__); + return 0; } - + command = data_from_user->command; - - if( command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT && command != ENABLE_CIF_RESOLUTION && - command != REG_READ && command != REG_WRITE && command != MEDUSA_READ && command != MEDUSA_WRITE) + + if( command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT && command != ENABLE_CIF_RESOLUTION && + command != REG_READ && command != REG_WRITE && command != MEDUSA_READ && command != MEDUSA_WRITE) { - return 0; + return 0; } - - + + switch(command) - { - case SET_VIDEO_STD: - dev->tvnorm = !strcmp(data_from_user->vid_stdname,"PAL") ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; - medusa_set_videostandard(dev); - break; - - case SET_PIXEL_FORMAT: - selected_channel = data_from_user->decoder_select; - pix_format = data_from_user->pixel_format; - - if( !(selected_channel <= 7 && selected_channel >= 0) ) - { - selected_channel -= 4; - selected_channel = selected_channel % 8; - } - - if( selected_channel >= 0 ) - cx25821_set_pixel_format( dev, selected_channel, pix_format ); - - break; - - case ENABLE_CIF_RESOLUTION: - selected_channel = data_from_user->decoder_select; - cif_enable = data_from_user->cif_resolution_enable; - cif_width = data_from_user->cif_width; - - if( cif_enable ) - { - if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK ) - width = 352; - else - width = (cif_width == 320 || cif_width == 352) ? cif_width : 320; - } - - if( !(selected_channel <= 7 && selected_channel >= 0) ) - { - selected_channel -= 4; - selected_channel = selected_channel % 8; - } - - - if( selected_channel <= 7 && selected_channel >= 0 ) - { - dev->use_cif_resolution[selected_channel] = cif_enable; - dev->cif_width[selected_channel] = width; - } - else - { - for( i=0; i < VID_CHANNEL_NUM; i++ ) - { - dev->use_cif_resolution[i] = cif_enable; - dev->cif_width[i] = width; - } - } - - medusa_set_resolution( dev, width, selected_channel ); - break; - case REG_READ: - data_from_user->reg_data = cx_read(data_from_user->reg_address); - break; - case REG_WRITE: - cx_write(data_from_user->reg_address, data_from_user->reg_data); - break; - case MEDUSA_READ: - value = cx25821_i2c_read(&dev->i2c_bus[0], (u16)data_from_user->reg_address, &data_from_user->reg_data); - break; - case MEDUSA_WRITE: - cx25821_i2c_write(&dev->i2c_bus[0], (u16)data_from_user->reg_address, data_from_user->reg_data); - break; + { + case SET_VIDEO_STD: + dev->tvnorm = !strcmp(data_from_user->vid_stdname,"PAL") ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; + medusa_set_videostandard(dev); + break; + + case SET_PIXEL_FORMAT: + selected_channel = data_from_user->decoder_select; + pix_format = data_from_user->pixel_format; + + if( !(selected_channel <= 7 && selected_channel >= 0) ) + { + selected_channel -= 4; + selected_channel = selected_channel % 8; + } + + if( selected_channel >= 0 ) + cx25821_set_pixel_format( dev, selected_channel, pix_format ); + + break; + + case ENABLE_CIF_RESOLUTION: + selected_channel = data_from_user->decoder_select; + cif_enable = data_from_user->cif_resolution_enable; + cif_width = data_from_user->cif_width; + + if( cif_enable ) + { + if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK ) + width = 352; + else + width = (cif_width == 320 || cif_width == 352) ? cif_width : 320; + } + + if( !(selected_channel <= 7 && selected_channel >= 0) ) + { + selected_channel -= 4; + selected_channel = selected_channel % 8; + } + + + if( selected_channel <= 7 && selected_channel >= 0 ) + { + dev->use_cif_resolution[selected_channel] = cif_enable; + dev->cif_width[selected_channel] = width; + } + else + { + for( i=0; i < VID_CHANNEL_NUM; i++ ) + { + dev->use_cif_resolution[i] = cif_enable; + dev->cif_width[i] = width; + } + } + + medusa_set_resolution( dev, width, selected_channel ); + break; + case REG_READ: + data_from_user->reg_data = cx_read(data_from_user->reg_address); + break; + case REG_WRITE: + cx_write(data_from_user->reg_address, data_from_user->reg_data); + break; + case MEDUSA_READ: + value = cx25821_i2c_read(&dev->i2c_bus[0], (u16)data_from_user->reg_address, &data_from_user->reg_data); + break; + case MEDUSA_WRITE: + cx25821_i2c_write(&dev->i2c_bus[0], (u16)data_from_user->reg_address, data_from_user->reg_data); + break; } - + return 0; } @@ -423,12 +423,12 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; int err; - - if (fh) + + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } return 0; diff --git a/linux/drivers/staging/cx25821/cx25821-vidups10.c b/linux/drivers/staging/cx25821/cx25821-vidups10.c index 4738e9184..1e18a8766 100644 --- a/linux/drivers/staging/cx25821/cx25821-vidups10.c +++ b/linux/drivers/staging/cx25821/cx25821-vidups10.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -41,37 +41,37 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH10]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH10]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -100,17 +100,17 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->video_dev[SRAM_CH10] && h->video_dev[SRAM_CH10]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->video_dev[SRAM_CH10] && h->video_dev[SRAM_CH10]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -118,8 +118,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; @@ -128,22 +128,22 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; + fh->height = 480; + - dev->channel_opened = 9; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -157,15 +157,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO10)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO10)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -175,21 +175,21 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO10)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; + return POLLIN|POLLRDNORM; return 0; } @@ -199,17 +199,17 @@ static int video_release(struct file *file) struct cx25821_dev *dev = fh->dev; //stop the risc engine and fifo - //cx_write(channel10->dma_ctl, 0); + //cx_write(channel10->dma_ctl, 0); /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO10)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO10); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO10); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -230,17 +230,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO10)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -253,61 +253,61 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO10); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } -static long video_ioctl_upstream10(struct file *file, unsigned int cmd, unsigned long arg) -{ +static long video_ioctl_upstream10(struct file *file, unsigned int cmd, unsigned long arg) +{ struct cx25821_fh *fh = file->private_data; struct cx25821_dev *dev = fh->dev; int command = 0; struct upstream_user_struct *data_from_user; - - data_from_user = (struct upstream_user_struct *)arg; - + + data_from_user = (struct upstream_user_struct *)arg; + if( !data_from_user ) { - printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); - return 0; + printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); + return 0; } - + command = data_from_user->command; - + if( command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO ) { - return 0; + return 0; } - + dev->input_filename_ch2 = data_from_user->input_filename; dev->input_audiofilename = data_from_user->input_filename; dev->vid_stdname_ch2 = data_from_user->vid_stdname; dev->pixel_format_ch2 = data_from_user->pixel_format; dev->channel_select_ch2 = data_from_user->channel_select; dev->command_ch2 = data_from_user->command; - - + + switch(command) - { - case UPSTREAM_START_VIDEO: - cx25821_start_upstream_video_ch2(dev, data_from_user); - break; - - case UPSTREAM_STOP_VIDEO: - cx25821_stop_upstream_video_ch2(dev); - break; + { + case UPSTREAM_START_VIDEO: + cx25821_start_upstream_video_ch2(dev, data_from_user); + break; + + case UPSTREAM_STOP_VIDEO: + cx25821_stop_upstream_video_ch2(dev); + break; } - + return 0; } @@ -318,18 +318,18 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; int err; - if (fh) + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->width = f->fmt.pix.width; fh->height = f->fmt.pix.height; @@ -366,11 +366,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; int err; - if (fh) + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } return 0; @@ -384,7 +384,7 @@ static const struct v4l2_file_operations video_fops = { .read = video_read, .poll = video_poll, .mmap = video_mmap, - .ioctl = video_ioctl_upstream10, + .ioctl = video_ioctl_upstream10, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { diff --git a/linux/drivers/staging/cx25821/cx25821-vidups9.c b/linux/drivers/staging/cx25821/cx25821-vidups9.c index 7832fd160..947ea5bc8 100644 --- a/linux/drivers/staging/cx25821/cx25821-vidups9.c +++ b/linux/drivers/staging/cx25821/cx25821-vidups9.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -40,37 +40,37 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH09]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH09]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); + dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb. i, buf->count, q->count); } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - - } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); - } + prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + } } if (list_empty(&q->active)) @@ -99,18 +99,18 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx25821_devlist) { - h = list_entry(list, struct cx25821_dev, devlist); + h = list_entry(list, struct cx25821_dev, devlist); - if (h->video_dev[SRAM_CH09] && h->video_dev[SRAM_CH09]->minor == minor) - { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } + if (h->video_dev[SRAM_CH09] && h->video_dev[SRAM_CH09]->minor == minor) + { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } if (NULL == dev) { - unlock_kernel(); - return -ENODEV; + unlock_kernel(); + return -ENODEV; } printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); @@ -118,8 +118,8 @@ static int video_open(struct file *file) /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh), GFP_KERNEL); if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; + unlock_kernel(); + return -ENOMEM; } file->private_data = fh; @@ -128,9 +128,9 @@ static int video_open(struct file *file) fh->width = 720; if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; + fh->height = 576; else - fh->height = 480; + fh->height = 480; dev->channel_opened = 8; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); @@ -138,11 +138,11 @@ static int video_open(struct file *file) v4l2_prio_open(&dev->prio,&fh->prio); videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), + fh); dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); @@ -156,15 +156,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO9)) - return -EBUSY; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + if (res_locked(fh->dev, RESOURCE_VIDEO9)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; + default: + BUG(); + return 0; } } @@ -174,21 +174,21 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait struct cx25821_buffer *buf; if (res_check(fh, RESOURCE_VIDEO9)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; + return POLLIN|POLLRDNORM; return 0; } @@ -199,17 +199,17 @@ static int video_release(struct file *file) struct cx25821_dev *dev = fh->dev; //stop the risc engine and fifo - //cx_write(channel9->dma_ctl, 0); + //cx_write(channel9->dma_ctl, 0); /* stop video capture */ if (res_check(fh, RESOURCE_VIDEO9)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO9); + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO9); } if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); } videobuf_mmap_free(&fh->vidq); @@ -230,17 +230,17 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { - return -EINVAL; + return -EINVAL; } if (unlikely(i != fh->type)) { - return -EINVAL; + return -EINVAL; } if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO9)))) { - return -EBUSY; + return -EBUSY; } return videobuf_streamon(get_queue(fh)); @@ -253,62 +253,62 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) int err, res; if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; + return -EINVAL; if (i != fh->type) - return -EINVAL; + return -EINVAL; res = get_resource(fh, RESOURCE_VIDEO9); err = videobuf_streamoff(get_queue(fh)); if (err < 0) - return err; + return err; res_free(dev, fh, res); return 0; } - -static long video_ioctl_upstream9(struct file *file, unsigned int cmd, unsigned long arg) -{ + +static long video_ioctl_upstream9(struct file *file, unsigned int cmd, unsigned long arg) +{ struct cx25821_fh *fh = file->private_data; struct cx25821_dev *dev = fh->dev; int command = 0; struct upstream_user_struct *data_from_user; - - + + data_from_user = (struct upstream_user_struct *)arg; - + if( !data_from_user ) { - printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); - return 0; + printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); + return 0; } - - command = data_from_user->command; - + + command = data_from_user->command; + if( command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO ) { - return 0; + return 0; } - - + + dev->input_filename = data_from_user->input_filename; dev->input_audiofilename = data_from_user->input_filename; dev->vid_stdname = data_from_user->vid_stdname; dev->pixel_format = data_from_user->pixel_format; dev->channel_select = data_from_user->channel_select; dev->command = data_from_user->command; - - + + switch(command) - { - case UPSTREAM_START_VIDEO: - cx25821_start_upstream_video_ch1(dev, data_from_user); - break; - - case UPSTREAM_STOP_VIDEO: - cx25821_stop_upstream_video_ch1(dev); - break; + { + case UPSTREAM_START_VIDEO: + cx25821_start_upstream_video_ch1(dev, data_from_user); + break; + + case UPSTREAM_STOP_VIDEO: + cx25821_stop_upstream_video_ch1(dev); + break; } - + return 0; } @@ -319,18 +319,18 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_forma struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; int err; - if (fh) + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } dprintk(2, "%s()\n", __func__); err = vidioc_try_fmt_vid_cap(file, priv, f); if (0 != err) - return err; + return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->width = f->fmt.pix.width; fh->height = f->fmt.pix.height; @@ -365,11 +365,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; struct cx25821_fh *fh = priv; int err; - if (fh) + if (fh) { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; } return 0; @@ -382,7 +382,7 @@ static const struct v4l2_file_operations video_fops = { .read = video_read, .poll = video_poll, .mmap = video_mmap, - .ioctl = video_ioctl_upstream9, + .ioctl = video_ioctl_upstream9, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { diff --git a/linux/drivers/staging/cx25821/cx25821.h b/linux/drivers/staging/cx25821/cx25821.h index ee21fa100..a70c61b61 100644 --- a/linux/drivers/staging/cx25821/cx25821.h +++ b/linux/drivers/staging/cx25821/cx25821.h @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX25821 PCIe bridge * - * Copyright (C) 2009 Conexant Systems Inc. + * Copyright (C) 2009 Conexant Systems Inc. * Authors , * Based on Steven Toth cx23885 driver * @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include #include @@ -63,7 +63,7 @@ #define FALSE 0 #define LINE_SIZE_D1 1440 -// Number of decoders and encoders +// Number of decoders and encoders #define MAX_DECODERS 8 #define MAX_ENCODERS 2 #define QUAD_DECODERS 4 @@ -92,7 +92,7 @@ #define UNKNOWN_BOARD 0 #define CX25821_BOARD 1 -/* Currently supported by the driver */ +/* Currently supported by the driver */ #define CX25821_NORMS (\ V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \ V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \ @@ -293,7 +293,7 @@ struct cx25821_dev { struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; /* Analog Audio Upstream */ - int _audio_is_running; + int _audio_is_running; int _audiopixel_format; int _is_first_audio_frame; int _audiofile_status; @@ -312,7 +312,7 @@ struct cx25821_dev { unsigned int _audiodata_buf_size; __le32 * _audiodata_buf_virt_addr; dma_addr_t _audiodata_buf_phys_addr; - char *_audiofilename; + char *_audiofilename; /* V4l */ u32 freq; @@ -323,7 +323,7 @@ struct cx25821_dev { struct cx25821_dmaqueue vidq[MAX_VID_CHANNEL_NUM]; spinlock_t slock; - + /* Video Upstream */ int _line_size; int _prog_cnt; @@ -344,8 +344,8 @@ struct cx25821_dev { unsigned int _data_buf_size; __le32 * _data_buf_virt_addr; dma_addr_t _data_buf_phys_addr; - char * _filename; - char * _defaultname; + char * _filename; + char * _defaultname; int _line_size_ch2; @@ -367,8 +367,8 @@ struct cx25821_dev { unsigned int _data_buf_size_ch2; __le32 * _data_buf_virt_addr_ch2; dma_addr_t _data_buf_phys_addr_ch2; - char * _filename_ch2; - char * _defaultname_ch2; + char * _filename_ch2; + char * _defaultname_ch2; /* MPEG Encoder ONLY settings */ u32 cx23417_mailbox; @@ -376,26 +376,26 @@ struct cx25821_dev { struct video_device *v4l_device; atomic_t v4l_reader_count; struct cx25821_tvnorm encodernorm; - + u32 upstream_riscbuf_size; u32 upstream_databuf_size; u32 upstream_riscbuf_size_ch2; u32 upstream_databuf_size_ch2; u32 audio_upstream_riscbuf_size; u32 audio_upstream_databuf_size; - int _isNTSC; - int _frame_index; - int _audioframe_index; - struct workqueue_struct * _irq_queues; - struct work_struct _irq_work_entry; - struct workqueue_struct * _irq_queues_ch2; - struct work_struct _irq_work_entry_ch2; - struct workqueue_struct * _irq_audio_queues; - struct work_struct _audio_work_entry; + int _isNTSC; + int _frame_index; + int _audioframe_index; + struct workqueue_struct * _irq_queues; + struct work_struct _irq_work_entry; + struct workqueue_struct * _irq_queues_ch2; + struct work_struct _irq_work_entry_ch2; + struct workqueue_struct * _irq_audio_queues; + struct work_struct _audio_work_entry; char *input_filename; char *input_filename_ch2; - int _frame_index_ch2; - int _isNTSC_ch2; + int _frame_index_ch2; + int _isNTSC_ch2; char *vid_stdname_ch2; int pixel_format_ch2; int channel_select_ch2; @@ -440,7 +440,7 @@ static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev) #define cx25821_call_all(dev, o, f, args...) \ v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) - + extern struct list_head cx25821_devlist; extern struct cx25821_board cx25821_boards[]; extern struct cx25821_subid cx25821_subids[]; @@ -488,16 +488,16 @@ struct sram_channel { u32 aud_cfg; u32 fld_aud_fifo_en; u32 fld_aud_risc_en; - + //For Upstream Video u32 vid_fmt_ctl; u32 vid_active_ctl1; u32 vid_active_ctl2; u32 vid_cdt_size; - + u32 vip_ctl; u32 pix_frmt; - u32 jumponly; + u32 jumponly; u32 irq_bit; }; extern struct sram_channel cx25821_sram_channels[]; @@ -530,9 +530,9 @@ extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value); extern int cx25821_i2c_unregister(struct cx25821_i2c *bus); extern void cx25821_gpio_init(struct cx25821_dev *dev); extern void cx25821_set_gpiopin_direction( struct cx25821_dev *dev, - int pin_number, - int pin_logic_value); - + int pin_number, + int pin_logic_value); + extern int medusa_video_init(struct cx25821_dev *dev); extern int medusa_set_videostandard(struct cx25821_dev *dev); extern void medusa_set_resolution(struct cx25821_dev *dev, int width, int decoder_select); @@ -544,18 +544,18 @@ extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int d extern int cx25821_sram_channel_setup(struct cx25821_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc); extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, - struct scatterlist *sglist, - unsigned int top_offset, - unsigned int bottom_offset, - unsigned int bpl, - unsigned int padding, - unsigned int lines); + struct scatterlist *sglist, + unsigned int top_offset, + unsigned int bottom_offset, + unsigned int bpl, + unsigned int padding, + unsigned int lines); extern int cx25821_risc_databuffer_audio(struct pci_dev *pci, - struct btcx_riscmem *risc, - struct scatterlist *sglist, - unsigned int bpl, - unsigned int lines, - unsigned int lpi); + struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int bpl, + unsigned int lines, + unsigned int lpi); extern void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf); extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,u32 reg, u32 mask, u32 value); extern void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch); @@ -566,26 +566,26 @@ extern struct cx25821_dev* cx25821_dev_get(struct pci_dev *pci); extern void cx25821_print_irqbits(char *name, char *tag, char **strings, int len, u32 bits, u32 mask); extern void cx25821_dev_unregister(struct cx25821_dev *dev); extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, - struct sram_channel *ch, - unsigned int bpl, u32 risc); - + struct sram_channel *ch, + unsigned int bpl, u32 risc); + extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, int pixel_format); extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, int pixel_format); extern int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select); -extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev); -extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev); -extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev); -extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, struct upstream_user_struct *up_data); -extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, struct upstream_user_struct *up_data); -extern void cx25821_start_upstream_audio(struct cx25821_dev *dev, struct upstream_user_struct *up_data); -extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev); -extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev); -extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev); +extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev); +extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev); +extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev); +extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, struct upstream_user_struct *up_data); +extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, struct upstream_user_struct *up_data); +extern void cx25821_start_upstream_audio(struct cx25821_dev *dev, struct upstream_user_struct *up_data); +extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev); +extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev); +extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev); extern int cx25821_sram_channel_setup_upstream( struct cx25821_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc); extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel, u32 format); extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev); extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, - struct pci_dev *pci, - struct video_device *template, - char *type); + struct pci_dev *pci, + struct video_device *template, + char *type); #endif diff --git a/v4l/Kconfig.staging b/v4l/Kconfig.staging index b8fbc9dcc..45bfeb002 100644 --- a/v4l/Kconfig.staging +++ b/v4l/Kconfig.staging @@ -61,6 +61,42 @@ config VIDEO_GO7007_USB_S2250_BOARD To compile this driver as a module, choose M here: the module will be called s2250. + +config VIDEO_CX25821 + tristate "Conexant cx25821 support" + depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT + select I2C_ALGOBIT + select VIDEO_BTCX + select VIDEO_TVEEPROM + select VIDEO_IR + select VIDEOBUF_DVB + select VIDEOBUF_DMA_SG + select VIDEO_CX25840 + select VIDEO_CX2341X + ---help--- + This is a video4linux driver for Conexant 25821 based + TV cards. + + To compile this driver as a module, choose M here: the + module will be called cx25821 + +config VIDEO_CX25821_ALSA + tristate "Conexant 25821 DMA audio support" + depends on VIDEO_CX25821 && SND && EXPERIMENTAL + select SND_PCM + ---help--- + This is a video4linux driver for direct (DMA) audio on + Conexant 25821 based capture cards using ALSA. + + It only works with boards with function 01 enabled. + To check if your board supports, use lspci -n. + If supported, you should see 14f1:8801 or 14f1:8811 + PCI device. + + To compile this driver as a module, choose M here: the + module will be called cx25821-alsa. + + endmenu endif # STAGING diff --git a/v4l/Makefile.staging b/v4l/Makefile.staging index b8dca80f0..77ba6a9fa 100644 --- a/v4l/Makefile.staging +++ b/v4l/Makefile.staging @@ -37,3 +37,22 @@ staging-install install-staging:: install -d $(KDIRA)/$$dir; \ for i in $$files;do if [ -e $$i ]; then echo -n "$$i "; \ install -m 644 -c $$i $(KDIRA)/$$dir; fi; done; echo; + +# From drivers/staging/cx25821/Makefile + +cx25821-objs := cx25821-core.o cx25821-cards.o cx25821-i2c.o cx25821-gpio.o \ + cx25821-medusa-video.o cx25821-video.o cx25821-video0.o cx25821-video1.o \ + cx25821-video2.o cx25821-video3.o cx25821-video4.o cx25821-video5.o \ + cx25821-video6.o cx25821-video7.o cx25821-vidups9.o cx25821-vidups10.o \ + cx25821-audups11.o cx25821-video-upstream.o cx25821-video-upstream-ch2.o \ + cx25821-audio-upstream.o cx25821-videoioctl.o + +obj-$(CONFIG_VIDEO_CX25821) += cx25821.o +obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o + +EXTRA_CFLAGS += -Idrivers/media/video +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends + +EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) + -- cgit v1.2.3 From 03fac1f4cbaf888008b495441f44ff827f6d42d4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Sep 2009 11:30:11 -0300 Subject: cx25821: some CodingStyle fixes From: Mauro Carvalho Chehab The original driver were generated with some dos editor, and used their own coding style. This patch does some automatic CodingStyle fixes, by running dos2unix and Lindent tools. More work still needs to be done for it to use upstream CodingStyle. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/staging/cx25821/cx25821-alsa.c | 415 ++- .../staging/cx25821/cx25821-audio-upstream.c | 1628 ++++++----- .../staging/cx25821/cx25821-audio-upstream.h | 121 +- linux/drivers/staging/cx25821/cx25821-audio.h | 117 +- linux/drivers/staging/cx25821/cx25821-audups11.c | 615 ++-- linux/drivers/staging/cx25821/cx25821-biffuncs.h | 90 +- linux/drivers/staging/cx25821/cx25821-cards.c | 84 +- linux/drivers/staging/cx25821/cx25821-core.c | 2496 ++++++++-------- linux/drivers/staging/cx25821/cx25821-gpio.c | 154 +- linux/drivers/staging/cx25821/cx25821-gpio.h | 1 - linux/drivers/staging/cx25821/cx25821-i2c.c | 261 +- .../staging/cx25821/cx25821-medusa-defines.h | 92 +- linux/drivers/staging/cx25821/cx25821-medusa-reg.h | 911 +++--- .../drivers/staging/cx25821/cx25821-medusa-video.c | 1346 +++++---- .../drivers/staging/cx25821/cx25821-medusa-video.h | 62 +- linux/drivers/staging/cx25821/cx25821-reg.h | 3033 ++++++++++---------- linux/drivers/staging/cx25821/cx25821-sram.h | 527 ++-- .../staging/cx25821/cx25821-video-upstream-ch2.c | 1682 ++++++----- .../staging/cx25821/cx25821-video-upstream-ch2.h | 210 +- .../staging/cx25821/cx25821-video-upstream.c | 1817 ++++++------ .../staging/cx25821/cx25821-video-upstream.h | 224 +- linux/drivers/staging/cx25821/cx25821-video.c | 1576 +++++----- linux/drivers/staging/cx25821/cx25821-video.h | 90 +- linux/drivers/staging/cx25821/cx25821-video0.c | 636 ++-- linux/drivers/staging/cx25821/cx25821-video1.c | 635 ++-- linux/drivers/staging/cx25821/cx25821-video2.c | 647 +++-- linux/drivers/staging/cx25821/cx25821-video3.c | 645 ++--- linux/drivers/staging/cx25821/cx25821-video4.c | 642 ++--- linux/drivers/staging/cx25821/cx25821-video5.c | 645 +++-- linux/drivers/staging/cx25821/cx25821-video6.c | 645 +++-- linux/drivers/staging/cx25821/cx25821-video7.c | 639 ++--- linux/drivers/staging/cx25821/cx25821-videoioctl.c | 710 +++-- linux/drivers/staging/cx25821/cx25821-vidups10.c | 614 ++-- linux/drivers/staging/cx25821/cx25821-vidups9.c | 614 ++-- linux/drivers/staging/cx25821/cx25821.h | 756 ++--- 35 files changed, 12623 insertions(+), 12757 deletions(-) diff --git a/linux/drivers/staging/cx25821/cx25821-alsa.c b/linux/drivers/staging/cx25821/cx25821-alsa.c index ee92e8286..e8b5ffc5b 100644 --- a/linux/drivers/staging/cx25821/cx25821-alsa.c +++ b/linux/drivers/staging/cx25821/cx25821-alsa.c @@ -1,26 +1,25 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * Based on SAA713x ALSA driver and CX88 driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - - +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on SAA713x ALSA driver and CX88 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + #include #include #include @@ -40,7 +39,6 @@ #include #endif - #include "cx25821.h" #include "cx25821-reg.h" @@ -52,50 +50,47 @@ #define dprintk_core(level,fmt, arg...) if (debug >= level) \ printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name , ## arg) - /**************************************************************************** Data type declarations - Can be moded to a header file later ****************************************************************************/ - static struct snd_card *snd_cx25821_cards[SNDRV_CARDS]; static int devno; struct cx25821_audio_dev { - struct cx25821_dev *dev; - struct cx25821_dmaqueue q; + struct cx25821_dev *dev; + struct cx25821_dmaqueue q; #if 0 u64 starttime; #endif /* pci i/o */ - struct pci_dev *pci; + struct pci_dev *pci; /* audio controls */ - int irq; + int irq; - struct snd_card *card; + struct snd_card *card; unsigned long iobase; - spinlock_t reg_lock; - atomic_t count; + spinlock_t reg_lock; + atomic_t count; - unsigned int dma_size; - unsigned int period_size; - unsigned int num_periods; + unsigned int dma_size; + unsigned int period_size; + unsigned int num_periods; - struct videobuf_dmabuf *dma_risc; + struct videobuf_dmabuf *dma_risc; - struct cx25821_buffer *buf; + struct cx25821_buffer *buf; - struct snd_pcm_substream *substream; + struct snd_pcm_substream *substream; }; typedef struct cx25821_audio_dev snd_cx25821_card_t; - #ifdef COMPAT_SND_CTL_BOOLEAN_MONO static int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) + struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; @@ -111,7 +106,7 @@ static int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol, static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; +static int enable[SNDRV_CARDS] = { 1,[1...(SNDRV_CARDS - 1)] = 1 }; module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled."); @@ -119,7 +114,6 @@ MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled."); module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s)."); - /**************************************************************************** Module macros ****************************************************************************/ @@ -127,11 +121,11 @@ MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s)."); MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards"); MODULE_AUTHOR("Hiep Huynh"); MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Conexant,25821}");//"{{Conexant,23881}," +MODULE_SUPPORTED_DEVICE("{{Conexant,25821}"); //"{{Conexant,23881}," static unsigned int debug; -module_param(debug,int,0644); -MODULE_PARM_DESC(debug,"enable debug messages"); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "enable debug messages"); /**************************************************************************** Module specific funtions @@ -140,7 +134,7 @@ MODULE_PARM_DESC(debug,"enable debug messages"); #define AUD_INT_DN_RISCI1 (1 << 0) #define AUD_INT_UP_RISCI1 (1 << 1) #define AUD_INT_RDS_DN_RISCI1 (1 << 2) -#define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */ +#define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */ #define AUD_INT_UP_RISCI2 (1 << 5) #define AUD_INT_RDS_DN_RISCI2 (1 << 6) #define AUD_INT_DN_SYNC (1 << 12) @@ -157,40 +151,46 @@ MODULE_PARM_DESC(debug,"enable debug messages"); * BOARD Specific: Sets audio DMA */ -static int _cx25821_start_audio_dma(snd_cx25821_card_t *chip) +static int _cx25821_start_audio_dma(snd_cx25821_card_t * chip) { - struct cx25821_buffer *buf = chip->buf; - struct cx25821_dev * dev = chip->dev; - struct sram_channel *audio_ch = &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]; + struct cx25821_buffer *buf = chip->buf; + struct cx25821_dev *dev = chip->dev; + struct sram_channel *audio_ch = + &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]; u32 tmp = 0; // enable output on the GPIO 0 for the MCLK ADC (Audio) - cx25821_set_gpiopin_direction( chip->dev, 0, 0 ); + cx25821_set_gpiopin_direction(chip->dev, 0, 0); /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ - cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN ); + cx_clear(AUD_INT_DMA_CTL, + FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN); /* setup fifo + format - out channel */ - cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl, buf->risc.dma); + cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl, + buf->risc.dma); /* sets bpl size */ cx_write(AUD_A_LNGTH, buf->bpl); /* reset counter */ - cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); //GP_COUNT_CONTROL_RESET = 0x3 + cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); //GP_COUNT_CONTROL_RESET = 0x3 atomic_set(&chip->count, 0); - //Set the input mode to 16-bit - tmp = cx_read(AUD_A_CFG); - cx_write(AUD_A_CFG, tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | FLD_AUD_CLK_ENABLE); + //Set the input mode to 16-bit + tmp = cx_read(AUD_A_CFG); + cx_write(AUD_A_CFG, + tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | + FLD_AUD_CLK_ENABLE); //printk(KERN_INFO "DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d " - // "byte buffer\n", buf->bpl, audio_ch->cmds_start, cx_read(audio_ch->cmds_start + 12)>>1, - // chip->num_periods, buf->bpl * chip->num_periods); - + // "byte buffer\n", buf->bpl, audio_ch->cmds_start, cx_read(audio_ch->cmds_start + 12)>>1, + // chip->num_periods, buf->bpl * chip->num_periods); /* Enables corresponding bits at AUD_INT_STAT */ - cx_write(AUD_A_INT_MSK, FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC | FLD_AUD_DST_OPC_ERR ); + cx_write(AUD_A_INT_MSK, + FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC | + FLD_AUD_DST_OPC_ERR); /* Clean any pending interrupt bits already set */ cx_write(AUD_A_INT_STAT, ~0); @@ -198,9 +198,10 @@ static int _cx25821_start_audio_dma(snd_cx25821_card_t *chip) /* enable audio irqs */ cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT); - // Turn on audio downstream fifo and risc enable 0x101 - tmp = cx_read(AUD_INT_DMA_CTL); - cx_set(AUD_INT_DMA_CTL, tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN) ); + // Turn on audio downstream fifo and risc enable 0x101 + tmp = cx_read(AUD_INT_DMA_CTL); + cx_set(AUD_INT_DMA_CTL, + tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN)); mdelay(100); return 0; @@ -209,16 +210,19 @@ static int _cx25821_start_audio_dma(snd_cx25821_card_t *chip) /* * BOARD Specific: Resets audio DMA */ -static int _cx25821_stop_audio_dma(snd_cx25821_card_t *chip) +static int _cx25821_stop_audio_dma(snd_cx25821_card_t * chip) { struct cx25821_dev *dev = chip->dev; /* stop dma */ - cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN ); + cx_clear(AUD_INT_DMA_CTL, + FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN); /* disable irqs */ cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT); - cx_clear(AUD_A_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); + cx_clear(AUD_A_INT_MSK, + AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 | + AUD_INT_DN_RISCI1); return 0; } @@ -229,50 +233,54 @@ static int _cx25821_stop_audio_dma(snd_cx25821_card_t *chip) * BOARD Specific: IRQ dma bits */ static char *cx25821_aud_irqs[32] = { - "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ - NULL, /* reserved */ - "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ - NULL, /* reserved */ - "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ - NULL, /* reserved */ - "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ - NULL, /* reserved */ - "opc_err", "par_err", "rip_err", /* 16-18 */ - "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ + "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ + NULL, /* reserved */ + "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ + NULL, /* reserved */ + "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ + NULL, /* reserved */ + "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ + NULL, /* reserved */ + "opc_err", "par_err", "rip_err", /* 16-18 */ + "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ }; /* * BOARD Specific: Threats IRQ audio specific calls */ -static void cx25821_aud_irq(snd_cx25821_card_t *chip, u32 status, u32 mask) +static void cx25821_aud_irq(snd_cx25821_card_t * chip, u32 status, u32 mask) { struct cx25821_dev *dev = chip->dev; - if (0 == (status & mask)) - { + if (0 == (status & mask)) { return; } cx_write(AUD_A_INT_STAT, status); - if (debug > 1 || (status & mask & ~0xff)) + if (debug > 1 || (status & mask & ~0xff)) cx25821_print_irqbits(dev->name, "irq aud", - cx25821_aud_irqs, ARRAY_SIZE(cx25821_aud_irqs), - status, mask); + cx25821_aud_irqs, + ARRAY_SIZE(cx25821_aud_irqs), status, + mask); /* risc op code error */ if (status & AUD_INT_OPC_ERR) { - printk(KERN_WARNING "WARNING %s/1: Audio risc op code error\n",dev->name); - - cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN ); - cx25821_sram_channel_dump_audio(dev, &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]); + printk(KERN_WARNING "WARNING %s/1: Audio risc op code error\n", + dev->name); + + cx_clear(AUD_INT_DMA_CTL, + FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN); + cx25821_sram_channel_dump_audio(dev, + &cx25821_sram_channels + [AUDIO_SRAM_CHANNEL]); } if (status & AUD_INT_DN_SYNC) { - printk(KERN_WARNING "WARNING %s: Downstream sync error!\n",dev->name); + printk(KERN_WARNING "WARNING %s: Downstream sync error!\n", + dev->name); cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); return; } - /* risc1 downstream */ if (status & AUD_INT_DN_RISCI1) { atomic_set(&chip->count, cx_read(AUD_A_GPCNT)); @@ -280,7 +288,6 @@ static void cx25821_aud_irq(snd_cx25821_card_t *chip, u32 status, u32 mask) } } - /* * BOARD Specific: Handles IRQ calls */ @@ -297,30 +304,26 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id) int loop, handled = 0; int audint_count = 0; - audint_status = cx_read(AUD_A_INT_STAT); - audint_mask = cx_read(AUD_A_INT_MSK); + audint_mask = cx_read(AUD_A_INT_MSK); audint_count = cx_read(AUD_A_GPCNT); status = cx_read(PCI_INT_STAT); - for (loop = 0; loop < 1; loop++) - { + for (loop = 0; loop < 1; loop++) { status = cx_read(PCI_INT_STAT); - if (0 == status) - { + if (0 == status) { status = cx_read(PCI_INT_STAT); audint_status = cx_read(AUD_A_INT_STAT); audint_mask = cx_read(AUD_A_INT_MSK); - if (status) - { + if (status) { handled = 1; cx_write(PCI_INT_STAT, status); - cx25821_aud_irq(chip, audint_status, audint_mask); + cx25821_aud_irq(chip, audint_status, + audint_mask); break; - } - else + } else goto out; } @@ -335,19 +338,18 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id) if (handled) cx_write(PCI_INT_STAT, pci_status); - out: + out: return IRQ_RETVAL(handled); } - -static int dsp_buffer_free(snd_cx25821_card_t *chip) +static int dsp_buffer_free(snd_cx25821_card_t * chip) { BUG_ON(!chip->dma_size); - dprintk(2,"Freeing buffer\n"); + dprintk(2, "Freeing buffer\n"); videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc); videobuf_dma_free(chip->dma_risc); - btcx_riscmem_free(chip->pci,&chip->buf->risc); + btcx_riscmem_free(chip->pci, &chip->buf->risc); kfree(chip->buf); chip->dma_risc = NULL; @@ -367,28 +369,25 @@ static int dsp_buffer_free(snd_cx25821_card_t *chip) #define DEFAULT_FIFO_SIZE 384 static struct snd_pcm_hardware snd_cx25821_digital_hw = { .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID, .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, .channels_min = 2, .channels_max = 2, /* Analog audio output will be full of clicks and pops if there are not exactly four lines in the SRAM FIFO buffer. */ - .period_bytes_min = DEFAULT_FIFO_SIZE/3, - .period_bytes_max = DEFAULT_FIFO_SIZE/3, + .period_bytes_min = DEFAULT_FIFO_SIZE / 3, + .period_bytes_max = DEFAULT_FIFO_SIZE / 3, .periods_min = 1, .periods_max = AUDIO_LINE_SIZE, - .buffer_bytes_max = (AUDIO_LINE_SIZE*AUDIO_LINE_SIZE), //128*128 = 16384 = 1024 * 16 + .buffer_bytes_max = (AUDIO_LINE_SIZE * AUDIO_LINE_SIZE), //128*128 = 16384 = 1024 * 16 }; #endif - - /* * audio pcm capture open callback */ @@ -401,11 +400,12 @@ static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) if (!chip) { printk(KERN_ERR "DEBUG: cx25821 can't find device struct." - " Can't proceed with open\n"); + " Can't proceed with open\n"); return -ENODEV; } - err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); + err = + snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); if (err < 0) goto _error; @@ -413,13 +413,12 @@ static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) runtime->hw = snd_cx25821_digital_hw; - if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size != DEFAULT_FIFO_SIZE) - { - bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3; //since there are 3 audio Clusters - bpl &= ~7; /* must be multiple of 8 */ + if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size != + DEFAULT_FIFO_SIZE) { + bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3; //since there are 3 audio Clusters + bpl &= ~7; /* must be multiple of 8 */ - if( bpl > AUDIO_LINE_SIZE ) - { + if (bpl > AUDIO_LINE_SIZE) { bpl = AUDIO_LINE_SIZE; } runtime->hw.period_bytes_min = bpl; @@ -427,8 +426,8 @@ static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) } return 0; -_error: - dprintk(1,"Error opening PCM!\n"); + _error: + dprintk(1, "Error opening PCM!\n"); return err; } @@ -443,8 +442,8 @@ static int snd_cx25821_close(struct snd_pcm_substream *substream) /* * hw_params callback */ -static int snd_cx25821_hw_params(struct snd_pcm_substream * substream, - struct snd_pcm_hw_params * hw_params) +static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); struct videobuf_dmabuf *dma; @@ -457,37 +456,34 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream * substream, substream->runtime->dma_area = NULL; } - chip->period_size = params_period_bytes(hw_params); chip->num_periods = params_periods(hw_params); chip->dma_size = chip->period_size * params_periods(hw_params); BUG_ON(!chip->dma_size); - BUG_ON(chip->num_periods & (chip->num_periods-1)); + BUG_ON(chip->num_periods & (chip->num_periods - 1)); buf = videobuf_sg_alloc(sizeof(*buf)); if (NULL == buf) return -ENOMEM; - - if( chip->period_size > AUDIO_LINE_SIZE ) - { + if (chip->period_size > AUDIO_LINE_SIZE) { chip->period_size = AUDIO_LINE_SIZE; } - buf->vb.memory = V4L2_MEMORY_MMAP; - buf->vb.field = V4L2_FIELD_NONE; - buf->vb.width = chip->period_size; - buf->bpl = chip->period_size; + buf->vb.field = V4L2_FIELD_NONE; + buf->vb.width = chip->period_size; + buf->bpl = chip->period_size; buf->vb.height = chip->num_periods; - buf->vb.size = chip->dma_size; + buf->vb.size = chip->dma_size; dma = videobuf_to_dma(&buf->vb); videobuf_dma_init(dma); ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, - (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); + (PAGE_ALIGN(buf->vb.size) >> + PAGE_SHIFT)); if (ret < 0) goto error; @@ -495,19 +491,19 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream * substream, if (ret < 0) goto error; - - ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist, buf->vb.width, buf->vb.height, 1); - if (ret < 0) - { - printk(KERN_INFO "DEBUG: ERROR after cx25821_risc_databuffer_audio() \n"); + ret = + cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist, + buf->vb.width, buf->vb.height, 1); + if (ret < 0) { + printk(KERN_INFO + "DEBUG: ERROR after cx25821_risc_databuffer_audio() \n"); goto error; } - /* Loop back to start of program */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ buf->vb.state = VIDEOBUF_PREPARED; @@ -520,7 +516,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream * substream, return 0; -error: + error: kfree(buf); return ret; } @@ -528,7 +524,7 @@ error: /* * hw free callback */ -static int snd_cx25821_hw_free(struct snd_pcm_substream * substream) +static int snd_cx25821_hw_free(struct snd_pcm_substream *substream) { snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); @@ -551,7 +547,8 @@ static int snd_cx25821_prepare(struct snd_pcm_substream *substream) /* * trigger callback */ -static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream, int cmd) +static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream, + int cmd) { snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); int err = 0; @@ -559,17 +556,16 @@ static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream, int cmd /* Local interrupts are already disabled by ALSA */ spin_lock(&chip->reg_lock); - switch (cmd) - { - case SNDRV_PCM_TRIGGER_START: - err = _cx25821_start_audio_dma(chip); - break; - case SNDRV_PCM_TRIGGER_STOP: - err = _cx25821_stop_audio_dma(chip); - break; - default: - err = -EINVAL; - break; + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + err = _cx25821_start_audio_dma(chip); + break; + case SNDRV_PCM_TRIGGER_STOP: + err = _cx25821_stop_audio_dma(chip); + break; + default: + err = -EINVAL; + break; } spin_unlock(&chip->reg_lock); @@ -580,7 +576,8 @@ static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream, int cmd /* * pointer callback */ -static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream + *substream) { snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; @@ -588,14 +585,14 @@ static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream *substream count = atomic_read(&chip->count); - return runtime->period_size * (count & (runtime->periods-1)); + return runtime->period_size * (count & (runtime->periods - 1)); } /* * page callback (needed for mmap) */ static struct page *snd_cx25821_page(struct snd_pcm_substream *substream, - unsigned long offset) + unsigned long offset) { void *pageptr = substream->runtime->dma_area + offset; @@ -617,20 +614,19 @@ static struct snd_pcm_ops snd_cx25821_pcm_ops = { .page = snd_cx25821_page, }; - /* * ALSA create a PCM device: Called when initializing the board. Sets up the name and hooks up * the callbacks */ -static int snd_cx25821_pcm(snd_cx25821_card_t *chip, int device, char *name) +static int snd_cx25821_pcm(snd_cx25821_card_t * chip, int device, char *name) { struct snd_pcm *pcm; int err; err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); - if (err < 0) - { - printk(KERN_INFO "ERROR: FAILED snd_pcm_new() in %s\n", __func__); + if (err < 0) { + printk(KERN_INFO "ERROR: FAILED snd_pcm_new() in %s\n", + __func__); return err; } pcm->private_data = chip; @@ -641,7 +637,6 @@ static int snd_cx25821_pcm(snd_cx25821_card_t *chip, int device, char *name) return 0; } - /**************************************************************************** Basic Flow for Sound Devices ****************************************************************************/ @@ -652,15 +647,16 @@ static int snd_cx25821_pcm(snd_cx25821_card_t *chip, int device, char *name) */ static struct pci_device_id cx25821_audio_pci_tbl[] __devinitdata = { - {0x14f1,0x0920,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, - {0, } + {0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} }; + MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl); -/* - * Not used in the function snd_cx25821_dev_free so removing - * from the file. - */ +/* + * Not used in the function snd_cx25821_dev_free so removing + * from the file. + */ /* static int snd_cx25821_free(snd_cx25821_card_t *chip) { @@ -672,12 +668,12 @@ static int snd_cx25821_free(snd_cx25821_card_t *chip) return 0; } -*/ +*/ /* * Component Destructor */ -static void snd_cx25821_dev_free(struct snd_card * card) +static void snd_cx25821_dev_free(struct snd_card *card) { snd_cx25821_card_t *chip = card->private_data; @@ -685,19 +681,18 @@ static void snd_cx25821_dev_free(struct snd_card * card) snd_card_free(chip->card); } - /* * Alsa Constructor - Component probe */ static int cx25821_audio_initdev(struct cx25821_dev *dev) { - struct snd_card *card; - snd_cx25821_card_t *chip; - int err; + struct snd_card *card; + snd_cx25821_card_t *chip; + int err; - if (devno >= SNDRV_CARDS) - { - printk(KERN_INFO "DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__); + if (devno >= SNDRV_CARDS) { + printk(KERN_INFO "DEBUG ERROR: devno >= SNDRV_CARDS %s\n", + __func__); return (-ENODEV); } @@ -707,10 +702,13 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) return (-ENOENT); } - card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx25821_card_t)); - if (!card) - { - printk(KERN_INFO "DEBUG ERROR: cannot create snd_card_new in %s\n", __func__); + card = + snd_card_new(index[devno], id[devno], THIS_MODULE, + sizeof(snd_cx25821_card_t)); + if (!card) { + printk(KERN_INFO + "DEBUG ERROR: cannot create snd_card_new in %s\n", + __func__); return (-ENOMEM); } @@ -726,37 +724,38 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) chip->pci = dev->pci; chip->iobase = pci_resource_start(dev->pci, 0); - chip->irq = dev->pci->irq; err = request_irq(dev->pci->irq, cx25821_irq, IRQF_SHARED | IRQF_DISABLED, chip->dev->name, chip); if (err < 0) { - printk(KERN_ERR "ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name, dev->pci->irq); + printk(KERN_ERR "ERROR %s: can't get IRQ %d for ALSA\n", + chip->dev->name, dev->pci->irq); goto error; } - - if ((err = snd_cx25821_pcm(chip, 0, "cx25821 Digital")) < 0) - { - printk(KERN_INFO "DEBUG ERROR: cannot create snd_cx25821_pcm %s\n", __func__); + if ((err = snd_cx25821_pcm(chip, 0, "cx25821 Digital")) < 0) { + printk(KERN_INFO + "DEBUG ERROR: cannot create snd_cx25821_pcm %s\n", + __func__); goto error; } snd_card_set_dev(card, &chip->pci->dev); - strcpy(card->shortname, "cx25821"); - sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name, chip->iobase, chip->irq); - strcpy (card->mixername, "CX25821"); + sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name, + chip->iobase, chip->irq); + strcpy(card->mixername, "CX25821"); - printk(KERN_INFO "%s/%i: ALSA support for cx25821 boards\n", card->driver, devno); + printk(KERN_INFO "%s/%i: ALSA support for cx25821 boards\n", + card->driver, devno); err = snd_card_register(card); - if (err < 0) - { - printk(KERN_INFO "DEBUG ERROR: cannot register sound card %s\n", __func__); + if (err < 0) { + printk(KERN_INFO "DEBUG ERROR: cannot register sound card %s\n", + __func__); goto error; } @@ -765,12 +764,11 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) devno++; return 0; -error: + error: snd_card_free(card); return err; } - /**************************************************************************** LINUX MODULE INIT ****************************************************************************/ @@ -791,13 +789,14 @@ static int cx25821_alsa_init(void) struct cx25821_dev *dev = NULL; struct list_head *list; - list_for_each(list,&cx25821_devlist) { + list_for_each(list, &cx25821_devlist) { dev = list_entry(list, struct cx25821_dev, devlist); cx25821_audio_initdev(dev); } if (dev == NULL) - printk(KERN_INFO "cx25821 ERROR ALSA: no cx25821 cards found\n"); + printk(KERN_INFO + "cx25821 ERROR ALSA: no cx25821 cards found\n"); return 0; diff --git a/linux/drivers/staging/cx25821/cx25821-audio-upstream.c b/linux/drivers/staging/cx25821/cx25821-audio-upstream.c index 376c953a8..ddddf6512 100644 --- a/linux/drivers/staging/cx25821/cx25821-audio-upstream.c +++ b/linux/drivers/staging/cx25821/cx25821-audio-upstream.c @@ -1,824 +1,804 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include "cx25821-video.h" -#include "cx25821-audio-upstream.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); -MODULE_AUTHOR("Hiep Huynh "); -MODULE_LICENSE("GPL"); - - -static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR; - - -int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, - struct sram_channel *ch, - unsigned int bpl, u32 risc) -{ - unsigned int i, lines; - u32 cdt; - - - if (ch->cmds_start == 0) { - cx_write(ch->ptr1_reg, 0); - cx_write(ch->ptr2_reg, 0); - cx_write(ch->cnt2_reg, 0); - cx_write(ch->cnt1_reg, 0); - return 0; - } - - bpl = (bpl + 7) & ~7; /* alignment */ - cdt = ch->cdt; - lines = ch->fifo_size / bpl; - - if (lines > 3) - { - lines = 3; - } - - BUG_ON(lines < 2); - - - /* write CDT */ - for (i = 0; i < lines; i++) { - cx_write(cdt + 16*i, ch->fifo_start + bpl*i); - cx_write(cdt + 16*i + 4, 0); - cx_write(cdt + 16*i + 8, 0); - cx_write(cdt + 16*i + 12, 0); - } - - /* write CMDS */ - cx_write(ch->cmds_start + 0, risc); - - cx_write(ch->cmds_start + 4, 0); - cx_write(ch->cmds_start + 8, cdt); - cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW); - cx_write(ch->cmds_start + 16, ch->ctrl_start); - - //IQ size - cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW); - - for (i = 24; i < 80; i += 4) - cx_write(ch->cmds_start + i, 0); - - /* fill registers */ - cx_write(ch->ptr1_reg, ch->fifo_start); - cx_write(ch->ptr2_reg, cdt); - cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW); - cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1); - - return 0; -} - - -static __le32 *cx25821_risc_field_upstream_audio( struct cx25821_dev *dev, __le32 *rp, - dma_addr_t databuf_phys_addr, - unsigned int bpl, int fifo_enable) -{ - unsigned int line; - struct sram_channel *sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select]; - int offset = 0; - - - /* scan lines */ - for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) - { - *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(databuf_phys_addr + offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - // Check if we need to enable the FIFO after the first 3 lines - // For the upstream audio channel, the risc engine will enable the FIFO. - if ( fifo_enable && line == 2 ) - { - *(rp++) = RISC_WRITECR; - *(rp++) = sram_ch->dma_ctl; - *(rp++) = sram_ch->fld_aud_fifo_en; - *(rp++) = 0x00000020; - } - - offset += AUDIO_LINE_SIZE; - } - - return rp; -} - -int cx25821_risc_buffer_upstream_audio( struct cx25821_dev *dev, - struct pci_dev *pci, - unsigned int bpl, unsigned int lines) -{ - __le32 *rp; - int fifo_enable = 0; - int frame = 0, i = 0; - int frame_size = AUDIO_DATA_BUF_SZ; - int databuf_offset = 0; - int risc_flag = RISC_CNT_INC; - dma_addr_t risc_phys_jump_addr; - - - /* Virtual address of Risc buffer program */ - rp = dev->_risc_virt_addr; - - /* sync instruction */ - *(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE); - - - for( frame = 0; frame < NUM_AUDIO_FRAMES; frame++ ) - { - databuf_offset = frame_size * frame; - - if( frame == 0 ) - { - fifo_enable = 1; - risc_flag = RISC_CNT_RESET; - } - else - { - fifo_enable = 0; - risc_flag = RISC_CNT_INC; - } - - //Calculate physical jump address - if( (frame+1) == NUM_AUDIO_FRAMES ) - { - risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE; - } - else - { - risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE*(frame+1); - } - - rp = cx25821_risc_field_upstream_audio(dev, rp, dev->_audiodata_buf_phys_addr+databuf_offset, bpl, fifo_enable); - - - if( USE_RISC_NOOP_AUDIO ) - { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } - } - - - // Loop to (Nth)FrameRISC or to Start of Risc program & generate IRQ - *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - - //Recalculate virtual address based on frame index - rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE/4 + (AUDIO_RISC_DMA_BUF_SIZE*(frame+1)/4 ) ; - } - - return 0; -} - - -void cx25821_free_memory_audio(struct cx25821_dev *dev) -{ - if (dev->_risc_virt_addr) - { - pci_free_consistent(dev->pci, dev->_audiorisc_size, dev->_risc_virt_addr, dev->_risc_phys_addr); - dev->_risc_virt_addr = NULL; - } - - if (dev->_audiodata_buf_virt_addr) - { - pci_free_consistent(dev->pci, dev->_audiodata_buf_size, dev->_audiodata_buf_virt_addr, dev->_audiodata_buf_phys_addr); - dev->_audiodata_buf_virt_addr = NULL; - } -} - -void cx25821_stop_upstream_audio(struct cx25821_dev *dev) -{ - struct sram_channel *sram_ch = &dev->sram_channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B]; - u32 tmp = 0; - - if( !dev->_audio_is_running ) - { - printk("cx25821: No audio file is currently running so return!\n"); - return; - } - - //Disable RISC interrupts - cx_write( sram_ch->int_msk, 0 ); - - //Turn OFF risc and fifo enable in AUD_DMA_CNTRL - tmp = cx_read( sram_ch->dma_ctl ); - cx_write( sram_ch->dma_ctl, tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en) ); - - //Clear data buffer memory - if( dev->_audiodata_buf_virt_addr ) - memset( dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size ); - - dev->_audio_is_running = 0; - dev->_is_first_audio_frame = 0; - dev->_audioframe_count = 0; - dev->_audiofile_status = END_OF_FILE; - - if( dev->_irq_audio_queues ) - { - kfree(dev->_irq_audio_queues); - dev->_irq_audio_queues = NULL; - } - - if( dev->_audiofilename != NULL ) - kfree(dev->_audiofilename); -} - - -void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev) -{ - if( dev->_audio_is_running ) - { - cx25821_stop_upstream_audio(dev); - } - - cx25821_free_memory_audio(dev); -} - - -int cx25821_get_audio_data(struct cx25821_dev *dev, struct sram_channel *sram_ch ) -{ - struct file * myfile; - int frame_index_temp = dev->_audioframe_index; - int i = 0; - int line_size = AUDIO_LINE_SIZE; - int frame_size = AUDIO_DATA_BUF_SZ; - int frame_offset = frame_size * frame_index_temp; - ssize_t vfs_read_retval = 0; - char mybuf[line_size]; - loff_t file_offset = dev->_audioframe_count * frame_size; - loff_t pos; - mm_segment_t old_fs; - - - if( dev->_audiofile_status == END_OF_FILE ) - return 0; - - myfile = filp_open( dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0 ); - - - if (IS_ERR(myfile)) - { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno); - return PTR_ERR(myfile); - } - else - { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered!\n", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered! \n", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( i = 0; i < dev->_audio_lines_count; i++ ) - { - pos = file_offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL ) - { - memcpy( (void*)(dev->_audiodata_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval); - } - - file_offset += vfs_read_retval; - frame_offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - dev->_audioframe_count++; - - dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - - set_fs(old_fs); - filp_close(myfile, NULL); - } - - return 0; -} - -static void cx25821_audioups_handler(struct work_struct *work) -{ - struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _audio_work_entry); - - if( !dev ) - { - printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); - return; - } - - cx25821_get_audio_data( dev, &dev->sram_channels[dev->_audio_upstream_channel_select] ); -} - -int cx25821_openfile_audio(struct cx25821_dev *dev, struct sram_channel *sram_ch) -{ - struct file * myfile; - int i = 0, j = 0; - int line_size = AUDIO_LINE_SIZE; - ssize_t vfs_read_retval = 0; - char mybuf[line_size]; - loff_t pos; - loff_t offset = (unsigned long)0; - mm_segment_t old_fs; - - - myfile = filp_open( dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0 ); - - - if (IS_ERR(myfile)) - { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno); - return PTR_ERR(myfile); - } - else - { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered! \n", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered! \n", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( j = 0; j < NUM_AUDIO_FRAMES; j++ ) - { - for( i = 0; i < dev->_audio_lines_count; i++ ) - { - pos = offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL ) - { - memcpy( (void*)(dev->_audiodata_buf_virt_addr+offset/4), mybuf, vfs_read_retval); - } - - offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - { - dev->_audioframe_count++; - } - - if( vfs_read_retval < line_size ) - { - break; - } - } - - dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - set_fs(old_fs); - myfile->f_pos = 0; - filp_close(myfile, NULL); - } - - return 0; -} - -static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, - struct sram_channel *sram_ch, - int bpl) -{ - int ret = 0; - dma_addr_t dma_addr; - dma_addr_t data_dma_addr; - - - cx25821_free_memory_audio(dev); - - dev->_risc_virt_addr = pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size, &dma_addr); - dev->_risc_virt_start_addr = dev->_risc_virt_addr; - dev->_risc_phys_start_addr = dma_addr; - dev->_risc_phys_addr = dma_addr; - dev->_audiorisc_size = dev->audio_upstream_riscbuf_size; - - - if (!dev->_risc_virt_addr) - { - printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n"); - return -ENOMEM; - } - - //Clear out memory at address - memset( dev->_risc_virt_addr, 0, dev->_audiorisc_size ); - - - //For Audio Data buffer allocation - dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size, &data_dma_addr); - dev->_audiodata_buf_phys_addr = data_dma_addr; - dev->_audiodata_buf_size = dev->audio_upstream_databuf_size; - - if (!dev->_audiodata_buf_virt_addr) - { - printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning. \n"); - return -ENOMEM; - } - - //Clear out memory at address - memset( dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size ); - - - ret = cx25821_openfile_audio(dev, sram_ch); - if( ret < 0 ) - return ret; - - - //Creating RISC programs - ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, dev->_audio_lines_count ); - if (ret < 0) - { - printk(KERN_DEBUG "cx25821 ERROR creating audio upstream RISC programs! \n"); - goto error; - } - - return 0; - -error: - return ret; -} - -int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, u32 status) -{ - int i = 0; - u32 int_msk_tmp; - struct sram_channel *channel = &dev->sram_channels[chan_num]; - dma_addr_t risc_phys_jump_addr; - __le32 * rp; - - - if (status & FLD_AUD_SRC_RISCI1) - { - //Get interrupt_index of the program that interrupted - u32 prog_cnt = cx_read( channel->gpcnt ); - - //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers - cx_write(channel->int_msk, 0); - cx_write(channel->int_stat, cx_read(channel->int_stat) ); - - spin_lock(&dev->slock); - - - while(prog_cnt != dev->_last_index_irq) - { - //Update _last_index_irq - if(dev->_last_index_irq < (NUMBER_OF_PROGRAMS-1)) - { - dev->_last_index_irq++; - } - else - { - dev->_last_index_irq = 0; - } - - dev->_audioframe_index = dev->_last_index_irq; - - queue_work(dev->_irq_audio_queues, &dev->_audio_work_entry); - } - - - if ( dev->_is_first_audio_frame ) - { - dev->_is_first_audio_frame = 0; - - if( dev->_risc_virt_start_addr != NULL ) - { - risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE; - - rp = cx25821_risc_field_upstream_audio(dev, dev->_risc_virt_start_addr+1, dev->_audiodata_buf_phys_addr, AUDIO_LINE_SIZE, FIFO_DISABLE); - - if( USE_RISC_NOOP_AUDIO ) - { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } - } - - // Jump to 2nd Audio Frame - *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_RESET); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - } - } - - spin_unlock(&dev->slock); - } - else - { - if(status & FLD_AUD_SRC_OF) - printk("%s: Audio Received Overflow Error Interrupt!\n", __func__); - - if(status & FLD_AUD_SRC_SYNC) - printk("%s: Audio Received Sync Error Interrupt!\n", __func__); - - if(status & FLD_AUD_SRC_OPC_ERR) - printk("%s: Audio Received OpCode Error Interrupt!\n", __func__); - - // Read and write back the interrupt status register to clear our bits - cx_write(channel->int_stat, cx_read(channel->int_stat) ); - } - - - if( dev->_audiofile_status == END_OF_FILE ) - { - printk("cx25821: EOF Channel Audio Framecount = %d\n", dev->_audioframe_count ); - return -1; - } - - //ElSE, set the interrupt mask register, re-enable irq. - int_msk_tmp = cx_read( channel->int_msk ); - cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); - - return 0; -} - -static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) -{ - struct cx25821_dev *dev = dev_id; - u32 msk_stat, audio_status; - int handled = 0; - struct sram_channel *sram_ch; - - - if( !dev ) - return -1; - - - sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select]; - - msk_stat = cx_read(sram_ch->int_mstat); - audio_status = cx_read(sram_ch->int_stat); - - // Only deal with our interrupt - if(audio_status) - { - handled = cx25821_audio_upstream_irq(dev, dev->_audio_upstream_channel_select, audio_status); - } - - - if( handled < 0 ) - { - cx25821_stop_upstream_audio(dev); - } - else - { - handled += handled; - } - - return IRQ_RETVAL(handled); -} - - -static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, struct sram_channel *sram_ch) -{ - int count = 0; - u32 tmp; - - do - { - //Wait 10 microsecond before checking to see if the FIFO is turned ON. - udelay(10); - - tmp = cx_read( sram_ch->dma_ctl ); - - if(count++ > 1000) //10 millisecond timeout - { - printk("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", __func__); - return; - } - - } while( !(tmp & sram_ch->fld_aud_fifo_en) ); - -} - - -int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, - struct sram_channel *sram_ch) -{ - u32 tmp = 0; - int err = 0; - - - // Set the physical start address of the RISC program in the initial program counter(IPC) member of the CMDS. - cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr); - cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ - - - /* reset counter */ - cx_write(sram_ch->gpcnt_ctl, 3); - - //Set the line length (It looks like we do not need to set the line length) - cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH); - - //Set the input mode to 16-bit - tmp = cx_read( sram_ch->aud_cfg ); - tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE; - cx_write( sram_ch->aud_cfg, tmp ); - - // Read and write back the interrupt status register to clear it - tmp = cx_read( sram_ch->int_stat); - cx_write( sram_ch->int_stat, tmp); - - // Clear our bits from the interrupt status register. - cx_write( sram_ch->int_stat, _intr_msk ); - - - //Set the interrupt mask register, enable irq. - cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); - tmp = cx_read( sram_ch->int_msk ); - cx_write( sram_ch->int_msk, tmp |= _intr_msk ); - - - err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); - if (err < 0) - { - printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); - goto fail_irq; - } - - - // Start the DMA engine - tmp = cx_read( sram_ch->dma_ctl ); - cx_set( sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en ); - - dev->_audio_is_running = 1; - dev->_is_first_audio_frame = 1; - - // The fifo_en bit turns on by the first Risc program - cx25821_wait_fifo_enable(dev, sram_ch); - - return 0; - - -fail_irq: - cx25821_dev_unregister(dev); - return err; -} - - -int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) -{ - struct sram_channel *sram_ch; - int retval = 0; - int err = 0; - int str_length = 0; - - if( dev->_audio_is_running ) - { - printk("Audio Channel is still running so return!\n"); - return 0; - } - - dev->_audio_upstream_channel_select = channel_select; - sram_ch = &dev->sram_channels[channel_select]; - - //Work queue - INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler); - dev->_irq_audio_queues = create_singlethread_workqueue("cx25821_audioworkqueue"); - - if(!dev->_irq_audio_queues) - { - printk("cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n"); - return -ENOMEM; - } - - - dev->_last_index_irq = 0; - dev->_audio_is_running = 0; - dev->_audioframe_count = 0; - dev->_audiofile_status = RESET_STATUS; - dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER; - _line_size = AUDIO_LINE_SIZE; - - - if( dev->input_audiofilename ) - { - str_length = strlen(dev->input_audiofilename); - dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_audiofilename ) - goto error; - - memcpy(dev->_audiofilename, dev->input_audiofilename, str_length + 1); - - //Default if filename is empty string - if( strcmp(dev->input_audiofilename,"") == 0) - { - dev->_audiofilename = "/root/audioGOOD.wav"; - } - } - else - { - str_length = strlen(_defaultAudioName); - dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_audiofilename ) - goto error; - - memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1); - } - - - retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch, _line_size, 0); - - dev->audio_upstream_riscbuf_size = AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS + RISC_SYNC_INSTRUCTION_SIZE; - dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS; - - - //Allocating buffers and prepare RISC program - retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch, _line_size); - if (retval < 0) - { - printk(KERN_ERR "%s: Failed to set up Audio upstream buffers!\n", dev->name); - goto error; - } - - //Start RISC engine - cx25821_start_audio_dma_upstream(dev, sram_ch); - - return 0; - -error: - cx25821_dev_unregister(dev); - - return err; -} +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" +#include "cx25821-audio-upstream.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); +MODULE_AUTHOR("Hiep Huynh "); +MODULE_LICENSE("GPL"); + +static int _intr_msk = + FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | FLD_AUD_SRC_SYNC | + FLD_AUD_SRC_OPC_ERR; + +int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, + struct sram_channel *ch, + unsigned int bpl, u32 risc) +{ + unsigned int i, lines; + u32 cdt; + + if (ch->cmds_start == 0) { + cx_write(ch->ptr1_reg, 0); + cx_write(ch->ptr2_reg, 0); + cx_write(ch->cnt2_reg, 0); + cx_write(ch->cnt1_reg, 0); + return 0; + } + + bpl = (bpl + 7) & ~7; /* alignment */ + cdt = ch->cdt; + lines = ch->fifo_size / bpl; + + if (lines > 3) { + lines = 3; + } + + BUG_ON(lines < 2); + + /* write CDT */ + for (i = 0; i < lines; i++) { + cx_write(cdt + 16 * i, ch->fifo_start + bpl * i); + cx_write(cdt + 16 * i + 4, 0); + cx_write(cdt + 16 * i + 8, 0); + cx_write(cdt + 16 * i + 12, 0); + } + + /* write CMDS */ + cx_write(ch->cmds_start + 0, risc); + + cx_write(ch->cmds_start + 4, 0); + cx_write(ch->cmds_start + 8, cdt); + cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW); + cx_write(ch->cmds_start + 16, ch->ctrl_start); + + //IQ size + cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW); + + for (i = 24; i < 80; i += 4) + cx_write(ch->cmds_start + i, 0); + + /* fill registers */ + cx_write(ch->ptr1_reg, ch->fifo_start); + cx_write(ch->ptr2_reg, cdt); + cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW); + cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1); + + return 0; +} + +static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev, + __le32 * rp, + dma_addr_t databuf_phys_addr, + unsigned int bpl, + int fifo_enable) +{ + unsigned int line; + struct sram_channel *sram_ch = + &dev->sram_channels[dev->_audio_upstream_channel_select]; + int offset = 0; + + /* scan lines */ + for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) { + *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); + *(rp++) = cpu_to_le32(databuf_phys_addr + offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + // Check if we need to enable the FIFO after the first 3 lines + // For the upstream audio channel, the risc engine will enable the FIFO. + if (fifo_enable && line == 2) { + *(rp++) = RISC_WRITECR; + *(rp++) = sram_ch->dma_ctl; + *(rp++) = sram_ch->fld_aud_fifo_en; + *(rp++) = 0x00000020; + } + + offset += AUDIO_LINE_SIZE; + } + + return rp; +} + +int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev, + struct pci_dev *pci, + unsigned int bpl, unsigned int lines) +{ + __le32 *rp; + int fifo_enable = 0; + int frame = 0, i = 0; + int frame_size = AUDIO_DATA_BUF_SZ; + int databuf_offset = 0; + int risc_flag = RISC_CNT_INC; + dma_addr_t risc_phys_jump_addr; + + /* Virtual address of Risc buffer program */ + rp = dev->_risc_virt_addr; + + /* sync instruction */ + *(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE); + + for (frame = 0; frame < NUM_AUDIO_FRAMES; frame++) { + databuf_offset = frame_size * frame; + + if (frame == 0) { + fifo_enable = 1; + risc_flag = RISC_CNT_RESET; + } else { + fifo_enable = 0; + risc_flag = RISC_CNT_INC; + } + + //Calculate physical jump address + if ((frame + 1) == NUM_AUDIO_FRAMES) { + risc_phys_jump_addr = + dev->_risc_phys_start_addr + + RISC_SYNC_INSTRUCTION_SIZE; + } else { + risc_phys_jump_addr = + dev->_risc_phys_start_addr + + RISC_SYNC_INSTRUCTION_SIZE + + AUDIO_RISC_DMA_BUF_SIZE * (frame + 1); + } + + rp = cx25821_risc_field_upstream_audio(dev, rp, + dev-> + _audiodata_buf_phys_addr + + databuf_offset, bpl, + fifo_enable); + + if (USE_RISC_NOOP_AUDIO) { + for (i = 0; i < NUM_NO_OPS; i++) { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + // Loop to (Nth)FrameRISC or to Start of Risc program & generate IRQ + *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + + //Recalculate virtual address based on frame index + rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 + + (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4); + } + + return 0; +} + +void cx25821_free_memory_audio(struct cx25821_dev *dev) +{ + if (dev->_risc_virt_addr) { + pci_free_consistent(dev->pci, dev->_audiorisc_size, + dev->_risc_virt_addr, dev->_risc_phys_addr); + dev->_risc_virt_addr = NULL; + } + + if (dev->_audiodata_buf_virt_addr) { + pci_free_consistent(dev->pci, dev->_audiodata_buf_size, + dev->_audiodata_buf_virt_addr, + dev->_audiodata_buf_phys_addr); + dev->_audiodata_buf_virt_addr = NULL; + } +} + +void cx25821_stop_upstream_audio(struct cx25821_dev *dev) +{ + struct sram_channel *sram_ch = + &dev->sram_channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B]; + u32 tmp = 0; + + if (!dev->_audio_is_running) { + printk + ("cx25821: No audio file is currently running so return!\n"); + return; + } + //Disable RISC interrupts + cx_write(sram_ch->int_msk, 0); + + //Turn OFF risc and fifo enable in AUD_DMA_CNTRL + tmp = cx_read(sram_ch->dma_ctl); + cx_write(sram_ch->dma_ctl, + tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en)); + + //Clear data buffer memory + if (dev->_audiodata_buf_virt_addr) + memset(dev->_audiodata_buf_virt_addr, 0, + dev->_audiodata_buf_size); + + dev->_audio_is_running = 0; + dev->_is_first_audio_frame = 0; + dev->_audioframe_count = 0; + dev->_audiofile_status = END_OF_FILE; + + if (dev->_irq_audio_queues) { + kfree(dev->_irq_audio_queues); + dev->_irq_audio_queues = NULL; + } + + if (dev->_audiofilename != NULL) + kfree(dev->_audiofilename); +} + +void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev) +{ + if (dev->_audio_is_running) { + cx25821_stop_upstream_audio(dev); + } + + cx25821_free_memory_audio(dev); +} + +int cx25821_get_audio_data(struct cx25821_dev *dev, + struct sram_channel *sram_ch) +{ + struct file *myfile; + int frame_index_temp = dev->_audioframe_index; + int i = 0; + int line_size = AUDIO_LINE_SIZE; + int frame_size = AUDIO_DATA_BUF_SZ; + int frame_offset = frame_size * frame_index_temp; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t file_offset = dev->_audioframe_count * frame_size; + loff_t pos; + mm_segment_t old_fs; + + if (dev->_audiofile_status == END_OF_FILE) + return 0; + + myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0); + + if (IS_ERR(myfile)) { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", + __func__, dev->_audiofilename, open_errno); + return PTR_ERR(myfile); + } else { + if (!(myfile->f_op)) { + printk("%s: File has no file operations registered!\n", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + if (!myfile->f_op->read) { + printk("%s: File has no READ operations registered! \n", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + for (i = 0; i < dev->_audio_lines_count; i++) { + pos = file_offset; + + vfs_read_retval = + vfs_read(myfile, mybuf, line_size, &pos); + + if (vfs_read_retval > 0 && vfs_read_retval == line_size + && dev->_audiodata_buf_virt_addr != NULL) { + memcpy((void *)(dev->_audiodata_buf_virt_addr + + frame_offset / 4), mybuf, + vfs_read_retval); + } + + file_offset += vfs_read_retval; + frame_offset += vfs_read_retval; + + if (vfs_read_retval < line_size) { + printk(KERN_INFO + "Done: exit %s() since no more bytes to read from Audio file.\n", + __func__); + break; + } + } + + if (i > 0) + dev->_audioframe_count++; + + dev->_audiofile_status = + (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + filp_close(myfile, NULL); + } + + return 0; +} + +static void cx25821_audioups_handler(struct work_struct *work) +{ + struct cx25821_dev *dev = + container_of(work, struct cx25821_dev, _audio_work_entry); + + if (!dev) { + printk("ERROR %s(): since container_of(work_struct) FAILED! \n", + __func__); + return; + } + + cx25821_get_audio_data(dev, + &dev->sram_channels[dev-> + _audio_upstream_channel_select]); +} + +int cx25821_openfile_audio(struct cx25821_dev *dev, + struct sram_channel *sram_ch) +{ + struct file *myfile; + int i = 0, j = 0; + int line_size = AUDIO_LINE_SIZE; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t pos; + loff_t offset = (unsigned long)0; + mm_segment_t old_fs; + + myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0); + + if (IS_ERR(myfile)) { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", + __func__, dev->_audiofilename, open_errno); + return PTR_ERR(myfile); + } else { + if (!(myfile->f_op)) { + printk("%s: File has no file operations registered! \n", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + if (!myfile->f_op->read) { + printk("%s: File has no READ operations registered! \n", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + for (j = 0; j < NUM_AUDIO_FRAMES; j++) { + for (i = 0; i < dev->_audio_lines_count; i++) { + pos = offset; + + vfs_read_retval = + vfs_read(myfile, mybuf, line_size, &pos); + + if (vfs_read_retval > 0 + && vfs_read_retval == line_size + && dev->_audiodata_buf_virt_addr != NULL) { + memcpy((void *)(dev-> + _audiodata_buf_virt_addr + + offset / 4), mybuf, + vfs_read_retval); + } + + offset += vfs_read_retval; + + if (vfs_read_retval < line_size) { + printk(KERN_INFO + "Done: exit %s() since no more bytes to read from Audio file.\n", + __func__); + break; + } + } + + if (i > 0) { + dev->_audioframe_count++; + } + + if (vfs_read_retval < line_size) { + break; + } + } + + dev->_audiofile_status = + (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + myfile->f_pos = 0; + filp_close(myfile, NULL); + } + + return 0; +} + +static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, + struct sram_channel *sram_ch, + int bpl) +{ + int ret = 0; + dma_addr_t dma_addr; + dma_addr_t data_dma_addr; + + cx25821_free_memory_audio(dev); + + dev->_risc_virt_addr = + pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size, + &dma_addr); + dev->_risc_virt_start_addr = dev->_risc_virt_addr; + dev->_risc_phys_start_addr = dma_addr; + dev->_risc_phys_addr = dma_addr; + dev->_audiorisc_size = dev->audio_upstream_riscbuf_size; + + if (!dev->_risc_virt_addr) { + printk + ("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n"); + return -ENOMEM; + } + //Clear out memory at address + memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size); + + //For Audio Data buffer allocation + dev->_audiodata_buf_virt_addr = + pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size, + &data_dma_addr); + dev->_audiodata_buf_phys_addr = data_dma_addr; + dev->_audiodata_buf_size = dev->audio_upstream_databuf_size; + + if (!dev->_audiodata_buf_virt_addr) { + printk + ("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning. \n"); + return -ENOMEM; + } + //Clear out memory at address + memset(dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size); + + ret = cx25821_openfile_audio(dev, sram_ch); + if (ret < 0) + return ret; + + //Creating RISC programs + ret = + cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, + dev->_audio_lines_count); + if (ret < 0) { + printk(KERN_DEBUG + "cx25821 ERROR creating audio upstream RISC programs! \n"); + goto error; + } + + return 0; + + error: + return ret; +} + +int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, + u32 status) +{ + int i = 0; + u32 int_msk_tmp; + struct sram_channel *channel = &dev->sram_channels[chan_num]; + dma_addr_t risc_phys_jump_addr; + __le32 *rp; + + if (status & FLD_AUD_SRC_RISCI1) { + //Get interrupt_index of the program that interrupted + u32 prog_cnt = cx_read(channel->gpcnt); + + //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers + cx_write(channel->int_msk, 0); + cx_write(channel->int_stat, cx_read(channel->int_stat)); + + spin_lock(&dev->slock); + + while (prog_cnt != dev->_last_index_irq) { + //Update _last_index_irq + if (dev->_last_index_irq < (NUMBER_OF_PROGRAMS - 1)) { + dev->_last_index_irq++; + } else { + dev->_last_index_irq = 0; + } + + dev->_audioframe_index = dev->_last_index_irq; + + queue_work(dev->_irq_audio_queues, + &dev->_audio_work_entry); + } + + if (dev->_is_first_audio_frame) { + dev->_is_first_audio_frame = 0; + + if (dev->_risc_virt_start_addr != NULL) { + risc_phys_jump_addr = + dev->_risc_phys_start_addr + + RISC_SYNC_INSTRUCTION_SIZE + + AUDIO_RISC_DMA_BUF_SIZE; + + rp = cx25821_risc_field_upstream_audio(dev, + dev-> + _risc_virt_start_addr + + 1, + dev-> + _audiodata_buf_phys_addr, + AUDIO_LINE_SIZE, + FIFO_DISABLE); + + if (USE_RISC_NOOP_AUDIO) { + for (i = 0; i < NUM_NO_OPS; i++) { + *(rp++) = + cpu_to_le32(RISC_NOOP); + } + } + // Jump to 2nd Audio Frame + *(rp++) = + cpu_to_le32(RISC_JUMP | RISC_IRQ1 | + RISC_CNT_RESET); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + } + + spin_unlock(&dev->slock); + } else { + if (status & FLD_AUD_SRC_OF) + printk("%s: Audio Received Overflow Error Interrupt!\n", + __func__); + + if (status & FLD_AUD_SRC_SYNC) + printk("%s: Audio Received Sync Error Interrupt!\n", + __func__); + + if (status & FLD_AUD_SRC_OPC_ERR) + printk("%s: Audio Received OpCode Error Interrupt!\n", + __func__); + + // Read and write back the interrupt status register to clear our bits + cx_write(channel->int_stat, cx_read(channel->int_stat)); + } + + if (dev->_audiofile_status == END_OF_FILE) { + printk("cx25821: EOF Channel Audio Framecount = %d\n", + dev->_audioframe_count); + return -1; + } + //ElSE, set the interrupt mask register, re-enable irq. + int_msk_tmp = cx_read(channel->int_msk); + cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); + + return 0; +} + +static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) +{ + struct cx25821_dev *dev = dev_id; + u32 msk_stat, audio_status; + int handled = 0; + struct sram_channel *sram_ch; + + if (!dev) + return -1; + + sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select]; + + msk_stat = cx_read(sram_ch->int_mstat); + audio_status = cx_read(sram_ch->int_stat); + + // Only deal with our interrupt + if (audio_status) { + handled = + cx25821_audio_upstream_irq(dev, + dev-> + _audio_upstream_channel_select, + audio_status); + } + + if (handled < 0) { + cx25821_stop_upstream_audio(dev); + } else { + handled += handled; + } + + return IRQ_RETVAL(handled); +} + +static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, + struct sram_channel *sram_ch) +{ + int count = 0; + u32 tmp; + + do { + //Wait 10 microsecond before checking to see if the FIFO is turned ON. + udelay(10); + + tmp = cx_read(sram_ch->dma_ctl); + + if (count++ > 1000) //10 millisecond timeout + { + printk + ("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", + __func__); + return; + } + + } while (!(tmp & sram_ch->fld_aud_fifo_en)); + +} + +int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, + struct sram_channel *sram_ch) +{ + u32 tmp = 0; + int err = 0; + + // Set the physical start address of the RISC program in the initial program counter(IPC) member of the CMDS. + cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr); + cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ + + /* reset counter */ + cx_write(sram_ch->gpcnt_ctl, 3); + + //Set the line length (It looks like we do not need to set the line length) + cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH); + + //Set the input mode to 16-bit + tmp = cx_read(sram_ch->aud_cfg); + tmp |= + FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | + FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE; + cx_write(sram_ch->aud_cfg, tmp); + + // Read and write back the interrupt status register to clear it + tmp = cx_read(sram_ch->int_stat); + cx_write(sram_ch->int_stat, tmp); + + // Clear our bits from the interrupt status register. + cx_write(sram_ch->int_stat, _intr_msk); + + //Set the interrupt mask register, enable irq. + cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); + tmp = cx_read(sram_ch->int_msk); + cx_write(sram_ch->int_msk, tmp |= _intr_msk); + + err = + request_irq(dev->pci->irq, cx25821_upstream_irq_audio, + IRQF_SHARED | IRQF_DISABLED, dev->name, dev); + if (err < 0) { + printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, + dev->pci->irq); + goto fail_irq; + } + + // Start the DMA engine + tmp = cx_read(sram_ch->dma_ctl); + cx_set(sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en); + + dev->_audio_is_running = 1; + dev->_is_first_audio_frame = 1; + + // The fifo_en bit turns on by the first Risc program + cx25821_wait_fifo_enable(dev, sram_ch); + + return 0; + + fail_irq: + cx25821_dev_unregister(dev); + return err; +} + +int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) +{ + struct sram_channel *sram_ch; + int retval = 0; + int err = 0; + int str_length = 0; + + if (dev->_audio_is_running) { + printk("Audio Channel is still running so return!\n"); + return 0; + } + + dev->_audio_upstream_channel_select = channel_select; + sram_ch = &dev->sram_channels[channel_select]; + + //Work queue + INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler); + dev->_irq_audio_queues = + create_singlethread_workqueue("cx25821_audioworkqueue"); + + if (!dev->_irq_audio_queues) { + printk + ("cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n"); + return -ENOMEM; + } + + dev->_last_index_irq = 0; + dev->_audio_is_running = 0; + dev->_audioframe_count = 0; + dev->_audiofile_status = RESET_STATUS; + dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER; + _line_size = AUDIO_LINE_SIZE; + + if (dev->input_audiofilename) { + str_length = strlen(dev->input_audiofilename); + dev->_audiofilename = + (char *)kmalloc(str_length + 1, GFP_KERNEL); + + if (!dev->_audiofilename) + goto error; + + memcpy(dev->_audiofilename, dev->input_audiofilename, + str_length + 1); + + //Default if filename is empty string + if (strcmp(dev->input_audiofilename, "") == 0) { + dev->_audiofilename = "/root/audioGOOD.wav"; + } + } else { + str_length = strlen(_defaultAudioName); + dev->_audiofilename = + (char *)kmalloc(str_length + 1, GFP_KERNEL); + + if (!dev->_audiofilename) + goto error; + + memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1); + } + + retval = + cx25821_sram_channel_setup_upstream_audio(dev, sram_ch, _line_size, + 0); + + dev->audio_upstream_riscbuf_size = + AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS + + RISC_SYNC_INSTRUCTION_SIZE; + dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS; + + //Allocating buffers and prepare RISC program + retval = + cx25821_audio_upstream_buffer_prepare(dev, sram_ch, _line_size); + if (retval < 0) { + printk(KERN_ERR + "%s: Failed to set up Audio upstream buffers!\n", + dev->name); + goto error; + } + //Start RISC engine + cx25821_start_audio_dma_upstream(dev, sram_ch); + + return 0; + + error: + cx25821_dev_unregister(dev); + + return err; +} diff --git a/linux/drivers/staging/cx25821/cx25821-audio-upstream.h b/linux/drivers/staging/cx25821/cx25821-audio-upstream.h index a7120ee48..db1ce7bf4 100644 --- a/linux/drivers/staging/cx25821/cx25821-audio-upstream.h +++ b/linux/drivers/staging/cx25821/cx25821-audio-upstream.h @@ -1,63 +1,58 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "compat.h" -#include -#include - - -#define NUM_AUDIO_PROGS 8 -#define NUM_AUDIO_FRAMES 8 -#define END_OF_FILE 0 -#define IN_PROGRESS 1 -#define RESET_STATUS -1 -#define FIFO_DISABLE 0 -#define FIFO_ENABLE 1 -#define NUM_NO_OPS 4 - - -#define RISC_READ_INSTRUCTION_SIZE 12 -#define RISC_JUMP_INSTRUCTION_SIZE 12 -#define RISC_WRITECR_INSTRUCTION_SIZE 16 -#define RISC_SYNC_INSTRUCTION_SIZE 4 -#define DWORD_SIZE 4 -#define AUDIO_SYNC_LINE 4 - - -#define LINES_PER_AUDIO_BUFFER 15 -#define AUDIO_LINE_SIZE 128 -#define AUDIO_DATA_BUF_SZ (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER) - -#define USE_RISC_NOOP_AUDIO 1 - -#ifdef USE_RISC_NOOP_AUDIO -#define AUDIO_RISC_DMA_BUF_SIZE ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE + RISC_JUMP_INSTRUCTION_SIZE) -#endif - - -#ifndef USE_RISC_NOOP_AUDIO -#define AUDIO_RISC_DMA_BUF_SIZE ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE) -#endif - -static int _line_size; -char * _defaultAudioName = "/root/audioGOOD.wav"; - +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "compat.h" +#include +#include + +#define NUM_AUDIO_PROGS 8 +#define NUM_AUDIO_FRAMES 8 +#define END_OF_FILE 0 +#define IN_PROGRESS 1 +#define RESET_STATUS -1 +#define FIFO_DISABLE 0 +#define FIFO_ENABLE 1 +#define NUM_NO_OPS 4 + +#define RISC_READ_INSTRUCTION_SIZE 12 +#define RISC_JUMP_INSTRUCTION_SIZE 12 +#define RISC_WRITECR_INSTRUCTION_SIZE 16 +#define RISC_SYNC_INSTRUCTION_SIZE 4 +#define DWORD_SIZE 4 +#define AUDIO_SYNC_LINE 4 + +#define LINES_PER_AUDIO_BUFFER 15 +#define AUDIO_LINE_SIZE 128 +#define AUDIO_DATA_BUF_SZ (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER) + +#define USE_RISC_NOOP_AUDIO 1 + +#ifdef USE_RISC_NOOP_AUDIO +#define AUDIO_RISC_DMA_BUF_SIZE ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE + RISC_JUMP_INSTRUCTION_SIZE) +#endif + +#ifndef USE_RISC_NOOP_AUDIO +#define AUDIO_RISC_DMA_BUF_SIZE ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE) +#endif + +static int _line_size; +char *_defaultAudioName = "/root/audioGOOD.wav"; diff --git a/linux/drivers/staging/cx25821/cx25821-audio.h b/linux/drivers/staging/cx25821/cx25821-audio.h index 1e1351800..503f42f03 100644 --- a/linux/drivers/staging/cx25821/cx25821-audio.h +++ b/linux/drivers/staging/cx25821/cx25821-audio.h @@ -1,60 +1,57 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __CX25821_AUDIO_H__ -#define __CX25821_AUDIO_H__ - - -#define USE_RISC_NOOP 1 -#define LINES_PER_BUFFER 15 -#define AUDIO_LINE_SIZE 128 - -//Number of buffer programs to use at once. -#define NUMBER_OF_PROGRAMS 8 - -//Max size of the RISC program for a buffer. - worst case is 2 writes per line -// Space is also added for the 4 no-op instructions added on the end. - -#ifndef USE_RISC_NOOP -#define MAX_BUFFER_PROGRAM_SIZE \ - (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE*4) -#endif - -// MAE 12 July 2005 Try to use NOOP RISC instruction instead -#ifdef USE_RISC_NOOP -#define MAX_BUFFER_PROGRAM_SIZE \ - (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_NOOP_INSTRUCTION_SIZE*4) -#endif - - -//Sizes of various instructions in bytes. Used when adding instructions. -#define RISC_WRITE_INSTRUCTION_SIZE 12 -#define RISC_JUMP_INSTRUCTION_SIZE 12 -#define RISC_SKIP_INSTRUCTION_SIZE 4 -#define RISC_SYNC_INSTRUCTION_SIZE 4 -#define RISC_WRITECR_INSTRUCTION_SIZE 16 -#define RISC_NOOP_INSTRUCTION_SIZE 4 - -#define MAX_AUDIO_DMA_BUFFER_SIZE (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE) - -#endif - +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __CX25821_AUDIO_H__ +#define __CX25821_AUDIO_H__ + +#define USE_RISC_NOOP 1 +#define LINES_PER_BUFFER 15 +#define AUDIO_LINE_SIZE 128 + +//Number of buffer programs to use at once. +#define NUMBER_OF_PROGRAMS 8 + +//Max size of the RISC program for a buffer. - worst case is 2 writes per line +// Space is also added for the 4 no-op instructions added on the end. + +#ifndef USE_RISC_NOOP +#define MAX_BUFFER_PROGRAM_SIZE \ + (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE*4) +#endif + +// MAE 12 July 2005 Try to use NOOP RISC instruction instead +#ifdef USE_RISC_NOOP +#define MAX_BUFFER_PROGRAM_SIZE \ + (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_NOOP_INSTRUCTION_SIZE*4) +#endif + +//Sizes of various instructions in bytes. Used when adding instructions. +#define RISC_WRITE_INSTRUCTION_SIZE 12 +#define RISC_JUMP_INSTRUCTION_SIZE 12 +#define RISC_SKIP_INSTRUCTION_SIZE 4 +#define RISC_SYNC_INSTRUCTION_SIZE 4 +#define RISC_WRITECR_INSTRUCTION_SIZE 16 +#define RISC_NOOP_INSTRUCTION_SIZE 4 + +#define MAX_AUDIO_DMA_BUFFER_SIZE (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE) + +#endif diff --git a/linux/drivers/staging/cx25821/cx25821-audups11.c b/linux/drivers/staging/cx25821/cx25821-audups11.c index 4a60be2f6..f78b8912d 100644 --- a/linux/drivers/staging/cx25821/cx25821-audups11.c +++ b/linux/drivers/staging/cx25821/cx25821-audups11.c @@ -23,419 +23,412 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH11]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH11]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH11]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[SRAM_CH11]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH11] && h->video_dev[SRAM_CH11]->minor == minor) - { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH11] + && h->video_dev[SRAM_CH11]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; - } + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; - dev->channel_opened = 10; - fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); + dev->channel_opened = 10; + fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); - v4l2_prio_open(&dev->prio,&fh->prio); + v4l2_prio_open(&dev->prio, &fh->prio); - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); - return 0; + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO11)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO11)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO11)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; - return 0; -} + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO11)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + return POLLIN | POLLRDNORM; + return 0; +} static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - //cx_write(channel11->dma_ctl, 0); + //stop the risc engine and fifo + //cx_write(channel11->dma_ctl, 0); - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO11)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO11); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO11)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO11); + } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); + v4l2_prio_close(&dev->prio, &fh->prio); - file->private_data = NULL; - kfree(fh); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO11)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO11)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO11); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO11); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vidq.field = f->fmt.pix.field; - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - return 0; + return err; + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vidq.field = f->fmt.pix.field; + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + return 0; } -static long video_ioctl_upstream11(struct file *file, unsigned int cmd, unsigned long arg) +static long video_ioctl_upstream11(struct file *file, unsigned int cmd, + unsigned long arg) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - int command = 0; - struct upstream_user_struct *data_from_user; - - - data_from_user = (struct upstream_user_struct *)arg; - - if( !data_from_user ) - { - printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); - return 0; - } - - command = data_from_user->command; - - if( command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO ) - { - return 0; - } + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + int command = 0; + struct upstream_user_struct *data_from_user; + + data_from_user = (struct upstream_user_struct *)arg; + + if (!data_from_user) { + printk + ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", + __func__); + return 0; + } + command = data_from_user->command; - dev->input_filename = data_from_user->input_filename; - dev->input_audiofilename = data_from_user->input_filename; - dev->vid_stdname = data_from_user->vid_stdname; - dev->pixel_format = data_from_user->pixel_format; - dev->channel_select = data_from_user->channel_select; - dev->command = data_from_user->command; + if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO) { + return 0; + } + dev->input_filename = data_from_user->input_filename; + dev->input_audiofilename = data_from_user->input_filename; + dev->vid_stdname = data_from_user->vid_stdname; + dev->pixel_format = data_from_user->pixel_format; + dev->channel_select = data_from_user->channel_select; + dev->command = data_from_user->command; - switch(command) - { + switch (command) { case UPSTREAM_START_AUDIO: - cx25821_start_upstream_audio(dev, data_from_user); - break; + cx25821_start_upstream_audio(dev, data_from_user); + break; case UPSTREAM_STOP_AUDIO: - cx25821_stop_upstream_audio(dev); - break; - } + cx25821_stop_upstream_audio(dev); + break; + } - return 0; + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct cx25821_fh *fh = priv; - return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + struct cx25821_fh *fh = priv; + return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + cx25821_call_all(dev, core, log_status); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; - } - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + return 0; } + // exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl_upstream11, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl_upstream11, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_video_template11 = { - .name = "cx25821-audioupstream", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-audioupstream", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821-biffuncs.h b/linux/drivers/staging/cx25821/cx25821-biffuncs.h index da826cb34..9326a7c72 100644 --- a/linux/drivers/staging/cx25821/cx25821-biffuncs.h +++ b/linux/drivers/staging/cx25821/cx25821-biffuncs.h @@ -1,45 +1,45 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _BITFUNCS_H -#define _BITFUNCS_H - -#define SetBit(Bit) (1 << Bit) - -inline u8 getBit(u32 sample, u8 index) -{ - return (u8) ((sample >> index) & 1); -} - -inline u32 clearBitAtPos(u32 value, u8 bit) -{ - return value & ~(1 << bit); -} - -inline u32 setBitAtPos(u32 sample, u8 bit) -{ - sample |= (1 << bit); - return sample; - -} - -#endif \ No newline at end of file +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _BITFUNCS_H +#define _BITFUNCS_H + +#define SetBit(Bit) (1 << Bit) + +inline u8 getBit(u32 sample, u8 index) +{ + return (u8) ((sample >> index) & 1); +} + +inline u32 clearBitAtPos(u32 value, u8 bit) +{ + return value & ~(1 << bit); +} + +inline u32 setBitAtPos(u32 sample, u8 bit) +{ + sample |= (1 << bit); + return sample; + +} + +#endif diff --git a/linux/drivers/staging/cx25821/cx25821-cards.c b/linux/drivers/staging/cx25821/cx25821-cards.c index 9eeed2d95..d4f663908 100644 --- a/linux/drivers/staging/cx25821/cx25821-cards.c +++ b/linux/drivers/staging/cx25821/cx25821-cards.c @@ -1,26 +1,26 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * Based on Steven Toth cx23885 driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + #include #include #include @@ -35,39 +35,37 @@ struct cx25821_board cx25821_boards[] = { [UNKNOWN_BOARD] = { - .name = "UNKNOWN/GENERIC", - // Ensure safe default for unknown boards - .clk_freq = 0, - }, + .name = "UNKNOWN/GENERIC", + // Ensure safe default for unknown boards + .clk_freq = 0, + }, [CX25821_BOARD] = { - .name = "CX25821", - .portb = CX25821_RAW, - .portc = CX25821_264, - .input[0].type = CX25821_VMUX_COMPOSITE, - }, + .name = "CX25821", + .portb = CX25821_RAW, + .portc = CX25821_264, + .input[0].type = CX25821_VMUX_COMPOSITE, + }, }; const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards); -struct cx25821_subid cx25821_subids[]={ - { - .subvendor = 0x14f1, - .subdevice = 0x0920, - .card = CX25821_BOARD, - }, +struct cx25821_subid cx25821_subids[] = { + { + .subvendor = 0x14f1, + .subdevice = 0x0920, + .card = CX25821_BOARD, + }, }; - void cx25821_card_setup(struct cx25821_dev *dev) { static u8 eeprom[256]; - if (dev->i2c_bus[0].i2c_rc == 0) - { + if (dev->i2c_bus[0].i2c_rc == 0) { dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; - tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); + tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, + sizeof(eeprom)); } } - diff --git a/linux/drivers/staging/cx25821/cx25821-core.c b/linux/drivers/staging/cx25821/cx25821-core.c index 175ac3fa0..3eca513c5 100644 --- a/linux/drivers/staging/cx25821/cx25821-core.c +++ b/linux/drivers/staging/cx25821/cx25821-core.c @@ -36,287 +36,283 @@ static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable debug messages"); -static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; -module_param_array(card, int, NULL, 0444); +static unsigned int card[] = {[0...(CX25821_MAXBOARDS - 1)] = UNSET }; +module_param_array(card, int, NULL, 0444); MODULE_PARM_DESC(card, "card type"); - static unsigned int cx25821_devcount = 0; static DEFINE_MUTEX(devlist); LIST_HEAD(cx25821_devlist); - struct sram_channel cx25821_sram_channels[] = { - [SRAM_CH00] = { - .i = SRAM_CH00, - .name = "VID A", - .cmds_start = VID_A_DOWN_CMDS, - .ctrl_start = VID_A_IQ, - .cdt = VID_A_CDT, - .fifo_start = VID_A_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA1_PTR1, - .ptr2_reg = DMA1_PTR2, - .cnt1_reg = DMA1_CNT1, - .cnt2_reg = DMA1_CNT2, - .int_msk = VID_A_INT_MSK, - .int_stat = VID_A_INT_STAT, - .int_mstat = VID_A_INT_MSTAT, - .dma_ctl = VID_DST_A_DMA_CTL, - .gpcnt_ctl = VID_DST_A_GPCNT_CTL, - .gpcnt = VID_DST_A_GPCNT, - .vip_ctl = VID_DST_A_VIP_CTL, - .pix_frmt = VID_DST_A_PIX_FRMT, - }, - - [SRAM_CH01] = { - .i = SRAM_CH01, - .name = "VID B", - .cmds_start = VID_B_DOWN_CMDS, - .ctrl_start = VID_B_IQ, - .cdt = VID_B_CDT, - .fifo_start = VID_B_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA2_PTR1, - .ptr2_reg = DMA2_PTR2, - .cnt1_reg = DMA2_CNT1, - .cnt2_reg = DMA2_CNT2, - .int_msk = VID_B_INT_MSK, - .int_stat = VID_B_INT_STAT, - .int_mstat = VID_B_INT_MSTAT, - .dma_ctl = VID_DST_B_DMA_CTL, - .gpcnt_ctl = VID_DST_B_GPCNT_CTL, - .gpcnt = VID_DST_B_GPCNT, - .vip_ctl = VID_DST_B_VIP_CTL, - .pix_frmt = VID_DST_B_PIX_FRMT, - }, - - [SRAM_CH02] = { - .i = SRAM_CH02, - .name = "VID C", - .cmds_start = VID_C_DOWN_CMDS, - .ctrl_start = VID_C_IQ, - .cdt = VID_C_CDT, - .fifo_start = VID_C_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA3_PTR1, - .ptr2_reg = DMA3_PTR2, - .cnt1_reg = DMA3_CNT1, - .cnt2_reg = DMA3_CNT2, - .int_msk = VID_C_INT_MSK, - .int_stat = VID_C_INT_STAT, - .int_mstat = VID_C_INT_MSTAT, - .dma_ctl = VID_DST_C_DMA_CTL, - .gpcnt_ctl = VID_DST_C_GPCNT_CTL, - .gpcnt = VID_DST_C_GPCNT, - .vip_ctl = VID_DST_C_VIP_CTL, - .pix_frmt = VID_DST_C_PIX_FRMT, - }, - - [SRAM_CH03] = { - .i = SRAM_CH03, - .name = "VID D", - .cmds_start = VID_D_DOWN_CMDS, - .ctrl_start = VID_D_IQ, - .cdt = VID_D_CDT, - .fifo_start = VID_D_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA4_PTR1, - .ptr2_reg = DMA4_PTR2, - .cnt1_reg = DMA4_CNT1, - .cnt2_reg = DMA4_CNT2, - .int_msk = VID_D_INT_MSK, - .int_stat = VID_D_INT_STAT, - .int_mstat = VID_D_INT_MSTAT, - .dma_ctl = VID_DST_D_DMA_CTL, - .gpcnt_ctl = VID_DST_D_GPCNT_CTL, - .gpcnt = VID_DST_D_GPCNT, - .vip_ctl = VID_DST_D_VIP_CTL, - .pix_frmt = VID_DST_D_PIX_FRMT, - }, - - [SRAM_CH04] = { - .i = SRAM_CH04, - .name = "VID E", - .cmds_start = VID_E_DOWN_CMDS, - .ctrl_start = VID_E_IQ, - .cdt = VID_E_CDT, - .fifo_start = VID_E_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA5_PTR1, - .ptr2_reg = DMA5_PTR2, - .cnt1_reg = DMA5_CNT1, - .cnt2_reg = DMA5_CNT2, - .int_msk = VID_E_INT_MSK, - .int_stat = VID_E_INT_STAT, - .int_mstat = VID_E_INT_MSTAT, - .dma_ctl = VID_DST_E_DMA_CTL, - .gpcnt_ctl = VID_DST_E_GPCNT_CTL, - .gpcnt = VID_DST_E_GPCNT, - .vip_ctl = VID_DST_E_VIP_CTL, - .pix_frmt = VID_DST_E_PIX_FRMT, - }, - - [SRAM_CH05] = { - .i = SRAM_CH05, - .name = "VID F", - .cmds_start = VID_F_DOWN_CMDS, - .ctrl_start = VID_F_IQ, - .cdt = VID_F_CDT, - .fifo_start = VID_F_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA6_PTR1, - .ptr2_reg = DMA6_PTR2, - .cnt1_reg = DMA6_CNT1, - .cnt2_reg = DMA6_CNT2, - .int_msk = VID_F_INT_MSK, - .int_stat = VID_F_INT_STAT, - .int_mstat = VID_F_INT_MSTAT, - .dma_ctl = VID_DST_F_DMA_CTL, - .gpcnt_ctl = VID_DST_F_GPCNT_CTL, - .gpcnt = VID_DST_F_GPCNT, - .vip_ctl = VID_DST_F_VIP_CTL, - .pix_frmt = VID_DST_F_PIX_FRMT, - }, - - [SRAM_CH06] = { - .i = SRAM_CH06, - .name = "VID G", - .cmds_start = VID_G_DOWN_CMDS, - .ctrl_start = VID_G_IQ, - .cdt = VID_G_CDT, - .fifo_start = VID_G_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA7_PTR1, - .ptr2_reg = DMA7_PTR2, - .cnt1_reg = DMA7_CNT1, - .cnt2_reg = DMA7_CNT2, - .int_msk = VID_G_INT_MSK, - .int_stat = VID_G_INT_STAT, - .int_mstat = VID_G_INT_MSTAT, - .dma_ctl = VID_DST_G_DMA_CTL, - .gpcnt_ctl = VID_DST_G_GPCNT_CTL, - .gpcnt = VID_DST_G_GPCNT, - .vip_ctl = VID_DST_G_VIP_CTL, - .pix_frmt = VID_DST_G_PIX_FRMT, - }, - - [SRAM_CH07] = { - .i = SRAM_CH07, - .name = "VID H", - .cmds_start = VID_H_DOWN_CMDS, - .ctrl_start = VID_H_IQ, - .cdt = VID_H_CDT, - .fifo_start = VID_H_DOWN_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA8_PTR1, - .ptr2_reg = DMA8_PTR2, - .cnt1_reg = DMA8_CNT1, - .cnt2_reg = DMA8_CNT2, - .int_msk = VID_H_INT_MSK, - .int_stat = VID_H_INT_STAT, - .int_mstat = VID_H_INT_MSTAT, - .dma_ctl = VID_DST_H_DMA_CTL, - .gpcnt_ctl = VID_DST_H_GPCNT_CTL, - .gpcnt = VID_DST_H_GPCNT, - .vip_ctl = VID_DST_H_VIP_CTL, - .pix_frmt = VID_DST_H_PIX_FRMT, - }, - - [SRAM_CH08] = { - .name = "audio from", - .cmds_start = AUD_A_DOWN_CMDS, - .ctrl_start = AUD_A_IQ, - .cdt = AUD_A_CDT, - .fifo_start = AUD_A_DOWN_CLUSTER_1, - .fifo_size = AUDIO_CLUSTER_SIZE * 3, - .ptr1_reg = DMA17_PTR1, - .ptr2_reg = DMA17_PTR2, - .cnt1_reg = DMA17_CNT1, - .cnt2_reg = DMA17_CNT2, - }, - - [SRAM_CH09] = { - .i = SRAM_CH09, - .name = "VID Upstream I", - .cmds_start = VID_I_UP_CMDS, - .ctrl_start = VID_I_IQ, - .cdt = VID_I_CDT, - .fifo_start = VID_I_UP_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA15_PTR1, - .ptr2_reg = DMA15_PTR2, - .cnt1_reg = DMA15_CNT1, - .cnt2_reg = DMA15_CNT2, - .int_msk = VID_I_INT_MSK, - .int_stat = VID_I_INT_STAT, - .int_mstat = VID_I_INT_MSTAT, - .dma_ctl = VID_SRC_I_DMA_CTL, - .gpcnt_ctl = VID_SRC_I_GPCNT_CTL, - .gpcnt = VID_SRC_I_GPCNT, - - .vid_fmt_ctl = VID_SRC_I_FMT_CTL, - .vid_active_ctl1= VID_SRC_I_ACTIVE_CTL1, - .vid_active_ctl2= VID_SRC_I_ACTIVE_CTL2, - .vid_cdt_size = VID_SRC_I_CDT_SZ, - .irq_bit = 8, - }, - - [SRAM_CH10] = { - .i = SRAM_CH10, - .name = "VID Upstream J", - .cmds_start = VID_J_UP_CMDS, - .ctrl_start = VID_J_IQ, - .cdt = VID_J_CDT, - .fifo_start = VID_J_UP_CLUSTER_1, - .fifo_size = (VID_CLUSTER_SIZE<<2), - .ptr1_reg = DMA16_PTR1, - .ptr2_reg = DMA16_PTR2, - .cnt1_reg = DMA16_CNT1, - .cnt2_reg = DMA16_CNT2, - .int_msk = VID_J_INT_MSK, - .int_stat = VID_J_INT_STAT, - .int_mstat = VID_J_INT_MSTAT, - .dma_ctl = VID_SRC_J_DMA_CTL, - .gpcnt_ctl = VID_SRC_J_GPCNT_CTL, - .gpcnt = VID_SRC_J_GPCNT, - - .vid_fmt_ctl = VID_SRC_J_FMT_CTL, - .vid_active_ctl1= VID_SRC_J_ACTIVE_CTL1, - .vid_active_ctl2= VID_SRC_J_ACTIVE_CTL2, - .vid_cdt_size = VID_SRC_J_CDT_SZ, - .irq_bit = 9, - }, - - - [SRAM_CH11] = { - .i = SRAM_CH11, - .name = "Audio Upstream Channel B", - .cmds_start = AUD_B_UP_CMDS, - .ctrl_start = AUD_B_IQ, - .cdt = AUD_B_CDT, - .fifo_start = AUD_B_UP_CLUSTER_1, - .fifo_size = (AUDIO_CLUSTER_SIZE*3), - .ptr1_reg = DMA22_PTR1, - .ptr2_reg = DMA22_PTR2, - .cnt1_reg = DMA22_CNT1, - .cnt2_reg = DMA22_CNT2, - .int_msk = AUD_B_INT_MSK, - .int_stat = AUD_B_INT_STAT, - .int_mstat = AUD_B_INT_MSTAT, - .dma_ctl = AUD_INT_DMA_CTL, - .gpcnt_ctl = AUD_B_GPCNT_CTL, - .gpcnt = AUD_B_GPCNT, - .aud_length = AUD_B_LNGTH, - .aud_cfg = AUD_B_CFG, - .fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN, - .fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN, - .irq_bit = 11, - }, + [SRAM_CH00] = { + .i = SRAM_CH00, + .name = "VID A", + .cmds_start = VID_A_DOWN_CMDS, + .ctrl_start = VID_A_IQ, + .cdt = VID_A_CDT, + .fifo_start = VID_A_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE << 2), + .ptr1_reg = DMA1_PTR1, + .ptr2_reg = DMA1_PTR2, + .cnt1_reg = DMA1_CNT1, + .cnt2_reg = DMA1_CNT2, + .int_msk = VID_A_INT_MSK, + .int_stat = VID_A_INT_STAT, + .int_mstat = VID_A_INT_MSTAT, + .dma_ctl = VID_DST_A_DMA_CTL, + .gpcnt_ctl = VID_DST_A_GPCNT_CTL, + .gpcnt = VID_DST_A_GPCNT, + .vip_ctl = VID_DST_A_VIP_CTL, + .pix_frmt = VID_DST_A_PIX_FRMT, + }, + + [SRAM_CH01] = { + .i = SRAM_CH01, + .name = "VID B", + .cmds_start = VID_B_DOWN_CMDS, + .ctrl_start = VID_B_IQ, + .cdt = VID_B_CDT, + .fifo_start = VID_B_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE << 2), + .ptr1_reg = DMA2_PTR1, + .ptr2_reg = DMA2_PTR2, + .cnt1_reg = DMA2_CNT1, + .cnt2_reg = DMA2_CNT2, + .int_msk = VID_B_INT_MSK, + .int_stat = VID_B_INT_STAT, + .int_mstat = VID_B_INT_MSTAT, + .dma_ctl = VID_DST_B_DMA_CTL, + .gpcnt_ctl = VID_DST_B_GPCNT_CTL, + .gpcnt = VID_DST_B_GPCNT, + .vip_ctl = VID_DST_B_VIP_CTL, + .pix_frmt = VID_DST_B_PIX_FRMT, + }, + + [SRAM_CH02] = { + .i = SRAM_CH02, + .name = "VID C", + .cmds_start = VID_C_DOWN_CMDS, + .ctrl_start = VID_C_IQ, + .cdt = VID_C_CDT, + .fifo_start = VID_C_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE << 2), + .ptr1_reg = DMA3_PTR1, + .ptr2_reg = DMA3_PTR2, + .cnt1_reg = DMA3_CNT1, + .cnt2_reg = DMA3_CNT2, + .int_msk = VID_C_INT_MSK, + .int_stat = VID_C_INT_STAT, + .int_mstat = VID_C_INT_MSTAT, + .dma_ctl = VID_DST_C_DMA_CTL, + .gpcnt_ctl = VID_DST_C_GPCNT_CTL, + .gpcnt = VID_DST_C_GPCNT, + .vip_ctl = VID_DST_C_VIP_CTL, + .pix_frmt = VID_DST_C_PIX_FRMT, + }, + + [SRAM_CH03] = { + .i = SRAM_CH03, + .name = "VID D", + .cmds_start = VID_D_DOWN_CMDS, + .ctrl_start = VID_D_IQ, + .cdt = VID_D_CDT, + .fifo_start = VID_D_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE << 2), + .ptr1_reg = DMA4_PTR1, + .ptr2_reg = DMA4_PTR2, + .cnt1_reg = DMA4_CNT1, + .cnt2_reg = DMA4_CNT2, + .int_msk = VID_D_INT_MSK, + .int_stat = VID_D_INT_STAT, + .int_mstat = VID_D_INT_MSTAT, + .dma_ctl = VID_DST_D_DMA_CTL, + .gpcnt_ctl = VID_DST_D_GPCNT_CTL, + .gpcnt = VID_DST_D_GPCNT, + .vip_ctl = VID_DST_D_VIP_CTL, + .pix_frmt = VID_DST_D_PIX_FRMT, + }, + + [SRAM_CH04] = { + .i = SRAM_CH04, + .name = "VID E", + .cmds_start = VID_E_DOWN_CMDS, + .ctrl_start = VID_E_IQ, + .cdt = VID_E_CDT, + .fifo_start = VID_E_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE << 2), + .ptr1_reg = DMA5_PTR1, + .ptr2_reg = DMA5_PTR2, + .cnt1_reg = DMA5_CNT1, + .cnt2_reg = DMA5_CNT2, + .int_msk = VID_E_INT_MSK, + .int_stat = VID_E_INT_STAT, + .int_mstat = VID_E_INT_MSTAT, + .dma_ctl = VID_DST_E_DMA_CTL, + .gpcnt_ctl = VID_DST_E_GPCNT_CTL, + .gpcnt = VID_DST_E_GPCNT, + .vip_ctl = VID_DST_E_VIP_CTL, + .pix_frmt = VID_DST_E_PIX_FRMT, + }, + + [SRAM_CH05] = { + .i = SRAM_CH05, + .name = "VID F", + .cmds_start = VID_F_DOWN_CMDS, + .ctrl_start = VID_F_IQ, + .cdt = VID_F_CDT, + .fifo_start = VID_F_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE << 2), + .ptr1_reg = DMA6_PTR1, + .ptr2_reg = DMA6_PTR2, + .cnt1_reg = DMA6_CNT1, + .cnt2_reg = DMA6_CNT2, + .int_msk = VID_F_INT_MSK, + .int_stat = VID_F_INT_STAT, + .int_mstat = VID_F_INT_MSTAT, + .dma_ctl = VID_DST_F_DMA_CTL, + .gpcnt_ctl = VID_DST_F_GPCNT_CTL, + .gpcnt = VID_DST_F_GPCNT, + .vip_ctl = VID_DST_F_VIP_CTL, + .pix_frmt = VID_DST_F_PIX_FRMT, + }, + + [SRAM_CH06] = { + .i = SRAM_CH06, + .name = "VID G", + .cmds_start = VID_G_DOWN_CMDS, + .ctrl_start = VID_G_IQ, + .cdt = VID_G_CDT, + .fifo_start = VID_G_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE << 2), + .ptr1_reg = DMA7_PTR1, + .ptr2_reg = DMA7_PTR2, + .cnt1_reg = DMA7_CNT1, + .cnt2_reg = DMA7_CNT2, + .int_msk = VID_G_INT_MSK, + .int_stat = VID_G_INT_STAT, + .int_mstat = VID_G_INT_MSTAT, + .dma_ctl = VID_DST_G_DMA_CTL, + .gpcnt_ctl = VID_DST_G_GPCNT_CTL, + .gpcnt = VID_DST_G_GPCNT, + .vip_ctl = VID_DST_G_VIP_CTL, + .pix_frmt = VID_DST_G_PIX_FRMT, + }, + + [SRAM_CH07] = { + .i = SRAM_CH07, + .name = "VID H", + .cmds_start = VID_H_DOWN_CMDS, + .ctrl_start = VID_H_IQ, + .cdt = VID_H_CDT, + .fifo_start = VID_H_DOWN_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE << 2), + .ptr1_reg = DMA8_PTR1, + .ptr2_reg = DMA8_PTR2, + .cnt1_reg = DMA8_CNT1, + .cnt2_reg = DMA8_CNT2, + .int_msk = VID_H_INT_MSK, + .int_stat = VID_H_INT_STAT, + .int_mstat = VID_H_INT_MSTAT, + .dma_ctl = VID_DST_H_DMA_CTL, + .gpcnt_ctl = VID_DST_H_GPCNT_CTL, + .gpcnt = VID_DST_H_GPCNT, + .vip_ctl = VID_DST_H_VIP_CTL, + .pix_frmt = VID_DST_H_PIX_FRMT, + }, + + [SRAM_CH08] = { + .name = "audio from", + .cmds_start = AUD_A_DOWN_CMDS, + .ctrl_start = AUD_A_IQ, + .cdt = AUD_A_CDT, + .fifo_start = AUD_A_DOWN_CLUSTER_1, + .fifo_size = AUDIO_CLUSTER_SIZE * 3, + .ptr1_reg = DMA17_PTR1, + .ptr2_reg = DMA17_PTR2, + .cnt1_reg = DMA17_CNT1, + .cnt2_reg = DMA17_CNT2, + }, + + [SRAM_CH09] = { + .i = SRAM_CH09, + .name = "VID Upstream I", + .cmds_start = VID_I_UP_CMDS, + .ctrl_start = VID_I_IQ, + .cdt = VID_I_CDT, + .fifo_start = VID_I_UP_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE << 2), + .ptr1_reg = DMA15_PTR1, + .ptr2_reg = DMA15_PTR2, + .cnt1_reg = DMA15_CNT1, + .cnt2_reg = DMA15_CNT2, + .int_msk = VID_I_INT_MSK, + .int_stat = VID_I_INT_STAT, + .int_mstat = VID_I_INT_MSTAT, + .dma_ctl = VID_SRC_I_DMA_CTL, + .gpcnt_ctl = VID_SRC_I_GPCNT_CTL, + .gpcnt = VID_SRC_I_GPCNT, + + .vid_fmt_ctl = VID_SRC_I_FMT_CTL, + .vid_active_ctl1 = VID_SRC_I_ACTIVE_CTL1, + .vid_active_ctl2 = VID_SRC_I_ACTIVE_CTL2, + .vid_cdt_size = VID_SRC_I_CDT_SZ, + .irq_bit = 8, + }, + + [SRAM_CH10] = { + .i = SRAM_CH10, + .name = "VID Upstream J", + .cmds_start = VID_J_UP_CMDS, + .ctrl_start = VID_J_IQ, + .cdt = VID_J_CDT, + .fifo_start = VID_J_UP_CLUSTER_1, + .fifo_size = (VID_CLUSTER_SIZE << 2), + .ptr1_reg = DMA16_PTR1, + .ptr2_reg = DMA16_PTR2, + .cnt1_reg = DMA16_CNT1, + .cnt2_reg = DMA16_CNT2, + .int_msk = VID_J_INT_MSK, + .int_stat = VID_J_INT_STAT, + .int_mstat = VID_J_INT_MSTAT, + .dma_ctl = VID_SRC_J_DMA_CTL, + .gpcnt_ctl = VID_SRC_J_GPCNT_CTL, + .gpcnt = VID_SRC_J_GPCNT, + + .vid_fmt_ctl = VID_SRC_J_FMT_CTL, + .vid_active_ctl1 = VID_SRC_J_ACTIVE_CTL1, + .vid_active_ctl2 = VID_SRC_J_ACTIVE_CTL2, + .vid_cdt_size = VID_SRC_J_CDT_SZ, + .irq_bit = 9, + }, + + [SRAM_CH11] = { + .i = SRAM_CH11, + .name = "Audio Upstream Channel B", + .cmds_start = AUD_B_UP_CMDS, + .ctrl_start = AUD_B_IQ, + .cdt = AUD_B_CDT, + .fifo_start = AUD_B_UP_CLUSTER_1, + .fifo_size = (AUDIO_CLUSTER_SIZE * 3), + .ptr1_reg = DMA22_PTR1, + .ptr2_reg = DMA22_PTR2, + .cnt1_reg = DMA22_CNT1, + .cnt2_reg = DMA22_CNT2, + .int_msk = AUD_B_INT_MSK, + .int_stat = AUD_B_INT_STAT, + .int_mstat = AUD_B_INT_MSTAT, + .dma_ctl = AUD_INT_DMA_CTL, + .gpcnt_ctl = AUD_B_GPCNT_CTL, + .gpcnt = AUD_B_GPCNT, + .aud_length = AUD_B_LNGTH, + .aud_cfg = AUD_B_CFG, + .fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN, + .fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN, + .irq_bit = 11, + }, }; - struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00]; struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01]; struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02]; @@ -333,1242 +329,1233 @@ struct cx25821_dmaqueue mpegq; static int cx25821_risc_decode(u32 risc) { - static char *instr[16] = { - [RISC_SYNC >> 28] = "sync", - [RISC_WRITE >> 28] = "write", - [RISC_WRITEC >> 28] = "writec", - [RISC_READ >> 28] = "read", - [RISC_READC >> 28] = "readc", - [RISC_JUMP >> 28] = "jump", - [RISC_SKIP >> 28] = "skip", - [RISC_WRITERM >> 28] = "writerm", - [RISC_WRITECM >> 28] = "writecm", - [RISC_WRITECR >> 28] = "writecr", - }; - static int incr[16] = { - [RISC_WRITE >> 28] = 3, - [RISC_JUMP >> 28] = 3, - [RISC_SKIP >> 28] = 1, - [RISC_SYNC >> 28] = 1, - [RISC_WRITERM >> 28] = 3, - [RISC_WRITECM >> 28] = 3, - [RISC_WRITECR >> 28] = 4, - }; - static char *bits[] = { - "12", "13", "14", "resync", - "cnt0", "cnt1", "18", "19", - "20", "21", "22", "23", - "irq1", "irq2", "eol", "sol", - }; - int i; - - printk("0x%08x [ %s", risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); - for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) - { - if (risc & (1 << (i + 12))) - printk(" %s", bits[i]); + static char *instr[16] = { + [RISC_SYNC >> 28] = "sync", + [RISC_WRITE >> 28] = "write", + [RISC_WRITEC >> 28] = "writec", + [RISC_READ >> 28] = "read", + [RISC_READC >> 28] = "readc", + [RISC_JUMP >> 28] = "jump", + [RISC_SKIP >> 28] = "skip", + [RISC_WRITERM >> 28] = "writerm", + [RISC_WRITECM >> 28] = "writecm", + [RISC_WRITECR >> 28] = "writecr", + }; + static int incr[16] = { + [RISC_WRITE >> 28] = 3, + [RISC_JUMP >> 28] = 3, + [RISC_SKIP >> 28] = 1, + [RISC_SYNC >> 28] = 1, + [RISC_WRITERM >> 28] = 3, + [RISC_WRITECM >> 28] = 3, + [RISC_WRITECR >> 28] = 4, + }; + static char *bits[] = { + "12", "13", "14", "resync", + "cnt0", "cnt1", "18", "19", + "20", "21", "22", "23", + "irq1", "irq2", "eol", "sol", + }; + int i; + + printk("0x%08x [ %s", risc, + instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); + for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) { + if (risc & (1 << (i + 12))) + printk(" %s", bits[i]); } - printk(" count=%d ]\n", risc & 0xfff); - return incr[risc >> 28] ? incr[risc >> 28] : 1; + printk(" count=%d ]\n", risc & 0xfff); + return incr[risc >> 28] ? incr[risc >> 28] : 1; } static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap) { - struct cx25821_i2c *bus = i2c_adap->algo_data; - struct cx25821_dev *dev = bus->dev; - return cx_read(bus->reg_stat) & 0x01; + struct cx25821_i2c *bus = i2c_adap->algo_data; + struct cx25821_dev *dev = bus->dev; + return cx_read(bus->reg_stat) & 0x01; } - -void cx_i2c_read_print(struct cx25821_dev *dev, u32 reg, const char* reg_string) +void cx_i2c_read_print(struct cx25821_dev *dev, u32 reg, const char *reg_string) { - int tmp = 0; - u32 value = 0; + int tmp = 0; + u32 value = 0; - value = cx25821_i2c_read(&dev->i2c_bus[0], reg, &tmp); + value = cx25821_i2c_read(&dev->i2c_bus[0], reg, &tmp); } static void cx25821_registers_init(struct cx25821_dev *dev) { - u32 tmp; + u32 tmp; - // enable RUN_RISC in Pecos - cx_write( DEV_CNTRL2, 0x20 ); + // enable RUN_RISC in Pecos + cx_write(DEV_CNTRL2, 0x20); - // Set the master PCI interrupt masks to enable video, audio, MBIF, and GPIO interrupts - // I2C interrupt masking is handled by the I2C objects themselves. - cx_write( PCI_INT_MSK, 0x2001FFFF ); + // Set the master PCI interrupt masks to enable video, audio, MBIF, and GPIO interrupts + // I2C interrupt masking is handled by the I2C objects themselves. + cx_write(PCI_INT_MSK, 0x2001FFFF); - tmp = cx_read( RDR_TLCTL0 ); - tmp &= ~FLD_CFG_RCB_CK_EN; // Clear the RCB_CK_EN bit - cx_write( RDR_TLCTL0, tmp); + tmp = cx_read(RDR_TLCTL0); + tmp &= ~FLD_CFG_RCB_CK_EN; // Clear the RCB_CK_EN bit + cx_write(RDR_TLCTL0, tmp); - // PLL-A setting for the Audio Master Clock - cx_write( PLL_A_INT_FRAC, 0x9807A58B ); + // PLL-A setting for the Audio Master Clock + cx_write(PLL_A_INT_FRAC, 0x9807A58B); - // PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 - cx_write( PLL_A_POST_STAT_BIST, 0x8000019C); + // PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 + cx_write(PLL_A_POST_STAT_BIST, 0x8000019C); - // clear reset bit [31] - tmp = cx_read( PLL_A_INT_FRAC ); - cx_write( PLL_A_INT_FRAC, tmp & 0x7FFFFFFF); + // clear reset bit [31] + tmp = cx_read(PLL_A_INT_FRAC); + cx_write(PLL_A_INT_FRAC, tmp & 0x7FFFFFFF); - // PLL-B setting for Mobilygen Host Bus Interface - cx_write( PLL_B_INT_FRAC, 0x9883A86F); + // PLL-B setting for Mobilygen Host Bus Interface + cx_write(PLL_B_INT_FRAC, 0x9883A86F); - // PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 - cx_write( PLL_B_POST_STAT_BIST, 0x8000018D); + // PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 + cx_write(PLL_B_POST_STAT_BIST, 0x8000018D); - // clear reset bit [31] - tmp = cx_read( PLL_B_INT_FRAC ); - cx_write( PLL_B_INT_FRAC, tmp & 0x7FFFFFFF); + // clear reset bit [31] + tmp = cx_read(PLL_B_INT_FRAC); + cx_write(PLL_B_INT_FRAC, tmp & 0x7FFFFFFF); - // PLL-C setting for video upstream channel - cx_write( PLL_C_INT_FRAC, 0x96A0EA3F); + // PLL-C setting for video upstream channel + cx_write(PLL_C_INT_FRAC, 0x96A0EA3F); - // PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 - cx_write( PLL_C_POST_STAT_BIST, 0x80000103); + // PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 + cx_write(PLL_C_POST_STAT_BIST, 0x80000103); - // clear reset bit [31] - tmp = cx_read( PLL_C_INT_FRAC ); - cx_write( PLL_C_INT_FRAC, tmp & 0x7FFFFFFF); + // clear reset bit [31] + tmp = cx_read(PLL_C_INT_FRAC); + cx_write(PLL_C_INT_FRAC, tmp & 0x7FFFFFFF); - // PLL-D setting for audio upstream channel - cx_write( PLL_D_INT_FRAC, 0x98757F5B); + // PLL-D setting for audio upstream channel + cx_write(PLL_D_INT_FRAC, 0x98757F5B); - // PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 - cx_write( PLL_D_POST_STAT_BIST, 0x80000113); + // PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 + cx_write(PLL_D_POST_STAT_BIST, 0x80000113); - // clear reset bit [31] - tmp = cx_read( PLL_D_INT_FRAC ); - cx_write( PLL_D_INT_FRAC, tmp & 0x7FFFFFFF); + // clear reset bit [31] + tmp = cx_read(PLL_D_INT_FRAC); + cx_write(PLL_D_INT_FRAC, tmp & 0x7FFFFFFF); + // This selects the PLL C clock source for the video upstream channel I and J + tmp = cx_read(VID_CH_CLK_SEL); + cx_write(VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000); - // This selects the PLL C clock source for the video upstream channel I and J - tmp = cx_read( VID_CH_CLK_SEL ); - cx_write( VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000); + // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + //select 656/VIP DST for downstream Channel A - C + tmp = cx_read(VID_CH_MODE_SEL); + //cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); + cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); + // enables 656 port I and J as output + tmp = cx_read(CLK_RST); + tmp |= FLD_USE_ALT_PLL_REF; // use external ALT_PLL_REF pin as its reference clock instead + cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE)); - // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C - //select 656/VIP DST for downstream Channel A - C - tmp = cx_read( VID_CH_MODE_SEL ); - //cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); - cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); + mdelay(100); +} +int cx25821_sram_channel_setup(struct cx25821_dev *dev, + struct sram_channel *ch, + unsigned int bpl, u32 risc) +{ + unsigned int i, lines; + u32 cdt; + + if (ch->cmds_start == 0) { + cx_write(ch->ptr1_reg, 0); + cx_write(ch->ptr2_reg, 0); + cx_write(ch->cnt2_reg, 0); + cx_write(ch->cnt1_reg, 0); + return 0; + } - // enables 656 port I and J as output - tmp = cx_read( CLK_RST ); - tmp |= FLD_USE_ALT_PLL_REF; // use external ALT_PLL_REF pin as its reference clock instead - cx_write( CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE) ); + bpl = (bpl + 7) & ~7; /* alignment */ + cdt = ch->cdt; + lines = ch->fifo_size / bpl; - mdelay(100); -} + if (lines > 4) { + lines = 4; + } + BUG_ON(lines < 2); + + cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + cx_write(8 + 4, 8); + cx_write(8 + 8, 0); + + /* write CDT */ + for (i = 0; i < lines; i++) { + cx_write(cdt + 16 * i, ch->fifo_start + bpl * i); + cx_write(cdt + 16 * i + 4, 0); + cx_write(cdt + 16 * i + 8, 0); + cx_write(cdt + 16 * i + 12, 0); + } + + //init the first cdt buffer + for (i = 0; i < 128; i++) + cx_write(ch->fifo_start + 4 * i, i); + + /* write CMDS */ + if (ch->jumponly) { + cx_write(ch->cmds_start + 0, 8); + } else { + cx_write(ch->cmds_start + 0, risc); + } + + cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ + cx_write(ch->cmds_start + 8, cdt); + cx_write(ch->cmds_start + 12, (lines * 16) >> 3); + cx_write(ch->cmds_start + 16, ch->ctrl_start); + + if (ch->jumponly) + cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); + else + cx_write(ch->cmds_start + 20, 64 >> 2); + + for (i = 24; i < 80; i += 4) + cx_write(ch->cmds_start + i, 0); + + /* fill registers */ + cx_write(ch->ptr1_reg, ch->fifo_start); + cx_write(ch->ptr2_reg, cdt); + cx_write(ch->cnt2_reg, (lines * 16) >> 3); + cx_write(ch->cnt1_reg, (bpl >> 3) - 1); -int cx25821_sram_channel_setup(struct cx25821_dev *dev, - struct sram_channel *ch, - unsigned int bpl, u32 risc) -{ - unsigned int i, lines; - u32 cdt; - - if (ch->cmds_start == 0) { - cx_write(ch->ptr1_reg, 0); - cx_write(ch->ptr2_reg, 0); - cx_write(ch->cnt2_reg, 0); - cx_write(ch->cnt1_reg, 0); return 0; - } - - bpl = (bpl + 7) & ~7; /* alignment */ - cdt = ch->cdt; - lines = ch->fifo_size / bpl; - - if (lines > 4) - { - lines = 4; - } - - BUG_ON(lines < 2); - - cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - cx_write(8 + 4, 8); - cx_write(8 + 8, 0); - - /* write CDT */ - for (i = 0; i < lines; i++) { - cx_write(cdt + 16*i, ch->fifo_start + bpl*i); - cx_write(cdt + 16*i + 4, 0); - cx_write(cdt + 16*i + 8, 0); - cx_write(cdt + 16*i + 12, 0); - } - - //init the first cdt buffer - for(i=0; i<128; i++) - cx_write(ch->fifo_start+4*i, i); - - /* write CMDS */ - if (ch->jumponly) - { - cx_write(ch->cmds_start + 0, 8); - } - else - { - cx_write(ch->cmds_start + 0, risc); - } - - cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ - cx_write(ch->cmds_start + 8, cdt); - cx_write(ch->cmds_start + 12, (lines*16) >> 3); - cx_write(ch->cmds_start + 16, ch->ctrl_start); - - if (ch->jumponly) - cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); - else - cx_write(ch->cmds_start + 20, 64 >> 2); - - for (i = 24; i < 80; i += 4) - cx_write(ch->cmds_start + i, 0); - - /* fill registers */ - cx_write(ch->ptr1_reg, ch->fifo_start); - cx_write(ch->ptr2_reg, cdt); - cx_write(ch->cnt2_reg, (lines*16) >> 3); - cx_write(ch->cnt1_reg, (bpl >> 3) - 1); - - return 0; } int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, - struct sram_channel *ch, - unsigned int bpl, u32 risc) + struct sram_channel *ch, + unsigned int bpl, u32 risc) { - unsigned int i, lines; - u32 cdt; + unsigned int i, lines; + u32 cdt; + + if (ch->cmds_start == 0) { + cx_write(ch->ptr1_reg, 0); + cx_write(ch->ptr2_reg, 0); + cx_write(ch->cnt2_reg, 0); + cx_write(ch->cnt1_reg, 0); + return 0; + } + bpl = (bpl + 7) & ~7; /* alignment */ + cdt = ch->cdt; + lines = ch->fifo_size / bpl; + + if (lines > 3) { + lines = 3; //for AUDIO + } + + BUG_ON(lines < 2); + + cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + cx_write(8 + 4, 8); + cx_write(8 + 8, 0); + + /* write CDT */ + for (i = 0; i < lines; i++) { + cx_write(cdt + 16 * i, ch->fifo_start + bpl * i); + cx_write(cdt + 16 * i + 4, 0); + cx_write(cdt + 16 * i + 8, 0); + cx_write(cdt + 16 * i + 12, 0); + } + + /* write CMDS */ + if (ch->jumponly) { + cx_write(ch->cmds_start + 0, 8); + } else { + cx_write(ch->cmds_start + 0, risc); + } + + cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ + cx_write(ch->cmds_start + 8, cdt); + cx_write(ch->cmds_start + 12, (lines * 16) >> 3); + cx_write(ch->cmds_start + 16, ch->ctrl_start); + + //IQ size + if (ch->jumponly) { + cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); + } else { + cx_write(ch->cmds_start + 20, 64 >> 2); + } + + //zero out + for (i = 24; i < 80; i += 4) + cx_write(ch->cmds_start + i, 0); + + /* fill registers */ + cx_write(ch->ptr1_reg, ch->fifo_start); + cx_write(ch->ptr2_reg, cdt); + cx_write(ch->cnt2_reg, (lines * 16) >> 3); + cx_write(ch->cnt1_reg, (bpl >> 3) - 1); - if (ch->cmds_start == 0) { - cx_write(ch->ptr1_reg, 0); - cx_write(ch->ptr2_reg, 0); - cx_write(ch->cnt2_reg, 0); - cx_write(ch->cnt1_reg, 0); return 0; - } - - bpl = (bpl + 7) & ~7; /* alignment */ - cdt = ch->cdt; - lines = ch->fifo_size / bpl; - - if (lines > 3) - { - lines = 3; //for AUDIO - } - - BUG_ON(lines < 2); - - - cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - cx_write(8 + 4, 8); - cx_write(8 + 8, 0); - - /* write CDT */ - for (i = 0; i < lines; i++) { - cx_write(cdt + 16*i, ch->fifo_start + bpl*i); - cx_write(cdt + 16*i + 4, 0); - cx_write(cdt + 16*i + 8, 0); - cx_write(cdt + 16*i + 12, 0); - } - - /* write CMDS */ - if (ch->jumponly) - { - cx_write(ch->cmds_start + 0, 8); - } - else - { - cx_write(ch->cmds_start + 0, risc); - } - - cx_write(ch->cmds_start + 4, 0); /* 64 bits 63-32 */ - cx_write(ch->cmds_start + 8, cdt); - cx_write(ch->cmds_start + 12, (lines*16) >> 3); - cx_write(ch->cmds_start + 16, ch->ctrl_start); - - //IQ size - if (ch->jumponly) - { - cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2)); - } - else - { - cx_write(ch->cmds_start + 20, 64 >> 2); - } - - //zero out - for (i = 24; i < 80; i += 4) - cx_write(ch->cmds_start + i, 0); - - /* fill registers */ - cx_write(ch->ptr1_reg, ch->fifo_start); - cx_write(ch->ptr2_reg, cdt); - cx_write(ch->cnt2_reg, (lines*16) >> 3); - cx_write(ch->cnt1_reg, (bpl >> 3) - 1); - - return 0; } - void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) { - static char *name[] = { - "init risc lo", - "init risc hi", - "cdt base", - "cdt size", - "iq base", - "iq size", - "risc pc lo", - "risc pc hi", - "iq wr ptr", - "iq rd ptr", - "cdt current", - "pci target lo", - "pci target hi", - "line / byte", - }; - u32 risc; - unsigned int i, j, n; - - printk(KERN_WARNING "%s: %s - dma channel status dump\n", dev->name, ch->name); - for (i = 0; i < ARRAY_SIZE(name); i++) - printk(KERN_WARNING "cmds + 0x%2x: %-15s: 0x%08x\n", i*4, name[i], - cx_read(ch->cmds_start + 4*i)); - - j=i*4; - for (i = 0; i < 4; ) { - risc = cx_read(ch->cmds_start + 4 * (i + 14)); - printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j+i*4, i); - i +=cx25821_risc_decode(risc); - } - - for (i = 0; i < (64 >> 2); i += n) { - risc = cx_read(ch->ctrl_start + 4 * i); - /* No consideration for bits 63-32 */ - - printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i); - n = cx25821_risc_decode(risc); - for (j = 1; j < n; j++) { - risc = cx_read(ch->ctrl_start + 4 * (i + j)); - printk(KERN_WARNING "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j); + static char *name[] = { + "init risc lo", + "init risc hi", + "cdt base", + "cdt size", + "iq base", + "iq size", + "risc pc lo", + "risc pc hi", + "iq wr ptr", + "iq rd ptr", + "cdt current", + "pci target lo", + "pci target hi", + "line / byte", + }; + u32 risc; + unsigned int i, j, n; + + printk(KERN_WARNING "%s: %s - dma channel status dump\n", dev->name, + ch->name); + for (i = 0; i < ARRAY_SIZE(name); i++) + printk(KERN_WARNING "cmds + 0x%2x: %-15s: 0x%08x\n", i * 4, + name[i], cx_read(ch->cmds_start + 4 * i)); + + j = i * 4; + for (i = 0; i < 4;) { + risc = cx_read(ch->cmds_start + 4 * (i + 14)); + printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j + i * 4, i); + i += cx25821_risc_decode(risc); } - } - - printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", ch->fifo_start, ch->fifo_start+ch->fifo_size); - printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", ch->ctrl_start, ch->ctrl_start + 6*16); - printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", cx_read(ch->ptr1_reg)); - printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", cx_read(ch->ptr2_reg)); - printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", cx_read(ch->cnt1_reg)); - printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", cx_read(ch->cnt2_reg)); + + for (i = 0; i < (64 >> 2); i += n) { + risc = cx_read(ch->ctrl_start + 4 * i); + /* No consideration for bits 63-32 */ + + printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4, + ch->ctrl_start + 4 * i, i); + n = cx25821_risc_decode(risc); + for (j = 1; j < n; j++) { + risc = cx_read(ch->ctrl_start + 4 * (i + j)); + printk(KERN_WARNING + "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", + 4 * (i + j), i + j, risc, j); + } + } + + printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", + ch->fifo_start, ch->fifo_start + ch->fifo_size); + printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", + ch->ctrl_start, ch->ctrl_start + 6 * 16); + printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", + cx_read(ch->ptr1_reg)); + printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", + cx_read(ch->ptr2_reg)); + printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", + cx_read(ch->cnt1_reg)); + printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", + cx_read(ch->cnt2_reg)); } -void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channel *ch) +void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, + struct sram_channel *ch) { - static char *name[] = { - "init risc lo", - "init risc hi", - "cdt base", - "cdt size", - "iq base", - "iq size", - "risc pc lo", - "risc pc hi", - "iq wr ptr", - "iq rd ptr", - "cdt current", - "pci target lo", - "pci target hi", - "line / byte", - }; + static char *name[] = { + "init risc lo", + "init risc hi", + "cdt base", + "cdt size", + "iq base", + "iq size", + "risc pc lo", + "risc pc hi", + "iq wr ptr", + "iq rd ptr", + "cdt current", + "pci target lo", + "pci target hi", + "line / byte", + }; u32 risc, value, tmp; - unsigned int i, j, n; + unsigned int i, j, n; + printk(KERN_INFO "\n%s: %s - dma Audio channel status dump\n", + dev->name, ch->name); - printk(KERN_INFO "\n%s: %s - dma Audio channel status dump\n", dev->name, ch->name); + for (i = 0; i < ARRAY_SIZE(name); i++) + printk(KERN_INFO "%s: cmds + 0x%2x: %-15s: 0x%08x\n", + dev->name, i * 4, name[i], + cx_read(ch->cmds_start + 4 * i)); - for (i = 0; i < ARRAY_SIZE(name); i++) - printk(KERN_INFO "%s: cmds + 0x%2x: %-15s: 0x%08x\n", dev->name, i*4, name[i], cx_read(ch->cmds_start + 4*i)); + j = i * 4; + for (i = 0; i < 4;) { + risc = cx_read(ch->cmds_start + 4 * (i + 14)); + printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j + i * 4, i); + i += cx25821_risc_decode(risc); + } + for (i = 0; i < (64 >> 2); i += n) { + risc = cx_read(ch->ctrl_start + 4 * i); + /* No consideration for bits 63-32 */ - j=i*4; - for (i = 0; i < 4; ) { - risc = cx_read(ch->cmds_start + 4 * (i + 14)); - printk(KERN_WARNING "cmds + 0x%2x: risc%d: ", j+i*4, i); - i += cx25821_risc_decode(risc); - } + printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i * 4, + ch->ctrl_start + 4 * i, i); + n = cx25821_risc_decode(risc); - for (i = 0; i < (64 >> 2); i += n) { - risc = cx_read(ch->ctrl_start + 4 * i); - /* No consideration for bits 63-32 */ + for (j = 1; j < n; j++) { + risc = cx_read(ch->ctrl_start + 4 * (i + j)); + printk(KERN_WARNING + "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", + 4 * (i + j), i + j, risc, j); + } + } - printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i); - n = cx25821_risc_decode(risc); + printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", + ch->fifo_start, ch->fifo_start + ch->fifo_size); + printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", + ch->ctrl_start, ch->ctrl_start + 6 * 16); + printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", + cx_read(ch->ptr1_reg)); + printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", + cx_read(ch->ptr2_reg)); + printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", + cx_read(ch->cnt1_reg)); + printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", + cx_read(ch->cnt2_reg)); + + for (i = 0; i < 4; i++) { + risc = cx_read(ch->cmds_start + 56 + (i * 4)); + printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc); + } - for (j = 1; j < n; j++) { - risc = cx_read(ch->ctrl_start + 4 * (i + j)); - printk(KERN_WARNING "ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j); + //read data from the first cdt buffer + risc = cx_read(AUD_A_CDT); + printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc); + for (i = 0; i < 8; i++) { + n = cx_read(risc + i * 4); + printk(KERN_WARNING "0x%x ", n); } - } - - printk(KERN_WARNING " : fifo: 0x%08x -> 0x%x\n", ch->fifo_start, ch->fifo_start+ch->fifo_size); - printk(KERN_WARNING " : ctrl: 0x%08x -> 0x%x\n", ch->ctrl_start, ch->ctrl_start + 6*16); - printk(KERN_WARNING " : ptr1_reg: 0x%08x\n", cx_read(ch->ptr1_reg)); - printk(KERN_WARNING " : ptr2_reg: 0x%08x\n", cx_read(ch->ptr2_reg)); - printk(KERN_WARNING " : cnt1_reg: 0x%08x\n", cx_read(ch->cnt1_reg)); - printk(KERN_WARNING " : cnt2_reg: 0x%08x\n", cx_read(ch->cnt2_reg)); - - for( i=0; i < 4; i++) - { - risc = cx_read(ch->cmds_start + 56 + (i*4)); - printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc); - } - - //read data from the first cdt buffer - risc = cx_read(AUD_A_CDT); - printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc); - for(i=0; i<8; i++) - { - n = cx_read(risc+i*4); - printk(KERN_WARNING "0x%x ", n); - } - printk(KERN_WARNING "\n\n"); - - - value = cx_read(CLK_RST); - CX25821_INFO(" CLK_RST = 0x%x \n\n", value); - - value = cx_read(PLL_A_POST_STAT_BIST); - CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x \n\n", value); - value = cx_read(PLL_A_INT_FRAC); - CX25821_INFO(" PLL_A_INT_FRAC = 0x%x \n\n", value); - - value = cx_read(PLL_B_POST_STAT_BIST); - CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x \n\n", value); - value = cx_read(PLL_B_INT_FRAC); - CX25821_INFO(" PLL_B_INT_FRAC = 0x%x \n\n", value); - - value = cx_read(PLL_C_POST_STAT_BIST); - CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x \n\n", value); - value = cx_read(PLL_C_INT_FRAC); - CX25821_INFO(" PLL_C_INT_FRAC = 0x%x \n\n", value); - - value = cx_read(PLL_D_POST_STAT_BIST); - CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x \n\n", value); - value = cx_read(PLL_D_INT_FRAC); - CX25821_INFO(" PLL_D_INT_FRAC = 0x%x \n\n", value); - - value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); - CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x \n\n", value); + printk(KERN_WARNING "\n\n"); + + value = cx_read(CLK_RST); + CX25821_INFO(" CLK_RST = 0x%x \n\n", value); + + value = cx_read(PLL_A_POST_STAT_BIST); + CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x \n\n", value); + value = cx_read(PLL_A_INT_FRAC); + CX25821_INFO(" PLL_A_INT_FRAC = 0x%x \n\n", value); + + value = cx_read(PLL_B_POST_STAT_BIST); + CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x \n\n", value); + value = cx_read(PLL_B_INT_FRAC); + CX25821_INFO(" PLL_B_INT_FRAC = 0x%x \n\n", value); + + value = cx_read(PLL_C_POST_STAT_BIST); + CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x \n\n", value); + value = cx_read(PLL_C_INT_FRAC); + CX25821_INFO(" PLL_C_INT_FRAC = 0x%x \n\n", value); + + value = cx_read(PLL_D_POST_STAT_BIST); + CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x \n\n", value); + value = cx_read(PLL_D_INT_FRAC); + CX25821_INFO(" PLL_D_INT_FRAC = 0x%x \n\n", value); + + value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); + CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x \n\n", value); } static void cx25821_shutdown(struct cx25821_dev *dev) { - int i; + int i; - /* disable RISC controller */ - cx_write(DEV_CNTRL2, 0); + /* disable RISC controller */ + cx_write(DEV_CNTRL2, 0); - /* Disable Video A/B activity */ - for(i=0; isram_channels[i].dma_ctl, 0); - cx_write(dev->sram_channels[i].int_msk, 0); - } + /* Disable Video A/B activity */ + for (i = 0; i < VID_CHANNEL_NUM; i++) { + cx_write(dev->sram_channels[i].dma_ctl, 0); + cx_write(dev->sram_channels[i].int_msk, 0); + } - for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) - { - cx_write(dev->sram_channels[i].dma_ctl, 0); - cx_write(dev->sram_channels[i].int_msk, 0); - } + for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; + i++) { + cx_write(dev->sram_channels[i].dma_ctl, 0); + cx_write(dev->sram_channels[i].int_msk, 0); + } - /* Disable Audio activity */ - cx_write(AUD_INT_DMA_CTL, 0); + /* Disable Audio activity */ + cx_write(AUD_INT_DMA_CTL, 0); - /* Disable Serial port */ - cx_write(UART_CTL, 0); + /* Disable Serial port */ + cx_write(UART_CTL, 0); - /* Disable Interrupts */ - cx_write(PCI_INT_MSK, 0); - cx_write(AUD_A_INT_MSK, 0); + /* Disable Interrupts */ + cx_write(PCI_INT_MSK, 0); + cx_write(AUD_A_INT_MSK, 0); } -void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, u32 format) +void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, + u32 format) { - struct sram_channel *ch; - - if( channel_select <= 7 && channel_select >= 0 ) - { - ch = &cx25821_sram_channels[channel_select]; - cx_write(ch->pix_frmt, format); - dev->pixel_formats[channel_select] = format; - } + struct sram_channel *ch; + + if (channel_select <= 7 && channel_select >= 0) { + ch = &cx25821_sram_channels[channel_select]; + cx_write(ch->pix_frmt, format); + dev->pixel_formats[channel_select] = format; + } } -static void cx25821_set_vip_mode(struct cx25821_dev *dev, struct sram_channel *ch) +static void cx25821_set_vip_mode(struct cx25821_dev *dev, + struct sram_channel *ch) { - cx_write(ch->pix_frmt, PIXEL_FRMT_422); - cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1); + cx_write(ch->pix_frmt, PIXEL_FRMT_422); + cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1); } static void cx25821_initialize(struct cx25821_dev *dev) { - int i; - - dprintk(1, "%s()\n", __func__); + int i; - cx25821_shutdown(dev); - cx_write(PCI_INT_STAT, 0xffffffff); + dprintk(1, "%s()\n", __func__); - for(i=0; isram_channels[i].int_stat, 0xffffffff); + cx25821_shutdown(dev); + cx_write(PCI_INT_STAT, 0xffffffff); + for (i = 0; i < VID_CHANNEL_NUM; i++) + cx_write(dev->sram_channels[i].int_stat, 0xffffffff); - cx_write(AUD_A_INT_STAT, 0xffffffff); - cx_write(AUD_B_INT_STAT, 0xffffffff); - cx_write(AUD_C_INT_STAT, 0xffffffff); - cx_write(AUD_D_INT_STAT, 0xffffffff); - cx_write(AUD_E_INT_STAT, 0xffffffff); + cx_write(AUD_A_INT_STAT, 0xffffffff); + cx_write(AUD_B_INT_STAT, 0xffffffff); + cx_write(AUD_C_INT_STAT, 0xffffffff); + cx_write(AUD_D_INT_STAT, 0xffffffff); + cx_write(AUD_E_INT_STAT, 0xffffffff); - cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000); - cx_write(PAD_CTRL, 0x12); //for I2C - cx25821_registers_init(dev); //init Pecos registers - mdelay(100); + cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000); + cx_write(PAD_CTRL, 0x12); //for I2C + cx25821_registers_init(dev); //init Pecos registers + mdelay(100); + for (i = 0; i < VID_CHANNEL_NUM; i++) { + cx25821_set_vip_mode(dev, &dev->sram_channels[i]); + cx25821_sram_channel_setup(dev, &dev->sram_channels[i], 1440, + 0); + dev->pixel_formats[i] = PIXEL_FRMT_422; + dev->use_cif_resolution[i] = FALSE; + } - for(i=0; isram_channels[i]); - cx25821_sram_channel_setup(dev, &dev->sram_channels[i], 1440, 0); - dev->pixel_formats[i] = PIXEL_FRMT_422; - dev->use_cif_resolution[i] = FALSE; - } - - //Probably only affect Downstream - for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) - { - cx25821_set_vip_mode(dev, &dev->sram_channels[i]); - } + //Probably only affect Downstream + for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; + i++) { + cx25821_set_vip_mode(dev, &dev->sram_channels[i]); + } - cx25821_sram_channel_setup_audio(dev, &dev->sram_channels[SRAM_CH08], 128, 0); + cx25821_sram_channel_setup_audio(dev, &dev->sram_channels[SRAM_CH08], + 128, 0); - cx25821_gpio_init(dev); + cx25821_gpio_init(dev); } static int get_resources(struct cx25821_dev *dev) { - if (request_mem_region(pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0), dev->name)) - return 0; + if (request_mem_region + (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0), + dev->name)) + return 0; - printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n", - dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); + printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n", + dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); - return -EBUSY; + return -EBUSY; } - static void cx25821_dev_checkrevision(struct cx25821_dev *dev) { - dev->hwrevision = cx_read(RDR_CFG2) & 0xff; + dev->hwrevision = cx_read(RDR_CFG2) & 0xff; - printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", __func__, dev->hwrevision); + printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", __func__, + dev->hwrevision); } static void cx25821_iounmap(struct cx25821_dev *dev) { - if (dev == NULL) - return; - - /* Releasing IO memory */ - if (dev->lmmio != NULL) - { - CX25821_INFO("Releasing lmmio.\n"); - iounmap(dev->lmmio); - dev->lmmio = NULL; - } + if (dev == NULL) + return; + + /* Releasing IO memory */ + if (dev->lmmio != NULL) { + CX25821_INFO("Releasing lmmio.\n"); + iounmap(dev->lmmio); + dev->lmmio = NULL; + } } - static int cx25821_dev_setup(struct cx25821_dev *dev) { - int io_size = 0, i; - - struct video_device *video_template[] = { - &cx25821_video_template0, - &cx25821_video_template1, - &cx25821_video_template2, - &cx25821_video_template3, - &cx25821_video_template4, - &cx25821_video_template5, - &cx25821_video_template6, - &cx25821_video_template7, - &cx25821_video_template9, - &cx25821_video_template10, - &cx25821_video_template11, - &cx25821_videoioctl_template, - }; - - printk(KERN_INFO "\n***********************************\n"); - printk(KERN_INFO "cx25821 set up\n"); - printk(KERN_INFO "***********************************\n\n"); - - mutex_init(&dev->lock); - - atomic_inc(&dev->refcount); - - dev->nr = ++cx25821_devcount; - sprintf(dev->name, "cx25821[%d]", dev->nr); - - mutex_lock(&devlist); - list_add_tail(&dev->devlist, &cx25821_devlist); - mutex_unlock(&devlist); - - strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown"); - strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); - - - if( dev->pci->device != 0x8210 ) - { - printk(KERN_INFO "%s() Exiting. Incorrect Hardware device = 0x%02x\n", - __func__, dev->pci->device); - return -1; - } - else - { - printk(KERN_INFO "Athena Hardware device = 0x%02x\n", dev->pci->device); - } - - /* Apply a sensible clock frequency for the PCIe bridge */ - dev->clk_freq = 28000000; - dev->sram_channels = cx25821_sram_channels; - - if(dev->nr > 1) - { - CX25821_INFO("dev->nr > 1!"); - } - - /* board config */ - dev->board = 1; //card[dev->nr]; - dev->_max_num_decoders = MAX_DECODERS; - - - dev->pci_bus = dev->pci->bus->number; - dev->pci_slot = PCI_SLOT(dev->pci->devfn); - dev->pci_irqmask = 0x001f00; - - /* External Master 1 Bus */ - dev->i2c_bus[0].nr = 0; - dev->i2c_bus[0].dev = dev; - dev->i2c_bus[0].reg_stat = I2C1_STAT; - dev->i2c_bus[0].reg_ctrl = I2C1_CTRL; - dev->i2c_bus[0].reg_addr = I2C1_ADDR; - dev->i2c_bus[0].reg_rdata = I2C1_RDATA; - dev->i2c_bus[0].reg_wdata = I2C1_WDATA; - dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */ + int io_size = 0, i; + + struct video_device *video_template[] = { + &cx25821_video_template0, + &cx25821_video_template1, + &cx25821_video_template2, + &cx25821_video_template3, + &cx25821_video_template4, + &cx25821_video_template5, + &cx25821_video_template6, + &cx25821_video_template7, + &cx25821_video_template9, + &cx25821_video_template10, + &cx25821_video_template11, + &cx25821_videoioctl_template, + }; + + printk(KERN_INFO "\n***********************************\n"); + printk(KERN_INFO "cx25821 set up\n"); + printk(KERN_INFO "***********************************\n\n"); + + mutex_init(&dev->lock); + + atomic_inc(&dev->refcount); + + dev->nr = ++cx25821_devcount; + sprintf(dev->name, "cx25821[%d]", dev->nr); + + mutex_lock(&devlist); + list_add_tail(&dev->devlist, &cx25821_devlist); + mutex_unlock(&devlist); + + strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown"); + strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); + + if (dev->pci->device != 0x8210) { + printk(KERN_INFO + "%s() Exiting. Incorrect Hardware device = 0x%02x\n", + __func__, dev->pci->device); + return -1; + } else { + printk(KERN_INFO "Athena Hardware device = 0x%02x\n", + dev->pci->device); + } + + /* Apply a sensible clock frequency for the PCIe bridge */ + dev->clk_freq = 28000000; + dev->sram_channels = cx25821_sram_channels; + + if (dev->nr > 1) { + CX25821_INFO("dev->nr > 1!"); + } + + /* board config */ + dev->board = 1; //card[dev->nr]; + dev->_max_num_decoders = MAX_DECODERS; + dev->pci_bus = dev->pci->bus->number; + dev->pci_slot = PCI_SLOT(dev->pci->devfn); + dev->pci_irqmask = 0x001f00; + + /* External Master 1 Bus */ + dev->i2c_bus[0].nr = 0; + dev->i2c_bus[0].dev = dev; + dev->i2c_bus[0].reg_stat = I2C1_STAT; + dev->i2c_bus[0].reg_ctrl = I2C1_CTRL; + dev->i2c_bus[0].reg_addr = I2C1_ADDR; + dev->i2c_bus[0].reg_rdata = I2C1_RDATA; + dev->i2c_bus[0].reg_wdata = I2C1_WDATA; + dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */ #if 0 - /* External Master 2 Bus */ - dev->i2c_bus[1].nr = 1; - dev->i2c_bus[1].dev = dev; - dev->i2c_bus[1].reg_stat = I2C2_STAT; - dev->i2c_bus[1].reg_ctrl = I2C2_CTRL; - dev->i2c_bus[1].reg_addr = I2C2_ADDR; - dev->i2c_bus[1].reg_rdata = I2C2_RDATA; - dev->i2c_bus[1].reg_wdata = I2C2_WDATA; - dev->i2c_bus[1].i2c_period = (0x27 << 24); /* 100kHz */ - - /* Internal Master 3 Bus */ - dev->i2c_bus[2].nr = 2; - dev->i2c_bus[2].dev = dev; - dev->i2c_bus[2].reg_stat = I2C3_STAT; - dev->i2c_bus[2].reg_ctrl = I2C3_CTRL; - dev->i2c_bus[2].reg_addr = I2C3_ADDR; - dev->i2c_bus[2].reg_rdata = I2C3_RDATA; - dev->i2c_bus[2].reg_wdata = I2C3_WDATA; - dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */ + /* External Master 2 Bus */ + dev->i2c_bus[1].nr = 1; + dev->i2c_bus[1].dev = dev; + dev->i2c_bus[1].reg_stat = I2C2_STAT; + dev->i2c_bus[1].reg_ctrl = I2C2_CTRL; + dev->i2c_bus[1].reg_addr = I2C2_ADDR; + dev->i2c_bus[1].reg_rdata = I2C2_RDATA; + dev->i2c_bus[1].reg_wdata = I2C2_WDATA; + dev->i2c_bus[1].i2c_period = (0x27 << 24); /* 100kHz */ + + /* Internal Master 3 Bus */ + dev->i2c_bus[2].nr = 2; + dev->i2c_bus[2].dev = dev; + dev->i2c_bus[2].reg_stat = I2C3_STAT; + dev->i2c_bus[2].reg_ctrl = I2C3_CTRL; + dev->i2c_bus[2].reg_addr = I2C3_ADDR; + dev->i2c_bus[2].reg_rdata = I2C3_RDATA; + dev->i2c_bus[2].reg_wdata = I2C3_WDATA; + dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */ #endif - if (get_resources(dev) < 0) - { - printk(KERN_ERR "%s No more PCIe resources for " - "subsystem: %04x:%04x\n", - dev->name, dev->pci->subsystem_vendor, - dev->pci->subsystem_device); - - cx25821_devcount--; - return -ENODEV; - } + if (get_resources(dev) < 0) { + printk(KERN_ERR "%s No more PCIe resources for " + "subsystem: %04x:%04x\n", + dev->name, dev->pci->subsystem_vendor, + dev->pci->subsystem_device); - /* PCIe stuff */ - dev->base_io_addr = pci_resource_start(dev->pci, 0); - io_size = pci_resource_len(dev->pci, 0); + cx25821_devcount--; + return -ENODEV; + } - if (!dev->base_io_addr) { - CX25821_ERR("No PCI Memory resources, exiting!\n"); - return -ENODEV; - } + /* PCIe stuff */ + dev->base_io_addr = pci_resource_start(dev->pci, 0); + io_size = pci_resource_len(dev->pci, 0); - dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0)); + if (!dev->base_io_addr) { + CX25821_ERR("No PCI Memory resources, exiting!\n"); + return -ENODEV; + } - if (!dev->lmmio) { - CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); - cx25821_iounmap(dev); - return -ENOMEM; - } + dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0)); + if (!dev->lmmio) { + CX25821_ERR + ("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); + cx25821_iounmap(dev); + return -ENOMEM; + } - dev->bmmio = (u8 __iomem *)dev->lmmio; + dev->bmmio = (u8 __iomem *) dev->lmmio; - printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", - dev->name, dev->pci->subsystem_vendor, - dev->pci->subsystem_device, cx25821_boards[dev->board].name, - dev->board, card[dev->nr] == dev->board ? - "insmod option" : "autodetected"); + printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + dev->name, dev->pci->subsystem_vendor, + dev->pci->subsystem_device, cx25821_boards[dev->board].name, + dev->board, card[dev->nr] == dev->board ? + "insmod option" : "autodetected"); - /* init hardware */ - cx25821_initialize(dev); + /* init hardware */ + cx25821_initialize(dev); - cx25821_i2c_register(&dev->i2c_bus[0]); + cx25821_i2c_register(&dev->i2c_bus[0]); // cx25821_i2c_register(&dev->i2c_bus[1]); // cx25821_i2c_register(&dev->i2c_bus[2]); - CX25821_INFO("i2c register! bus->i2c_rc = %d\n", dev->i2c_bus[0].i2c_rc); + CX25821_INFO("i2c register! bus->i2c_rc = %d\n", + dev->i2c_bus[0].i2c_rc); - cx25821_card_setup(dev); - medusa_video_init(dev); + cx25821_card_setup(dev); + medusa_video_init(dev); - for(i = 0; i < VID_CHANNEL_NUM; i++) - { - if (cx25821_video_register(dev, i, video_template[i]) < 0) { - printk(KERN_ERR "%s() Failed to register analog video adapters on VID channel %d\n", __func__, i); + for (i = 0; i < VID_CHANNEL_NUM; i++) { + if (cx25821_video_register(dev, i, video_template[i]) < 0) { + printk(KERN_ERR + "%s() Failed to register analog video adapters on VID channel %d\n", + __func__, i); + } } - } - - for(i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) - { - //Since we don't have template8 for Audio Downstream - if (cx25821_video_register(dev, i, video_template[i-1]) < 0) { - printk(KERN_ERR "%s() Failed to register analog video adapters for Upstream channel %d.\n", __func__, i); + for (i = VID_UPSTREAM_SRAM_CHANNEL_I; + i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) { + //Since we don't have template8 for Audio Downstream + if (cx25821_video_register(dev, i, video_template[i - 1]) < 0) { + printk(KERN_ERR + "%s() Failed to register analog video adapters for Upstream channel %d.\n", + __func__, i); + } } - } - - // register IOCTL device - dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH], "video"); - if( video_register_device(dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0 ) - { - cx25821_videoioctl_unregister(dev); - printk(KERN_ERR "%s() Failed to register video adapter for IOCTL so releasing.\n", __func__); - } + // register IOCTL device + dev->ioctl_dev = + cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH], + "video"); + + if (video_register_device + (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) { + cx25821_videoioctl_unregister(dev); + printk(KERN_ERR + "%s() Failed to register video adapter for IOCTL so releasing.\n", + __func__); + } - cx25821_dev_checkrevision(dev); - CX25821_INFO("cx25821 setup done!\n"); + cx25821_dev_checkrevision(dev); + CX25821_INFO("cx25821 setup done!\n"); - return 0; + return 0; } - -void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, struct upstream_user_struct *up_data) +void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, + struct upstream_user_struct *up_data) { - dev->_isNTSC = !strcmp(dev->vid_stdname,"NTSC") ? 1 : 0; + dev->_isNTSC = !strcmp(dev->vid_stdname, "NTSC") ? 1 : 0; - dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; - medusa_set_videostandard(dev); + dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; + medusa_set_videostandard(dev); - cx25821_vidupstream_init_ch1(dev, dev->channel_select, dev->pixel_format); + cx25821_vidupstream_init_ch1(dev, dev->channel_select, + dev->pixel_format); } - -void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, struct upstream_user_struct *up_data) +void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, + struct upstream_user_struct *up_data) { - dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2,"NTSC") ? 1 : 0; + dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2, "NTSC") ? 1 : 0; - dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; - medusa_set_videostandard(dev); + dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; + medusa_set_videostandard(dev); - cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2, dev->pixel_format_ch2); + cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2, + dev->pixel_format_ch2); } - -void cx25821_start_upstream_audio(struct cx25821_dev *dev, struct upstream_user_struct *up_data) +void cx25821_start_upstream_audio(struct cx25821_dev *dev, + struct upstream_user_struct *up_data) { - cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B); + cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B); } void cx25821_dev_unregister(struct cx25821_dev *dev) { - int i; + int i; - if (!dev->base_io_addr) - return; + if (!dev->base_io_addr) + return; - cx25821_free_mem_upstream_ch1(dev); - cx25821_free_mem_upstream_ch2(dev); - cx25821_free_mem_upstream_audio(dev); + cx25821_free_mem_upstream_ch1(dev); + cx25821_free_mem_upstream_ch2(dev); + cx25821_free_mem_upstream_audio(dev); - release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); + release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); - if (!atomic_dec_and_test(&dev->refcount)) - return; + if (!atomic_dec_and_test(&dev->refcount)) + return; - for(i=0; i < VID_CHANNEL_NUM; i++) - cx25821_video_unregister(dev, i); + for (i = 0; i < VID_CHANNEL_NUM; i++) + cx25821_video_unregister(dev, i); + for (i = VID_UPSTREAM_SRAM_CHANNEL_I; + i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) { + cx25821_video_unregister(dev, i); + } - for(i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) - { - cx25821_video_unregister(dev, i); - } - - cx25821_videoioctl_unregister(dev); + cx25821_videoioctl_unregister(dev); - cx25821_i2c_unregister( &dev->i2c_bus[0] ); - cx25821_iounmap(dev); + cx25821_i2c_unregister(&dev->i2c_bus[0]); + cx25821_iounmap(dev); } - - -static __le32 *cx25821_risc_field(__le32 *rp, struct scatterlist *sglist, - unsigned int offset, u32 sync_line, - unsigned int bpl, unsigned int padding, - unsigned int lines) +static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, + unsigned int offset, u32 sync_line, + unsigned int bpl, unsigned int padding, + unsigned int lines) { - struct scatterlist *sg; - unsigned int line, todo; - - /* sync instruction */ - if (sync_line != NO_SYNC_LINE) - { - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); - } - - /* scan lines */ - sg = sglist; - for (line = 0; line < lines; line++) { - while (offset && offset >= sg_dma_len(sg)) { - offset -= sg_dma_len(sg); - sg++; - } - if (bpl <= sg_dma_len(sg)-offset) { - /* fits into current chunk */ - *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - offset += bpl; - } else { - /* scanline needs to be split */ - todo = bpl; - *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|(sg_dma_len(sg)-offset)); - *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++) = cpu_to_le32(RISC_WRITE|sg_dma_len(sg)); - *(rp++) = cpu_to_le32(sg_dma_address(sg)); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - todo -= sg_dma_len(sg); - sg++; - } - *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo); - *(rp++) = cpu_to_le32(sg_dma_address(sg)); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - offset += todo; + struct scatterlist *sg; + unsigned int line, todo; + + /* sync instruction */ + if (sync_line != NO_SYNC_LINE) { + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); } - offset += padding; - } + /* scan lines */ + sg = sglist; + for (line = 0; line < lines; line++) { + while (offset && offset >= sg_dma_len(sg)) { + offset -= sg_dma_len(sg); + sg++; + } + if (bpl <= sg_dma_len(sg) - offset) { + /* fits into current chunk */ + *(rp++) = + cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | bpl); + *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + offset += bpl; + } else { + /* scanline needs to be split */ + todo = bpl; + *(rp++) = + cpu_to_le32(RISC_WRITE | RISC_SOL | + (sg_dma_len(sg) - offset)); + *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + todo -= (sg_dma_len(sg) - offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++) = + cpu_to_le32(RISC_WRITE | sg_dma_len(sg)); + *(rp++) = cpu_to_le32(sg_dma_address(sg)); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + todo -= sg_dma_len(sg); + sg++; + } + *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo); + *(rp++) = cpu_to_le32(sg_dma_address(sg)); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + offset += todo; + } + + offset += padding; + } - return rp; + return rp; } int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, - struct scatterlist *sglist, unsigned int top_offset, - unsigned int bottom_offset, unsigned int bpl, - unsigned int padding, unsigned int lines) + struct scatterlist *sglist, unsigned int top_offset, + unsigned int bottom_offset, unsigned int bpl, + unsigned int padding, unsigned int lines) { - u32 instructions; - u32 fields; - __le32 *rp; - int rc; - - fields = 0; - if (UNSET != top_offset) - fields++; - if (UNSET != bottom_offset) - fields++; - - /* estimate risc mem: worst case is one write per page border + - one write per scan line + syncs + jump (all 2 dwords). Padding - can cause next bpl to start close to a page border. First DMA - region may be smaller than PAGE_SIZE */ - /* write and jump need and extra dword */ - instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); - instructions += 2; - rc = btcx_riscmem_alloc(pci, risc, instructions*12); - - if (rc < 0) - return rc; - - /* write risc instructions */ - rp = risc->cpu; - - if (UNSET != top_offset) - { - rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding, lines); - } - - if (UNSET != bottom_offset) - { - rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl, padding, lines); - } - - /* save pointer to jmp instruction address */ - risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); - - return 0; -} - + u32 instructions; + u32 fields; + __le32 *rp; + int rc; + + fields = 0; + if (UNSET != top_offset) + fields++; + if (UNSET != bottom_offset) + fields++; + + /* estimate risc mem: worst case is one write per page border + + one write per scan line + syncs + jump (all 2 dwords). Padding + can cause next bpl to start close to a page border. First DMA + region may be smaller than PAGE_SIZE */ + /* write and jump need and extra dword */ + instructions = + fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); + instructions += 2; + rc = btcx_riscmem_alloc(pci, risc, instructions * 12); + + if (rc < 0) + return rc; + + /* write risc instructions */ + rp = risc->cpu; + + if (UNSET != top_offset) { + rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding, + lines); + } -static __le32* cx25821_risc_field_audio(__le32 *rp, struct scatterlist *sglist, - unsigned int offset, u32 sync_line, - unsigned int bpl, unsigned int padding, - unsigned int lines, unsigned int lpi) -{ - struct scatterlist *sg; - unsigned int line, todo, sol; - - /* sync instruction */ - if (sync_line != NO_SYNC_LINE) - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); - - /* scan lines */ - sg = sglist; - for (line = 0; line < lines; line++) { - while (offset && offset >= sg_dma_len(sg)) { - offset -= sg_dma_len(sg); - sg++; + if (UNSET != bottom_offset) { + rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl, + padding, lines); } - if (lpi && line > 0 && !(line % lpi)) - sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; - else - sol = RISC_SOL; - - if (bpl <= sg_dma_len(sg)-offset) { - /* fits into current chunk */ - *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - *(rp++)=cpu_to_le32(0); /* bits 63-32 */ - offset+=bpl; - } else { - /* scanline needs to be split */ - todo = bpl; - *(rp++) = cpu_to_le32(RISC_WRITE|sol| - (sg_dma_len(sg)-offset)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - *(rp++)=cpu_to_le32(0); /* bits 63-32 */ - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(RISC_WRITE| - sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); - *(rp++)=cpu_to_le32(0); /* bits 63-32 */ - todo -= sg_dma_len(sg); - sg++; - } - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); - *(rp++)=cpu_to_le32(0); /* bits 63-32 */ - offset += todo; + /* save pointer to jmp instruction address */ + risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); + + return 0; +} + +static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist, + unsigned int offset, u32 sync_line, + unsigned int bpl, unsigned int padding, + unsigned int lines, unsigned int lpi) +{ + struct scatterlist *sg; + unsigned int line, todo, sol; + + /* sync instruction */ + if (sync_line != NO_SYNC_LINE) + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + + /* scan lines */ + sg = sglist; + for (line = 0; line < lines; line++) { + while (offset && offset >= sg_dma_len(sg)) { + offset -= sg_dma_len(sg); + sg++; + } + + if (lpi && line > 0 && !(line % lpi)) + sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; + else + sol = RISC_SOL; + + if (bpl <= sg_dma_len(sg) - offset) { + /* fits into current chunk */ + *(rp++) = + cpu_to_le32(RISC_WRITE | sol | RISC_EOL | bpl); + *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + offset += bpl; + } else { + /* scanline needs to be split */ + todo = bpl; + *(rp++) = cpu_to_le32(RISC_WRITE | sol | + (sg_dma_len(sg) - offset)); + *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + todo -= (sg_dma_len(sg) - offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++) = cpu_to_le32(RISC_WRITE | + sg_dma_len(sg)); + *(rp++) = cpu_to_le32(sg_dma_address(sg)); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + todo -= sg_dma_len(sg); + sg++; + } + *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo); + *(rp++) = cpu_to_le32(sg_dma_address(sg)); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + offset += todo; + } + offset += padding; } - offset += padding; - } - return rp; + return rp; } int cx25821_risc_databuffer_audio(struct pci_dev *pci, - struct btcx_riscmem *risc, - struct scatterlist *sglist, - unsigned int bpl, - unsigned int lines, - unsigned int lpi) + struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int bpl, + unsigned int lines, unsigned int lpi) { - u32 instructions; - __le32 *rp; - int rc; - - /* estimate risc mem: worst case is one write per page border + - one write per scan line + syncs + jump (all 2 dwords). Here - there is no padding and no sync. First DMA region may be smaller - than PAGE_SIZE */ - /* Jump and write need an extra dword */ - instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; - instructions += 1; - - if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0) - return rc; - - - /* write risc instructions */ - rp = risc->cpu; - rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi); - - /* save pointer to jmp instruction address */ - risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); - return 0; + u32 instructions; + __le32 *rp; + int rc; + + /* estimate risc mem: worst case is one write per page border + + one write per scan line + syncs + jump (all 2 dwords). Here + there is no padding and no sync. First DMA region may be smaller + than PAGE_SIZE */ + /* Jump and write need an extra dword */ + instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; + instructions += 1; + + if ((rc = btcx_riscmem_alloc(pci, risc, instructions * 12)) < 0) + return rc; + + /* write risc instructions */ + rp = risc->cpu; + rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, + lines, lpi); + + /* save pointer to jmp instruction address */ + risc->jmp = rp; + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size); + return 0; } - -int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,u32 reg, u32 mask, u32 value) +int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, + u32 reg, u32 mask, u32 value) { - __le32 *rp; - int rc; + __le32 *rp; + int rc; - rc = btcx_riscmem_alloc(pci, risc, 4*16); + rc = btcx_riscmem_alloc(pci, risc, 4 * 16); - if (rc < 0) - return rc; + if (rc < 0) + return rc; - /* write risc instructions */ - rp = risc->cpu; + /* write risc instructions */ + rp = risc->cpu; - *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1); - *(rp++) = cpu_to_le32(reg); - *(rp++) = cpu_to_le32(value); - *(rp++) = cpu_to_le32(mask); - *(rp++) = cpu_to_le32(RISC_JUMP); - *(rp++) = cpu_to_le32(risc->dma); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - return 0; + *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1); + *(rp++) = cpu_to_le32(reg); + *(rp++) = cpu_to_le32(value); + *(rp++) = cpu_to_le32(mask); + *(rp++) = cpu_to_le32(RISC_JUMP); + *(rp++) = cpu_to_le32(risc->dma); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + return 0; } void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf) { - struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); - - BUG_ON(in_interrupt()); - videobuf_waiton(&buf->vb, 0, 0); - videobuf_dma_unmap(q, dma); - videobuf_dma_free(dma); - btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); - buf->vb.state = VIDEOBUF_NEEDS_INIT; + struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); + + BUG_ON(in_interrupt()); + videobuf_waiton(&buf->vb, 0, 0); + videobuf_dma_unmap(q, dma); + videobuf_dma_free(dma); + btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); + buf->vb.state = VIDEOBUF_NEEDS_INIT; } - static irqreturn_t cx25821_irq(int irq, void *dev_id) { - struct cx25821_dev *dev = dev_id; - u32 pci_status, pci_mask; - u32 vid_status; - int i, handled = 0; - u32 mask[8] = {1, 2, 4, 8, 16, 32, 64, 128}; + struct cx25821_dev *dev = dev_id; + u32 pci_status, pci_mask; + u32 vid_status; + int i, handled = 0; + u32 mask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 }; - pci_status = cx_read(PCI_INT_STAT); - pci_mask = cx_read(PCI_INT_MSK); + pci_status = cx_read(PCI_INT_STAT); + pci_mask = cx_read(PCI_INT_MSK); + if (pci_status == 0) + goto out; - if (pci_status == 0) - goto out; + for (i = 0; i < VID_CHANNEL_NUM; i++) { + if (pci_status & mask[i]) { + vid_status = cx_read(dev->sram_channels[i].int_stat); - for(i = 0; i < VID_CHANNEL_NUM; i++) - { - if(pci_status & mask[i]) - { - vid_status = cx_read(dev->sram_channels[i].int_stat); - - if(vid_status) - handled += cx25821_video_irq(dev, i, vid_status); + if (vid_status) + handled += + cx25821_video_irq(dev, i, vid_status); - cx_write(PCI_INT_STAT, mask[i]); + cx_write(PCI_INT_STAT, mask[i]); + } } - } -out: - return IRQ_RETVAL(handled); + out: + return IRQ_RETVAL(handled); } void cx25821_print_irqbits(char *name, char *tag, char **strings, int len, u32 bits, u32 mask) { - unsigned int i; - - printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits); - - for (i = 0; i < len; i++) { - if (!(bits & (1 << i))) - continue; - if (strings[i]) - printk(" %s", strings[i]); - else - printk(" %d", i); - if (!(mask & (1 << i))) - continue; - printk("*"); - } - printk("\n"); + unsigned int i; + + printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits); + + for (i = 0; i < len; i++) { + if (!(bits & (1 << i))) + continue; + if (strings[i]) + printk(" %s", strings[i]); + else + printk(" %d", i); + if (!(mask & (1 << i))) + continue; + printk("*"); + } + printk("\n"); } -struct cx25821_dev* cx25821_dev_get(struct pci_dev *pci) +struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci) { - struct cx25821_dev *dev = pci_get_drvdata(pci); - return dev; + struct cx25821_dev *dev = pci_get_drvdata(pci); + return dev; } -static int __devinit cx25821_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) +static int __devinit cx25821_initdev(struct pci_dev *pci_dev, + const struct pci_device_id *pci_id) { - struct cx25821_dev *dev; - int err = 0; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (NULL == dev) - return -ENOMEM; - + struct cx25821_dev *dev; + int err = 0; - err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); - if (err < 0) - goto fail_free; + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (NULL == dev) + return -ENOMEM; - /* pci init */ - dev->pci = pci_dev; - if (pci_enable_device(pci_dev)) - { - err = -EIO; + err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); + if (err < 0) + goto fail_free; - printk(KERN_INFO "pci enable failed! "); + /* pci init */ + dev->pci = pci_dev; + if (pci_enable_device(pci_dev)) { + err = -EIO; - goto fail_unregister_device; - } + printk(KERN_INFO "pci enable failed! "); - printk(KERN_INFO "cx25821 Athena pci enable ! \n"); - - if (cx25821_dev_setup(dev) < 0) - { - err = -EINVAL; - goto fail_unregister_device; - } + goto fail_unregister_device; + } - /* print pci info */ - pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); - pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " - "latency: %d, mmio: 0x%llx\n", dev->name, - pci_name(pci_dev), dev->pci_rev, pci_dev->irq, - dev->pci_lat, - (unsigned long long)dev->base_io_addr ); + printk(KERN_INFO "cx25821 Athena pci enable ! \n"); + if (cx25821_dev_setup(dev) < 0) { + err = -EINVAL; + goto fail_unregister_device; + } - pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev, 0xffffffff)) - { - printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); - err = -EIO; - goto fail_irq; - } + /* print pci info */ + pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); + pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); + printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " + "latency: %d, mmio: 0x%llx\n", dev->name, + pci_name(pci_dev), dev->pci_rev, pci_dev->irq, + dev->pci_lat, (unsigned long long)dev->base_io_addr); + + pci_set_master(pci_dev); + if (!pci_dma_supported(pci_dev, 0xffffffff)) { + printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name); + err = -EIO; + goto fail_irq; + } - err = request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); + err = + request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED | IRQF_DISABLED, + dev->name, dev); - if (err < 0) - { - printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name, pci_dev->irq); - goto fail_irq; - } + if (err < 0) { + printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name, + pci_dev->irq); + goto fail_irq; + } - return 0; + return 0; -fail_irq: - printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ ! \n"); - cx25821_dev_unregister(dev); + fail_irq: + printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ ! \n"); + cx25821_dev_unregister(dev); -fail_unregister_device: - v4l2_device_unregister(&dev->v4l2_dev); + fail_unregister_device: + v4l2_device_unregister(&dev->v4l2_dev); -fail_free: - kfree(dev); - return err; + fail_free: + kfree(dev); + return err; } static void __devexit cx25821_finidev(struct pci_dev *pci_dev) { - struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); - struct cx25821_dev *dev = get_cx25821(v4l2_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct cx25821_dev *dev = get_cx25821(v4l2_dev); - cx25821_shutdown(dev); - pci_disable_device(pci_dev); + cx25821_shutdown(dev); + pci_disable_device(pci_dev); - /* unregister stuff */ - if( pci_dev->irq ) - free_irq(pci_dev->irq, dev); + /* unregister stuff */ + if (pci_dev->irq) + free_irq(pci_dev->irq, dev); + mutex_lock(&devlist); + list_del(&dev->devlist); + mutex_unlock(&devlist); - mutex_lock(&devlist); - list_del(&dev->devlist); - mutex_unlock(&devlist); - - cx25821_dev_unregister(dev); - v4l2_device_unregister(v4l2_dev); - kfree(dev); + cx25821_dev_unregister(dev); + v4l2_device_unregister(v4l2_dev); + kfree(dev); } static struct pci_device_id cx25821_pci_tbl[] = { - { - /* CX25821 Athena*/ - .vendor = 0x14f1, - .device = 0x8210, - .subvendor = 0x14f1, - .subdevice = 0x0920, - }, - { - /* --- end of list --- */ - } + { + /* CX25821 Athena */ + .vendor = 0x14f1, + .device = 0x8210, + .subvendor = 0x14f1, + .subdevice = 0x0920, + }, + { + /* --- end of list --- */ + } }; MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl); -static struct pci_driver cx25821_pci_driver = -{ - .name = "cx25821", - .id_table = cx25821_pci_tbl, - .probe = cx25821_initdev, - .remove = __devexit_p(cx25821_finidev), - /* TODO */ - .suspend = NULL, - .resume = NULL, +static struct pci_driver cx25821_pci_driver = { + .name = "cx25821", + .id_table = cx25821_pci_tbl, + .probe = cx25821_initdev, + .remove = __devexit_p(cx25821_finidev), + /* TODO */ + .suspend = NULL, + .resume = NULL, }; static int cx25821_init(void) { - INIT_LIST_HEAD(&cx25821_devlist); - printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n", - (CX25821_VERSION_CODE >> 16) & 0xff, - (CX25821_VERSION_CODE >> 8) & 0xff, - CX25821_VERSION_CODE & 0xff); - return pci_register_driver(&cx25821_pci_driver); + INIT_LIST_HEAD(&cx25821_devlist); + printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n", + (CX25821_VERSION_CODE >> 16) & 0xff, + (CX25821_VERSION_CODE >> 8) & 0xff, CX25821_VERSION_CODE & 0xff); + return pci_register_driver(&cx25821_pci_driver); } static void cx25821_fini(void) { - pci_unregister_driver(&cx25821_pci_driver); + pci_unregister_driver(&cx25821_pci_driver); } - EXPORT_SYMBOL(cx25821_devlist); EXPORT_SYMBOL(cx25821_sram_channels); EXPORT_SYMBOL(cx25821_print_irqbits); @@ -1583,4 +1570,3 @@ EXPORT_SYMBOL(cx25821_set_gpiopin_direction); module_init(cx25821_init); module_exit(cx25821_fini); - diff --git a/linux/drivers/staging/cx25821/cx25821-gpio.c b/linux/drivers/staging/cx25821/cx25821-gpio.c index 074c19682..e8a37b47e 100644 --- a/linux/drivers/staging/cx25821/cx25821-gpio.c +++ b/linux/drivers/staging/cx25821/cx25821-gpio.c @@ -1,116 +1,98 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "cx25821.h" +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "cx25821.h" /********************* GPIO stuffs *********************/ -void cx25821_set_gpiopin_direction( struct cx25821_dev *dev, - int pin_number, - int pin_logic_value) +void cx25821_set_gpiopin_direction(struct cx25821_dev *dev, + int pin_number, int pin_logic_value) { - int bit = pin_number; - u32 gpio_oe_reg = GPIO_LO_OE; + int bit = pin_number; + u32 gpio_oe_reg = GPIO_LO_OE; u32 gpio_register = 0; - u32 value = 0; - - // Check for valid pinNumber - if ( pin_number >= 47 ) - return; + u32 value = 0; + // Check for valid pinNumber + if (pin_number >= 47) + return; - if ( pin_number > 31 ) - { - bit = pin_number - 31; - gpio_oe_reg = GPIO_HI_OE; + if (pin_number > 31) { + bit = pin_number - 31; + gpio_oe_reg = GPIO_HI_OE; } + // Here we will make sure that the GPIOs 0 and 1 are output. keep the rest as is + gpio_register = cx_read(gpio_oe_reg); - // Here we will make sure that the GPIOs 0 and 1 are output. keep the rest as is - gpio_register = cx_read( gpio_oe_reg ); - - if (pin_logic_value == 1) - { - value = gpio_register | Set_GPIO_Bit(bit) ; - } - else - { - value = gpio_register & Clear_GPIO_Bit(bit) ; - } + if (pin_logic_value == 1) { + value = gpio_register | Set_GPIO_Bit(bit); + } else { + value = gpio_register & Clear_GPIO_Bit(bit); + } - cx_write( gpio_oe_reg, value ); + cx_write(gpio_oe_reg, value); } -static void cx25821_set_gpiopin_logicvalue( struct cx25821_dev *dev, - int pin_number, - int pin_logic_value) +static void cx25821_set_gpiopin_logicvalue(struct cx25821_dev *dev, + int pin_number, int pin_logic_value) { - int bit = pin_number; - u32 gpio_reg = GPIO_LO; - u32 value = 0; - + int bit = pin_number; + u32 gpio_reg = GPIO_LO; + u32 value = 0; // Check for valid pinNumber - if (pin_number >= 47) - return; - - cx25821_set_gpiopin_direction(dev, pin_number, 0); // change to output direction + if (pin_number >= 47) + return; + cx25821_set_gpiopin_direction(dev, pin_number, 0); // change to output direction - if ( pin_number > 31 ) - { - bit = pin_number - 31; - gpio_reg = GPIO_HI; + if (pin_number > 31) { + bit = pin_number - 31; + gpio_reg = GPIO_HI; } - value = cx_read( gpio_reg ); + value = cx_read(gpio_reg); + if (pin_logic_value == 0) { + value &= Clear_GPIO_Bit(bit); + } else { + value |= Set_GPIO_Bit(bit); + } - if (pin_logic_value == 0) - { - value &= Clear_GPIO_Bit(bit); - } - else - { - value |= Set_GPIO_Bit(bit); - } - - cx_write( gpio_reg, value); + cx_write(gpio_reg, value); } void cx25821_gpio_init(struct cx25821_dev *dev) { - if( dev == NULL ) - { - return; + if (dev == NULL) { + return; } - switch (dev->board) - { - case CX25821_BOARD_CONEXANT_ATHENA10: - default: - //set GPIO 5 to select the path for Medusa/Athena - cx25821_set_gpiopin_logicvalue(dev, 5, 1); - mdelay(20); - break; + switch (dev->board) { + case CX25821_BOARD_CONEXANT_ATHENA10: + default: + //set GPIO 5 to select the path for Medusa/Athena + cx25821_set_gpiopin_logicvalue(dev, 5, 1); + mdelay(20); + break; } } diff --git a/linux/drivers/staging/cx25821/cx25821-gpio.h b/linux/drivers/staging/cx25821/cx25821-gpio.h index 2dd938dbd..ca0764415 100644 --- a/linux/drivers/staging/cx25821/cx25821-gpio.h +++ b/linux/drivers/staging/cx25821/cx25821-gpio.h @@ -1,3 +1,2 @@ void cx25821_gpio_init(struct athena_dev *dev); - diff --git a/linux/drivers/staging/cx25821/cx25821-i2c.c b/linux/drivers/staging/cx25821/cx25821-i2c.c index 441edf823..3cec12201 100644 --- a/linux/drivers/staging/cx25821/cx25821-i2c.c +++ b/linux/drivers/staging/cx25821/cx25821-i2c.c @@ -1,35 +1,34 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * Based on Steven Toth cx23885 driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * Based on Steven Toth cx23885 driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + #include "cx25821.h" #include - static unsigned int i2c_debug; module_param(i2c_debug, int, 0644); MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); -static unsigned int i2c_scan=0; +static unsigned int i2c_scan = 0; module_param(i2c_scan, int, 0444); MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); @@ -44,7 +43,6 @@ MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); #define I2C_EXTEND (1 << 3) #define I2C_NOSTOP (1 << 4) - static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap) { struct cx25821_i2c *bus = i2c_adap->algo_data; @@ -75,7 +73,8 @@ static int i2c_wait_done(struct i2c_adapter *i2c_adap) return 1; } -static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg, int joined_rlen) +static int i2c_sendbytes(struct i2c_adapter *i2c_adap, + const struct i2c_msg *msg, int joined_rlen) { struct cx25821_i2c *bus = i2c_adap->algo_data; struct cx25821_dev *dev = bus->dev; @@ -83,13 +82,13 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg int retval, cnt; if (joined_rlen) - dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__, msg->len, joined_rlen); + dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__, + msg->len, joined_rlen); else dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len); /* Deal with i2c probe functions with zero payload */ - if (msg->len == 0) - { + if (msg->len == 0) { cx_write(bus->reg_addr, msg->addr << 25); cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2)); @@ -125,8 +124,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg if (retval == 0) goto eio; - if (i2c_debug) - { + if (i2c_debug) { if (!(ctrl & I2C_NOSTOP)) printk(" >\n"); } @@ -152,8 +150,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg if (retval == 0) goto eio; - if (i2c_debug) - { + if (i2c_debug) { dprintk(1, " %02x", msg->buf[cnt]); if (!(ctrl & I2C_NOSTOP)) dprintk(1, " >\n"); @@ -162,22 +159,22 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg return msg->len; - eio: + eio: retval = -EIO; - err: + err: if (i2c_debug) printk(KERN_ERR " ERR: %d\n", retval); return retval; } -static int i2c_readbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg, int joined) +static int i2c_readbytes(struct i2c_adapter *i2c_adap, + const struct i2c_msg *msg, int joined) { struct cx25821_i2c *bus = i2c_adap->algo_data; struct cx25821_dev *dev = bus->dev; u32 ctrl, cnt; int retval; - if (i2c_debug && !joined) dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len); @@ -190,7 +187,6 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg if (!i2c_slave_did_ack(i2c_adap)) return -EIO; - dprintk(1, "%s() returns 0\n", __func__); return 0; } @@ -209,7 +205,6 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg if (cnt < msg->len - 1) ctrl |= I2C_NOSTOP | I2C_EXTEND; - cx_write(bus->reg_addr, msg->addr << 25); cx_write(bus->reg_ctrl, ctrl); @@ -228,9 +223,9 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg } return msg->len; - eio: + eio: retval = -EIO; - err: + err: if (i2c_debug) printk(KERN_ERR " ERR: %d\n", retval); return retval; @@ -244,29 +239,24 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) dprintk(1, "%s(num = %d)\n", __func__, num); - for (i = 0 ; i < num; i++) - { + for (i = 0; i < num; i++) { dprintk(1, "%s(num = %d) addr = 0x%02x len = 0x%x\n", __func__, num, msgs[i].addr, msgs[i].len); - if (msgs[i].flags & I2C_M_RD) - { + if (msgs[i].flags & I2C_M_RD) { /* read */ retval = i2c_readbytes(i2c_adap, &msgs[i], 0); - } - else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && - msgs[i].addr == msgs[i + 1].addr) - { + } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && + msgs[i].addr == msgs[i + 1].addr) { /* write then read from same address */ - retval = i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len); + retval = + i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len); if (retval < 0) goto err; i++; retval = i2c_readbytes(i2c_adap, &msgs[i], 1); - } - else - { + } else { /* write */ retval = i2c_sendbytes(i2c_adap, &msgs[i], 0); } @@ -276,9 +266,9 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) } return num; - err: + err: return retval; -} +} #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int attach_inform(struct i2c_client *client) @@ -287,7 +277,7 @@ static int attach_inform(struct i2c_client *client) struct cx25821_dev *dev = bus->dev; printk(KERN_INFO "attach: %s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, client->name); + client->driver->driver.name, client->addr, client->name); if (!client->driver->command) return 0; @@ -295,11 +285,10 @@ static int attach_inform(struct i2c_client *client) if (dev->videc_type != UNSET) { printk(KERN_INFO "%s i2c attach [addr=0x%x,client=%s]\n", - client->driver->driver.name, client->addr, client->name); + client->driver->driver.name, client->addr, client->name); } - printk(KERN_INFO "attach done!\n"); return 0; @@ -314,45 +303,44 @@ static int detach_inform(struct i2c_client *client) return 0; } -void cx25821_call_i2c_clients(struct cx25821_i2c *bus, unsigned int cmd, void *arg) +void cx25821_call_i2c_clients(struct cx25821_i2c *bus, unsigned int cmd, + void *arg) { if (bus->i2c_rc != 0) return; i2c_clients_command(&bus->i2c_adap, cmd, arg); } -#endif +#endif static u32 cx25821_functionality(struct i2c_adapter *adap) { return I2C_FUNC_SMBUS_EMUL | - I2C_FUNC_I2C | - I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_READ_WORD_DATA | - I2C_FUNC_SMBUS_WRITE_WORD_DATA; + I2C_FUNC_I2C | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA; } static struct i2c_algorithm cx25821_i2c_algo_template = { - .master_xfer = i2c_xfer, - .functionality = cx25821_functionality, + .master_xfer = i2c_xfer, + .functionality = cx25821_functionality, #ifdef NEED_ALGO_CONTROL .algo_control = dummy_algo_control, #endif }; - static struct i2c_adapter cx25821_i2c_adap_template = { - .name = "cx25821", - .owner = THIS_MODULE, - .id = I2C_HW_B_CX25821, - .algo = &cx25821_i2c_algo_template, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) - .class = I2C_CLASS_TV_ANALOG, + .name = "cx25821", + .owner = THIS_MODULE, + .id = I2C_HW_B_CX25821, + .algo = &cx25821_i2c_algo_template, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + .class = I2C_CLASS_TV_ANALOG, #endif }; static struct i2c_client cx25821_i2c_client_template = { - .name = "cx25821 internal", + .name = "cx25821 internal", }; /* init + register i2c algo-bit adapter */ @@ -374,14 +362,14 @@ int cx25821_i2c_register(struct cx25821_i2c *bus) strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); bus->i2c_algo.data = bus; - bus->i2c_adap.algo_data = bus; + bus->i2c_adap.algo_data = bus; i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&bus->i2c_adap); bus->i2c_client.adapter = &bus->i2c_adap; - //set up the I2c - bus->i2c_client.addr = (0x88>>1); + //set up the I2c + bus->i2c_client.addr = (0x88 >> 1); return bus->i2c_rc; } @@ -415,71 +403,66 @@ void cx25821_av_clk(struct cx25821_dev *dev, int enable) i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1); } - int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value) { - struct i2c_client *client = &bus->i2c_client; - int retval = 0; - int v = 0; - u8 addr[2] = {0, 0}; - u8 buf[4] = {0,0,0,0}; - - struct i2c_msg msgs[2]={ - { - .addr = client->addr, - .flags = 0, - .len = 2, - .buf = addr, - }, { - .addr = client->addr, - .flags = I2C_M_RD, - .len = 4, - .buf = buf, - } - }; - - - addr[0] = (reg_addr>>8); - addr[1] = (reg_addr & 0xff); - msgs[0].addr = 0x44; - msgs[1].addr = 0x44; - - retval = i2c_xfer(client->adapter, msgs, 2); - - v = (buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0]; - *value = v; - - return v; -} + struct i2c_client *client = &bus->i2c_client; + int retval = 0; + int v = 0; + u8 addr[2] = { 0, 0 }; + u8 buf[4] = { 0, 0, 0, 0 }; + struct i2c_msg msgs[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 2, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 4, + .buf = buf, + } + }; + + addr[0] = (reg_addr >> 8); + addr[1] = (reg_addr & 0xff); + msgs[0].addr = 0x44; + msgs[1].addr = 0x44; + + retval = i2c_xfer(client->adapter, msgs, 2); + + v = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + *value = v; + + return v; +} int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value) { - struct i2c_client *client = &bus->i2c_client; - int retval = 0; - u8 buf[6] = {0, 0, 0, 0, 0, 0}; - - struct i2c_msg msgs[1]={ - { - .addr = client->addr, - .flags = 0, - .len = 6, - .buf = buf, - } - }; - - - buf[0] = reg_addr>>8; - buf[1] = reg_addr & 0xff; - buf[5] = (value>>24) & 0xff; - buf[4] = (value>>16) & 0xff; - buf[3] = (value>>8) & 0xff; - buf[2] = value & 0xff; - client->flags = 0; - msgs[0].addr = 0x44; - - retval = i2c_xfer(client->adapter, msgs, 1); - - return retval; -} + struct i2c_client *client = &bus->i2c_client; + int retval = 0; + u8 buf[6] = { 0, 0, 0, 0, 0, 0 }; + struct i2c_msg msgs[1] = { + { + .addr = client->addr, + .flags = 0, + .len = 6, + .buf = buf, + } + }; + + buf[0] = reg_addr >> 8; + buf[1] = reg_addr & 0xff; + buf[5] = (value >> 24) & 0xff; + buf[4] = (value >> 16) & 0xff; + buf[3] = (value >> 8) & 0xff; + buf[2] = value & 0xff; + client->flags = 0; + msgs[0].addr = 0x44; + + retval = i2c_xfer(client->adapter, msgs, 1); + + return retval; +} diff --git a/linux/drivers/staging/cx25821/cx25821-medusa-defines.h b/linux/drivers/staging/cx25821/cx25821-medusa-defines.h index 75161e488..b0d216ba7 100644 --- a/linux/drivers/staging/cx25821/cx25821-medusa-defines.h +++ b/linux/drivers/staging/cx25821/cx25821-medusa-defines.h @@ -1,51 +1,51 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _MEDUSA_DEF_H_ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _MEDUSA_DEF_H_ #define _MEDUSA_DEF_H_ - -// Video deocder that we supported -#define VDEC_A 0 -#define VDEC_B 1 -#define VDEC_C 2 -#define VDEC_D 3 -#define VDEC_E 4 -#define VDEC_F 5 -#define VDEC_G 6 -#define VDEC_H 7 - + +// Video deocder that we supported +#define VDEC_A 0 +#define VDEC_B 1 +#define VDEC_C 2 +#define VDEC_D 3 +#define VDEC_E 4 +#define VDEC_F 5 +#define VDEC_G 6 +#define VDEC_H 7 + //#define AUTO_SWITCH_BIT[] = { 8, 9, 10, 11, 12, 13, 14, 15 }; - -// The following bit position enables automatic source switching for decoder A-H. -// Display index per camera. + +// The following bit position enables automatic source switching for decoder A-H. +// Display index per camera. //#define VDEC_INDEX[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}; - -// Select input bit to video decoder A-H. + +// Select input bit to video decoder A-H. //#define CH_SRC_SEL_BIT[] = {24, 25, 26, 27, 28, 29, 30, 31}; - -// end of display sequence -#define END_OF_SEQ 0xF; - -// registry string size -#define MAX_REGISTRY_SZ 40; - + +// end of display sequence +#define END_OF_SEQ 0xF; + +// registry string size +#define MAX_REGISTRY_SZ 40; + #endif diff --git a/linux/drivers/staging/cx25821/cx25821-medusa-reg.h b/linux/drivers/staging/cx25821/cx25821-medusa-reg.h index 1ddf781ac..12c90f831 100644 --- a/linux/drivers/staging/cx25821/cx25821-medusa-reg.h +++ b/linux/drivers/staging/cx25821/cx25821-medusa-reg.h @@ -1,456 +1,455 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __MEDUSA_REGISTERS__ -#define __MEDUSA_REGISTERS__ - -// Serial Slave Registers -#define HOST_REGISTER1 0x0000 -#define HOST_REGISTER2 0x0001 - -// Chip Configuration Registers -#define CHIP_CTRL 0x0100 -#define AFE_AB_CTRL 0x0104 -#define AFE_CD_CTRL 0x0108 -#define AFE_EF_CTRL 0x010C -#define AFE_GH_CTRL 0x0110 -#define DENC_AB_CTRL 0x0114 -#define BYP_AB_CTRL 0x0118 -#define MON_A_CTRL 0x011C -#define DISP_SEQ_A 0x0120 -#define DISP_SEQ_B 0x0124 -#define DISP_AB_CNT 0x0128 -#define DISP_CD_CNT 0x012C -#define DISP_EF_CNT 0x0130 -#define DISP_GH_CNT 0x0134 -#define DISP_IJ_CNT 0x0138 -#define PIN_OE_CTRL 0x013C -#define PIN_SPD_CTRL 0x0140 -#define PIN_SPD_CTRL2 0x0144 -#define IRQ_STAT_CTRL 0x0148 -#define POWER_CTRL_AB 0x014C -#define POWER_CTRL_CD 0x0150 -#define POWER_CTRL_EF 0x0154 -#define POWER_CTRL_GH 0x0158 -#define TUNE_CTRL 0x015C -#define BIAS_CTRL 0x0160 -#define AFE_AB_DIAG_CTRL 0x0164 -#define AFE_CD_DIAG_CTRL 0x0168 -#define AFE_EF_DIAG_CTRL 0x016C -#define AFE_GH_DIAG_CTRL 0x0170 -#define PLL_AB_DIAG_CTRL 0x0174 -#define PLL_CD_DIAG_CTRL 0x0178 -#define PLL_EF_DIAG_CTRL 0x017C -#define PLL_GH_DIAG_CTRL 0x0180 -#define TEST_CTRL 0x0184 -#define BIST_STAT 0x0188 -#define BIST_STAT2 0x018C -#define BIST_VID_PLL_AB_STAT 0x0190 -#define BIST_VID_PLL_CD_STAT 0x0194 -#define BIST_VID_PLL_EF_STAT 0x0198 -#define BIST_VID_PLL_GH_STAT 0x019C -#define DLL_DIAG_CTRL 0x01A0 -#define DEV_CH_ID_CTRL 0x01A4 -#define ABIST_CTRL_STATUS 0x01A8 -#define ABIST_FREQ 0x01AC -#define ABIST_GOERT_SHIFT 0x01B0 -#define ABIST_COEF12 0x01B4 -#define ABIST_COEF34 0x01B8 -#define ABIST_COEF56 0x01BC -#define ABIST_COEF7_SNR 0x01C0 -#define ABIST_ADC_CAL 0x01C4 -#define ABIST_BIN1_VGA0 0x01C8 -#define ABIST_BIN2_VGA1 0x01CC -#define ABIST_BIN3_VGA2 0x01D0 -#define ABIST_BIN4_VGA3 0x01D4 -#define ABIST_BIN5_VGA4 0x01D8 -#define ABIST_BIN6_VGA5 0x01DC -#define ABIST_BIN7_VGA6 0x0x1E0 -#define ABIST_CLAMP_A 0x0x1E4 -#define ABIST_CLAMP_B 0x0x1E8 -#define ABIST_CLAMP_C 0x01EC -#define ABIST_CLAMP_D 0x01F0 -#define ABIST_CLAMP_E 0x01F4 -#define ABIST_CLAMP_F 0x01F8 - -// Digital Video Encoder A Registers -#define DENC_A_REG_1 0x0200 -#define DENC_A_REG_2 0x0204 -#define DENC_A_REG_3 0x0208 -#define DENC_A_REG_4 0x020C -#define DENC_A_REG_5 0x0210 -#define DENC_A_REG_6 0x0214 -#define DENC_A_REG_7 0x0218 -#define DENC_A_REG_8 0x021C - -// Digital Video Encoder B Registers -#define DENC_B_REG_1 0x0300 -#define DENC_B_REG_2 0x0304 -#define DENC_B_REG_3 0x0308 -#define DENC_B_REG_4 0x030C -#define DENC_B_REG_5 0x0310 -#define DENC_B_REG_6 0x0314 -#define DENC_B_REG_7 0x0318 -#define DENC_B_REG_8 0x031C - -// Video Decoder A Registers -#define MODE_CTRL 0x1000 -#define OUT_CTRL1 0x1004 -#define OUT_CTRL_NS 0x1008 -#define GEN_STAT 0x100C -#define INT_STAT_MASK 0x1010 -#define LUMA_CTRL 0x1014 -#define CHROMA_CTRL 0x1018 -#define CRUSH_CTRL 0x101C -#define HORIZ_TIM_CTRL 0x1020 -#define VERT_TIM_CTRL 0x1024 -#define MISC_TIM_CTRL 0x1028 -#define FIELD_COUNT 0x102C -#define HSCALE_CTRL 0x1030 -#define VSCALE_CTRL 0x1034 -#define MAN_VGA_CTRL 0x1038 -#define MAN_AGC_CTRL 0x103C -#define DFE_CTRL1 0x1040 -#define DFE_CTRL2 0x1044 -#define DFE_CTRL3 0x1048 -#define PLL_CTRL 0x104C -#define PLL_CTRL_FAST 0x1050 -#define HTL_CTRL 0x1054 -#define SRC_CFG 0x1058 -#define SC_STEP_SIZE 0x105C -#define SC_CONVERGE_CTRL 0x1060 -#define SC_LOOP_CTRL 0x1064 -#define COMB_2D_HFS_CFG 0x1068 -#define COMB_2D_HFD_CFG 0x106C -#define COMB_2D_LF_CFG 0x1070 -#define COMB_2D_BLEND 0x1074 -#define COMB_MISC_CTRL 0x1078 -#define COMB_FLAT_THRESH_CTRL 0x107C -#define COMB_TEST 0x1080 -#define BP_MISC_CTRL 0x1084 -#define VCR_DET_CTRL 0x1088 -#define NOISE_DET_CTRL 0x108C -#define COMB_FLAT_NOISE_CTRL 0x1090 -#define VERSION 0x11F8 -#define SOFT_RST_CTRL 0x11FC - -// Video Decoder B Registers -#define VDEC_B_MODE_CTRL 0x1200 -#define VDEC_B_OUT_CTRL1 0x1204 -#define VDEC_B_OUT_CTRL_NS 0x1208 -#define VDEC_B_GEN_STAT 0x120C -#define VDEC_B_INT_STAT_MASK 0x1210 -#define VDEC_B_LUMA_CTRL 0x1214 -#define VDEC_B_CHROMA_CTRL 0x1218 -#define VDEC_B_CRUSH_CTRL 0x121C -#define VDEC_B_HORIZ_TIM_CTRL 0x1220 -#define VDEC_B_VERT_TIM_CTRL 0x1224 -#define VDEC_B_MISC_TIM_CTRL 0x1228 -#define VDEC_B_FIELD_COUNT 0x122C -#define VDEC_B_HSCALE_CTRL 0x1230 -#define VDEC_B_VSCALE_CTRL 0x1234 -#define VDEC_B_MAN_VGA_CTRL 0x1238 -#define VDEC_B_MAN_AGC_CTRL 0x123C -#define VDEC_B_DFE_CTRL1 0x1240 -#define VDEC_B_DFE_CTRL2 0x1244 -#define VDEC_B_DFE_CTRL3 0x1248 -#define VDEC_B_PLL_CTRL 0x124C -#define VDEC_B_PLL_CTRL_FAST 0x1250 -#define VDEC_B_HTL_CTRL 0x1254 -#define VDEC_B_SRC_CFG 0x1258 -#define VDEC_B_SC_STEP_SIZE 0x125C -#define VDEC_B_SC_CONVERGE_CTRL 0x1260 -#define VDEC_B_SC_LOOP_CTRL 0x1264 -#define VDEC_B_COMB_2D_HFS_CFG 0x1268 -#define VDEC_B_COMB_2D_HFD_CFG 0x126C -#define VDEC_B_COMB_2D_LF_CFG 0x1270 -#define VDEC_B_COMB_2D_BLEND 0x1274 -#define VDEC_B_COMB_MISC_CTRL 0x1278 -#define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C -#define VDEC_B_COMB_TEST 0x1280 -#define VDEC_B_BP_MISC_CTRL 0x1284 -#define VDEC_B_VCR_DET_CTRL 0x1288 -#define VDEC_B_NOISE_DET_CTRL 0x128C -#define VDEC_B_COMB_FLAT_NOISE_CTRL 0x1290 -#define VDEC_B_VERSION 0x13F8 -#define VDEC_B_SOFT_RST_CTRL 0x13FC - -// Video Decoder C Registers -#define VDEC_C_MODE_CTRL 0x1400 -#define VDEC_C_OUT_CTRL1 0x1404 -#define VDEC_C_OUT_CTRL_NS 0x1408 -#define VDEC_C_GEN_STAT 0x140C -#define VDEC_C_INT_STAT_MASK 0x1410 -#define VDEC_C_LUMA_CTRL 0x1414 -#define VDEC_C_CHROMA_CTRL 0x1418 -#define VDEC_C_CRUSH_CTRL 0x141C -#define VDEC_C_HORIZ_TIM_CTRL 0x1420 -#define VDEC_C_VERT_TIM_CTRL 0x1424 -#define VDEC_C_MISC_TIM_CTRL 0x1428 -#define VDEC_C_FIELD_COUNT 0x142C -#define VDEC_C_HSCALE_CTRL 0x1430 -#define VDEC_C_VSCALE_CTRL 0x1434 -#define VDEC_C_MAN_VGA_CTRL 0x1438 -#define VDEC_C_MAN_AGC_CTRL 0x143C -#define VDEC_C_DFE_CTRL1 0x1440 -#define VDEC_C_DFE_CTRL2 0x1444 -#define VDEC_C_DFE_CTRL3 0x1448 -#define VDEC_C_PLL_CTRL 0x144C -#define VDEC_C_PLL_CTRL_FAST 0x1450 -#define VDEC_C_HTL_CTRL 0x1454 -#define VDEC_C_SRC_CFG 0x1458 -#define VDEC_C_SC_STEP_SIZE 0x145C -#define VDEC_C_SC_CONVERGE_CTRL 0x1460 -#define VDEC_C_SC_LOOP_CTRL 0x1464 -#define VDEC_C_COMB_2D_HFS_CFG 0x1468 -#define VDEC_C_COMB_2D_HFD_CFG 0x146C -#define VDEC_C_COMB_2D_LF_CFG 0x1470 -#define VDEC_C_COMB_2D_BLEND 0x1474 -#define VDEC_C_COMB_MISC_CTRL 0x1478 -#define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C -#define VDEC_C_COMB_TEST 0x1480 -#define VDEC_C_BP_MISC_CTRL 0x1484 -#define VDEC_C_VCR_DET_CTRL 0x1488 -#define VDEC_C_NOISE_DET_CTRL 0x148C -#define VDEC_C_COMB_FLAT_NOISE_CTRL 0x1490 -#define VDEC_C_VERSION 0x15F8 -#define VDEC_C_SOFT_RST_CTRL 0x15FC - -// Video Decoder D Registers -#define VDEC_D_MODE_CTRL 0x1600 -#define VDEC_D_OUT_CTRL1 0x1604 -#define VDEC_D_OUT_CTRL_NS 0x1608 -#define VDEC_D_GEN_STAT 0x160C -#define VDEC_D_INT_STAT_MASK 0x1610 -#define VDEC_D_LUMA_CTRL 0x1614 -#define VDEC_D_CHROMA_CTRL 0x1618 -#define VDEC_D_CRUSH_CTRL 0x161C -#define VDEC_D_HORIZ_TIM_CTRL 0x1620 -#define VDEC_D_VERT_TIM_CTRL 0x1624 -#define VDEC_D_MISC_TIM_CTRL 0x1628 -#define VDEC_D_FIELD_COUNT 0x162C -#define VDEC_D_HSCALE_CTRL 0x1630 -#define VDEC_D_VSCALE_CTRL 0x1634 -#define VDEC_D_MAN_VGA_CTRL 0x1638 -#define VDEC_D_MAN_AGC_CTRL 0x163C -#define VDEC_D_DFE_CTRL1 0x1640 -#define VDEC_D_DFE_CTRL2 0x1644 -#define VDEC_D_DFE_CTRL3 0x1648 -#define VDEC_D_PLL_CTRL 0x164C -#define VDEC_D_PLL_CTRL_FAST 0x1650 -#define VDEC_D_HTL_CTRL 0x1654 -#define VDEC_D_SRC_CFG 0x1658 -#define VDEC_D_SC_STEP_SIZE 0x165C -#define VDEC_D_SC_CONVERGE_CTRL 0x1660 -#define VDEC_D_SC_LOOP_CTRL 0x1664 -#define VDEC_D_COMB_2D_HFS_CFG 0x1668 -#define VDEC_D_COMB_2D_HFD_CFG 0x166C -#define VDEC_D_COMB_2D_LF_CFG 0x1670 -#define VDEC_D_COMB_2D_BLEND 0x1674 -#define VDEC_D_COMB_MISC_CTRL 0x1678 -#define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C -#define VDEC_D_COMB_TEST 0x1680 -#define VDEC_D_BP_MISC_CTRL 0x1684 -#define VDEC_D_VCR_DET_CTRL 0x1688 -#define VDEC_D_NOISE_DET_CTRL 0x168C -#define VDEC_D_COMB_FLAT_NOISE_CTRL 0x1690 -#define VDEC_D_VERSION 0x17F8 -#define VDEC_D_SOFT_RST_CTRL 0x17FC - -// Video Decoder E Registers -#define VDEC_E_MODE_CTRL 0x1800 -#define VDEC_E_OUT_CTRL1 0x1804 -#define VDEC_E_OUT_CTRL_NS 0x1808 -#define VDEC_E_GEN_STAT 0x180C -#define VDEC_E_INT_STAT_MASK 0x1810 -#define VDEC_E_LUMA_CTRL 0x1814 -#define VDEC_E_CHROMA_CTRL 0x1818 -#define VDEC_E_CRUSH_CTRL 0x181C -#define VDEC_E_HORIZ_TIM_CTRL 0x1820 -#define VDEC_E_VERT_TIM_CTRL 0x1824 -#define VDEC_E_MISC_TIM_CTRL 0x1828 -#define VDEC_E_FIELD_COUNT 0x182C -#define VDEC_E_HSCALE_CTRL 0x1830 -#define VDEC_E_VSCALE_CTRL 0x1834 -#define VDEC_E_MAN_VGA_CTRL 0x1838 -#define VDEC_E_MAN_AGC_CTRL 0x183C -#define VDEC_E_DFE_CTRL1 0x1840 -#define VDEC_E_DFE_CTRL2 0x1844 -#define VDEC_E_DFE_CTRL3 0x1848 -#define VDEC_E_PLL_CTRL 0x184C -#define VDEC_E_PLL_CTRL_FAST 0x1850 -#define VDEC_E_HTL_CTRL 0x1854 -#define VDEC_E_SRC_CFG 0x1858 -#define VDEC_E_SC_STEP_SIZE 0x185C -#define VDEC_E_SC_CONVERGE_CTRL 0x1860 -#define VDEC_E_SC_LOOP_CTRL 0x1864 -#define VDEC_E_COMB_2D_HFS_CFG 0x1868 -#define VDEC_E_COMB_2D_HFD_CFG 0x186C -#define VDEC_E_COMB_2D_LF_CFG 0x1870 -#define VDEC_E_COMB_2D_BLEND 0x1874 -#define VDEC_E_COMB_MISC_CTRL 0x1878 -#define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C -#define VDEC_E_COMB_TEST 0x1880 -#define VDEC_E_BP_MISC_CTRL 0x1884 -#define VDEC_E_VCR_DET_CTRL 0x1888 -#define VDEC_E_NOISE_DET_CTRL 0x188C -#define VDEC_E_COMB_FLAT_NOISE_CTRL 0x1890 -#define VDEC_E_VERSION 0x19F8 -#define VDEC_E_SOFT_RST_CTRL 0x19FC - -// Video Decoder F Registers -#define VDEC_F_MODE_CTRL 0x1A00 -#define VDEC_F_OUT_CTRL1 0x1A04 -#define VDEC_F_OUT_CTRL_NS 0x1A08 -#define VDEC_F_GEN_STAT 0x1A0C -#define VDEC_F_INT_STAT_MASK 0x1A10 -#define VDEC_F_LUMA_CTRL 0x1A14 -#define VDEC_F_CHROMA_CTRL 0x1A18 -#define VDEC_F_CRUSH_CTRL 0x1A1C -#define VDEC_F_HORIZ_TIM_CTRL 0x1A20 -#define VDEC_F_VERT_TIM_CTRL 0x1A24 -#define VDEC_F_MISC_TIM_CTRL 0x1A28 -#define VDEC_F_FIELD_COUNT 0x1A2C -#define VDEC_F_HSCALE_CTRL 0x1A30 -#define VDEC_F_VSCALE_CTRL 0x1A34 -#define VDEC_F_MAN_VGA_CTRL 0x1A38 -#define VDEC_F_MAN_AGC_CTRL 0x1A3C -#define VDEC_F_DFE_CTRL1 0x1A40 -#define VDEC_F_DFE_CTRL2 0x1A44 -#define VDEC_F_DFE_CTRL3 0x1A48 -#define VDEC_F_PLL_CTRL 0x1A4C -#define VDEC_F_PLL_CTRL_FAST 0x1A50 -#define VDEC_F_HTL_CTRL 0x1A54 -#define VDEC_F_SRC_CFG 0x1A58 -#define VDEC_F_SC_STEP_SIZE 0x1A5C -#define VDEC_F_SC_CONVERGE_CTRL 0x1A60 -#define VDEC_F_SC_LOOP_CTRL 0x1A64 -#define VDEC_F_COMB_2D_HFS_CFG 0x1A68 -#define VDEC_F_COMB_2D_HFD_CFG 0x1A6C -#define VDEC_F_COMB_2D_LF_CFG 0x1A70 -#define VDEC_F_COMB_2D_BLEND 0x1A74 -#define VDEC_F_COMB_MISC_CTRL 0x1A78 -#define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C -#define VDEC_F_COMB_TEST 0x1A80 -#define VDEC_F_BP_MISC_CTRL 0x1A84 -#define VDEC_F_VCR_DET_CTRL 0x1A88 -#define VDEC_F_NOISE_DET_CTRL 0x1A8C -#define VDEC_F_COMB_FLAT_NOISE_CTRL 0x1A90 -#define VDEC_F_VERSION 0x1BF8 -#define VDEC_F_SOFT_RST_CTRL 0x1BFC - -// Video Decoder G Registers -#define VDEC_G_MODE_CTRL 0x1C00 -#define VDEC_G_OUT_CTRL1 0x1C04 -#define VDEC_G_OUT_CTRL_NS 0x1C08 -#define VDEC_G_GEN_STAT 0x1C0C -#define VDEC_G_INT_STAT_MASK 0x1C10 -#define VDEC_G_LUMA_CTRL 0x1C14 -#define VDEC_G_CHROMA_CTRL 0x1C18 -#define VDEC_G_CRUSH_CTRL 0x1C1C -#define VDEC_G_HORIZ_TIM_CTRL 0x1C20 -#define VDEC_G_VERT_TIM_CTRL 0x1C24 -#define VDEC_G_MISC_TIM_CTRL 0x1C28 -#define VDEC_G_FIELD_COUNT 0x1C2C -#define VDEC_G_HSCALE_CTRL 0x1C30 -#define VDEC_G_VSCALE_CTRL 0x1C34 -#define VDEC_G_MAN_VGA_CTRL 0x1C38 -#define VDEC_G_MAN_AGC_CTRL 0x1C3C -#define VDEC_G_DFE_CTRL1 0x1C40 -#define VDEC_G_DFE_CTRL2 0x1C44 -#define VDEC_G_DFE_CTRL3 0x1C48 -#define VDEC_G_PLL_CTRL 0x1C4C -#define VDEC_G_PLL_CTRL_FAST 0x1C50 -#define VDEC_G_HTL_CTRL 0x1C54 -#define VDEC_G_SRC_CFG 0x1C58 -#define VDEC_G_SC_STEP_SIZE 0x1C5C -#define VDEC_G_SC_CONVERGE_CTRL 0x1C60 -#define VDEC_G_SC_LOOP_CTRL 0x1C64 -#define VDEC_G_COMB_2D_HFS_CFG 0x1C68 -#define VDEC_G_COMB_2D_HFD_CFG 0x1C6C -#define VDEC_G_COMB_2D_LF_CFG 0x1C70 -#define VDEC_G_COMB_2D_BLEND 0x1C74 -#define VDEC_G_COMB_MISC_CTRL 0x1C78 -#define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C -#define VDEC_G_COMB_TEST 0x1C80 -#define VDEC_G_BP_MISC_CTRL 0x1C84 -#define VDEC_G_VCR_DET_CTRL 0x1C88 -#define VDEC_G_NOISE_DET_CTRL 0x1C8C -#define VDEC_G_COMB_FLAT_NOISE_CTRL 0x1C90 -#define VDEC_G_VERSION 0x1DF8 -#define VDEC_G_SOFT_RST_CTRL 0x1DFC - -// Video Decoder H Registers -#define VDEC_H_MODE_CTRL 0x1E00 -#define VDEC_H_OUT_CTRL1 0x1E04 -#define VDEC_H_OUT_CTRL_NS 0x1E08 -#define VDEC_H_GEN_STAT 0x1E0C -#define VDEC_H_INT_STAT_MASK 0x1E1E -#define VDEC_H_LUMA_CTRL 0x1E14 -#define VDEC_H_CHROMA_CTRL 0x1E18 -#define VDEC_H_CRUSH_CTRL 0x1E1C -#define VDEC_H_HORIZ_TIM_CTRL 0x1E20 -#define VDEC_H_VERT_TIM_CTRL 0x1E24 -#define VDEC_H_MISC_TIM_CTRL 0x1E28 -#define VDEC_H_FIELD_COUNT 0x1E2C -#define VDEC_H_HSCALE_CTRL 0x1E30 -#define VDEC_H_VSCALE_CTRL 0x1E34 -#define VDEC_H_MAN_VGA_CTRL 0x1E38 -#define VDEC_H_MAN_AGC_CTRL 0x1E3C -#define VDEC_H_DFE_CTRL1 0x1E40 -#define VDEC_H_DFE_CTRL2 0x1E44 -#define VDEC_H_DFE_CTRL3 0x1E48 -#define VDEC_H_PLL_CTRL 0x1E4C -#define VDEC_H_PLL_CTRL_FAST 0x1E50 -#define VDEC_H_HTL_CTRL 0x1E54 -#define VDEC_H_SRC_CFG 0x1E58 -#define VDEC_H_SC_STEP_SIZE 0x1E5C -#define VDEC_H_SC_CONVERGE_CTRL 0x1E60 -#define VDEC_H_SC_LOOP_CTRL 0x1E64 -#define VDEC_H_COMB_2D_HFS_CFG 0x1E68 -#define VDEC_H_COMB_2D_HFD_CFG 0x1E6C -#define VDEC_H_COMB_2D_LF_CFG 0x1E70 -#define VDEC_H_COMB_2D_BLEND 0x1E74 -#define VDEC_H_COMB_MISC_CTRL 0x1E78 -#define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C -#define VDEC_H_COMB_TEST 0x1E80 -#define VDEC_H_BP_MISC_CTRL 0x1E84 -#define VDEC_H_VCR_DET_CTRL 0x1E88 -#define VDEC_H_NOISE_DET_CTRL 0x1E8C -#define VDEC_H_COMB_FLAT_NOISE_CTRL 0x1E90 -#define VDEC_H_VERSION 0x1FF8 -#define VDEC_H_SOFT_RST_CTRL 0x1FFC - -//***************************************************************************** -// LUMA_CTRL register fields -#define VDEC_A_BRITE_CTRL 0x1014 -#define VDEC_A_CNTRST_CTRL 0x1015 -#define VDEC_A_PEAK_SEL 0x1016 - -//***************************************************************************** -// CHROMA_CTRL register fields -#define VDEC_A_USAT_CTRL 0x1018 -#define VDEC_A_VSAT_CTRL 0x1019 -#define VDEC_A_HUE_CTRL 0x101A - - -#endif \ No newline at end of file +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MEDUSA_REGISTERS__ +#define __MEDUSA_REGISTERS__ + +// Serial Slave Registers +#define HOST_REGISTER1 0x0000 +#define HOST_REGISTER2 0x0001 + +// Chip Configuration Registers +#define CHIP_CTRL 0x0100 +#define AFE_AB_CTRL 0x0104 +#define AFE_CD_CTRL 0x0108 +#define AFE_EF_CTRL 0x010C +#define AFE_GH_CTRL 0x0110 +#define DENC_AB_CTRL 0x0114 +#define BYP_AB_CTRL 0x0118 +#define MON_A_CTRL 0x011C +#define DISP_SEQ_A 0x0120 +#define DISP_SEQ_B 0x0124 +#define DISP_AB_CNT 0x0128 +#define DISP_CD_CNT 0x012C +#define DISP_EF_CNT 0x0130 +#define DISP_GH_CNT 0x0134 +#define DISP_IJ_CNT 0x0138 +#define PIN_OE_CTRL 0x013C +#define PIN_SPD_CTRL 0x0140 +#define PIN_SPD_CTRL2 0x0144 +#define IRQ_STAT_CTRL 0x0148 +#define POWER_CTRL_AB 0x014C +#define POWER_CTRL_CD 0x0150 +#define POWER_CTRL_EF 0x0154 +#define POWER_CTRL_GH 0x0158 +#define TUNE_CTRL 0x015C +#define BIAS_CTRL 0x0160 +#define AFE_AB_DIAG_CTRL 0x0164 +#define AFE_CD_DIAG_CTRL 0x0168 +#define AFE_EF_DIAG_CTRL 0x016C +#define AFE_GH_DIAG_CTRL 0x0170 +#define PLL_AB_DIAG_CTRL 0x0174 +#define PLL_CD_DIAG_CTRL 0x0178 +#define PLL_EF_DIAG_CTRL 0x017C +#define PLL_GH_DIAG_CTRL 0x0180 +#define TEST_CTRL 0x0184 +#define BIST_STAT 0x0188 +#define BIST_STAT2 0x018C +#define BIST_VID_PLL_AB_STAT 0x0190 +#define BIST_VID_PLL_CD_STAT 0x0194 +#define BIST_VID_PLL_EF_STAT 0x0198 +#define BIST_VID_PLL_GH_STAT 0x019C +#define DLL_DIAG_CTRL 0x01A0 +#define DEV_CH_ID_CTRL 0x01A4 +#define ABIST_CTRL_STATUS 0x01A8 +#define ABIST_FREQ 0x01AC +#define ABIST_GOERT_SHIFT 0x01B0 +#define ABIST_COEF12 0x01B4 +#define ABIST_COEF34 0x01B8 +#define ABIST_COEF56 0x01BC +#define ABIST_COEF7_SNR 0x01C0 +#define ABIST_ADC_CAL 0x01C4 +#define ABIST_BIN1_VGA0 0x01C8 +#define ABIST_BIN2_VGA1 0x01CC +#define ABIST_BIN3_VGA2 0x01D0 +#define ABIST_BIN4_VGA3 0x01D4 +#define ABIST_BIN5_VGA4 0x01D8 +#define ABIST_BIN6_VGA5 0x01DC +#define ABIST_BIN7_VGA6 0x0x1E0 +#define ABIST_CLAMP_A 0x0x1E4 +#define ABIST_CLAMP_B 0x0x1E8 +#define ABIST_CLAMP_C 0x01EC +#define ABIST_CLAMP_D 0x01F0 +#define ABIST_CLAMP_E 0x01F4 +#define ABIST_CLAMP_F 0x01F8 + +// Digital Video Encoder A Registers +#define DENC_A_REG_1 0x0200 +#define DENC_A_REG_2 0x0204 +#define DENC_A_REG_3 0x0208 +#define DENC_A_REG_4 0x020C +#define DENC_A_REG_5 0x0210 +#define DENC_A_REG_6 0x0214 +#define DENC_A_REG_7 0x0218 +#define DENC_A_REG_8 0x021C + +// Digital Video Encoder B Registers +#define DENC_B_REG_1 0x0300 +#define DENC_B_REG_2 0x0304 +#define DENC_B_REG_3 0x0308 +#define DENC_B_REG_4 0x030C +#define DENC_B_REG_5 0x0310 +#define DENC_B_REG_6 0x0314 +#define DENC_B_REG_7 0x0318 +#define DENC_B_REG_8 0x031C + +// Video Decoder A Registers +#define MODE_CTRL 0x1000 +#define OUT_CTRL1 0x1004 +#define OUT_CTRL_NS 0x1008 +#define GEN_STAT 0x100C +#define INT_STAT_MASK 0x1010 +#define LUMA_CTRL 0x1014 +#define CHROMA_CTRL 0x1018 +#define CRUSH_CTRL 0x101C +#define HORIZ_TIM_CTRL 0x1020 +#define VERT_TIM_CTRL 0x1024 +#define MISC_TIM_CTRL 0x1028 +#define FIELD_COUNT 0x102C +#define HSCALE_CTRL 0x1030 +#define VSCALE_CTRL 0x1034 +#define MAN_VGA_CTRL 0x1038 +#define MAN_AGC_CTRL 0x103C +#define DFE_CTRL1 0x1040 +#define DFE_CTRL2 0x1044 +#define DFE_CTRL3 0x1048 +#define PLL_CTRL 0x104C +#define PLL_CTRL_FAST 0x1050 +#define HTL_CTRL 0x1054 +#define SRC_CFG 0x1058 +#define SC_STEP_SIZE 0x105C +#define SC_CONVERGE_CTRL 0x1060 +#define SC_LOOP_CTRL 0x1064 +#define COMB_2D_HFS_CFG 0x1068 +#define COMB_2D_HFD_CFG 0x106C +#define COMB_2D_LF_CFG 0x1070 +#define COMB_2D_BLEND 0x1074 +#define COMB_MISC_CTRL 0x1078 +#define COMB_FLAT_THRESH_CTRL 0x107C +#define COMB_TEST 0x1080 +#define BP_MISC_CTRL 0x1084 +#define VCR_DET_CTRL 0x1088 +#define NOISE_DET_CTRL 0x108C +#define COMB_FLAT_NOISE_CTRL 0x1090 +#define VERSION 0x11F8 +#define SOFT_RST_CTRL 0x11FC + +// Video Decoder B Registers +#define VDEC_B_MODE_CTRL 0x1200 +#define VDEC_B_OUT_CTRL1 0x1204 +#define VDEC_B_OUT_CTRL_NS 0x1208 +#define VDEC_B_GEN_STAT 0x120C +#define VDEC_B_INT_STAT_MASK 0x1210 +#define VDEC_B_LUMA_CTRL 0x1214 +#define VDEC_B_CHROMA_CTRL 0x1218 +#define VDEC_B_CRUSH_CTRL 0x121C +#define VDEC_B_HORIZ_TIM_CTRL 0x1220 +#define VDEC_B_VERT_TIM_CTRL 0x1224 +#define VDEC_B_MISC_TIM_CTRL 0x1228 +#define VDEC_B_FIELD_COUNT 0x122C +#define VDEC_B_HSCALE_CTRL 0x1230 +#define VDEC_B_VSCALE_CTRL 0x1234 +#define VDEC_B_MAN_VGA_CTRL 0x1238 +#define VDEC_B_MAN_AGC_CTRL 0x123C +#define VDEC_B_DFE_CTRL1 0x1240 +#define VDEC_B_DFE_CTRL2 0x1244 +#define VDEC_B_DFE_CTRL3 0x1248 +#define VDEC_B_PLL_CTRL 0x124C +#define VDEC_B_PLL_CTRL_FAST 0x1250 +#define VDEC_B_HTL_CTRL 0x1254 +#define VDEC_B_SRC_CFG 0x1258 +#define VDEC_B_SC_STEP_SIZE 0x125C +#define VDEC_B_SC_CONVERGE_CTRL 0x1260 +#define VDEC_B_SC_LOOP_CTRL 0x1264 +#define VDEC_B_COMB_2D_HFS_CFG 0x1268 +#define VDEC_B_COMB_2D_HFD_CFG 0x126C +#define VDEC_B_COMB_2D_LF_CFG 0x1270 +#define VDEC_B_COMB_2D_BLEND 0x1274 +#define VDEC_B_COMB_MISC_CTRL 0x1278 +#define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C +#define VDEC_B_COMB_TEST 0x1280 +#define VDEC_B_BP_MISC_CTRL 0x1284 +#define VDEC_B_VCR_DET_CTRL 0x1288 +#define VDEC_B_NOISE_DET_CTRL 0x128C +#define VDEC_B_COMB_FLAT_NOISE_CTRL 0x1290 +#define VDEC_B_VERSION 0x13F8 +#define VDEC_B_SOFT_RST_CTRL 0x13FC + +// Video Decoder C Registers +#define VDEC_C_MODE_CTRL 0x1400 +#define VDEC_C_OUT_CTRL1 0x1404 +#define VDEC_C_OUT_CTRL_NS 0x1408 +#define VDEC_C_GEN_STAT 0x140C +#define VDEC_C_INT_STAT_MASK 0x1410 +#define VDEC_C_LUMA_CTRL 0x1414 +#define VDEC_C_CHROMA_CTRL 0x1418 +#define VDEC_C_CRUSH_CTRL 0x141C +#define VDEC_C_HORIZ_TIM_CTRL 0x1420 +#define VDEC_C_VERT_TIM_CTRL 0x1424 +#define VDEC_C_MISC_TIM_CTRL 0x1428 +#define VDEC_C_FIELD_COUNT 0x142C +#define VDEC_C_HSCALE_CTRL 0x1430 +#define VDEC_C_VSCALE_CTRL 0x1434 +#define VDEC_C_MAN_VGA_CTRL 0x1438 +#define VDEC_C_MAN_AGC_CTRL 0x143C +#define VDEC_C_DFE_CTRL1 0x1440 +#define VDEC_C_DFE_CTRL2 0x1444 +#define VDEC_C_DFE_CTRL3 0x1448 +#define VDEC_C_PLL_CTRL 0x144C +#define VDEC_C_PLL_CTRL_FAST 0x1450 +#define VDEC_C_HTL_CTRL 0x1454 +#define VDEC_C_SRC_CFG 0x1458 +#define VDEC_C_SC_STEP_SIZE 0x145C +#define VDEC_C_SC_CONVERGE_CTRL 0x1460 +#define VDEC_C_SC_LOOP_CTRL 0x1464 +#define VDEC_C_COMB_2D_HFS_CFG 0x1468 +#define VDEC_C_COMB_2D_HFD_CFG 0x146C +#define VDEC_C_COMB_2D_LF_CFG 0x1470 +#define VDEC_C_COMB_2D_BLEND 0x1474 +#define VDEC_C_COMB_MISC_CTRL 0x1478 +#define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C +#define VDEC_C_COMB_TEST 0x1480 +#define VDEC_C_BP_MISC_CTRL 0x1484 +#define VDEC_C_VCR_DET_CTRL 0x1488 +#define VDEC_C_NOISE_DET_CTRL 0x148C +#define VDEC_C_COMB_FLAT_NOISE_CTRL 0x1490 +#define VDEC_C_VERSION 0x15F8 +#define VDEC_C_SOFT_RST_CTRL 0x15FC + +// Video Decoder D Registers +#define VDEC_D_MODE_CTRL 0x1600 +#define VDEC_D_OUT_CTRL1 0x1604 +#define VDEC_D_OUT_CTRL_NS 0x1608 +#define VDEC_D_GEN_STAT 0x160C +#define VDEC_D_INT_STAT_MASK 0x1610 +#define VDEC_D_LUMA_CTRL 0x1614 +#define VDEC_D_CHROMA_CTRL 0x1618 +#define VDEC_D_CRUSH_CTRL 0x161C +#define VDEC_D_HORIZ_TIM_CTRL 0x1620 +#define VDEC_D_VERT_TIM_CTRL 0x1624 +#define VDEC_D_MISC_TIM_CTRL 0x1628 +#define VDEC_D_FIELD_COUNT 0x162C +#define VDEC_D_HSCALE_CTRL 0x1630 +#define VDEC_D_VSCALE_CTRL 0x1634 +#define VDEC_D_MAN_VGA_CTRL 0x1638 +#define VDEC_D_MAN_AGC_CTRL 0x163C +#define VDEC_D_DFE_CTRL1 0x1640 +#define VDEC_D_DFE_CTRL2 0x1644 +#define VDEC_D_DFE_CTRL3 0x1648 +#define VDEC_D_PLL_CTRL 0x164C +#define VDEC_D_PLL_CTRL_FAST 0x1650 +#define VDEC_D_HTL_CTRL 0x1654 +#define VDEC_D_SRC_CFG 0x1658 +#define VDEC_D_SC_STEP_SIZE 0x165C +#define VDEC_D_SC_CONVERGE_CTRL 0x1660 +#define VDEC_D_SC_LOOP_CTRL 0x1664 +#define VDEC_D_COMB_2D_HFS_CFG 0x1668 +#define VDEC_D_COMB_2D_HFD_CFG 0x166C +#define VDEC_D_COMB_2D_LF_CFG 0x1670 +#define VDEC_D_COMB_2D_BLEND 0x1674 +#define VDEC_D_COMB_MISC_CTRL 0x1678 +#define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C +#define VDEC_D_COMB_TEST 0x1680 +#define VDEC_D_BP_MISC_CTRL 0x1684 +#define VDEC_D_VCR_DET_CTRL 0x1688 +#define VDEC_D_NOISE_DET_CTRL 0x168C +#define VDEC_D_COMB_FLAT_NOISE_CTRL 0x1690 +#define VDEC_D_VERSION 0x17F8 +#define VDEC_D_SOFT_RST_CTRL 0x17FC + +// Video Decoder E Registers +#define VDEC_E_MODE_CTRL 0x1800 +#define VDEC_E_OUT_CTRL1 0x1804 +#define VDEC_E_OUT_CTRL_NS 0x1808 +#define VDEC_E_GEN_STAT 0x180C +#define VDEC_E_INT_STAT_MASK 0x1810 +#define VDEC_E_LUMA_CTRL 0x1814 +#define VDEC_E_CHROMA_CTRL 0x1818 +#define VDEC_E_CRUSH_CTRL 0x181C +#define VDEC_E_HORIZ_TIM_CTRL 0x1820 +#define VDEC_E_VERT_TIM_CTRL 0x1824 +#define VDEC_E_MISC_TIM_CTRL 0x1828 +#define VDEC_E_FIELD_COUNT 0x182C +#define VDEC_E_HSCALE_CTRL 0x1830 +#define VDEC_E_VSCALE_CTRL 0x1834 +#define VDEC_E_MAN_VGA_CTRL 0x1838 +#define VDEC_E_MAN_AGC_CTRL 0x183C +#define VDEC_E_DFE_CTRL1 0x1840 +#define VDEC_E_DFE_CTRL2 0x1844 +#define VDEC_E_DFE_CTRL3 0x1848 +#define VDEC_E_PLL_CTRL 0x184C +#define VDEC_E_PLL_CTRL_FAST 0x1850 +#define VDEC_E_HTL_CTRL 0x1854 +#define VDEC_E_SRC_CFG 0x1858 +#define VDEC_E_SC_STEP_SIZE 0x185C +#define VDEC_E_SC_CONVERGE_CTRL 0x1860 +#define VDEC_E_SC_LOOP_CTRL 0x1864 +#define VDEC_E_COMB_2D_HFS_CFG 0x1868 +#define VDEC_E_COMB_2D_HFD_CFG 0x186C +#define VDEC_E_COMB_2D_LF_CFG 0x1870 +#define VDEC_E_COMB_2D_BLEND 0x1874 +#define VDEC_E_COMB_MISC_CTRL 0x1878 +#define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C +#define VDEC_E_COMB_TEST 0x1880 +#define VDEC_E_BP_MISC_CTRL 0x1884 +#define VDEC_E_VCR_DET_CTRL 0x1888 +#define VDEC_E_NOISE_DET_CTRL 0x188C +#define VDEC_E_COMB_FLAT_NOISE_CTRL 0x1890 +#define VDEC_E_VERSION 0x19F8 +#define VDEC_E_SOFT_RST_CTRL 0x19FC + +// Video Decoder F Registers +#define VDEC_F_MODE_CTRL 0x1A00 +#define VDEC_F_OUT_CTRL1 0x1A04 +#define VDEC_F_OUT_CTRL_NS 0x1A08 +#define VDEC_F_GEN_STAT 0x1A0C +#define VDEC_F_INT_STAT_MASK 0x1A10 +#define VDEC_F_LUMA_CTRL 0x1A14 +#define VDEC_F_CHROMA_CTRL 0x1A18 +#define VDEC_F_CRUSH_CTRL 0x1A1C +#define VDEC_F_HORIZ_TIM_CTRL 0x1A20 +#define VDEC_F_VERT_TIM_CTRL 0x1A24 +#define VDEC_F_MISC_TIM_CTRL 0x1A28 +#define VDEC_F_FIELD_COUNT 0x1A2C +#define VDEC_F_HSCALE_CTRL 0x1A30 +#define VDEC_F_VSCALE_CTRL 0x1A34 +#define VDEC_F_MAN_VGA_CTRL 0x1A38 +#define VDEC_F_MAN_AGC_CTRL 0x1A3C +#define VDEC_F_DFE_CTRL1 0x1A40 +#define VDEC_F_DFE_CTRL2 0x1A44 +#define VDEC_F_DFE_CTRL3 0x1A48 +#define VDEC_F_PLL_CTRL 0x1A4C +#define VDEC_F_PLL_CTRL_FAST 0x1A50 +#define VDEC_F_HTL_CTRL 0x1A54 +#define VDEC_F_SRC_CFG 0x1A58 +#define VDEC_F_SC_STEP_SIZE 0x1A5C +#define VDEC_F_SC_CONVERGE_CTRL 0x1A60 +#define VDEC_F_SC_LOOP_CTRL 0x1A64 +#define VDEC_F_COMB_2D_HFS_CFG 0x1A68 +#define VDEC_F_COMB_2D_HFD_CFG 0x1A6C +#define VDEC_F_COMB_2D_LF_CFG 0x1A70 +#define VDEC_F_COMB_2D_BLEND 0x1A74 +#define VDEC_F_COMB_MISC_CTRL 0x1A78 +#define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C +#define VDEC_F_COMB_TEST 0x1A80 +#define VDEC_F_BP_MISC_CTRL 0x1A84 +#define VDEC_F_VCR_DET_CTRL 0x1A88 +#define VDEC_F_NOISE_DET_CTRL 0x1A8C +#define VDEC_F_COMB_FLAT_NOISE_CTRL 0x1A90 +#define VDEC_F_VERSION 0x1BF8 +#define VDEC_F_SOFT_RST_CTRL 0x1BFC + +// Video Decoder G Registers +#define VDEC_G_MODE_CTRL 0x1C00 +#define VDEC_G_OUT_CTRL1 0x1C04 +#define VDEC_G_OUT_CTRL_NS 0x1C08 +#define VDEC_G_GEN_STAT 0x1C0C +#define VDEC_G_INT_STAT_MASK 0x1C10 +#define VDEC_G_LUMA_CTRL 0x1C14 +#define VDEC_G_CHROMA_CTRL 0x1C18 +#define VDEC_G_CRUSH_CTRL 0x1C1C +#define VDEC_G_HORIZ_TIM_CTRL 0x1C20 +#define VDEC_G_VERT_TIM_CTRL 0x1C24 +#define VDEC_G_MISC_TIM_CTRL 0x1C28 +#define VDEC_G_FIELD_COUNT 0x1C2C +#define VDEC_G_HSCALE_CTRL 0x1C30 +#define VDEC_G_VSCALE_CTRL 0x1C34 +#define VDEC_G_MAN_VGA_CTRL 0x1C38 +#define VDEC_G_MAN_AGC_CTRL 0x1C3C +#define VDEC_G_DFE_CTRL1 0x1C40 +#define VDEC_G_DFE_CTRL2 0x1C44 +#define VDEC_G_DFE_CTRL3 0x1C48 +#define VDEC_G_PLL_CTRL 0x1C4C +#define VDEC_G_PLL_CTRL_FAST 0x1C50 +#define VDEC_G_HTL_CTRL 0x1C54 +#define VDEC_G_SRC_CFG 0x1C58 +#define VDEC_G_SC_STEP_SIZE 0x1C5C +#define VDEC_G_SC_CONVERGE_CTRL 0x1C60 +#define VDEC_G_SC_LOOP_CTRL 0x1C64 +#define VDEC_G_COMB_2D_HFS_CFG 0x1C68 +#define VDEC_G_COMB_2D_HFD_CFG 0x1C6C +#define VDEC_G_COMB_2D_LF_CFG 0x1C70 +#define VDEC_G_COMB_2D_BLEND 0x1C74 +#define VDEC_G_COMB_MISC_CTRL 0x1C78 +#define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C +#define VDEC_G_COMB_TEST 0x1C80 +#define VDEC_G_BP_MISC_CTRL 0x1C84 +#define VDEC_G_VCR_DET_CTRL 0x1C88 +#define VDEC_G_NOISE_DET_CTRL 0x1C8C +#define VDEC_G_COMB_FLAT_NOISE_CTRL 0x1C90 +#define VDEC_G_VERSION 0x1DF8 +#define VDEC_G_SOFT_RST_CTRL 0x1DFC + +// Video Decoder H Registers +#define VDEC_H_MODE_CTRL 0x1E00 +#define VDEC_H_OUT_CTRL1 0x1E04 +#define VDEC_H_OUT_CTRL_NS 0x1E08 +#define VDEC_H_GEN_STAT 0x1E0C +#define VDEC_H_INT_STAT_MASK 0x1E1E +#define VDEC_H_LUMA_CTRL 0x1E14 +#define VDEC_H_CHROMA_CTRL 0x1E18 +#define VDEC_H_CRUSH_CTRL 0x1E1C +#define VDEC_H_HORIZ_TIM_CTRL 0x1E20 +#define VDEC_H_VERT_TIM_CTRL 0x1E24 +#define VDEC_H_MISC_TIM_CTRL 0x1E28 +#define VDEC_H_FIELD_COUNT 0x1E2C +#define VDEC_H_HSCALE_CTRL 0x1E30 +#define VDEC_H_VSCALE_CTRL 0x1E34 +#define VDEC_H_MAN_VGA_CTRL 0x1E38 +#define VDEC_H_MAN_AGC_CTRL 0x1E3C +#define VDEC_H_DFE_CTRL1 0x1E40 +#define VDEC_H_DFE_CTRL2 0x1E44 +#define VDEC_H_DFE_CTRL3 0x1E48 +#define VDEC_H_PLL_CTRL 0x1E4C +#define VDEC_H_PLL_CTRL_FAST 0x1E50 +#define VDEC_H_HTL_CTRL 0x1E54 +#define VDEC_H_SRC_CFG 0x1E58 +#define VDEC_H_SC_STEP_SIZE 0x1E5C +#define VDEC_H_SC_CONVERGE_CTRL 0x1E60 +#define VDEC_H_SC_LOOP_CTRL 0x1E64 +#define VDEC_H_COMB_2D_HFS_CFG 0x1E68 +#define VDEC_H_COMB_2D_HFD_CFG 0x1E6C +#define VDEC_H_COMB_2D_LF_CFG 0x1E70 +#define VDEC_H_COMB_2D_BLEND 0x1E74 +#define VDEC_H_COMB_MISC_CTRL 0x1E78 +#define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C +#define VDEC_H_COMB_TEST 0x1E80 +#define VDEC_H_BP_MISC_CTRL 0x1E84 +#define VDEC_H_VCR_DET_CTRL 0x1E88 +#define VDEC_H_NOISE_DET_CTRL 0x1E8C +#define VDEC_H_COMB_FLAT_NOISE_CTRL 0x1E90 +#define VDEC_H_VERSION 0x1FF8 +#define VDEC_H_SOFT_RST_CTRL 0x1FFC + +//***************************************************************************** +// LUMA_CTRL register fields +#define VDEC_A_BRITE_CTRL 0x1014 +#define VDEC_A_CNTRST_CTRL 0x1015 +#define VDEC_A_PEAK_SEL 0x1016 + +//***************************************************************************** +// CHROMA_CTRL register fields +#define VDEC_A_USAT_CTRL 0x1018 +#define VDEC_A_VSAT_CTRL 0x1019 +#define VDEC_A_HUE_CTRL 0x101A + +#endif diff --git a/linux/drivers/staging/cx25821/cx25821-medusa-video.c b/linux/drivers/staging/cx25821/cx25821-medusa-video.c index 84c68b3c5..e4df8134f 100644 --- a/linux/drivers/staging/cx25821/cx25821-medusa-video.c +++ b/linux/drivers/staging/cx25821/cx25821-medusa-video.c @@ -24,746 +24,846 @@ #include "cx25821-medusa-video.h" #include "cx25821-biffuncs.h" - ///////////////////////////////////////////////////////////////////////////////////////// //medusa_enable_bluefield_output() // // Enable the generation of blue filed output if no video // -static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel, int enable) +static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel, + int enable) { - int ret_val = 1; - u32 value = 0; - u32 tmp = 0; - int out_ctrl = OUT_CTRL1; - int out_ctrl_ns = OUT_CTRL_NS; - + int ret_val = 1; + u32 value = 0; + u32 tmp = 0; + int out_ctrl = OUT_CTRL1; + int out_ctrl_ns = OUT_CTRL_NS; - switch (channel) - { + switch (channel) { default: case VDEC_A: - break; + break; case VDEC_B: - out_ctrl = VDEC_B_OUT_CTRL1; - out_ctrl_ns = VDEC_B_OUT_CTRL_NS; - break; + out_ctrl = VDEC_B_OUT_CTRL1; + out_ctrl_ns = VDEC_B_OUT_CTRL_NS; + break; case VDEC_C: - out_ctrl = VDEC_C_OUT_CTRL1; - out_ctrl_ns = VDEC_C_OUT_CTRL_NS; - break; + out_ctrl = VDEC_C_OUT_CTRL1; + out_ctrl_ns = VDEC_C_OUT_CTRL_NS; + break; case VDEC_D: - out_ctrl = VDEC_D_OUT_CTRL1; - out_ctrl_ns = VDEC_D_OUT_CTRL_NS; - break; + out_ctrl = VDEC_D_OUT_CTRL1; + out_ctrl_ns = VDEC_D_OUT_CTRL_NS; + break; case VDEC_E: - out_ctrl = VDEC_E_OUT_CTRL1; - out_ctrl_ns = VDEC_E_OUT_CTRL_NS; - return; + out_ctrl = VDEC_E_OUT_CTRL1; + out_ctrl_ns = VDEC_E_OUT_CTRL_NS; + return; case VDEC_F: - out_ctrl = VDEC_F_OUT_CTRL1; - out_ctrl_ns = VDEC_F_OUT_CTRL_NS; - return; + out_ctrl = VDEC_F_OUT_CTRL1; + out_ctrl_ns = VDEC_F_OUT_CTRL_NS; + return; case VDEC_G: - out_ctrl = VDEC_G_OUT_CTRL1; - out_ctrl_ns = VDEC_G_OUT_CTRL_NS; - return; + out_ctrl = VDEC_G_OUT_CTRL1; + out_ctrl_ns = VDEC_G_OUT_CTRL_NS; + return; case VDEC_H: - out_ctrl = VDEC_H_OUT_CTRL1; - out_ctrl_ns = VDEC_H_OUT_CTRL_NS; - return; - } - - value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp); - value &= 0xFFFFFF7F; // clear BLUE_FIELD_EN - if (enable) - value |= 0x00000080; // set BLUE_FIELD_EN - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value); - - value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp); - value &= 0xFFFFFF7F; - if (enable) - value |= 0x00000080; // set BLUE_FIELD_EN - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value); + out_ctrl = VDEC_H_OUT_CTRL1; + out_ctrl_ns = VDEC_H_OUT_CTRL_NS; + return; + } + + value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp); + value &= 0xFFFFFF7F; // clear BLUE_FIELD_EN + if (enable) + value |= 0x00000080; // set BLUE_FIELD_EN + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value); + + value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp); + value &= 0xFFFFFF7F; + if (enable) + value |= 0x00000080; // set BLUE_FIELD_EN + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value); } - static int medusa_initialize_ntsc(struct cx25821_dev *dev) { - int ret_val = 0; - int i = 0; - u32 value = 0; - u32 tmp = 0; - - mutex_lock(&dev->lock); - - - for (i=0; i < MAX_DECODERS; i++) - { - // set video format NTSC-M - value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp); - value &= 0xFFFFFFF0; - value |= 0x10001; // enable the fast locking mode bit[16] - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value); - - // resolution NTSC 720x480 - value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp); - value &= 0x00C00C00; - value |= 0x612D0074; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value); - - value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp); - value &= 0x00C00C00; - value |= 0x1C1E001A; // vblank_cnt + 2 to get camera ID - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value); - - // chroma subcarrier step size - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x43E00000); - - // enable VIP optional active - value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp); - value &= 0xFFFBFFFF; - value |= 0x00040000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value); - - // enable VIP optional active (VIP_OPT_AL) for direct output. - value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp); - value &= 0xFFFBFFFF; - value |= 0x00040000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value); - - // clear VPRES_VERT_EN bit, fixes the chroma run away problem - // when the input switching rate < 16 fields - // - value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp); - value = setBitAtPos(value, 14); // disable special play detection - value = clearBitAtPos(value, 15); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value); - - // set vbi_gate_en to 0 - value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp); - value = clearBitAtPos(value, 29); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value); - - // Enable the generation of blue field output if no video - medusa_enable_bluefield_output(dev, i, 1); - } - - - for (i=0; i < MAX_ENCODERS; i++) - { - // NTSC hclock - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp); - value &= 0xF000FC00; - value |= 0x06B402D0; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value); - - // burst begin and burst end - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp); - value &= 0xFF000000; - value |= 0x007E9054; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value); - - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp); - value &= 0xFC00FE00; - value |= 0x00EC00F0; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value); - - // set NTSC vblank, no phase alternation, 7.5 IRE pedestal - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp); - value &= 0x00FCFFFF; - value |= 0x13020000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value); - - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp); - value &= 0xFFFF0000; - value |= 0x0000E575; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value); - - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x009A89C1); - - // Subcarrier Increment - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x21F07C1F); - } - - - //set picture resolutions - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 480 - - // set Bypass input format to NTSC 525 lines - value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); - value |= 0x00080200; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); - - mutex_unlock(&dev->lock); - - return ret_val; -} + int ret_val = 0; + int i = 0; + u32 value = 0; + u32 tmp = 0; + + mutex_lock(&dev->lock); + + for (i = 0; i < MAX_DECODERS; i++) { + // set video format NTSC-M + value = + cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), + &tmp); + value &= 0xFFFFFFF0; + value |= 0x10001; // enable the fast locking mode bit[16] + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), + value); + + // resolution NTSC 720x480 + value = + cx25821_i2c_read(&dev->i2c_bus[0], + HORIZ_TIM_CTRL + (0x200 * i), &tmp); + value &= 0x00C00C00; + value |= 0x612D0074; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + HORIZ_TIM_CTRL + (0x200 * i), value); + + value = + cx25821_i2c_read(&dev->i2c_bus[0], + VERT_TIM_CTRL + (0x200 * i), &tmp); + value &= 0x00C00C00; + value |= 0x1C1E001A; // vblank_cnt + 2 to get camera ID + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + VERT_TIM_CTRL + (0x200 * i), value); + + // chroma subcarrier step size + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + SC_STEP_SIZE + (0x200 * i), 0x43E00000); + + // enable VIP optional active + value = + cx25821_i2c_read(&dev->i2c_bus[0], + OUT_CTRL_NS + (0x200 * i), &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + OUT_CTRL_NS + (0x200 * i), value); + + // enable VIP optional active (VIP_OPT_AL) for direct output. + value = + cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), + &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), + value); + + // clear VPRES_VERT_EN bit, fixes the chroma run away problem + // when the input switching rate < 16 fields + // + value = + cx25821_i2c_read(&dev->i2c_bus[0], + MISC_TIM_CTRL + (0x200 * i), &tmp); + value = setBitAtPos(value, 14); // disable special play detection + value = clearBitAtPos(value, 15); + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + MISC_TIM_CTRL + (0x200 * i), value); + + // set vbi_gate_en to 0 + value = + cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), + &tmp); + value = clearBitAtPos(value, 29); + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), + value); + + // Enable the generation of blue field output if no video + medusa_enable_bluefield_output(dev, i, 1); + } + + for (i = 0; i < MAX_ENCODERS; i++) { + // NTSC hclock + value = + cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_1 + (0x100 * i), &tmp); + value &= 0xF000FC00; + value |= 0x06B402D0; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_1 + (0x100 * i), value); + + // burst begin and burst end + value = + cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_2 + (0x100 * i), &tmp); + value &= 0xFF000000; + value |= 0x007E9054; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_2 + (0x100 * i), value); + + value = + cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_3 + (0x100 * i), &tmp); + value &= 0xFC00FE00; + value |= 0x00EC00F0; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_3 + (0x100 * i), value); + + // set NTSC vblank, no phase alternation, 7.5 IRE pedestal + value = + cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_4 + (0x100 * i), &tmp); + value &= 0x00FCFFFF; + value |= 0x13020000; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_4 + (0x100 * i), value); + + value = + cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_5 + (0x100 * i), &tmp); + value &= 0xFFFF0000; + value |= 0x0000E575; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_5 + (0x100 * i), value); + + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_6 + (0x100 * i), 0x009A89C1); + + // Subcarrier Increment + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_7 + (0x100 * i), 0x21F07C1F); + } + + //set picture resolutions + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 480 + + // set Bypass input format to NTSC 525 lines + value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); + value |= 0x00080200; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); + mutex_unlock(&dev->lock); + + return ret_val; +} static int medusa_PALCombInit(struct cx25821_dev *dev, int dec) { - int ret_val = -1; - u32 value = 0, tmp = 0; - - // Setup for 2D threshold - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG+(0x200*dec), 0x20002861); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG+(0x200*dec), 0x20002861); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG+(0x200*dec), 0x200A1023); - - // Setup flat chroma and luma thresholds - value = cx25821_i2c_read(&dev->i2c_bus[0], COMB_FLAT_THRESH_CTRL+(0x200*dec), &tmp); - value &= 0x06230000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_FLAT_THRESH_CTRL+(0x200*dec), value); - - // set comb 2D blend - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND+(0x200*dec), 0x210F0F0F); - - // COMB MISC CONTROL - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL+(0x200*dec), 0x41120A7F); - - return ret_val; + int ret_val = -1; + u32 value = 0, tmp = 0; + + // Setup for 2D threshold + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec), + 0x20002861); + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG + (0x200 * dec), + 0x20002861); + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec), + 0x200A1023); + + // Setup flat chroma and luma thresholds + value = + cx25821_i2c_read(&dev->i2c_bus[0], + COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp); + value &= 0x06230000; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + COMB_FLAT_THRESH_CTRL + (0x200 * dec), value); + + // set comb 2D blend + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec), + 0x210F0F0F); + + // COMB MISC CONTROL + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec), + 0x41120A7F); + + return ret_val; } - static int medusa_initialize_pal(struct cx25821_dev *dev) { - int ret_val = 0; - int i = 0; - u32 value = 0; - u32 tmp = 0; - - mutex_lock(&dev->lock); - - for (i=0; i < MAX_DECODERS; i++) - { - // set video format PAL-BDGHI - value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp); - value &= 0xFFFFFFF0; - value |= 0x10004; // enable the fast locking mode bit[16] - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value); - - - // resolution PAL 720x576 - value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp); - value &= 0x00C00C00; - value |= 0x632D007D; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value); - - // vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 - value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp); - value &= 0x00C00C00; - value |= 0x28240026; // vblank_cnt + 2 to get camera ID - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value); - - // chroma subcarrier step size - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x5411E2D0); - - // enable VIP optional active - value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp); - value &= 0xFFFBFFFF; - value |= 0x00040000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value); - - // enable VIP optional active (VIP_OPT_AL) for direct output. - value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp); - value &= 0xFFFBFFFF; - value |= 0x00040000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value); - - // clear VPRES_VERT_EN bit, fixes the chroma run away problem - // when the input switching rate < 16 fields - value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp); - value = setBitAtPos(value, 14); // disable special play detection - value = clearBitAtPos(value, 15); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value); - - // set vbi_gate_en to 0 - value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp); - value = clearBitAtPos(value, 29); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value); - - medusa_PALCombInit(dev, i); - - // Enable the generation of blue field output if no video - medusa_enable_bluefield_output(dev, i, 1); - } - - - for (i=0; i < MAX_ENCODERS; i++) - { - // PAL hclock - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp); - value &= 0xF000FC00; - value |= 0x06C002D0; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value); - - // burst begin and burst end - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp); - value &= 0xFF000000; - value |= 0x007E9754; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value); - - // hblank and vactive - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp); - value &= 0xFC00FE00; - value |= 0x00FC0120; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value); - - // set PAL vblank, phase alternation, 0 IRE pedestal - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp); - value &= 0x00FCFFFF; - value |= 0x14010000; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value); - - - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp); - value &= 0xFFFF0000; - value |= 0x0000F078; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value); - - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x00A493CF); - - // Subcarrier Increment - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x2A098ACB); - } - - - //set picture resolutions - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 576 - - // set Bypass input format to PAL 625 lines - value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); - value &= 0xFFF7FDFF; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); - - mutex_unlock(&dev->lock); - - return ret_val; -} + int ret_val = 0; + int i = 0; + u32 value = 0; + u32 tmp = 0; + + mutex_lock(&dev->lock); + + for (i = 0; i < MAX_DECODERS; i++) { + // set video format PAL-BDGHI + value = + cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), + &tmp); + value &= 0xFFFFFFF0; + value |= 0x10004; // enable the fast locking mode bit[16] + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), + value); + + // resolution PAL 720x576 + value = + cx25821_i2c_read(&dev->i2c_bus[0], + HORIZ_TIM_CTRL + (0x200 * i), &tmp); + value &= 0x00C00C00; + value |= 0x632D007D; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + HORIZ_TIM_CTRL + (0x200 * i), value); + + // vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 + value = + cx25821_i2c_read(&dev->i2c_bus[0], + VERT_TIM_CTRL + (0x200 * i), &tmp); + value &= 0x00C00C00; + value |= 0x28240026; // vblank_cnt + 2 to get camera ID + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + VERT_TIM_CTRL + (0x200 * i), value); + + // chroma subcarrier step size + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + SC_STEP_SIZE + (0x200 * i), 0x5411E2D0); + + // enable VIP optional active + value = + cx25821_i2c_read(&dev->i2c_bus[0], + OUT_CTRL_NS + (0x200 * i), &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + OUT_CTRL_NS + (0x200 * i), value); + + // enable VIP optional active (VIP_OPT_AL) for direct output. + value = + cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), + &tmp); + value &= 0xFFFBFFFF; + value |= 0x00040000; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), + value); + + // clear VPRES_VERT_EN bit, fixes the chroma run away problem + // when the input switching rate < 16 fields + value = + cx25821_i2c_read(&dev->i2c_bus[0], + MISC_TIM_CTRL + (0x200 * i), &tmp); + value = setBitAtPos(value, 14); // disable special play detection + value = clearBitAtPos(value, 15); + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + MISC_TIM_CTRL + (0x200 * i), value); + + // set vbi_gate_en to 0 + value = + cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), + &tmp); + value = clearBitAtPos(value, 29); + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), + value); + + medusa_PALCombInit(dev, i); + + // Enable the generation of blue field output if no video + medusa_enable_bluefield_output(dev, i, 1); + } + + for (i = 0; i < MAX_ENCODERS; i++) { + // PAL hclock + value = + cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_1 + (0x100 * i), &tmp); + value &= 0xF000FC00; + value |= 0x06C002D0; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_1 + (0x100 * i), value); + + // burst begin and burst end + value = + cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_2 + (0x100 * i), &tmp); + value &= 0xFF000000; + value |= 0x007E9754; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_2 + (0x100 * i), value); + + // hblank and vactive + value = + cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_3 + (0x100 * i), &tmp); + value &= 0xFC00FE00; + value |= 0x00FC0120; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_3 + (0x100 * i), value); + + // set PAL vblank, phase alternation, 0 IRE pedestal + value = + cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_4 + (0x100 * i), &tmp); + value &= 0x00FCFFFF; + value |= 0x14010000; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_4 + (0x100 * i), value); + + value = + cx25821_i2c_read(&dev->i2c_bus[0], + DENC_A_REG_5 + (0x100 * i), &tmp); + value &= 0xFFFF0000; + value |= 0x0000F078; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_5 + (0x100 * i), value); + + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_6 + (0x100 * i), 0x00A493CF); + + // Subcarrier Increment + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + DENC_A_REG_7 + (0x100 * i), 0x2A098ACB); + } + + //set picture resolutions + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); //0 - 720 + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); //0 - 576 + + // set Bypass input format to PAL 625 lines + value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); + value &= 0xFFF7FDFF; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); + + mutex_unlock(&dev->lock); + return ret_val; +} int medusa_set_videostandard(struct cx25821_dev *dev) { - int status = STATUS_SUCCESS; - u32 value = 0, tmp = 0; - - - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - { - status = medusa_initialize_pal(dev); - } - else - { - status = medusa_initialize_ntsc(dev); - } - - // Enable DENC_A output - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp); - value = setBitAtPos(value, 4); - status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value); - - // Enable DENC_B output - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp); - value = setBitAtPos(value, 4); - status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value); - - return status; + int status = STATUS_SUCCESS; + u32 value = 0, tmp = 0; + + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) { + status = medusa_initialize_pal(dev); + } else { + status = medusa_initialize_ntsc(dev); + } + + // Enable DENC_A output + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp); + value = setBitAtPos(value, 4); + status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value); + + // Enable DENC_B output + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp); + value = setBitAtPos(value, 4); + status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value); + + return status; } - -void medusa_set_resolution(struct cx25821_dev *dev, int width, int decoder_select) +void medusa_set_resolution(struct cx25821_dev *dev, int width, + int decoder_select) { - int decoder = 0; - int decoder_count = 0; - int ret_val = 0; - u32 hscale = 0x0; - u32 vscale = 0x0; - const int MAX_WIDTH = 720; - - mutex_lock(&dev->lock); - - // validate the width - cannot be negative - if (width > MAX_WIDTH) - { - printk("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH \n", __func__, width, MAX_WIDTH); - width = MAX_WIDTH; - } - - if( decoder_select <= 7 && decoder_select >= 0 ) - { - decoder = decoder_select; - decoder_count = decoder_select + 1; - } - else - { - decoder = 0; - decoder_count = _num_decoders; - } - - - switch( width ) - { + int decoder = 0; + int decoder_count = 0; + int ret_val = 0; + u32 hscale = 0x0; + u32 vscale = 0x0; + const int MAX_WIDTH = 720; + + mutex_lock(&dev->lock); + + // validate the width - cannot be negative + if (width > MAX_WIDTH) { + printk + ("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH \n", + __func__, width, MAX_WIDTH); + width = MAX_WIDTH; + } + + if (decoder_select <= 7 && decoder_select >= 0) { + decoder = decoder_select; + decoder_count = decoder_select + 1; + } else { + decoder = 0; + decoder_count = _num_decoders; + } + + switch (width) { case 320: - hscale = 0x13E34B; - vscale = 0x0; - break; + hscale = 0x13E34B; + vscale = 0x0; + break; case 352: - hscale = 0x10A273; - vscale = 0x0; - break; + hscale = 0x10A273; + vscale = 0x0; + break; case 176: - hscale = 0x3115B2; - vscale = 0x1E00; - break; + hscale = 0x3115B2; + vscale = 0x1E00; + break; case 160: - hscale = 0x378D84; - vscale = 0x1E00; - break; - - default: //720 - hscale = 0x0; - vscale = 0x0; - break; - } - - for( ; decoder < decoder_count; decoder++) - { - // write scaling values for each decoder - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL+(0x200*decoder), hscale); - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL+(0x200*decoder), vscale); - } - - mutex_unlock(&dev->lock); + hscale = 0x378D84; + vscale = 0x1E00; + break; + + default: //720 + hscale = 0x0; + vscale = 0x0; + break; + } + + for (; decoder < decoder_count; decoder++) { + // write scaling values for each decoder + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + HSCALE_CTRL + (0x200 * decoder), hscale); + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], + VSCALE_CTRL + (0x200 * decoder), vscale); + } + + mutex_unlock(&dev->lock); } -static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, int duration) +static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, + int duration) { - int ret_val = 0; - u32 fld_cnt = 0; - u32 tmp = 0; - u32 disp_cnt_reg = DISP_AB_CNT; + int ret_val = 0; + u32 fld_cnt = 0; + u32 tmp = 0; + u32 disp_cnt_reg = DISP_AB_CNT; - mutex_lock(&dev->lock); + mutex_lock(&dev->lock); - // no support - if (decoder < VDEC_A && decoder > VDEC_H) - { - mutex_unlock(&dev->lock); - return; - } + // no support + if (decoder < VDEC_A && decoder > VDEC_H) { + mutex_unlock(&dev->lock); + return; + } - switch (decoder) - { + switch (decoder) { default: - break; + break; case VDEC_C: case VDEC_D: - disp_cnt_reg = DISP_CD_CNT; - break; + disp_cnt_reg = DISP_CD_CNT; + break; case VDEC_E: case VDEC_F: - disp_cnt_reg = DISP_EF_CNT; - break; + disp_cnt_reg = DISP_EF_CNT; + break; case VDEC_G: case VDEC_H: - disp_cnt_reg = DISP_GH_CNT; - break; - } + disp_cnt_reg = DISP_GH_CNT; + break; + } - _display_field_cnt[decoder] = duration; + _display_field_cnt[decoder] = duration; - // update hardware - fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp); + // update hardware + fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp); - if (!(decoder % 2)) // EVEN decoder - { - fld_cnt &= 0xFFFF0000; - fld_cnt |= duration; - } - else - { - fld_cnt &= 0x0000FFFF; - fld_cnt |= ((u32)duration) << 16; - } + if (!(decoder % 2)) // EVEN decoder + { + fld_cnt &= 0xFFFF0000; + fld_cnt |= duration; + } else { + fld_cnt &= 0x0000FFFF; + fld_cnt |= ((u32) duration) << 16; + } - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt); + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt); - mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); } ///////////////////////////////////////////////////////////////////////////////////////// // Map to Medusa register setting -static int mapM( - int srcMin, - int srcMax, - int srcVal, - int dstMin, - int dstMax, - int* dstVal -) +static int mapM(int srcMin, + int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal) { - int numerator; - int denominator; - int quotient; - - if((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax)) - { - return -1; - } - - // This is the overall expression used: - // *dstVal = (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin; - // but we need to account for rounding so below we use the modulus - // operator to find the remainder and increment if necessary. - numerator = (srcVal - srcMin)*(dstMax - dstMin); - denominator = srcMax - srcMin; - quotient = numerator/denominator; - - if(2 * ( numerator % denominator ) >= denominator) - { - quotient++; - } - - *dstVal = quotient + dstMin; - - return 0; + int numerator; + int denominator; + int quotient; + + if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax)) { + return -1; + } + // This is the overall expression used: + // *dstVal = (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin; + // but we need to account for rounding so below we use the modulus + // operator to find the remainder and increment if necessary. + numerator = (srcVal - srcMin) * (dstMax - dstMin); + denominator = srcMax - srcMin; + quotient = numerator / denominator; + + if (2 * (numerator % denominator) >= denominator) { + quotient++; + } + + *dstVal = quotient + dstMin; + + return 0; } static unsigned long convert_to_twos(long numeric, unsigned long bits_len) { - unsigned char temp; - - if (numeric >= 0) - return numeric; - else - { - temp = ~(abs(numeric) & 0xFF); - temp += 1; - return temp; - } + unsigned char temp; + + if (numeric >= 0) + return numeric; + else { + temp = ~(abs(numeric) & 0xFF); + temp += 1; + return temp; + } } + ///////////////////////////////////////////////////////////////////////////////////////// int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) { - int ret_val = 0; - int value = 0; - u32 val = 0, tmp = 0; - - mutex_lock(&dev->lock); - if((brightness > VIDEO_PROCAMP_MAX) || (brightness < VIDEO_PROCAMP_MIN)) - { + int ret_val = 0; + int value = 0; + u32 val = 0, tmp = 0; + + mutex_lock(&dev->lock); + if ((brightness > VIDEO_PROCAMP_MAX) + || (brightness < VIDEO_PROCAMP_MIN)) { + mutex_unlock(&dev->lock); + return -1; + } + ret_val = + mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, + SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); + value = convert_to_twos(value, 8); + val = + cx25821_i2c_read(&dev->i2c_bus[0], + VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp); + val &= 0xFFFFFF00; + ret_val |= + cx25821_i2c_write(&dev->i2c_bus[0], + VDEC_A_BRITE_CTRL + (0x200 * decoder), + val | value); mutex_unlock(&dev->lock); - return -1; - } - ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); - value = convert_to_twos(value, 8); - val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_BRITE_CTRL+(0x200*decoder), &tmp); - val &= 0xFFFFFF00; - ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_BRITE_CTRL+(0x200*decoder), val | value); - mutex_unlock(&dev->lock); - return ret_val; + return ret_val; } ///////////////////////////////////////////////////////////////////////////////////////// int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) { - int ret_val = 0; - int value = 0; - u32 val = 0, tmp = 0; - - mutex_lock(&dev->lock); + int ret_val = 0; + int value = 0; + u32 val = 0, tmp = 0; + + mutex_lock(&dev->lock); + + if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) { + mutex_unlock(&dev->lock); + return -1; + } + + ret_val = + mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, + UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); + val = + cx25821_i2c_read(&dev->i2c_bus[0], + VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp); + val &= 0xFFFFFF00; + ret_val |= + cx25821_i2c_write(&dev->i2c_bus[0], + VDEC_A_CNTRST_CTRL + (0x200 * decoder), + val | value); - if((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) - { mutex_unlock(&dev->lock); - return -1; - } - - ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); - val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_CNTRST_CTRL+(0x200*decoder), &tmp); - val &= 0xFFFFFF00; - ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_CNTRST_CTRL+(0x200*decoder), val | value); - - mutex_unlock(&dev->lock); - return ret_val; + return ret_val; } ///////////////////////////////////////////////////////////////////////////////////////// int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) { - int ret_val = 0; - int value = 0; - u32 val = 0, tmp = 0; + int ret_val = 0; + int value = 0; + u32 val = 0, tmp = 0; - mutex_lock(&dev->lock); + mutex_lock(&dev->lock); - if((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) - { - mutex_unlock(&dev->lock); - return -1; - } + if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) { + mutex_unlock(&dev->lock); + return -1; + } - ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); + ret_val = + mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN, + SIGNED_BYTE_MAX, &value); - value = convert_to_twos(value, 8); - val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_HUE_CTRL+(0x200*decoder), &tmp); - val &= 0xFFFFFF00; + value = convert_to_twos(value, 8); + val = + cx25821_i2c_read(&dev->i2c_bus[0], + VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp); + val &= 0xFFFFFF00; - ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_HUE_CTRL+(0x200*decoder), val | value); + ret_val |= + cx25821_i2c_write(&dev->i2c_bus[0], + VDEC_A_HUE_CTRL + (0x200 * decoder), val | value); - mutex_unlock(&dev->lock); - return ret_val; + mutex_unlock(&dev->lock); + return ret_val; } - ///////////////////////////////////////////////////////////////////////////////////////// int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) { - int ret_val = 0; - int value = 0; - u32 val = 0, tmp = 0; + int ret_val = 0; + int value = 0; + u32 val = 0, tmp = 0; + + mutex_lock(&dev->lock); + + if ((saturation > VIDEO_PROCAMP_MAX) + || (saturation < VIDEO_PROCAMP_MIN)) { + mutex_unlock(&dev->lock); + return -1; + } + + ret_val = + mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, + UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); + + val = + cx25821_i2c_read(&dev->i2c_bus[0], + VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp); + val &= 0xFFFFFF00; + ret_val |= + cx25821_i2c_write(&dev->i2c_bus[0], + VDEC_A_USAT_CTRL + (0x200 * decoder), + val | value); + + val = + cx25821_i2c_read(&dev->i2c_bus[0], + VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp); + val &= 0xFFFFFF00; + ret_val |= + cx25821_i2c_write(&dev->i2c_bus[0], + VDEC_A_VSAT_CTRL + (0x200 * decoder), + val | value); - mutex_lock(&dev->lock); - - if((saturation > VIDEO_PROCAMP_MAX) || (saturation < VIDEO_PROCAMP_MIN)) - { mutex_unlock(&dev->lock); - return -1; - } - - ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); - - val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_USAT_CTRL+(0x200*decoder), &tmp); - val &= 0xFFFFFF00; - ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_USAT_CTRL+(0x200*decoder), val | value); - - val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_VSAT_CTRL+(0x200*decoder), &tmp); - val &= 0xFFFFFF00; - ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_VSAT_CTRL+(0x200*decoder), val | value); - - mutex_unlock(&dev->lock); - return ret_val; + return ret_val; } - ///////////////////////////////////////////////////////////////////////////////////////// // Program the display sequence and monitor output. // int medusa_video_init(struct cx25821_dev *dev) { - u32 value = 0, tmp = 0; - int ret_val = 0; - int i=0; - - mutex_lock(&dev->lock); - - _num_decoders = dev->_max_num_decoders; - + u32 value = 0, tmp = 0; + int ret_val = 0; + int i = 0; - // disable Auto source selection on all video decoders - value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); - value &= 0xFFFFF0FF; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); + mutex_lock(&dev->lock); - if (ret_val < 0) - { - mutex_unlock(&dev->lock); - return -EINVAL; - } - - // Turn off Master source switch enable - value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); - value &= 0xFFFFFFDF; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); - - if (ret_val < 0) - { - mutex_unlock(&dev->lock); - return -EINVAL; - } + _num_decoders = dev->_max_num_decoders; - mutex_unlock(&dev->lock); + // disable Auto source selection on all video decoders + value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); + value &= 0xFFFFF0FF; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); - for (i=0; i < _num_decoders; i++) - { - medusa_set_decoderduration(dev, i, _display_field_cnt[i]); - } + if (ret_val < 0) { + mutex_unlock(&dev->lock); + return -EINVAL; + } + // Turn off Master source switch enable + value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); + value &= 0xFFFFFFDF; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); - mutex_lock(&dev->lock); + if (ret_val < 0) { + mutex_unlock(&dev->lock); + return -EINVAL; + } - // Select monitor as DENC A input, power up the DAC - value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp); - value &= 0xFF70FF70; - value |= 0x00090008; // set en_active - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value); - - if (ret_val < 0) - { mutex_unlock(&dev->lock); - return -EINVAL; - } - // enable input is VIP/656 - value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); - value |= 0x00040100; // enable VIP - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); + for (i = 0; i < _num_decoders; i++) { + medusa_set_decoderduration(dev, i, _display_field_cnt[i]); + } + + mutex_lock(&dev->lock); + + // Select monitor as DENC A input, power up the DAC + value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp); + value &= 0xFF70FF70; + value |= 0x00090008; // set en_active + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value); + + if (ret_val < 0) { + mutex_unlock(&dev->lock); + return -EINVAL; + } + // enable input is VIP/656 + value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); + value |= 0x00040100; // enable VIP + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); + + if (ret_val < 0) { + mutex_unlock(&dev->lock); + return -EINVAL; + } + // select AFE clock to output mode + value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); + value &= 0x83FFFFFF; + ret_val = + cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, + value | 0x10000000); + + if (ret_val < 0) { + mutex_unlock(&dev->lock); + return -EINVAL; + } + // Turn on all of the data out and control output pins. + value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp); + value &= 0xFEF0FE00; + if (_num_decoders == MAX_DECODERS) { + // Note: The octal board does not support control pins(bit16-19). + // These bits are ignored in the octal board. + value |= 0x010001F8; // disable VDEC A-C port, default to Mobilygen Interface + } else { + value |= 0x010F0108; // disable VDEC A-C port, default to Mobilygen Interface + } + + value |= 7; + ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value); + if (ret_val < 0) { + mutex_unlock(&dev->lock); + return -EINVAL; + } - if (ret_val < 0) - { mutex_unlock(&dev->lock); - return -EINVAL; - } - // select AFE clock to output mode - value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); - value &= 0x83FFFFFF; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, value | 0x10000000); + ret_val = medusa_set_videostandard(dev); - if (ret_val < 0) - { - mutex_unlock(&dev->lock); - return -EINVAL; - } - - // Turn on all of the data out and control output pins. - value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp); - value &= 0xFEF0FE00; - if (_num_decoders == MAX_DECODERS) - { - // Note: The octal board does not support control pins(bit16-19). - // These bits are ignored in the octal board. - value |= 0x010001F8; // disable VDEC A-C port, default to Mobilygen Interface - } - else - { - value |= 0x010F0108; // disable VDEC A-C port, default to Mobilygen Interface - } - - value |= 7; - ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value); - if (ret_val < 0) - { - mutex_unlock(&dev->lock); - return -EINVAL; - } - - mutex_unlock(&dev->lock); - - - ret_val = medusa_set_videostandard(dev); - - - if (ret_val < 0) - { - mutex_unlock(&dev->lock); - return -EINVAL; - } + if (ret_val < 0) { + mutex_unlock(&dev->lock); + return -EINVAL; + } - return 1; + return 1; } diff --git a/linux/drivers/staging/cx25821/cx25821-medusa-video.h b/linux/drivers/staging/cx25821/cx25821-medusa-video.h index 92fcd7a7b..2fab4b2f2 100644 --- a/linux/drivers/staging/cx25821/cx25821-medusa-video.h +++ b/linux/drivers/staging/cx25821/cx25821-medusa-video.h @@ -1,30 +1,29 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _MEDUSA_VIDEO_H -#define _MEDUSA_VIDEO_H - -#include "cx25821-medusa-defines.h" +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _MEDUSA_VIDEO_H +#define _MEDUSA_VIDEO_H +#include "cx25821-medusa-defines.h" // Color control constants #define VIDEO_PROCAMP_MIN 0 @@ -41,11 +40,10 @@ #define CONTRAST_DEFAULT 5000 #define HUE_DEFAULT 5000 +unsigned short _num_decoders; +unsigned short _num_cameras; -unsigned short _num_decoders; -unsigned short _num_cameras; +unsigned int _video_standard; +int _display_field_cnt[MAX_DECODERS]; -unsigned int _video_standard; -int _display_field_cnt[MAX_DECODERS]; - -#endif \ No newline at end of file +#endif diff --git a/linux/drivers/staging/cx25821/cx25821-reg.h b/linux/drivers/staging/cx25821/cx25821-reg.h index 3d9812465..7241e7ee3 100644 --- a/linux/drivers/staging/cx25821/cx25821-reg.h +++ b/linux/drivers/staging/cx25821/cx25821-reg.h @@ -1,24 +1,24 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ #ifndef __CX25821_REGISTERS__ #define __CX25821_REGISTERS__ @@ -47,25 +47,25 @@ #define RISC_SYNC_ODD_VBI 0x00000006 #define RISC_SYNC_EVEN_VBI 0x00000207 #define RISC_NOOP 0xF0000000 - -//***************************************************************************** + +//***************************************************************************** // ASB SRAM //***************************************************************************** -#define TX_SRAM 0x000000 // Transmit SRAM +#define TX_SRAM 0x000000 // Transmit SRAM //***************************************************************************** -#define RX_RAM 0x010000 // Receive SRAM +#define RX_RAM 0x010000 // Receive SRAM //***************************************************************************** // Application Layer (AL) //***************************************************************************** -#define DEV_CNTRL2 0x040000 // Device control +#define DEV_CNTRL2 0x040000 // Device control #define FLD_RUN_RISC 0x00000020 //***************************************************************************** -#define PCI_INT_MSK 0x040010 // PCI interrupt mask -#define PCI_INT_STAT 0x040014 // PCI interrupt status -#define PCI_INT_MSTAT 0x040018 // PCI interrupt masked status +#define PCI_INT_MSK 0x040010 // PCI interrupt mask +#define PCI_INT_STAT 0x040014 // PCI interrupt status +#define PCI_INT_MSTAT 0x040018 // PCI interrupt masked status #define FLD_HAMMERHEAD_INT (1 << 27) #define FLD_UART_INT (1 << 26) #define FLD_IRQN_INT (1 << 25) @@ -94,1499 +94,1484 @@ #define FLD_VID_A_INT (1 << 0) //***************************************************************************** -#define VID_A_INT_MSK 0x040020 // Video A interrupt mask -#define VID_A_INT_STAT 0x040024 // Video A interrupt status -#define VID_A_INT_MSTAT 0x040028 // Video A interrupt masked status -#define VID_A_INT_SSTAT 0x04002C // Video A interrupt set status - -//***************************************************************************** -#define VID_B_INT_MSK 0x040030 // Video B interrupt mask -#define VID_B_INT_STAT 0x040034 // Video B interrupt status -#define VID_B_INT_MSTAT 0x040038 // Video B interrupt masked status -#define VID_B_INT_SSTAT 0x04003C // Video B interrupt set status - -//***************************************************************************** -#define VID_C_INT_MSK 0x040040 // Video C interrupt mask -#define VID_C_INT_STAT 0x040044 // Video C interrupt status -#define VID_C_INT_MSTAT 0x040048 // Video C interrupt masked status -#define VID_C_INT_SSTAT 0x04004C // Video C interrupt set status - -//***************************************************************************** -#define VID_D_INT_MSK 0x040050 // Video D interrupt mask -#define VID_D_INT_STAT 0x040054 // Video D interrupt status -#define VID_D_INT_MSTAT 0x040058 // Video D interrupt masked status -#define VID_D_INT_SSTAT 0x04005C // Video D interrupt set status - -//***************************************************************************** -#define VID_E_INT_MSK 0x040060 // Video E interrupt mask -#define VID_E_INT_STAT 0x040064 // Video E interrupt status -#define VID_E_INT_MSTAT 0x040068 // Video E interrupt masked status -#define VID_E_INT_SSTAT 0x04006C // Video E interrupt set status - -//***************************************************************************** -#define VID_F_INT_MSK 0x040070 // Video F interrupt mask -#define VID_F_INT_STAT 0x040074 // Video F interrupt status -#define VID_F_INT_MSTAT 0x040078 // Video F interrupt masked status -#define VID_F_INT_SSTAT 0x04007C // Video F interrupt set status - -//***************************************************************************** -#define VID_G_INT_MSK 0x040080 // Video G interrupt mask -#define VID_G_INT_STAT 0x040084 // Video G interrupt status -#define VID_G_INT_MSTAT 0x040088 // Video G interrupt masked status -#define VID_G_INT_SSTAT 0x04008C // Video G interrupt set status - -//***************************************************************************** -#define VID_H_INT_MSK 0x040090 // Video H interrupt mask -#define VID_H_INT_STAT 0x040094 // Video H interrupt status -#define VID_H_INT_MSTAT 0x040098 // Video H interrupt masked status -#define VID_H_INT_SSTAT 0x04009C // Video H interrupt set status - -//***************************************************************************** -#define VID_I_INT_MSK 0x0400A0 // Video I interrupt mask -#define VID_I_INT_STAT 0x0400A4 // Video I interrupt status -#define VID_I_INT_MSTAT 0x0400A8 // Video I interrupt masked status -#define VID_I_INT_SSTAT 0x0400AC // Video I interrupt set status - -//***************************************************************************** -#define VID_J_INT_MSK 0x0400B0 // Video J interrupt mask -#define VID_J_INT_STAT 0x0400B4 // Video J interrupt status -#define VID_J_INT_MSTAT 0x0400B8 // Video J interrupt masked status -#define VID_J_INT_SSTAT 0x0400BC // Video J interrupt set status - -#define FLD_VID_SRC_OPC_ERR 0x00020000 -#define FLD_VID_DST_OPC_ERR 0x00010000 -#define FLD_VID_SRC_SYNC 0x00002000 -#define FLD_VID_DST_SYNC 0x00001000 -#define FLD_VID_SRC_UF 0x00000200 -#define FLD_VID_DST_OF 0x00000100 -#define FLD_VID_SRC_RISC2 0x00000020 -#define FLD_VID_DST_RISC2 0x00000010 -#define FLD_VID_SRC_RISC1 0x00000002 -#define FLD_VID_DST_RISC1 0x00000001 -#define FLD_VID_SRC_ERRORS FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF -#define FLD_VID_DST_ERRORS FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF - - -//***************************************************************************** -#define AUD_A_INT_MSK 0x0400C0 // Audio Int interrupt mask -#define AUD_A_INT_STAT 0x0400C4 // Audio Int interrupt status -#define AUD_A_INT_MSTAT 0x0400C8 // Audio Int interrupt masked status -#define AUD_A_INT_SSTAT 0x0400CC // Audio Int interrupt set status - -//***************************************************************************** -#define AUD_B_INT_MSK 0x0400D0 // Audio Int interrupt mask -#define AUD_B_INT_STAT 0x0400D4 // Audio Int interrupt status -#define AUD_B_INT_MSTAT 0x0400D8 // Audio Int interrupt masked status -#define AUD_B_INT_SSTAT 0x0400DC // Audio Int interrupt set status - -//***************************************************************************** -#define AUD_C_INT_MSK 0x0400E0 // Audio Int interrupt mask -#define AUD_C_INT_STAT 0x0400E4 // Audio Int interrupt status -#define AUD_C_INT_MSTAT 0x0400E8 // Audio Int interrupt masked status -#define AUD_C_INT_SSTAT 0x0400EC // Audio Int interrupt set status - -//***************************************************************************** -#define AUD_D_INT_MSK 0x0400F0 // Audio Int interrupt mask -#define AUD_D_INT_STAT 0x0400F4 // Audio Int interrupt status -#define AUD_D_INT_MSTAT 0x0400F8 // Audio Int interrupt masked status -#define AUD_D_INT_SSTAT 0x0400FC // Audio Int interrupt set status - -//***************************************************************************** -#define AUD_E_INT_MSK 0x040100 // Audio Int interrupt mask -#define AUD_E_INT_STAT 0x040104 // Audio Int interrupt status -#define AUD_E_INT_MSTAT 0x040108 // Audio Int interrupt masked status -#define AUD_E_INT_SSTAT 0x04010C // Audio Int interrupt set status - -#define FLD_AUD_SRC_OPC_ERR 0x00020000 -#define FLD_AUD_DST_OPC_ERR 0x00010000 -#define FLD_AUD_SRC_SYNC 0x00002000 -#define FLD_AUD_DST_SYNC 0x00001000 -#define FLD_AUD_SRC_OF 0x00000200 -#define FLD_AUD_DST_OF 0x00000100 -#define FLD_AUD_SRC_RISCI2 0x00000020 -#define FLD_AUD_DST_RISCI2 0x00000010 -#define FLD_AUD_SRC_RISCI1 0x00000002 -#define FLD_AUD_DST_RISCI1 0x00000001 - -//***************************************************************************** -#define MBIF_A_INT_MSK 0x040110 // MBIF Int interrupt mask -#define MBIF_A_INT_STAT 0x040114 // MBIF Int interrupt status -#define MBIF_A_INT_MSTAT 0x040118 // MBIF Int interrupt masked status -#define MBIF_A_INT_SSTAT 0x04011C // MBIF Int interrupt set status - -//***************************************************************************** -#define MBIF_B_INT_MSK 0x040120 // MBIF Int interrupt mask -#define MBIF_B_INT_STAT 0x040124 // MBIF Int interrupt status -#define MBIF_B_INT_MSTAT 0x040128 // MBIF Int interrupt masked status -#define MBIF_B_INT_SSTAT 0x04012C // MBIF Int interrupt set status - -#define FLD_MBIF_DST_OPC_ERR 0x00010000 -#define FLD_MBIF_DST_SYNC 0x00001000 -#define FLD_MBIF_DST_OF 0x00000100 -#define FLD_MBIF_DST_RISCI2 0x00000010 -#define FLD_MBIF_DST_RISCI1 0x00000001 - -//***************************************************************************** -#define AUD_EXT_INT_MSK 0x040060 // Audio Ext interrupt mask -#define AUD_EXT_INT_STAT 0x040064 // Audio Ext interrupt status -#define AUD_EXT_INT_MSTAT 0x040068 // Audio Ext interrupt masked status -#define AUD_EXT_INT_SSTAT 0x04006C // Audio Ext interrupt set status -#define FLD_AUD_EXT_OPC_ERR 0x00010000 -#define FLD_AUD_EXT_SYNC 0x00001000 -#define FLD_AUD_EXT_OF 0x00000100 -#define FLD_AUD_EXT_RISCI2 0x00000010 -#define FLD_AUD_EXT_RISCI1 0x00000001 - - -//***************************************************************************** -#define GPIO_LO 0x110010 // Lower of GPIO pins [31:0] -#define GPIO_HI 0x110014 // Upper WORD of GPIO pins [47:31] - -#define GPIO_LO_OE 0x110018 // Lower of GPIO output enable [31:0] -#define GPIO_HI_OE 0x11001C // Upper word of GPIO output enable [47:32] - -#define GPIO_LO_INT_MSK 0x11003C // GPIO interrupt mask -#define GPIO_LO_INT_STAT 0x110044 // GPIO interrupt status -#define GPIO_LO_INT_MSTAT 0x11004C // GPIO interrupt masked status -#define GPIO_LO_ISM_SNS 0x110054 // GPIO interrupt sensitivity -#define GPIO_LO_ISM_POL 0x11005C // GPIO interrupt polarity - -#define GPIO_HI_INT_MSK 0x110040 // GPIO interrupt mask -#define GPIO_HI_INT_STAT 0x110048 // GPIO interrupt status -#define GPIO_HI_INT_MSTAT 0x110050 // GPIO interrupt masked status -#define GPIO_HI_ISM_SNS 0x110058 // GPIO interrupt sensitivity -#define GPIO_HI_ISM_POL 0x110060 // GPIO interrupt polarity - -#define FLD_GPIO43_INT (1 << 11) -#define FLD_GPIO42_INT (1 << 10) -#define FLD_GPIO41_INT (1 << 9) -#define FLD_GPIO40_INT (1 << 8) - -#define FLD_GPIO9_INT (1 << 9) -#define FLD_GPIO8_INT (1 << 8) -#define FLD_GPIO7_INT (1 << 7) -#define FLD_GPIO6_INT (1 << 6) -#define FLD_GPIO5_INT (1 << 5) -#define FLD_GPIO4_INT (1 << 4) -#define FLD_GPIO3_INT (1 << 3) -#define FLD_GPIO2_INT (1 << 2) -#define FLD_GPIO1_INT (1 << 1) -#define FLD_GPIO0_INT (1 << 0) - -//***************************************************************************** -#define TC_REQ 0x040090 // Rider PCI Express traFFic class request - -//***************************************************************************** -#define TC_REQ_SET 0x040094 // Rider PCI Express traFFic class request set - - -//***************************************************************************** -// Rider -//***************************************************************************** - -// PCI Compatible Header -//***************************************************************************** -#define RDR_CFG0 0x050000 -#define RDR_VENDOR_DEVICE_ID_CFG 0x050000 - -//***************************************************************************** -#define RDR_CFG1 0x050004 - -//***************************************************************************** -#define RDR_CFG2 0x050008 - -//***************************************************************************** -#define RDR_CFG3 0x05000C - -//***************************************************************************** -#define RDR_CFG4 0x050010 - -//***************************************************************************** -#define RDR_CFG5 0x050014 - -//***************************************************************************** -#define RDR_CFG6 0x050018 - -//***************************************************************************** -#define RDR_CFG7 0x05001C - -//***************************************************************************** -#define RDR_CFG8 0x050020 - -//***************************************************************************** -#define RDR_CFG9 0x050024 - -//***************************************************************************** -#define RDR_CFGA 0x050028 - -//***************************************************************************** -#define RDR_CFGB 0x05002C -#define RDR_SUSSYSTEM_ID_CFG 0x05002C - -//***************************************************************************** -#define RDR_CFGC 0x050030 - -//***************************************************************************** -#define RDR_CFGD 0x050034 - -//***************************************************************************** -#define RDR_CFGE 0x050038 - -//***************************************************************************** -#define RDR_CFGF 0x05003C - -//***************************************************************************** -// PCI-Express Capabilities -//***************************************************************************** -#define RDR_PECAP 0x050040 - -//***************************************************************************** -#define RDR_PEDEVCAP 0x050044 - -//***************************************************************************** -#define RDR_PEDEVSC 0x050048 - -//***************************************************************************** -#define RDR_PELINKCAP 0x05004C - -//***************************************************************************** -#define RDR_PELINKSC 0x050050 - -//***************************************************************************** -#define RDR_PMICAP 0x050080 - -//***************************************************************************** -#define RDR_PMCSR 0x050084 - -//***************************************************************************** -#define RDR_VPDCAP 0x050090 - -//***************************************************************************** -#define RDR_VPDDATA 0x050094 - -//***************************************************************************** -#define RDR_MSICAP 0x0500A0 - -//***************************************************************************** -#define RDR_MSIARL 0x0500A4 - -//***************************************************************************** -#define RDR_MSIARU 0x0500A8 - -//***************************************************************************** -#define RDR_MSIDATA 0x0500AC - -//***************************************************************************** -// PCI Express Extended Capabilities -//***************************************************************************** -#define RDR_AERXCAP 0x050100 - -//***************************************************************************** -#define RDR_AERUESTA 0x050104 - -//***************************************************************************** -#define RDR_AERUEMSK 0x050108 - -//***************************************************************************** -#define RDR_AERUESEV 0x05010C - -//***************************************************************************** -#define RDR_AERCESTA 0x050110 - -//***************************************************************************** -#define RDR_AERCEMSK 0x050114 - -//***************************************************************************** -#define RDR_AERCC 0x050118 - -//***************************************************************************** -#define RDR_AERHL0 0x05011C - -//***************************************************************************** -#define RDR_AERHL1 0x050120 - -//***************************************************************************** -#define RDR_AERHL2 0x050124 - -//***************************************************************************** -#define RDR_AERHL3 0x050128 - -//***************************************************************************** -#define RDR_VCXCAP 0x050200 - -//***************************************************************************** -#define RDR_VCCAP1 0x050204 - -//***************************************************************************** -#define RDR_VCCAP2 0x050208 - -//***************************************************************************** -#define RDR_VCSC 0x05020C - -//***************************************************************************** -#define RDR_VCR0_CAP 0x050210 - -//***************************************************************************** -#define RDR_VCR0_CTRL 0x050214 - -//***************************************************************************** -#define RDR_VCR0_STAT 0x050218 - -//***************************************************************************** -#define RDR_VCR1_CAP 0x05021C - -//***************************************************************************** -#define RDR_VCR1_CTRL 0x050220 - -//***************************************************************************** -#define RDR_VCR1_STAT 0x050224 - -//***************************************************************************** -#define RDR_VCR2_CAP 0x050228 - -//***************************************************************************** -#define RDR_VCR2_CTRL 0x05022C - -//***************************************************************************** -#define RDR_VCR2_STAT 0x050230 - -//***************************************************************************** -#define RDR_VCR3_CAP 0x050234 - -//***************************************************************************** -#define RDR_VCR3_CTRL 0x050238 - -//***************************************************************************** -#define RDR_VCR3_STAT 0x05023C - -//***************************************************************************** -#define RDR_VCARB0 0x050240 - -//***************************************************************************** -#define RDR_VCARB1 0x050244 - -//***************************************************************************** -#define RDR_VCARB2 0x050248 - -//***************************************************************************** -#define RDR_VCARB3 0x05024C - -//***************************************************************************** -#define RDR_VCARB4 0x050250 - -//***************************************************************************** -#define RDR_VCARB5 0x050254 - -//***************************************************************************** -#define RDR_VCARB6 0x050258 - -//***************************************************************************** -#define RDR_VCARB7 0x05025C - -//***************************************************************************** -#define RDR_RDRSTAT0 0x050300 - -//***************************************************************************** -#define RDR_RDRSTAT1 0x050304 - -//***************************************************************************** -#define RDR_RDRCTL0 0x050308 - -//***************************************************************************** -#define RDR_RDRCTL1 0x05030C - -//***************************************************************************** -// Transaction Layer Registers -//***************************************************************************** -#define RDR_TLSTAT0 0x050310 - -//***************************************************************************** -#define RDR_TLSTAT1 0x050314 - -//***************************************************************************** -#define RDR_TLCTL0 0x050318 -#define FLD_CFG_UR_CPL_MODE 0x00000040 -#define FLD_CFG_CORR_ERR_QUITE 0x00000020 -#define FLD_CFG_RCB_CK_EN 0x00000010 -#define FLD_CFG_BNDRY_CK_EN 0x00000008 -#define FLD_CFG_BYTE_EN_CK_EN 0x00000004 -#define FLD_CFG_RELAX_ORDER_MSK 0x00000002 -#define FLD_CFG_TAG_ORDER_EN 0x00000001 - -//***************************************************************************** -#define RDR_TLCTL1 0x05031C - -//***************************************************************************** -#define RDR_REQRCAL 0x050320 - -//***************************************************************************** -#define RDR_REQRCAU 0x050324 - -//***************************************************************************** -#define RDR_REQEPA 0x050328 - -//***************************************************************************** -#define RDR_REQCTRL 0x05032C - -//***************************************************************************** -#define RDR_REQSTAT 0x050330 - -//***************************************************************************** -#define RDR_TL_TEST 0x050334 - -//***************************************************************************** -#define RDR_VCR01_CTL 0x050348 - -//***************************************************************************** -#define RDR_VCR23_CTL 0x05034C - -//***************************************************************************** -#define RDR_RX_VCR0_FC 0x050350 - -//***************************************************************************** -#define RDR_RX_VCR1_FC 0x050354 - -//***************************************************************************** -#define RDR_RX_VCR2_FC 0x050358 - -//***************************************************************************** -#define RDR_RX_VCR3_FC 0x05035C - -//***************************************************************************** -// Data Link Layer Registers -//***************************************************************************** -#define RDR_DLLSTAT 0x050360 - -//***************************************************************************** -#define RDR_DLLCTRL 0x050364 - -//***************************************************************************** -#define RDR_REPLAYTO 0x050368 - -//***************************************************************************** -#define RDR_ACKLATTO 0x05036C - -//***************************************************************************** -// MAC Layer Registers -//***************************************************************************** -#define RDR_MACSTAT0 0x050380 - -//***************************************************************************** -#define RDR_MACSTAT1 0x050384 - -//***************************************************************************** -#define RDR_MACCTRL0 0x050388 - -//***************************************************************************** -#define RDR_MACCTRL1 0x05038C - -//***************************************************************************** -#define RDR_MACCTRL2 0x050390 - -//***************************************************************************** -#define RDR_MAC_LB_DATA 0x050394 - -//***************************************************************************** -#define RDR_L0S_EXIT_LAT 0x050398 - -//***************************************************************************** -// DMAC -//***************************************************************************** -#define DMA1_PTR1 0x100000 // DMA Current Ptr : Ch#1 - -//***************************************************************************** -#define DMA2_PTR1 0x100004 // DMA Current Ptr : Ch#2 - -//***************************************************************************** -#define DMA3_PTR1 0x100008 // DMA Current Ptr : Ch#3 - -//***************************************************************************** -#define DMA4_PTR1 0x10000C // DMA Current Ptr : Ch#4 - -//***************************************************************************** -#define DMA5_PTR1 0x100010 // DMA Current Ptr : Ch#5 - -//***************************************************************************** -#define DMA6_PTR1 0x100014 // DMA Current Ptr : Ch#6 - -//***************************************************************************** -#define DMA7_PTR1 0x100018 // DMA Current Ptr : Ch#7 - -//***************************************************************************** -#define DMA8_PTR1 0x10001C // DMA Current Ptr : Ch#8 - -//***************************************************************************** -#define DMA9_PTR1 0x100020 // DMA Current Ptr : Ch#9 - -//***************************************************************************** -#define DMA10_PTR1 0x100024 // DMA Current Ptr : Ch#10 - -//***************************************************************************** -#define DMA11_PTR1 0x100028 // DMA Current Ptr : Ch#11 - -//***************************************************************************** -#define DMA12_PTR1 0x10002C // DMA Current Ptr : Ch#12 - -//***************************************************************************** -#define DMA13_PTR1 0x100030 // DMA Current Ptr : Ch#13 - -//***************************************************************************** -#define DMA14_PTR1 0x100034 // DMA Current Ptr : Ch#14 - -//***************************************************************************** -#define DMA15_PTR1 0x100038 // DMA Current Ptr : Ch#15 - -//***************************************************************************** -#define DMA16_PTR1 0x10003C // DMA Current Ptr : Ch#16 - -//***************************************************************************** -#define DMA17_PTR1 0x100040 // DMA Current Ptr : Ch#17 - -//***************************************************************************** -#define DMA18_PTR1 0x100044 // DMA Current Ptr : Ch#18 - -//***************************************************************************** -#define DMA19_PTR1 0x100048 // DMA Current Ptr : Ch#19 - -//***************************************************************************** -#define DMA20_PTR1 0x10004C // DMA Current Ptr : Ch#20 - -//***************************************************************************** -#define DMA21_PTR1 0x100050 // DMA Current Ptr : Ch#21 - -//***************************************************************************** -#define DMA22_PTR1 0x100054 // DMA Current Ptr : Ch#22 - -//***************************************************************************** -#define DMA23_PTR1 0x100058 // DMA Current Ptr : Ch#23 - -//***************************************************************************** -#define DMA24_PTR1 0x10005C // DMA Current Ptr : Ch#24 - -//***************************************************************************** -#define DMA25_PTR1 0x100060 // DMA Current Ptr : Ch#25 - -//***************************************************************************** -#define DMA26_PTR1 0x100064 // DMA Current Ptr : Ch#26 - - -//***************************************************************************** -#define DMA1_PTR2 0x100080 // DMA Tab Ptr : Ch#1 - -//***************************************************************************** -#define DMA2_PTR2 0x100084 // DMA Tab Ptr : Ch#2 - -//***************************************************************************** -#define DMA3_PTR2 0x100088 // DMA Tab Ptr : Ch#3 - -//***************************************************************************** -#define DMA4_PTR2 0x10008C // DMA Tab Ptr : Ch#4 - -//***************************************************************************** -#define DMA5_PTR2 0x100090 // DMA Tab Ptr : Ch#5 - -//***************************************************************************** -#define DMA6_PTR2 0x100094 // DMA Tab Ptr : Ch#6 - -//***************************************************************************** -#define DMA7_PTR2 0x100098 // DMA Tab Ptr : Ch#7 - -//***************************************************************************** -#define DMA8_PTR2 0x10009C // DMA Tab Ptr : Ch#8 - -//***************************************************************************** -#define DMA9_PTR2 0x1000A0 // DMA Tab Ptr : Ch#9 - -//***************************************************************************** -#define DMA10_PTR2 0x1000A4 // DMA Tab Ptr : Ch#10 - -//***************************************************************************** -#define DMA11_PTR2 0x1000A8 // DMA Tab Ptr : Ch#11 - -//***************************************************************************** -#define DMA12_PTR2 0x1000AC // DMA Tab Ptr : Ch#12 - -//***************************************************************************** -#define DMA13_PTR2 0x1000B0 // DMA Tab Ptr : Ch#13 - -//***************************************************************************** -#define DMA14_PTR2 0x1000B4 // DMA Tab Ptr : Ch#14 - -//***************************************************************************** -#define DMA15_PTR2 0x1000B8 // DMA Tab Ptr : Ch#15 - -//***************************************************************************** -#define DMA16_PTR2 0x1000BC // DMA Tab Ptr : Ch#16 - -//***************************************************************************** -#define DMA17_PTR2 0x1000C0 // DMA Tab Ptr : Ch#17 - -//***************************************************************************** -#define DMA18_PTR2 0x1000C4 // DMA Tab Ptr : Ch#18 - -//***************************************************************************** -#define DMA19_PTR2 0x1000C8 // DMA Tab Ptr : Ch#19 - -//***************************************************************************** -#define DMA20_PTR2 0x1000CC // DMA Tab Ptr : Ch#20 - -//***************************************************************************** -#define DMA21_PTR2 0x1000D0 // DMA Tab Ptr : Ch#21 - -//***************************************************************************** -#define DMA22_PTR2 0x1000D4 // DMA Tab Ptr : Ch#22 - -//***************************************************************************** -#define DMA23_PTR2 0x1000D8 // DMA Tab Ptr : Ch#23 - -//***************************************************************************** -#define DMA24_PTR2 0x1000DC // DMA Tab Ptr : Ch#24 - -//***************************************************************************** -#define DMA25_PTR2 0x1000E0 // DMA Tab Ptr : Ch#25 - -//***************************************************************************** -#define DMA26_PTR2 0x1000E4 // DMA Tab Ptr : Ch#26 - - - -//***************************************************************************** -#define DMA1_CNT1 0x100100 // DMA BuFFer Size : Ch#1 - -//***************************************************************************** -#define DMA2_CNT1 0x100104 // DMA BuFFer Size : Ch#2 - -//***************************************************************************** -#define DMA3_CNT1 0x100108 // DMA BuFFer Size : Ch#3 - -//***************************************************************************** -#define DMA4_CNT1 0x10010C // DMA BuFFer Size : Ch#4 - -//***************************************************************************** -#define DMA5_CNT1 0x100110 // DMA BuFFer Size : Ch#5 - -//***************************************************************************** -#define DMA6_CNT1 0x100114 // DMA BuFFer Size : Ch#6 - -//***************************************************************************** -#define DMA7_CNT1 0x100118 // DMA BuFFer Size : Ch#7 - -//***************************************************************************** -#define DMA8_CNT1 0x10011C // DMA BuFFer Size : Ch#8 - -//***************************************************************************** -#define DMA9_CNT1 0x100120 // DMA BuFFer Size : Ch#9 - -//***************************************************************************** -#define DMA10_CNT1 0x100124 // DMA BuFFer Size : Ch#10 - -//***************************************************************************** -#define DMA11_CNT1 0x100128 // DMA BuFFer Size : Ch#11 - -//***************************************************************************** -#define DMA12_CNT1 0x10012C // DMA BuFFer Size : Ch#12 - -//***************************************************************************** -#define DMA13_CNT1 0x100130 // DMA BuFFer Size : Ch#13 - -//***************************************************************************** -#define DMA14_CNT1 0x100134 // DMA BuFFer Size : Ch#14 - -//***************************************************************************** -#define DMA15_CNT1 0x100138 // DMA BuFFer Size : Ch#15 - -//***************************************************************************** -#define DMA16_CNT1 0x10013C // DMA BuFFer Size : Ch#16 - -//***************************************************************************** -#define DMA17_CNT1 0x100140 // DMA BuFFer Size : Ch#17 - -//***************************************************************************** -#define DMA18_CNT1 0x100144 // DMA BuFFer Size : Ch#18 - -//***************************************************************************** -#define DMA19_CNT1 0x100148 // DMA BuFFer Size : Ch#19 - -//***************************************************************************** -#define DMA20_CNT1 0x10014C // DMA BuFFer Size : Ch#20 - -//***************************************************************************** -#define DMA21_CNT1 0x100150 // DMA BuFFer Size : Ch#21 - -//***************************************************************************** -#define DMA22_CNT1 0x100154 // DMA BuFFer Size : Ch#22 - -//***************************************************************************** -#define DMA23_CNT1 0x100158 // DMA BuFFer Size : Ch#23 - -//***************************************************************************** -#define DMA24_CNT1 0x10015C // DMA BuFFer Size : Ch#24 - -//***************************************************************************** -#define DMA25_CNT1 0x100160 // DMA BuFFer Size : Ch#25 - -//***************************************************************************** -#define DMA26_CNT1 0x100164 // DMA BuFFer Size : Ch#26 - - -//***************************************************************************** -#define DMA1_CNT2 0x100180 // DMA Table Size : Ch#1 - -//***************************************************************************** -#define DMA2_CNT2 0x100184 // DMA Table Size : Ch#2 - -//***************************************************************************** -#define DMA3_CNT2 0x100188 // DMA Table Size : Ch#3 - -//***************************************************************************** -#define DMA4_CNT2 0x10018C // DMA Table Size : Ch#4 - -//***************************************************************************** -#define DMA5_CNT2 0x100190 // DMA Table Size : Ch#5 - -//***************************************************************************** -#define DMA6_CNT2 0x100194 // DMA Table Size : Ch#6 - -//***************************************************************************** -#define DMA7_CNT2 0x100198 // DMA Table Size : Ch#7 - -//***************************************************************************** -#define DMA8_CNT2 0x10019C // DMA Table Size : Ch#8 - -//***************************************************************************** -#define DMA9_CNT2 0x1001A0 // DMA Table Size : Ch#9 - -//***************************************************************************** -#define DMA10_CNT2 0x1001A4 // DMA Table Size : Ch#10 - -//***************************************************************************** -#define DMA11_CNT2 0x1001A8 // DMA Table Size : Ch#11 - -//***************************************************************************** -#define DMA12_CNT2 0x1001AC // DMA Table Size : Ch#12 - -//***************************************************************************** -#define DMA13_CNT2 0x1001B0 // DMA Table Size : Ch#13 - -//***************************************************************************** -#define DMA14_CNT2 0x1001B4 // DMA Table Size : Ch#14 - -//***************************************************************************** -#define DMA15_CNT2 0x1001B8 // DMA Table Size : Ch#15 - -//***************************************************************************** -#define DMA16_CNT2 0x1001BC // DMA Table Size : Ch#16 - -//***************************************************************************** -#define DMA17_CNT2 0x1001C0 // DMA Table Size : Ch#17 - -//***************************************************************************** -#define DMA18_CNT2 0x1001C4 // DMA Table Size : Ch#18 - -//***************************************************************************** -#define DMA19_CNT2 0x1001C8 // DMA Table Size : Ch#19 - -//***************************************************************************** -#define DMA20_CNT2 0x1001CC // DMA Table Size : Ch#20 - -//***************************************************************************** -#define DMA21_CNT2 0x1001D0 // DMA Table Size : Ch#21 - -//***************************************************************************** -#define DMA22_CNT2 0x1001D4 // DMA Table Size : Ch#22 - -//***************************************************************************** -#define DMA23_CNT2 0x1001D8 // DMA Table Size : Ch#23 - -//***************************************************************************** -#define DMA24_CNT2 0x1001DC // DMA Table Size : Ch#24 - -//***************************************************************************** -#define DMA25_CNT2 0x1001E0 // DMA Table Size : Ch#25 - -//***************************************************************************** -#define DMA26_CNT2 0x1001E4 // DMA Table Size : Ch#26 - - - -//***************************************************************************** - // ITG -//***************************************************************************** -#define TM_CNT_LDW 0x110000 // Timer : Counter low - -//***************************************************************************** -#define TM_CNT_UW 0x110004 // Timer : Counter high word - -//***************************************************************************** -#define TM_LMT_LDW 0x110008 // Timer : Limit low - -//***************************************************************************** -#define TM_LMT_UW 0x11000C // Timer : Limit high word - -//***************************************************************************** -#define GP0_IO 0x110010 // GPIO output enables data I/O -#define FLD_GP_OE 0x00FF0000 // GPIO: GP_OE output enable -#define FLD_GP_IN 0x0000FF00 // GPIO: GP_IN status -#define FLD_GP_OUT 0x000000FF // GPIO: GP_OUT control - -//***************************************************************************** -#define GPIO_ISM 0x110014 // GPIO interrupt sensitivity mode -#define FLD_GP_ISM_SNS 0x00000070 -#define FLD_GP_ISM_POL 0x00000007 - -//***************************************************************************** -#define SOFT_RESET 0x11001C // Output system reset reg -#define FLD_PECOS_SOFT_RESET 0x00000001 - -//***************************************************************************** -#define MC416_RWD 0x110020 // MC416 GPIO[18:3] pin -#define MC416_OEN 0x110024 // Output enable of GPIO[18:3] -#define MC416_CTL 0x110028 - -//***************************************************************************** -#define ALT_PIN_OUT_SEL 0x11002C // Alternate GPIO output select - -#define FLD_ALT_GPIO_OUT_SEL 0xF0000000 -// 0 Disabled <-- default -// 1 GPIO[0] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] -// 8 ATT_IF - -#define FLD_AUX_PLL_CLK_ALT_SEL 0x0F000000 -// 0 AUX_PLL_CLK<-- default -// 1 GPIO[2] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] - -#define FLD_IR_TX_ALT_SEL 0x00F00000 -// 0 IR_TX <-- default -// 1 GPIO[1] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] - -#define FLD_IR_RX_ALT_SEL 0x000F0000 -// 0 IR_RX <-- default -// 1 GPIO[0] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] - -#define FLD_GPIO10_ALT_SEL 0x0000F000 -// 0 GPIO[10] <-- default -// 1 GPIO[0] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] - -#define FLD_GPIO2_ALT_SEL 0x00000F00 -// 0 GPIO[2] <-- default -// 1 GPIO[1] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] - -#define FLD_GPIO1_ALT_SEL 0x000000F0 -// 0 GPIO[1] <-- default -// 1 GPIO[0] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] - -#define FLD_GPIO0_ALT_SEL 0x0000000F -// 0 GPIO[0] <-- default -// 1 GPIO[1] -// 2 GPIO[10] -// 3 VIP_656_DATA_VAL -// 4 VIP_656_DATA[0] -// 5 VIP_656_CLK -// 6 VIP_656_DATA_EXT[1] -// 7 VIP_656_DATA_EXT[0] - -#define ALT_PIN_IN_SEL 0x110030 // Alternate GPIO input select - -#define FLD_GPIO10_ALT_IN_SEL 0x0000F000 -// 0 GPIO[10] <-- default -// 1 IR_RX -// 2 IR_TX -// 3 AUX_PLL_CLK -// 4 IF_ATT_SEL -// 5 GPIO[0] -// 6 GPIO[1] -// 7 GPIO[2] - -#define FLD_GPIO2_ALT_IN_SEL 0x00000F00 -// 0 GPIO[2] <-- default -// 1 IR_RX -// 2 IR_TX -// 3 AUX_PLL_CLK -// 4 IF_ATT_SEL - -#define FLD_GPIO1_ALT_IN_SEL 0x000000F0 -// 0 GPIO[1] <-- default -// 1 IR_RX -// 2 IR_TX -// 3 AUX_PLL_CLK -// 4 IF_ATT_SEL - -#define FLD_GPIO0_ALT_IN_SEL 0x0000000F -// 0 GPIO[0] <-- default -// 1 IR_RX -// 2 IR_TX -// 3 AUX_PLL_CLK -// 4 IF_ATT_SEL - -//***************************************************************************** -#define TEST_BUS_CTL1 0x110040 // Test bus control register #1 - -//***************************************************************************** -#define TEST_BUS_CTL2 0x110044 // Test bus control register #2 - -//***************************************************************************** -#define CLK_DELAY 0x110048 // Clock delay -#define FLD_MOE_CLK_DIS 0x80000000 // Disable MoE clock - - -//***************************************************************************** -#define PAD_CTRL 0x110068 // Pad drive strength control - -//***************************************************************************** -#define MBIST_CTRL 0x110050 // SRAM memory built-in self test control - -//***************************************************************************** -#define MBIST_STAT 0x110054 // SRAM memory built-in self test status - -//***************************************************************************** -// PLL registers -//***************************************************************************** -#define PLL_A_INT_FRAC 0x110088 -#define PLL_A_POST_STAT_BIST 0x11008C -#define PLL_B_INT_FRAC 0x110090 -#define PLL_B_POST_STAT_BIST 0x110094 -#define PLL_C_INT_FRAC 0x110098 -#define PLL_C_POST_STAT_BIST 0x11009C -#define PLL_D_INT_FRAC 0x1100A0 -#define PLL_D_POST_STAT_BIST 0x1100A4 - -#define CLK_RST 0x11002C -#define FLD_VID_I_CLK_NOE 0x00001000 -#define FLD_VID_J_CLK_NOE 0x00002000 -#define FLD_USE_ALT_PLL_REF 0x00004000 - -#define VID_CH_MODE_SEL 0x110078 -#define VID_CH_CLK_SEL 0x11007C - - -//***************************************************************************** -#define VBI_A_DMA 0x130008 // VBI A DMA data port - -//***************************************************************************** -#define VID_A_VIP_CTL 0x130080 // Video A VIP format control -#define FLD_VIP_MODE 0x00000001 - -//***************************************************************************** -#define VID_A_PIXEL_FRMT 0x130084 // Video A pixel format -#define FLD_VID_A_GAMMA_DIS 0x00000008 -#define FLD_VID_A_FORMAT 0x00000007 -#define FLD_VID_A_GAMMA_FACTOR 0x00000010 - -//***************************************************************************** -#define VID_A_VBI_CTL 0x130088 // Video A VBI miscellaneous control -#define FLD_VID_A_VIP_EXT 0x00000003 - -//***************************************************************************** -#define VID_B_DMA 0x130100 // Video B DMA data port - -//***************************************************************************** -#define VBI_B_DMA 0x130108 // VBI B DMA data port - -//***************************************************************************** -#define VID_B_SRC_SEL 0x130144 // Video B source select -#define FLD_VID_B_SRC_SEL 0x00000000 - -//***************************************************************************** -#define VID_B_LNGTH 0x130150 // Video B line length -#define FLD_VID_B_LN_LNGTH 0x00000FFF - -//***************************************************************************** -#define VID_B_VIP_CTL 0x130180 // Video B VIP format control - -//***************************************************************************** -#define VID_B_PIXEL_FRMT 0x130184 // Video B pixel format -#define FLD_VID_B_GAMMA_DIS 0x00000008 -#define FLD_VID_B_FORMAT 0x00000007 -#define FLD_VID_B_GAMMA_FACTOR 0x00000010 - -//***************************************************************************** -#define VID_C_DMA 0x130200 // Video C DMA data port - -//***************************************************************************** -#define VID_C_LNGTH 0x130250 // Video C line length -#define FLD_VID_C_LN_LNGTH 0x00000FFF - - -//***************************************************************************** -// Video Destination Channels -//***************************************************************************** - -#define VID_DST_A_GPCNT 0x130020 // Video A general purpose counter -#define VID_DST_B_GPCNT 0x130120 // Video B general purpose counter -#define VID_DST_C_GPCNT 0x130220 // Video C general purpose counter -#define VID_DST_D_GPCNT 0x130320 // Video D general purpose counter -#define VID_DST_E_GPCNT 0x130420 // Video E general purpose counter -#define VID_DST_F_GPCNT 0x130520 // Video F general purpose counter -#define VID_DST_G_GPCNT 0x130620 // Video G general purpose counter -#define VID_DST_H_GPCNT 0x130720 // Video H general purpose counter - -//***************************************************************************** - -#define VID_DST_A_GPCNT_CTL 0x130030 // Video A general purpose control -#define VID_DST_B_GPCNT_CTL 0x130130 // Video B general purpose control -#define VID_DST_C_GPCNT_CTL 0x130230 // Video C general purpose control -#define VID_DST_D_GPCNT_CTL 0x130330 // Video D general purpose control -#define VID_DST_E_GPCNT_CTL 0x130430 // Video E general purpose control -#define VID_DST_F_GPCNT_CTL 0x130530 // Video F general purpose control -#define VID_DST_G_GPCNT_CTL 0x130630 // Video G general purpose control -#define VID_DST_H_GPCNT_CTL 0x130730 // Video H general purpose control - - -//***************************************************************************** - -#define VID_DST_A_DMA_CTL 0x130040 // Video A DMA control -#define VID_DST_B_DMA_CTL 0x130140 // Video B DMA control -#define VID_DST_C_DMA_CTL 0x130240 // Video C DMA control -#define VID_DST_D_DMA_CTL 0x130340 // Video D DMA control -#define VID_DST_E_DMA_CTL 0x130440 // Video E DMA control -#define VID_DST_F_DMA_CTL 0x130540 // Video F DMA control -#define VID_DST_G_DMA_CTL 0x130640 // Video G DMA control -#define VID_DST_H_DMA_CTL 0x130740 // Video H DMA control - -#define FLD_VID_RISC_EN 0x00000010 -#define FLD_VID_FIFO_EN 0x00000001 - -//***************************************************************************** - -#define VID_DST_A_VIP_CTL 0x130080 // Video A VIP control -#define VID_DST_B_VIP_CTL 0x130180 // Video B VIP control -#define VID_DST_C_VIP_CTL 0x130280 // Video C VIP control -#define VID_DST_D_VIP_CTL 0x130380 // Video D VIP control -#define VID_DST_E_VIP_CTL 0x130480 // Video E VIP control -#define VID_DST_F_VIP_CTL 0x130580 // Video F VIP control -#define VID_DST_G_VIP_CTL 0x130680 // Video G VIP control -#define VID_DST_H_VIP_CTL 0x130780 // Video H VIP control - -//***************************************************************************** - -#define VID_DST_A_PIX_FRMT 0x130084 // Video A Pixel format -#define VID_DST_B_PIX_FRMT 0x130184 // Video B Pixel format -#define VID_DST_C_PIX_FRMT 0x130284 // Video C Pixel format -#define VID_DST_D_PIX_FRMT 0x130384 // Video D Pixel format -#define VID_DST_E_PIX_FRMT 0x130484 // Video E Pixel format -#define VID_DST_F_PIX_FRMT 0x130584 // Video F Pixel format -#define VID_DST_G_PIX_FRMT 0x130684 // Video G Pixel format -#define VID_DST_H_PIX_FRMT 0x130784 // Video H Pixel format - -//***************************************************************************** -// Video Source Channels -//***************************************************************************** - -#define VID_SRC_A_GPCNT_CTL 0x130804 // Video A general purpose control -#define VID_SRC_B_GPCNT_CTL 0x130904 // Video B general purpose control -#define VID_SRC_C_GPCNT_CTL 0x130A04 // Video C general purpose control -#define VID_SRC_D_GPCNT_CTL 0x130B04 // Video D general purpose control -#define VID_SRC_E_GPCNT_CTL 0x130C04 // Video E general purpose control -#define VID_SRC_F_GPCNT_CTL 0x130D04 // Video F general purpose control -#define VID_SRC_I_GPCNT_CTL 0x130E04 // Video I general purpose control -#define VID_SRC_J_GPCNT_CTL 0x130F04 // Video J general purpose control - -//***************************************************************************** - -#define VID_SRC_A_GPCNT 0x130808 // Video A general purpose counter -#define VID_SRC_B_GPCNT 0x130908 // Video B general purpose counter -#define VID_SRC_C_GPCNT 0x130A08 // Video C general purpose counter -#define VID_SRC_D_GPCNT 0x130B08 // Video D general purpose counter -#define VID_SRC_E_GPCNT 0x130C08 // Video E general purpose counter -#define VID_SRC_F_GPCNT 0x130D08 // Video F general purpose counter -#define VID_SRC_I_GPCNT 0x130E08 // Video I general purpose counter -#define VID_SRC_J_GPCNT 0x130F08 // Video J general purpose counter - -//***************************************************************************** - -#define VID_SRC_A_DMA_CTL 0x13080C // Video A DMA control -#define VID_SRC_B_DMA_CTL 0x13090C // Video B DMA control -#define VID_SRC_C_DMA_CTL 0x130A0C // Video C DMA control -#define VID_SRC_D_DMA_CTL 0x130B0C // Video D DMA control -#define VID_SRC_E_DMA_CTL 0x130C0C // Video E DMA control -#define VID_SRC_F_DMA_CTL 0x130D0C // Video F DMA control -#define VID_SRC_I_DMA_CTL 0x130E0C // Video I DMA control -#define VID_SRC_J_DMA_CTL 0x130F0C // Video J DMA control - -#define FLD_APB_RISC_EN 0x00000010 -#define FLD_APB_FIFO_EN 0x00000001 - -//***************************************************************************** - -#define VID_SRC_A_FMT_CTL 0x130810 // Video A format control -#define VID_SRC_B_FMT_CTL 0x130910 // Video B format control -#define VID_SRC_C_FMT_CTL 0x130A10 // Video C format control -#define VID_SRC_D_FMT_CTL 0x130B10 // Video D format control -#define VID_SRC_E_FMT_CTL 0x130C10 // Video E format control -#define VID_SRC_F_FMT_CTL 0x130D10 // Video F format control -#define VID_SRC_I_FMT_CTL 0x130E10 // Video I format control -#define VID_SRC_J_FMT_CTL 0x130F10 // Video J format control - -//***************************************************************************** - -#define VID_SRC_A_ACTIVE_CTL1 0x130814 // Video A active control 1 -#define VID_SRC_B_ACTIVE_CTL1 0x130914 // Video B active control 1 -#define VID_SRC_C_ACTIVE_CTL1 0x130A14 // Video C active control 1 -#define VID_SRC_D_ACTIVE_CTL1 0x130B14 // Video D active control 1 -#define VID_SRC_E_ACTIVE_CTL1 0x130C14 // Video E active control 1 -#define VID_SRC_F_ACTIVE_CTL1 0x130D14 // Video F active control 1 -#define VID_SRC_I_ACTIVE_CTL1 0x130E14 // Video I active control 1 -#define VID_SRC_J_ACTIVE_CTL1 0x130F14 // Video J active control 1 - -//***************************************************************************** - -#define VID_SRC_A_ACTIVE_CTL2 0x130818 // Video A active control 2 -#define VID_SRC_B_ACTIVE_CTL2 0x130918 // Video B active control 2 -#define VID_SRC_C_ACTIVE_CTL2 0x130A18 // Video C active control 2 -#define VID_SRC_D_ACTIVE_CTL2 0x130B18 // Video D active control 2 -#define VID_SRC_E_ACTIVE_CTL2 0x130C18 // Video E active control 2 -#define VID_SRC_F_ACTIVE_CTL2 0x130D18 // Video F active control 2 -#define VID_SRC_I_ACTIVE_CTL2 0x130E18 // Video I active control 2 -#define VID_SRC_J_ACTIVE_CTL2 0x130F18 // Video J active control 2 - -//***************************************************************************** - -#define VID_SRC_A_CDT_SZ 0x13081C // Video A CDT size -#define VID_SRC_B_CDT_SZ 0x13091C // Video B CDT size -#define VID_SRC_C_CDT_SZ 0x130A1C // Video C CDT size -#define VID_SRC_D_CDT_SZ 0x130B1C // Video D CDT size -#define VID_SRC_E_CDT_SZ 0x130C1C // Video E CDT size -#define VID_SRC_F_CDT_SZ 0x130D1C // Video F CDT size -#define VID_SRC_I_CDT_SZ 0x130E1C // Video I CDT size -#define VID_SRC_J_CDT_SZ 0x130F1C // Video J CDT size - -//***************************************************************************** -// Audio I/F -//***************************************************************************** -#define AUD_DST_A_DMA 0x140000 // Audio Int A DMA data port -#define AUD_SRC_A_DMA 0x140008 // Audio Int A DMA data port - -#define AUD_A_GPCNT 0x140010 // Audio Int A gp counter -#define FLD_AUD_A_GP_CNT 0x0000FFFF - -#define AUD_A_GPCNT_CTL 0x140014 // Audio Int A gp control - -#define AUD_A_LNGTH 0x140018 // Audio Int A line length - -#define AUD_A_CFG 0x14001C // Audio Int A configuration - -//***************************************************************************** -#define AUD_DST_B_DMA 0x140100 // Audio Int B DMA data port -#define AUD_SRC_B_DMA 0x140108 // Audio Int B DMA data port - -#define AUD_B_GPCNT 0x140110 // Audio Int B gp counter -#define FLD_AUD_B_GP_CNT 0x0000FFFF - -#define AUD_B_GPCNT_CTL 0x140114 // Audio Int B gp control - -#define AUD_B_LNGTH 0x140118 // Audio Int B line length - -#define AUD_B_CFG 0x14011C // Audio Int B configuration - -//***************************************************************************** -#define AUD_DST_C_DMA 0x140200 // Audio Int C DMA data port -#define AUD_SRC_C_DMA 0x140208 // Audio Int C DMA data port - -#define AUD_C_GPCNT 0x140210 // Audio Int C gp counter -#define FLD_AUD_C_GP_CNT 0x0000FFFF - -#define AUD_C_GPCNT_CTL 0x140214 // Audio Int C gp control - -#define AUD_C_LNGTH 0x140218 // Audio Int C line length - -#define AUD_C_CFG 0x14021C // Audio Int C configuration - -//***************************************************************************** -#define AUD_DST_D_DMA 0x140300 // Audio Int D DMA data port -#define AUD_SRC_D_DMA 0x140308 // Audio Int D DMA data port - -#define AUD_D_GPCNT 0x140310 // Audio Int D gp counter -#define FLD_AUD_D_GP_CNT 0x0000FFFF - -#define AUD_D_GPCNT_CTL 0x140314 // Audio Int D gp control - -#define AUD_D_LNGTH 0x140318 // Audio Int D line length - -#define AUD_D_CFG 0x14031C // Audio Int D configuration - -//***************************************************************************** -#define AUD_SRC_E_DMA 0x140400 // Audio Int E DMA data port - -#define AUD_E_GPCNT 0x140410 // Audio Int E gp counter -#define FLD_AUD_E_GP_CNT 0x0000FFFF - -#define AUD_E_GPCNT_CTL 0x140414 // Audio Int E gp control - -#define AUD_E_CFG 0x14041C // Audio Int E configuration - -//***************************************************************************** - -#define FLD_AUD_DST_LN_LNGTH 0x00000FFF - -#define FLD_AUD_DST_PK_MODE 0x00004000 - -#define FLD_AUD_CLK_ENABLE 0x00000200 - -#define FLD_AUD_MASTER_MODE 0x00000002 - -#define FLD_AUD_SONY_MODE 0x00000001 - -#define FLD_AUD_CLK_SELECT_PLL_D 0x00001800 - -#define FLD_AUD_DST_ENABLE 0x00020000 - -#define FLD_AUD_SRC_ENABLE 0x00010000 - -//***************************************************************************** -#define AUD_INT_DMA_CTL 0x140500 // Audio Int DMA control - -#define FLD_AUD_SRC_E_RISC_EN 0x00008000 -#define FLD_AUD_SRC_C_RISC_EN 0x00004000 -#define FLD_AUD_SRC_B_RISC_EN 0x00002000 -#define FLD_AUD_SRC_A_RISC_EN 0x00001000 - -#define FLD_AUD_DST_D_RISC_EN 0x00000800 -#define FLD_AUD_DST_C_RISC_EN 0x00000400 -#define FLD_AUD_DST_B_RISC_EN 0x00000200 -#define FLD_AUD_DST_A_RISC_EN 0x00000100 - -#define FLD_AUD_SRC_E_FIFO_EN 0x00000080 -#define FLD_AUD_SRC_C_FIFO_EN 0x00000040 -#define FLD_AUD_SRC_B_FIFO_EN 0x00000020 -#define FLD_AUD_SRC_A_FIFO_EN 0x00000010 - -#define FLD_AUD_DST_D_FIFO_EN 0x00000008 -#define FLD_AUD_DST_C_FIFO_EN 0x00000004 -#define FLD_AUD_DST_B_FIFO_EN 0x00000002 -#define FLD_AUD_DST_A_FIFO_EN 0x00000001 - - -//***************************************************************************** -// -// Mobilygen Interface Registers -// -//***************************************************************************** -// Mobilygen Interface A -//***************************************************************************** -#define MB_IF_A_DMA 0x150000 // MBIF A DMA data port -#define MB_IF_A_GPCN 0x150008 // MBIF A GP counter -#define MB_IF_A_GPCN_CTRL 0x15000C -#define MB_IF_A_DMA_CTRL 0x150010 -#define MB_IF_A_LENGTH 0x150014 -#define MB_IF_A_HDMA_XFER_SZ 0x150018 -#define MB_IF_A_HCMD 0x15001C -#define MB_IF_A_HCONFIG 0x150020 -#define MB_IF_A_DATA_STRUCT_0 0x150024 -#define MB_IF_A_DATA_STRUCT_1 0x150028 -#define MB_IF_A_DATA_STRUCT_2 0x15002C -#define MB_IF_A_DATA_STRUCT_3 0x150030 -#define MB_IF_A_DATA_STRUCT_4 0x150034 -#define MB_IF_A_DATA_STRUCT_5 0x150038 -#define MB_IF_A_DATA_STRUCT_6 0x15003C -#define MB_IF_A_DATA_STRUCT_7 0x150040 -#define MB_IF_A_DATA_STRUCT_8 0x150044 -#define MB_IF_A_DATA_STRUCT_9 0x150048 -#define MB_IF_A_DATA_STRUCT_A 0x15004C -#define MB_IF_A_DATA_STRUCT_B 0x150050 -#define MB_IF_A_DATA_STRUCT_C 0x150054 -#define MB_IF_A_DATA_STRUCT_D 0x150058 -#define MB_IF_A_DATA_STRUCT_E 0x15005C -#define MB_IF_A_DATA_STRUCT_F 0x150060 -//***************************************************************************** -// Mobilygen Interface B -//***************************************************************************** -#define MB_IF_B_DMA 0x160000 // MBIF A DMA data port -#define MB_IF_B_GPCN 0x160008 // MBIF A GP counter -#define MB_IF_B_GPCN_CTRL 0x16000C -#define MB_IF_B_DMA_CTRL 0x160010 -#define MB_IF_B_LENGTH 0x160014 -#define MB_IF_B_HDMA_XFER_SZ 0x160018 -#define MB_IF_B_HCMD 0x16001C -#define MB_IF_B_HCONFIG 0x160020 -#define MB_IF_B_DATA_STRUCT_0 0x160024 -#define MB_IF_B_DATA_STRUCT_1 0x160028 -#define MB_IF_B_DATA_STRUCT_2 0x16002C -#define MB_IF_B_DATA_STRUCT_3 0x160030 -#define MB_IF_B_DATA_STRUCT_4 0x160034 -#define MB_IF_B_DATA_STRUCT_5 0x160038 -#define MB_IF_B_DATA_STRUCT_6 0x16003C -#define MB_IF_B_DATA_STRUCT_7 0x160040 -#define MB_IF_B_DATA_STRUCT_8 0x160044 -#define MB_IF_B_DATA_STRUCT_9 0x160048 -#define MB_IF_B_DATA_STRUCT_A 0x16004C -#define MB_IF_B_DATA_STRUCT_B 0x160050 -#define MB_IF_B_DATA_STRUCT_C 0x160054 -#define MB_IF_B_DATA_STRUCT_D 0x160058 -#define MB_IF_B_DATA_STRUCT_E 0x16005C -#define MB_IF_B_DATA_STRUCT_F 0x160060 - -// MB_DMA_CTRL -#define FLD_MB_IF_RISC_EN 0x00000010 -#define FLD_MB_IF_FIFO_EN 0x00000001 - -// MB_LENGTH -#define FLD_MB_IF_LN_LNGTH 0x00000FFF - -// MB_HCMD register -#define FLD_MB_HCMD_H_GO 0x80000000 -#define FLD_MB_HCMD_H_BUSY 0x40000000 -#define FLD_MB_HCMD_H_DMA_HOLD 0x10000000 -#define FLD_MB_HCMD_H_DMA_BUSY 0x08000000 -#define FLD_MB_HCMD_H_DMA_TYPE 0x04000000 -#define FLD_MB_HCMD_H_DMA_XACT 0x02000000 -#define FLD_MB_HCMD_H_RW_N 0x01000000 -#define FLD_MB_HCMD_H_ADDR 0x00FF0000 -#define FLD_MB_HCMD_H_DATA 0x0000FFFF - - -//***************************************************************************** -// I2C #1 -//***************************************************************************** -#define I2C1_ADDR 0x180000 // I2C #1 address -#define FLD_I2C_DADDR 0xfe000000 // RW [31:25] I2C Device Address - // RO [24] reserved -//***************************************************************************** -#define FLD_I2C_SADDR 0x00FFFFFF // RW [23:0] I2C Sub-address - -//***************************************************************************** -#define I2C1_WDATA 0x180004 // I2C #1 write data -#define FLD_I2C_WDATA 0xFFFFFFFF // RW [31:0] - -//***************************************************************************** -#define I2C1_CTRL 0x180008 // I2C #1 control -#define FLD_I2C_PERIOD 0xFF000000 // RW [31:24] -#define FLD_I2C_SCL_IN 0x00200000 // RW [21] -#define FLD_I2C_SDA_IN 0x00100000 // RW [20] - // RO [19:18] reserved -#define FLD_I2C_SCL_OUT 0x00020000 // RW [17] -#define FLD_I2C_SDA_OUT 0x00010000 // RW [16] - // RO [15] reserved -#define FLD_I2C_DATA_LEN 0x00007000 // RW [14:12] -#define FLD_I2C_SADDR_INC 0x00000800 // RW [11] - // RO [10:9] reserved -#define FLD_I2C_SADDR_LEN 0x00000300 // RW [9:8] - // RO [7:6] reserved -#define FLD_I2C_SOFT 0x00000020 // RW [5] -#define FLD_I2C_NOSTOP 0x00000010 // RW [4] -#define FLD_I2C_EXTEND 0x00000008 // RW [3] -#define FLD_I2C_SYNC 0x00000004 // RW [2] -#define FLD_I2C_READ_SA 0x00000002 // RW [1] -#define FLD_I2C_READ_WRN 0x00000001 // RW [0] - -//***************************************************************************** -#define I2C1_RDATA 0x18000C // I2C #1 read data -#define FLD_I2C_RDATA 0xFFFFFFFF // RO [31:0] - -//***************************************************************************** -#define I2C1_STAT 0x180010 // I2C #1 status -#define FLD_I2C_XFER_IN_PROG 0x00000002 // RO [1] -#define FLD_I2C_RACK 0x00000001 // RO [0] - -//***************************************************************************** -// I2C #2 -//***************************************************************************** -#define I2C2_ADDR 0x190000 // I2C #2 address - -//***************************************************************************** -#define I2C2_WDATA 0x190004 // I2C #2 write data - -//***************************************************************************** -#define I2C2_CTRL 0x190008 // I2C #2 control - -//***************************************************************************** -#define I2C2_RDATA 0x19000C // I2C #2 read data - -//***************************************************************************** -#define I2C2_STAT 0x190010 // I2C #2 status - -//***************************************************************************** -// I2C #3 -//***************************************************************************** -#define I2C3_ADDR 0x1A0000 // I2C #3 address - -//***************************************************************************** -#define I2C3_WDATA 0x1A0004 // I2C #3 write data - -//***************************************************************************** -#define I2C3_CTRL 0x1A0008 // I2C #3 control - -//***************************************************************************** -#define I2C3_RDATA 0x1A000C // I2C #3 read data - -//***************************************************************************** -#define I2C3_STAT 0x1A0010 // I2C #3 status - -//***************************************************************************** -// UART -//***************************************************************************** -#define UART_CTL 0x1B0000 // UART Control Register -#define FLD_LOOP_BACK_EN (1 << 7) // RW field - default 0 -#define FLD_RX_TRG_SZ (3 << 2) // RW field - default 0 -#define FLD_RX_EN (1 << 1) // RW field - default 0 -#define FLD_TX_EN (1 << 0) // RW field - default 0 - -//***************************************************************************** -#define UART_BRD 0x1B0004 // UART Baud Rate Divisor -#define FLD_BRD 0x0000FFFF // RW field - default 0x197 - -//***************************************************************************** -#define UART_DBUF 0x1B0008 // UART Tx/Rx Data BuFFer -#define FLD_DB 0xFFFFFFFF // RW field - default 0 - -//***************************************************************************** -#define UART_ISR 0x1B000C // UART Interrupt Status -#define FLD_RXD_TIMEOUT_EN (1 << 7) // RW field - default 0 -#define FLD_FRM_ERR_EN (1 << 6) // RW field - default 0 -#define FLD_RXD_RDY_EN (1 << 5) // RW field - default 0 -#define FLD_TXD_EMPTY_EN (1 << 4) // RW field - default 0 -#define FLD_RXD_OVERFLOW (1 << 3) // RW field - default 0 -#define FLD_FRM_ERR (1 << 2) // RW field - default 0 -#define FLD_RXD_RDY (1 << 1) // RW field - default 0 -#define FLD_TXD_EMPTY (1 << 0) // RW field - default 0 - -//***************************************************************************** -#define UART_CNT 0x1B0010 // UART Tx/Rx FIFO Byte Count -#define FLD_TXD_CNT (0x1F << 8) // RW field - default 0 -#define FLD_RXD_CNT (0x1F << 0) // RW field - default 0 - -//***************************************************************************** +#define VID_A_INT_MSK 0x040020 // Video A interrupt mask +#define VID_A_INT_STAT 0x040024 // Video A interrupt status +#define VID_A_INT_MSTAT 0x040028 // Video A interrupt masked status +#define VID_A_INT_SSTAT 0x04002C // Video A interrupt set status + +//***************************************************************************** +#define VID_B_INT_MSK 0x040030 // Video B interrupt mask +#define VID_B_INT_STAT 0x040034 // Video B interrupt status +#define VID_B_INT_MSTAT 0x040038 // Video B interrupt masked status +#define VID_B_INT_SSTAT 0x04003C // Video B interrupt set status + +//***************************************************************************** +#define VID_C_INT_MSK 0x040040 // Video C interrupt mask +#define VID_C_INT_STAT 0x040044 // Video C interrupt status +#define VID_C_INT_MSTAT 0x040048 // Video C interrupt masked status +#define VID_C_INT_SSTAT 0x04004C // Video C interrupt set status + +//***************************************************************************** +#define VID_D_INT_MSK 0x040050 // Video D interrupt mask +#define VID_D_INT_STAT 0x040054 // Video D interrupt status +#define VID_D_INT_MSTAT 0x040058 // Video D interrupt masked status +#define VID_D_INT_SSTAT 0x04005C // Video D interrupt set status + +//***************************************************************************** +#define VID_E_INT_MSK 0x040060 // Video E interrupt mask +#define VID_E_INT_STAT 0x040064 // Video E interrupt status +#define VID_E_INT_MSTAT 0x040068 // Video E interrupt masked status +#define VID_E_INT_SSTAT 0x04006C // Video E interrupt set status + +//***************************************************************************** +#define VID_F_INT_MSK 0x040070 // Video F interrupt mask +#define VID_F_INT_STAT 0x040074 // Video F interrupt status +#define VID_F_INT_MSTAT 0x040078 // Video F interrupt masked status +#define VID_F_INT_SSTAT 0x04007C // Video F interrupt set status + +//***************************************************************************** +#define VID_G_INT_MSK 0x040080 // Video G interrupt mask +#define VID_G_INT_STAT 0x040084 // Video G interrupt status +#define VID_G_INT_MSTAT 0x040088 // Video G interrupt masked status +#define VID_G_INT_SSTAT 0x04008C // Video G interrupt set status + +//***************************************************************************** +#define VID_H_INT_MSK 0x040090 // Video H interrupt mask +#define VID_H_INT_STAT 0x040094 // Video H interrupt status +#define VID_H_INT_MSTAT 0x040098 // Video H interrupt masked status +#define VID_H_INT_SSTAT 0x04009C // Video H interrupt set status + +//***************************************************************************** +#define VID_I_INT_MSK 0x0400A0 // Video I interrupt mask +#define VID_I_INT_STAT 0x0400A4 // Video I interrupt status +#define VID_I_INT_MSTAT 0x0400A8 // Video I interrupt masked status +#define VID_I_INT_SSTAT 0x0400AC // Video I interrupt set status + +//***************************************************************************** +#define VID_J_INT_MSK 0x0400B0 // Video J interrupt mask +#define VID_J_INT_STAT 0x0400B4 // Video J interrupt status +#define VID_J_INT_MSTAT 0x0400B8 // Video J interrupt masked status +#define VID_J_INT_SSTAT 0x0400BC // Video J interrupt set status + +#define FLD_VID_SRC_OPC_ERR 0x00020000 +#define FLD_VID_DST_OPC_ERR 0x00010000 +#define FLD_VID_SRC_SYNC 0x00002000 +#define FLD_VID_DST_SYNC 0x00001000 +#define FLD_VID_SRC_UF 0x00000200 +#define FLD_VID_DST_OF 0x00000100 +#define FLD_VID_SRC_RISC2 0x00000020 +#define FLD_VID_DST_RISC2 0x00000010 +#define FLD_VID_SRC_RISC1 0x00000002 +#define FLD_VID_DST_RISC1 0x00000001 +#define FLD_VID_SRC_ERRORS FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF +#define FLD_VID_DST_ERRORS FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF + +//***************************************************************************** +#define AUD_A_INT_MSK 0x0400C0 // Audio Int interrupt mask +#define AUD_A_INT_STAT 0x0400C4 // Audio Int interrupt status +#define AUD_A_INT_MSTAT 0x0400C8 // Audio Int interrupt masked status +#define AUD_A_INT_SSTAT 0x0400CC // Audio Int interrupt set status + +//***************************************************************************** +#define AUD_B_INT_MSK 0x0400D0 // Audio Int interrupt mask +#define AUD_B_INT_STAT 0x0400D4 // Audio Int interrupt status +#define AUD_B_INT_MSTAT 0x0400D8 // Audio Int interrupt masked status +#define AUD_B_INT_SSTAT 0x0400DC // Audio Int interrupt set status + +//***************************************************************************** +#define AUD_C_INT_MSK 0x0400E0 // Audio Int interrupt mask +#define AUD_C_INT_STAT 0x0400E4 // Audio Int interrupt status +#define AUD_C_INT_MSTAT 0x0400E8 // Audio Int interrupt masked status +#define AUD_C_INT_SSTAT 0x0400EC // Audio Int interrupt set status + +//***************************************************************************** +#define AUD_D_INT_MSK 0x0400F0 // Audio Int interrupt mask +#define AUD_D_INT_STAT 0x0400F4 // Audio Int interrupt status +#define AUD_D_INT_MSTAT 0x0400F8 // Audio Int interrupt masked status +#define AUD_D_INT_SSTAT 0x0400FC // Audio Int interrupt set status + +//***************************************************************************** +#define AUD_E_INT_MSK 0x040100 // Audio Int interrupt mask +#define AUD_E_INT_STAT 0x040104 // Audio Int interrupt status +#define AUD_E_INT_MSTAT 0x040108 // Audio Int interrupt masked status +#define AUD_E_INT_SSTAT 0x04010C // Audio Int interrupt set status + +#define FLD_AUD_SRC_OPC_ERR 0x00020000 +#define FLD_AUD_DST_OPC_ERR 0x00010000 +#define FLD_AUD_SRC_SYNC 0x00002000 +#define FLD_AUD_DST_SYNC 0x00001000 +#define FLD_AUD_SRC_OF 0x00000200 +#define FLD_AUD_DST_OF 0x00000100 +#define FLD_AUD_SRC_RISCI2 0x00000020 +#define FLD_AUD_DST_RISCI2 0x00000010 +#define FLD_AUD_SRC_RISCI1 0x00000002 +#define FLD_AUD_DST_RISCI1 0x00000001 + +//***************************************************************************** +#define MBIF_A_INT_MSK 0x040110 // MBIF Int interrupt mask +#define MBIF_A_INT_STAT 0x040114 // MBIF Int interrupt status +#define MBIF_A_INT_MSTAT 0x040118 // MBIF Int interrupt masked status +#define MBIF_A_INT_SSTAT 0x04011C // MBIF Int interrupt set status + +//***************************************************************************** +#define MBIF_B_INT_MSK 0x040120 // MBIF Int interrupt mask +#define MBIF_B_INT_STAT 0x040124 // MBIF Int interrupt status +#define MBIF_B_INT_MSTAT 0x040128 // MBIF Int interrupt masked status +#define MBIF_B_INT_SSTAT 0x04012C // MBIF Int interrupt set status + +#define FLD_MBIF_DST_OPC_ERR 0x00010000 +#define FLD_MBIF_DST_SYNC 0x00001000 +#define FLD_MBIF_DST_OF 0x00000100 +#define FLD_MBIF_DST_RISCI2 0x00000010 +#define FLD_MBIF_DST_RISCI1 0x00000001 + +//***************************************************************************** +#define AUD_EXT_INT_MSK 0x040060 // Audio Ext interrupt mask +#define AUD_EXT_INT_STAT 0x040064 // Audio Ext interrupt status +#define AUD_EXT_INT_MSTAT 0x040068 // Audio Ext interrupt masked status +#define AUD_EXT_INT_SSTAT 0x04006C // Audio Ext interrupt set status +#define FLD_AUD_EXT_OPC_ERR 0x00010000 +#define FLD_AUD_EXT_SYNC 0x00001000 +#define FLD_AUD_EXT_OF 0x00000100 +#define FLD_AUD_EXT_RISCI2 0x00000010 +#define FLD_AUD_EXT_RISCI1 0x00000001 + +//***************************************************************************** +#define GPIO_LO 0x110010 // Lower of GPIO pins [31:0] +#define GPIO_HI 0x110014 // Upper WORD of GPIO pins [47:31] + +#define GPIO_LO_OE 0x110018 // Lower of GPIO output enable [31:0] +#define GPIO_HI_OE 0x11001C // Upper word of GPIO output enable [47:32] + +#define GPIO_LO_INT_MSK 0x11003C // GPIO interrupt mask +#define GPIO_LO_INT_STAT 0x110044 // GPIO interrupt status +#define GPIO_LO_INT_MSTAT 0x11004C // GPIO interrupt masked status +#define GPIO_LO_ISM_SNS 0x110054 // GPIO interrupt sensitivity +#define GPIO_LO_ISM_POL 0x11005C // GPIO interrupt polarity + +#define GPIO_HI_INT_MSK 0x110040 // GPIO interrupt mask +#define GPIO_HI_INT_STAT 0x110048 // GPIO interrupt status +#define GPIO_HI_INT_MSTAT 0x110050 // GPIO interrupt masked status +#define GPIO_HI_ISM_SNS 0x110058 // GPIO interrupt sensitivity +#define GPIO_HI_ISM_POL 0x110060 // GPIO interrupt polarity + +#define FLD_GPIO43_INT (1 << 11) +#define FLD_GPIO42_INT (1 << 10) +#define FLD_GPIO41_INT (1 << 9) +#define FLD_GPIO40_INT (1 << 8) + +#define FLD_GPIO9_INT (1 << 9) +#define FLD_GPIO8_INT (1 << 8) +#define FLD_GPIO7_INT (1 << 7) +#define FLD_GPIO6_INT (1 << 6) +#define FLD_GPIO5_INT (1 << 5) +#define FLD_GPIO4_INT (1 << 4) +#define FLD_GPIO3_INT (1 << 3) +#define FLD_GPIO2_INT (1 << 2) +#define FLD_GPIO1_INT (1 << 1) +#define FLD_GPIO0_INT (1 << 0) + +//***************************************************************************** +#define TC_REQ 0x040090 // Rider PCI Express traFFic class request + +//***************************************************************************** +#define TC_REQ_SET 0x040094 // Rider PCI Express traFFic class request set + +//***************************************************************************** +// Rider +//***************************************************************************** + +// PCI Compatible Header +//***************************************************************************** +#define RDR_CFG0 0x050000 +#define RDR_VENDOR_DEVICE_ID_CFG 0x050000 + +//***************************************************************************** +#define RDR_CFG1 0x050004 + +//***************************************************************************** +#define RDR_CFG2 0x050008 + +//***************************************************************************** +#define RDR_CFG3 0x05000C + +//***************************************************************************** +#define RDR_CFG4 0x050010 + +//***************************************************************************** +#define RDR_CFG5 0x050014 + +//***************************************************************************** +#define RDR_CFG6 0x050018 + +//***************************************************************************** +#define RDR_CFG7 0x05001C + +//***************************************************************************** +#define RDR_CFG8 0x050020 + +//***************************************************************************** +#define RDR_CFG9 0x050024 + +//***************************************************************************** +#define RDR_CFGA 0x050028 + +//***************************************************************************** +#define RDR_CFGB 0x05002C +#define RDR_SUSSYSTEM_ID_CFG 0x05002C + +//***************************************************************************** +#define RDR_CFGC 0x050030 + +//***************************************************************************** +#define RDR_CFGD 0x050034 + +//***************************************************************************** +#define RDR_CFGE 0x050038 + +//***************************************************************************** +#define RDR_CFGF 0x05003C + +//***************************************************************************** +// PCI-Express Capabilities +//***************************************************************************** +#define RDR_PECAP 0x050040 + +//***************************************************************************** +#define RDR_PEDEVCAP 0x050044 + +//***************************************************************************** +#define RDR_PEDEVSC 0x050048 + +//***************************************************************************** +#define RDR_PELINKCAP 0x05004C + +//***************************************************************************** +#define RDR_PELINKSC 0x050050 + +//***************************************************************************** +#define RDR_PMICAP 0x050080 + +//***************************************************************************** +#define RDR_PMCSR 0x050084 + +//***************************************************************************** +#define RDR_VPDCAP 0x050090 + +//***************************************************************************** +#define RDR_VPDDATA 0x050094 + +//***************************************************************************** +#define RDR_MSICAP 0x0500A0 + +//***************************************************************************** +#define RDR_MSIARL 0x0500A4 + +//***************************************************************************** +#define RDR_MSIARU 0x0500A8 + +//***************************************************************************** +#define RDR_MSIDATA 0x0500AC + +//***************************************************************************** +// PCI Express Extended Capabilities +//***************************************************************************** +#define RDR_AERXCAP 0x050100 + +//***************************************************************************** +#define RDR_AERUESTA 0x050104 + +//***************************************************************************** +#define RDR_AERUEMSK 0x050108 + +//***************************************************************************** +#define RDR_AERUESEV 0x05010C + +//***************************************************************************** +#define RDR_AERCESTA 0x050110 + +//***************************************************************************** +#define RDR_AERCEMSK 0x050114 + +//***************************************************************************** +#define RDR_AERCC 0x050118 + +//***************************************************************************** +#define RDR_AERHL0 0x05011C + +//***************************************************************************** +#define RDR_AERHL1 0x050120 + +//***************************************************************************** +#define RDR_AERHL2 0x050124 + +//***************************************************************************** +#define RDR_AERHL3 0x050128 + +//***************************************************************************** +#define RDR_VCXCAP 0x050200 + +//***************************************************************************** +#define RDR_VCCAP1 0x050204 + +//***************************************************************************** +#define RDR_VCCAP2 0x050208 + +//***************************************************************************** +#define RDR_VCSC 0x05020C + +//***************************************************************************** +#define RDR_VCR0_CAP 0x050210 + +//***************************************************************************** +#define RDR_VCR0_CTRL 0x050214 + +//***************************************************************************** +#define RDR_VCR0_STAT 0x050218 + +//***************************************************************************** +#define RDR_VCR1_CAP 0x05021C + +//***************************************************************************** +#define RDR_VCR1_CTRL 0x050220 + +//***************************************************************************** +#define RDR_VCR1_STAT 0x050224 + +//***************************************************************************** +#define RDR_VCR2_CAP 0x050228 + +//***************************************************************************** +#define RDR_VCR2_CTRL 0x05022C + +//***************************************************************************** +#define RDR_VCR2_STAT 0x050230 + +//***************************************************************************** +#define RDR_VCR3_CAP 0x050234 + +//***************************************************************************** +#define RDR_VCR3_CTRL 0x050238 + +//***************************************************************************** +#define RDR_VCR3_STAT 0x05023C + +//***************************************************************************** +#define RDR_VCARB0 0x050240 + +//***************************************************************************** +#define RDR_VCARB1 0x050244 + +//***************************************************************************** +#define RDR_VCARB2 0x050248 + +//***************************************************************************** +#define RDR_VCARB3 0x05024C + +//***************************************************************************** +#define RDR_VCARB4 0x050250 + +//***************************************************************************** +#define RDR_VCARB5 0x050254 + +//***************************************************************************** +#define RDR_VCARB6 0x050258 + +//***************************************************************************** +#define RDR_VCARB7 0x05025C + +//***************************************************************************** +#define RDR_RDRSTAT0 0x050300 + +//***************************************************************************** +#define RDR_RDRSTAT1 0x050304 + +//***************************************************************************** +#define RDR_RDRCTL0 0x050308 + +//***************************************************************************** +#define RDR_RDRCTL1 0x05030C + +//***************************************************************************** +// Transaction Layer Registers +//***************************************************************************** +#define RDR_TLSTAT0 0x050310 + +//***************************************************************************** +#define RDR_TLSTAT1 0x050314 + +//***************************************************************************** +#define RDR_TLCTL0 0x050318 +#define FLD_CFG_UR_CPL_MODE 0x00000040 +#define FLD_CFG_CORR_ERR_QUITE 0x00000020 +#define FLD_CFG_RCB_CK_EN 0x00000010 +#define FLD_CFG_BNDRY_CK_EN 0x00000008 +#define FLD_CFG_BYTE_EN_CK_EN 0x00000004 +#define FLD_CFG_RELAX_ORDER_MSK 0x00000002 +#define FLD_CFG_TAG_ORDER_EN 0x00000001 + +//***************************************************************************** +#define RDR_TLCTL1 0x05031C + +//***************************************************************************** +#define RDR_REQRCAL 0x050320 + +//***************************************************************************** +#define RDR_REQRCAU 0x050324 + +//***************************************************************************** +#define RDR_REQEPA 0x050328 + +//***************************************************************************** +#define RDR_REQCTRL 0x05032C + +//***************************************************************************** +#define RDR_REQSTAT 0x050330 + +//***************************************************************************** +#define RDR_TL_TEST 0x050334 + +//***************************************************************************** +#define RDR_VCR01_CTL 0x050348 + +//***************************************************************************** +#define RDR_VCR23_CTL 0x05034C + +//***************************************************************************** +#define RDR_RX_VCR0_FC 0x050350 + +//***************************************************************************** +#define RDR_RX_VCR1_FC 0x050354 + +//***************************************************************************** +#define RDR_RX_VCR2_FC 0x050358 + +//***************************************************************************** +#define RDR_RX_VCR3_FC 0x05035C + +//***************************************************************************** +// Data Link Layer Registers +//***************************************************************************** +#define RDR_DLLSTAT 0x050360 + +//***************************************************************************** +#define RDR_DLLCTRL 0x050364 + +//***************************************************************************** +#define RDR_REPLAYTO 0x050368 + +//***************************************************************************** +#define RDR_ACKLATTO 0x05036C + +//***************************************************************************** +// MAC Layer Registers +//***************************************************************************** +#define RDR_MACSTAT0 0x050380 + +//***************************************************************************** +#define RDR_MACSTAT1 0x050384 + +//***************************************************************************** +#define RDR_MACCTRL0 0x050388 + +//***************************************************************************** +#define RDR_MACCTRL1 0x05038C + +//***************************************************************************** +#define RDR_MACCTRL2 0x050390 + +//***************************************************************************** +#define RDR_MAC_LB_DATA 0x050394 + +//***************************************************************************** +#define RDR_L0S_EXIT_LAT 0x050398 + +//***************************************************************************** +// DMAC +//***************************************************************************** +#define DMA1_PTR1 0x100000 // DMA Current Ptr : Ch#1 + +//***************************************************************************** +#define DMA2_PTR1 0x100004 // DMA Current Ptr : Ch#2 + +//***************************************************************************** +#define DMA3_PTR1 0x100008 // DMA Current Ptr : Ch#3 + +//***************************************************************************** +#define DMA4_PTR1 0x10000C // DMA Current Ptr : Ch#4 + +//***************************************************************************** +#define DMA5_PTR1 0x100010 // DMA Current Ptr : Ch#5 + +//***************************************************************************** +#define DMA6_PTR1 0x100014 // DMA Current Ptr : Ch#6 + +//***************************************************************************** +#define DMA7_PTR1 0x100018 // DMA Current Ptr : Ch#7 + +//***************************************************************************** +#define DMA8_PTR1 0x10001C // DMA Current Ptr : Ch#8 + +//***************************************************************************** +#define DMA9_PTR1 0x100020 // DMA Current Ptr : Ch#9 + +//***************************************************************************** +#define DMA10_PTR1 0x100024 // DMA Current Ptr : Ch#10 + +//***************************************************************************** +#define DMA11_PTR1 0x100028 // DMA Current Ptr : Ch#11 + +//***************************************************************************** +#define DMA12_PTR1 0x10002C // DMA Current Ptr : Ch#12 + +//***************************************************************************** +#define DMA13_PTR1 0x100030 // DMA Current Ptr : Ch#13 + +//***************************************************************************** +#define DMA14_PTR1 0x100034 // DMA Current Ptr : Ch#14 + +//***************************************************************************** +#define DMA15_PTR1 0x100038 // DMA Current Ptr : Ch#15 + +//***************************************************************************** +#define DMA16_PTR1 0x10003C // DMA Current Ptr : Ch#16 + +//***************************************************************************** +#define DMA17_PTR1 0x100040 // DMA Current Ptr : Ch#17 + +//***************************************************************************** +#define DMA18_PTR1 0x100044 // DMA Current Ptr : Ch#18 + +//***************************************************************************** +#define DMA19_PTR1 0x100048 // DMA Current Ptr : Ch#19 + +//***************************************************************************** +#define DMA20_PTR1 0x10004C // DMA Current Ptr : Ch#20 + +//***************************************************************************** +#define DMA21_PTR1 0x100050 // DMA Current Ptr : Ch#21 + +//***************************************************************************** +#define DMA22_PTR1 0x100054 // DMA Current Ptr : Ch#22 + +//***************************************************************************** +#define DMA23_PTR1 0x100058 // DMA Current Ptr : Ch#23 + +//***************************************************************************** +#define DMA24_PTR1 0x10005C // DMA Current Ptr : Ch#24 + +//***************************************************************************** +#define DMA25_PTR1 0x100060 // DMA Current Ptr : Ch#25 + +//***************************************************************************** +#define DMA26_PTR1 0x100064 // DMA Current Ptr : Ch#26 + +//***************************************************************************** +#define DMA1_PTR2 0x100080 // DMA Tab Ptr : Ch#1 + +//***************************************************************************** +#define DMA2_PTR2 0x100084 // DMA Tab Ptr : Ch#2 + +//***************************************************************************** +#define DMA3_PTR2 0x100088 // DMA Tab Ptr : Ch#3 + +//***************************************************************************** +#define DMA4_PTR2 0x10008C // DMA Tab Ptr : Ch#4 + +//***************************************************************************** +#define DMA5_PTR2 0x100090 // DMA Tab Ptr : Ch#5 + +//***************************************************************************** +#define DMA6_PTR2 0x100094 // DMA Tab Ptr : Ch#6 + +//***************************************************************************** +#define DMA7_PTR2 0x100098 // DMA Tab Ptr : Ch#7 + +//***************************************************************************** +#define DMA8_PTR2 0x10009C // DMA Tab Ptr : Ch#8 + +//***************************************************************************** +#define DMA9_PTR2 0x1000A0 // DMA Tab Ptr : Ch#9 + +//***************************************************************************** +#define DMA10_PTR2 0x1000A4 // DMA Tab Ptr : Ch#10 + +//***************************************************************************** +#define DMA11_PTR2 0x1000A8 // DMA Tab Ptr : Ch#11 + +//***************************************************************************** +#define DMA12_PTR2 0x1000AC // DMA Tab Ptr : Ch#12 + +//***************************************************************************** +#define DMA13_PTR2 0x1000B0 // DMA Tab Ptr : Ch#13 + +//***************************************************************************** +#define DMA14_PTR2 0x1000B4 // DMA Tab Ptr : Ch#14 + +//***************************************************************************** +#define DMA15_PTR2 0x1000B8 // DMA Tab Ptr : Ch#15 + +//***************************************************************************** +#define DMA16_PTR2 0x1000BC // DMA Tab Ptr : Ch#16 + +//***************************************************************************** +#define DMA17_PTR2 0x1000C0 // DMA Tab Ptr : Ch#17 + +//***************************************************************************** +#define DMA18_PTR2 0x1000C4 // DMA Tab Ptr : Ch#18 + +//***************************************************************************** +#define DMA19_PTR2 0x1000C8 // DMA Tab Ptr : Ch#19 + +//***************************************************************************** +#define DMA20_PTR2 0x1000CC // DMA Tab Ptr : Ch#20 + +//***************************************************************************** +#define DMA21_PTR2 0x1000D0 // DMA Tab Ptr : Ch#21 + +//***************************************************************************** +#define DMA22_PTR2 0x1000D4 // DMA Tab Ptr : Ch#22 + +//***************************************************************************** +#define DMA23_PTR2 0x1000D8 // DMA Tab Ptr : Ch#23 + +//***************************************************************************** +#define DMA24_PTR2 0x1000DC // DMA Tab Ptr : Ch#24 + +//***************************************************************************** +#define DMA25_PTR2 0x1000E0 // DMA Tab Ptr : Ch#25 + +//***************************************************************************** +#define DMA26_PTR2 0x1000E4 // DMA Tab Ptr : Ch#26 + +//***************************************************************************** +#define DMA1_CNT1 0x100100 // DMA BuFFer Size : Ch#1 + +//***************************************************************************** +#define DMA2_CNT1 0x100104 // DMA BuFFer Size : Ch#2 + +//***************************************************************************** +#define DMA3_CNT1 0x100108 // DMA BuFFer Size : Ch#3 + +//***************************************************************************** +#define DMA4_CNT1 0x10010C // DMA BuFFer Size : Ch#4 + +//***************************************************************************** +#define DMA5_CNT1 0x100110 // DMA BuFFer Size : Ch#5 + +//***************************************************************************** +#define DMA6_CNT1 0x100114 // DMA BuFFer Size : Ch#6 + +//***************************************************************************** +#define DMA7_CNT1 0x100118 // DMA BuFFer Size : Ch#7 + +//***************************************************************************** +#define DMA8_CNT1 0x10011C // DMA BuFFer Size : Ch#8 + +//***************************************************************************** +#define DMA9_CNT1 0x100120 // DMA BuFFer Size : Ch#9 + +//***************************************************************************** +#define DMA10_CNT1 0x100124 // DMA BuFFer Size : Ch#10 + +//***************************************************************************** +#define DMA11_CNT1 0x100128 // DMA BuFFer Size : Ch#11 + +//***************************************************************************** +#define DMA12_CNT1 0x10012C // DMA BuFFer Size : Ch#12 + +//***************************************************************************** +#define DMA13_CNT1 0x100130 // DMA BuFFer Size : Ch#13 + +//***************************************************************************** +#define DMA14_CNT1 0x100134 // DMA BuFFer Size : Ch#14 + +//***************************************************************************** +#define DMA15_CNT1 0x100138 // DMA BuFFer Size : Ch#15 + +//***************************************************************************** +#define DMA16_CNT1 0x10013C // DMA BuFFer Size : Ch#16 + +//***************************************************************************** +#define DMA17_CNT1 0x100140 // DMA BuFFer Size : Ch#17 + +//***************************************************************************** +#define DMA18_CNT1 0x100144 // DMA BuFFer Size : Ch#18 + +//***************************************************************************** +#define DMA19_CNT1 0x100148 // DMA BuFFer Size : Ch#19 + +//***************************************************************************** +#define DMA20_CNT1 0x10014C // DMA BuFFer Size : Ch#20 + +//***************************************************************************** +#define DMA21_CNT1 0x100150 // DMA BuFFer Size : Ch#21 + +//***************************************************************************** +#define DMA22_CNT1 0x100154 // DMA BuFFer Size : Ch#22 + +//***************************************************************************** +#define DMA23_CNT1 0x100158 // DMA BuFFer Size : Ch#23 + +//***************************************************************************** +#define DMA24_CNT1 0x10015C // DMA BuFFer Size : Ch#24 + +//***************************************************************************** +#define DMA25_CNT1 0x100160 // DMA BuFFer Size : Ch#25 + +//***************************************************************************** +#define DMA26_CNT1 0x100164 // DMA BuFFer Size : Ch#26 + +//***************************************************************************** +#define DMA1_CNT2 0x100180 // DMA Table Size : Ch#1 + +//***************************************************************************** +#define DMA2_CNT2 0x100184 // DMA Table Size : Ch#2 + +//***************************************************************************** +#define DMA3_CNT2 0x100188 // DMA Table Size : Ch#3 + +//***************************************************************************** +#define DMA4_CNT2 0x10018C // DMA Table Size : Ch#4 + +//***************************************************************************** +#define DMA5_CNT2 0x100190 // DMA Table Size : Ch#5 + +//***************************************************************************** +#define DMA6_CNT2 0x100194 // DMA Table Size : Ch#6 + +//***************************************************************************** +#define DMA7_CNT2 0x100198 // DMA Table Size : Ch#7 + +//***************************************************************************** +#define DMA8_CNT2 0x10019C // DMA Table Size : Ch#8 + +//***************************************************************************** +#define DMA9_CNT2 0x1001A0 // DMA Table Size : Ch#9 + +//***************************************************************************** +#define DMA10_CNT2 0x1001A4 // DMA Table Size : Ch#10 + +//***************************************************************************** +#define DMA11_CNT2 0x1001A8 // DMA Table Size : Ch#11 + +//***************************************************************************** +#define DMA12_CNT2 0x1001AC // DMA Table Size : Ch#12 + +//***************************************************************************** +#define DMA13_CNT2 0x1001B0 // DMA Table Size : Ch#13 + +//***************************************************************************** +#define DMA14_CNT2 0x1001B4 // DMA Table Size : Ch#14 + +//***************************************************************************** +#define DMA15_CNT2 0x1001B8 // DMA Table Size : Ch#15 + +//***************************************************************************** +#define DMA16_CNT2 0x1001BC // DMA Table Size : Ch#16 + +//***************************************************************************** +#define DMA17_CNT2 0x1001C0 // DMA Table Size : Ch#17 + +//***************************************************************************** +#define DMA18_CNT2 0x1001C4 // DMA Table Size : Ch#18 + +//***************************************************************************** +#define DMA19_CNT2 0x1001C8 // DMA Table Size : Ch#19 + +//***************************************************************************** +#define DMA20_CNT2 0x1001CC // DMA Table Size : Ch#20 + +//***************************************************************************** +#define DMA21_CNT2 0x1001D0 // DMA Table Size : Ch#21 + +//***************************************************************************** +#define DMA22_CNT2 0x1001D4 // DMA Table Size : Ch#22 + +//***************************************************************************** +#define DMA23_CNT2 0x1001D8 // DMA Table Size : Ch#23 + +//***************************************************************************** +#define DMA24_CNT2 0x1001DC // DMA Table Size : Ch#24 + +//***************************************************************************** +#define DMA25_CNT2 0x1001E0 // DMA Table Size : Ch#25 + +//***************************************************************************** +#define DMA26_CNT2 0x1001E4 // DMA Table Size : Ch#26 + +//***************************************************************************** + // ITG +//***************************************************************************** +#define TM_CNT_LDW 0x110000 // Timer : Counter low + +//***************************************************************************** +#define TM_CNT_UW 0x110004 // Timer : Counter high word + +//***************************************************************************** +#define TM_LMT_LDW 0x110008 // Timer : Limit low + +//***************************************************************************** +#define TM_LMT_UW 0x11000C // Timer : Limit high word + +//***************************************************************************** +#define GP0_IO 0x110010 // GPIO output enables data I/O +#define FLD_GP_OE 0x00FF0000 // GPIO: GP_OE output enable +#define FLD_GP_IN 0x0000FF00 // GPIO: GP_IN status +#define FLD_GP_OUT 0x000000FF // GPIO: GP_OUT control + +//***************************************************************************** +#define GPIO_ISM 0x110014 // GPIO interrupt sensitivity mode +#define FLD_GP_ISM_SNS 0x00000070 +#define FLD_GP_ISM_POL 0x00000007 + +//***************************************************************************** +#define SOFT_RESET 0x11001C // Output system reset reg +#define FLD_PECOS_SOFT_RESET 0x00000001 + +//***************************************************************************** +#define MC416_RWD 0x110020 // MC416 GPIO[18:3] pin +#define MC416_OEN 0x110024 // Output enable of GPIO[18:3] +#define MC416_CTL 0x110028 + +//***************************************************************************** +#define ALT_PIN_OUT_SEL 0x11002C // Alternate GPIO output select + +#define FLD_ALT_GPIO_OUT_SEL 0xF0000000 +// 0 Disabled <-- default +// 1 GPIO[0] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] +// 8 ATT_IF + +#define FLD_AUX_PLL_CLK_ALT_SEL 0x0F000000 +// 0 AUX_PLL_CLK<-- default +// 1 GPIO[2] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_IR_TX_ALT_SEL 0x00F00000 +// 0 IR_TX <-- default +// 1 GPIO[1] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_IR_RX_ALT_SEL 0x000F0000 +// 0 IR_RX <-- default +// 1 GPIO[0] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_GPIO10_ALT_SEL 0x0000F000 +// 0 GPIO[10] <-- default +// 1 GPIO[0] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_GPIO2_ALT_SEL 0x00000F00 +// 0 GPIO[2] <-- default +// 1 GPIO[1] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_GPIO1_ALT_SEL 0x000000F0 +// 0 GPIO[1] <-- default +// 1 GPIO[0] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define FLD_GPIO0_ALT_SEL 0x0000000F +// 0 GPIO[0] <-- default +// 1 GPIO[1] +// 2 GPIO[10] +// 3 VIP_656_DATA_VAL +// 4 VIP_656_DATA[0] +// 5 VIP_656_CLK +// 6 VIP_656_DATA_EXT[1] +// 7 VIP_656_DATA_EXT[0] + +#define ALT_PIN_IN_SEL 0x110030 // Alternate GPIO input select + +#define FLD_GPIO10_ALT_IN_SEL 0x0000F000 +// 0 GPIO[10] <-- default +// 1 IR_RX +// 2 IR_TX +// 3 AUX_PLL_CLK +// 4 IF_ATT_SEL +// 5 GPIO[0] +// 6 GPIO[1] +// 7 GPIO[2] + +#define FLD_GPIO2_ALT_IN_SEL 0x00000F00 +// 0 GPIO[2] <-- default +// 1 IR_RX +// 2 IR_TX +// 3 AUX_PLL_CLK +// 4 IF_ATT_SEL + +#define FLD_GPIO1_ALT_IN_SEL 0x000000F0 +// 0 GPIO[1] <-- default +// 1 IR_RX +// 2 IR_TX +// 3 AUX_PLL_CLK +// 4 IF_ATT_SEL + +#define FLD_GPIO0_ALT_IN_SEL 0x0000000F +// 0 GPIO[0] <-- default +// 1 IR_RX +// 2 IR_TX +// 3 AUX_PLL_CLK +// 4 IF_ATT_SEL + +//***************************************************************************** +#define TEST_BUS_CTL1 0x110040 // Test bus control register #1 + +//***************************************************************************** +#define TEST_BUS_CTL2 0x110044 // Test bus control register #2 + +//***************************************************************************** +#define CLK_DELAY 0x110048 // Clock delay +#define FLD_MOE_CLK_DIS 0x80000000 // Disable MoE clock + +//***************************************************************************** +#define PAD_CTRL 0x110068 // Pad drive strength control + +//***************************************************************************** +#define MBIST_CTRL 0x110050 // SRAM memory built-in self test control + +//***************************************************************************** +#define MBIST_STAT 0x110054 // SRAM memory built-in self test status + +//***************************************************************************** +// PLL registers +//***************************************************************************** +#define PLL_A_INT_FRAC 0x110088 +#define PLL_A_POST_STAT_BIST 0x11008C +#define PLL_B_INT_FRAC 0x110090 +#define PLL_B_POST_STAT_BIST 0x110094 +#define PLL_C_INT_FRAC 0x110098 +#define PLL_C_POST_STAT_BIST 0x11009C +#define PLL_D_INT_FRAC 0x1100A0 +#define PLL_D_POST_STAT_BIST 0x1100A4 + +#define CLK_RST 0x11002C +#define FLD_VID_I_CLK_NOE 0x00001000 +#define FLD_VID_J_CLK_NOE 0x00002000 +#define FLD_USE_ALT_PLL_REF 0x00004000 + +#define VID_CH_MODE_SEL 0x110078 +#define VID_CH_CLK_SEL 0x11007C + +//***************************************************************************** +#define VBI_A_DMA 0x130008 // VBI A DMA data port + +//***************************************************************************** +#define VID_A_VIP_CTL 0x130080 // Video A VIP format control +#define FLD_VIP_MODE 0x00000001 + +//***************************************************************************** +#define VID_A_PIXEL_FRMT 0x130084 // Video A pixel format +#define FLD_VID_A_GAMMA_DIS 0x00000008 +#define FLD_VID_A_FORMAT 0x00000007 +#define FLD_VID_A_GAMMA_FACTOR 0x00000010 + +//***************************************************************************** +#define VID_A_VBI_CTL 0x130088 // Video A VBI miscellaneous control +#define FLD_VID_A_VIP_EXT 0x00000003 + +//***************************************************************************** +#define VID_B_DMA 0x130100 // Video B DMA data port + +//***************************************************************************** +#define VBI_B_DMA 0x130108 // VBI B DMA data port + +//***************************************************************************** +#define VID_B_SRC_SEL 0x130144 // Video B source select +#define FLD_VID_B_SRC_SEL 0x00000000 + +//***************************************************************************** +#define VID_B_LNGTH 0x130150 // Video B line length +#define FLD_VID_B_LN_LNGTH 0x00000FFF + +//***************************************************************************** +#define VID_B_VIP_CTL 0x130180 // Video B VIP format control + +//***************************************************************************** +#define VID_B_PIXEL_FRMT 0x130184 // Video B pixel format +#define FLD_VID_B_GAMMA_DIS 0x00000008 +#define FLD_VID_B_FORMAT 0x00000007 +#define FLD_VID_B_GAMMA_FACTOR 0x00000010 + +//***************************************************************************** +#define VID_C_DMA 0x130200 // Video C DMA data port + +//***************************************************************************** +#define VID_C_LNGTH 0x130250 // Video C line length +#define FLD_VID_C_LN_LNGTH 0x00000FFF + +//***************************************************************************** +// Video Destination Channels +//***************************************************************************** + +#define VID_DST_A_GPCNT 0x130020 // Video A general purpose counter +#define VID_DST_B_GPCNT 0x130120 // Video B general purpose counter +#define VID_DST_C_GPCNT 0x130220 // Video C general purpose counter +#define VID_DST_D_GPCNT 0x130320 // Video D general purpose counter +#define VID_DST_E_GPCNT 0x130420 // Video E general purpose counter +#define VID_DST_F_GPCNT 0x130520 // Video F general purpose counter +#define VID_DST_G_GPCNT 0x130620 // Video G general purpose counter +#define VID_DST_H_GPCNT 0x130720 // Video H general purpose counter + +//***************************************************************************** + +#define VID_DST_A_GPCNT_CTL 0x130030 // Video A general purpose control +#define VID_DST_B_GPCNT_CTL 0x130130 // Video B general purpose control +#define VID_DST_C_GPCNT_CTL 0x130230 // Video C general purpose control +#define VID_DST_D_GPCNT_CTL 0x130330 // Video D general purpose control +#define VID_DST_E_GPCNT_CTL 0x130430 // Video E general purpose control +#define VID_DST_F_GPCNT_CTL 0x130530 // Video F general purpose control +#define VID_DST_G_GPCNT_CTL 0x130630 // Video G general purpose control +#define VID_DST_H_GPCNT_CTL 0x130730 // Video H general purpose control + +//***************************************************************************** + +#define VID_DST_A_DMA_CTL 0x130040 // Video A DMA control +#define VID_DST_B_DMA_CTL 0x130140 // Video B DMA control +#define VID_DST_C_DMA_CTL 0x130240 // Video C DMA control +#define VID_DST_D_DMA_CTL 0x130340 // Video D DMA control +#define VID_DST_E_DMA_CTL 0x130440 // Video E DMA control +#define VID_DST_F_DMA_CTL 0x130540 // Video F DMA control +#define VID_DST_G_DMA_CTL 0x130640 // Video G DMA control +#define VID_DST_H_DMA_CTL 0x130740 // Video H DMA control + +#define FLD_VID_RISC_EN 0x00000010 +#define FLD_VID_FIFO_EN 0x00000001 + +//***************************************************************************** + +#define VID_DST_A_VIP_CTL 0x130080 // Video A VIP control +#define VID_DST_B_VIP_CTL 0x130180 // Video B VIP control +#define VID_DST_C_VIP_CTL 0x130280 // Video C VIP control +#define VID_DST_D_VIP_CTL 0x130380 // Video D VIP control +#define VID_DST_E_VIP_CTL 0x130480 // Video E VIP control +#define VID_DST_F_VIP_CTL 0x130580 // Video F VIP control +#define VID_DST_G_VIP_CTL 0x130680 // Video G VIP control +#define VID_DST_H_VIP_CTL 0x130780 // Video H VIP control + +//***************************************************************************** + +#define VID_DST_A_PIX_FRMT 0x130084 // Video A Pixel format +#define VID_DST_B_PIX_FRMT 0x130184 // Video B Pixel format +#define VID_DST_C_PIX_FRMT 0x130284 // Video C Pixel format +#define VID_DST_D_PIX_FRMT 0x130384 // Video D Pixel format +#define VID_DST_E_PIX_FRMT 0x130484 // Video E Pixel format +#define VID_DST_F_PIX_FRMT 0x130584 // Video F Pixel format +#define VID_DST_G_PIX_FRMT 0x130684 // Video G Pixel format +#define VID_DST_H_PIX_FRMT 0x130784 // Video H Pixel format + +//***************************************************************************** +// Video Source Channels +//***************************************************************************** + +#define VID_SRC_A_GPCNT_CTL 0x130804 // Video A general purpose control +#define VID_SRC_B_GPCNT_CTL 0x130904 // Video B general purpose control +#define VID_SRC_C_GPCNT_CTL 0x130A04 // Video C general purpose control +#define VID_SRC_D_GPCNT_CTL 0x130B04 // Video D general purpose control +#define VID_SRC_E_GPCNT_CTL 0x130C04 // Video E general purpose control +#define VID_SRC_F_GPCNT_CTL 0x130D04 // Video F general purpose control +#define VID_SRC_I_GPCNT_CTL 0x130E04 // Video I general purpose control +#define VID_SRC_J_GPCNT_CTL 0x130F04 // Video J general purpose control + +//***************************************************************************** + +#define VID_SRC_A_GPCNT 0x130808 // Video A general purpose counter +#define VID_SRC_B_GPCNT 0x130908 // Video B general purpose counter +#define VID_SRC_C_GPCNT 0x130A08 // Video C general purpose counter +#define VID_SRC_D_GPCNT 0x130B08 // Video D general purpose counter +#define VID_SRC_E_GPCNT 0x130C08 // Video E general purpose counter +#define VID_SRC_F_GPCNT 0x130D08 // Video F general purpose counter +#define VID_SRC_I_GPCNT 0x130E08 // Video I general purpose counter +#define VID_SRC_J_GPCNT 0x130F08 // Video J general purpose counter + +//***************************************************************************** + +#define VID_SRC_A_DMA_CTL 0x13080C // Video A DMA control +#define VID_SRC_B_DMA_CTL 0x13090C // Video B DMA control +#define VID_SRC_C_DMA_CTL 0x130A0C // Video C DMA control +#define VID_SRC_D_DMA_CTL 0x130B0C // Video D DMA control +#define VID_SRC_E_DMA_CTL 0x130C0C // Video E DMA control +#define VID_SRC_F_DMA_CTL 0x130D0C // Video F DMA control +#define VID_SRC_I_DMA_CTL 0x130E0C // Video I DMA control +#define VID_SRC_J_DMA_CTL 0x130F0C // Video J DMA control + +#define FLD_APB_RISC_EN 0x00000010 +#define FLD_APB_FIFO_EN 0x00000001 + +//***************************************************************************** + +#define VID_SRC_A_FMT_CTL 0x130810 // Video A format control +#define VID_SRC_B_FMT_CTL 0x130910 // Video B format control +#define VID_SRC_C_FMT_CTL 0x130A10 // Video C format control +#define VID_SRC_D_FMT_CTL 0x130B10 // Video D format control +#define VID_SRC_E_FMT_CTL 0x130C10 // Video E format control +#define VID_SRC_F_FMT_CTL 0x130D10 // Video F format control +#define VID_SRC_I_FMT_CTL 0x130E10 // Video I format control +#define VID_SRC_J_FMT_CTL 0x130F10 // Video J format control + +//***************************************************************************** + +#define VID_SRC_A_ACTIVE_CTL1 0x130814 // Video A active control 1 +#define VID_SRC_B_ACTIVE_CTL1 0x130914 // Video B active control 1 +#define VID_SRC_C_ACTIVE_CTL1 0x130A14 // Video C active control 1 +#define VID_SRC_D_ACTIVE_CTL1 0x130B14 // Video D active control 1 +#define VID_SRC_E_ACTIVE_CTL1 0x130C14 // Video E active control 1 +#define VID_SRC_F_ACTIVE_CTL1 0x130D14 // Video F active control 1 +#define VID_SRC_I_ACTIVE_CTL1 0x130E14 // Video I active control 1 +#define VID_SRC_J_ACTIVE_CTL1 0x130F14 // Video J active control 1 + +//***************************************************************************** + +#define VID_SRC_A_ACTIVE_CTL2 0x130818 // Video A active control 2 +#define VID_SRC_B_ACTIVE_CTL2 0x130918 // Video B active control 2 +#define VID_SRC_C_ACTIVE_CTL2 0x130A18 // Video C active control 2 +#define VID_SRC_D_ACTIVE_CTL2 0x130B18 // Video D active control 2 +#define VID_SRC_E_ACTIVE_CTL2 0x130C18 // Video E active control 2 +#define VID_SRC_F_ACTIVE_CTL2 0x130D18 // Video F active control 2 +#define VID_SRC_I_ACTIVE_CTL2 0x130E18 // Video I active control 2 +#define VID_SRC_J_ACTIVE_CTL2 0x130F18 // Video J active control 2 + +//***************************************************************************** + +#define VID_SRC_A_CDT_SZ 0x13081C // Video A CDT size +#define VID_SRC_B_CDT_SZ 0x13091C // Video B CDT size +#define VID_SRC_C_CDT_SZ 0x130A1C // Video C CDT size +#define VID_SRC_D_CDT_SZ 0x130B1C // Video D CDT size +#define VID_SRC_E_CDT_SZ 0x130C1C // Video E CDT size +#define VID_SRC_F_CDT_SZ 0x130D1C // Video F CDT size +#define VID_SRC_I_CDT_SZ 0x130E1C // Video I CDT size +#define VID_SRC_J_CDT_SZ 0x130F1C // Video J CDT size + +//***************************************************************************** +// Audio I/F +//***************************************************************************** +#define AUD_DST_A_DMA 0x140000 // Audio Int A DMA data port +#define AUD_SRC_A_DMA 0x140008 // Audio Int A DMA data port + +#define AUD_A_GPCNT 0x140010 // Audio Int A gp counter +#define FLD_AUD_A_GP_CNT 0x0000FFFF + +#define AUD_A_GPCNT_CTL 0x140014 // Audio Int A gp control + +#define AUD_A_LNGTH 0x140018 // Audio Int A line length + +#define AUD_A_CFG 0x14001C // Audio Int A configuration + +//***************************************************************************** +#define AUD_DST_B_DMA 0x140100 // Audio Int B DMA data port +#define AUD_SRC_B_DMA 0x140108 // Audio Int B DMA data port + +#define AUD_B_GPCNT 0x140110 // Audio Int B gp counter +#define FLD_AUD_B_GP_CNT 0x0000FFFF + +#define AUD_B_GPCNT_CTL 0x140114 // Audio Int B gp control + +#define AUD_B_LNGTH 0x140118 // Audio Int B line length + +#define AUD_B_CFG 0x14011C // Audio Int B configuration + +//***************************************************************************** +#define AUD_DST_C_DMA 0x140200 // Audio Int C DMA data port +#define AUD_SRC_C_DMA 0x140208 // Audio Int C DMA data port + +#define AUD_C_GPCNT 0x140210 // Audio Int C gp counter +#define FLD_AUD_C_GP_CNT 0x0000FFFF + +#define AUD_C_GPCNT_CTL 0x140214 // Audio Int C gp control + +#define AUD_C_LNGTH 0x140218 // Audio Int C line length + +#define AUD_C_CFG 0x14021C // Audio Int C configuration + +//***************************************************************************** +#define AUD_DST_D_DMA 0x140300 // Audio Int D DMA data port +#define AUD_SRC_D_DMA 0x140308 // Audio Int D DMA data port + +#define AUD_D_GPCNT 0x140310 // Audio Int D gp counter +#define FLD_AUD_D_GP_CNT 0x0000FFFF + +#define AUD_D_GPCNT_CTL 0x140314 // Audio Int D gp control + +#define AUD_D_LNGTH 0x140318 // Audio Int D line length + +#define AUD_D_CFG 0x14031C // Audio Int D configuration + +//***************************************************************************** +#define AUD_SRC_E_DMA 0x140400 // Audio Int E DMA data port + +#define AUD_E_GPCNT 0x140410 // Audio Int E gp counter +#define FLD_AUD_E_GP_CNT 0x0000FFFF + +#define AUD_E_GPCNT_CTL 0x140414 // Audio Int E gp control + +#define AUD_E_CFG 0x14041C // Audio Int E configuration + +//***************************************************************************** + +#define FLD_AUD_DST_LN_LNGTH 0x00000FFF + +#define FLD_AUD_DST_PK_MODE 0x00004000 + +#define FLD_AUD_CLK_ENABLE 0x00000200 + +#define FLD_AUD_MASTER_MODE 0x00000002 + +#define FLD_AUD_SONY_MODE 0x00000001 + +#define FLD_AUD_CLK_SELECT_PLL_D 0x00001800 + +#define FLD_AUD_DST_ENABLE 0x00020000 + +#define FLD_AUD_SRC_ENABLE 0x00010000 + +//***************************************************************************** +#define AUD_INT_DMA_CTL 0x140500 // Audio Int DMA control + +#define FLD_AUD_SRC_E_RISC_EN 0x00008000 +#define FLD_AUD_SRC_C_RISC_EN 0x00004000 +#define FLD_AUD_SRC_B_RISC_EN 0x00002000 +#define FLD_AUD_SRC_A_RISC_EN 0x00001000 + +#define FLD_AUD_DST_D_RISC_EN 0x00000800 +#define FLD_AUD_DST_C_RISC_EN 0x00000400 +#define FLD_AUD_DST_B_RISC_EN 0x00000200 +#define FLD_AUD_DST_A_RISC_EN 0x00000100 + +#define FLD_AUD_SRC_E_FIFO_EN 0x00000080 +#define FLD_AUD_SRC_C_FIFO_EN 0x00000040 +#define FLD_AUD_SRC_B_FIFO_EN 0x00000020 +#define FLD_AUD_SRC_A_FIFO_EN 0x00000010 + +#define FLD_AUD_DST_D_FIFO_EN 0x00000008 +#define FLD_AUD_DST_C_FIFO_EN 0x00000004 +#define FLD_AUD_DST_B_FIFO_EN 0x00000002 +#define FLD_AUD_DST_A_FIFO_EN 0x00000001 + +//***************************************************************************** +// +// Mobilygen Interface Registers +// +//***************************************************************************** +// Mobilygen Interface A +//***************************************************************************** +#define MB_IF_A_DMA 0x150000 // MBIF A DMA data port +#define MB_IF_A_GPCN 0x150008 // MBIF A GP counter +#define MB_IF_A_GPCN_CTRL 0x15000C +#define MB_IF_A_DMA_CTRL 0x150010 +#define MB_IF_A_LENGTH 0x150014 +#define MB_IF_A_HDMA_XFER_SZ 0x150018 +#define MB_IF_A_HCMD 0x15001C +#define MB_IF_A_HCONFIG 0x150020 +#define MB_IF_A_DATA_STRUCT_0 0x150024 +#define MB_IF_A_DATA_STRUCT_1 0x150028 +#define MB_IF_A_DATA_STRUCT_2 0x15002C +#define MB_IF_A_DATA_STRUCT_3 0x150030 +#define MB_IF_A_DATA_STRUCT_4 0x150034 +#define MB_IF_A_DATA_STRUCT_5 0x150038 +#define MB_IF_A_DATA_STRUCT_6 0x15003C +#define MB_IF_A_DATA_STRUCT_7 0x150040 +#define MB_IF_A_DATA_STRUCT_8 0x150044 +#define MB_IF_A_DATA_STRUCT_9 0x150048 +#define MB_IF_A_DATA_STRUCT_A 0x15004C +#define MB_IF_A_DATA_STRUCT_B 0x150050 +#define MB_IF_A_DATA_STRUCT_C 0x150054 +#define MB_IF_A_DATA_STRUCT_D 0x150058 +#define MB_IF_A_DATA_STRUCT_E 0x15005C +#define MB_IF_A_DATA_STRUCT_F 0x150060 +//***************************************************************************** +// Mobilygen Interface B +//***************************************************************************** +#define MB_IF_B_DMA 0x160000 // MBIF A DMA data port +#define MB_IF_B_GPCN 0x160008 // MBIF A GP counter +#define MB_IF_B_GPCN_CTRL 0x16000C +#define MB_IF_B_DMA_CTRL 0x160010 +#define MB_IF_B_LENGTH 0x160014 +#define MB_IF_B_HDMA_XFER_SZ 0x160018 +#define MB_IF_B_HCMD 0x16001C +#define MB_IF_B_HCONFIG 0x160020 +#define MB_IF_B_DATA_STRUCT_0 0x160024 +#define MB_IF_B_DATA_STRUCT_1 0x160028 +#define MB_IF_B_DATA_STRUCT_2 0x16002C +#define MB_IF_B_DATA_STRUCT_3 0x160030 +#define MB_IF_B_DATA_STRUCT_4 0x160034 +#define MB_IF_B_DATA_STRUCT_5 0x160038 +#define MB_IF_B_DATA_STRUCT_6 0x16003C +#define MB_IF_B_DATA_STRUCT_7 0x160040 +#define MB_IF_B_DATA_STRUCT_8 0x160044 +#define MB_IF_B_DATA_STRUCT_9 0x160048 +#define MB_IF_B_DATA_STRUCT_A 0x16004C +#define MB_IF_B_DATA_STRUCT_B 0x160050 +#define MB_IF_B_DATA_STRUCT_C 0x160054 +#define MB_IF_B_DATA_STRUCT_D 0x160058 +#define MB_IF_B_DATA_STRUCT_E 0x16005C +#define MB_IF_B_DATA_STRUCT_F 0x160060 + +// MB_DMA_CTRL +#define FLD_MB_IF_RISC_EN 0x00000010 +#define FLD_MB_IF_FIFO_EN 0x00000001 + +// MB_LENGTH +#define FLD_MB_IF_LN_LNGTH 0x00000FFF + +// MB_HCMD register +#define FLD_MB_HCMD_H_GO 0x80000000 +#define FLD_MB_HCMD_H_BUSY 0x40000000 +#define FLD_MB_HCMD_H_DMA_HOLD 0x10000000 +#define FLD_MB_HCMD_H_DMA_BUSY 0x08000000 +#define FLD_MB_HCMD_H_DMA_TYPE 0x04000000 +#define FLD_MB_HCMD_H_DMA_XACT 0x02000000 +#define FLD_MB_HCMD_H_RW_N 0x01000000 +#define FLD_MB_HCMD_H_ADDR 0x00FF0000 +#define FLD_MB_HCMD_H_DATA 0x0000FFFF + +//***************************************************************************** +// I2C #1 +//***************************************************************************** +#define I2C1_ADDR 0x180000 // I2C #1 address +#define FLD_I2C_DADDR 0xfe000000 // RW [31:25] I2C Device Address + // RO [24] reserved +//***************************************************************************** +#define FLD_I2C_SADDR 0x00FFFFFF // RW [23:0] I2C Sub-address + +//***************************************************************************** +#define I2C1_WDATA 0x180004 // I2C #1 write data +#define FLD_I2C_WDATA 0xFFFFFFFF // RW [31:0] + +//***************************************************************************** +#define I2C1_CTRL 0x180008 // I2C #1 control +#define FLD_I2C_PERIOD 0xFF000000 // RW [31:24] +#define FLD_I2C_SCL_IN 0x00200000 // RW [21] +#define FLD_I2C_SDA_IN 0x00100000 // RW [20] + // RO [19:18] reserved +#define FLD_I2C_SCL_OUT 0x00020000 // RW [17] +#define FLD_I2C_SDA_OUT 0x00010000 // RW [16] + // RO [15] reserved +#define FLD_I2C_DATA_LEN 0x00007000 // RW [14:12] +#define FLD_I2C_SADDR_INC 0x00000800 // RW [11] + // RO [10:9] reserved +#define FLD_I2C_SADDR_LEN 0x00000300 // RW [9:8] + // RO [7:6] reserved +#define FLD_I2C_SOFT 0x00000020 // RW [5] +#define FLD_I2C_NOSTOP 0x00000010 // RW [4] +#define FLD_I2C_EXTEND 0x00000008 // RW [3] +#define FLD_I2C_SYNC 0x00000004 // RW [2] +#define FLD_I2C_READ_SA 0x00000002 // RW [1] +#define FLD_I2C_READ_WRN 0x00000001 // RW [0] + +//***************************************************************************** +#define I2C1_RDATA 0x18000C // I2C #1 read data +#define FLD_I2C_RDATA 0xFFFFFFFF // RO [31:0] + +//***************************************************************************** +#define I2C1_STAT 0x180010 // I2C #1 status +#define FLD_I2C_XFER_IN_PROG 0x00000002 // RO [1] +#define FLD_I2C_RACK 0x00000001 // RO [0] + +//***************************************************************************** +// I2C #2 +//***************************************************************************** +#define I2C2_ADDR 0x190000 // I2C #2 address + +//***************************************************************************** +#define I2C2_WDATA 0x190004 // I2C #2 write data + +//***************************************************************************** +#define I2C2_CTRL 0x190008 // I2C #2 control + +//***************************************************************************** +#define I2C2_RDATA 0x19000C // I2C #2 read data + +//***************************************************************************** +#define I2C2_STAT 0x190010 // I2C #2 status + +//***************************************************************************** +// I2C #3 +//***************************************************************************** +#define I2C3_ADDR 0x1A0000 // I2C #3 address + +//***************************************************************************** +#define I2C3_WDATA 0x1A0004 // I2C #3 write data + +//***************************************************************************** +#define I2C3_CTRL 0x1A0008 // I2C #3 control + +//***************************************************************************** +#define I2C3_RDATA 0x1A000C // I2C #3 read data + +//***************************************************************************** +#define I2C3_STAT 0x1A0010 // I2C #3 status + +//***************************************************************************** +// UART +//***************************************************************************** +#define UART_CTL 0x1B0000 // UART Control Register +#define FLD_LOOP_BACK_EN (1 << 7) // RW field - default 0 +#define FLD_RX_TRG_SZ (3 << 2) // RW field - default 0 +#define FLD_RX_EN (1 << 1) // RW field - default 0 +#define FLD_TX_EN (1 << 0) // RW field - default 0 + +//***************************************************************************** +#define UART_BRD 0x1B0004 // UART Baud Rate Divisor +#define FLD_BRD 0x0000FFFF // RW field - default 0x197 + +//***************************************************************************** +#define UART_DBUF 0x1B0008 // UART Tx/Rx Data BuFFer +#define FLD_DB 0xFFFFFFFF // RW field - default 0 + +//***************************************************************************** +#define UART_ISR 0x1B000C // UART Interrupt Status +#define FLD_RXD_TIMEOUT_EN (1 << 7) // RW field - default 0 +#define FLD_FRM_ERR_EN (1 << 6) // RW field - default 0 +#define FLD_RXD_RDY_EN (1 << 5) // RW field - default 0 +#define FLD_TXD_EMPTY_EN (1 << 4) // RW field - default 0 +#define FLD_RXD_OVERFLOW (1 << 3) // RW field - default 0 +#define FLD_FRM_ERR (1 << 2) // RW field - default 0 +#define FLD_RXD_RDY (1 << 1) // RW field - default 0 +#define FLD_TXD_EMPTY (1 << 0) // RW field - default 0 + +//***************************************************************************** +#define UART_CNT 0x1B0010 // UART Tx/Rx FIFO Byte Count +#define FLD_TXD_CNT (0x1F << 8) // RW field - default 0 +#define FLD_RXD_CNT (0x1F << 0) // RW field - default 0 + +//***************************************************************************** // Motion Detection #define MD_CH0_GRID_BLOCK_YCNT 0x170014 #define MD_CH1_GRID_BLOCK_YCNT 0x170094 @@ -1604,6 +1589,4 @@ #define PIXEL_ENGINE_VIP1 0 #define PIXEL_ENGINE_VIP2 1 -#endif //Athena_REGISTERS - - +#endif //Athena_REGISTERS diff --git a/linux/drivers/staging/cx25821/cx25821-sram.h b/linux/drivers/staging/cx25821/cx25821-sram.h index 813063582..bd677ee22 100644 --- a/linux/drivers/staging/cx25821/cx25821-sram.h +++ b/linux/drivers/staging/cx25821/cx25821-sram.h @@ -1,266 +1,261 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ATHENA_SRAM_H__ -#define __ATHENA_SRAM_H__ - -//#define RX_SRAM_START_SIZE = 0; // Start of reserved SRAM -#define VID_CMDS_SIZE 80 // Video CMDS size in bytes -#define AUDIO_CMDS_SIZE 80 // AUDIO CMDS size in bytes -#define MBIF_CMDS_SIZE 80 // MBIF CMDS size in bytes - -//#define RX_SRAM_POOL_START_SIZE = 0; // Start of useable RX SRAM for buffers -#define VID_IQ_SIZE 64 // VID instruction queue size in bytes -#define MBIF_IQ_SIZE 64 -#define AUDIO_IQ_SIZE 64 // AUD instruction queue size in bytes - -#define VID_CDT_SIZE 64 // VID cluster descriptor table size in bytes -#define MBIF_CDT_SIZE 64 // MBIF/HBI cluster descriptor table size in bytes -#define AUDIO_CDT_SIZE 48 // AUD cluster descriptor table size in bytes - -//#define RX_SRAM_POOL_FREE_SIZE = 16; // Start of available RX SRAM -//#define RX_SRAM_END_SIZE = 0; // End of RX SRAM - -//#define TX_SRAM_POOL_START_SIZE = 0; // Start of transmit pool SRAM -//#define MSI_DATA_SIZE = 64; // Reserved (MSI Data, RISC working stora - -#define VID_CLUSTER_SIZE 1440 // VID cluster data line -#define AUDIO_CLUSTER_SIZE 128 // AUDIO cluster data line -#define MBIF_CLUSTER_SIZE 1440 // MBIF/HBI cluster data line - - -//#define TX_SRAM_POOL_FREE_SIZE = 704; // Start of available TX SRAM -//#define TX_SRAM_END_SIZE = 0; // End of TX SRAM - -// Receive SRAM -#define RX_SRAM_START 0x10000 -#define VID_A_DOWN_CMDS 0x10000 -#define VID_B_DOWN_CMDS 0x10050 -#define VID_C_DOWN_CMDS 0x100A0 -#define VID_D_DOWN_CMDS 0x100F0 -#define VID_E_DOWN_CMDS 0x10140 -#define VID_F_DOWN_CMDS 0x10190 -#define VID_G_DOWN_CMDS 0x101E0 -#define VID_H_DOWN_CMDS 0x10230 -#define VID_A_UP_CMDS 0x10280 -#define VID_B_UP_CMDS 0x102D0 -#define VID_C_UP_CMDS 0x10320 -#define VID_D_UP_CMDS 0x10370 -#define VID_E_UP_CMDS 0x103C0 -#define VID_F_UP_CMDS 0x10410 -#define VID_I_UP_CMDS 0x10460 -#define VID_J_UP_CMDS 0x104B0 -#define AUD_A_DOWN_CMDS 0x10500 -#define AUD_B_DOWN_CMDS 0x10550 -#define AUD_C_DOWN_CMDS 0x105A0 -#define AUD_D_DOWN_CMDS 0x105F0 -#define AUD_A_UP_CMDS 0x10640 -#define AUD_B_UP_CMDS 0x10690 -#define AUD_C_UP_CMDS 0x106E0 -#define AUD_E_UP_CMDS 0x10730 -#define MBIF_A_DOWN_CMDS 0x10780 -#define MBIF_B_DOWN_CMDS 0x107D0 -#define DMA_SCRATCH_PAD 0x10820 // Scratch pad area from 0x10820 to 0x10B40 - -//#define RX_SRAM_POOL_START = 0x105B0; - -#define VID_A_IQ 0x11000 -#define VID_B_IQ 0x11040 -#define VID_C_IQ 0x11080 -#define VID_D_IQ 0x110C0 -#define VID_E_IQ 0x11100 -#define VID_F_IQ 0x11140 -#define VID_G_IQ 0x11180 -#define VID_H_IQ 0x111C0 -#define VID_I_IQ 0x11200 -#define VID_J_IQ 0x11240 -#define AUD_A_IQ 0x11280 -#define AUD_B_IQ 0x112C0 -#define AUD_C_IQ 0x11300 -#define AUD_D_IQ 0x11340 -#define AUD_E_IQ 0x11380 -#define MBIF_A_IQ 0x11000 -#define MBIF_B_IQ 0x110C0 - -#define VID_A_CDT 0x10C00 -#define VID_B_CDT 0x10C40 -#define VID_C_CDT 0x10C80 -#define VID_D_CDT 0x10CC0 -#define VID_E_CDT 0x10D00 -#define VID_F_CDT 0x10D40 -#define VID_G_CDT 0x10D80 -#define VID_H_CDT 0x10DC0 -#define VID_I_CDT 0x10E00 -#define VID_J_CDT 0x10E40 -#define AUD_A_CDT 0x10E80 -#define AUD_B_CDT 0x10EB0 -#define AUD_C_CDT 0x10EE0 -#define AUD_D_CDT 0x10F10 -#define AUD_E_CDT 0x10F40 -#define MBIF_A_CDT 0x10C00 -#define MBIF_B_CDT 0x10CC0 - -// Cluster Buffer for RX -#define VID_A_UP_CLUSTER_1 0x11400 -#define VID_A_UP_CLUSTER_2 0x119A0 -#define VID_A_UP_CLUSTER_3 0x11F40 -#define VID_A_UP_CLUSTER_4 0x124E0 - -#define VID_B_UP_CLUSTER_1 0x12A80 -#define VID_B_UP_CLUSTER_2 0x13020 -#define VID_B_UP_CLUSTER_3 0x135C0 -#define VID_B_UP_CLUSTER_4 0x13B60 - -#define VID_C_UP_CLUSTER_1 0x14100 -#define VID_C_UP_CLUSTER_2 0x146A0 -#define VID_C_UP_CLUSTER_3 0x14C40 -#define VID_C_UP_CLUSTER_4 0x151E0 - -#define VID_D_UP_CLUSTER_1 0x15780 -#define VID_D_UP_CLUSTER_2 0x15D20 -#define VID_D_UP_CLUSTER_3 0x162C0 -#define VID_D_UP_CLUSTER_4 0x16860 - -#define VID_E_UP_CLUSTER_1 0x16E00 -#define VID_E_UP_CLUSTER_2 0x173A0 -#define VID_E_UP_CLUSTER_3 0x17940 -#define VID_E_UP_CLUSTER_4 0x17EE0 - -#define VID_F_UP_CLUSTER_1 0x18480 -#define VID_F_UP_CLUSTER_2 0x18A20 -#define VID_F_UP_CLUSTER_3 0x18FC0 -#define VID_F_UP_CLUSTER_4 0x19560 - -#define VID_I_UP_CLUSTER_1 0x19B00 -#define VID_I_UP_CLUSTER_2 0x1A0A0 -#define VID_I_UP_CLUSTER_3 0x1A640 -#define VID_I_UP_CLUSTER_4 0x1ABE0 - -#define VID_J_UP_CLUSTER_1 0x1B180 -#define VID_J_UP_CLUSTER_2 0x1B720 -#define VID_J_UP_CLUSTER_3 0x1BCC0 -#define VID_J_UP_CLUSTER_4 0x1C260 - -#define AUD_A_UP_CLUSTER_1 0x1C800 -#define AUD_A_UP_CLUSTER_2 0x1C880 -#define AUD_A_UP_CLUSTER_3 0x1C900 - -#define AUD_B_UP_CLUSTER_1 0x1C980 -#define AUD_B_UP_CLUSTER_2 0x1CA00 -#define AUD_B_UP_CLUSTER_3 0x1CA80 - -#define AUD_C_UP_CLUSTER_1 0x1CB00 -#define AUD_C_UP_CLUSTER_2 0x1CB80 -#define AUD_C_UP_CLUSTER_3 0x1CC00 - -#define AUD_E_UP_CLUSTER_1 0x1CC80 -#define AUD_E_UP_CLUSTER_2 0x1CD00 -#define AUD_E_UP_CLUSTER_3 0x1CD80 - -#define RX_SRAM_POOL_FREE 0x1CE00 -#define RX_SRAM_END 0x1D000 - -// Free Receive SRAM 144 Bytes - - -// Transmit SRAM -#define TX_SRAM_POOL_START 0x00000 - -#define VID_A_DOWN_CLUSTER_1 0x00040 -#define VID_A_DOWN_CLUSTER_2 0x005E0 -#define VID_A_DOWN_CLUSTER_3 0x00B80 -#define VID_A_DOWN_CLUSTER_4 0x01120 - -#define VID_B_DOWN_CLUSTER_1 0x016C0 -#define VID_B_DOWN_CLUSTER_2 0x01C60 -#define VID_B_DOWN_CLUSTER_3 0x02200 -#define VID_B_DOWN_CLUSTER_4 0x027A0 - -#define VID_C_DOWN_CLUSTER_1 0x02D40 -#define VID_C_DOWN_CLUSTER_2 0x032E0 -#define VID_C_DOWN_CLUSTER_3 0x03880 -#define VID_C_DOWN_CLUSTER_4 0x03E20 - -#define VID_D_DOWN_CLUSTER_1 0x043C0 -#define VID_D_DOWN_CLUSTER_2 0x04960 -#define VID_D_DOWN_CLUSTER_3 0x04F00 -#define VID_D_DOWN_CLUSTER_4 0x054A0 - -#define VID_E_DOWN_CLUSTER_1 0x05a40 -#define VID_E_DOWN_CLUSTER_2 0x05FE0 -#define VID_E_DOWN_CLUSTER_3 0x06580 -#define VID_E_DOWN_CLUSTER_4 0x06B20 - -#define VID_F_DOWN_CLUSTER_1 0x070C0 -#define VID_F_DOWN_CLUSTER_2 0x07660 -#define VID_F_DOWN_CLUSTER_3 0x07C00 -#define VID_F_DOWN_CLUSTER_4 0x081A0 - -#define VID_G_DOWN_CLUSTER_1 0x08740 -#define VID_G_DOWN_CLUSTER_2 0x08CE0 -#define VID_G_DOWN_CLUSTER_3 0x09280 -#define VID_G_DOWN_CLUSTER_4 0x09820 - -#define VID_H_DOWN_CLUSTER_1 0x09DC0 -#define VID_H_DOWN_CLUSTER_2 0x0A360 -#define VID_H_DOWN_CLUSTER_3 0x0A900 -#define VID_H_DOWN_CLUSTER_4 0x0AEA0 - -#define AUD_A_DOWN_CLUSTER_1 0x0B500 -#define AUD_A_DOWN_CLUSTER_2 0x0B580 -#define AUD_A_DOWN_CLUSTER_3 0x0B600 - -#define AUD_B_DOWN_CLUSTER_1 0x0B680 -#define AUD_B_DOWN_CLUSTER_2 0x0B700 -#define AUD_B_DOWN_CLUSTER_3 0x0B780 - -#define AUD_C_DOWN_CLUSTER_1 0x0B800 -#define AUD_C_DOWN_CLUSTER_2 0x0B880 -#define AUD_C_DOWN_CLUSTER_3 0x0B900 - -#define AUD_D_DOWN_CLUSTER_1 0x0B980 -#define AUD_D_DOWN_CLUSTER_2 0x0BA00 -#define AUD_D_DOWN_CLUSTER_3 0x0BA80 - -#define TX_SRAM_POOL_FREE 0x0BB00 -#define TX_SRAM_END 0x0C000 - - -#define BYTES_TO_DWORDS(bcount) ((bcount) >> 2) -#define BYTES_TO_QWORDS(bcount) ((bcount) >> 3) -#define BYTES_TO_OWORDS(bcount) ((bcount) >> 4) - -#define VID_IQ_SIZE_DW BYTES_TO_DWORDS(VID_IQ_SIZE) -#define VID_CDT_SIZE_QW BYTES_TO_QWORDS(VID_CDT_SIZE) -#define VID_CLUSTER_SIZE_OW BYTES_TO_OWORDS(VID_CLUSTER_SIZE) - -#define AUDIO_IQ_SIZE_DW BYTES_TO_DWORDS(AUDIO_IQ_SIZE) -#define AUDIO_CDT_SIZE_QW BYTES_TO_QWORDS(AUDIO_CDT_SIZE) -#define AUDIO_CLUSTER_SIZE_QW BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE) - -#define MBIF_IQ_SIZE_DW BYTES_TO_DWORDS(MBIF_IQ_SIZE) -#define MBIF_CDT_SIZE_QW BYTES_TO_QWORDS(MBIF_CDT_SIZE) -#define MBIF_CLUSTER_SIZE_OW BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE) - - -#endif - +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ATHENA_SRAM_H__ +#define __ATHENA_SRAM_H__ + +//#define RX_SRAM_START_SIZE = 0; // Start of reserved SRAM +#define VID_CMDS_SIZE 80 // Video CMDS size in bytes +#define AUDIO_CMDS_SIZE 80 // AUDIO CMDS size in bytes +#define MBIF_CMDS_SIZE 80 // MBIF CMDS size in bytes + +//#define RX_SRAM_POOL_START_SIZE = 0; // Start of useable RX SRAM for buffers +#define VID_IQ_SIZE 64 // VID instruction queue size in bytes +#define MBIF_IQ_SIZE 64 +#define AUDIO_IQ_SIZE 64 // AUD instruction queue size in bytes + +#define VID_CDT_SIZE 64 // VID cluster descriptor table size in bytes +#define MBIF_CDT_SIZE 64 // MBIF/HBI cluster descriptor table size in bytes +#define AUDIO_CDT_SIZE 48 // AUD cluster descriptor table size in bytes + +//#define RX_SRAM_POOL_FREE_SIZE = 16; // Start of available RX SRAM +//#define RX_SRAM_END_SIZE = 0; // End of RX SRAM + +//#define TX_SRAM_POOL_START_SIZE = 0; // Start of transmit pool SRAM +//#define MSI_DATA_SIZE = 64; // Reserved (MSI Data, RISC working stora + +#define VID_CLUSTER_SIZE 1440 // VID cluster data line +#define AUDIO_CLUSTER_SIZE 128 // AUDIO cluster data line +#define MBIF_CLUSTER_SIZE 1440 // MBIF/HBI cluster data line + +//#define TX_SRAM_POOL_FREE_SIZE = 704; // Start of available TX SRAM +//#define TX_SRAM_END_SIZE = 0; // End of TX SRAM + +// Receive SRAM +#define RX_SRAM_START 0x10000 +#define VID_A_DOWN_CMDS 0x10000 +#define VID_B_DOWN_CMDS 0x10050 +#define VID_C_DOWN_CMDS 0x100A0 +#define VID_D_DOWN_CMDS 0x100F0 +#define VID_E_DOWN_CMDS 0x10140 +#define VID_F_DOWN_CMDS 0x10190 +#define VID_G_DOWN_CMDS 0x101E0 +#define VID_H_DOWN_CMDS 0x10230 +#define VID_A_UP_CMDS 0x10280 +#define VID_B_UP_CMDS 0x102D0 +#define VID_C_UP_CMDS 0x10320 +#define VID_D_UP_CMDS 0x10370 +#define VID_E_UP_CMDS 0x103C0 +#define VID_F_UP_CMDS 0x10410 +#define VID_I_UP_CMDS 0x10460 +#define VID_J_UP_CMDS 0x104B0 +#define AUD_A_DOWN_CMDS 0x10500 +#define AUD_B_DOWN_CMDS 0x10550 +#define AUD_C_DOWN_CMDS 0x105A0 +#define AUD_D_DOWN_CMDS 0x105F0 +#define AUD_A_UP_CMDS 0x10640 +#define AUD_B_UP_CMDS 0x10690 +#define AUD_C_UP_CMDS 0x106E0 +#define AUD_E_UP_CMDS 0x10730 +#define MBIF_A_DOWN_CMDS 0x10780 +#define MBIF_B_DOWN_CMDS 0x107D0 +#define DMA_SCRATCH_PAD 0x10820 // Scratch pad area from 0x10820 to 0x10B40 + +//#define RX_SRAM_POOL_START = 0x105B0; + +#define VID_A_IQ 0x11000 +#define VID_B_IQ 0x11040 +#define VID_C_IQ 0x11080 +#define VID_D_IQ 0x110C0 +#define VID_E_IQ 0x11100 +#define VID_F_IQ 0x11140 +#define VID_G_IQ 0x11180 +#define VID_H_IQ 0x111C0 +#define VID_I_IQ 0x11200 +#define VID_J_IQ 0x11240 +#define AUD_A_IQ 0x11280 +#define AUD_B_IQ 0x112C0 +#define AUD_C_IQ 0x11300 +#define AUD_D_IQ 0x11340 +#define AUD_E_IQ 0x11380 +#define MBIF_A_IQ 0x11000 +#define MBIF_B_IQ 0x110C0 + +#define VID_A_CDT 0x10C00 +#define VID_B_CDT 0x10C40 +#define VID_C_CDT 0x10C80 +#define VID_D_CDT 0x10CC0 +#define VID_E_CDT 0x10D00 +#define VID_F_CDT 0x10D40 +#define VID_G_CDT 0x10D80 +#define VID_H_CDT 0x10DC0 +#define VID_I_CDT 0x10E00 +#define VID_J_CDT 0x10E40 +#define AUD_A_CDT 0x10E80 +#define AUD_B_CDT 0x10EB0 +#define AUD_C_CDT 0x10EE0 +#define AUD_D_CDT 0x10F10 +#define AUD_E_CDT 0x10F40 +#define MBIF_A_CDT 0x10C00 +#define MBIF_B_CDT 0x10CC0 + +// Cluster Buffer for RX +#define VID_A_UP_CLUSTER_1 0x11400 +#define VID_A_UP_CLUSTER_2 0x119A0 +#define VID_A_UP_CLUSTER_3 0x11F40 +#define VID_A_UP_CLUSTER_4 0x124E0 + +#define VID_B_UP_CLUSTER_1 0x12A80 +#define VID_B_UP_CLUSTER_2 0x13020 +#define VID_B_UP_CLUSTER_3 0x135C0 +#define VID_B_UP_CLUSTER_4 0x13B60 + +#define VID_C_UP_CLUSTER_1 0x14100 +#define VID_C_UP_CLUSTER_2 0x146A0 +#define VID_C_UP_CLUSTER_3 0x14C40 +#define VID_C_UP_CLUSTER_4 0x151E0 + +#define VID_D_UP_CLUSTER_1 0x15780 +#define VID_D_UP_CLUSTER_2 0x15D20 +#define VID_D_UP_CLUSTER_3 0x162C0 +#define VID_D_UP_CLUSTER_4 0x16860 + +#define VID_E_UP_CLUSTER_1 0x16E00 +#define VID_E_UP_CLUSTER_2 0x173A0 +#define VID_E_UP_CLUSTER_3 0x17940 +#define VID_E_UP_CLUSTER_4 0x17EE0 + +#define VID_F_UP_CLUSTER_1 0x18480 +#define VID_F_UP_CLUSTER_2 0x18A20 +#define VID_F_UP_CLUSTER_3 0x18FC0 +#define VID_F_UP_CLUSTER_4 0x19560 + +#define VID_I_UP_CLUSTER_1 0x19B00 +#define VID_I_UP_CLUSTER_2 0x1A0A0 +#define VID_I_UP_CLUSTER_3 0x1A640 +#define VID_I_UP_CLUSTER_4 0x1ABE0 + +#define VID_J_UP_CLUSTER_1 0x1B180 +#define VID_J_UP_CLUSTER_2 0x1B720 +#define VID_J_UP_CLUSTER_3 0x1BCC0 +#define VID_J_UP_CLUSTER_4 0x1C260 + +#define AUD_A_UP_CLUSTER_1 0x1C800 +#define AUD_A_UP_CLUSTER_2 0x1C880 +#define AUD_A_UP_CLUSTER_3 0x1C900 + +#define AUD_B_UP_CLUSTER_1 0x1C980 +#define AUD_B_UP_CLUSTER_2 0x1CA00 +#define AUD_B_UP_CLUSTER_3 0x1CA80 + +#define AUD_C_UP_CLUSTER_1 0x1CB00 +#define AUD_C_UP_CLUSTER_2 0x1CB80 +#define AUD_C_UP_CLUSTER_3 0x1CC00 + +#define AUD_E_UP_CLUSTER_1 0x1CC80 +#define AUD_E_UP_CLUSTER_2 0x1CD00 +#define AUD_E_UP_CLUSTER_3 0x1CD80 + +#define RX_SRAM_POOL_FREE 0x1CE00 +#define RX_SRAM_END 0x1D000 + +// Free Receive SRAM 144 Bytes + +// Transmit SRAM +#define TX_SRAM_POOL_START 0x00000 + +#define VID_A_DOWN_CLUSTER_1 0x00040 +#define VID_A_DOWN_CLUSTER_2 0x005E0 +#define VID_A_DOWN_CLUSTER_3 0x00B80 +#define VID_A_DOWN_CLUSTER_4 0x01120 + +#define VID_B_DOWN_CLUSTER_1 0x016C0 +#define VID_B_DOWN_CLUSTER_2 0x01C60 +#define VID_B_DOWN_CLUSTER_3 0x02200 +#define VID_B_DOWN_CLUSTER_4 0x027A0 + +#define VID_C_DOWN_CLUSTER_1 0x02D40 +#define VID_C_DOWN_CLUSTER_2 0x032E0 +#define VID_C_DOWN_CLUSTER_3 0x03880 +#define VID_C_DOWN_CLUSTER_4 0x03E20 + +#define VID_D_DOWN_CLUSTER_1 0x043C0 +#define VID_D_DOWN_CLUSTER_2 0x04960 +#define VID_D_DOWN_CLUSTER_3 0x04F00 +#define VID_D_DOWN_CLUSTER_4 0x054A0 + +#define VID_E_DOWN_CLUSTER_1 0x05a40 +#define VID_E_DOWN_CLUSTER_2 0x05FE0 +#define VID_E_DOWN_CLUSTER_3 0x06580 +#define VID_E_DOWN_CLUSTER_4 0x06B20 + +#define VID_F_DOWN_CLUSTER_1 0x070C0 +#define VID_F_DOWN_CLUSTER_2 0x07660 +#define VID_F_DOWN_CLUSTER_3 0x07C00 +#define VID_F_DOWN_CLUSTER_4 0x081A0 + +#define VID_G_DOWN_CLUSTER_1 0x08740 +#define VID_G_DOWN_CLUSTER_2 0x08CE0 +#define VID_G_DOWN_CLUSTER_3 0x09280 +#define VID_G_DOWN_CLUSTER_4 0x09820 + +#define VID_H_DOWN_CLUSTER_1 0x09DC0 +#define VID_H_DOWN_CLUSTER_2 0x0A360 +#define VID_H_DOWN_CLUSTER_3 0x0A900 +#define VID_H_DOWN_CLUSTER_4 0x0AEA0 + +#define AUD_A_DOWN_CLUSTER_1 0x0B500 +#define AUD_A_DOWN_CLUSTER_2 0x0B580 +#define AUD_A_DOWN_CLUSTER_3 0x0B600 + +#define AUD_B_DOWN_CLUSTER_1 0x0B680 +#define AUD_B_DOWN_CLUSTER_2 0x0B700 +#define AUD_B_DOWN_CLUSTER_3 0x0B780 + +#define AUD_C_DOWN_CLUSTER_1 0x0B800 +#define AUD_C_DOWN_CLUSTER_2 0x0B880 +#define AUD_C_DOWN_CLUSTER_3 0x0B900 + +#define AUD_D_DOWN_CLUSTER_1 0x0B980 +#define AUD_D_DOWN_CLUSTER_2 0x0BA00 +#define AUD_D_DOWN_CLUSTER_3 0x0BA80 + +#define TX_SRAM_POOL_FREE 0x0BB00 +#define TX_SRAM_END 0x0C000 + +#define BYTES_TO_DWORDS(bcount) ((bcount) >> 2) +#define BYTES_TO_QWORDS(bcount) ((bcount) >> 3) +#define BYTES_TO_OWORDS(bcount) ((bcount) >> 4) + +#define VID_IQ_SIZE_DW BYTES_TO_DWORDS(VID_IQ_SIZE) +#define VID_CDT_SIZE_QW BYTES_TO_QWORDS(VID_CDT_SIZE) +#define VID_CLUSTER_SIZE_OW BYTES_TO_OWORDS(VID_CLUSTER_SIZE) + +#define AUDIO_IQ_SIZE_DW BYTES_TO_DWORDS(AUDIO_IQ_SIZE) +#define AUDIO_CDT_SIZE_QW BYTES_TO_QWORDS(AUDIO_CDT_SIZE) +#define AUDIO_CLUSTER_SIZE_QW BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE) + +#define MBIF_IQ_SIZE_DW BYTES_TO_DWORDS(MBIF_IQ_SIZE) +#define MBIF_CDT_SIZE_QW BYTES_TO_QWORDS(MBIF_CDT_SIZE) +#define MBIF_CLUSTER_SIZE_OW BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE) + +#endif diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c index 720729efc..c8905e0ac 100644 --- a/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.c @@ -1,847 +1,835 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include "cx25821-video.h" -#include "cx25821-video-upstream-ch2.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); -MODULE_AUTHOR("Hiep Huynh "); -MODULE_LICENSE("GPL"); - - -static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; - - -static __le32 *cx25821_update_riscprogram_ch2( struct cx25821_dev *dev, - __le32 *rp, unsigned int offset, unsigned int bpl, - u32 sync_line, unsigned int lines, int fifo_enable, int field_type) -{ - unsigned int line, i; - int dist_betwn_starts = bpl * 2; - - - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); - - - if( USE_RISC_NOOP_VIDEO ) - { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } - } - - /* scan lines */ - for (line = 0; line < lines; line++) - { - *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) ) - { - offset += dist_betwn_starts; - } - } - - return rp; -} - -static __le32 *cx25821_risc_field_upstream_ch2( struct cx25821_dev *dev, - __le32 *rp, - dma_addr_t databuf_phys_addr, - unsigned int offset, u32 sync_line, unsigned int bpl, - unsigned int lines, int fifo_enable, int field_type) -{ - unsigned int line, i; - struct sram_channel *sram_ch = &dev->sram_channels[dev->_channel2_upstream_select]; - int dist_betwn_starts = bpl * 2; - - - /* sync instruction */ - if (sync_line != NO_SYNC_LINE) - { - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); - } - - - if( USE_RISC_NOOP_VIDEO ) - { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } - } - - /* scan lines */ - for (line = 0; line < lines; line++) - { - *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(databuf_phys_addr+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - - if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) ) - { - offset += dist_betwn_starts; - } - - - // check if we need to enable the FIFO after the first 4 lines - // For the upstream video channel, the risc engine will enable the FIFO. - if ( fifo_enable && line == 3 ) - { - *(rp++) = RISC_WRITECR; - *(rp++) = sram_ch->dma_ctl; - *(rp++) = FLD_VID_FIFO_EN; - *(rp++) = 0x00000001; - } - } - - return rp; -} - -int cx25821_risc_buffer_upstream_ch2( struct cx25821_dev *dev, struct pci_dev *pci, - unsigned int top_offset, - unsigned int bpl, unsigned int lines) -{ - __le32 *rp; - int fifo_enable = 0; - int singlefield_lines = lines >> 1; //get line count for single field - int odd_num_lines = singlefield_lines; - int frame = 0; - int frame_size = 0; - int databuf_offset = 0; - int risc_program_size = 0; - int risc_flag = RISC_CNT_RESET; - unsigned int bottom_offset = bpl; - dma_addr_t risc_phys_jump_addr; - - - if( dev->_isNTSC_ch2 ) - { - odd_num_lines = singlefield_lines + 1; - risc_program_size = FRAME1_VID_PROG_SIZE; - frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; - } - else - { - risc_program_size = PAL_VID_PROG_SIZE; - frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; - } - - - /* Virtual address of Risc buffer program */ - rp = dev->_dma_virt_addr_ch2; - - for( frame = 0; frame < NUM_FRAMES; frame++ ) - { - databuf_offset = frame_size * frame; - - - if (UNSET != top_offset) - { - fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; - rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD); - } - - fifo_enable = FIFO_DISABLE; - - - //Even field - rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD); - - - if( frame == 0 ) - { - risc_flag = RISC_CNT_RESET; - risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + risc_program_size; - } - else - { - risc_flag = RISC_CNT_INC; - risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2; - } - - - // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ - *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - } - - return 0; -} - - -void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) -{ - struct sram_channel *sram_ch = &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_J]; - u32 tmp = 0; - - if( !dev->_is_running_ch2 ) - { - printk("cx25821: No video file is currently running so return!\n"); - return; - } - - //Disable RISC interrupts - tmp = cx_read( sram_ch->int_msk ); - cx_write( sram_ch->int_msk, tmp & ~_intr_msk); - - //Turn OFF risc and fifo - tmp = cx_read( sram_ch->dma_ctl ); - cx_write( sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN) ); - - //Clear data buffer memory - if( dev->_data_buf_virt_addr_ch2 ) - memset( dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2 ); - - dev->_is_running_ch2 = 0; - dev->_is_first_frame_ch2 = 0; - dev->_frame_count_ch2 = 0; - dev->_file_status_ch2 = END_OF_FILE; - - if( dev->_irq_queues_ch2 ) - { - kfree(dev->_irq_queues_ch2); - dev->_irq_queues_ch2 = NULL; - } - - if( dev->_filename_ch2 != NULL ) - kfree(dev->_filename_ch2); - - tmp = cx_read( VID_CH_MODE_SEL ); - cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); -} - -void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev) -{ - if( dev->_is_running_ch2 ) - { - cx25821_stop_upstream_video_ch2(dev); - } - - if (dev->_dma_virt_addr_ch2) - { - pci_free_consistent(dev->pci, dev->_risc_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2); - dev->_dma_virt_addr_ch2 = NULL; - } - - if (dev->_data_buf_virt_addr_ch2) - { - pci_free_consistent(dev->pci, dev->_data_buf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2); - dev->_data_buf_virt_addr_ch2 = NULL; - } -} - - -int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch ) -{ - struct file * myfile; - int frame_index_temp = dev->_frame_index_ch2; - int i = 0; - int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; - int frame_size = 0; - int frame_offset = 0; - ssize_t vfs_read_retval = 0; - char mybuf[line_size]; - loff_t file_offset; - loff_t pos; - mm_segment_t old_fs; - - - if( dev->_file_status_ch2 == END_OF_FILE ) - return 0; - - if( dev->_isNTSC_ch2 ) - { - frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; - } - else - { - frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; - } - - frame_offset = (frame_index_temp > 0) ? frame_size : 0; - file_offset = dev->_frame_count_ch2 * frame_size; - - - myfile = filp_open( dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0 ); - - - if (IS_ERR(myfile)) - { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno); - return PTR_ERR(myfile); - } - else - { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( i = 0; i < dev->_lines_count_ch2; i++ ) - { - pos = file_offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL ) - { - memcpy( (void*)(dev->_data_buf_virt_addr_ch2+frame_offset/4), mybuf, vfs_read_retval); - } - - file_offset += vfs_read_retval; - frame_offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - dev->_frame_count_ch2++; - - dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - - set_fs(old_fs); - filp_close(myfile, NULL); - } - - return 0; -} - -static void cx25821_vidups_handler_ch2(struct work_struct *work) -{ - struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _irq_work_entry_ch2); - - if( !dev ) - { - printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); - return; - } - - cx25821_get_frame_ch2( dev, &dev->sram_channels[dev->_channel2_upstream_select] ); -} - - -int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) -{ - struct file * myfile; - int i = 0, j = 0; - int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; - ssize_t vfs_read_retval = 0; - char mybuf[line_size]; - loff_t pos; - loff_t offset = (unsigned long)0; - mm_segment_t old_fs; - - - myfile = filp_open( dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0 ); - - - if (IS_ERR(myfile)) - { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno); - return PTR_ERR(myfile); - } - else - { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered! Returning.", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( j = 0; j < NUM_FRAMES; j++ ) - { - for( i = 0; i < dev->_lines_count_ch2; i++ ) - { - pos = offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL ) - { - memcpy( (void*)(dev->_data_buf_virt_addr_ch2+offset/4), mybuf, vfs_read_retval); - } - - - offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - dev->_frame_count_ch2++; - - if( vfs_read_retval < line_size ) - { - break; - } - } - - dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - set_fs(old_fs); - myfile->f_pos = 0; - filp_close(myfile, NULL); - } - - return 0; -} - - -static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, - struct sram_channel *sram_ch, - int bpl) -{ - int ret = 0; - dma_addr_t dma_addr; - dma_addr_t data_dma_addr; - - - if( dev->_dma_virt_addr_ch2 != NULL ) - { - pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2); - } - - dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, &dma_addr); - dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2; - dev->_dma_phys_start_addr_ch2 = dma_addr; - dev->_dma_phys_addr_ch2 = dma_addr; - dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2; - - - if (!dev->_dma_virt_addr_ch2) - { - printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); - return -ENOMEM; - } - - - //Iniitize at this address until n bytes to 0 - memset( dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2 ); - - - if( dev->_data_buf_virt_addr_ch2 != NULL ) - { - pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2); - } - - //For Video Data buffer allocation - dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2, &data_dma_addr); - dev->_data_buf_phys_addr_ch2 = data_dma_addr; - dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2; - - if (!dev->_data_buf_virt_addr_ch2) - { - printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); - return -ENOMEM; - } - - - //Initialize at this address until n bytes to 0 - memset( dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2 ); - - - ret = cx25821_openfile_ch2(dev, sram_ch); - if( ret < 0 ) - return ret; - - - //Creating RISC programs - ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl, dev->_lines_count_ch2 ); - if (ret < 0) - { - printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n"); - goto error; - } - - return 0; - -error: - return ret; -} - -int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, u32 status) -{ - u32 int_msk_tmp; - struct sram_channel *channel = &dev->sram_channels[chan_num]; - int singlefield_lines = NTSC_FIELD_HEIGHT; - int line_size_in_bytes = Y422_LINE_SZ; - int odd_risc_prog_size = 0; - dma_addr_t risc_phys_jump_addr; - __le32 * rp; - - - - if (status & FLD_VID_SRC_RISC1) - { - // We should only process one program per call - u32 prog_cnt = cx_read( channel->gpcnt ); - - //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers - int_msk_tmp = cx_read(channel->int_msk); - cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); - cx_write( channel->int_stat, _intr_msk ); - - spin_lock(&dev->slock); - - dev->_frame_index_ch2 = prog_cnt; - - queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2); - - - if ( dev->_is_first_frame_ch2 ) - { - dev->_is_first_frame_ch2 = 0; - - if( dev->_isNTSC_ch2 ) - { - singlefield_lines += 1; - odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; - } - else - { - singlefield_lines = PAL_FIELD_HEIGHT; - odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; - } - - - if( dev->_dma_virt_start_addr_ch2 != NULL ) - { - line_size_in_bytes = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; - risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + odd_risc_prog_size; - - rp = cx25821_update_riscprogram_ch2(dev, dev->_dma_virt_start_addr_ch2, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD); - - // Jump to Even Risc program of 1st Frame - *(rp++) = cpu_to_le32(RISC_JUMP); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - } - } - - spin_unlock(&dev->slock); - } - - - if( dev->_file_status_ch2 == END_OF_FILE ) - { - printk("cx25821: EOF Channel 2 Framecount = %d\n", dev->_frame_count_ch2 ); - return -1; - } - - //ElSE, set the interrupt mask register, re-enable irq. - int_msk_tmp = cx_read( channel->int_msk ); - cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); - - return 0; -} - -static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) -{ - struct cx25821_dev *dev = dev_id; - u32 msk_stat, vid_status; - int handled = 0; - int channel_num = 0; - struct sram_channel *sram_ch; - - - if( !dev ) - return -1; - - channel_num = VID_UPSTREAM_SRAM_CHANNEL_J; - - sram_ch = &dev->sram_channels[channel_num]; - - msk_stat = cx_read(sram_ch->int_mstat); - vid_status = cx_read(sram_ch->int_stat); - - // Only deal with our interrupt - if(vid_status) - { - handled = cx25821_video_upstream_irq_ch2(dev, channel_num, vid_status); - } - - - if( handled < 0 ) - { - cx25821_stop_upstream_video_ch2(dev); - } - else - { - handled += handled; - } - - return IRQ_RETVAL(handled); -} - - -static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, struct sram_channel *ch, int pix_format) -{ - int width = WIDTH_D1; - int height = dev->_lines_count_ch2; - int num_lines, odd_num_lines; - u32 value; - int vip_mode = PIXEL_ENGINE_VIP1; - - - value = ( (pix_format & 0x3) << 12 ) | ( vip_mode & 0x7 ); - value &= 0xFFFFFFEF; - value |= dev->_isNTSC_ch2 ? 0 : 0x10; - cx_write( ch->vid_fmt_ctl, value ); - - // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format - cx_write( ch->vid_active_ctl1, width ); - - num_lines = (height / 2) & 0x3FF; - odd_num_lines = num_lines; - - if(dev->_isNTSC_ch2) - { - odd_num_lines += 1; - } - - value = (num_lines << 16) | odd_num_lines; - - // set number of active lines in field 0 (top) and field 1 (bottom) - cx_write( ch->vid_active_ctl2, value ); - - cx_write( ch->vid_cdt_size, VID_CDT_SIZE >> 3 ); -} - - -int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, - struct sram_channel *sram_ch) -{ - u32 tmp = 0; - int err = 0; - - - // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C - tmp = cx_read( VID_CH_MODE_SEL ); - cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); - - - // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. - cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2); - cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ - - /* reset counter */ - cx_write(sram_ch->gpcnt_ctl, 3); - - // Clear our bits from the interrupt status register. - cx_write( sram_ch->int_stat, _intr_msk ); - - - //Set the interrupt mask register, enable irq. - cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); - tmp = cx_read( sram_ch->int_msk ); - cx_write( sram_ch->int_msk, tmp |= _intr_msk ); - - - err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); - if (err < 0) - { - printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); - goto fail_irq; - } - - // Start the DMA engine - tmp = cx_read( sram_ch->dma_ctl ); - cx_set( sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN ); - - dev->_is_running_ch2 = 1; - dev->_is_first_frame_ch2 = 1; - - return 0; - - -fail_irq: - cx25821_dev_unregister(dev); - return err; -} - - -int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, int pixel_format) -{ - struct sram_channel *sram_ch; - u32 tmp; - int retval = 0; - int err = 0; - int data_frame_size = 0; - int risc_buffer_size = 0; - int str_length = 0; - - if( dev->_is_running_ch2 ) - { - printk("Video Channel is still running so return!\n"); - return 0; - } - - dev->_channel2_upstream_select = channel_select; - sram_ch = &dev->sram_channels[channel_select]; - - - INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2); - dev->_irq_queues_ch2 = create_singlethread_workqueue("cx25821_workqueue2"); - - if(!dev->_irq_queues_ch2) - { - printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); - return -ENOMEM; - } - - // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C - tmp = cx_read( VID_CH_MODE_SEL ); - cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); - - - dev->_is_running_ch2 = 0; - dev->_frame_count_ch2 = 0; - dev->_file_status_ch2 = RESET_STATUS; - dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576; - dev->_pixel_format_ch2 = pixel_format; - dev->_line_size_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; - data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; - risc_buffer_size = dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; - - - if( dev->input_filename_ch2 ) - { - str_length = strlen(dev->input_filename_ch2); - dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_filename_ch2 ) - goto error; - - memcpy(dev->_filename_ch2, dev->input_filename_ch2, str_length + 1); - } - else - { - str_length = strlen(dev->_defaultname_ch2); - dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_filename_ch2 ) - goto error; - - memcpy(dev->_filename_ch2, dev->_defaultname_ch2, str_length + 1); - } - - - //Default if filename is empty string - if( strcmp(dev->input_filename_ch2,"") == 0) - { - if( dev->_isNTSC_ch2 ) - { - dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv"; - } - else - { - dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv"; - } - } - - - retval = cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size_ch2, 0); - - - /* setup fifo + format */ - cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2); - - dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2; - dev->upstream_databuf_size_ch2 = data_frame_size * 2; - - - //Allocating buffers and prepare RISC program - retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch, dev->_line_size_ch2); - if (retval < 0) - { - printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name); - goto error; - } - - - cx25821_start_video_dma_upstream_ch2(dev, sram_ch); - - return 0; - -error: - cx25821_dev_unregister(dev); - - return err; -} - +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" +#include "cx25821-video-upstream-ch2.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); +MODULE_AUTHOR("Hiep Huynh "); +MODULE_LICENSE("GPL"); + +static int _intr_msk = + FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; + +static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev, + __le32 * rp, unsigned int offset, + unsigned int bpl, u32 sync_line, + unsigned int lines, + int fifo_enable, int field_type) +{ + unsigned int line, i; + int dist_betwn_starts = bpl * 2; + + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + + if (USE_RISC_NOOP_VIDEO) { + for (i = 0; i < NUM_NO_OPS; i++) { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + /* scan lines */ + for (line = 0; line < lines; line++) { + *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); + *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + if ((lines <= NTSC_FIELD_HEIGHT) + || (line < (NTSC_FIELD_HEIGHT - 1)) + || !(dev->_isNTSC_ch2)) { + offset += dist_betwn_starts; + } + } + + return rp; +} + +static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev, + __le32 * rp, + dma_addr_t databuf_phys_addr, + unsigned int offset, + u32 sync_line, unsigned int bpl, + unsigned int lines, + int fifo_enable, int field_type) +{ + unsigned int line, i; + struct sram_channel *sram_ch = + &dev->sram_channels[dev->_channel2_upstream_select]; + int dist_betwn_starts = bpl * 2; + + /* sync instruction */ + if (sync_line != NO_SYNC_LINE) { + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + } + + if (USE_RISC_NOOP_VIDEO) { + for (i = 0; i < NUM_NO_OPS; i++) { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + /* scan lines */ + for (line = 0; line < lines; line++) { + *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); + *(rp++) = cpu_to_le32(databuf_phys_addr + offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + if ((lines <= NTSC_FIELD_HEIGHT) + || (line < (NTSC_FIELD_HEIGHT - 1)) + || !(dev->_isNTSC_ch2)) { + offset += dist_betwn_starts; + } + + // check if we need to enable the FIFO after the first 4 lines + // For the upstream video channel, the risc engine will enable the FIFO. + if (fifo_enable && line == 3) { + *(rp++) = RISC_WRITECR; + *(rp++) = sram_ch->dma_ctl; + *(rp++) = FLD_VID_FIFO_EN; + *(rp++) = 0x00000001; + } + } + + return rp; +} + +int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, + struct pci_dev *pci, + unsigned int top_offset, unsigned int bpl, + unsigned int lines) +{ + __le32 *rp; + int fifo_enable = 0; + int singlefield_lines = lines >> 1; //get line count for single field + int odd_num_lines = singlefield_lines; + int frame = 0; + int frame_size = 0; + int databuf_offset = 0; + int risc_program_size = 0; + int risc_flag = RISC_CNT_RESET; + unsigned int bottom_offset = bpl; + dma_addr_t risc_phys_jump_addr; + + if (dev->_isNTSC_ch2) { + odd_num_lines = singlefield_lines + 1; + risc_program_size = FRAME1_VID_PROG_SIZE; + frame_size = + (bpl == + Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : + FRAME_SIZE_NTSC_Y422; + } else { + risc_program_size = PAL_VID_PROG_SIZE; + frame_size = + (bpl == + Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + } + + /* Virtual address of Risc buffer program */ + rp = dev->_dma_virt_addr_ch2; + + for (frame = 0; frame < NUM_FRAMES; frame++) { + databuf_offset = frame_size * frame; + + if (UNSET != top_offset) { + fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; + rp = cx25821_risc_field_upstream_ch2(dev, rp, + dev-> + _data_buf_phys_addr_ch2 + + databuf_offset, + top_offset, 0, bpl, + odd_num_lines, + fifo_enable, + ODD_FIELD); + } + + fifo_enable = FIFO_DISABLE; + + //Even field + rp = cx25821_risc_field_upstream_ch2(dev, rp, + dev-> + _data_buf_phys_addr_ch2 + + databuf_offset, + bottom_offset, 0x200, bpl, + singlefield_lines, + fifo_enable, EVEN_FIELD); + + if (frame == 0) { + risc_flag = RISC_CNT_RESET; + risc_phys_jump_addr = + dev->_dma_phys_start_addr_ch2 + risc_program_size; + } else { + risc_flag = RISC_CNT_INC; + risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2; + } + + // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ + *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + + return 0; +} + +void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) +{ + struct sram_channel *sram_ch = + &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_J]; + u32 tmp = 0; + + if (!dev->_is_running_ch2) { + printk + ("cx25821: No video file is currently running so return!\n"); + return; + } + //Disable RISC interrupts + tmp = cx_read(sram_ch->int_msk); + cx_write(sram_ch->int_msk, tmp & ~_intr_msk); + + //Turn OFF risc and fifo + tmp = cx_read(sram_ch->dma_ctl); + cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); + + //Clear data buffer memory + if (dev->_data_buf_virt_addr_ch2) + memset(dev->_data_buf_virt_addr_ch2, 0, + dev->_data_buf_size_ch2); + + dev->_is_running_ch2 = 0; + dev->_is_first_frame_ch2 = 0; + dev->_frame_count_ch2 = 0; + dev->_file_status_ch2 = END_OF_FILE; + + if (dev->_irq_queues_ch2) { + kfree(dev->_irq_queues_ch2); + dev->_irq_queues_ch2 = NULL; + } + + if (dev->_filename_ch2 != NULL) + kfree(dev->_filename_ch2); + + tmp = cx_read(VID_CH_MODE_SEL); + cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); +} + +void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev) +{ + if (dev->_is_running_ch2) { + cx25821_stop_upstream_video_ch2(dev); + } + + if (dev->_dma_virt_addr_ch2) { + pci_free_consistent(dev->pci, dev->_risc_size_ch2, + dev->_dma_virt_addr_ch2, + dev->_dma_phys_addr_ch2); + dev->_dma_virt_addr_ch2 = NULL; + } + + if (dev->_data_buf_virt_addr_ch2) { + pci_free_consistent(dev->pci, dev->_data_buf_size_ch2, + dev->_data_buf_virt_addr_ch2, + dev->_data_buf_phys_addr_ch2); + dev->_data_buf_virt_addr_ch2 = NULL; + } +} + +int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) +{ + struct file *myfile; + int frame_index_temp = dev->_frame_index_ch2; + int i = 0; + int line_size = + (dev->_pixel_format_ch2 == + PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + int frame_size = 0; + int frame_offset = 0; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t file_offset; + loff_t pos; + mm_segment_t old_fs; + + if (dev->_file_status_ch2 == END_OF_FILE) + return 0; + + if (dev->_isNTSC_ch2) { + frame_size = + (line_size == + Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : + FRAME_SIZE_NTSC_Y422; + } else { + frame_size = + (line_size == + Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + } + + frame_offset = (frame_index_temp > 0) ? frame_size : 0; + file_offset = dev->_frame_count_ch2 * frame_size; + + myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0); + + if (IS_ERR(myfile)) { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", + __func__, dev->_filename_ch2, open_errno); + return PTR_ERR(myfile); + } else { + if (!(myfile->f_op)) { + printk("%s: File has no file operations registered!", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + if (!myfile->f_op->read) { + printk("%s: File has no READ operations registered!", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + for (i = 0; i < dev->_lines_count_ch2; i++) { + pos = file_offset; + + vfs_read_retval = + vfs_read(myfile, mybuf, line_size, &pos); + + if (vfs_read_retval > 0 && vfs_read_retval == line_size + && dev->_data_buf_virt_addr_ch2 != NULL) { + memcpy((void *)(dev->_data_buf_virt_addr_ch2 + + frame_offset / 4), mybuf, + vfs_read_retval); + } + + file_offset += vfs_read_retval; + frame_offset += vfs_read_retval; + + if (vfs_read_retval < line_size) { + printk(KERN_INFO + "Done: exit %s() since no more bytes to read from Video file.\n", + __func__); + break; + } + } + + if (i > 0) + dev->_frame_count_ch2++; + + dev->_file_status_ch2 = + (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + filp_close(myfile, NULL); + } + + return 0; +} + +static void cx25821_vidups_handler_ch2(struct work_struct *work) +{ + struct cx25821_dev *dev = + container_of(work, struct cx25821_dev, _irq_work_entry_ch2); + + if (!dev) { + printk("ERROR %s(): since container_of(work_struct) FAILED! \n", + __func__); + return; + } + + cx25821_get_frame_ch2(dev, + &dev->sram_channels[dev-> + _channel2_upstream_select]); +} + +int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) +{ + struct file *myfile; + int i = 0, j = 0; + int line_size = + (dev->_pixel_format_ch2 == + PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t pos; + loff_t offset = (unsigned long)0; + mm_segment_t old_fs; + + myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0); + + if (IS_ERR(myfile)) { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", + __func__, dev->_filename_ch2, open_errno); + return PTR_ERR(myfile); + } else { + if (!(myfile->f_op)) { + printk("%s: File has no file operations registered!", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + if (!myfile->f_op->read) { + printk + ("%s: File has no READ operations registered! Returning.", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + for (j = 0; j < NUM_FRAMES; j++) { + for (i = 0; i < dev->_lines_count_ch2; i++) { + pos = offset; + + vfs_read_retval = + vfs_read(myfile, mybuf, line_size, &pos); + + if (vfs_read_retval > 0 + && vfs_read_retval == line_size + && dev->_data_buf_virt_addr_ch2 != NULL) { + memcpy((void *)(dev-> + _data_buf_virt_addr_ch2 + + offset / 4), mybuf, + vfs_read_retval); + } + + offset += vfs_read_retval; + + if (vfs_read_retval < line_size) { + printk(KERN_INFO + "Done: exit %s() since no more bytes to read from Video file.\n", + __func__); + break; + } + } + + if (i > 0) + dev->_frame_count_ch2++; + + if (vfs_read_retval < line_size) { + break; + } + } + + dev->_file_status_ch2 = + (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + myfile->f_pos = 0; + filp_close(myfile, NULL); + } + + return 0; +} + +static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, + struct sram_channel *sram_ch, + int bpl) +{ + int ret = 0; + dma_addr_t dma_addr; + dma_addr_t data_dma_addr; + + if (dev->_dma_virt_addr_ch2 != NULL) { + pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, + dev->_dma_virt_addr_ch2, + dev->_dma_phys_addr_ch2); + } + + dev->_dma_virt_addr_ch2 = + pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, + &dma_addr); + dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2; + dev->_dma_phys_start_addr_ch2 = dma_addr; + dev->_dma_phys_addr_ch2 = dma_addr; + dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2; + + if (!dev->_dma_virt_addr_ch2) { + printk + ("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); + return -ENOMEM; + } + + //Iniitize at this address until n bytes to 0 + memset(dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2); + + if (dev->_data_buf_virt_addr_ch2 != NULL) { + pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2, + dev->_data_buf_virt_addr_ch2, + dev->_data_buf_phys_addr_ch2); + } + //For Video Data buffer allocation + dev->_data_buf_virt_addr_ch2 = + pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2, + &data_dma_addr); + dev->_data_buf_phys_addr_ch2 = data_dma_addr; + dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2; + + if (!dev->_data_buf_virt_addr_ch2) { + printk + ("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); + return -ENOMEM; + } + + //Initialize at this address until n bytes to 0 + memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2); + + ret = cx25821_openfile_ch2(dev, sram_ch); + if (ret < 0) + return ret; + + //Creating RISC programs + ret = + cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl, + dev->_lines_count_ch2); + if (ret < 0) { + printk(KERN_INFO + "cx25821: Failed creating Video Upstream Risc programs! \n"); + goto error; + } + + return 0; + + error: + return ret; +} + +int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, + u32 status) +{ + u32 int_msk_tmp; + struct sram_channel *channel = &dev->sram_channels[chan_num]; + int singlefield_lines = NTSC_FIELD_HEIGHT; + int line_size_in_bytes = Y422_LINE_SZ; + int odd_risc_prog_size = 0; + dma_addr_t risc_phys_jump_addr; + __le32 *rp; + + if (status & FLD_VID_SRC_RISC1) { + // We should only process one program per call + u32 prog_cnt = cx_read(channel->gpcnt); + + //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers + int_msk_tmp = cx_read(channel->int_msk); + cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); + cx_write(channel->int_stat, _intr_msk); + + spin_lock(&dev->slock); + + dev->_frame_index_ch2 = prog_cnt; + + queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2); + + if (dev->_is_first_frame_ch2) { + dev->_is_first_frame_ch2 = 0; + + if (dev->_isNTSC_ch2) { + singlefield_lines += 1; + odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; + } else { + singlefield_lines = PAL_FIELD_HEIGHT; + odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; + } + + if (dev->_dma_virt_start_addr_ch2 != NULL) { + line_size_in_bytes = + (dev->_pixel_format_ch2 == + PIXEL_FRMT_411) ? Y411_LINE_SZ : + Y422_LINE_SZ; + risc_phys_jump_addr = + dev->_dma_phys_start_addr_ch2 + + odd_risc_prog_size; + + rp = cx25821_update_riscprogram_ch2(dev, + dev-> + _dma_virt_start_addr_ch2, + TOP_OFFSET, + line_size_in_bytes, + 0x0, + singlefield_lines, + FIFO_DISABLE, + ODD_FIELD); + + // Jump to Even Risc program of 1st Frame + *(rp++) = cpu_to_le32(RISC_JUMP); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + } + + spin_unlock(&dev->slock); + } + + if (dev->_file_status_ch2 == END_OF_FILE) { + printk("cx25821: EOF Channel 2 Framecount = %d\n", + dev->_frame_count_ch2); + return -1; + } + //ElSE, set the interrupt mask register, re-enable irq. + int_msk_tmp = cx_read(channel->int_msk); + cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); + + return 0; +} + +static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) +{ + struct cx25821_dev *dev = dev_id; + u32 msk_stat, vid_status; + int handled = 0; + int channel_num = 0; + struct sram_channel *sram_ch; + + if (!dev) + return -1; + + channel_num = VID_UPSTREAM_SRAM_CHANNEL_J; + + sram_ch = &dev->sram_channels[channel_num]; + + msk_stat = cx_read(sram_ch->int_mstat); + vid_status = cx_read(sram_ch->int_stat); + + // Only deal with our interrupt + if (vid_status) { + handled = + cx25821_video_upstream_irq_ch2(dev, channel_num, + vid_status); + } + + if (handled < 0) { + cx25821_stop_upstream_video_ch2(dev); + } else { + handled += handled; + } + + return IRQ_RETVAL(handled); +} + +static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, + struct sram_channel *ch, int pix_format) +{ + int width = WIDTH_D1; + int height = dev->_lines_count_ch2; + int num_lines, odd_num_lines; + u32 value; + int vip_mode = PIXEL_ENGINE_VIP1; + + value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7); + value &= 0xFFFFFFEF; + value |= dev->_isNTSC_ch2 ? 0 : 0x10; + cx_write(ch->vid_fmt_ctl, value); + + // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format + cx_write(ch->vid_active_ctl1, width); + + num_lines = (height / 2) & 0x3FF; + odd_num_lines = num_lines; + + if (dev->_isNTSC_ch2) { + odd_num_lines += 1; + } + + value = (num_lines << 16) | odd_num_lines; + + // set number of active lines in field 0 (top) and field 1 (bottom) + cx_write(ch->vid_active_ctl2, value); + + cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); +} + +int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, + struct sram_channel *sram_ch) +{ + u32 tmp = 0; + int err = 0; + + // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + tmp = cx_read(VID_CH_MODE_SEL); + cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); + + // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. + cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2); + cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ + + /* reset counter */ + cx_write(sram_ch->gpcnt_ctl, 3); + + // Clear our bits from the interrupt status register. + cx_write(sram_ch->int_stat, _intr_msk); + + //Set the interrupt mask register, enable irq. + cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); + tmp = cx_read(sram_ch->int_msk); + cx_write(sram_ch->int_msk, tmp |= _intr_msk); + + err = + request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, + IRQF_SHARED | IRQF_DISABLED, dev->name, dev); + if (err < 0) { + printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, + dev->pci->irq); + goto fail_irq; + } + // Start the DMA engine + tmp = cx_read(sram_ch->dma_ctl); + cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); + + dev->_is_running_ch2 = 1; + dev->_is_first_frame_ch2 = 1; + + return 0; + + fail_irq: + cx25821_dev_unregister(dev); + return err; +} + +int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, + int pixel_format) +{ + struct sram_channel *sram_ch; + u32 tmp; + int retval = 0; + int err = 0; + int data_frame_size = 0; + int risc_buffer_size = 0; + int str_length = 0; + + if (dev->_is_running_ch2) { + printk("Video Channel is still running so return!\n"); + return 0; + } + + dev->_channel2_upstream_select = channel_select; + sram_ch = &dev->sram_channels[channel_select]; + + INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2); + dev->_irq_queues_ch2 = + create_singlethread_workqueue("cx25821_workqueue2"); + + if (!dev->_irq_queues_ch2) { + printk + ("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); + return -ENOMEM; + } + // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + tmp = cx_read(VID_CH_MODE_SEL); + cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); + + dev->_is_running_ch2 = 0; + dev->_frame_count_ch2 = 0; + dev->_file_status_ch2 = RESET_STATUS; + dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576; + dev->_pixel_format_ch2 = pixel_format; + dev->_line_size_ch2 = + (dev->_pixel_format_ch2 == + PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; + data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; + risc_buffer_size = + dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; + + if (dev->input_filename_ch2) { + str_length = strlen(dev->input_filename_ch2); + dev->_filename_ch2 = + (char *)kmalloc(str_length + 1, GFP_KERNEL); + + if (!dev->_filename_ch2) + goto error; + + memcpy(dev->_filename_ch2, dev->input_filename_ch2, + str_length + 1); + } else { + str_length = strlen(dev->_defaultname_ch2); + dev->_filename_ch2 = + (char *)kmalloc(str_length + 1, GFP_KERNEL); + + if (!dev->_filename_ch2) + goto error; + + memcpy(dev->_filename_ch2, dev->_defaultname_ch2, + str_length + 1); + } + + //Default if filename is empty string + if (strcmp(dev->input_filename_ch2, "") == 0) { + if (dev->_isNTSC_ch2) { + dev->_filename_ch2 = + (dev->_pixel_format_ch2 == + PIXEL_FRMT_411) ? "/root/vid411.yuv" : + "/root/vidtest.yuv"; + } else { + dev->_filename_ch2 = + (dev->_pixel_format_ch2 == + PIXEL_FRMT_411) ? "/root/pal411.yuv" : + "/root/pal422.yuv"; + } + } + + retval = + cx25821_sram_channel_setup_upstream(dev, sram_ch, + dev->_line_size_ch2, 0); + + /* setup fifo + format */ + cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2); + + dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2; + dev->upstream_databuf_size_ch2 = data_frame_size * 2; + + //Allocating buffers and prepare RISC program + retval = + cx25821_upstream_buffer_prepare_ch2(dev, sram_ch, + dev->_line_size_ch2); + if (retval < 0) { + printk(KERN_ERR + "%s: Failed to set up Video upstream buffers!\n", + dev->name); + goto error; + } + + cx25821_start_video_dma_upstream_ch2(dev, sram_ch); + + return 0; + + error: + cx25821_dev_unregister(dev); + + return err; +} diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h index 372d4e515..79dfc8759 100644 --- a/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream-ch2.h @@ -1,108 +1,102 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "compat.h" -#include -#include - - -#define OPEN_FILE_1 0 -#define NUM_PROGS 8 -#define NUM_FRAMES 2 -#define ODD_FIELD 0 -#define EVEN_FIELD 1 -#define TOP_OFFSET 0 -#define FIFO_DISABLE 0 -#define FIFO_ENABLE 1 -#define TEST_FRAMES 5 -#define END_OF_FILE 0 -#define IN_PROGRESS 1 -#define RESET_STATUS -1 -#define NUM_NO_OPS 5 - - - -// PAL and NTSC line sizes and number of lines. -#define WIDTH_D1 720 -#define NTSC_LINES_PER_FRAME 480 -#define PAL_LINES_PER_FRAME 576 -#define PAL_LINE_SZ 1440 -#define Y422_LINE_SZ 1440 -#define Y411_LINE_SZ 1080 -#define NTSC_FIELD_HEIGHT 240 -#define NTSC_ODD_FLD_LINES 241 -#define PAL_FIELD_HEIGHT 288 - -#define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) -#define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) -#define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) -#define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) - -#define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) -#define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) - -#define RISC_WRITECR_INSTRUCTION_SIZE 16 -#define RISC_SYNC_INSTRUCTION_SIZE 4 -#define JUMP_INSTRUCTION_SIZE 12 -#define MAXSIZE_NO_OPS 36 -#define DWORD_SIZE 4 - - - -#define USE_RISC_NOOP_VIDEO 1 - -#ifdef USE_RISC_NOOP_VIDEO -#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - -#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) - -#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) - -#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - -#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - -#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) - -#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) -#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) -#endif - - -#ifndef USE_RISC_NOOP_VIDEO -#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) -#define PAL_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE) ) -#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) -#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) -#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) -#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) -#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) -#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) -#endif +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "compat.h" +#include +#include + +#define OPEN_FILE_1 0 +#define NUM_PROGS 8 +#define NUM_FRAMES 2 +#define ODD_FIELD 0 +#define EVEN_FIELD 1 +#define TOP_OFFSET 0 +#define FIFO_DISABLE 0 +#define FIFO_ENABLE 1 +#define TEST_FRAMES 5 +#define END_OF_FILE 0 +#define IN_PROGRESS 1 +#define RESET_STATUS -1 +#define NUM_NO_OPS 5 + +// PAL and NTSC line sizes and number of lines. +#define WIDTH_D1 720 +#define NTSC_LINES_PER_FRAME 480 +#define PAL_LINES_PER_FRAME 576 +#define PAL_LINE_SZ 1440 +#define Y422_LINE_SZ 1440 +#define Y411_LINE_SZ 1080 +#define NTSC_FIELD_HEIGHT 240 +#define NTSC_ODD_FLD_LINES 241 +#define PAL_FIELD_HEIGHT 288 + +#define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) +#define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) +#define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) +#define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) + +#define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) +#define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) + +#define RISC_WRITECR_INSTRUCTION_SIZE 16 +#define RISC_SYNC_INSTRUCTION_SIZE 4 +#define JUMP_INSTRUCTION_SIZE 12 +#define MAXSIZE_NO_OPS 36 +#define DWORD_SIZE 4 + +#define USE_RISC_NOOP_VIDEO 1 + +#ifdef USE_RISC_NOOP_VIDEO +#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ + RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) + +#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) + +#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ + JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) + +#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) +#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) +#endif + +#ifndef USE_RISC_NOOP_VIDEO +#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) +#define PAL_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE) ) +#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) +#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) +#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) +#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) +#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) +#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) +#endif diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream.c b/linux/drivers/staging/cx25821/cx25821-video-upstream.c index 0f7a6c5bb..3d7dd3f66 100644 --- a/linux/drivers/staging/cx25821/cx25821-video-upstream.c +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream.c @@ -1,923 +1,894 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include "cx25821-video.h" -#include "cx25821-video-upstream.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); -MODULE_AUTHOR("Hiep Huynh "); -MODULE_LICENSE("GPL"); - - -static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; - -int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, - struct sram_channel *ch, - unsigned int bpl, u32 risc) -{ - unsigned int i, lines; - u32 cdt; - - - if (ch->cmds_start == 0) { - cx_write(ch->ptr1_reg, 0); - cx_write(ch->ptr2_reg, 0); - cx_write(ch->cnt2_reg, 0); - cx_write(ch->cnt1_reg, 0); - return 0; - } - - bpl = (bpl + 7) & ~7; /* alignment */ - cdt = ch->cdt; - lines = ch->fifo_size / bpl; - - if (lines > 4) - { - lines = 4; - } - - BUG_ON(lines < 2); - - - /* write CDT */ - for (i = 0; i < lines; i++) { - cx_write(cdt + 16*i, ch->fifo_start + bpl*i); - cx_write(cdt + 16*i + 4, 0); - cx_write(cdt + 16*i + 8, 0); - cx_write(cdt + 16*i + 12, 0); - } - - /* write CMDS */ - cx_write(ch->cmds_start + 0, risc); - - cx_write(ch->cmds_start + 4, 0); - cx_write(ch->cmds_start + 8, cdt); - cx_write(ch->cmds_start + 12, (lines*16) >> 3); - cx_write(ch->cmds_start + 16, ch->ctrl_start); - - - cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW); - - for (i = 24; i < 80; i += 4) - cx_write(ch->cmds_start + i, 0); - - /* fill registers */ - cx_write(ch->ptr1_reg, ch->fifo_start); - cx_write(ch->ptr2_reg, cdt); - cx_write(ch->cnt2_reg, (lines*16) >> 3); - cx_write(ch->cnt1_reg, (bpl >> 3) - 1); - - return 0; -} - -static __le32 *cx25821_update_riscprogram( struct cx25821_dev *dev, - __le32 *rp, unsigned int offset, unsigned int bpl, - u32 sync_line, unsigned int lines, int fifo_enable, int field_type) -{ - unsigned int line, i; - int dist_betwn_starts = bpl * 2; - - - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); - - - if( USE_RISC_NOOP_VIDEO ) - { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } - } - - /* scan lines */ - for (line = 0; line < lines; line++) - { - *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) ) - { - offset += dist_betwn_starts; - } - } - - return rp; -} - -static __le32 *cx25821_risc_field_upstream( struct cx25821_dev *dev, __le32 *rp, - dma_addr_t databuf_phys_addr, - unsigned int offset, u32 sync_line, - unsigned int bpl, unsigned int lines, int fifo_enable, int field_type) -{ - unsigned int line, i; - struct sram_channel *sram_ch = &dev->sram_channels[dev->_channel_upstream_select]; - int dist_betwn_starts = bpl * 2; - - - /* sync instruction */ - if (sync_line != NO_SYNC_LINE) - { - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); - } - - - if( USE_RISC_NOOP_VIDEO ) - { - for( i = 0; i < NUM_NO_OPS; i++ ) - { - *(rp++) = cpu_to_le32(RISC_NOOP); - } - } - - /* scan lines */ - for (line = 0; line < lines; line++) - { - *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); - *(rp++) = cpu_to_le32(databuf_phys_addr+offset); - *(rp++) = cpu_to_le32(0); /* bits 63-32 */ - - - if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) ) - { - offset += dist_betwn_starts; //to skip the other field line - } - - - // check if we need to enable the FIFO after the first 4 lines - // For the upstream video channel, the risc engine will enable the FIFO. - if ( fifo_enable && line == 3 ) - { - *(rp++) = RISC_WRITECR; - *(rp++) = sram_ch->dma_ctl; - *(rp++) = FLD_VID_FIFO_EN; - *(rp++) = 0x00000001; - } - } - - return rp; -} - -int cx25821_risc_buffer_upstream( struct cx25821_dev *dev, - struct pci_dev *pci, - unsigned int top_offset, - unsigned int bpl, unsigned int lines) -{ - __le32 *rp; - int fifo_enable = 0; - int singlefield_lines = lines >> 1; //get line count for single field - int odd_num_lines = singlefield_lines; - int frame = 0; - int frame_size = 0; - int databuf_offset = 0; - int risc_program_size = 0; - int risc_flag = RISC_CNT_RESET; - unsigned int bottom_offset = bpl; - dma_addr_t risc_phys_jump_addr; - - if( dev->_isNTSC ) - { - odd_num_lines = singlefield_lines + 1; - risc_program_size = FRAME1_VID_PROG_SIZE; - frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; - } - else - { - risc_program_size = PAL_VID_PROG_SIZE; - frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; - } - - - /* Virtual address of Risc buffer program */ - rp = dev->_dma_virt_addr; - - for( frame = 0; frame < NUM_FRAMES; frame++ ) - { - databuf_offset = frame_size * frame; - - if (UNSET != top_offset) - { - fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; - rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD); - } - - - fifo_enable = FIFO_DISABLE; - - - //Even Field - rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD); - - - if( frame == 0 ) - { - risc_flag = RISC_CNT_RESET; - risc_phys_jump_addr = dev->_dma_phys_start_addr + risc_program_size; - } - else - { - risc_phys_jump_addr = dev->_dma_phys_start_addr; - risc_flag = RISC_CNT_INC; - } - - - // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ - *(rp++) = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - } - - return 0; -} - - -void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) -{ - struct sram_channel *sram_ch = &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_I]; - u32 tmp = 0; - - if( !dev->_is_running ) - { - printk("cx25821: No video file is currently running so return!\n"); - return; - } - - //Disable RISC interrupts - tmp = cx_read( sram_ch->int_msk ); - cx_write( sram_ch->int_msk, tmp & ~_intr_msk); - - //Turn OFF risc and fifo enable - tmp = cx_read( sram_ch->dma_ctl ); - cx_write( sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN) ); - - //Clear data buffer memory - if( dev->_data_buf_virt_addr ) - memset( dev->_data_buf_virt_addr, 0, dev->_data_buf_size ); - - dev->_is_running = 0; - dev->_is_first_frame = 0; - dev->_frame_count = 0; - dev->_file_status = END_OF_FILE; - - if( dev->_irq_queues ) - { - kfree(dev->_irq_queues); - dev->_irq_queues = NULL; - } - - if( dev->_filename != NULL ) - kfree(dev->_filename); - - tmp = cx_read( VID_CH_MODE_SEL ); - cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); -} - -void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev) -{ - if( dev->_is_running ) - { - cx25821_stop_upstream_video_ch1(dev); - } - - if (dev->_dma_virt_addr) - { - pci_free_consistent(dev->pci, dev->_risc_size, dev->_dma_virt_addr, dev->_dma_phys_addr); - dev->_dma_virt_addr = NULL; - } - - if (dev->_data_buf_virt_addr) - { - pci_free_consistent(dev->pci, dev->_data_buf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr); - dev->_data_buf_virt_addr = NULL; - } -} - - -int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch ) -{ - struct file * myfile; - int frame_index_temp = dev->_frame_index; - int i = 0; - int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; - int frame_size = 0; - int frame_offset = 0; - ssize_t vfs_read_retval = 0; - char mybuf[line_size]; - loff_t file_offset; - loff_t pos; - mm_segment_t old_fs; - - - if( dev->_file_status == END_OF_FILE ) - return 0; - - if( dev->_isNTSC ) - { - frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; - } - else - { - frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; - } - - frame_offset = (frame_index_temp > 0) ? frame_size : 0; - file_offset = dev->_frame_count * frame_size; - - - myfile = filp_open( dev->_filename, O_RDONLY | O_LARGEFILE, 0 ); - - - if (IS_ERR(myfile)) - { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno); - return PTR_ERR(myfile); - } - else - { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( i = 0; i < dev->_lines_count; i++ ) - { - pos = file_offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL ) - { - memcpy( (void*)(dev->_data_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval); - } - - file_offset += vfs_read_retval; - frame_offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - dev->_frame_count++; - - dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - - set_fs(old_fs); - filp_close(myfile, NULL); - } - - return 0; -} - -static void cx25821_vidups_handler(struct work_struct *work) -{ - struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _irq_work_entry); - - if( !dev ) - { - printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ ); - return; - } - - cx25821_get_frame( dev, &dev->sram_channels[dev->_channel_upstream_select] ); -} - - -int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) -{ - struct file * myfile; - int i = 0, j = 0; - int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; - ssize_t vfs_read_retval = 0; - char mybuf[line_size]; - loff_t pos; - loff_t offset = (unsigned long)0; - mm_segment_t old_fs; - - - myfile = filp_open( dev->_filename, O_RDONLY | O_LARGEFILE, 0 ); - - - if (IS_ERR(myfile)) - { - const int open_errno = -PTR_ERR(myfile); - printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno); - return PTR_ERR(myfile); - } - else - { - if( !(myfile->f_op) ) - { - printk("%s: File has no file operations registered!", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - - if( !myfile->f_op->read ) - { - printk("%s: File has no READ operations registered! Returning.", __func__); - filp_close(myfile, NULL); - return -EIO; - } - - pos = myfile->f_pos; - old_fs = get_fs(); - set_fs(KERNEL_DS); - - - for( j = 0; j < NUM_FRAMES; j++ ) - { - for( i = 0; i < dev->_lines_count; i++ ) - { - pos = offset; - - vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos); - - if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL ) - { - memcpy( (void*)(dev->_data_buf_virt_addr+offset/4), mybuf, vfs_read_retval); - } - - - offset += vfs_read_retval; - - if( vfs_read_retval < line_size ) - { - printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ ); - break; - } - } - - if( i > 0 ) - dev->_frame_count++; - - if( vfs_read_retval < line_size ) - { - break; - } - } - - - dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; - - set_fs(old_fs); - myfile->f_pos = 0; - filp_close(myfile, NULL); - } - - return 0; -} - - -int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, - struct sram_channel *sram_ch, - int bpl) -{ - int ret = 0; - dma_addr_t dma_addr; - dma_addr_t data_dma_addr; - - if( dev->_dma_virt_addr != NULL ) - { - pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, dev->_dma_virt_addr, dev->_dma_phys_addr); - } - - - dev->_dma_virt_addr = pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size, &dma_addr); - dev->_dma_virt_start_addr = dev->_dma_virt_addr; - dev->_dma_phys_start_addr = dma_addr; - dev->_dma_phys_addr = dma_addr; - dev->_risc_size = dev->upstream_riscbuf_size; - - - if (!dev->_dma_virt_addr) - { - printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); - return -ENOMEM; - } - - - //Clear memory at address - memset( dev->_dma_virt_addr, 0, dev->_risc_size ); - - - if( dev->_data_buf_virt_addr != NULL ) - { - pci_free_consistent(dev->pci, dev->upstream_databuf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr); - } - - //For Video Data buffer allocation - dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci, dev->upstream_databuf_size, &data_dma_addr); - dev->_data_buf_phys_addr = data_dma_addr; - dev->_data_buf_size = dev->upstream_databuf_size; - - if (!dev->_data_buf_virt_addr) - { - printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); - return -ENOMEM; - } - - - //Clear memory at address - memset( dev->_data_buf_virt_addr, 0, dev->_data_buf_size ); - - - ret = cx25821_openfile(dev, sram_ch); - if( ret < 0 ) - return ret; - - - //Create RISC programs - ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, dev->_lines_count ); - if (ret < 0) - { - printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n"); - goto error; - } - - return 0; - -error: - return ret; -} - -int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, u32 status) -{ - u32 int_msk_tmp; - struct sram_channel *channel = &dev->sram_channels[chan_num]; - int singlefield_lines = NTSC_FIELD_HEIGHT; - int line_size_in_bytes = Y422_LINE_SZ; - int odd_risc_prog_size = 0; - dma_addr_t risc_phys_jump_addr; - __le32 * rp; - - - - if (status & FLD_VID_SRC_RISC1) - { - // We should only process one program per call - u32 prog_cnt = cx_read( channel->gpcnt ); - - //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers - int_msk_tmp = cx_read(channel->int_msk); - cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); - cx_write( channel->int_stat, _intr_msk ); - - spin_lock(&dev->slock); - - dev->_frame_index = prog_cnt; - - queue_work(dev->_irq_queues, &dev->_irq_work_entry); - - - if ( dev->_is_first_frame ) - { - dev->_is_first_frame = 0; - - if( dev->_isNTSC ) - { - singlefield_lines += 1; - odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; - } - else - { - singlefield_lines = PAL_FIELD_HEIGHT; - odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; - } - - - if( dev->_dma_virt_start_addr != NULL ) - { - line_size_in_bytes = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; - risc_phys_jump_addr = dev->_dma_phys_start_addr + odd_risc_prog_size; - - rp = cx25821_update_riscprogram(dev, dev->_dma_virt_start_addr, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD); - - // Jump to Even Risc program of 1st Frame - *(rp++) = cpu_to_le32(RISC_JUMP); - *(rp++) = cpu_to_le32(risc_phys_jump_addr); - *(rp++) = cpu_to_le32(0); - } - } - - spin_unlock(&dev->slock); - } - else - { - if(status & FLD_VID_SRC_UF) - printk("%s: Video Received Underflow Error Interrupt!\n", __func__); - - if(status & FLD_VID_SRC_SYNC) - printk("%s: Video Received Sync Error Interrupt!\n", __func__); - - if(status & FLD_VID_SRC_OPC_ERR) - printk("%s: Video Received OpCode Error Interrupt!\n", __func__); - } - - - if( dev->_file_status == END_OF_FILE ) - { - printk("cx25821: EOF Channel 1 Framecount = %d\n", dev->_frame_count ); - return -1; - } - - //ElSE, set the interrupt mask register, re-enable irq. - int_msk_tmp = cx_read( channel->int_msk ); - cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); - - return 0; -} - -static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) -{ - struct cx25821_dev *dev = dev_id; - u32 msk_stat, vid_status; - int handled = 0; - int channel_num = 0; - struct sram_channel *sram_ch; - - - if( !dev ) - return -1; - - channel_num = VID_UPSTREAM_SRAM_CHANNEL_I; - - sram_ch = &dev->sram_channels[channel_num]; - - msk_stat = cx_read(sram_ch->int_mstat); - vid_status = cx_read(sram_ch->int_stat); - - // Only deal with our interrupt - if(vid_status) - { - handled = cx25821_video_upstream_irq(dev, channel_num, vid_status); - } - - if( handled < 0 ) - { - cx25821_stop_upstream_video_ch1(dev); - } - else - { - handled += handled; - } - - return IRQ_RETVAL(handled); -} - - -void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch, int pix_format) -{ - int width = WIDTH_D1; - int height = dev->_lines_count; - int num_lines, odd_num_lines; - u32 value; - int vip_mode = OUTPUT_FRMT_656; - - - value = ( (pix_format & 0x3) << 12 ) | ( vip_mode & 0x7 ); - value &= 0xFFFFFFEF; - value |= dev->_isNTSC ? 0 : 0x10; - cx_write( ch->vid_fmt_ctl, value ); - - - // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format - cx_write( ch->vid_active_ctl1, width ); - - num_lines = (height / 2) & 0x3FF; - odd_num_lines = num_lines; - - if(dev->_isNTSC) - { - odd_num_lines += 1; - } - - value = (num_lines << 16) | odd_num_lines; - - // set number of active lines in field 0 (top) and field 1 (bottom) - cx_write( ch->vid_active_ctl2, value ); - - cx_write( ch->vid_cdt_size, VID_CDT_SIZE >> 3 ); -} - - -int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, - struct sram_channel *sram_ch) -{ - u32 tmp = 0; - int err = 0; - - - // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C - tmp = cx_read( VID_CH_MODE_SEL ); - cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); - - - // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. - cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr); - cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ - - /* reset counter */ - cx_write(sram_ch->gpcnt_ctl, 3); - - // Clear our bits from the interrupt status register. - cx_write( sram_ch->int_stat, _intr_msk ); - - - //Set the interrupt mask register, enable irq. - cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); - tmp = cx_read( sram_ch->int_msk ); - cx_write( sram_ch->int_msk, tmp |= _intr_msk ); - - - err = request_irq(dev->pci->irq, cx25821_upstream_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); - if (err < 0) - { - printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq); - goto fail_irq; - } - - - // Start the DMA engine - tmp = cx_read( sram_ch->dma_ctl ); - cx_set( sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN ); - - dev->_is_running = 1; - dev->_is_first_frame = 1; - - return 0; - -fail_irq: - cx25821_dev_unregister(dev); - return err; -} - - -int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, int pixel_format) -{ - struct sram_channel *sram_ch; - u32 tmp; - int retval = 0; - int err = 0; - int data_frame_size = 0; - int risc_buffer_size = 0; - int str_length = 0; - - - if( dev->_is_running ) - { - printk("Video Channel is still running so return!\n"); - return 0; - } - - - dev->_channel_upstream_select = channel_select; - sram_ch = &dev->sram_channels[channel_select]; - - - INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler); - dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue"); - - if(!dev->_irq_queues) - { - printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); - return -ENOMEM; - } - - // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C - tmp = cx_read( VID_CH_MODE_SEL ); - cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); - - - dev->_is_running = 0; - dev->_frame_count = 0; - dev->_file_status = RESET_STATUS; - dev->_lines_count = dev->_isNTSC ? 480 : 576; - dev->_pixel_format = pixel_format; - dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; - data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; - risc_buffer_size = dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; - - - if( dev->input_filename ) - { - str_length = strlen(dev->input_filename); - dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_filename ) - goto error; - - memcpy(dev->_filename, dev->input_filename, str_length + 1); - } - else - { - str_length = strlen(dev->_defaultname); - dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL); - - if( !dev->_filename ) - goto error; - - memcpy(dev->_filename, dev->_defaultname, str_length + 1); - } - - - //Default if filename is empty string - if( strcmp(dev->input_filename,"") == 0) - { - if( dev->_isNTSC ) - { - dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv"; - } - else - { - dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv"; - } - } - - dev->_is_running = 0; - dev->_frame_count = 0; - dev->_file_status = RESET_STATUS; - dev->_lines_count = dev->_isNTSC ? 480 : 576; - dev->_pixel_format = pixel_format; - dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; - - retval = cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size, 0); - - /* setup fifo + format */ - cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format); - - dev->upstream_riscbuf_size = risc_buffer_size * 2; - dev->upstream_databuf_size = data_frame_size * 2; - - - //Allocating buffers and prepare RISC program - retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size); - if (retval < 0) - { - printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name); - goto error; - } - - - cx25821_start_video_dma_upstream(dev, sram_ch); - - return 0; - -error: - cx25821_dev_unregister(dev); - - return err; -} - +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821-video.h" +#include "cx25821-video-upstream.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); +MODULE_AUTHOR("Hiep Huynh "); +MODULE_LICENSE("GPL"); + +static int _intr_msk = + FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; + +int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, + struct sram_channel *ch, + unsigned int bpl, u32 risc) +{ + unsigned int i, lines; + u32 cdt; + + if (ch->cmds_start == 0) { + cx_write(ch->ptr1_reg, 0); + cx_write(ch->ptr2_reg, 0); + cx_write(ch->cnt2_reg, 0); + cx_write(ch->cnt1_reg, 0); + return 0; + } + + bpl = (bpl + 7) & ~7; /* alignment */ + cdt = ch->cdt; + lines = ch->fifo_size / bpl; + + if (lines > 4) { + lines = 4; + } + + BUG_ON(lines < 2); + + /* write CDT */ + for (i = 0; i < lines; i++) { + cx_write(cdt + 16 * i, ch->fifo_start + bpl * i); + cx_write(cdt + 16 * i + 4, 0); + cx_write(cdt + 16 * i + 8, 0); + cx_write(cdt + 16 * i + 12, 0); + } + + /* write CMDS */ + cx_write(ch->cmds_start + 0, risc); + + cx_write(ch->cmds_start + 4, 0); + cx_write(ch->cmds_start + 8, cdt); + cx_write(ch->cmds_start + 12, (lines * 16) >> 3); + cx_write(ch->cmds_start + 16, ch->ctrl_start); + + cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW); + + for (i = 24; i < 80; i += 4) + cx_write(ch->cmds_start + i, 0); + + /* fill registers */ + cx_write(ch->ptr1_reg, ch->fifo_start); + cx_write(ch->ptr2_reg, cdt); + cx_write(ch->cnt2_reg, (lines * 16) >> 3); + cx_write(ch->cnt1_reg, (bpl >> 3) - 1); + + return 0; +} + +static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev, + __le32 * rp, unsigned int offset, + unsigned int bpl, u32 sync_line, + unsigned int lines, int fifo_enable, + int field_type) +{ + unsigned int line, i; + int dist_betwn_starts = bpl * 2; + + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + + if (USE_RISC_NOOP_VIDEO) { + for (i = 0; i < NUM_NO_OPS; i++) { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + /* scan lines */ + for (line = 0; line < lines; line++) { + *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); + *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr + offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + if ((lines <= NTSC_FIELD_HEIGHT) + || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) { + offset += dist_betwn_starts; + } + } + + return rp; +} + +static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp, + dma_addr_t databuf_phys_addr, + unsigned int offset, u32 sync_line, + unsigned int bpl, unsigned int lines, + int fifo_enable, int field_type) +{ + unsigned int line, i; + struct sram_channel *sram_ch = + &dev->sram_channels[dev->_channel_upstream_select]; + int dist_betwn_starts = bpl * 2; + + /* sync instruction */ + if (sync_line != NO_SYNC_LINE) { + *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); + } + + if (USE_RISC_NOOP_VIDEO) { + for (i = 0; i < NUM_NO_OPS; i++) { + *(rp++) = cpu_to_le32(RISC_NOOP); + } + } + + /* scan lines */ + for (line = 0; line < lines; line++) { + *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); + *(rp++) = cpu_to_le32(databuf_phys_addr + offset); + *(rp++) = cpu_to_le32(0); /* bits 63-32 */ + + if ((lines <= NTSC_FIELD_HEIGHT) + || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) { + offset += dist_betwn_starts; //to skip the other field line + } + + // check if we need to enable the FIFO after the first 4 lines + // For the upstream video channel, the risc engine will enable the FIFO. + if (fifo_enable && line == 3) { + *(rp++) = RISC_WRITECR; + *(rp++) = sram_ch->dma_ctl; + *(rp++) = FLD_VID_FIFO_EN; + *(rp++) = 0x00000001; + } + } + + return rp; +} + +int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, + struct pci_dev *pci, + unsigned int top_offset, + unsigned int bpl, unsigned int lines) +{ + __le32 *rp; + int fifo_enable = 0; + int singlefield_lines = lines >> 1; //get line count for single field + int odd_num_lines = singlefield_lines; + int frame = 0; + int frame_size = 0; + int databuf_offset = 0; + int risc_program_size = 0; + int risc_flag = RISC_CNT_RESET; + unsigned int bottom_offset = bpl; + dma_addr_t risc_phys_jump_addr; + + if (dev->_isNTSC) { + odd_num_lines = singlefield_lines + 1; + risc_program_size = FRAME1_VID_PROG_SIZE; + frame_size = + (bpl == + Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : + FRAME_SIZE_NTSC_Y422; + } else { + risc_program_size = PAL_VID_PROG_SIZE; + frame_size = + (bpl == + Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + } + + /* Virtual address of Risc buffer program */ + rp = dev->_dma_virt_addr; + + for (frame = 0; frame < NUM_FRAMES; frame++) { + databuf_offset = frame_size * frame; + + if (UNSET != top_offset) { + fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; + rp = cx25821_risc_field_upstream(dev, rp, + dev-> + _data_buf_phys_addr + + databuf_offset, + top_offset, 0, bpl, + odd_num_lines, + fifo_enable, + ODD_FIELD); + } + + fifo_enable = FIFO_DISABLE; + + //Even Field + rp = cx25821_risc_field_upstream(dev, rp, + dev->_data_buf_phys_addr + + databuf_offset, bottom_offset, + 0x200, bpl, singlefield_lines, + fifo_enable, EVEN_FIELD); + + if (frame == 0) { + risc_flag = RISC_CNT_RESET; + risc_phys_jump_addr = + dev->_dma_phys_start_addr + risc_program_size; + } else { + risc_phys_jump_addr = dev->_dma_phys_start_addr; + risc_flag = RISC_CNT_INC; + } + + // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ + *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + + return 0; +} + +void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) +{ + struct sram_channel *sram_ch = + &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_I]; + u32 tmp = 0; + + if (!dev->_is_running) { + printk + ("cx25821: No video file is currently running so return!\n"); + return; + } + //Disable RISC interrupts + tmp = cx_read(sram_ch->int_msk); + cx_write(sram_ch->int_msk, tmp & ~_intr_msk); + + //Turn OFF risc and fifo enable + tmp = cx_read(sram_ch->dma_ctl); + cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); + + //Clear data buffer memory + if (dev->_data_buf_virt_addr) + memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size); + + dev->_is_running = 0; + dev->_is_first_frame = 0; + dev->_frame_count = 0; + dev->_file_status = END_OF_FILE; + + if (dev->_irq_queues) { + kfree(dev->_irq_queues); + dev->_irq_queues = NULL; + } + + if (dev->_filename != NULL) + kfree(dev->_filename); + + tmp = cx_read(VID_CH_MODE_SEL); + cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); +} + +void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev) +{ + if (dev->_is_running) { + cx25821_stop_upstream_video_ch1(dev); + } + + if (dev->_dma_virt_addr) { + pci_free_consistent(dev->pci, dev->_risc_size, + dev->_dma_virt_addr, dev->_dma_phys_addr); + dev->_dma_virt_addr = NULL; + } + + if (dev->_data_buf_virt_addr) { + pci_free_consistent(dev->pci, dev->_data_buf_size, + dev->_data_buf_virt_addr, + dev->_data_buf_phys_addr); + dev->_data_buf_virt_addr = NULL; + } +} + +int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) +{ + struct file *myfile; + int frame_index_temp = dev->_frame_index; + int i = 0; + int line_size = + (dev->_pixel_format == + PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + int frame_size = 0; + int frame_offset = 0; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t file_offset; + loff_t pos; + mm_segment_t old_fs; + + if (dev->_file_status == END_OF_FILE) + return 0; + + if (dev->_isNTSC) { + frame_size = + (line_size == + Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : + FRAME_SIZE_NTSC_Y422; + } else { + frame_size = + (line_size == + Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; + } + + frame_offset = (frame_index_temp > 0) ? frame_size : 0; + file_offset = dev->_frame_count * frame_size; + + myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0); + + if (IS_ERR(myfile)) { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", + __func__, dev->_filename, open_errno); + return PTR_ERR(myfile); + } else { + if (!(myfile->f_op)) { + printk("%s: File has no file operations registered!", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + if (!myfile->f_op->read) { + printk("%s: File has no READ operations registered!", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + for (i = 0; i < dev->_lines_count; i++) { + pos = file_offset; + + vfs_read_retval = + vfs_read(myfile, mybuf, line_size, &pos); + + if (vfs_read_retval > 0 && vfs_read_retval == line_size + && dev->_data_buf_virt_addr != NULL) { + memcpy((void *)(dev->_data_buf_virt_addr + + frame_offset / 4), mybuf, + vfs_read_retval); + } + + file_offset += vfs_read_retval; + frame_offset += vfs_read_retval; + + if (vfs_read_retval < line_size) { + printk(KERN_INFO + "Done: exit %s() since no more bytes to read from Video file.\n", + __func__); + break; + } + } + + if (i > 0) + dev->_frame_count++; + + dev->_file_status = + (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + filp_close(myfile, NULL); + } + + return 0; +} + +static void cx25821_vidups_handler(struct work_struct *work) +{ + struct cx25821_dev *dev = + container_of(work, struct cx25821_dev, _irq_work_entry); + + if (!dev) { + printk("ERROR %s(): since container_of(work_struct) FAILED! \n", + __func__); + return; + } + + cx25821_get_frame(dev, + &dev->sram_channels[dev->_channel_upstream_select]); +} + +int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) +{ + struct file *myfile; + int i = 0, j = 0; + int line_size = + (dev->_pixel_format == + PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; + ssize_t vfs_read_retval = 0; + char mybuf[line_size]; + loff_t pos; + loff_t offset = (unsigned long)0; + mm_segment_t old_fs; + + myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0); + + if (IS_ERR(myfile)) { + const int open_errno = -PTR_ERR(myfile); + printk("%s(): ERROR opening file(%s) with errno = %d! \n", + __func__, dev->_filename, open_errno); + return PTR_ERR(myfile); + } else { + if (!(myfile->f_op)) { + printk("%s: File has no file operations registered!", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + if (!myfile->f_op->read) { + printk + ("%s: File has no READ operations registered! Returning.", + __func__); + filp_close(myfile, NULL); + return -EIO; + } + + pos = myfile->f_pos; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + for (j = 0; j < NUM_FRAMES; j++) { + for (i = 0; i < dev->_lines_count; i++) { + pos = offset; + + vfs_read_retval = + vfs_read(myfile, mybuf, line_size, &pos); + + if (vfs_read_retval > 0 + && vfs_read_retval == line_size + && dev->_data_buf_virt_addr != NULL) { + memcpy((void *)(dev-> + _data_buf_virt_addr + + offset / 4), mybuf, + vfs_read_retval); + } + + offset += vfs_read_retval; + + if (vfs_read_retval < line_size) { + printk(KERN_INFO + "Done: exit %s() since no more bytes to read from Video file.\n", + __func__); + break; + } + } + + if (i > 0) + dev->_frame_count++; + + if (vfs_read_retval < line_size) { + break; + } + } + + dev->_file_status = + (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; + + set_fs(old_fs); + myfile->f_pos = 0; + filp_close(myfile, NULL); + } + + return 0; +} + +int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, + struct sram_channel *sram_ch, int bpl) +{ + int ret = 0; + dma_addr_t dma_addr; + dma_addr_t data_dma_addr; + + if (dev->_dma_virt_addr != NULL) { + pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, + dev->_dma_virt_addr, dev->_dma_phys_addr); + } + + dev->_dma_virt_addr = + pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size, + &dma_addr); + dev->_dma_virt_start_addr = dev->_dma_virt_addr; + dev->_dma_phys_start_addr = dma_addr; + dev->_dma_phys_addr = dma_addr; + dev->_risc_size = dev->upstream_riscbuf_size; + + if (!dev->_dma_virt_addr) { + printk + ("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n"); + return -ENOMEM; + } + + //Clear memory at address + memset(dev->_dma_virt_addr, 0, dev->_risc_size); + + if (dev->_data_buf_virt_addr != NULL) { + pci_free_consistent(dev->pci, dev->upstream_databuf_size, + dev->_data_buf_virt_addr, + dev->_data_buf_phys_addr); + } + //For Video Data buffer allocation + dev->_data_buf_virt_addr = + pci_alloc_consistent(dev->pci, dev->upstream_databuf_size, + &data_dma_addr); + dev->_data_buf_phys_addr = data_dma_addr; + dev->_data_buf_size = dev->upstream_databuf_size; + + if (!dev->_data_buf_virt_addr) { + printk + ("cx25821: FAILED to allocate memory for data buffer! Returning.\n"); + return -ENOMEM; + } + + //Clear memory at address + memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size); + + ret = cx25821_openfile(dev, sram_ch); + if (ret < 0) + return ret; + + //Create RISC programs + ret = + cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, + dev->_lines_count); + if (ret < 0) { + printk(KERN_INFO + "cx25821: Failed creating Video Upstream Risc programs! \n"); + goto error; + } + + return 0; + + error: + return ret; +} + +int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, + u32 status) +{ + u32 int_msk_tmp; + struct sram_channel *channel = &dev->sram_channels[chan_num]; + int singlefield_lines = NTSC_FIELD_HEIGHT; + int line_size_in_bytes = Y422_LINE_SZ; + int odd_risc_prog_size = 0; + dma_addr_t risc_phys_jump_addr; + __le32 *rp; + + if (status & FLD_VID_SRC_RISC1) { + // We should only process one program per call + u32 prog_cnt = cx_read(channel->gpcnt); + + //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers + int_msk_tmp = cx_read(channel->int_msk); + cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); + cx_write(channel->int_stat, _intr_msk); + + spin_lock(&dev->slock); + + dev->_frame_index = prog_cnt; + + queue_work(dev->_irq_queues, &dev->_irq_work_entry); + + if (dev->_is_first_frame) { + dev->_is_first_frame = 0; + + if (dev->_isNTSC) { + singlefield_lines += 1; + odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; + } else { + singlefield_lines = PAL_FIELD_HEIGHT; + odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; + } + + if (dev->_dma_virt_start_addr != NULL) { + line_size_in_bytes = + (dev->_pixel_format == + PIXEL_FRMT_411) ? Y411_LINE_SZ : + Y422_LINE_SZ; + risc_phys_jump_addr = + dev->_dma_phys_start_addr + + odd_risc_prog_size; + + rp = cx25821_update_riscprogram(dev, + dev-> + _dma_virt_start_addr, + TOP_OFFSET, + line_size_in_bytes, + 0x0, + singlefield_lines, + FIFO_DISABLE, + ODD_FIELD); + + // Jump to Even Risc program of 1st Frame + *(rp++) = cpu_to_le32(RISC_JUMP); + *(rp++) = cpu_to_le32(risc_phys_jump_addr); + *(rp++) = cpu_to_le32(0); + } + } + + spin_unlock(&dev->slock); + } else { + if (status & FLD_VID_SRC_UF) + printk + ("%s: Video Received Underflow Error Interrupt!\n", + __func__); + + if (status & FLD_VID_SRC_SYNC) + printk("%s: Video Received Sync Error Interrupt!\n", + __func__); + + if (status & FLD_VID_SRC_OPC_ERR) + printk("%s: Video Received OpCode Error Interrupt!\n", + __func__); + } + + if (dev->_file_status == END_OF_FILE) { + printk("cx25821: EOF Channel 1 Framecount = %d\n", + dev->_frame_count); + return -1; + } + //ElSE, set the interrupt mask register, re-enable irq. + int_msk_tmp = cx_read(channel->int_msk); + cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); + + return 0; +} + +static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) +{ + struct cx25821_dev *dev = dev_id; + u32 msk_stat, vid_status; + int handled = 0; + int channel_num = 0; + struct sram_channel *sram_ch; + + if (!dev) + return -1; + + channel_num = VID_UPSTREAM_SRAM_CHANNEL_I; + + sram_ch = &dev->sram_channels[channel_num]; + + msk_stat = cx_read(sram_ch->int_mstat); + vid_status = cx_read(sram_ch->int_stat); + + // Only deal with our interrupt + if (vid_status) { + handled = + cx25821_video_upstream_irq(dev, channel_num, vid_status); + } + + if (handled < 0) { + cx25821_stop_upstream_video_ch1(dev); + } else { + handled += handled; + } + + return IRQ_RETVAL(handled); +} + +void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch, + int pix_format) +{ + int width = WIDTH_D1; + int height = dev->_lines_count; + int num_lines, odd_num_lines; + u32 value; + int vip_mode = OUTPUT_FRMT_656; + + value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7); + value &= 0xFFFFFFEF; + value |= dev->_isNTSC ? 0 : 0x10; + cx_write(ch->vid_fmt_ctl, value); + + // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format + cx_write(ch->vid_active_ctl1, width); + + num_lines = (height / 2) & 0x3FF; + odd_num_lines = num_lines; + + if (dev->_isNTSC) { + odd_num_lines += 1; + } + + value = (num_lines << 16) | odd_num_lines; + + // set number of active lines in field 0 (top) and field 1 (bottom) + cx_write(ch->vid_active_ctl2, value); + + cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); +} + +int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, + struct sram_channel *sram_ch) +{ + u32 tmp = 0; + int err = 0; + + // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + tmp = cx_read(VID_CH_MODE_SEL); + cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); + + // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds. + cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr); + cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ + + /* reset counter */ + cx_write(sram_ch->gpcnt_ctl, 3); + + // Clear our bits from the interrupt status register. + cx_write(sram_ch->int_stat, _intr_msk); + + //Set the interrupt mask register, enable irq. + cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); + tmp = cx_read(sram_ch->int_msk); + cx_write(sram_ch->int_msk, tmp |= _intr_msk); + + err = + request_irq(dev->pci->irq, cx25821_upstream_irq, + IRQF_SHARED | IRQF_DISABLED, dev->name, dev); + if (err < 0) { + printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, + dev->pci->irq); + goto fail_irq; + } + + // Start the DMA engine + tmp = cx_read(sram_ch->dma_ctl); + cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); + + dev->_is_running = 1; + dev->_is_first_frame = 1; + + return 0; + + fail_irq: + cx25821_dev_unregister(dev); + return err; +} + +int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, + int pixel_format) +{ + struct sram_channel *sram_ch; + u32 tmp; + int retval = 0; + int err = 0; + int data_frame_size = 0; + int risc_buffer_size = 0; + int str_length = 0; + + if (dev->_is_running) { + printk("Video Channel is still running so return!\n"); + return 0; + } + + dev->_channel_upstream_select = channel_select; + sram_ch = &dev->sram_channels[channel_select]; + + INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler); + dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue"); + + if (!dev->_irq_queues) { + printk + ("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); + return -ENOMEM; + } + // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C + tmp = cx_read(VID_CH_MODE_SEL); + cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); + + dev->_is_running = 0; + dev->_frame_count = 0; + dev->_file_status = RESET_STATUS; + dev->_lines_count = dev->_isNTSC ? 480 : 576; + dev->_pixel_format = pixel_format; + dev->_line_size = + (dev->_pixel_format == + PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; + data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; + risc_buffer_size = + dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; + + if (dev->input_filename) { + str_length = strlen(dev->input_filename); + dev->_filename = (char *)kmalloc(str_length + 1, GFP_KERNEL); + + if (!dev->_filename) + goto error; + + memcpy(dev->_filename, dev->input_filename, str_length + 1); + } else { + str_length = strlen(dev->_defaultname); + dev->_filename = (char *)kmalloc(str_length + 1, GFP_KERNEL); + + if (!dev->_filename) + goto error; + + memcpy(dev->_filename, dev->_defaultname, str_length + 1); + } + + //Default if filename is empty string + if (strcmp(dev->input_filename, "") == 0) { + if (dev->_isNTSC) { + dev->_filename = + (dev->_pixel_format == + PIXEL_FRMT_411) ? "/root/vid411.yuv" : + "/root/vidtest.yuv"; + } else { + dev->_filename = + (dev->_pixel_format == + PIXEL_FRMT_411) ? "/root/pal411.yuv" : + "/root/pal422.yuv"; + } + } + + dev->_is_running = 0; + dev->_frame_count = 0; + dev->_file_status = RESET_STATUS; + dev->_lines_count = dev->_isNTSC ? 480 : 576; + dev->_pixel_format = pixel_format; + dev->_line_size = + (dev->_pixel_format == + PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; + + retval = + cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size, + 0); + + /* setup fifo + format */ + cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format); + + dev->upstream_riscbuf_size = risc_buffer_size * 2; + dev->upstream_databuf_size = data_frame_size * 2; + + //Allocating buffers and prepare RISC program + retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size); + if (retval < 0) { + printk(KERN_ERR + "%s: Failed to set up Video upstream buffers!\n", + dev->name); + goto error; + } + + cx25821_start_video_dma_upstream(dev, sram_ch); + + return 0; + + error: + cx25821_dev_unregister(dev); + + return err; +} diff --git a/linux/drivers/staging/cx25821/cx25821-video-upstream.h b/linux/drivers/staging/cx25821/cx25821-video-upstream.h index 71c3dfb39..eb8c59796 100644 --- a/linux/drivers/staging/cx25821/cx25821-video-upstream.h +++ b/linux/drivers/staging/cx25821/cx25821-video-upstream.h @@ -1,114 +1,110 @@ -/* - * Driver for the Conexant CX25821 PCIe bridge - * - * Copyright (C) 2009 Conexant Systems Inc. - * Authors , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "compat.h" -#include -#include - -#define OUTPUT_FRMT_656 0 -#define OPEN_FILE_1 0 -#define NUM_PROGS 8 -#define NUM_FRAMES 2 -#define ODD_FIELD 0 -#define EVEN_FIELD 1 -#define TOP_OFFSET 0 -#define FIFO_DISABLE 0 -#define FIFO_ENABLE 1 -#define TEST_FRAMES 5 -#define END_OF_FILE 0 -#define IN_PROGRESS 1 -#define RESET_STATUS -1 -#define NUM_NO_OPS 5 - - - -// PAL and NTSC line sizes and number of lines. -#define WIDTH_D1 720 -#define NTSC_LINES_PER_FRAME 480 -#define PAL_LINES_PER_FRAME 576 -#define PAL_LINE_SZ 1440 -#define Y422_LINE_SZ 1440 -#define Y411_LINE_SZ 1080 -#define NTSC_FIELD_HEIGHT 240 -#define NTSC_ODD_FLD_LINES 241 -#define PAL_FIELD_HEIGHT 288 - -#define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) -#define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) -#define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) -#define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) - -#define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) -#define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) - -#define RISC_WRITECR_INSTRUCTION_SIZE 16 -#define RISC_SYNC_INSTRUCTION_SIZE 4 -#define JUMP_INSTRUCTION_SIZE 12 -#define MAXSIZE_NO_OPS 36 -#define DWORD_SIZE 4 - - -#define USE_RISC_NOOP_VIDEO 1 - -#ifdef USE_RISC_NOOP_VIDEO -#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - -#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) - -#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) - -#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - -#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - -#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) - -#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) - -#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) - -#endif - - -#ifndef USE_RISC_NOOP_VIDEO -#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ - RISC_SYNC_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) - -#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) - -#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) - -#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) -#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) - -#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) -#define NTSC_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) -#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ - RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) -#endif +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "compat.h" +#include +#include + +#define OUTPUT_FRMT_656 0 +#define OPEN_FILE_1 0 +#define NUM_PROGS 8 +#define NUM_FRAMES 2 +#define ODD_FIELD 0 +#define EVEN_FIELD 1 +#define TOP_OFFSET 0 +#define FIFO_DISABLE 0 +#define FIFO_ENABLE 1 +#define TEST_FRAMES 5 +#define END_OF_FILE 0 +#define IN_PROGRESS 1 +#define RESET_STATUS -1 +#define NUM_NO_OPS 5 + +// PAL and NTSC line sizes and number of lines. +#define WIDTH_D1 720 +#define NTSC_LINES_PER_FRAME 480 +#define PAL_LINES_PER_FRAME 576 +#define PAL_LINE_SZ 1440 +#define Y422_LINE_SZ 1440 +#define Y411_LINE_SZ 1080 +#define NTSC_FIELD_HEIGHT 240 +#define NTSC_ODD_FLD_LINES 241 +#define PAL_FIELD_HEIGHT 288 + +#define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) +#define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) +#define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) +#define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) + +#define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) +#define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) + +#define RISC_WRITECR_INSTRUCTION_SIZE 16 +#define RISC_SYNC_INSTRUCTION_SIZE 4 +#define JUMP_INSTRUCTION_SIZE 12 +#define MAXSIZE_NO_OPS 36 +#define DWORD_SIZE 4 + +#define USE_RISC_NOOP_VIDEO 1 + +#ifdef USE_RISC_NOOP_VIDEO +#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ + RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) + +#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) + +#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ + JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) + +#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) + +#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) + +#endif + +#ifndef USE_RISC_NOOP_VIDEO +#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ + RISC_SYNC_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) + +#define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) + +#define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) + +#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) +#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) + +#define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) +#define NTSC_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) +#define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) +#endif diff --git a/linux/drivers/staging/cx25821/cx25821-video.c b/linux/drivers/staging/cx25821/cx25821-video.c index ba8115b6e..938635313 100644 --- a/linux/drivers/staging/cx25821/cx25821-video.c +++ b/linux/drivers/staging/cx25821/cx25821-video.c @@ -27,8 +27,8 @@ MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); MODULE_AUTHOR("Steven Toth "); MODULE_LICENSE("GPL"); -static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; -static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; +static unsigned int video_nr[] = {[0...(CX25821_MAXBOARDS - 1)] = UNSET }; +static unsigned int radio_nr[] = {[0...(CX25821_MAXBOARDS - 1)] = UNSET }; module_param_array(video_nr, int, NULL, 0444); module_param_array(radio_nr, int, NULL, 0444); @@ -36,7 +36,7 @@ module_param_array(radio_nr, int, NULL, 0444); MODULE_PARM_DESC(video_nr, "video device numbers"); MODULE_PARM_DESC(radio_nr, "radio device numbers"); -static unsigned int video_debug=VIDEO_DEBUG; +static unsigned int video_debug = VIDEO_DEBUG; module_param(video_debug, int, 0644); MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); @@ -53,147 +53,143 @@ static void init_controls(struct cx25821_dev *dev, int chan_num); #define FORMAT_FLAGS_PACKED 0x01 struct cx25821_fmt formats[] = { - { - .name = "8 bpp, gray", - .fourcc = V4L2_PIX_FMT_GREY, - .depth = 8, - .flags = FORMAT_FLAGS_PACKED, - }, { - .name = "4:1:1, packed, Y41P", - .fourcc = V4L2_PIX_FMT_Y41P, - .depth = 12, - .flags = FORMAT_FLAGS_PACKED, - }, { - .name = "4:2:2, packed, YUYV", - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - }, { - .name = "4:2:2, packed, UYVY", - .fourcc = V4L2_PIX_FMT_UYVY, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "4:2:0, YUV", - .fourcc = V4L2_PIX_FMT_YUV420, - .depth = 12, - .flags = FORMAT_FLAGS_PACKED, - }, + { + .name = "8 bpp, gray", + .fourcc = V4L2_PIX_FMT_GREY, + .depth = 8, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "4:1:1, packed, Y41P", + .fourcc = V4L2_PIX_FMT_Y41P, + .depth = 12, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "4:2:2, packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "4:2:2, packed, UYVY", + .fourcc = V4L2_PIX_FMT_UYVY, + .depth = 16, + .flags = FORMAT_FLAGS_PACKED, + }, { + .name = "4:2:0, YUV", + .fourcc = V4L2_PIX_FMT_YUV420, + .depth = 12, + .flags = FORMAT_FLAGS_PACKED, + }, }; - int get_format_size(void) { - return ARRAY_SIZE(formats); + return ARRAY_SIZE(formats); } - struct cx25821_fmt *format_by_fourcc(unsigned int fourcc) { - unsigned int i; + unsigned int i; - if( fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P ) - { - return formats+1; - } + if (fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P) { + return formats + 1; + } - for (i = 0; i < ARRAY_SIZE(formats); i++) - if (formats[i].fourcc == fourcc) - return formats+i; + for (i = 0; i < ARRAY_SIZE(formats); i++) + if (formats[i].fourcc == fourcc) + return formats + i; - printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc); - return NULL; + printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc); + return NULL; } void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q) { - struct cx25821_buffer *buf; - struct list_head *item; - dprintk(1, "%s()\n", __func__); + struct cx25821_buffer *buf; + struct list_head *item; + dprintk(1, "%s()\n", __func__); - if (!list_empty(&q->active)) { - list_for_each(item, &q->active) - buf = list_entry(item, struct cx25821_buffer, vb.queue); - } + if (!list_empty(&q->active)) { + list_for_each(item, &q->active) + buf = list_entry(item, struct cx25821_buffer, vb.queue); + } - if (!list_empty(&q->queued)) - { - list_for_each(item, &q->queued) - buf = list_entry(item, struct cx25821_buffer, vb.queue); - } + if (!list_empty(&q->queued)) { + list_for_each(item, &q->queued) + buf = list_entry(item, struct cx25821_buffer, vb.queue); + } } - -void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, u32 count) +void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, + u32 count) { - struct cx25821_buffer *buf; - int bc; + struct cx25821_buffer *buf; + int bc; - for (bc = 0;; bc++) { - if (list_empty(&q->active)) - { - dprintk(1, "bc=%d (=0: active empty)\n", bc); - break; - } + for (bc = 0;; bc++) { + if (list_empty(&q->active)) { + dprintk(1, "bc=%d (=0: active empty)\n", bc); + break; + } - buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); + buf = + list_entry(q->active.next, struct cx25821_buffer, vb.queue); - /* count comes from the hw and it is 16bit wide -- - * this trick handles wrap-arounds correctly for - * up to 32767 buffers in flight... */ - if ((s16) (count - buf->count) < 0) - { - break; - } + /* count comes from the hw and it is 16bit wide -- + * this trick handles wrap-arounds correctly for + * up to 32767 buffers in flight... */ + if ((s16) (count - buf->count) < 0) { + break; + } - do_gettimeofday(&buf->vb.ts); - buf->vb.state = VIDEOBUF_DONE; - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); - } + do_gettimeofday(&buf->vb.ts); + buf->vb.state = VIDEOBUF_DONE; + list_del(&buf->vb.queue); + wake_up(&buf->vb.done); + } - if (list_empty(&q->active)) - del_timer(&q->timeout); - else - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - if (bc != 1) - printk(KERN_ERR "%s: %d buffers handled (should be 1)\n", __func__, bc); + if (list_empty(&q->active)) + del_timer(&q->timeout); + else + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + if (bc != 1) + printk(KERN_ERR "%s: %d buffers handled (should be 1)\n", + __func__, bc); } #ifdef TUNER_FLAG int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm) { - dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__, - (unsigned int)norm, - v4l2_norm_to_name(norm)); + dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__, + (unsigned int)norm, v4l2_norm_to_name(norm)); - dev->tvnorm = norm; + dev->tvnorm = norm; - /* Tell the internal A/V decoder */ - cx25821_call_all(dev, core, s_std, norm); + /* Tell the internal A/V decoder */ + cx25821_call_all(dev, core, s_std, norm); - return 0; + return 0; } #endif struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, - struct pci_dev *pci, - struct video_device *template, - char *type) + struct pci_dev *pci, + struct video_device *template, + char *type) { - struct video_device *vfd; - dprintk(1, "%s()\n", __func__); - - vfd = video_device_alloc(); - if (NULL == vfd) - return NULL; - *vfd = *template; - vfd->minor = -1; - vfd->v4l2_dev = &dev->v4l2_dev; - vfd->release = video_device_release; - snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, cx25821_boards[dev->board].name); - return vfd; + struct video_device *vfd; + dprintk(1, "%s()\n", __func__); + + vfd = video_device_alloc(); + if (NULL == vfd) + return NULL; + *vfd = *template; + vfd->minor = -1; + vfd->v4l2_dev = &dev->v4l2_dev; + vfd->release = video_device_release; + snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, + cx25821_boards[dev->board].name); + return vfd; } /* @@ -218,615 +214,609 @@ static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) // resource management int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit) { - dprintk(1, "%s()\n", __func__); - if (fh->resources & bit) - /* have it already allocated */ - return 1; - - /* is it free? */ - mutex_lock(&dev->lock); - if (dev->resources & bit) { - /* no, someone else uses it */ + dprintk(1, "%s()\n", __func__); + if (fh->resources & bit) + /* have it already allocated */ + return 1; + + /* is it free? */ + mutex_lock(&dev->lock); + if (dev->resources & bit) { + /* no, someone else uses it */ + mutex_unlock(&dev->lock); + return 0; + } + /* it's free, grab it */ + fh->resources |= bit; + dev->resources |= bit; + dprintk(1, "res: get %d\n", bit); mutex_unlock(&dev->lock); - return 0; - } - /* it's free, grab it */ - fh->resources |= bit; - dev->resources |= bit; - dprintk(1, "res: get %d\n", bit); - mutex_unlock(&dev->lock); - return 1; + return 1; } int res_check(struct cx25821_fh *fh, unsigned int bit) { - return fh->resources & bit; + return fh->resources & bit; } int res_locked(struct cx25821_dev *dev, unsigned int bit) { - return dev->resources & bit; + return dev->resources & bit; } void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits) { - BUG_ON((fh->resources & bits) != bits); - dprintk(1, "%s()\n", __func__); - - mutex_lock(&dev->lock); - fh->resources &= ~bits; - dev->resources &= ~bits; - dprintk(1, "res: put %d\n", bits); - mutex_unlock(&dev->lock); + BUG_ON((fh->resources & bits) != bits); + dprintk(1, "%s()\n", __func__); + + mutex_lock(&dev->lock); + fh->resources &= ~bits; + dev->resources &= ~bits; + dprintk(1, "res: put %d\n", bits); + mutex_unlock(&dev->lock); } int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input) { - struct v4l2_routing route; - memset(&route, 0, sizeof(route)); + struct v4l2_routing route; + memset(&route, 0, sizeof(route)); - dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", __func__, - input, INPUT(input)->vmux, - INPUT(input)->gpio0, INPUT(input)->gpio1, - INPUT(input)->gpio2, INPUT(input)->gpio3); - dev->input = input; + dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", + __func__, input, INPUT(input)->vmux, INPUT(input)->gpio0, + INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3); + dev->input = input; - route.input = INPUT(input)->vmux; + route.input = INPUT(input)->vmux; - /* Tell the internal A/V decoder */ - cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0); + /* Tell the internal A/V decoder */ + cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0); - return 0; + return 0; } int cx25821_start_video_dma(struct cx25821_dev *dev, - struct cx25821_dmaqueue *q, - struct cx25821_buffer *buf, - struct sram_channel *channel) + struct cx25821_dmaqueue *q, + struct cx25821_buffer *buf, + struct sram_channel *channel) { - int tmp = 0; + int tmp = 0; - /* setup fifo + format */ - cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma); + /* setup fifo + format */ + cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma); - /* reset counter */ - cx_write(channel->gpcnt_ctl, 3); - q->count = 1; + /* reset counter */ + cx_write(channel->gpcnt_ctl, 3); + q->count = 1; - /* enable irq */ - cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1<i)); - cx_set(channel->int_msk, 0x11); + /* enable irq */ + cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i)); + cx_set(channel->int_msk, 0x11); - /* start dma */ - cx_write(channel->dma_ctl, 0x11); /* FIFO and RISC enable */ + /* start dma */ + cx_write(channel->dma_ctl, 0x11); /* FIFO and RISC enable */ - /* make sure upstream setting if any is reversed */ - tmp = cx_read( VID_CH_MODE_SEL ); - cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00); + /* make sure upstream setting if any is reversed */ + tmp = cx_read(VID_CH_MODE_SEL); + cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); - return 0; + return 0; } - -int cx25821_restart_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, struct sram_channel *channel) +int cx25821_restart_video_queue(struct cx25821_dev *dev, + struct cx25821_dmaqueue *q, + struct sram_channel *channel) { - struct cx25821_buffer *buf, *prev; - struct list_head *item; + struct cx25821_buffer *buf, *prev; + struct list_head *item; - if (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); + if (!list_empty(&q->active)) { + buf = + list_entry(q->active.next, struct cx25821_buffer, vb.queue); - cx25821_start_video_dma(dev, q, buf, channel); + cx25821_start_video_dma(dev, q, buf, channel); - list_for_each(item, &q->active) { - buf = list_entry(item, struct cx25821_buffer, vb.queue); - buf->count = q->count++; - } + list_for_each(item, &q->active) { + buf = list_entry(item, struct cx25821_buffer, vb.queue); + buf->count = q->count++; + } - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - return 0; - } + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + return 0; + } - prev = NULL; - for (;;) { - if (list_empty(&q->queued)) - return 0; - - buf = list_entry(q->queued.next, struct cx25821_buffer, vb.queue); - - if (NULL == prev) { - list_move_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, channel); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - } else if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_move_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */ - } else { - return 0; + prev = NULL; + for (;;) { + if (list_empty(&q->queued)) + return 0; + + buf = + list_entry(q->queued.next, struct cx25821_buffer, vb.queue); + + if (NULL == prev) { + list_move_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, channel); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + } else if (prev->vb.width == buf->vb.width && + prev->vb.height == buf->vb.height && + prev->fmt == buf->fmt) { + list_move_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */ + } else { + return 0; + } + prev = buf; } - prev = buf; - } } void cx25821_vid_timeout(unsigned long data) { - struct cx25821_data *timeout_data = (struct cx25821_data *)data; - struct cx25821_dev *dev = timeout_data->dev; - struct sram_channel *channel = timeout_data->channel; - struct cx25821_dmaqueue *q = &dev->vidq[channel->i]; - struct cx25821_buffer *buf; - unsigned long flags; - - //cx25821_sram_channel_dump(dev, channel); - cx_clear(channel->dma_ctl, 0x11); - - spin_lock_irqsave(&dev->slock, flags); - while (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue); - list_del(&buf->vb.queue); - - buf->vb.state = VIDEOBUF_ERROR; - wake_up(&buf->vb.done); - } + struct cx25821_data *timeout_data = (struct cx25821_data *)data; + struct cx25821_dev *dev = timeout_data->dev; + struct sram_channel *channel = timeout_data->channel; + struct cx25821_dmaqueue *q = &dev->vidq[channel->i]; + struct cx25821_buffer *buf; + unsigned long flags; + + //cx25821_sram_channel_dump(dev, channel); + cx_clear(channel->dma_ctl, 0x11); + + spin_lock_irqsave(&dev->slock, flags); + while (!list_empty(&q->active)) { + buf = + list_entry(q->active.next, struct cx25821_buffer, vb.queue); + list_del(&buf->vb.queue); - cx25821_restart_video_queue(dev, q, channel); - spin_unlock_irqrestore(&dev->slock, flags); + buf->vb.state = VIDEOBUF_ERROR; + wake_up(&buf->vb.done); + } + + cx25821_restart_video_queue(dev, q, channel); + spin_unlock_irqrestore(&dev->slock, flags); } int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) { - u32 count=0; - int handled = 0; - u32 mask; - struct sram_channel *channel = &dev->sram_channels[chan_num]; - - mask = cx_read(channel->int_msk); - if (0 == (status & mask)) - return handled; - - cx_write(channel->int_stat, status); - - /* risc op code error */ - if (status & (1 << 16)) { - printk(KERN_WARNING "%s, %s: video risc op code error\n", dev->name, channel->name); - cx_clear(channel->dma_ctl, 0x11); - cx25821_sram_channel_dump(dev, channel); - } + u32 count = 0; + int handled = 0; + u32 mask; + struct sram_channel *channel = &dev->sram_channels[chan_num]; + + mask = cx_read(channel->int_msk); + if (0 == (status & mask)) + return handled; + + cx_write(channel->int_stat, status); + + /* risc op code error */ + if (status & (1 << 16)) { + printk(KERN_WARNING "%s, %s: video risc op code error\n", + dev->name, channel->name); + cx_clear(channel->dma_ctl, 0x11); + cx25821_sram_channel_dump(dev, channel); + } - /* risc1 y */ - if (status & FLD_VID_DST_RISC1) { - spin_lock(&dev->slock); - count = cx_read(channel->gpcnt); - cx25821_video_wakeup(dev, &dev->vidq[channel->i], count); - spin_unlock(&dev->slock); - handled++; - } + /* risc1 y */ + if (status & FLD_VID_DST_RISC1) { + spin_lock(&dev->slock); + count = cx_read(channel->gpcnt); + cx25821_video_wakeup(dev, &dev->vidq[channel->i], count); + spin_unlock(&dev->slock); + handled++; + } - /* risc2 y */ - if (status & 0x10) { - dprintk(2, "stopper video\n"); - spin_lock(&dev->slock); - cx25821_restart_video_queue(dev, &dev->vidq[channel->i], channel); - spin_unlock(&dev->slock); - handled++; - } - return handled; + /* risc2 y */ + if (status & 0x10) { + dprintk(2, "stopper video\n"); + spin_lock(&dev->slock); + cx25821_restart_video_queue(dev, &dev->vidq[channel->i], + channel); + spin_unlock(&dev->slock); + handled++; + } + return handled; } void cx25821_videoioctl_unregister(struct cx25821_dev *dev) { - if( dev->ioctl_dev ) - { - if (dev->ioctl_dev->minor != -1) - video_unregister_device(dev->ioctl_dev); - else - video_device_release(dev->ioctl_dev); + if (dev->ioctl_dev) { + if (dev->ioctl_dev->minor != -1) + video_unregister_device(dev->ioctl_dev); + else + video_device_release(dev->ioctl_dev); - dev->ioctl_dev = NULL; - } + dev->ioctl_dev = NULL; + } } void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) { - cx_clear(PCI_INT_MSK, 1); + cx_clear(PCI_INT_MSK, 1); - if (dev->video_dev[chan_num]) { - if (-1 != dev->video_dev[chan_num]->minor) - video_unregister_device(dev->video_dev[chan_num]); - else - video_device_release(dev->video_dev[chan_num]); + if (dev->video_dev[chan_num]) { + if (-1 != dev->video_dev[chan_num]->minor) + video_unregister_device(dev->video_dev[chan_num]); + else + video_device_release(dev->video_dev[chan_num]); - dev->video_dev[chan_num] = NULL; + dev->video_dev[chan_num] = NULL; - btcx_riscmem_free(dev->pci, &dev->vidq[chan_num].stopper); + btcx_riscmem_free(dev->pci, &dev->vidq[chan_num].stopper); - printk(KERN_WARNING "device %d released!\n", chan_num); - } + printk(KERN_WARNING "device %d released!\n", chan_num); + } } - -int cx25821_video_register(struct cx25821_dev *dev, int chan_num, struct video_device *video_template) +int cx25821_video_register(struct cx25821_dev *dev, int chan_num, + struct video_device *video_template) { - int err; + int err; - spin_lock_init(&dev->slock); + spin_lock_init(&dev->slock); - //printk(KERN_WARNING "Channel %d\n", chan_num); + //printk(KERN_WARNING "Channel %d\n", chan_num); #ifdef TUNER_FLAG - dev->tvnorm = video_template->current_norm; + dev->tvnorm = video_template->current_norm; #endif - /* init video dma queues */ - dev->timeout_data[chan_num].dev = dev; - dev->timeout_data[chan_num].channel = &dev->sram_channels[chan_num]; - INIT_LIST_HEAD(&dev->vidq[chan_num].active); - INIT_LIST_HEAD(&dev->vidq[chan_num].queued); - dev->vidq[chan_num].timeout.function = cx25821_vid_timeout; - dev->vidq[chan_num].timeout.data = (unsigned long)&dev->timeout_data[chan_num]; - init_timer(&dev->vidq[chan_num].timeout); - cx25821_risc_stopper(dev->pci, &dev->vidq[chan_num].stopper, dev->sram_channels[chan_num].dma_ctl, 0x11, 0); - - - /* register v4l devices */ - dev->video_dev[chan_num] = cx25821_vdev_init(dev, dev->pci, video_template, "video"); - err = video_register_device(dev->video_dev[chan_num], VFL_TYPE_GRABBER, video_nr[dev->nr]); - - if (err < 0) { - goto fail_unreg; - } - - //set PCI interrupt - cx_set(PCI_INT_MSK, 0xff); - + /* init video dma queues */ + dev->timeout_data[chan_num].dev = dev; + dev->timeout_data[chan_num].channel = &dev->sram_channels[chan_num]; + INIT_LIST_HEAD(&dev->vidq[chan_num].active); + INIT_LIST_HEAD(&dev->vidq[chan_num].queued); + dev->vidq[chan_num].timeout.function = cx25821_vid_timeout; + dev->vidq[chan_num].timeout.data = + (unsigned long)&dev->timeout_data[chan_num]; + init_timer(&dev->vidq[chan_num].timeout); + cx25821_risc_stopper(dev->pci, &dev->vidq[chan_num].stopper, + dev->sram_channels[chan_num].dma_ctl, 0x11, 0); + + /* register v4l devices */ + dev->video_dev[chan_num] = + cx25821_vdev_init(dev, dev->pci, video_template, "video"); + err = + video_register_device(dev->video_dev[chan_num], VFL_TYPE_GRABBER, + video_nr[dev->nr]); + + if (err < 0) { + goto fail_unreg; + } + //set PCI interrupt + cx_set(PCI_INT_MSK, 0xff); - /* initial device configuration */ - mutex_lock(&dev->lock); + /* initial device configuration */ + mutex_lock(&dev->lock); #ifdef TUNER_FLAG - cx25821_set_tvnorm(dev, dev->tvnorm); + cx25821_set_tvnorm(dev, dev->tvnorm); #endif - mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); - init_controls(dev, chan_num); + init_controls(dev, chan_num); - return 0; + return 0; -fail_unreg: - cx25821_video_unregister(dev, chan_num); - return err; + fail_unreg: + cx25821_video_unregister(dev, chan_num); + return err; } -int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) +int buffer_setup(struct videobuf_queue *q, unsigned int *count, + unsigned int *size) { - struct cx25821_fh *fh = q->priv_data; - - *size = fh->fmt->depth*fh->width*fh->height >> 3; + struct cx25821_fh *fh = q->priv_data; + *size = fh->fmt->depth * fh->width * fh->height >> 3; - if (0 == *count) - *count = 32; + if (0 == *count) + *count = 32; - while (*size * *count > vid_limit * 1024 * 1024) - (*count)--; + while (*size * *count > vid_limit * 1024 * 1024) + (*count)--; - return 0; + return 0; } -int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) +int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, + enum v4l2_field field) { - struct cx25821_fh *fh = q->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - int rc, init_buffer = 0; - u32 line0_offset, line1_offset; - struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); - int bpl_local = LINE_SIZE_D1; - int channel_opened = 0; - - - BUG_ON(NULL == fh->fmt); - if (fh->width < 48 || fh->width > 720 || - fh->height < 32 || fh->height > 576) - return -EINVAL; - - buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; - - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - - if (buf->fmt != fh->fmt || - buf->vb.width != fh->width || - buf->vb.height != fh->height || - buf->vb.field != field) { - buf->fmt = fh->fmt; - buf->vb.width = fh->width; - buf->vb.height = fh->height; - buf->vb.field = field; - init_buffer = 1; - } - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - init_buffer = 1; - rc = videobuf_iolock(q, &buf->vb, NULL); - if (0 != rc) - { - printk(KERN_DEBUG "videobuf_iolock failed!\n"); - goto fail; - } - } - - dprintk(1, "init_buffer=%d\n", init_buffer); - - if (init_buffer) { - - channel_opened = dev->channel_opened; - channel_opened = (channel_opened < 0 || channel_opened > 7) ? 7 : channel_opened; + struct cx25821_fh *fh = q->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + int rc, init_buffer = 0; + u32 line0_offset, line1_offset; + struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); + int bpl_local = LINE_SIZE_D1; + int channel_opened = 0; + + BUG_ON(NULL == fh->fmt); + if (fh->width < 48 || fh->width > 720 || + fh->height < 32 || fh->height > 576) + return -EINVAL; - if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 ) - buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; - else - buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); + buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; + if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) + return -EINVAL; - if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 ) - { - bpl_local = buf->bpl; + if (buf->fmt != fh->fmt || + buf->vb.width != fh->width || + buf->vb.height != fh->height || buf->vb.field != field) { + buf->fmt = fh->fmt; + buf->vb.width = fh->width; + buf->vb.height = fh->height; + buf->vb.field = field; + init_buffer = 1; } - else - { - bpl_local = buf->bpl; //Default - - if( channel_opened >= 0 && channel_opened <= 7 ) - { - if( dev->use_cif_resolution[channel_opened] ) - { - if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK ) - bpl_local = 352 << 1; - else - bpl_local = dev->cif_width[channel_opened] << 1; + + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { + init_buffer = 1; + rc = videobuf_iolock(q, &buf->vb, NULL); + if (0 != rc) { + printk(KERN_DEBUG "videobuf_iolock failed!\n"); + goto fail; } - } } + dprintk(1, "init_buffer=%d\n", init_buffer); + + if (init_buffer) { + + channel_opened = dev->channel_opened; + channel_opened = (channel_opened < 0 + || channel_opened > 7) ? 7 : channel_opened; + + if (dev->pixel_formats[channel_opened] == PIXEL_FRMT_411) + buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; + else + buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); + + if (dev->pixel_formats[channel_opened] == PIXEL_FRMT_411) { + bpl_local = buf->bpl; + } else { + bpl_local = buf->bpl; //Default + + if (channel_opened >= 0 && channel_opened <= 7) { + if (dev->use_cif_resolution[channel_opened]) { + if (dev->tvnorm & V4L2_STD_PAL_BG + || dev->tvnorm & V4L2_STD_PAL_DK) + bpl_local = 352 << 1; + else + bpl_local = + dev-> + cif_width[channel_opened] << + 1; + } + } + } - switch (buf->vb.field) { - case V4L2_FIELD_TOP: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, 0, UNSET, - buf->bpl, 0, buf->vb.height); - break; - case V4L2_FIELD_BOTTOM: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, UNSET, 0, - buf->bpl, 0, buf->vb.height); - break; - case V4L2_FIELD_INTERLACED: - /* All other formats are top field first */ - line0_offset = 0; - line1_offset = buf->bpl; - dprintk(1, "top field first\n"); - - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, line0_offset, - bpl_local, bpl_local, bpl_local, - buf->vb.height >> 1); - break; - case V4L2_FIELD_SEQ_TB: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, - 0, buf->bpl * (buf->vb.height >> 1), - buf->bpl, 0, - buf->vb.height >> 1); - break; - case V4L2_FIELD_SEQ_BT: - cx25821_risc_buffer(dev->pci, &buf->risc, - dma->sglist, - buf->bpl * (buf->vb.height >> 1), 0, - buf->bpl, 0, - buf->vb.height >> 1); - break; - default: - BUG(); + switch (buf->vb.field) { + case V4L2_FIELD_TOP: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, 0, UNSET, + buf->bpl, 0, buf->vb.height); + break; + case V4L2_FIELD_BOTTOM: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, UNSET, 0, + buf->bpl, 0, buf->vb.height); + break; + case V4L2_FIELD_INTERLACED: + /* All other formats are top field first */ + line0_offset = 0; + line1_offset = buf->bpl; + dprintk(1, "top field first\n"); + + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, line0_offset, + bpl_local, bpl_local, bpl_local, + buf->vb.height >> 1); + break; + case V4L2_FIELD_SEQ_TB: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, + 0, buf->bpl * (buf->vb.height >> 1), + buf->bpl, 0, buf->vb.height >> 1); + break; + case V4L2_FIELD_SEQ_BT: + cx25821_risc_buffer(dev->pci, &buf->risc, + dma->sglist, + buf->bpl * (buf->vb.height >> 1), 0, + buf->bpl, 0, buf->vb.height >> 1); + break; + default: + BUG(); + } } - } - dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", - buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth, fh->fmt->name, - (unsigned long)buf->risc.dma); + dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", + buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth, + fh->fmt->name, (unsigned long)buf->risc.dma); - buf->vb.state = VIDEOBUF_PREPARED; + buf->vb.state = VIDEOBUF_PREPARED; - return 0; + return 0; - fail: - cx25821_free_buffer(q, buf); - return rc; + fail: + cx25821_free_buffer(q, buf); + return rc; } - void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); - cx25821_free_buffer(q, buf); + cx25821_free_buffer(q, buf); } - struct videobuf_queue *get_queue(struct cx25821_fh *fh) { - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - return &fh->vidq; - default: - BUG(); - return NULL; - } + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return &fh->vidq; + default: + BUG(); + return NULL; + } } int get_resource(struct cx25821_fh *fh, int resource) { - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - return resource; - default: - BUG(); - return 0; - } + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return resource; + default: + BUG(); + return 0; + } } - int video_mmap(struct file *file, struct vm_area_struct *vma) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - return videobuf_mmap_mapper(get_queue(fh), vma); + return videobuf_mmap_mapper(get_queue(fh), vma); } /* VIDEO IOCTLS */ int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct cx25821_fh *fh = priv; + struct cx25821_fh *fh = priv; - f->fmt.pix.width = fh->width; - f->fmt.pix.height = fh->height; - f->fmt.pix.field = fh->vidq.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; - f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3; - f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.width = fh->width; + f->fmt.pix.height = fh->height; + f->fmt.pix.field = fh->vidq.field; + f->fmt.pix.pixelformat = fh->fmt->fourcc; + f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; - return 0; + return 0; } int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - struct cx25821_fmt *fmt; - enum v4l2_field field; - unsigned int maxw, maxh; + struct cx25821_fmt *fmt; + enum v4l2_field field; + unsigned int maxw, maxh; - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (NULL == fmt) - return -EINVAL; + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (NULL == fmt) + return -EINVAL; - field = f->fmt.pix.field; - maxw = 720; - maxh = 576; + field = f->fmt.pix.field; + maxw = 720; + maxh = 576; - if (V4L2_FIELD_ANY == field) { - field = (f->fmt.pix.height > maxh/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_TOP; - } + if (V4L2_FIELD_ANY == field) { + field = (f->fmt.pix.height > maxh / 2) + ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; + } - switch (field) { - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - maxh = maxh / 2; - break; - case V4L2_FIELD_INTERLACED: - break; - default: - return -EINVAL; - } + switch (field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + maxh = maxh / 2; + break; + case V4L2_FIELD_INTERLACED: + break; + default: + return -EINVAL; + } - f->fmt.pix.field = field; - if (f->fmt.pix.height < 32) - f->fmt.pix.height = 32; - if (f->fmt.pix.height > maxh) - f->fmt.pix.height = maxh; - if (f->fmt.pix.width < 48) - f->fmt.pix.width = 48; - if (f->fmt.pix.width > maxw) - f->fmt.pix.width = maxw; - f->fmt.pix.width &= ~0x03; - f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; - f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.field = field; + if (f->fmt.pix.height < 32) + f->fmt.pix.height = 32; + if (f->fmt.pix.height > maxh) + f->fmt.pix.height = maxh; + if (f->fmt.pix.width < 48) + f->fmt.pix.width = 48; + if (f->fmt.pix.width > maxw) + f->fmt.pix.width = maxw; + f->fmt.pix.width &= ~0x03; + f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; - return 0; + return 0; } - - -int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) +int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - - strcpy(cap->driver, "cx25821"); - strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); - sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); - cap->version = CX25821_VERSION_CODE; - cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - if (UNSET != dev->tuner_type) - cap->capabilities |= V4L2_CAP_TUNER; - return 0; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + + strcpy(cap->driver, "cx25821"); + strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); + sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); + cap->version = CX25821_VERSION_CODE; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + if (UNSET != dev->tuner_type) + cap->capabilities |= V4L2_CAP_TUNER; + return 0; } -int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) +int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) { - if (unlikely(f->index >= ARRAY_SIZE(formats))) - return -EINVAL; + if (unlikely(f->index >= ARRAY_SIZE(formats))) + return -EINVAL; - strlcpy(f->description, formats[f->index].name, sizeof(f->description)); - f->pixelformat = formats[f->index].fourcc; + strlcpy(f->description, formats[f->index].name, sizeof(f->description)); + f->pixelformat = formats[f->index].fourcc; - return 0; + return 0; } #ifdef CONFIG_VIDEO_V4L1_COMPAT int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) { - struct cx25821_fh *fh = priv; - struct videobuf_queue *q; - struct v4l2_requestbuffers req; - unsigned int i; - int err; - - q = get_queue(fh); - memset(&req, 0, sizeof(req)); - req.type = q->type; - req.count = 8; - req.memory = V4L2_MEMORY_MMAP; - err = videobuf_reqbufs(q, &req); - if (err < 0) - return err; + struct cx25821_fh *fh = priv; + struct videobuf_queue *q; + struct v4l2_requestbuffers req; + unsigned int i; + int err; - mbuf->frames = req.count; - mbuf->size = 0; - for (i = 0; i < mbuf->frames; i++) { - mbuf->offsets[i] = q->bufs[i]->boff; - mbuf->size += q->bufs[i]->bsize; - } - return 0; + q = get_queue(fh); + memset(&req, 0, sizeof(req)); + req.type = q->type; + req.count = 8; + req.memory = V4L2_MEMORY_MMAP; + err = videobuf_reqbufs(q, &req); + if (err < 0) + return err; + + mbuf->frames = req.count; + mbuf->size = 0; + for (i = 0; i < mbuf->frames; i++) { + mbuf->offsets[i] = q->bufs[i]->boff; + mbuf->size += q->bufs[i]->bsize; + } + return 0; } #endif int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) { - struct cx25821_fh *fh = priv; - return videobuf_reqbufs(get_queue(fh), p); + struct cx25821_fh *fh = priv; + return videobuf_reqbufs(get_queue(fh), p); } int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct cx25821_fh *fh = priv; - return videobuf_querybuf(get_queue(fh), p); + struct cx25821_fh *fh = priv; + return videobuf_querybuf(get_queue(fh), p); } int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct cx25821_fh *fh = priv; - return videobuf_qbuf(get_queue(fh), p); + struct cx25821_fh *fh = priv; + return videobuf_qbuf(get_queue(fh), p); } int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) @@ -838,8 +828,7 @@ int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) return 0; } -int vidioc_s_priority(struct file *file, void *f, - enum v4l2_priority prio) +int vidioc_s_priority(struct file *file, void *f, enum v4l2_priority prio) { struct cx25821_fh *fh = f; struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; @@ -847,266 +836,257 @@ int vidioc_s_priority(struct file *file, void *f, return v4l2_prio_change(&dev->prio, &fh->prio, prio); } - #ifdef TUNER_FLAG -int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) +int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; - dprintk(1, "%s()\n", __func__); + dprintk(1, "%s()\n", __func__); - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; - } + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } - if( dev->tvnorm == *tvnorms ) - { - return 0; - } + if (dev->tvnorm == *tvnorms) { + return 0; + } - mutex_lock(&dev->lock); - cx25821_set_tvnorm(dev, *tvnorms); - mutex_unlock(&dev->lock); + mutex_lock(&dev->lock); + cx25821_set_tvnorm(dev, *tvnorms); + mutex_unlock(&dev->lock); - medusa_set_videostandard(dev); + medusa_set_videostandard(dev); - return 0; + return 0; } #endif int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i) { - static const char *iname[] = { - [CX25821_VMUX_COMPOSITE] = "Composite", - [CX25821_VMUX_SVIDEO] = "S-Video", - [CX25821_VMUX_DEBUG] = "for debug only", - }; - unsigned int n; - dprintk(1, "%s()\n", __func__); - - n = i->index; - if (n > 2) - return -EINVAL; + static const char *iname[] = { + [CX25821_VMUX_COMPOSITE] = "Composite", + [CX25821_VMUX_SVIDEO] = "S-Video", + [CX25821_VMUX_DEBUG] = "for debug only", + }; + unsigned int n; + dprintk(1, "%s()\n", __func__); - if (0 == INPUT(n)->type) - return -EINVAL; + n = i->index; + if (n > 2) + return -EINVAL; + + if (0 == INPUT(n)->type) + return -EINVAL; - memset(i, 0, sizeof(*i)); - i->index = n; - i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name, iname[INPUT(n)->type]); + memset(i, 0, sizeof(*i)); + i->index = n; + i->type = V4L2_INPUT_TYPE_CAMERA; + strcpy(i->name, iname[INPUT(n)->type]); - i->std = CX25821_NORMS; - return 0; + i->std = CX25821_NORMS; + return 0; } int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - dprintk(1, "%s()\n", __func__); - return cx25821_enum_input(dev, i); + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + dprintk(1, "%s()\n", __func__); + return cx25821_enum_input(dev, i); } int vidioc_g_input(struct file *file, void *priv, unsigned int *i) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - *i = dev->input; - dprintk(1, "%s() returns %d\n", __func__, *i); - return 0; + *i = dev->input; + dprintk(1, "%s() returns %d\n", __func__, *i); + return 0; } - int vidioc_s_input(struct file *file, void *priv, unsigned int i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; - dprintk(1, "%s(%d)\n", __func__, i); + dprintk(1, "%s(%d)\n", __func__, i); - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; - } + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } - if (i > 2) { - dprintk(1, "%s() -EINVAL\n", __func__); - return -EINVAL; - } + if (i > 2) { + dprintk(1, "%s() -EINVAL\n", __func__); + return -EINVAL; + } - mutex_lock(&dev->lock); - cx25821_video_mux(dev, i); - mutex_unlock(&dev->lock); - return 0; + mutex_lock(&dev->lock); + cx25821_video_mux(dev, i); + mutex_unlock(&dev->lock); + return 0; } #ifdef TUNER_FLAG int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - f->frequency = dev->freq; + f->frequency = dev->freq; - cx25821_call_all(dev, tuner, g_frequency, f); + cx25821_call_all(dev, tuner, g_frequency, f); - return 0; + return 0; } int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f) { - mutex_lock(&dev->lock); - dev->freq = f->frequency; + mutex_lock(&dev->lock); + dev->freq = f->frequency; - cx25821_call_all(dev, tuner, s_frequency, f); + cx25821_call_all(dev, tuner, s_frequency, f); - /* When changing channels it is required to reset TVAUDIO */ - msleep(10); + /* When changing channels it is required to reset TVAUDIO */ + msleep(10); - mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); - return 0; + return 0; } int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; - } + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err; - return cx25821_set_freq(dev, f); + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + return cx25821_set_freq(dev, f); } #endif #ifdef CONFIG_VIDEO_ADV_DEBUG int vidioc_g_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) + struct v4l2_dbg_register *reg) { - struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; + struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; + if (!v4l2_chip_match_host(®->match)) + return -EINVAL; - cx25821_call_all(dev, core, g_register, reg); + cx25821_call_all(dev, core, g_register, reg); - return 0; + return 0; } int vidioc_s_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) + struct v4l2_dbg_register *reg) { - struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; + struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; + if (!v4l2_chip_match_host(®->match)) + return -EINVAL; - cx25821_call_all(dev, core, s_register, reg); + cx25821_call_all(dev, core, s_register, reg); - return 0; + return 0; } #endif - #ifdef TUNER_FLAG int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - if (unlikely(UNSET == dev->tuner_type)) - return -EINVAL; - if (0 != t->index) - return -EINVAL; + if (unlikely(UNSET == dev->tuner_type)) + return -EINVAL; + if (0 != t->index) + return -EINVAL; - strcpy(t->name, "Television"); - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM; - t->rangehigh = 0xffffffffUL; + strcpy(t->name, "Television"); + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM; + t->rangehigh = 0xffffffffUL; - t->signal = 0xffff ; /* LOCKED */ - return 0; + t->signal = 0xffff; /* LOCKED */ + return 0; } -int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *t) +int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - struct cx25821_fh *fh = priv; - int err; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; - } + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + struct cx25821_fh *fh = priv; + int err; - dprintk(1, "%s()\n", __func__); - if (UNSET == dev->tuner_type) - return -EINVAL; - if (0 != t->index) - return -EINVAL; + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } - return 0; + dprintk(1, "%s()\n", __func__); + if (UNSET == dev->tuner_type) + return -EINVAL; + if (0 != t->index) + return -EINVAL; + + return 0; } #endif // ****************************************************************************************** static const struct v4l2_queryctrl no_ctl = { - .name = "42", + .name = "42", .flags = V4L2_CTRL_FLAG_DISABLED, }; static struct v4l2_queryctrl cx25821_ctls[] = { /* --- video --- */ { - .id = V4L2_CID_BRIGHTNESS, - .name = "Brightness", - .minimum = 0, - .maximum = 10000, - .step = 1, - .default_value = 6200, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_CONTRAST, - .name = "Contrast", - .minimum = 0, - .maximum = 10000, - .step = 1, - .default_value = 5000, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_SATURATION, - .name = "Saturation", - .minimum = 0, - .maximum = 10000, - .step = 1, - .default_value = 5000, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_HUE, - .name = "Hue", - .minimum = 0, - .maximum = 10000, - .step = 1, - .default_value = 5000, - .type = V4L2_CTRL_TYPE_INTEGER, - } + .id = V4L2_CID_BRIGHTNESS, + .name = "Brightness", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 6200, + .type = V4L2_CTRL_TYPE_INTEGER, + }, { + .id = V4L2_CID_CONTRAST, + .name = "Contrast", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 5000, + .type = V4L2_CTRL_TYPE_INTEGER, + }, { + .id = V4L2_CID_SATURATION, + .name = "Saturation", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 5000, + .type = V4L2_CTRL_TYPE_INTEGER, + }, { + .id = V4L2_CID_HUE, + .name = "Hue", + .minimum = 0, + .maximum = 10000, + .step = 1, + .default_value = 5000, + .type = V4L2_CTRL_TYPE_INTEGER, + } }; static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls); @@ -1114,8 +1094,7 @@ static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) { int i; - if (qctrl->id < V4L2_CID_BASE || - qctrl->id >= V4L2_CID_LASTP1) + if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) return -EINVAL; for (i = 0; i < CX25821_CTLS; i++) if (cx25821_ctls[i].id == qctrl->id) @@ -1129,7 +1108,7 @@ static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) } int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qctrl) + struct v4l2_queryctrl *qctrl) { return cx25821_ctrl_query(qctrl); } @@ -1137,40 +1116,37 @@ int vidioc_queryctrl(struct file *file, void *priv, /* ------------------------------------------------------------------ */ /* VIDEO CTRL IOCTLS */ -static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id) +static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id) { unsigned int i; for (i = 0; i < CX25821_CTLS; i++) if (cx25821_ctls[i].id == id) - return cx25821_ctls+i; + return cx25821_ctls + i; return NULL; } -int vidioc_g_ctrl(struct file *file, - void *priv, - struct v4l2_control *ctl) +int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctl) { struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - const struct v4l2_queryctrl* ctrl; + const struct v4l2_queryctrl *ctrl; ctrl = ctrl_by_id(ctl->id); if (NULL == ctrl) return -EINVAL; - switch (ctl->id) - { - case V4L2_CID_BRIGHTNESS: + switch (ctl->id) { + case V4L2_CID_BRIGHTNESS: ctl->value = dev->ctl_bright; break; - case V4L2_CID_HUE: + case V4L2_CID_HUE: ctl->value = dev->ctl_hue; break; - case V4L2_CID_CONTRAST: + case V4L2_CID_CONTRAST: ctl->value = dev->ctl_contrast; break; - case V4L2_CID_SATURATION: + case V4L2_CID_SATURATION: ctl->value = dev->ctl_saturation; break; } @@ -1178,10 +1154,10 @@ int vidioc_g_ctrl(struct file *file, } int cx25821_set_control(struct cx25821_dev *dev, - struct v4l2_control *ctl, int chan_num) + struct v4l2_control *ctl, int chan_num) { int err; - const struct v4l2_queryctrl* ctrl; + const struct v4l2_queryctrl *ctrl; err = -EINVAL; @@ -1190,35 +1166,33 @@ int cx25821_set_control(struct cx25821_dev *dev, if (NULL == ctrl) return err; - switch (ctrl->type) - { - case V4L2_CTRL_TYPE_BOOLEAN: - case V4L2_CTRL_TYPE_MENU: - case V4L2_CTRL_TYPE_INTEGER: + switch (ctrl->type) { + case V4L2_CTRL_TYPE_BOOLEAN: + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_INTEGER: if (ctl->value < ctrl->minimum) ctl->value = ctrl->minimum; if (ctl->value > ctrl->maximum) ctl->value = ctrl->maximum; break; - default: - /* nothing */; + default: + /* nothing */ ; }; - switch (ctl->id) - { - case V4L2_CID_BRIGHTNESS: + switch (ctl->id) { + case V4L2_CID_BRIGHTNESS: dev->ctl_bright = ctl->value; medusa_set_brightness(dev, ctl->value, chan_num); break; - case V4L2_CID_HUE: + case V4L2_CID_HUE: dev->ctl_hue = ctl->value; medusa_set_hue(dev, ctl->value, chan_num); break; - case V4L2_CID_CONTRAST: + case V4L2_CID_CONTRAST: dev->ctl_contrast = ctl->value; medusa_set_contrast(dev, ctl->value, chan_num); break; - case V4L2_CID_SATURATION: + case V4L2_CID_SATURATION: dev->ctl_saturation = ctl->value; medusa_set_saturation(dev, ctl->value, chan_num); break; @@ -1241,9 +1215,7 @@ static void init_controls(struct cx25821_dev *dev, int chan_num) } } -int vidioc_cropcap(struct file *file, - void *priv, - struct v4l2_cropcap *cropcap) +int vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cropcap) { struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; @@ -1252,86 +1224,76 @@ int vidioc_cropcap(struct file *file, cropcap->bounds.top = cropcap->bounds.left = 0; cropcap->bounds.width = 720; cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480; - cropcap->pixelaspect.numerator = dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10; - cropcap->pixelaspect.denominator = dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11; + cropcap->pixelaspect.numerator = + dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10; + cropcap->pixelaspect.denominator = + dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11; cropcap->defrect = cropcap->bounds; return 0; } -int vidioc_s_crop(struct file *file, - void *priv, - struct v4l2_crop *crop) +int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - struct cx25821_fh *fh = priv; - int err; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; - } - // vidioc_s_crop not supported - return -EINVAL; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + struct cx25821_fh *fh = priv; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + // vidioc_s_crop not supported + return -EINVAL; } -int vidioc_g_crop(struct file *file, - void *priv, - struct v4l2_crop *crop) +int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) { - // vidioc_g_crop not supported - return -EINVAL; + // vidioc_g_crop not supported + return -EINVAL; } -int vidioc_querystd(struct file *file, - void *priv, - v4l2_std_id *norm) +int vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm) { - // medusa does not support video standard sensing of current input - *norm = CX25821_NORMS; + // medusa does not support video standard sensing of current input + *norm = CX25821_NORMS; - return 0; + return 0; } int is_valid_width(u32 width, v4l2_std_id tvnorm) { - if(tvnorm == V4L2_STD_PAL_BG) - { - if (width == 352 || width == 720) - return 1; - else - return 0; - } + if (tvnorm == V4L2_STD_PAL_BG) { + if (width == 352 || width == 720) + return 1; + else + return 0; + } - if(tvnorm == V4L2_STD_NTSC_M) - { - if (width == 320 || width == 352 || width == 720) - return 1; - else - return 0; - } - return 0; + if (tvnorm == V4L2_STD_NTSC_M) { + if (width == 320 || width == 352 || width == 720) + return 1; + else + return 0; + } + return 0; } int is_valid_height(u32 height, v4l2_std_id tvnorm) { - if(tvnorm == V4L2_STD_PAL_BG) - { - if (height == 576 || height == 288) - return 1; - else - return 0; - } + if (tvnorm == V4L2_STD_PAL_BG) { + if (height == 576 || height == 288) + return 1; + else + return 0; + } - if(tvnorm == V4L2_STD_NTSC_M) - { - if (height == 480 || height == 240) - return 1; - else - return 0; - } + if (tvnorm == V4L2_STD_NTSC_M) { + if (height == 480 || height == 240) + return 1; + else + return 0; + } - return 0; + return 0; } - diff --git a/linux/drivers/staging/cx25821/cx25821-video.h b/linux/drivers/staging/cx25821/cx25821-video.h index cef846ccb..68df23bab 100644 --- a/linux/drivers/staging/cx25821/cx25821-video.h +++ b/linux/drivers/staging/cx25821/cx25821-video.h @@ -24,7 +24,6 @@ #ifndef CX25821_VIDEO_H_ #define CX25821_VIDEO_H_ - #include #include #include @@ -56,7 +55,6 @@ printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\ } while (0) - //For IOCTL to identify running upstream #define UPSTREAM_START_VIDEO 700 #define UPSTREAM_STOP_VIDEO 701 @@ -97,62 +95,82 @@ extern struct video_device cx25821_video_template11; extern struct video_device cx25821_videoioctl_template; //extern const u32 *ctrl_classes[]; -extern unsigned int vid_limit; +extern unsigned int vid_limit; #define FORMAT_FLAGS_PACKED 0x01 extern struct cx25821_fmt formats[]; extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc); extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; -extern void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q); -extern void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, u32 count); +extern void dump_video_queue(struct cx25821_dev *dev, + struct cx25821_dmaqueue *q); +extern void cx25821_video_wakeup(struct cx25821_dev *dev, + struct cx25821_dmaqueue *q, u32 count); #ifdef TUNER_FLAG extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm); #endif - -extern int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit); +extern int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, + unsigned int bit); extern int res_check(struct cx25821_fh *fh, unsigned int bit); extern int res_locked(struct cx25821_dev *dev, unsigned int bit); -extern void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits); +extern void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, + unsigned int bits); extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input); extern int cx25821_start_video_dma(struct cx25821_dev *dev, - struct cx25821_dmaqueue *q, - struct cx25821_buffer *buf, - struct sram_channel *channel); + struct cx25821_dmaqueue *q, + struct cx25821_buffer *buf, + struct sram_channel *channel); -extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width, unsigned int height, enum v4l2_field field); +extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width, + unsigned int height, enum v4l2_field field); extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status); extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num); -extern int cx25821_video_register(struct cx25821_dev *dev, int chan_num, struct video_device *video_template); +extern int cx25821_video_register(struct cx25821_dev *dev, int chan_num, + struct video_device *video_template); extern int get_format_size(void); -extern int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size); -extern int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field); -extern void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb); +extern int buffer_setup(struct videobuf_queue *q, unsigned int *count, + unsigned int *size); +extern int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, + enum v4l2_field field); +extern void buffer_release(struct videobuf_queue *q, + struct videobuf_buffer *vb); extern struct videobuf_queue *get_queue(struct cx25821_fh *fh); extern int get_resource(struct cx25821_fh *fh, int resource); extern int video_mmap(struct file *file, struct vm_area_struct *vma); -extern int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f); -extern int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap); -extern int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f); +extern int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f); +extern int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap); +extern int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f); extern int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf); -extern int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p); -extern int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p); +extern int vidioc_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p); +extern int vidioc_querybuf(struct file *file, void *priv, + struct v4l2_buffer *p); extern int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p); -extern int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms); +extern int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms); extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i); -extern int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i); +extern int vidioc_enum_input(struct file *file, void *priv, + struct v4l2_input *i); extern int vidioc_g_input(struct file *file, void *priv, unsigned int *i); extern int vidioc_s_input(struct file *file, void *priv, unsigned int i); -extern int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctl); -extern int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f); -extern int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f); +extern int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctl); +extern int vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f); +extern int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f); extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f); -extern int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f); -extern int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg); -extern int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg); +extern int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f); +extern int vidioc_g_register(struct file *file, void *fh, + struct v4l2_dbg_register *reg); +extern int vidioc_s_register(struct file *file, void *fh, + struct v4l2_dbg_register *reg); extern int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t); extern int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t); @@ -160,14 +178,18 @@ extern int is_valid_width(u32 width, v4l2_std_id tvnorm); extern int is_valid_height(u32 height, v4l2_std_id tvnorm); extern int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p); -extern int vidioc_s_priority(struct file *file, void *f, enum v4l2_priority prio); +extern int vidioc_s_priority(struct file *file, void *f, + enum v4l2_priority prio); -extern int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qctrl); -extern int cx25821_set_control(struct cx25821_dev *dev, struct v4l2_control *ctrl, int chan_num); +extern int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qctrl); +extern int cx25821_set_control(struct cx25821_dev *dev, + struct v4l2_control *ctrl, int chan_num); -extern int vidioc_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap); +extern int vidioc_cropcap(struct file *file, void *fh, + struct v4l2_cropcap *cropcap); extern int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop); extern int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop); -extern int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm); +extern int vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm); #endif diff --git a/linux/drivers/staging/cx25821/cx25821-video0.c b/linux/drivers/staging/cx25821/cx25821-video0.c index 92b5eb937..950fac1d7 100644 --- a/linux/drivers/staging/cx25821/cx25821-video0.c +++ b/linux/drivers/staging/cx25821/cx25821-video0.c @@ -23,359 +23,356 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH00]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH00]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH00]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[SRAM_CH00]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - u32 pix_format; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH00] && h->video_dev[SRAM_CH00]->minor == minor) - { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH00] + && h->video_dev[SRAM_CH00]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; - } + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; - dev->channel_opened = SRAM_CH00; - pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); + dev->channel_opened = SRAM_CH00; + pix_format = + (dev->pixel_formats[dev->channel_opened] == + PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); - v4l2_prio_open(&dev->prio,&fh->prio); + v4l2_prio_open(&dev->prio, &fh->prio); - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); - return 0; + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO0)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO0)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO0)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH00] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO0)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } - return POLLIN|POLLRDNORM; - } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { + if (buf->vb.state == VIDEOBUF_DONE) { + struct cx25821_dev *dev = fh->dev; + + if (dev && dev->use_cif_resolution[SRAM_CH00]) { + u8 cam_id = *((char *)buf->vb.baddr + 3); + memcpy((char *)buf->vb.baddr, + (char *)buf->vb.baddr + (fh->width * 2), + (fh->width * 2)); + *((char *)buf->vb.baddr + 3) = cam_id; + } + } + + return POLLIN | POLLRDNORM; + } - return 0; + return 0; } - static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ + //stop the risc engine and fifo + cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO0)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO0); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO0)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO0); + } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); - file->private_data = NULL; - kfree(fh); + v4l2_prio_close(&dev->prio, &fh->prio); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO0)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO0)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO0); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO0); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = PIXEL_FRMT_422; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = PIXEL_FRMT_422; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) - { - fh->width = f->fmt.pix.width; - } - - if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) - { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format( dev, SRAM_CH00, pix_format ); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) - { - dev->use_cif_resolution[SRAM_CH00] = 1; - }else - { - dev->use_cif_resolution[SRAM_CH00] = 0; - } - dev->cif_width[SRAM_CH00] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH00 ); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format(dev, SRAM_CH00, pix_format); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) { + dev->use_cif_resolution[SRAM_CH00] = 1; + } else { + dev->use_cif_resolution[SRAM_CH00] = 0; + } + dev->cif_width[SRAM_CH00] = fh->width; + medusa_set_resolution(dev, fh->width, SRAM_CH00); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - p->sequence = dev->vidq[SRAM_CH00].count; + p->sequence = dev->vidq[SRAM_CH00].count; - return ret_val; + return ret_val; } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH00]; - u32 tmp = 0; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH00]; + u32 tmp = 0; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 0 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + cx25821_call_all(dev, core, log_status); + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 0 is %s\n", + (tmp & 0x11) ? "streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; @@ -392,66 +389,63 @@ static int vidioc_s_ctrl(struct file *file, void *priv, // exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl2, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_video_template0 = { - .name = "cx25821-video", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821-video1.c b/linux/drivers/staging/cx25821/cx25821-video1.c index c36f664f6..a4dddc684 100644 --- a/linux/drivers/staging/cx25821/cx25821-video1.c +++ b/linux/drivers/staging/cx25821/cx25821-video1.c @@ -23,359 +23,356 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH01]; - - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH01]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH01]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[SRAM_CH01]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - u32 pix_format; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH01] && h->video_dev[SRAM_CH01]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH01] + && h->video_dev[SRAM_CH01]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; - } + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; - dev->channel_opened = SRAM_CH01; - pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); + dev->channel_opened = SRAM_CH01; + pix_format = + (dev->pixel_formats[dev->channel_opened] == + PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); - v4l2_prio_open(&dev->prio,&fh->prio); + v4l2_prio_open(&dev->prio, &fh->prio); - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); - return 0; + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO1)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO1)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO1)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH01] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO1)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } - return POLLIN|POLLRDNORM; - } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { + if (buf->vb.state == VIDEOBUF_DONE) { + struct cx25821_dev *dev = fh->dev; + + if (dev && dev->use_cif_resolution[SRAM_CH01]) { + u8 cam_id = *((char *)buf->vb.baddr + 3); + memcpy((char *)buf->vb.baddr, + (char *)buf->vb.baddr + (fh->width * 2), + (fh->width * 2)); + *((char *)buf->vb.baddr + 3) = cam_id; + } + } + + return POLLIN | POLLRDNORM; + } - return 0; + return 0; } static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - cx_write(channel1->dma_ctl, 0); /* FIFO and RISC disable */ + //stop the risc engine and fifo + cx_write(channel1->dma_ctl, 0); /* FIFO and RISC disable */ - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO1)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO1); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO1)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO1); + } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); - file->private_data = NULL; - kfree(fh); + v4l2_prio_close(&dev->prio, &fh->prio); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO1)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO1)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO1); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO1); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) - { - fh->width = f->fmt.pix.width; - } - - if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) - { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format( dev, SRAM_CH01, pix_format ); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) - { - dev->use_cif_resolution[SRAM_CH01] = 1; - }else - { - dev->use_cif_resolution[SRAM_CH01] = 0; - } - dev->cif_width[SRAM_CH01] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH01 ); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format(dev, SRAM_CH01, pix_format); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) { + dev->use_cif_resolution[SRAM_CH01] = 1; + } else { + dev->use_cif_resolution[SRAM_CH01] = 0; + } + dev->cif_width[SRAM_CH01] = fh->width; + medusa_set_resolution(dev, fh->width, SRAM_CH01); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - p->sequence = dev->vidq[SRAM_CH01].count; + p->sequence = dev->vidq[SRAM_CH01].count; - return ret_val; + return ret_val; } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH01]; - u32 tmp = 0; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH01]; + u32 tmp = 0; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 1 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + cx25821_call_all(dev, core, log_status); + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 1 is %s\n", + (tmp & 0x11) ? "streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; @@ -389,68 +386,66 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return cx25821_set_control(dev, ctl, SRAM_CH01); } + //exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl2, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_video_template1 = { - .name = "cx25821-video", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821-video2.c b/linux/drivers/staging/cx25821/cx25821-video2.c index 10df4f981..8e04e253f 100644 --- a/linux/drivers/staging/cx25821/cx25821-video2.c +++ b/linux/drivers/staging/cx25821/cx25821-video2.c @@ -23,362 +23,357 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH02]; - - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH02]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH02]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[SRAM_CH02]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - u32 pix_format; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH02] && h->video_dev[SRAM_CH02]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH02] + && h->video_dev[SRAM_CH02]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH02; + pix_format = + (dev->pixel_formats[dev->channel_opened] == + PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio, &fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); + + dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); - return -ENOMEM; - } - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH02; - pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio,&fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; + + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO2)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO2)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO2)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH02] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO2)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } - return POLLIN|POLLRDNORM; - } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { + if (buf->vb.state == VIDEOBUF_DONE) { + struct cx25821_dev *dev = fh->dev; + + if (dev && dev->use_cif_resolution[SRAM_CH02]) { + u8 cam_id = *((char *)buf->vb.baddr + 3); + memcpy((char *)buf->vb.baddr, + (char *)buf->vb.baddr + (fh->width * 2), + (fh->width * 2)); + *((char *)buf->vb.baddr + 3) = cam_id; + } + } + + return POLLIN | POLLRDNORM; + } - return 0; + return 0; } - static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - cx_write(channel2->dma_ctl, 0); /* FIFO and RISC disable */ + //stop the risc engine and fifo + cx_write(channel2->dma_ctl, 0); /* FIFO and RISC disable */ - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO2)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO2); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO2)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO2); + } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); - file->private_data = NULL; - kfree(fh); + v4l2_prio_close(&dev->prio, &fh->prio); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO2)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO2)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO2); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO2); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) - { - fh->width = f->fmt.pix.width; - } - - if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) - { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format( dev, SRAM_CH02, pix_format ); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) - { - dev->use_cif_resolution[SRAM_CH02] = 1; - }else - { - dev->use_cif_resolution[SRAM_CH02] = 0; - } - dev->cif_width[SRAM_CH02] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH02 ); - - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format(dev, SRAM_CH02, pix_format); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) { + dev->use_cif_resolution[SRAM_CH02] = 1; + } else { + dev->use_cif_resolution[SRAM_CH02] = 0; + } + dev->cif_width[SRAM_CH02] = fh->width; + medusa_set_resolution(dev, fh->width, SRAM_CH02); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - p->sequence = dev->vidq[SRAM_CH02].count; + p->sequence = dev->vidq[SRAM_CH02].count; - return ret_val; + return ret_val; } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH02]; - u32 tmp = 0; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH02]; + u32 tmp = 0; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); + cx25821_call_all(dev, core, log_status); - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 2 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 2 is %s\n", + (tmp & 0x11) ? "streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; @@ -392,68 +387,66 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return cx25821_set_control(dev, ctl, SRAM_CH02); } + // exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl2, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_video_template2 = { - .name = "cx25821-video", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821-video3.c b/linux/drivers/staging/cx25821/cx25821-video3.c index 2191152d7..8801a8ead 100644 --- a/linux/drivers/staging/cx25821/cx25821-video3.c +++ b/linux/drivers/staging/cx25821/cx25821-video3.c @@ -23,360 +23,356 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH03]; - - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH03]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH03]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[SRAM_CH03]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - u32 pix_format; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH03] && h->video_dev[SRAM_CH03]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH03] + && h->video_dev[SRAM_CH03]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH03; + pix_format = + (dev->pixel_formats[dev->channel_opened] == + PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio, &fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); + + dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); - return -ENOMEM; - } - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH03; - pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio,&fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; + + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO3)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO3)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO3)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH03] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO3)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } - return POLLIN|POLLRDNORM; - } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { + if (buf->vb.state == VIDEOBUF_DONE) { + struct cx25821_dev *dev = fh->dev; + + if (dev && dev->use_cif_resolution[SRAM_CH03]) { + u8 cam_id = *((char *)buf->vb.baddr + 3); + memcpy((char *)buf->vb.baddr, + (char *)buf->vb.baddr + (fh->width * 2), + (fh->width * 2)); + *((char *)buf->vb.baddr + 3) = cam_id; + } + } + + return POLLIN | POLLRDNORM; + } - return 0; + return 0; } - static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - cx_write(channel3->dma_ctl, 0); /* FIFO and RISC disable */ + //stop the risc engine and fifo + cx_write(channel3->dma_ctl, 0); /* FIFO and RISC disable */ - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO3)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO3); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO3)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO3); + } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); - file->private_data = NULL; - kfree(fh); + v4l2_prio_close(&dev->prio, &fh->prio); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO3)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO3)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO3); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO3); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) - { - fh->width = f->fmt.pix.width; - } - - if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) - { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format( dev, SRAM_CH03, pix_format ); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) - { - dev->use_cif_resolution[SRAM_CH03] = 1; - }else - { - dev->use_cif_resolution[SRAM_CH03] = 0; - } - dev->cif_width[SRAM_CH03] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH03 ); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format(dev, SRAM_CH03, pix_format); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) { + dev->use_cif_resolution[SRAM_CH03] = 1; + } else { + dev->use_cif_resolution[SRAM_CH03] = 0; + } + dev->cif_width[SRAM_CH03] = fh->width; + medusa_set_resolution(dev, fh->width, SRAM_CH03); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - p->sequence = dev->vidq[SRAM_CH03].count; + p->sequence = dev->vidq[SRAM_CH03].count; - return ret_val; + return ret_val; } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH03]; - u32 tmp = 0; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH03]; + u32 tmp = 0; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); + cx25821_call_all(dev, core, log_status); - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 3 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 3 is %s\n", + (tmp & 0x11) ? "streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; @@ -393,66 +389,63 @@ static int vidioc_s_ctrl(struct file *file, void *priv, // exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl2, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_video_template3 = { - .name = "cx25821-video", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821-video4.c b/linux/drivers/staging/cx25821/cx25821-video4.c index c1799d981..ab0d74713 100644 --- a/linux/drivers/staging/cx25821/cx25821-video4.c +++ b/linux/drivers/staging/cx25821/cx25821-video4.c @@ -23,358 +23,355 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH04]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH04]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH04]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[SRAM_CH04]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - u32 pix_format; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH04] && h->video_dev[SRAM_CH04]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH04] + && h->video_dev[SRAM_CH04]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH04; + pix_format = + (dev->pixel_formats[dev->channel_opened] == + PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio, &fh->prio); + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); + + dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); - return -ENOMEM; - } - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH04; - pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio,&fh->prio); - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; + + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO4)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO4)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO4)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH04] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO4)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } - return POLLIN|POLLRDNORM; - } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { + if (buf->vb.state == VIDEOBUF_DONE) { + struct cx25821_dev *dev = fh->dev; + + if (dev && dev->use_cif_resolution[SRAM_CH04]) { + u8 cam_id = *((char *)buf->vb.baddr + 3); + memcpy((char *)buf->vb.baddr, + (char *)buf->vb.baddr + (fh->width * 2), + (fh->width * 2)); + *((char *)buf->vb.baddr + 3) = cam_id; + } + } + + return POLLIN | POLLRDNORM; + } - return 0; + return 0; } - static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - cx_write(channel4->dma_ctl, 0); /* FIFO and RISC disable */ + //stop the risc engine and fifo + cx_write(channel4->dma_ctl, 0); /* FIFO and RISC disable */ - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO4)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO4); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO4)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO4); + } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); - file->private_data = NULL; - kfree(fh); + v4l2_prio_close(&dev->prio, &fh->prio); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO4)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO4)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO4); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO4); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + // check priority + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) -{ - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - // check priority - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) - return err; - } - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) - { - fh->width = f->fmt.pix.width; - } - - if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) - { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format( dev, SRAM_CH04, pix_format ); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) - { - dev->use_cif_resolution[SRAM_CH04] = 1; - }else - { - dev->use_cif_resolution[SRAM_CH04] = 0; - } - dev->cif_width[SRAM_CH04] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH04); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format(dev, SRAM_CH04, pix_format); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) { + dev->use_cif_resolution[SRAM_CH04] = 1; + } else { + dev->use_cif_resolution[SRAM_CH04] = 0; + } + dev->cif_width[SRAM_CH04] = fh->width; + medusa_set_resolution(dev, fh->width, SRAM_CH04); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - p->sequence = dev->vidq[SRAM_CH04].count; + p->sequence = dev->vidq[SRAM_CH04].count; - return ret_val; + return ret_val; } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH04]; - u32 tmp = 0; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH04]; + u32 tmp = 0; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); + cx25821_call_all(dev, core, log_status); - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 4 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 4 is %s\n", + (tmp & 0x11) ? "streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; @@ -391,66 +388,63 @@ static int vidioc_s_ctrl(struct file *file, void *priv, // exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl2, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_video_template4 = { - .name = "cx25821-video", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821-video5.c b/linux/drivers/staging/cx25821/cx25821-video5.c index f1b474258..7ef0b971f 100644 --- a/linux/drivers/staging/cx25821/cx25821-video5.c +++ b/linux/drivers/staging/cx25821/cx25821-video5.c @@ -23,357 +23,355 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH05]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH05]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH05]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[SRAM_CH05]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - u32 pix_format; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH05] && h->video_dev[SRAM_CH05]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH05] + && h->video_dev[SRAM_CH05]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH05; + pix_format = + (dev->pixel_formats[dev->channel_opened] == + PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio, &fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); + + dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); - return -ENOMEM; - } - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH05; - pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio,&fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; + + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO5)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO5)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO5)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH05] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO5)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } - return POLLIN|POLLRDNORM; - } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { + if (buf->vb.state == VIDEOBUF_DONE) { + struct cx25821_dev *dev = fh->dev; + + if (dev && dev->use_cif_resolution[SRAM_CH05]) { + u8 cam_id = *((char *)buf->vb.baddr + 3); + memcpy((char *)buf->vb.baddr, + (char *)buf->vb.baddr + (fh->width * 2), + (fh->width * 2)); + *((char *)buf->vb.baddr + 3) = cam_id; + } + } + + return POLLIN | POLLRDNORM; + } - return 0; + return 0; } - static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - cx_write(channel5->dma_ctl, 0); /* FIFO and RISC disable */ + //stop the risc engine and fifo + cx_write(channel5->dma_ctl, 0); /* FIFO and RISC disable */ - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO5)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO5); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO5)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO5); + } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); - file->private_data = NULL; - kfree(fh); + v4l2_prio_close(&dev->prio, &fh->prio); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO5)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO5)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO5); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO5); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) - { - fh->width = f->fmt.pix.width; - } - - if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) - { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format( dev, SRAM_CH05, pix_format ); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) - { - dev->use_cif_resolution[SRAM_CH05] = 1; - }else - { - dev->use_cif_resolution[SRAM_CH05] = 0; - } - dev->cif_width[SRAM_CH05] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH05 ); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format(dev, SRAM_CH05, pix_format); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) { + dev->use_cif_resolution[SRAM_CH05] = 1; + } else { + dev->use_cif_resolution[SRAM_CH05] = 0; + } + dev->cif_width[SRAM_CH05] = fh->width; + medusa_set_resolution(dev, fh->width, SRAM_CH05); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - p->sequence = dev->vidq[SRAM_CH05].count; + p->sequence = dev->vidq[SRAM_CH05].count; - return ret_val; + return ret_val; } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH05]; - u32 tmp = 0; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH05]; + u32 tmp = 0; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); + cx25821_call_all(dev, core, log_status); - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 5 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 5 is %s\n", + (tmp & 0x11) ? "streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; @@ -390,66 +388,63 @@ static int vidioc_s_ctrl(struct file *file, void *priv, // exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl2, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_video_template5 = { - .name = "cx25821-video", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821-video6.c b/linux/drivers/staging/cx25821/cx25821-video6.c index 1c0319c7a..3c41b49e2 100644 --- a/linux/drivers/staging/cx25821/cx25821-video6.c +++ b/linux/drivers/staging/cx25821/cx25821-video6.c @@ -23,357 +23,355 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH06]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH06]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH06]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[SRAM_CH06]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - u32 pix_format; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH06] && h->video_dev[SRAM_CH06]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH06] + && h->video_dev[SRAM_CH06]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH06; + pix_format = + (dev->pixel_formats[dev->channel_opened] == + PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio, &fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); + + dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); - return -ENOMEM; - } - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH06; - pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio,&fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; + + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO6)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO6)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO6)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH06] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO6)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } - return POLLIN|POLLRDNORM; - } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { + if (buf->vb.state == VIDEOBUF_DONE) { + struct cx25821_dev *dev = fh->dev; + + if (dev && dev->use_cif_resolution[SRAM_CH06]) { + u8 cam_id = *((char *)buf->vb.baddr + 3); + memcpy((char *)buf->vb.baddr, + (char *)buf->vb.baddr + (fh->width * 2), + (fh->width * 2)); + *((char *)buf->vb.baddr + 3) = cam_id; + } + } + + return POLLIN | POLLRDNORM; + } - return 0; + return 0; } - static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - cx_write(channel6->dma_ctl, 0); /* FIFO and RISC disable */ + //stop the risc engine and fifo + cx_write(channel6->dma_ctl, 0); /* FIFO and RISC disable */ - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO6)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO6); - } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO6)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO6); + } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); - file->private_data = NULL; - kfree(fh); + v4l2_prio_close(&dev->prio, &fh->prio); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO6)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO6)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO6); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO6); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) - { - fh->width = f->fmt.pix.width; - } - - if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) - { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format( dev, SRAM_CH06, pix_format ); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) - { - dev->use_cif_resolution[SRAM_CH06] = 1; - }else - { - dev->use_cif_resolution[SRAM_CH06] = 0; - } - dev->cif_width[SRAM_CH06] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH06 ); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format(dev, SRAM_CH06, pix_format); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) { + dev->use_cif_resolution[SRAM_CH06] = 1; + } else { + dev->use_cif_resolution[SRAM_CH06] = 0; + } + dev->cif_width[SRAM_CH06] = fh->width; + medusa_set_resolution(dev, fh->width, SRAM_CH06); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - p->sequence = dev->vidq[SRAM_CH06].count; + p->sequence = dev->vidq[SRAM_CH06].count; - return ret_val; + return ret_val; } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH06]; - u32 tmp = 0; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH06]; + u32 tmp = 0; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); + cx25821_call_all(dev, core, log_status); - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 6 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 6 is %s\n", + (tmp & 0x11) ? "streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; @@ -390,66 +388,63 @@ static int vidioc_s_ctrl(struct file *file, void *priv, // exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl2, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_video_template6 = { - .name = "cx25821-video", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821-video7.c b/linux/drivers/staging/cx25821/cx25821-video7.c index 71da80992..625c9b78a 100644 --- a/linux/drivers/staging/cx25821/cx25821-video7.c +++ b/linux/drivers/staging/cx25821/cx25821-video7.c @@ -23,356 +23,354 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH07]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH07]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH07]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[SRAM_CH07]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - u32 pix_format; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH07] && h->video_dev[SRAM_CH07]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH07] + && h->video_dev[SRAM_CH07]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; + + dev->channel_opened = SRAM_CH07; + pix_format = + (dev->pixel_formats[dev->channel_opened] == + PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); + + v4l2_prio_open(&dev->prio, &fh->prio); + + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); + + dprintk(1, "post videobuf_queue_init()\n"); unlock_kernel(); - return -ENOMEM; - } - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; - - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; - - dev->channel_opened = SRAM_CH07; - pix_format = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); - - v4l2_prio_open(&dev->prio,&fh->prio); - - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); - - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); - - return 0; + + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO7)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO7)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO7)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - { - if( buf->vb.state == VIDEOBUF_DONE ) - { - struct cx25821_dev *dev = fh->dev; - - if( dev && dev->use_cif_resolution[SRAM_CH07] ) - { - u8 cam_id = *((char*)buf->vb.baddr+3); - memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2)); - *((char*)buf->vb.baddr+3) = cam_id; - } + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO7)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; } - return POLLIN|POLLRDNORM; - } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { + if (buf->vb.state == VIDEOBUF_DONE) { + struct cx25821_dev *dev = fh->dev; + + if (dev && dev->use_cif_resolution[SRAM_CH07]) { + u8 cam_id = *((char *)buf->vb.baddr + 3); + memcpy((char *)buf->vb.baddr, + (char *)buf->vb.baddr + (fh->width * 2), + (fh->width * 2)); + *((char *)buf->vb.baddr + 3) = cam_id; + } + } + + return POLLIN | POLLRDNORM; + } - return 0; + return 0; } - static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - cx_write(channel7->dma_ctl, 0); /* FIFO and RISC disable */ + //stop the risc engine and fifo + cx_write(channel7->dma_ctl, 0); /* FIFO and RISC disable */ - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO7)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO7); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO7)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO7); + } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); - file->private_data = NULL; - kfree(fh); + v4l2_prio_close(&dev->prio, &fh->prio); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO7)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO7)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO7); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO7); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - int pix_format = 0; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + int pix_format = 0; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); + if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->vidq.field = f->fmt.pix.field; - - // check if width and height is valid based on set standard - if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) - { - fh->width = f->fmt.pix.width; - } - - if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) - { - fh->height = f->fmt.pix.height; - } - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) - pix_format = PIXEL_FRMT_411; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) - pix_format = PIXEL_FRMT_422; - else - return -EINVAL; - - cx25821_set_pixel_format( dev, SRAM_CH07, pix_format ); - - // check if cif resolution - if (fh->width == 320 || fh->width == 352) - { - dev->use_cif_resolution[SRAM_CH07] = 1; - }else - { - dev->use_cif_resolution[SRAM_CH07] = 0; - } - dev->cif_width[SRAM_CH07] = fh->width; - medusa_set_resolution( dev, fh->width, SRAM_CH07 ); - - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - - return 0; + return err; + + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->vidq.field = f->fmt.pix.field; + + // check if width and height is valid based on set standard + if (is_valid_width(f->fmt.pix.width, dev->tvnorm)) { + fh->width = f->fmt.pix.width; + } + + if (is_valid_height(f->fmt.pix.height, dev->tvnorm)) { + fh->height = f->fmt.pix.height; + } + + if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) + pix_format = PIXEL_FRMT_411; + else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) + pix_format = PIXEL_FRMT_422; + else + return -EINVAL; + + cx25821_set_pixel_format(dev, SRAM_CH07, pix_format); + + // check if cif resolution + if (fh->width == 320 || fh->width == 352) { + dev->use_cif_resolution[SRAM_CH07] = 1; + } else { + dev->use_cif_resolution[SRAM_CH07] = 0; + } + dev->cif_width[SRAM_CH07] = fh->width; + medusa_set_resolution(dev, fh->width, SRAM_CH07); + + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - int ret_val = 0; - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int ret_val = 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); - p->sequence = dev->vidq[SRAM_CH07].count; + p->sequence = dev->vidq[SRAM_CH07].count; - return ret_val; + return ret_val; } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH07]; - u32 tmp = 0; + struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH07]; + u32 tmp = 0; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); + cx25821_call_all(dev, core, log_status); - tmp = cx_read(sram_ch->dma_ctl); - printk(KERN_INFO "Video input 7 is %s\n", (tmp & 0x11)?"streaming" : "stopped"); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + tmp = cx_read(sram_ch->dma_ctl); + printk(KERN_INFO "Video input 7 is %s\n", + (tmp & 0x11) ? "streaming" : "stopped"); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { struct cx25821_fh *fh = priv; struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; @@ -389,66 +387,63 @@ static int vidioc_s_ctrl(struct file *file, void *priv, // exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl2, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl2, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_video_template7 = { - .name = "cx25821-video", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-video", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821-videoioctl.c b/linux/drivers/staging/cx25821/cx25821-videoioctl.c index ca93cd2af..2a312ce78 100644 --- a/linux/drivers/staging/cx25821/cx25821-videoioctl.c +++ b/linux/drivers/staging/cx25821/cx25821-videoioctl.c @@ -23,478 +23,474 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[VIDEO_IOCTL_CH]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[VIDEO_IOCTL_CH]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[VIDEO_IOCTL_CH]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[VIDEO_IOCTL_CH]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - u32 pix_format; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->ioctl_dev && h->ioctl_dev->minor == minor) - { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + u32 pix_format; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->ioctl_dev && h->ioctl_dev->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; - } + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; - dev->channel_opened = VIDEO_IOCTL_CH; - pix_format = V4L2_PIX_FMT_YUYV; - fh->fmt = format_by_fourcc(pix_format); + dev->channel_opened = VIDEO_IOCTL_CH; + pix_format = V4L2_PIX_FMT_YUYV; + fh->fmt = format_by_fourcc(pix_format); - v4l2_prio_open(&dev->prio,&fh->prio); + v4l2_prio_open(&dev->prio, &fh->prio); - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); - return 0; + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO_IOCTL)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO_IOCTL)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; - - return 0; -} + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + return POLLIN | POLLRDNORM; + + return 0; +} static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO_IOCTL); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO_IOCTL)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO_IOCTL); + } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); + v4l2_prio_close(&dev->prio, &fh->prio); - file->private_data = NULL; - kfree(fh); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO_IOCTL)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO_IOCTL)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO_IOCTL); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO_IOCTL); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vidq.field = f->fmt.pix.field; - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - return 0; + return err; + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vidq.field = f->fmt.pix.field; + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct cx25821_fh *fh = priv; - return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + struct cx25821_fh *fh = priv; + return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); } -static long video_ioctl_set(struct file *file, unsigned int cmd, unsigned long arg) +static long video_ioctl_set(struct file *file, unsigned int cmd, + unsigned long arg) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - struct downstream_user_struct *data_from_user; - int command; - int width = 720; - int selected_channel = 0, pix_format = 0, i = 0; - int cif_enable = 0, cif_width = 0; - u32 value = 0; - - - data_from_user = (struct downstream_user_struct *)arg; - - if( !data_from_user ) - { - printk("cx25821 in %s(): User data is INVALID. Returning.\n", __func__); - return 0; - } + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + struct downstream_user_struct *data_from_user; + int command; + int width = 720; + int selected_channel = 0, pix_format = 0, i = 0; + int cif_enable = 0, cif_width = 0; + u32 value = 0; + + data_from_user = (struct downstream_user_struct *)arg; + + if (!data_from_user) { + printk("cx25821 in %s(): User data is INVALID. Returning.\n", + __func__); + return 0; + } - command = data_from_user->command; - - if( command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT && command != ENABLE_CIF_RESOLUTION && - command != REG_READ && command != REG_WRITE && command != MEDUSA_READ && command != MEDUSA_WRITE) - { - return 0; - } + command = data_from_user->command; + if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT + && command != ENABLE_CIF_RESOLUTION && command != REG_READ + && command != REG_WRITE && command != MEDUSA_READ + && command != MEDUSA_WRITE) { + return 0; + } - switch(command) - { + switch (command) { case SET_VIDEO_STD: - dev->tvnorm = !strcmp(data_from_user->vid_stdname,"PAL") ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; - medusa_set_videostandard(dev); - break; + dev->tvnorm = + !strcmp(data_from_user->vid_stdname, + "PAL") ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; + medusa_set_videostandard(dev); + break; case SET_PIXEL_FORMAT: - selected_channel = data_from_user->decoder_select; - pix_format = data_from_user->pixel_format; + selected_channel = data_from_user->decoder_select; + pix_format = data_from_user->pixel_format; - if( !(selected_channel <= 7 && selected_channel >= 0) ) - { - selected_channel -= 4; - selected_channel = selected_channel % 8; - } + if (!(selected_channel <= 7 && selected_channel >= 0)) { + selected_channel -= 4; + selected_channel = selected_channel % 8; + } - if( selected_channel >= 0 ) - cx25821_set_pixel_format( dev, selected_channel, pix_format ); + if (selected_channel >= 0) + cx25821_set_pixel_format(dev, selected_channel, + pix_format); - break; + break; case ENABLE_CIF_RESOLUTION: - selected_channel = data_from_user->decoder_select; - cif_enable = data_from_user->cif_resolution_enable; - cif_width = data_from_user->cif_width; - - if( cif_enable ) - { - if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK ) - width = 352; - else - width = (cif_width == 320 || cif_width == 352) ? cif_width : 320; - } - - if( !(selected_channel <= 7 && selected_channel >= 0) ) - { - selected_channel -= 4; - selected_channel = selected_channel % 8; - } - - - if( selected_channel <= 7 && selected_channel >= 0 ) - { - dev->use_cif_resolution[selected_channel] = cif_enable; - dev->cif_width[selected_channel] = width; - } - else - { - for( i=0; i < VID_CHANNEL_NUM; i++ ) - { - dev->use_cif_resolution[i] = cif_enable; - dev->cif_width[i] = width; + selected_channel = data_from_user->decoder_select; + cif_enable = data_from_user->cif_resolution_enable; + cif_width = data_from_user->cif_width; + + if (cif_enable) { + if (dev->tvnorm & V4L2_STD_PAL_BG + || dev->tvnorm & V4L2_STD_PAL_DK) + width = 352; + else + width = (cif_width == 320 + || cif_width == 352) ? cif_width : 320; } - } - medusa_set_resolution( dev, width, selected_channel ); - break; + if (!(selected_channel <= 7 && selected_channel >= 0)) { + selected_channel -= 4; + selected_channel = selected_channel % 8; + } + + if (selected_channel <= 7 && selected_channel >= 0) { + dev->use_cif_resolution[selected_channel] = cif_enable; + dev->cif_width[selected_channel] = width; + } else { + for (i = 0; i < VID_CHANNEL_NUM; i++) { + dev->use_cif_resolution[i] = cif_enable; + dev->cif_width[i] = width; + } + } + + medusa_set_resolution(dev, width, selected_channel); + break; case REG_READ: data_from_user->reg_data = cx_read(data_from_user->reg_address); - break; + break; case REG_WRITE: cx_write(data_from_user->reg_address, data_from_user->reg_data); - break; + break; case MEDUSA_READ: - value = cx25821_i2c_read(&dev->i2c_bus[0], (u16)data_from_user->reg_address, &data_from_user->reg_data); - break; + value = + cx25821_i2c_read(&dev->i2c_bus[0], + (u16) data_from_user->reg_address, + &data_from_user->reg_data); + break; case MEDUSA_WRITE: - cx25821_i2c_write(&dev->i2c_bus[0], (u16)data_from_user->reg_address, data_from_user->reg_data); - break; - } + cx25821_i2c_write(&dev->i2c_bus[0], + (u16) data_from_user->reg_address, + data_from_user->reg_data); + break; + } - return 0; + return 0; } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + cx25821_call_all(dev, core, log_status); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; - } + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } return 0; } + // exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl_set, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl_set, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_videoioctl_template = { - .name = "cx25821-videoioctl", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-videoioctl", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821-vidups10.c b/linux/drivers/staging/cx25821/cx25821-vidups10.c index 1e18a8766..77b63b060 100644 --- a/linux/drivers/staging/cx25821/cx25821-vidups10.c +++ b/linux/drivers/staging/cx25821/cx25821-vidups10.c @@ -23,421 +23,413 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH10]; - - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH10]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH10]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[SRAM_CH10]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH10] && h->video_dev[SRAM_CH10]->minor == minor) { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH10] + && h->video_dev[SRAM_CH10]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; - } + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; - dev->channel_opened = 9; - fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); + dev->channel_opened = 9; + fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); - v4l2_prio_open(&dev->prio,&fh->prio); + v4l2_prio_open(&dev->prio, &fh->prio); - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); - return 0; + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO10)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO10)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO10)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; - return 0; + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO10)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + return POLLIN | POLLRDNORM; + return 0; } static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - //cx_write(channel10->dma_ctl, 0); + //stop the risc engine and fifo + //cx_write(channel10->dma_ctl, 0); - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO10)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO10); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO10)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO10); + } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); + v4l2_prio_close(&dev->prio, &fh->prio); - file->private_data = NULL; - kfree(fh); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO10)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO10)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO10); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO10); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } - -static long video_ioctl_upstream10(struct file *file, unsigned int cmd, unsigned long arg) +static long video_ioctl_upstream10(struct file *file, unsigned int cmd, + unsigned long arg) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - int command = 0; - struct upstream_user_struct *data_from_user; - - - data_from_user = (struct upstream_user_struct *)arg; - - if( !data_from_user ) - { - printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); - return 0; - } - - command = data_from_user->command; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + int command = 0; + struct upstream_user_struct *data_from_user; + + data_from_user = (struct upstream_user_struct *)arg; + + if (!data_from_user) { + printk + ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", + __func__); + return 0; + } - if( command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO ) - { - return 0; - } + command = data_from_user->command; - dev->input_filename_ch2 = data_from_user->input_filename; - dev->input_audiofilename = data_from_user->input_filename; - dev->vid_stdname_ch2 = data_from_user->vid_stdname; - dev->pixel_format_ch2 = data_from_user->pixel_format; - dev->channel_select_ch2 = data_from_user->channel_select; - dev->command_ch2 = data_from_user->command; + if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) { + return 0; + } + dev->input_filename_ch2 = data_from_user->input_filename; + dev->input_audiofilename = data_from_user->input_filename; + dev->vid_stdname_ch2 = data_from_user->vid_stdname; + dev->pixel_format_ch2 = data_from_user->pixel_format; + dev->channel_select_ch2 = data_from_user->channel_select; + dev->command_ch2 = data_from_user->command; - switch(command) - { + switch (command) { case UPSTREAM_START_VIDEO: - cx25821_start_upstream_video_ch2(dev, data_from_user); - break; + cx25821_start_upstream_video_ch2(dev, data_from_user); + break; case UPSTREAM_STOP_VIDEO: - cx25821_stop_upstream_video_ch2(dev); - break; - } + cx25821_stop_upstream_video_ch2(dev); + break; + } - return 0; + return 0; } - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vidq.field = f->fmt.pix.field; - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - return 0; + return err; + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vidq.field = f->fmt.pix.field; + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct cx25821_fh *fh = priv; - return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + struct cx25821_fh *fh = priv; + return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + cx25821_call_all(dev, core, log_status); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; - - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; - } + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } - return 0; + return 0; } //exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl_upstream10, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl_upstream10, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_video_template10 = { - .name = "cx25821-upstream10", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-upstream10", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821-vidups9.c b/linux/drivers/staging/cx25821/cx25821-vidups9.c index 947ea5bc8..75c8c1eed 100644 --- a/linux/drivers/staging/cx25821/cx25821-vidups9.c +++ b/linux/drivers/staging/cx25821/cx25821-vidups9.c @@ -23,419 +23,411 @@ #include "cx25821-video.h" - static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb); - struct cx25821_buffer *prev; - struct cx25821_fh *fh = vq->priv_data; - struct cx25821_dev *dev = fh->dev; - struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH09]; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ - - dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue, &q->active); - cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH09]); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", - buf, buf->vb. i, buf->count, q->count); - } else { - prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - - /* 64 bit bits 63-32 */ - prev->risc.jmp[2] = cpu_to_le32(0); - dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", buf, buf->vb.i, buf->count); - + struct cx25821_buffer *buf = + container_of(vb, struct cx25821_buffer, vb); + struct cx25821_buffer *prev; + struct cx25821_fh *fh = vq->priv_data; + struct cx25821_dev *dev = fh->dev; + struct cx25821_dmaqueue *q = &dev->vidq[SRAM_CH09]; + + /* add jump to stopper */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); + buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ + + dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); + + if (!list_empty(&q->queued)) { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, + buf->vb.i); + + } else if (list_empty(&q->active)) { + list_add_tail(&buf->vb.queue, &q->active); + cx25821_start_video_dma(dev, q, buf, + &dev->sram_channels[SRAM_CH09]); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); + dprintk(2, + "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", + buf, buf->vb.i, buf->count, q->count); } else { - list_add_tail(&buf->vb.queue, &q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i); + prev = + list_entry(q->active.prev, struct cx25821_buffer, vb.queue); + if (prev->vb.width == buf->vb.width + && prev->vb.height == buf->vb.height + && prev->fmt == buf->fmt) { + list_add_tail(&buf->vb.queue, &q->active); + buf->vb.state = VIDEOBUF_ACTIVE; + buf->count = q->count++; + prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); + + /* 64 bit bits 63-32 */ + prev->risc.jmp[2] = cpu_to_le32(0); + dprintk(2, + "[%p/%d] buffer_queue - append to active, buf->count=%d\n", + buf, buf->vb.i, buf->count); + + } else { + list_add_tail(&buf->vb.queue, &q->queued); + buf->vb.state = VIDEOBUF_QUEUED; + dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, + buf->vb.i); + } } - } - if (list_empty(&q->active)) - { - dprintk(2, "active queue empty!\n"); - } + if (list_empty(&q->active)) { + dprintk(2, "active queue empty!\n"); + } } - static struct videobuf_queue_ops cx25821_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, }; - static int video_open(struct file *file) { - int minor = video_devdata(file)->minor; - struct cx25821_dev *h, *dev = NULL; - struct cx25821_fh *fh; - struct list_head *list; - enum v4l2_buf_type type = 0; - - lock_kernel(); - list_for_each(list, &cx25821_devlist) - { - h = list_entry(list, struct cx25821_dev, devlist); - - if (h->video_dev[SRAM_CH09] && h->video_dev[SRAM_CH09]->minor == minor) - { - dev = h; - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + int minor = video_devdata(file)->minor; + struct cx25821_dev *h, *dev = NULL; + struct cx25821_fh *fh; + struct list_head *list; + enum v4l2_buf_type type = 0; + + lock_kernel(); + list_for_each(list, &cx25821_devlist) { + h = list_entry(list, struct cx25821_dev, devlist); + + if (h->video_dev[SRAM_CH09] + && h->video_dev[SRAM_CH09]->minor == minor) { + dev = h; + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } } - } - if (NULL == dev) { - unlock_kernel(); - return -ENODEV; - } + if (NULL == dev) { + unlock_kernel(); + return -ENODEV; + } - printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); + printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]); - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh), GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); - return -ENOMEM; - } + /* allocate + initialize per filehandle data */ + fh = kzalloc(sizeof(*fh), GFP_KERNEL); + if (NULL == fh) { + unlock_kernel(); + return -ENOMEM; + } - file->private_data = fh; - fh->dev = dev; - fh->type = type; - fh->width = 720; + file->private_data = fh; + fh->dev = dev; + fh->type = type; + fh->width = 720; - if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) - fh->height = 576; - else - fh->height = 480; + if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) + fh->height = 576; + else + fh->height = 480; - dev->channel_opened = 8; - fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); + dev->channel_opened = 8; + fh->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); - v4l2_prio_open(&dev->prio,&fh->prio); + v4l2_prio_open(&dev->prio, &fh->prio); - videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx25821_buffer), - fh); + videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, + &dev->pci->dev, &dev->slock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_INTERLACED, + sizeof(struct cx25821_buffer), fh); - dprintk(1, "post videobuf_queue_init()\n"); - unlock_kernel(); + dprintk(1, "post videobuf_queue_init()\n"); + unlock_kernel(); - return 0; + return 0; } -static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char __user * data, size_t count, + loff_t * ppos) { - struct cx25821_fh *fh = file->private_data; + struct cx25821_fh *fh = file->private_data; - switch (fh->type) - { + switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (res_locked(fh->dev, RESOURCE_VIDEO9)) - return -EBUSY; + if (res_locked(fh->dev, RESOURCE_VIDEO9)) + return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK); + return videobuf_read_one(&fh->vidq, data, count, ppos, + file->f_flags & O_NONBLOCK); default: - BUG(); - return 0; - } + BUG(); + return 0; + } } -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int video_poll(struct file *file, + struct poll_table_struct *wait) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_buffer *buf; - - if (res_check(fh, RESOURCE_VIDEO9)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - return POLLERR; - buf = list_entry(fh->vidq.stream.next, - struct cx25821_buffer, vb.stream); - } else { - /* read() capture */ - buf = (struct cx25821_buffer *)fh->vidq.read_buf; - if (NULL == buf) - return POLLERR; - } - - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; - return 0; -} + struct cx25821_fh *fh = file->private_data; + struct cx25821_buffer *buf; + + if (res_check(fh, RESOURCE_VIDEO9)) { + /* streaming capture */ + if (list_empty(&fh->vidq.stream)) + return POLLERR; + buf = list_entry(fh->vidq.stream.next, + struct cx25821_buffer, vb.stream); + } else { + /* read() capture */ + buf = (struct cx25821_buffer *)fh->vidq.read_buf; + if (NULL == buf) + return POLLERR; + } + poll_wait(file, &buf->vb.done, wait); + if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) + return POLLIN | POLLRDNORM; + return 0; +} static int video_release(struct file *file) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; - //stop the risc engine and fifo - //cx_write(channel9->dma_ctl, 0); + //stop the risc engine and fifo + //cx_write(channel9->dma_ctl, 0); - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO9)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev, fh, RESOURCE_VIDEO9); - } + /* stop video capture */ + if (res_check(fh, RESOURCE_VIDEO9)) { + videobuf_queue_cancel(&fh->vidq); + res_free(dev, fh, RESOURCE_VIDEO9); + } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq, fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } + if (fh->vidq.read_buf) { + buffer_release(&fh->vidq, fh->vidq.read_buf); + kfree(fh->vidq.read_buf); + } - videobuf_mmap_free(&fh->vidq); + videobuf_mmap_free(&fh->vidq); - v4l2_prio_close(&dev->prio,&fh->prio); + v4l2_prio_close(&dev->prio, &fh->prio); - file->private_data = NULL; - kfree(fh); + file->private_data = NULL; + kfree(fh); - return 0; + return 0; } - static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) - { - return -EINVAL; - } + if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + return -EINVAL; + } - if (unlikely(i != fh->type)) - { - return -EINVAL; - } + if (unlikely(i != fh->type)) { + return -EINVAL; + } - if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO9)))) - { - return -EBUSY; - } + if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO9)))) { + return -EBUSY; + } - return videobuf_streamon(get_queue(fh)); + return videobuf_streamon(get_queue(fh)); } static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = fh->dev; - int err, res; - - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - if (i != fh->type) - return -EINVAL; - - res = get_resource(fh, RESOURCE_VIDEO9); - err = videobuf_streamoff(get_queue(fh)); - if (err < 0) - return err; - res_free(dev, fh, res); - return 0; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = fh->dev; + int err, res; + + if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (i != fh->type) + return -EINVAL; + + res = get_resource(fh, RESOURCE_VIDEO9); + err = videobuf_streamoff(get_queue(fh)); + if (err < 0) + return err; + res_free(dev, fh, res); + return 0; } - -static long video_ioctl_upstream9(struct file *file, unsigned int cmd, unsigned long arg) +static long video_ioctl_upstream9(struct file *file, unsigned int cmd, + unsigned long arg) { - struct cx25821_fh *fh = file->private_data; - struct cx25821_dev *dev = fh->dev; - int command = 0; - struct upstream_user_struct *data_from_user; - - - data_from_user = (struct upstream_user_struct *)arg; - - if( !data_from_user ) - { - printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__); - return 0; - } - - command = data_from_user->command; - - if( command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO ) - { - return 0; - } + struct cx25821_fh *fh = file->private_data; + struct cx25821_dev *dev = fh->dev; + int command = 0; + struct upstream_user_struct *data_from_user; + + data_from_user = (struct upstream_user_struct *)arg; + + if (!data_from_user) { + printk + ("cx25821 in %s(): Upstream data is INVALID. Returning.\n", + __func__); + return 0; + } + command = data_from_user->command; - dev->input_filename = data_from_user->input_filename; - dev->input_audiofilename = data_from_user->input_filename; - dev->vid_stdname = data_from_user->vid_stdname; - dev->pixel_format = data_from_user->pixel_format; - dev->channel_select = data_from_user->channel_select; - dev->command = data_from_user->command; + if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) { + return 0; + } + dev->input_filename = data_from_user->input_filename; + dev->input_audiofilename = data_from_user->input_filename; + dev->vid_stdname = data_from_user->vid_stdname; + dev->pixel_format = data_from_user->pixel_format; + dev->channel_select = data_from_user->channel_select; + dev->command = data_from_user->command; - switch(command) - { + switch (command) { case UPSTREAM_START_VIDEO: - cx25821_start_upstream_video_ch1(dev, data_from_user); - break; + cx25821_start_upstream_video_ch1(dev, data_from_user); + break; case UPSTREAM_STOP_VIDEO: - cx25821_stop_upstream_video_ch1(dev); - break; - } + cx25821_stop_upstream_video_ch1(dev); + break; + } - return 0; + return 0; } - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) { - struct cx25821_fh *fh = priv; - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - int err; + struct cx25821_fh *fh = priv; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + int err; + + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } + + dprintk(2, "%s()\n", __func__); + err = vidioc_try_fmt_vid_cap(file, priv, f); - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) - return err; - } - - dprintk(2, "%s()\n", __func__); - err = vidioc_try_fmt_vid_cap(file, priv, f); - - if (0 != err) - return err; - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - fh->vidq.field = f->fmt.pix.field; - dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); - cx25821_call_all(dev, video, s_fmt, f); - return 0; + return err; + fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + fh->vidq.field = f->fmt.pix.field; + dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, + fh->height, fh->vidq.field); + cx25821_call_all(dev, video, s_fmt, f); + return 0; } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct cx25821_fh *fh = priv; - return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); + struct cx25821_fh *fh = priv; + return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); } -static int vidioc_log_status (struct file *file, void *priv) +static int vidioc_log_status(struct file *file, void *priv) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - char name[32 + 2]; + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + char name[32 + 2]; - snprintf(name, sizeof(name), "%s/2", dev->name); - printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", + snprintf(name, sizeof(name), "%s/2", dev->name); + printk(KERN_INFO "%s/2: ============ START LOG STATUS ============\n", dev->name); - cx25821_call_all(dev, core, log_status); - printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", + cx25821_call_all(dev, core, log_status); + printk(KERN_INFO "%s/2: ============= END LOG STATUS =============\n", dev->name); - return 0; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctl) + struct v4l2_control *ctl) { - struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; - struct cx25821_fh *fh = priv; - int err; - if (fh) - { - err = v4l2_prio_check(&dev->prio, &fh->prio); - if (0 != err) - return err; - } + struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; + struct cx25821_fh *fh = priv; + int err; + if (fh) { + err = v4l2_prio_check(&dev->prio, &fh->prio); + if (0 != err) + return err; + } - return 0; + return 0; } + // exported stuff static const struct v4l2_file_operations video_fops = { - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .ioctl = video_ioctl_upstream9, + .owner = THIS_MODULE, + .open = video_open, + .release = video_release, + .read = video_read, + .poll = video_poll, + .mmap = video_mmap, + .ioctl = video_ioctl_upstream9, }; static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, + .vidioc_querycap = vidioc_querycap, + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vidioc_reqbufs, + .vidioc_querybuf = vidioc_querybuf, + .vidioc_qbuf = vidioc_qbuf, + .vidioc_dqbuf = vidioc_dqbuf, #ifdef TUNER_FLAG - .vidioc_s_std = vidioc_s_std, - .vidioc_querystd = vidioc_querystd, + .vidioc_s_std = vidioc_s_std, + .vidioc_querystd = vidioc_querystd, #endif - .vidioc_cropcap = vidioc_cropcap, - .vidioc_s_crop = vidioc_s_crop, - .vidioc_g_crop = vidioc_g_crop, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_log_status = vidioc_log_status, - .vidioc_g_priority = vidioc_g_priority, - .vidioc_s_priority = vidioc_s_priority, + .vidioc_cropcap = vidioc_cropcap, + .vidioc_s_crop = vidioc_s_crop, + .vidioc_g_crop = vidioc_g_crop, + .vidioc_enum_input = vidioc_enum_input, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_streamon = vidioc_streamon, + .vidioc_streamoff = vidioc_streamoff, + .vidioc_log_status = vidioc_log_status, + .vidioc_g_priority = vidioc_g_priority, + .vidioc_s_priority = vidioc_s_priority, #ifdef CONFIG_VIDEO_V4L1_COMPAT - .vidiocgmbuf = vidiocgmbuf, + .vidiocgmbuf = vidiocgmbuf, #endif #ifdef TUNER_FLAG - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, #endif #ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, #endif }; struct video_device cx25821_video_template9 = { - .name = "cx25821-upstream9", - .fops = &video_fops, - .minor = -1, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX25821_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .name = "cx25821-upstream9", + .fops = &video_fops, + .minor = -1, + .ioctl_ops = &video_ioctl_ops, + .tvnorms = CX25821_NORMS, + .current_norm = V4L2_STD_NTSC_M, }; - - - diff --git a/linux/drivers/staging/cx25821/cx25821.h b/linux/drivers/staging/cx25821/cx25821.h index a70c61b61..c1fad805e 100644 --- a/linux/drivers/staging/cx25821/cx25821.h +++ b/linux/drivers/staging/cx25821/cx25821.h @@ -21,7 +21,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - #ifndef CX25821_H_ #define CX25821_H_ @@ -86,8 +85,7 @@ #define RESOURCE_VIDEO11 2048 #define RESOURCE_VIDEO_IOCTL 4096 - -#define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ +#define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ #define UNKNOWN_BOARD 0 #define CX25821_BOARD 1 @@ -104,338 +102,336 @@ #define VID_CHANNEL_NUM 8 struct cx25821_fmt { - char *name; - u32 fourcc; /* v4l2 format id */ - int depth; - int flags; - u32 cxformat; + char *name; + u32 fourcc; /* v4l2 format id */ + int depth; + int flags; + u32 cxformat; }; struct cx25821_ctrl { - struct v4l2_queryctrl v; - u32 off; - u32 reg; - u32 mask; - u32 shift; + struct v4l2_queryctrl v; + u32 off; + u32 reg; + u32 mask; + u32 shift; }; struct cx25821_tvnorm { - char *name; - v4l2_std_id id; - u32 cxiformat; - u32 cxoformat; + char *name; + v4l2_std_id id; + u32 cxiformat; + u32 cxoformat; }; struct cx25821_fh { - struct cx25821_dev *dev; - enum v4l2_buf_type type; - int radio; - u32 resources; + struct cx25821_dev *dev; + enum v4l2_buf_type type; + int radio; + u32 resources; - enum v4l2_priority prio; + enum v4l2_priority prio; - /* video overlay */ - struct v4l2_window win; - struct v4l2_clip *clips; - unsigned int nclips; + /* video overlay */ + struct v4l2_window win; + struct v4l2_clip *clips; + unsigned int nclips; - /* video capture */ - struct cx25821_fmt *fmt; - unsigned int width, height; + /* video capture */ + struct cx25821_fmt *fmt; + unsigned int width, height; - /* vbi capture */ - struct videobuf_queue vidq; - struct videobuf_queue vbiq; + /* vbi capture */ + struct videobuf_queue vidq; + struct videobuf_queue vbiq; - /* H264 Encoder specifics ONLY */ - struct videobuf_queue mpegq; - atomic_t v4l_reading; + /* H264 Encoder specifics ONLY */ + struct videobuf_queue mpegq; + atomic_t v4l_reading; }; enum cx25821_itype { - CX25821_VMUX_COMPOSITE = 1, - CX25821_VMUX_SVIDEO, - CX25821_VMUX_DEBUG, - CX25821_RADIO, + CX25821_VMUX_COMPOSITE = 1, + CX25821_VMUX_SVIDEO, + CX25821_VMUX_DEBUG, + CX25821_RADIO, }; enum cx25821_src_sel_type { - CX25821_SRC_SEL_EXT_656_VIDEO = 0, - CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO + CX25821_SRC_SEL_EXT_656_VIDEO = 0, + CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO }; /* buffer for one video frame */ struct cx25821_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - /* cx25821 specific */ - unsigned int bpl; - struct btcx_riscmem risc; - struct cx25821_fmt *fmt; - u32 count; + /* common v4l buffer stuff -- must be first */ + struct videobuf_buffer vb; + + /* cx25821 specific */ + unsigned int bpl; + struct btcx_riscmem risc; + struct cx25821_fmt *fmt; + u32 count; }; struct cx25821_input { - enum cx25821_itype type; - unsigned int vmux; - u32 gpio0, gpio1, gpio2, gpio3; + enum cx25821_itype type; + unsigned int vmux; + u32 gpio0, gpio1, gpio2, gpio3; }; typedef enum { - CX25821_UNDEFINED = 0, - CX25821_RAW, - CX25821_264 + CX25821_UNDEFINED = 0, + CX25821_RAW, + CX25821_264 } port_t; struct cx25821_board { - char *name; - port_t porta, portb, portc; - unsigned int tuner_type; - unsigned int radio_type; - unsigned char tuner_addr; - unsigned char radio_addr; - - u32 clk_freq; - struct cx25821_input input[2]; + char *name; + port_t porta, portb, portc; + unsigned int tuner_type; + unsigned int radio_type; + unsigned char tuner_addr; + unsigned char radio_addr; + + u32 clk_freq; + struct cx25821_input input[2]; }; struct cx25821_subid { - u16 subvendor; - u16 subdevice; - u32 card; + u16 subvendor; + u16 subdevice; + u32 card; }; struct cx25821_i2c { - struct cx25821_dev *dev; - - int nr; - - /* i2c i/o */ - struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; - struct i2c_client i2c_client; - u32 i2c_rc; - - /* cx25821 registers used for raw addess */ - u32 i2c_period; - u32 reg_ctrl; - u32 reg_stat; - u32 reg_addr; - u32 reg_rdata; - u32 reg_wdata; + struct cx25821_dev *dev; + + int nr; + + /* i2c i/o */ + struct i2c_adapter i2c_adap; + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + u32 i2c_rc; + + /* cx25821 registers used for raw addess */ + u32 i2c_period; + u32 reg_ctrl; + u32 reg_stat; + u32 reg_addr; + u32 reg_rdata; + u32 reg_wdata; }; struct cx25821_dmaqueue { - struct list_head active; - struct list_head queued; - struct timer_list timeout; - struct btcx_riscmem stopper; - u32 count; + struct list_head active; + struct list_head queued; + struct timer_list timeout; + struct btcx_riscmem stopper; + u32 count; }; struct cx25821_data { - struct cx25821_dev *dev; - struct sram_channel *channel; + struct cx25821_dev *dev; + struct sram_channel *channel; }; struct cx25821_dev { - struct list_head devlist; - atomic_t refcount; - struct v4l2_device v4l2_dev; - - struct v4l2_prio_state prio; - - /* pci stuff */ - struct pci_dev *pci; - unsigned char pci_rev, pci_lat; - int pci_bus, pci_slot; - u32 base_io_addr; - u32 __iomem *lmmio; - u8 __iomem *bmmio; - int pci_irqmask; - int hwrevision; - - u32 clk_freq; - - /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ - struct cx25821_i2c i2c_bus[3]; - - int nr; - struct mutex lock; - - /* board details */ - unsigned int board; - char name[32]; - - /* sram configuration */ - struct sram_channel *sram_channels; - - /* Analog video */ - u32 resources; - unsigned int input; - u32 tvaudio; - v4l2_std_id tvnorm; - unsigned int tuner_type; - unsigned char tuner_addr; - unsigned int radio_type; - unsigned char radio_addr; - unsigned int has_radio; - unsigned int videc_type; - unsigned char videc_addr; - unsigned short _max_num_decoders; - - int ctl_bright; - int ctl_contrast; - int ctl_hue; - int ctl_saturation; - - struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; - - /* Analog Audio Upstream */ - int _audio_is_running; - int _audiopixel_format; - int _is_first_audio_frame; - int _audiofile_status; - int _audio_lines_count; - int _audioframe_count; - int _audio_upstream_channel_select; - int _last_index_irq; //The last interrupt index processed. - - __le32 * _risc_audio_jmp_addr; - __le32 * _risc_virt_start_addr; - __le32 * _risc_virt_addr; - dma_addr_t _risc_phys_addr; - dma_addr_t _risc_phys_start_addr; - - unsigned int _audiorisc_size; - unsigned int _audiodata_buf_size; - __le32 * _audiodata_buf_virt_addr; - dma_addr_t _audiodata_buf_phys_addr; - char *_audiofilename; - - /* V4l */ - u32 freq; - struct video_device *video_dev[MAX_VID_CHANNEL_NUM]; - struct video_device *vbi_dev; - struct video_device *radio_dev; - struct video_device *ioctl_dev; - - struct cx25821_dmaqueue vidq[MAX_VID_CHANNEL_NUM]; - spinlock_t slock; - - /* Video Upstream */ - int _line_size; - int _prog_cnt; - int _pixel_format; - int _is_first_frame; - int _is_running; - int _file_status; - int _lines_count; - int _frame_count; - int _channel_upstream_select; - unsigned int _risc_size; - - __le32 * _dma_virt_start_addr; - __le32 * _dma_virt_addr; - dma_addr_t _dma_phys_addr; - dma_addr_t _dma_phys_start_addr; - - unsigned int _data_buf_size; - __le32 * _data_buf_virt_addr; - dma_addr_t _data_buf_phys_addr; - char * _filename; - char * _defaultname; - - - int _line_size_ch2; - int _prog_cnt_ch2; - int _pixel_format_ch2; - int _is_first_frame_ch2; - int _is_running_ch2; - int _file_status_ch2; - int _lines_count_ch2; - int _frame_count_ch2; - int _channel2_upstream_select; - unsigned int _risc_size_ch2; - - __le32 * _dma_virt_start_addr_ch2; - __le32 * _dma_virt_addr_ch2; - dma_addr_t _dma_phys_addr_ch2; - dma_addr_t _dma_phys_start_addr_ch2; - - unsigned int _data_buf_size_ch2; - __le32 * _data_buf_virt_addr_ch2; - dma_addr_t _data_buf_phys_addr_ch2; - char * _filename_ch2; - char * _defaultname_ch2; - - /* MPEG Encoder ONLY settings */ - u32 cx23417_mailbox; - struct cx2341x_mpeg_params mpeg_params; - struct video_device *v4l_device; - atomic_t v4l_reader_count; - struct cx25821_tvnorm encodernorm; - - u32 upstream_riscbuf_size; - u32 upstream_databuf_size; - u32 upstream_riscbuf_size_ch2; - u32 upstream_databuf_size_ch2; - u32 audio_upstream_riscbuf_size; - u32 audio_upstream_databuf_size; - int _isNTSC; - int _frame_index; - int _audioframe_index; - struct workqueue_struct * _irq_queues; - struct work_struct _irq_work_entry; - struct workqueue_struct * _irq_queues_ch2; - struct work_struct _irq_work_entry_ch2; - struct workqueue_struct * _irq_audio_queues; - struct work_struct _audio_work_entry; - char *input_filename; - char *input_filename_ch2; - int _frame_index_ch2; - int _isNTSC_ch2; - char *vid_stdname_ch2; - int pixel_format_ch2; - int channel_select_ch2; - int command_ch2; - char *input_audiofilename; - char *vid_stdname; - int pixel_format; - int channel_select; - int command; - int pixel_formats[VID_CHANNEL_NUM]; - int use_cif_resolution[VID_CHANNEL_NUM]; - int cif_width[VID_CHANNEL_NUM]; - int channel_opened; + struct list_head devlist; + atomic_t refcount; + struct v4l2_device v4l2_dev; + + struct v4l2_prio_state prio; + + /* pci stuff */ + struct pci_dev *pci; + unsigned char pci_rev, pci_lat; + int pci_bus, pci_slot; + u32 base_io_addr; + u32 __iomem *lmmio; + u8 __iomem *bmmio; + int pci_irqmask; + int hwrevision; + + u32 clk_freq; + + /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ + struct cx25821_i2c i2c_bus[3]; + + int nr; + struct mutex lock; + + /* board details */ + unsigned int board; + char name[32]; + + /* sram configuration */ + struct sram_channel *sram_channels; + + /* Analog video */ + u32 resources; + unsigned int input; + u32 tvaudio; + v4l2_std_id tvnorm; + unsigned int tuner_type; + unsigned char tuner_addr; + unsigned int radio_type; + unsigned char radio_addr; + unsigned int has_radio; + unsigned int videc_type; + unsigned char videc_addr; + unsigned short _max_num_decoders; + + int ctl_bright; + int ctl_contrast; + int ctl_hue; + int ctl_saturation; + + struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; + + /* Analog Audio Upstream */ + int _audio_is_running; + int _audiopixel_format; + int _is_first_audio_frame; + int _audiofile_status; + int _audio_lines_count; + int _audioframe_count; + int _audio_upstream_channel_select; + int _last_index_irq; //The last interrupt index processed. + + __le32 *_risc_audio_jmp_addr; + __le32 *_risc_virt_start_addr; + __le32 *_risc_virt_addr; + dma_addr_t _risc_phys_addr; + dma_addr_t _risc_phys_start_addr; + + unsigned int _audiorisc_size; + unsigned int _audiodata_buf_size; + __le32 *_audiodata_buf_virt_addr; + dma_addr_t _audiodata_buf_phys_addr; + char *_audiofilename; + + /* V4l */ + u32 freq; + struct video_device *video_dev[MAX_VID_CHANNEL_NUM]; + struct video_device *vbi_dev; + struct video_device *radio_dev; + struct video_device *ioctl_dev; + + struct cx25821_dmaqueue vidq[MAX_VID_CHANNEL_NUM]; + spinlock_t slock; + + /* Video Upstream */ + int _line_size; + int _prog_cnt; + int _pixel_format; + int _is_first_frame; + int _is_running; + int _file_status; + int _lines_count; + int _frame_count; + int _channel_upstream_select; + unsigned int _risc_size; + + __le32 *_dma_virt_start_addr; + __le32 *_dma_virt_addr; + dma_addr_t _dma_phys_addr; + dma_addr_t _dma_phys_start_addr; + + unsigned int _data_buf_size; + __le32 *_data_buf_virt_addr; + dma_addr_t _data_buf_phys_addr; + char *_filename; + char *_defaultname; + + int _line_size_ch2; + int _prog_cnt_ch2; + int _pixel_format_ch2; + int _is_first_frame_ch2; + int _is_running_ch2; + int _file_status_ch2; + int _lines_count_ch2; + int _frame_count_ch2; + int _channel2_upstream_select; + unsigned int _risc_size_ch2; + + __le32 *_dma_virt_start_addr_ch2; + __le32 *_dma_virt_addr_ch2; + dma_addr_t _dma_phys_addr_ch2; + dma_addr_t _dma_phys_start_addr_ch2; + + unsigned int _data_buf_size_ch2; + __le32 *_data_buf_virt_addr_ch2; + dma_addr_t _data_buf_phys_addr_ch2; + char *_filename_ch2; + char *_defaultname_ch2; + + /* MPEG Encoder ONLY settings */ + u32 cx23417_mailbox; + struct cx2341x_mpeg_params mpeg_params; + struct video_device *v4l_device; + atomic_t v4l_reader_count; + struct cx25821_tvnorm encodernorm; + + u32 upstream_riscbuf_size; + u32 upstream_databuf_size; + u32 upstream_riscbuf_size_ch2; + u32 upstream_databuf_size_ch2; + u32 audio_upstream_riscbuf_size; + u32 audio_upstream_databuf_size; + int _isNTSC; + int _frame_index; + int _audioframe_index; + struct workqueue_struct *_irq_queues; + struct work_struct _irq_work_entry; + struct workqueue_struct *_irq_queues_ch2; + struct work_struct _irq_work_entry_ch2; + struct workqueue_struct *_irq_audio_queues; + struct work_struct _audio_work_entry; + char *input_filename; + char *input_filename_ch2; + int _frame_index_ch2; + int _isNTSC_ch2; + char *vid_stdname_ch2; + int pixel_format_ch2; + int channel_select_ch2; + int command_ch2; + char *input_audiofilename; + char *vid_stdname; + int pixel_format; + int channel_select; + int command; + int pixel_formats[VID_CHANNEL_NUM]; + int use_cif_resolution[VID_CHANNEL_NUM]; + int cif_width[VID_CHANNEL_NUM]; + int channel_opened; }; - struct upstream_user_struct { - char *input_filename; - char *vid_stdname; - int pixel_format; - int channel_select; - int command; + char *input_filename; + char *vid_stdname; + int pixel_format; + int channel_select; + int command; }; struct downstream_user_struct { - char *vid_stdname; - int pixel_format; - int cif_resolution_enable; - int cif_width; - int decoder_select; - int command; - int reg_address; - int reg_data; + char *vid_stdname; + int pixel_format; + int cif_resolution_enable; + int cif_width; + int decoder_select; + int command; + int reg_address; + int reg_data; }; extern struct upstream_user_struct *up_data; static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev) { - return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev); + return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev); } #define cx25821_call_all(dev, o, f, args...) \ @@ -445,21 +441,19 @@ extern struct list_head cx25821_devlist; extern struct cx25821_board cx25821_boards[]; extern struct cx25821_subid cx25821_subids[]; -#define SRAM_CH00 0 /* Video A */ -#define SRAM_CH01 1 /* Video B */ -#define SRAM_CH02 2 /* Video C */ -#define SRAM_CH03 3 /* Video D */ -#define SRAM_CH04 4 /* Video E */ -#define SRAM_CH05 5 /* Video F */ -#define SRAM_CH06 6 /* Video G */ -#define SRAM_CH07 7 /* Video H */ - -#define SRAM_CH08 8 /* Audio A */ -#define SRAM_CH09 9 /* Video Upstream I */ -#define SRAM_CH10 10 /* Video Upstream J */ -#define SRAM_CH11 11 /* Audio Upstream AUD_CHANNEL_B */ - +#define SRAM_CH00 0 /* Video A */ +#define SRAM_CH01 1 /* Video B */ +#define SRAM_CH02 2 /* Video C */ +#define SRAM_CH03 3 /* Video D */ +#define SRAM_CH04 4 /* Video E */ +#define SRAM_CH05 5 /* Video F */ +#define SRAM_CH06 6 /* Video G */ +#define SRAM_CH07 7 /* Video H */ +#define SRAM_CH08 8 /* Audio A */ +#define SRAM_CH09 9 /* Video Upstream I */ +#define SRAM_CH10 10 /* Video Upstream J */ +#define SRAM_CH11 11 /* Audio Upstream AUD_CHANNEL_B */ #define VID_UPSTREAM_SRAM_CHANNEL_I SRAM_CH09 #define VID_UPSTREAM_SRAM_CHANNEL_J SRAM_CH10 @@ -467,38 +461,38 @@ extern struct cx25821_subid cx25821_subids[]; #define VIDEO_IOCTL_CH 11 struct sram_channel { - char *name; - u32 i; - u32 cmds_start; - u32 ctrl_start; - u32 cdt; - u32 fifo_start; - u32 fifo_size; - u32 ptr1_reg; - u32 ptr2_reg; - u32 cnt1_reg; - u32 cnt2_reg; - u32 int_msk; - u32 int_stat; - u32 int_mstat; - u32 dma_ctl; - u32 gpcnt_ctl; - u32 gpcnt; - u32 aud_length; - u32 aud_cfg; - u32 fld_aud_fifo_en; - u32 fld_aud_risc_en; - - //For Upstream Video - u32 vid_fmt_ctl; - u32 vid_active_ctl1; - u32 vid_active_ctl2; - u32 vid_cdt_size; - - u32 vip_ctl; - u32 pix_frmt; - u32 jumponly; - u32 irq_bit; + char *name; + u32 i; + u32 cmds_start; + u32 ctrl_start; + u32 cdt; + u32 fifo_start; + u32 fifo_size; + u32 ptr1_reg; + u32 ptr2_reg; + u32 cnt1_reg; + u32 cnt2_reg; + u32 int_msk; + u32 int_stat; + u32 int_mstat; + u32 dma_ctl; + u32 gpcnt_ctl; + u32 gpcnt; + u32 aud_length; + u32 aud_cfg; + u32 fld_aud_fifo_en; + u32 fld_aud_risc_en; + + //For Upstream Video + u32 vid_fmt_ctl; + u32 vid_active_ctl1; + u32 vid_active_ctl2; + u32 vid_cdt_size; + + u32 vip_ctl; + u32 pix_frmt; + u32 jumponly; + u32 irq_bit; }; extern struct sram_channel cx25821_sram_channels[]; @@ -522,70 +516,88 @@ extern struct sram_channel cx25821_sram_channels[]; #define CX25821_WARN(fmt, args...) printk(KERN_WARNING "cx25821(%d): " fmt, dev->board , ## args) #define CX25821_INFO(fmt, args...) printk(KERN_INFO "cx25821(%d): " fmt, dev->board , ## args) -extern int cx25821_i2c_register(struct cx25821_i2c *bus); +extern int cx25821_i2c_register(struct cx25821_i2c *bus); extern void cx25821_card_setup(struct cx25821_dev *dev); -extern int cx25821_ir_init(struct cx25821_dev *dev); -extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value); -extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value); -extern int cx25821_i2c_unregister(struct cx25821_i2c *bus); +extern int cx25821_ir_init(struct cx25821_dev *dev); +extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value); +extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value); +extern int cx25821_i2c_unregister(struct cx25821_i2c *bus); extern void cx25821_gpio_init(struct cx25821_dev *dev); -extern void cx25821_set_gpiopin_direction( struct cx25821_dev *dev, - int pin_number, - int pin_logic_value); - -extern int medusa_video_init(struct cx25821_dev *dev); -extern int medusa_set_videostandard(struct cx25821_dev *dev); -extern void medusa_set_resolution(struct cx25821_dev *dev, int width, int decoder_select); -extern int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder); -extern int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder); -extern int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder); -extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder); - -extern int cx25821_sram_channel_setup(struct cx25821_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc); +extern void cx25821_set_gpiopin_direction(struct cx25821_dev *dev, + int pin_number, int pin_logic_value); + +extern int medusa_video_init(struct cx25821_dev *dev); +extern int medusa_set_videostandard(struct cx25821_dev *dev); +extern void medusa_set_resolution(struct cx25821_dev *dev, int width, + int decoder_select); +extern int medusa_set_brightness(struct cx25821_dev *dev, int brightness, + int decoder); +extern int medusa_set_contrast(struct cx25821_dev *dev, int contrast, + int decoder); +extern int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder); +extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation, + int decoder); + +extern int cx25821_sram_channel_setup(struct cx25821_dev *dev, + struct sram_channel *ch, unsigned int bpl, + u32 risc); extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, - struct scatterlist *sglist, - unsigned int top_offset, - unsigned int bottom_offset, - unsigned int bpl, - unsigned int padding, - unsigned int lines); + struct scatterlist *sglist, + unsigned int top_offset, + unsigned int bottom_offset, + unsigned int bpl, + unsigned int padding, unsigned int lines); extern int cx25821_risc_databuffer_audio(struct pci_dev *pci, - struct btcx_riscmem *risc, - struct scatterlist *sglist, - unsigned int bpl, - unsigned int lines, - unsigned int lpi); -extern void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf); -extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,u32 reg, u32 mask, u32 value); -extern void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch); -extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channel *ch); - - -extern struct cx25821_dev* cx25821_dev_get(struct pci_dev *pci); -extern void cx25821_print_irqbits(char *name, char *tag, char **strings, int len, u32 bits, u32 mask); + struct btcx_riscmem *risc, + struct scatterlist *sglist, + unsigned int bpl, + unsigned int lines, unsigned int lpi); +extern void cx25821_free_buffer(struct videobuf_queue *q, + struct cx25821_buffer *buf); +extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, + u32 reg, u32 mask, u32 value); +extern void cx25821_sram_channel_dump(struct cx25821_dev *dev, + struct sram_channel *ch); +extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, + struct sram_channel *ch); + +extern struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci); +extern void cx25821_print_irqbits(char *name, char *tag, char **strings, + int len, u32 bits, u32 mask); extern void cx25821_dev_unregister(struct cx25821_dev *dev); extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, - struct sram_channel *ch, - unsigned int bpl, u32 risc); - -extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, int pixel_format); -extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, int pixel_format); -extern int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select); + struct sram_channel *ch, + unsigned int bpl, u32 risc); + +extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, + int channel_select, int pixel_format); +extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, + int channel_select, int pixel_format); +extern int cx25821_audio_upstream_init(struct cx25821_dev *dev, + int channel_select); extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev); extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev); extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev); -extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, struct upstream_user_struct *up_data); -extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, struct upstream_user_struct *up_data); -extern void cx25821_start_upstream_audio(struct cx25821_dev *dev, struct upstream_user_struct *up_data); +extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, + struct upstream_user_struct + *up_data); +extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, + struct upstream_user_struct + *up_data); +extern void cx25821_start_upstream_audio(struct cx25821_dev *dev, + struct upstream_user_struct *up_data); extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev); extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev); extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev); -extern int cx25821_sram_channel_setup_upstream( struct cx25821_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc); -extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel, u32 format); +extern int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, + struct sram_channel *ch, + unsigned int bpl, u32 risc); +extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel, + u32 format); extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev); extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, - struct pci_dev *pci, - struct video_device *template, - char *type); + struct pci_dev *pci, + struct video_device *template, + char *type); #endif -- cgit v1.2.3 From 456ab49bde813a457bdbc271321a7131209f7a34 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Sep 2009 11:39:12 -0300 Subject: cx25821: Fix some compilation troubles From: Mauro Carvalho Chehab Lindent caused some compilation breakages. There were also others related to some other changes at kernel KABI. There's still one missing warning fix against 2.6.30: /home/v4l/cx25821/v4l/cx25821-alsa.c: In function 'cx25821_audio_initdev': /home/v4l/cx25821/v4l/cx25821-alsa.c:706: warning: 'snd_card_new' is deprecated (declared at include/sound/core.h:306) Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/staging/cx25821/cx25821-alsa.c | 11 +++++------ linux/drivers/staging/cx25821/cx25821-core.c | 2 +- linux/drivers/staging/cx25821/cx25821-i2c.c | 1 - linux/drivers/staging/cx25821/cx25821-video.c | 4 ++-- v4l/versions.txt | 3 +++ 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/linux/drivers/staging/cx25821/cx25821-alsa.c b/linux/drivers/staging/cx25821/cx25821-alsa.c index e8b5ffc5b..bd532ecef 100644 --- a/linux/drivers/staging/cx25821/cx25821-alsa.c +++ b/linux/drivers/staging/cx25821/cx25821-alsa.c @@ -106,7 +106,7 @@ static int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol, static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = { 1,[1...(SNDRV_CARDS - 1)] = 1 }; +static int enable[SNDRV_CARDS] = { 1,[1 ... (SNDRV_CARDS - 1)] = 1 }; module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled."); @@ -702,14 +702,13 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) return (-ENOENT); } - card = - snd_card_new(index[devno], id[devno], THIS_MODULE, - sizeof(snd_cx25821_card_t)); - if (!card) { + err = snd_card_create(index[devno], id[devno], THIS_MODULE, + sizeof(snd_cx25821_card_t), &card); + if (err < 0) { printk(KERN_INFO "DEBUG ERROR: cannot create snd_card_new in %s\n", __func__); - return (-ENOMEM); + return err; } strcpy(card->driver, "cx25821"); diff --git a/linux/drivers/staging/cx25821/cx25821-core.c b/linux/drivers/staging/cx25821/cx25821-core.c index 3eca513c5..c820407a0 100644 --- a/linux/drivers/staging/cx25821/cx25821-core.c +++ b/linux/drivers/staging/cx25821/cx25821-core.c @@ -36,7 +36,7 @@ static unsigned int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "enable debug messages"); -static unsigned int card[] = {[0...(CX25821_MAXBOARDS - 1)] = UNSET }; +static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); MODULE_PARM_DESC(card, "card type"); diff --git a/linux/drivers/staging/cx25821/cx25821-i2c.c b/linux/drivers/staging/cx25821/cx25821-i2c.c index 3cec12201..0769f9519 100644 --- a/linux/drivers/staging/cx25821/cx25821-i2c.c +++ b/linux/drivers/staging/cx25821/cx25821-i2c.c @@ -332,7 +332,6 @@ static struct i2c_algorithm cx25821_i2c_algo_template = { static struct i2c_adapter cx25821_i2c_adap_template = { .name = "cx25821", .owner = THIS_MODULE, - .id = I2C_HW_B_CX25821, .algo = &cx25821_i2c_algo_template, #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) .class = I2C_CLASS_TV_ANALOG, diff --git a/linux/drivers/staging/cx25821/cx25821-video.c b/linux/drivers/staging/cx25821/cx25821-video.c index 938635313..8834bc80a 100644 --- a/linux/drivers/staging/cx25821/cx25821-video.c +++ b/linux/drivers/staging/cx25821/cx25821-video.c @@ -27,8 +27,8 @@ MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); MODULE_AUTHOR("Steven Toth "); MODULE_LICENSE("GPL"); -static unsigned int video_nr[] = {[0...(CX25821_MAXBOARDS - 1)] = UNSET }; -static unsigned int radio_nr[] = {[0...(CX25821_MAXBOARDS - 1)] = UNSET }; +static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; +static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; module_param_array(video_nr, int, NULL, 0444); module_param_array(radio_nr, int, NULL, 0444); diff --git a/v4l/versions.txt b/v4l/versions.txt index 1995c9006..f7caf396e 100644 --- a/v4l/versions.txt +++ b/v4l/versions.txt @@ -7,6 +7,9 @@ VIDEO_VPSS_SYSTEM VIDEO_VPFE_CAPTURE VIDEO_DM6446_CCDC VIDEO_DM355_CCDC +# Start version for those drivers - probably compile with older versions +VIDEO_CX25821 +VIDEO_CX25821_ALSA [2.6.29] # Needs defines that are only available from 2.6.29 -- cgit v1.2.3 From 8906956d60b8473b607b9a97ac73928e8c160df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Wed, 1 Jul 2009 07:49:23 +0200 Subject: gspca - m5602-s5k4aa: Add vflip quirk for the Amilo Pa 2548 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Erik Andrén Add vflip quirk for the Fujitsu Siemens Amilo Pa 2548 Priority: normal Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 1dd7c161f..6b17f56ac 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -48,6 +48,12 @@ static DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550") } + }, { + .ident = "Fujitsu-Siemens Amilo Pa 2548", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548") + } }, { .ident = "MSI GX700", .matches = { -- cgit v1.2.3 From b2a81d5ecbfe7db00ab13b0bc425d15d3c29ed85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Sun, 30 Aug 2009 14:43:40 +0200 Subject: gspca - m5602-s5k4aa: Add vflip quirk for the GX700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Brian Kloppenborg The MSI GX700 is a tricky machine to support. Some revisions do need the sensor flipped, but not all. Add another quirk, distinguished by its BIOS date. Priority: normal Signed-off-by: Brian Kloppenborg Signed-off-by: Erik Andrén --- linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 6b17f56ac..38a56294d 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -61,6 +61,13 @@ static DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), DMI_MATCH(DMI_BIOS_DATE, "07/26/2007") } + }, { + .ident = "MSI GX700", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), + DMI_MATCH(DMI_PRODUCT_NAME, "GX700"), + DMI_MATCH(DMI_BIOS_DATE, "07/19/2007") + } }, { .ident = "MSI GX700/GX705/EX700", .matches = { -- cgit v1.2.3