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/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 +- 21 files changed, 113 insertions(+), 270 deletions(-) (limited to 'linux/drivers') 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", -- 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/drivers/media/video/v4l2-dev.c | 55 ++++++++++-------------------------- 1 file changed, 15 insertions(+), 40 deletions(-) (limited to 'linux/drivers') 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 -- 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/drivers/media/video/v4l2-dev.c | 40 +++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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/drivers/media/video/gspca/Kconfig | 9 + linux/drivers/media/video/gspca/Makefile | 2 + linux/drivers/media/video/gspca/jeilinj.c | 388 ++++++++++++++++++++++++++++++ 3 files changed, 399 insertions(+) create mode 100644 linux/drivers/media/video/gspca/jeilinj.c (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 + 2 files changed, 57 insertions(+) (limited to 'linux/drivers') 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, -- 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(-) (limited to 'linux/drivers') 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 (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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/drivers/media/video/em28xx/em28xx-cards.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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/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 + 4 files changed, 52 insertions(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 + 6 files changed, 100 insertions(+), 1 deletion(-) (limited to 'linux/drivers') 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 -- 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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/drivers/media/video/cx88/cx88-input.c | 37 +++++++++++++---------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') 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); -- 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(-) (limited to 'linux/drivers') 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 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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 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/drivers/media/video/soc_camera.c | 61 +++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 15 deletions(-) (limited to 'linux/drivers') 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; } -- 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 +++--- 11 files changed, 682 insertions(+), 664 deletions(-) (limited to 'linux/drivers') 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; -- 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 +++++------ 12 files changed, 783 insertions(+), 945 deletions(-) (limited to 'linux/drivers') 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; -- 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(-) (limited to 'linux/drivers') 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 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'linux/drivers') 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); } -- 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(-) (limited to 'linux/drivers') 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 +++++++++------ 12 files changed, 172 insertions(+), 146 deletions(-) (limited to 'linux/drivers') 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) { -- 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 ++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 15 deletions(-) (limited to 'linux/drivers') 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; } -- 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(+) (limited to 'linux/drivers') 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 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'linux/drivers') 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, -- 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 +++---- 12 files changed, 141 insertions(+), 137 deletions(-) (limited to 'linux/drivers') 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 = { -- 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 +++++++++++++----------- 5 files changed, 38 insertions(+), 40 deletions(-) (limited to 'linux/drivers') 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 -- 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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/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 +++- 12 files changed, 1465 insertions(+), 631 deletions(-) (limited to 'linux/drivers') 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; -- 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 ---------- 5 files changed, 26 insertions(+), 78 deletions(-) (limited to 'linux/drivers') 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); -- 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 --------------- 5 files changed, 100 insertions(+), 62 deletions(-) (limited to 'linux/drivers') 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; } -- 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/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 ++- 8 files changed, 32 insertions(+), 14 deletions(-) (limited to 'linux/drivers') 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, -- 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(-) (limited to 'linux/drivers') 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 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 ++-- 3 files changed, 53 insertions(+), 24 deletions(-) (limited to 'linux/drivers') 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 -- 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(-) (limited to 'linux/drivers') 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 18da6da5146ce9ae730fbca22f57b010ee5956ca Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 8 Aug 2009 14:00:37 +0200 Subject: FM TX: si4713: Add Kconfig and Makefile entries From: Hans Verkuil Simply add Makefile and Kconfig entries. Priority: normal Signed-off-by: Eduardo Valentin [hverkuil@xs4all.nl: auto-select I2C_SI4713] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/Kconfig | 23 +++++++++++++++++++++++ linux/drivers/media/radio/Makefile | 2 ++ 2 files changed, 25 insertions(+) (limited to 'linux/drivers') diff --git a/linux/drivers/media/radio/Kconfig b/linux/drivers/media/radio/Kconfig index 0e39edf75..25a36ad60 100644 --- a/linux/drivers/media/radio/Kconfig +++ b/linux/drivers/media/radio/Kconfig @@ -329,6 +329,29 @@ config RADIO_ZOLTRIX_PORT help Enter the I/O port of your Zoltrix radio card. +config I2C_SI4713 + tristate "I2C driver for Silicon Labs Si4713 device" + depends on I2C && VIDEO_V4L2 + ---help--- + Say Y here if you want support to Si4713 I2C device. + This device driver supports only i2c bus. + + To compile this driver as a module, choose M here: the + module will be called si4713. + +config RADIO_SI4713 + tristate "Silicon Labs Si4713 FM Radio Transmitter support" + depends on I2C && VIDEO_V4L2 + select I2C_SI4713 + ---help--- + Say Y here if you want support to Si4713 FM Radio Transmitter. + This device can transmit audio through FM. It can transmit + EDS and EBDS signals as well. This module is the v4l2 radio + interface for the i2c driver of this device. + + To compile this driver as a module, choose M here: the + module will be called radio-si4713. + config USB_DSBR tristate "D-Link/GemTek USB FM radio support" depends on USB && VIDEO_V4L2 diff --git a/linux/drivers/media/radio/Makefile b/linux/drivers/media/radio/Makefile index 18111e1fe..2a1be3bf4 100644 --- a/linux/drivers/media/radio/Makefile +++ b/linux/drivers/media/radio/Makefile @@ -15,6 +15,8 @@ obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o +obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o +obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_RADIO_SI470X) += si470x/ -- 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/drivers/media/radio/radio-si4713.c | 367 ++++++ linux/drivers/media/radio/si4713-i2c.c | 2067 ++++++++++++++++++++++++++++++ linux/drivers/media/radio/si4713-i2c.h | 237 ++++ 3 files changed, 2671 insertions(+) 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 (limited to 'linux/drivers') 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 */ -- 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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/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 + 3 files changed, 45 insertions(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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/drivers/media/video/gspca/pac7311.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux/drivers') 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 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/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 + 3 files changed, 49 insertions(+), 2 deletions(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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/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 + 3 files changed, 59 insertions(+) (limited to 'linux/drivers') 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 +- 12 files changed, 2804 insertions(+), 2514 deletions(-) (limited to 'linux/drivers') 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) -- 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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 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/drivers/media/common/ir-keymaps.c | 44 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-cards.c | 22 +++++++++++++ linux/drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 67 insertions(+) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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/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 +++++++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'linux/drivers') 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 -- cgit v1.2.3 From b44bf030127d080ec77a3092ecd8ff84c8f2546f Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf 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 Added Kworld DVD Maker 2 Thanks to C Western for reporting this board. Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-cards.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 ++ 24 files changed, 10818 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 (limited to 'linux/drivers') 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"); -- 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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/drivers/media/video/davinci/vpif_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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(-) (limited to 'linux/drivers') 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 +++++++ 37 files changed, 16888 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 (limited to 'linux/drivers') 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 -- 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(+) (limited to 'linux/drivers') 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 +- 29 files changed, 3917 insertions(+), 3918 deletions(-) (limited to 'linux/drivers') 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 -- 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(-) (limited to 'linux/drivers') 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 ++-- 4 files changed, 8 insertions(+), 10 deletions(-) (limited to 'linux/drivers') 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); -- 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(+) (limited to 'linux/drivers') 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(+) (limited to 'linux/drivers') 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