diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-21 16:50:31 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-21 16:50:31 -0800 |
commit | 13a3cec8443290b082af2a5254562aca247fe591 (patch) | |
tree | 5c873a2c9333be348266234ac5d7101caa1b6d7d /drivers | |
parent | 973c9f4f49ca96a53bcf6384c4c59ccd26c33906 (diff) | |
parent | 88914bdf8c677ebd7e797adac05e47303fd6ac77 (diff) |
Merge branch 'media_fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'media_fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (101 commits)
[media] staging/lirc: fix mem leaks and ptr err usage
[media] hdpvr: reduce latency of i2c read/write w/recycled buffer
[media] hdpvr: enable IR part
[media] rc/mceusb: timeout should be in ns, not us
[media] v4l2-device: fix 'use-after-freed' oops
[media] v4l2-dev: don't memset video_device.dev
[media] zoran: use video_device_alloc instead of kmalloc
[media] w9966: zero device state after a detach
[media] v4l: Fix a use-before-set in the control framework
[media] v4l: Include linux/videodev2.h in media/v4l2-ctrls.h
[media] DocBook/v4l: update V4L2 revision and update copyright years
[media] DocBook/v4l: fix validation error in dev-rds.xml
[media] v4l2-ctrls: queryctrl shouldn't attempt to replace V4L2_CID_PRIVATE_BASE IDs
[media] v4l2-ctrls: fix missing 'read-only' check
[media] pvrusb2: Provide more information about IR units to lirc_zilog and ir-kbd-i2c
[media] ir-kbd-i2c: Add back defaults setting for Zilog Z8's at addr 0x71
[media] lirc_zilog: Update TODO.lirc_zilog
[media] lirc_zilog: Add Andy Walls to copyright notice and authors list
[media] lirc_zilog: Remove useless struct i2c_driver.command function
[media] lirc_zilog: Remove unneeded tests for existence of the IR Tx function
...
Diffstat (limited to 'drivers')
122 files changed, 2376 insertions, 2635 deletions
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 982f000a57ff..9f47e383c57a 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -452,7 +452,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device)); dev->ext = ext; - mutex_init(&dev->lock); + mutex_init(&dev->v4l2_lock); spin_lock_init(&dev->int_slock); spin_lock_init(&dev->slock); diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index e3fedc60fe77..1bd3dd762c6b 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -15,18 +15,15 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit) } /* is it free? */ - mutex_lock(&dev->lock); if (vv->resources & bit) { DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit)); /* no, someone else uses it */ - mutex_unlock(&dev->lock); return 0; } /* it's free, grab it */ fh->resources |= bit; vv->resources |= bit; DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources)); - mutex_unlock(&dev->lock); return 1; } @@ -37,11 +34,9 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) BUG_ON((fh->resources & bits) != bits); - mutex_lock(&dev->lock); fh->resources &= ~bits; vv->resources &= ~bits; DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources)); - mutex_unlock(&dev->lock); } @@ -396,7 +391,7 @@ static const struct v4l2_file_operations video_fops = .write = fops_write, .poll = fops_poll, .mmap = fops_mmap, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, }; static void vv_callback(struct saa7146_dev *dev, unsigned long status) @@ -505,6 +500,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, vfd->fops = &video_fops; vfd->ioctl_ops = &dev->ext_vv_data->ops; vfd->release = video_device_release; + vfd->lock = &dev->v4l2_lock; vfd->tvnorms = 0; for (i = 0; i < dev->ext_vv_data->num_stds; i++) vfd->tvnorms |= dev->ext_vv_data->stds[i].id; diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index 2d4533ab22b7..afe85801d6ca 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c @@ -412,7 +412,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, // FIXME: does this really work? sizeof(struct saa7146_buf), - file, NULL); + file, &dev->v4l2_lock); init_timer(&fh->vbi_read_timeout); fh->vbi_read_timeout.function = vbi_read_timeout; diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 0ac5c619aecf..9aafa4e969a8 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -553,8 +553,6 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f } } - mutex_lock(&dev->lock); - /* ok, accept it */ vv->ov_fb = *fb; vv->ov_fmt = fmt; @@ -563,8 +561,6 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8; DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline)); } - - mutex_unlock(&dev->lock); return 0; } @@ -649,8 +645,6 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) return -EINVAL; } - mutex_lock(&dev->lock); - switch (ctrl->type) { case V4L2_CTRL_TYPE_BOOLEAN: case V4L2_CTRL_TYPE_MENU: @@ -693,7 +687,6 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) /* fixme: we can support changing VFLIP and HFLIP here... */ if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D(("V4L2_CID_HFLIP while active capture.\n")); - mutex_unlock(&dev->lock); return -EBUSY; } vv->hflip = c->value; @@ -701,16 +694,13 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) case V4L2_CID_VFLIP: if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D(("V4L2_CID_VFLIP while active capture.\n")); - mutex_unlock(&dev->lock); return -EBUSY; } vv->vflip = c->value; break; default: - mutex_unlock(&dev->lock); return -EINVAL; } - mutex_unlock(&dev->lock); if (IS_OVERLAY_ACTIVE(fh) != 0) { saa7146_stop_preview(fh); @@ -902,22 +892,18 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_f err = vidioc_try_fmt_vid_overlay(file, fh, f); if (0 != err) return err; - mutex_lock(&dev->lock); fh->ov.win = f->fmt.win; fh->ov.nclips = f->fmt.win.clipcount; if (fh->ov.nclips > 16) fh->ov.nclips = 16; if (copy_from_user(fh->ov.clips, f->fmt.win.clips, sizeof(struct v4l2_clip) * fh->ov.nclips)) { - mutex_unlock(&dev->lock); return -EFAULT; } /* fh->ov.fh is used to indicate that we have valid overlay informations, too */ fh->ov.fh = fh; - mutex_unlock(&dev->lock); - /* check if our current overlay is active */ if (IS_OVERLAY_ACTIVE(fh) != 0) { saa7146_stop_preview(fh); @@ -976,8 +962,6 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id) } } - mutex_lock(&dev->lock); - for (i = 0; i < dev->ext_vv_data->num_stds; i++) if (*id & dev->ext_vv_data->stds[i].id) break; @@ -988,8 +972,6 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id) found = 1; } - mutex_unlock(&dev->lock); - if (vv->ov_suspend != NULL) { saa7146_start_preview(vv->ov_suspend); vv->ov_suspend = NULL; @@ -1354,7 +1336,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file) V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct saa7146_buf), - file, NULL); + file, &dev->v4l2_lock); return 0; } diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index c9062ceddc71..bc6a67768af1 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c @@ -95,8 +95,7 @@ static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close) msleep(20); } else { msg = disable; - tuner_i2c_xfer_send(&priv->i2c_props, msg, 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, msg, 1, &msg[1], 1); buf[2] = msg[1]; buf[2] &= ~0x04; @@ -233,19 +232,22 @@ static void tda8290_set_params(struct dvb_frontend *fe, tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); } + tda8290_i2c_bridge(fe, 1); if (fe->ops.tuner_ops.set_analog_params) fe->ops.tuner_ops.set_analog_params(fe, params); for (i = 0; i < 3; i++) { - tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &addr_pll_stat, 1, &pll_stat, 1); if (pll_stat & 0x80) { - tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); - tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &addr_adc_sat, 1, + &adc_sat, 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &addr_agc_stat, 1, + &agc_stat, 1); tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); break; } else { @@ -259,20 +261,22 @@ static void tda8290_set_params(struct dvb_frontend *fe, agc_stat, adc_sat, pll_stat & 0x80); tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2); msleep(100); - tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); - tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &addr_agc_stat, 1, &agc_stat, 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &addr_pll_stat, 1, &pll_stat, 1); if ((agc_stat > 115) || !(pll_stat & 0x80)) { tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", agc_stat, pll_stat & 0x80); if (priv->cfg.agcf) priv->cfg.agcf(fe); msleep(100); - tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); - tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &addr_agc_stat, 1, + &agc_stat, 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &addr_pll_stat, 1, + &pll_stat, 1); if((agc_stat > 115) || !(pll_stat & 0x80)) { tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2); @@ -284,10 +288,12 @@ static void tda8290_set_params(struct dvb_frontend *fe, /* l/ l' deadlock? */ if(priv->tda8290_easy_mode & 0x60) { - tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); - tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &addr_adc_sat, 1, + &adc_sat, 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &addr_pll_stat, 1, + &pll_stat, 1); if ((adc_sat > 20) || !(pll_stat & 0x80)) { tuner_dbg("trying to resolve SECAM L deadlock\n"); tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2); @@ -307,8 +313,7 @@ static void tda8295_power(struct dvb_frontend *fe, int enable) struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ - tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1); if (enable) buf[1] = 0x01; @@ -323,8 +328,7 @@ static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable) struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x01, 0x00 }; - tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1); if (enable) buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */ @@ -353,8 +357,7 @@ static void tda8295_agc1_out(struct dvb_frontend *fe, int enable) struct tda8290_priv *priv = fe->analog_demod_priv; unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ - tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1); if (enable) buf[1] &= ~0x40; @@ -370,10 +373,10 @@ static void tda8295_agc2_out(struct dvb_frontend *fe, int enable) unsigned char set_gpio_cf[] = { 0x44, 0x00 }; unsigned char set_gpio_val[] = { 0x46, 0x00 }; - tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1); - tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &set_gpio_cf[0], 1, &set_gpio_cf[1], 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &set_gpio_val[0], 1, &set_gpio_val[1], 1); set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */ @@ -392,8 +395,7 @@ static int tda8295_has_signal(struct dvb_frontend *fe) unsigned char hvpll_stat = 0x26; unsigned char ret; - tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, &hvpll_stat, 1, &ret, 1); return (ret & 0x01) ? 65535 : 0; } @@ -413,8 +415,8 @@ static void tda8295_set_params(struct dvb_frontend *fe, tda8295_power(fe, 1); tda8295_agc1_out(fe, 1); - tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1); - tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + &blanking_mode[0], 1, &blanking_mode[1], 1); tda8295_set_video_std(fe); @@ -447,8 +449,8 @@ static int tda8290_has_signal(struct dvb_frontend *fe) unsigned char i2c_get_afc[1] = { 0x1B }; unsigned char afc = 0; - tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc)); - tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1); + tuner_i2c_xfer_send_recv(&priv->i2c_props, + i2c_get_afc, ARRAY_SIZE(i2c_get_afc), &afc, 1); return (afc & 0x80)? 65535:0; } @@ -654,20 +656,26 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) static int tda8290_probe(struct tuner_i2c_props *i2c_props) { #define TDA8290_ID 0x89 - unsigned char tda8290_id[] = { 0x1f, 0x00 }; + u8 reg = 0x1f, id; + struct i2c_msg msg_read[] = { + { .addr = 0x4b, .flags = 0, .len = 1, .buf = ® }, + { .addr = 0x4b, .flags = I2C_M_RD, .len = 1, .buf = &id }, + }; /* detect tda8290 */ - tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1); - tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1); + if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) { + printk(KERN_WARNING "%s: tda8290 couldn't read register 0x%02x\n", + __func__, reg); + return -ENODEV; + } - if (tda8290_id[1] == TDA8290_ID) { + if (id == TDA8290_ID) { if (debug) printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n", __func__, i2c_adapter_id(i2c_props->adap), i2c_props->addr); return 0; } - return -ENODEV; } @@ -675,16 +683,23 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props) { #define TDA8295_ID 0x8a #define TDA8295C2_ID 0x8b - unsigned char tda8295_id[] = { 0x2f, 0x00 }; + u8 reg = 0x2f, id; + struct i2c_msg msg_read[] = { + { .addr = 0x4b, .flags = 0, .len = 1, .buf = ® }, + { .addr = 0x4b, .flags = I2C_M_RD, .len = 1, .buf = &id }, + }; - /* detect tda8295 */ - tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1); - tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1); + /* detect tda8290 */ + if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) { + printk(KERN_WARNING "%s: tda8290 couldn't read register 0x%02x\n", + __func__, reg); + return -ENODEV; + } - if ((tda8295_id[1] & 0xfe) == TDA8295_ID) { + if ((id & 0xfe) == TDA8295_ID) { if (debug) printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n", - __func__, (tda8295_id[1] == TDA8295_ID) ? + __func__, (id == TDA8295_ID) ? "tda8295c1" : "tda8295c2", i2c_adapter_id(i2c_props->adap), i2c_props->addr); @@ -740,9 +755,11 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, sizeof(struct analog_demod_ops)); } - if ((!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) && - (tda829x_find_tuner(fe) < 0)) - goto fail; + if (!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) { + tda8295_power(fe, 1); + if (tda829x_find_tuner(fe) < 0) + goto fail; + } switch (priv->ver) { case TDA8290: @@ -786,6 +803,8 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, return fe; fail: + memset(&fe->ops.analog_ops, 0, sizeof(struct analog_demod_ops)); + tda829x_release(fe); return NULL; } @@ -809,8 +828,8 @@ int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr) int i; /* rule out tda9887, which would return the same byte repeatedly */ - tuner_i2c_xfer_send(&i2c_props, soft_reset, 1); - tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE); + tuner_i2c_xfer_send_recv(&i2c_props, + soft_reset, 1, buf, PROBE_BUFFER_SIZE); for (i = 1; i < PROBE_BUFFER_SIZE; i++) { if (buf[i] != buf[0]) break; @@ -827,13 +846,12 @@ int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr) /* fall back to old probing method */ tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2); tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); - tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); - tuner_i2c_xfer_recv(&i2c_props, &data, 1); + tuner_i2c_xfer_send_recv(&i2c_props, &addr_dto_lsb, 1, &data, 1); if (data == 0) { tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2); tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); - tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); - tuner_i2c_xfer_recv(&i2c_props, &data, 1); + tuner_i2c_xfer_send_recv(&i2c_props, + &addr_dto_lsb, 1, &data, 1); if (data == 0x7b) { return 0; } diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 8ca48f76dfa9..98ffb40728e3 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -514,8 +514,8 @@ struct dib0700_rc_response { union { u16 system16; struct { - u8 system; u8 not_system; + u8 system; }; }; u8 data; @@ -575,7 +575,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) if ((poll_reply->system ^ poll_reply->not_system) != 0xff) { deb_data("NEC extended protocol\n"); /* NEC extended code - 24 bits */ - keycode = poll_reply->system16 << 8 | poll_reply->data; + keycode = be16_to_cpu(poll_reply->system16) << 8 | poll_reply->data; } else { deb_data("NEC normal protocol\n"); /* normal NEC code - 16 bits */ @@ -587,7 +587,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) deb_data("RC5 protocol\n"); /* RC5 Protocol */ toggle = poll_reply->report_id; - keycode = poll_reply->system16 << 8 | poll_reply->data; + keycode = poll_reply->system << 8 | poll_reply->data; break; } diff --git a/drivers/media/dvb/firewire/firedtv-rc.c b/drivers/media/dvb/firewire/firedtv-rc.c index fcf3828472b8..f82d4a93feb3 100644 --- a/drivers/media/dvb/firewire/firedtv-rc.c +++ b/drivers/media/dvb/firewire/firedtv-rc.c @@ -172,7 +172,8 @@ void fdtv_unregister_rc(struct firedtv *fdtv) void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) { - u16 *keycode = fdtv->remote_ctrl_dev->keycode; + struct input_dev *idev = fdtv->remote_ctrl_dev; + u16 *keycode = idev->keycode; if (code >= 0x0300 && code <= 0x031f) code = keycode[code - 0x0300]; @@ -188,6 +189,8 @@ void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) return; } - input_report_key(fdtv->remote_ctrl_dev, code, 1); - input_report_key(fdtv->remote_ctrl_dev, code, 0); + input_report_key(idev, code, 1); + input_sync(idev); + input_report_key(idev, code, 0); + input_sync(idev); } diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c index ce222055526d..ba25fa0b0fc2 100644 --- a/drivers/media/dvb/frontends/af9013.c +++ b/drivers/media/dvb/frontends/af9013.c @@ -334,11 +334,11 @@ static int af9013_set_freq_ctrl(struct af9013_state *state, fe_bandwidth_t bw) if_sample_freq = 3300000; /* 3.3 MHz */ break; case BANDWIDTH_7_MHZ: - if_sample_freq = 3800000; /* 3.8 MHz */ + if_sample_freq = 3500000; /* 3.5 MHz */ break; case BANDWIDTH_8_MHZ: default: - if_sample_freq = 4300000; /* 4.3 MHz */ + if_sample_freq = 4000000; /* 4.0 MHz */ break; } } else if (state->config.tuner == AF9013_TUNER_TDA18218) { diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c index 6360c681ded9..6c2e929bd79f 100644 --- a/drivers/media/dvb/frontends/ix2505v.c +++ b/drivers/media/dvb/frontends/ix2505v.c @@ -311,7 +311,7 @@ struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe, return fe; error: - ix2505v_release(fe); + kfree(state); return NULL; } EXPORT_SYMBOL(ix2505v_attach); diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c index d3ad3e75a35a..cc4acd2f920d 100644 --- a/drivers/media/dvb/frontends/mb86a20s.c +++ b/drivers/media/dvb/frontends/mb86a20s.c @@ -43,6 +43,8 @@ struct mb86a20s_state { const struct mb86a20s_config *config; struct dvb_frontend frontend; + + bool need_init; }; struct regdata { @@ -318,7 +320,7 @@ static int mb86a20s_i2c_writereg(struct mb86a20s_state *state, rc = i2c_transfer(state->i2c, &msg, 1); if (rc != 1) { - printk("%s: writereg rcor(rc == %i, reg == 0x%02x," + printk("%s: writereg error (rc == %i, reg == 0x%02x," " data == 0x%02x)\n", __func__, rc, reg, data); return rc; } @@ -353,7 +355,7 @@ static int mb86a20s_i2c_readreg(struct mb86a20s_state *state, rc = i2c_transfer(state->i2c, msg, 2); if (rc != 2) { - rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc); + rc("%s: reg=0x%x (error=%d)\n", __func__, reg, rc); return rc; } @@ -382,23 +384,31 @@ static int mb86a20s_initfe(struct dvb_frontend *fe) /* Initialize the frontend */ rc = mb86a20s_writeregdata(state, mb86a20s_init); if (rc < 0) - return rc; + goto err; if (!state->config->is_serial) { regD5 &= ~1; rc = mb86a20s_writereg(state, 0x50, 0xd5); if (rc < 0) - return rc; + goto err; rc = mb86a20s_writereg(state, 0x51, regD5); if (rc < 0) - return rc; + goto err; } if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - return 0; +err: + if (rc < 0) { + state->need_init = true; + printk(KERN_INFO "mb86a20s: Init failed. Will try again later\n"); + } else { + state->need_init = false; + dprintk("Initialization succeded.\n"); + } + return rc; } static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength) @@ -485,8 +495,22 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe, if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); + dprintk("Calling tuner set parameters\n"); fe->ops.tuner_ops.set_params(fe, p); + /* + * Make it more reliable: if, for some reason, the initial + * device initialization doesn't happen, initialize it when + * a SBTVD parameters are adjusted. + * + * Unfortunately, due to a hard to track bug at tda829x/tda18271, + * the agc callback logic is not called during DVB attach time, + * causing mb86a20s to not be initialized with Kworld SBTVD. + * So, this hack is needed, in order to make Kworld SBTVD to work. + */ + if (state->need_init) + mb86a20s_initfe(fe); + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception); diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c index 122c72806916..9fc1dd0ba4c3 100644 --- a/drivers/media/dvb/ttpci/av7110_ca.c +++ b/drivers/media/dvb/ttpci/av7110_ca.c @@ -277,7 +277,7 @@ static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg) { ca_slot_info_t *info=(ca_slot_info_t *)parg; - if (info->num > 1) + if (info->num < 0 || info->num > 1) return -EINVAL; av7110->ci_slot[info->num].num = info->num; av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 3c5a4739ed70..ecdffa6aac66 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -151,20 +151,6 @@ config RADIO_GEMTEK_PROBE following ports will be probed: 0x20c, 0x30c, 0x24c, 0x34c, 0x248 and 0x28c. -config RADIO_GEMTEK_PCI - tristate "GemTek PCI Radio Card support" - depends on VIDEO_V4L2 && PCI - ---help--- - Choose Y here if you have this PCI FM radio card. - - In order to control your radio card, you will need to use programs - that are compatible with the Video for Linux API. Information on - this API and pointers to "v4l" programs may be found at - <file:Documentation/video4linux/API.html>. - - To compile this driver as a module, choose M here: the - module will be called radio-gemtek-pci. - config RADIO_MAXIRADIO tristate "Guillemot MAXI Radio FM 2000 radio" depends on VIDEO_V4L2 && PCI diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index d2970748a69f..717656d2f749 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_RADIO_MAXIRADIO) += radio-maxiradio.o obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o 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 diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 6cc5d130fbc8..4ce10dbeadd8 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -31,6 +31,7 @@ #include <linux/module.h> /* Modules */ #include <linux/init.h> /* Initdata */ #include <linux/ioport.h> /* request_region */ +#include <linux/delay.h> /* msleep */ #include <linux/videodev2.h> /* kernel radio structs */ #include <linux/version.h> /* for KERNEL_VERSION MACRO */ #include <linux/io.h> /* outb, outb_p */ diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c deleted file mode 100644 index 28fa85ba2087..000000000000 --- a/drivers/media/radio/radio-gemtek-pci.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - *************************************************************************** - * - * radio-gemtek-pci.c - Gemtek PCI Radio driver - * (C) 2001 Vladimir Shebordaev <vshebordaev@mail.ru> - * - *************************************************************************** - * - * 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. - * - *************************************************************************** - * - * Gemtek Corp still silently refuses to release any specifications - * of their multimedia devices, so the protocol still has to be - * reverse engineered. - * - * The v4l code was inspired by Jonas Munsin's Gemtek serial line - * radio device driver. - * - * Please, let me know if this piece of code was useful :) - * - * TODO: multiple device support and portability were not tested - * - * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org> - * - *************************************************************************** - */ - -#include <linux/types.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/videodev2.h> -#include <linux/errno.h> -#include <linux/version.h> /* for KERNEL_VERSION MACRO */ -#include <linux/io.h> -#include <linux/slab.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> - -MODULE_AUTHOR("Vladimir Shebordaev <vshebordaev@mail.ru>"); -MODULE_DESCRIPTION("The video4linux driver for the Gemtek PCI Radio Card"); -MODULE_LICENSE("GPL"); - -static int nr_radio = -1; -static int mx = 1; - -module_param(mx, bool, 0); -MODULE_PARM_DESC(mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not"); -module_param(nr_radio, int, 0); -MODULE_PARM_DESC(nr_radio, "video4linux device number to use"); - -#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) - -#ifndef PCI_VENDOR_ID_GEMTEK -#define PCI_VENDOR_ID_GEMTEK 0x5046 -#endif - -#ifndef PCI_DEVICE_ID_GEMTEK_PR103 -#define PCI_DEVICE_ID_GEMTEK_PR103 0x1001 -#endif - -#ifndef GEMTEK_PCI_RANGE_LOW -#define GEMTEK_PCI_RANGE_LOW (87*16000) -#endif - -#ifndef GEMTEK_PCI_RANGE_HIGH -#define GEMTEK_PCI_RANGE_HIGH (108*16000) -#endif - -struct gemtek_pci { - struct v4l2_device v4l2_dev; - struct video_device vdev; - struct mutex lock; - struct pci_dev *pdev; - - u32 iobase; - u32 length; - - u32 current_frequency; - u8 mute; -}; - -static inline struct gemtek_pci *to_gemtek_pci(struct v4l2_device *v4l2_dev) -{ - return container_of(v4l2_dev, struct gemtek_pci, v4l2_dev); -} - -static inline u8 gemtek_pci_out(u16 value, u32 port) -{ - outw(value, port); - - return (u8)value; -} - -#define _b0(v) (*((u8 *)&v)) - -static void __gemtek_pci_cmd(u16 value, u32 port, u8 *last_byte, int keep) -{ - u8 byte = *last_byte; - - if (!value) { - if (!keep) - value = (u16)port; - byte &= 0xfd; - } else - byte |= 2; - - _b0(value) = byte; - outw(value, port); - byte |= 1; - _b0(value) = byte; - outw(value, port); - byte &= 0xfe; - _b0(value) = byte; - outw(value, port); - - *last_byte = byte; -} - -static inline void gemtek_pci_nil(u32 port, u8 *last_byte) -{ - __gemtek_pci_cmd(0x00, port, last_byte, false); -} - -static inline void gemtek_pci_cmd(u16 cmd, u32 port, u8 *last_byte) -{ - __gemtek_pci_cmd(cmd, port, last_byte, true); -} - -static void gemtek_pci_setfrequency(struct gemtek_pci *card, unsigned long frequency) -{ - int i; - u32 value = frequency / 200 + 856; - u16 mask = 0x8000; - u8 last_byte; - u32 port = card->iobase; - - mutex_lock(&card->lock); - card->current_frequency = frequency; - last_byte = gemtek_pci_out(0x06, port); - - i = 0; - do { - gemtek_pci_nil(port, &last_byte); - i++; - } while (i < 9); - - i = 0; - do { - gemtek_pci_cmd(value & mask, port, &last_byte); - mask >>= 1; - i++; - } while (i < 16); - - outw(0x10, port); - mutex_unlock(&card->lock); -} - - -static void gemtek_pci_mute(struct gemtek_pci *card) -{ - mutex_lock(&card->lock); - outb(0x1f, card->iobase); - card->mute = true; - mutex_unlock(&card->lock); -} - -static void gemtek_pci_unmute(struct gemtek_pci *card) -{ - if (card->mute) { - gemtek_pci_setfrequency(card, card->current_frequency); - card->mute = false; - } -} - -static int gemtek_pci_getsignal(struct gemtek_pci *card) -{ - int sig; - - mutex_lock(&card->lock); - sig = (inb(card->iobase) & 0x08) ? 0 : 1; - mutex_unlock(&card->lock); - return sig; -} - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *v) -{ - struct gemtek_pci *card = video_drvdata(file); - - strlcpy(v->driver, "radio-gemtek-pci", sizeof(v->driver)); - strlcpy(v->card, "GemTek PCI Radio", sizeof(v->card)); - snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(card->pdev)); - v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; - return 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *v) -{ - struct gemtek_pci *card = video_drvdata(file); - - if (v->index > 0) - return -EINVAL; - - strlcpy(v->name, "FM", sizeof(v->name)); - v->type = V4L2_TUNER_RADIO; - v->rangelow = GEMTEK_PCI_RANGE_LOW; - v->rangehigh = GEMTEK_PCI_RANGE_HIGH; - v->rxsubchans = V4L2_TUNER_SUB_MONO; - v->capability = V4L2_TUNER_CAP_LOW; - v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xffff * gemtek_pci_getsignal(card); - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *v) -{ - return v->index ? -EINVAL : 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct gemtek_pci *card = video_drvdata(file); - - if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) - return -EINVAL; - if (f->frequency < GEMTEK_PCI_RANGE_LOW || - f->frequency > GEMTEK_PCI_RANGE_HIGH) - return -EINVAL; - gemtek_pci_setfrequency(card, f->frequency); - card->mute = false; - return 0; -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct gemtek_pci *card = video_drvdata(file); - - if (f->tuner != 0) - return -EINVAL; - f->type = V4L2_TUNER_RADIO; - f->frequency = card->current_frequency; - return 0; -} - -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - switch (qc->id) { - case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535); - } - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct gemtek_pci *card = video_drvdata(file); - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - ctrl->value = card->mute; - return 0; - case V4L2_CID_AUDIO_VOLUME: - if (card->mute) - ctrl->value = 0; - else - ctrl->value = 65535; - return 0; - } - return -EINVAL; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct gemtek_pci *card = video_drvdata(file); - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) - gemtek_pci_mute(card); - else - gemtek_pci_unmute(card); - return 0; - case V4L2_CID_AUDIO_VOLUME: - if (ctrl->value) - gemtek_pci_unmute(card); - else - gemtek_pci_mute(card); - return 0; - } - return -EINVAL; -} - -static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) -{ - return i ? -EINVAL : 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - a->index = 0; - strlcpy(a->name, "Radio", sizeof(a->name)); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - return a->index ? -EINVAL : 0; -} - -enum { - GEMTEK_PR103 -}; - -static char *card_names[] __devinitdata = { - "GEMTEK_PR103" -}; - -static struct pci_device_id gemtek_pci_id[] = -{ - { PCI_VENDOR_ID_GEMTEK, PCI_DEVICE_ID_GEMTEK_PR103, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, GEMTEK_PR103 }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, gemtek_pci_id); - -static const struct v4l2_file_operations gemtek_pci_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, -}; - -static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -{ - struct gemtek_pci *card; - struct v4l2_device *v4l2_dev; - int res; - - card = kzalloc(sizeof(struct gemtek_pci), GFP_KERNEL); - if (card == NULL) { - dev_err(&pdev->dev, "out of memory\n"); - return -ENOMEM; - } - - v4l2_dev = &card->v4l2_dev; - mutex_init(&card->lock); - card->pdev = pdev; - - strlcpy(v4l2_dev->name, "gemtek_pci", sizeof(v4l2_dev->name)); - - res = v4l2_device_register(&pdev->dev, v4l2_dev); - if (res < 0) { - v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); - kfree(card); - return res; - } - - if (pci_enable_device(pdev)) - goto err_pci; - - card->iobase = pci_resource_start(pdev, 0); - card->length = pci_resource_len(pdev, 0); - - if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) { - v4l2_err(v4l2_dev, "i/o port already in use\n"); - goto err_pci; - } - - strlcpy(card->vdev.name, v4l2_dev->name, sizeof(card->vdev.name)); - card->vdev.v4l2_dev = v4l2_dev; - card->vdev.fops = &gemtek_pci_fops; - card->vdev.ioctl_ops = &gemtek_pci_ioctl_ops; - card->vdev.release = video_device_release_empty; - video_set_drvdata(&card->vdev, card); - - gemtek_pci_mute(card); - - if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0) - goto err_video; - - v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", - pdev->revision, card->iobase, card->iobase + card->length - 1); - - return 0; - -err_video: - release_region(card->iobase, card->length); - -err_pci: - v4l2_device_unregister(v4l2_dev); - kfree(card); - return -ENODEV; -} - -static void __devexit gemtek_pci_remove(struct pci_dev *pdev) -{ - struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); - struct gemtek_pci *card = to_gemtek_pci(v4l2_dev); - - video_unregister_device(&card->vdev); - v4l2_device_unregister(v4l2_dev); - - release_region(card->iobase, card->length); - - if (mx) - gemtek_pci_mute(card); - - kfree(card); -} - -static struct pci_driver gemtek_pci_driver = { - .name = "gemtek_pci", - .id_table = gemtek_pci_id, - .probe = gemtek_pci_probe, - .remove = __devexit_p(gemtek_pci_remove), -}; - -static int __init gemtek_pci_init(void) -{ - return pci_register_driver(&gemtek_pci_driver); -} - -static void __exit gemtek_pci_exit(void) -{ - pci_unregister_driver(&gemtek_pci_driver); -} - -module_init(gemtek_pci_init); -module_exit(gemtek_pci_exit); diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 6459a220b0dd..5c2a9058c09f 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -77,8 +77,8 @@ MODULE_PARM_DESC(debug, "activates debug info"); /* TEA5757 pin mappings */ static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16; -#define FREQ_LO (50 * 16000) -#define FREQ_HI (150 * 16000) +#define FREQ_LO (87 * 16000) +#define FREQ_HI (108 * 16000) #define FREQ_IF 171200 /* 10.7*16000 */ #define FREQ_STEP 200 /* 12.5*16 */ diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index dd6bd364efa0..7ecc8e657663 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -1407,7 +1407,7 @@ static const struct v4l2_file_operations wl1273_fops = { .read = wl1273_fm_fops_read, .write = wl1273_fm_fops_write, .poll = wl1273_fm_fops_poll, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .open = wl1273_fm_fops_open, .release = wl1273_fm_fops_release, }; diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index ac76dfe5b3fa..60c176fe328e 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -357,7 +357,8 @@ int si470x_start(struct si470x_device *radio) goto done; /* sysconfig 1 */ - radio->registers[SYSCONFIG1] = SYSCONFIG1_DE; + radio->registers[SYSCONFIG1] = + (de << 11) & SYSCONFIG1_DE; /* DE*/ retval = si470x_set_register(radio, SYSCONFIG1); if (retval < 0) goto done; @@ -687,12 +688,8 @@ 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 | V4L2_TUNER_CAP_RDS_BLOCK_IO; -#else - tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; -#endif /* range limits */ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { @@ -718,12 +715,10 @@ 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/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index 80b3c319f698..1ac49139158d 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -446,27 +446,27 @@ static void ene_rx_setup(struct ene_device *dev) select_timeout: if (dev->rx_fan_input_inuse) { - dev->rdev->rx_resolution = MS_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN); + dev->rdev->rx_resolution = US_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN); /* Fan input doesn't support timeouts, it just ends the input with a maximum sample */ dev->rdev->min_timeout = dev->rdev->max_timeout = - MS_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK * + US_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK * ENE_FW_SAMPLE_PERIOD_FAN); } else { - dev->rdev->rx_resolution = MS_TO_NS(sample_period); + dev->rdev->rx_resolution = US_TO_NS(sample_period); /* Theoreticly timeout is unlimited, but we cap it * because it was seen that on one device, it * would stop sending spaces after around 250 msec. * Besides, this is close to 2^32 anyway and timeout is u32. */ - dev->rdev->min_timeout = MS_TO_NS(127 * sample_period); - dev->rdev->max_timeout = MS_TO_NS(200000); + dev->rdev->min_timeout = US_TO_NS(127 * sample_period); + dev->rdev->max_timeout = US_TO_NS(200000); } if (dev->hw_learning_and_tx_capable) - dev->rdev->tx_resolution = MS_TO_NS(sample_period); + dev->rdev->tx_resolution = US_TO_NS(sample_period); if (dev->rdev->timeout > dev->rdev->max_timeout) dev->rdev->timeout = dev->rdev->max_timeout; @@ -801,7 +801,7 @@ static irqreturn_t ene_isr(int irq, void *data) dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space"); - ev.duration = MS_TO_NS(hw_sample); + ev.duration = US_TO_NS(hw_sample); ev.pulse = pulse; ir_raw_event_store_with_filter(dev->rdev, &ev); } @@ -821,7 +821,7 @@ static void ene_setup_default_settings(struct ene_device *dev) dev->learning_mode_enabled = learning_mode_force; /* Set reasonable default timeout */ - dev->rdev->timeout = MS_TO_NS(150000); + dev->rdev->timeout = US_TO_NS(150000); } /* Upload all hardware settings at once. Used at load and resume time */ @@ -1004,6 +1004,10 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) /* validate resources */ error = -ENODEV; + /* init these to -1, as 0 is valid for both */ + dev->hw_io = -1; + dev->irq = -1; + if (!pnp_port_valid(pnp_dev, 0) || pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE) goto error; @@ -1072,6 +1076,8 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) rdev->input_name = "ENE eHome Infrared Remote Transceiver"; } + dev->rdev = rdev; + ene_rx_setup_hw_buffer(dev); ene_setup_default_settings(dev); ene_setup_hw_settings(dev); @@ -1083,7 +1089,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) if (error < 0) goto error; - dev->rdev = rdev; ene_notice("driver has been succesfully loaded"); return 0; error: diff --git a/drivers/media/rc/ene_ir.h b/drivers/media/rc/ene_ir.h index c179baf34cb4..337a41d4450b 100644 --- a/drivers/media/rc/ene_ir.h +++ b/drivers/media/rc/ene_ir.h @@ -201,8 +201,6 @@ #define dbg_verbose(format, ...) __dbg(2, format, ## __VA_ARGS__) #define dbg_regs(format, ...) __dbg(3, format, ## __VA_ARGS__) -#define MS_TO_NS(msec) ((msec) * 1000) - struct ene_device { struct pnp_dev *pnp_dev; struct rc_dev *rdev; diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 6811512b4e83..e7dc6b46fdfa 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -988,7 +988,6 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type) int retval; struct imon_context *ictx = rc->priv; struct device *dev = ictx->dev; - bool pad_mouse; unsigned char ir_proto_packet[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; @@ -1000,29 +999,20 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type) case RC_TYPE_RC6: dev_dbg(dev, "Configuring IR receiver for MCE protocol\n"); ir_proto_packet[0] = 0x01; - pad_mouse = false; break; case RC_TYPE_UNKNOWN: case RC_TYPE_OTHER: dev_dbg(dev, "Configuring IR receiver for iMON protocol\n"); - if (pad_stabilize && !nomouse) - pad_mouse = true; - else { + if (!pad_stabilize) dev_dbg(dev, "PAD stabilize functionality disabled\n"); - pad_mouse = false; - } /* ir_proto_packet[0] = 0x00; // already the default */ rc_type = RC_TYPE_OTHER; break; default: dev_warn(dev, "Unsupported IR protocol specified, overriding " "to iMON IR protocol\n"); - if (pad_stabilize && !nomouse) - pad_mouse = true; - else { + if (!pad_stabilize) dev_dbg(dev, "PAD stabilize functionality disabled\n"); - pad_mouse = false; - } /* ir_proto_packet[0] = 0x00; // already the default */ rc_type = RC_TYPE_OTHER; break; @@ -1035,7 +1025,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type) goto out; ictx->rc_type = rc_type; - ictx->pad_mouse = pad_mouse; + ictx->pad_mouse = false; out: return retval; @@ -1517,7 +1507,7 @@ static void imon_incoming_packet(struct imon_context *ictx, spin_unlock_irqrestore(&ictx->kc_lock, flags); return; } else { - ictx->pad_mouse = 0; + ictx->pad_mouse = false; dev_dbg(dev, "mouse mode disabled, passing key value\n"); } } @@ -1756,7 +1746,6 @@ static void imon_get_ffdc_type(struct imon_context *ictx) printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte); ictx->display_type = detected_display_type; - ictx->rdev->allowed_protos = allowed_protos; ictx->rc_type = allowed_protos; } @@ -1839,10 +1828,6 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx) rdev->allowed_protos = RC_TYPE_OTHER | RC_TYPE_RC6; /* iMON PAD or MCE */ rdev->change_protocol = imon_ir_change_protocol; rdev->driver_name = MOD_NAME; - if (ictx->rc_type == RC_TYPE_RC6) - rdev->map_name = RC_MAP_IMON_MCE; - else - rdev->map_name = RC_MAP_IMON_PAD; /* Enable front-panel buttons and/or knobs */ memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet)); @@ -1851,11 +1836,18 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx) if (ret) dev_info(ictx->dev, "panel buttons/knobs setup failed\n"); - if (ictx->product == 0xffdc) + if (ictx->product == 0xffdc) { imon_get_ffdc_type(ictx); + rdev->allowed_protos = ictx->rc_type; + } imon_set_display_type(ictx); + if (ictx->rc_type == RC_TYPE_RC6) + rdev->map_name = RC_MAP_IMON_MCE; + else + rdev->map_name = RC_MAP_IMON_PAD; + ret = rc_register_device(rdev); if (ret < 0) { dev_err(ictx->dev, "remote input dev register failed\n"); @@ -2108,18 +2100,6 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) goto find_endpoint_failed; } - ictx->idev = imon_init_idev(ictx); - if (!ictx->idev) { - dev_err(dev, "%s: input device setup failed\n", __func__); - goto idev_setup_failed; - } - - ictx->rdev = imon_init_rdev(ictx); - if (!ictx->rdev) { - dev_err(dev, "%s: rc device setup failed\n", __func__); - goto rdev_setup_failed; - } - usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, usb_rcvintpipe(ictx->usbdev_intf0, ictx->rx_endpoint_intf0->bEndpointAddress), @@ -2133,13 +2113,25 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) goto urb_submit_failed; } + ictx->idev = imon_init_idev(ictx); + if (!ictx->idev) { + dev_err(dev, "%s: input device setup failed\n", __func__); + goto idev_setup_failed; + } + + ictx->rdev = imon_init_rdev(ictx); + if (!ictx->rdev) { + dev_err(dev, "%s: rc device setup failed\n", __func__); + goto rdev_setup_failed; + } + return ictx; -urb_submit_failed: - rc_unregister_device(ictx->rdev); rdev_setup_failed: input_unregister_device(ictx->idev); idev_setup_failed: + usb_kill_urb(ictx->rx_urb_intf0); +urb_submit_failed: find_endpoint_failed: mutex_unlock(&ictx->lock); usb_free_urb(tx_urb); diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c index 185baddcbf14..73230ff93b8a 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c @@ -233,7 +233,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_handle); /* used internally by the sysfs interface */ u64 -ir_raw_get_allowed_protocols() +ir_raw_get_allowed_protocols(void) { u64 protocols; mutex_lock(&ir_raw_handler_lock); diff --git a/drivers/media/rc/keymaps/rc-dib0700-nec.c b/drivers/media/rc/keymaps/rc-dib0700-nec.c index c59851b203da..7a5f5300caf9 100644 --- a/drivers/media/rc/keymaps/rc-dib0700-nec.c +++ b/drivers/media/rc/keymaps/rc-dib0700-nec.c @@ -19,35 +19,35 @@ static struct rc_map_table dib0700_nec_table[] = { /* Key codes for the Pixelview SBTVD remote */ - { 0x8613, KEY_MUTE }, - { 0x8612, KEY_POWER }, - { 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 }, - { 0x8600, KEY_0 }, - { 0x860d, KEY_CHANNELUP }, - { 0x8619, KEY_CHANNELDOWN }, - { 0x8610, KEY_VOLUMEUP }, - { 0x860c, KEY_VOLUMEDOWN }, + { 0x866b13, KEY_MUTE }, + { 0x866b12, KEY_POWER }, + { 0x866b01, KEY_1 }, + { 0x866b02, KEY_2 }, + { 0x866b03, KEY_3 }, + { 0x866b04, KEY_4 }, + { 0x866b05, KEY_5 }, + { 0x866b06, KEY_6 }, + { 0x866b07, KEY_7 }, + { 0x866b08, KEY_8 }, + { 0x866b09, KEY_9 }, + { 0x866b00, KEY_0 }, + { 0x866b0d, KEY_CHANNELUP }, + { 0x866b19, KEY_CHANNELDOWN }, + { 0x866b10, KEY_VOLUMEUP }, + { 0x866b0c, KEY_VOLUMEDOWN }, - { 0x860a, KEY_CAMERA }, - { 0x860b, KEY_ZOOM }, - { 0x861b, KEY_BACKSPACE }, - { 0x8615, KEY_ENTER }, + { 0x866b0a, KEY_CAMERA }, + { 0x866b0b, KEY_ZOOM }, + { 0x866b1b, KEY_BACKSPACE }, + { 0x866b15, KEY_ENTER }, - { 0x861d, KEY_UP }, - { 0x861e, KEY_DOWN }, - { 0x860e, KEY_LEFT }, - { 0x860f, KEY_RIGHT }, + { 0x866b1d, KEY_UP }, + { 0x866b1e, KEY_DOWN }, + { 0x866b0e, KEY_LEFT }, + { 0x866b0f, KEY_RIGHT }, - { 0x8618, KEY_RECORD }, - { 0x861a, KEY_STOP }, + { 0x866b18, KEY_RECORD }, + { 0x866b1a, KEY_STOP }, /* Key codes for the EvolutePC TVWay+ remote */ { 0x7a00, KEY_MENU }, diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 0fef6efad537..079353e5d558 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -48,7 +48,6 @@ #define USB_BUFLEN 32 /* USB reception buffer length */ #define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */ #define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */ -#define MS_TO_NS(msec) ((msec) * 1000) /* MCE constants */ #define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */ @@ -858,7 +857,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) ir->rem--; rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0); rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK) - * MS_TO_NS(MCE_TIME_UNIT); + * MS_TO_US(MCE_TIME_UNIT); dev_dbg(ir->dev, "Storing %s with duration %d\n", rawir.pulse ? "pulse" : "space", diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 34e7abadceaa..aa021600e9df 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -141,15 +141,6 @@ config VIDEO_TDA9840 To compile this driver as a module, choose M here: the module will be called tda9840. -config VIDEO_TDA9875 - tristate "Philips TDA9875 audio processor" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for tda9875 audio decoder chip found on some bt8xx boards. - - To compile this driver as a module, choose M here: the - module will be called tda9875. - config VIDEO_TEA6415C tristate "Philips TEA6415C audio processor" depends on I2C diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 81e38cb0b846..a509d317e258 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -27,7 +27,6 @@ obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o obj-$(CONFIG_VIDEO_TUNER) += tuner.o obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o -obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index f318b51448b3..d2327dbb473f 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c @@ -303,11 +303,22 @@ static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ide return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0); } +static int adv7175_s_power(struct v4l2_subdev *sd, int on) +{ + if (on) + adv7175_write(sd, 0x01, 0x00); + else + adv7175_write(sd, 0x01, 0x78); + + return 0; +} + /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops adv7175_core_ops = { .g_chip_ident = adv7175_g_chip_ident, .init = adv7175_init, + .s_power = adv7175_s_power, }; static const struct v4l2_subdev_video_ops adv7175_video_ops = { diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 49efcf660ba6..7f58756d72c8 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -1373,7 +1373,6 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0x1800, .audio_mode_gpio= fv2000s_audio, .no_msp34xx = 1, - .no_tda9875 = 1, .needs_tvaudio = 1, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, @@ -1511,7 +1510,6 @@ struct tvcard bttv_tvcards[] = { .gpiomute = 0x09, .needs_tvaudio = 1, .no_msp34xx = 1, - .no_tda9875 = 1, .pll = PLL_28, .tuner_type = TUNER_PHILIPS_PAL, .tuner_addr = ADDR_UNSET, @@ -1550,7 +1548,6 @@ struct tvcard bttv_tvcards[] = { .gpiomask2 = 0x07ff, .muxsel = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), .no_msp34xx = 1, - .no_tda9875 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .muxsel_hook = rv605_muxsel, @@ -1686,7 +1683,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, [BTTV_BOARD_OSPREY1x0_848] = { @@ -1699,7 +1695,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, @@ -1714,7 +1709,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, [BTTV_BOARD_OSPREY1x1] = { @@ -1727,7 +1721,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, [BTTV_BOARD_OSPREY1x1_SVID] = { @@ -1740,7 +1733,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, [BTTV_BOARD_OSPREY2xx] = { @@ -1753,7 +1745,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, @@ -1768,7 +1759,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, [BTTV_BOARD_OSPREY2x0] = { @@ -1781,7 +1771,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, [BTTV_BOARD_OSPREY500] = { @@ -1794,7 +1783,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, [BTTV_BOARD_OSPREY540] = { @@ -1805,7 +1793,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, @@ -1820,7 +1807,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, /* must avoid, conflicts with the bt860 */ }, [BTTV_BOARD_IDS_EAGLE] = { @@ -1835,7 +1821,6 @@ struct tvcard bttv_tvcards[] = { .muxsel = MUXSEL(2, 2, 2, 2), .muxsel_hook = eagle_muxsel, .no_msp34xx = 1, - .no_tda9875 = 1, .pll = PLL_28, }, [BTTV_BOARD_PINNACLESAT] = { @@ -1846,7 +1831,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .muxsel = MUXSEL(3, 1), .pll = PLL_28, @@ -1897,7 +1881,6 @@ struct tvcard bttv_tvcards[] = { .svhs = 2, .gpiomask = 0, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .muxsel = MUXSEL(2, 0, 1), .pll = PLL_28, @@ -1970,7 +1953,6 @@ struct tvcard bttv_tvcards[] = { /* Tuner, CVid, SVid, CVid over SVid connector */ .muxsel = MUXSEL(2, 3, 1, 1), .gpiomask = 0, - .no_tda9875 = 1, .no_tda7432 = 1, .tuner_type = TUNER_PHILIPS_PAL_I, .tuner_addr = ADDR_UNSET, @@ -2017,7 +1999,6 @@ struct tvcard bttv_tvcards[] = { .muxsel = MUXSEL(2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0), .muxsel_hook = xguard_muxsel, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, }, @@ -2029,7 +2010,6 @@ struct tvcard bttv_tvcards[] = { .svhs = NO_SVHS, .muxsel = MUXSEL(2, 3, 1, 0), .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, .tuner_type = TUNER_ABSENT, @@ -2134,7 +2114,6 @@ struct tvcard bttv_tvcards[] = { .svhs = NO_SVHS, /* card has no svhs */ .needs_tvaudio = 0, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .gpiomask = 0x00, .muxsel = MUXSEL(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), @@ -2156,7 +2135,6 @@ struct tvcard bttv_tvcards[] = { [BTTV_BOARD_TWINHAN_DST] = { .name = "Twinhan DST + clones", .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -2171,7 +2149,6 @@ struct tvcard bttv_tvcards[] = { /* Vid In, SVid In, Vid over SVid in connector */ .muxsel = MUXSEL(3, 1, 1, 3), .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -2226,7 +2203,6 @@ struct tvcard bttv_tvcards[] = { .svhs = NO_SVHS, .muxsel = MUXSEL(2, 3, 1, 0), .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .needs_tvaudio = 0, .tuner_type = TUNER_ABSENT, @@ -2278,7 +2254,6 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 0, .gpiomask2 = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/ .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, /*878A input is always MUX0, see above.*/ .muxsel = MUXSEL(2, 2, 2, 2), @@ -2302,7 +2277,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_TEMIC_PAL, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, }, [BTTV_BOARD_AVDVBT_771] = { /* Wolfram Joost <wojo@frokaschwei.de> */ @@ -2313,7 +2287,6 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .muxsel = MUXSEL(3, 3), .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, .has_dvb = 1, @@ -2329,7 +2302,6 @@ struct tvcard bttv_tvcards[] = { .svhs = 1, .muxsel = MUXSEL(3, 1, 2, 0), /* Comp0, S-Video, ?, ? */ .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, .tuner_type = TUNER_ABSENT, @@ -2393,7 +2365,6 @@ struct tvcard bttv_tvcards[] = { /* Chris Pascoe <c.pascoe@itee.uq.edu.au> */ .name = "DViCO FusionHDTV DVB-T Lite", .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, .no_video = 1, @@ -2440,7 +2411,6 @@ struct tvcard bttv_tvcards[] = { .muxsel = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), .pll = PLL_28, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -2478,7 +2448,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .no_msp34xx = 1, .no_tda7432 = 1, - .no_tda9875 = 1, .muxsel_hook = kodicom4400r_muxsel, }, [BTTV_BOARD_KODICOM_4400R_SL] = { @@ -2500,7 +2469,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .no_msp34xx = 1, .no_tda7432 = 1, - .no_tda9875 = 1, .muxsel_hook = kodicom4400r_muxsel, }, /* ---- card 0x86---------------------------------- */ @@ -2530,7 +2498,6 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0x00400005, 0, 0x00000001, 0 }, .gpiomute = 0x00c00007, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .has_dvb = 1, }, @@ -2630,7 +2597,6 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, /* ---- card 0x8d ---------------------------------- */ @@ -2658,7 +2624,6 @@ struct tvcard bttv_tvcards[] = { .muxsel = MUXSEL(2, 3, 1, 1), .gpiomux = { 100000, 100002, 100002, 100000 }, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .pll = PLL_28, .tuner_type = TUNER_TNF_5335MF, @@ -2674,7 +2639,6 @@ struct tvcard bttv_tvcards[] = { .gpiomask = 0x0f, /* old: 7 */ .muxsel = MUXSEL(0, 1, 3, 2), /* Composite 0-3 */ .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, @@ -2732,7 +2696,6 @@ struct tvcard bttv_tvcards[] = { .gpiomux = { 0x00400005, 0, 0x00000001, 0 }, .gpiomute = 0x00c00007, .no_msp34xx = 1, - .no_tda9875 = 1, .no_tda7432 = 1, }, /* ---- card 0x95---------------------------------- */ @@ -2874,7 +2837,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .no_msp34xx = 1, .no_tda7432 = 1, - .no_tda9875 = 1, .muxsel_hook = gv800s_muxsel, }, [BTTV_BOARD_GEOVISION_GV800S_SL] = { @@ -2899,7 +2861,6 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_28, .no_msp34xx = 1, .no_tda7432 = 1, - .no_tda9875 = 1, .muxsel_hook = gv800s_muxsel, }, [BTTV_BOARD_PV183] = { diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index fd62bf15d779..c6333595c6b9 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -234,7 +234,6 @@ struct tvcard { /* i2c audio flags */ unsigned int no_msp34xx:1; - unsigned int no_tda9875:1; unsigned int no_tda7432:1; unsigned int needs_tvaudio:1; unsigned int msp34xx_alt:1; diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 49f1b8f1418e..55ffd60ffa7f 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -2001,6 +2001,11 @@ static int cafe_pci_probe(struct pci_dev *pdev, .min_width = 320, .min_height = 240, }; + struct i2c_board_info ov7670_info = { + .type = "ov7670", + .addr = 0x42, + .platform_data = &sensor_cfg, + }; /* * Start putting together one of our big camera structures. @@ -2062,9 +2067,9 @@ static int cafe_pci_probe(struct pci_dev *pdev, if (dmi_check_system(olpc_xo1_dmi)) sensor_cfg.clock_speed = 45; - cam->sensor_addr = 0x42; - cam->sensor = v4l2_i2c_new_subdev_cfg(&cam->v4l2_dev, &cam->i2c_adapter, - "ov7670", 0, &sensor_cfg, cam->sensor_addr, NULL); + cam->sensor_addr = ov7670_info.addr; + cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev, &cam->i2c_adapter, + &ov7670_info, NULL); if (cam->sensor == NULL) { ret = -ENODEV; goto out_smbus; diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h index 916c13d5cf7d..6d6d1843791c 100644 --- a/drivers/media/video/cpia2/cpia2.h +++ b/drivers/media/video/cpia2/cpia2.h @@ -378,7 +378,7 @@ struct cpia2_fh { struct camera_data { /* locks */ - struct mutex busy_lock; /* guard against SMP multithreading */ + struct mutex v4l2_lock; /* serialize file operations */ struct v4l2_prio_state prio; /* camera status */ diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c index 9606bc01b803..aaffca8e13fd 100644 --- a/drivers/media/video/cpia2/cpia2_core.c +++ b/drivers/media/video/cpia2/cpia2_core.c @@ -2247,7 +2247,7 @@ struct camera_data *cpia2_init_camera_struct(void) cam->present = 1; - mutex_init(&cam->busy_lock); + mutex_init(&cam->v4l2_lock); init_waitqueue_head(&cam->wq_stream); return cam; @@ -2365,9 +2365,9 @@ long cpia2_read(struct camera_data *cam, char __user *buf, unsigned long count, int noblock) { struct framebuf *frame; - if (!count) { + + if (!count) return 0; - } if (!buf) { ERR("%s: buffer NULL\n",__func__); @@ -2379,17 +2379,12 @@ long cpia2_read(struct camera_data *cam, return -EINVAL; } - /* make this _really_ smp and multithread-safe */ - if (mutex_lock_interruptible(&cam->busy_lock)) - return -ERESTARTSYS; - if (!cam->present) { LOG("%s: camera removed\n",__func__); - mutex_unlock(&cam->busy_lock); return 0; /* EOF */ } - if(!cam->streaming) { + if (!cam->streaming) { /* Start streaming */ cpia2_usb_stream_start(cam, cam->params.camera_state.stream_mode); @@ -2398,42 +2393,31 @@ long cpia2_read(struct camera_data *cam, /* Copy cam->curbuff in case it changes while we're processing */ frame = cam->curbuff; if (noblock && frame->status != FRAME_READY) { - mutex_unlock(&cam->busy_lock); return -EAGAIN; } - if(frame->status != FRAME_READY) { - mutex_unlock(&cam->busy_lock); + if (frame->status != FRAME_READY) { + mutex_unlock(&cam->v4l2_lock); wait_event_interruptible(cam->wq_stream, !cam->present || (frame = cam->curbuff)->status == FRAME_READY); + mutex_lock(&cam->v4l2_lock); if (signal_pending(current)) return -ERESTARTSYS; - /* make this _really_ smp and multithread-safe */ - if (mutex_lock_interruptible(&cam->busy_lock)) { - return -ERESTARTSYS; - } - if(!cam->present) { - mutex_unlock(&cam->busy_lock); + if (!cam->present) return 0; - } } /* copy data to user space */ - if (frame->length > count) { - mutex_unlock(&cam->busy_lock); + if (frame->length > count) return -EFAULT; - } - if (copy_to_user(buf, frame->data, frame->length)) { - mutex_unlock(&cam->busy_lock); + if (copy_to_user(buf, frame->data, frame->length)) return -EFAULT; - } count = frame->length; frame->status = FRAME_EMPTY; - mutex_unlock(&cam->busy_lock); return count; } @@ -2447,17 +2431,13 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp, { unsigned int status=0; - if(!cam) { + if (!cam) { ERR("%s: Internal error, camera_data not found!\n",__func__); return POLLERR; } - mutex_lock(&cam->busy_lock); - - if(!cam->present) { - mutex_unlock(&cam->busy_lock); + if (!cam->present) return POLLHUP; - } if(!cam->streaming) { /* Start streaming */ @@ -2465,16 +2445,13 @@ unsigned int cpia2_poll(struct camera_data *cam, struct file *filp, cam->params.camera_state.stream_mode); } - mutex_unlock(&cam->busy_lock); poll_wait(filp, &cam->wq_stream, wait); - mutex_lock(&cam->busy_lock); if(!cam->present) status = POLLHUP; else if(cam->curbuff->status == FRAME_READY) status = POLLIN | POLLRDNORM; - mutex_unlock(&cam->busy_lock); return status; } @@ -2496,29 +2473,19 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma) DBG("mmap offset:%ld size:%ld\n", start_offset, size); - /* make this _really_ smp-safe */ - if (mutex_lock_interruptible(&cam->busy_lock)) - return -ERESTARTSYS; - - if (!cam->present) { - mutex_unlock(&cam->busy_lock); + if (!cam->present) return -ENODEV; - } if (size > cam->frame_size*cam->num_frames || (start_offset % cam->frame_size) != 0 || - (start_offset+size > cam->frame_size*cam->num_frames)) { - mutex_unlock(&cam->busy_lock); + (start_offset+size > cam->frame_size*cam->num_frames)) return -EINVAL; - } pos = ((unsigned long) (cam->frame_buffer)) + start_offset; while (size > 0) { page = kvirt_to_pa(pos); - if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) { - mutex_unlock(&cam->busy_lock); + if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; - } start += PAGE_SIZE; pos += PAGE_SIZE; if (size > PAGE_SIZE) @@ -2528,7 +2495,5 @@ int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma) } cam->mmapped = true; - mutex_unlock(&cam->busy_lock); return 0; } - diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 7edf80b0d01a..9bad39842936 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -238,59 +238,40 @@ static struct v4l2_queryctrl controls[] = { static int cpia2_open(struct file *file) { struct camera_data *cam = video_drvdata(file); - int retval = 0; + struct cpia2_fh *fh; if (!cam) { ERR("Internal error, camera_data not found!\n"); return -ENODEV; } - if(mutex_lock_interruptible(&cam->busy_lock)) - return -ERESTARTSYS; - - if(!cam->present) { - retval = -ENODEV; - goto err_return; - } + if (!cam->present) + return -ENODEV; - if (cam->open_count > 0) { - goto skip_init; - } + if (cam->open_count == 0) { + if (cpia2_allocate_buffers(cam)) + return -ENOMEM; - if (cpia2_allocate_buffers(cam)) { - retval = -ENOMEM; - goto err_return; - } + /* reset the camera */ + if (cpia2_reset_camera(cam) < 0) + return -EIO; - /* reset the camera */ - if (cpia2_reset_camera(cam) < 0) { - retval = -EIO; - goto err_return; + cam->APP_len = 0; + cam->COM_len = 0; } - cam->APP_len = 0; - cam->COM_len = 0; - -skip_init: - { - struct cpia2_fh *fh = kmalloc(sizeof(*fh),GFP_KERNEL); - if(!fh) { - retval = -ENOMEM; - goto err_return; - } - file->private_data = fh; - fh->prio = V4L2_PRIORITY_UNSET; - v4l2_prio_open(&cam->prio, &fh->prio); - fh->mmapped = 0; - } + fh = kmalloc(sizeof(*fh), GFP_KERNEL); + if (!fh) + return -ENOMEM; + file->private_data = fh; + fh->prio = V4L2_PRIORITY_UNSET; + v4l2_prio_open(&cam->prio, &fh->prio); + fh->mmapped = 0; ++cam->open_count; cpia2_dbg_dump_registers(cam); - -err_return: - mutex_unlock(&cam->busy_lock); - return retval; + return 0; } /****************************************************************************** @@ -304,15 +285,11 @@ static int cpia2_close(struct file *file) struct camera_data *cam = video_get_drvdata(dev); struct cpia2_fh *fh = file->private_data; - mutex_lock(&cam->busy_lock); - if (cam->present && - (cam->open_count == 1 - || fh->prio == V4L2_PRIORITY_RECORD - )) { + (cam->open_count == 1 || fh->prio == V4L2_PRIORITY_RECORD)) { cpia2_usb_stream_stop(cam); - if(cam->open_count == 1) { + if (cam->open_count == 1) { /* save camera state for later open */ cpia2_save_camera_state(cam); @@ -321,26 +298,21 @@ static int cpia2_close(struct file *file) } } - { - if(fh->mmapped) - cam->mmapped = 0; - v4l2_prio_close(&cam->prio, fh->prio); - file->private_data = NULL; - kfree(fh); - } + if (fh->mmapped) + cam->mmapped = 0; + v4l2_prio_close(&cam->prio, fh->prio); + file->private_data = NULL; + kfree(fh); if (--cam->open_count == 0) { cpia2_free_buffers(cam); if (!cam->present) { video_unregister_device(dev); - mutex_unlock(&cam->busy_lock); kfree(cam); return 0; } } - mutex_unlock(&cam->busy_lock); - return 0; } @@ -405,11 +377,11 @@ static int sync(struct camera_data *cam, int frame_nr) return 0; } - mutex_unlock(&cam->busy_lock); + mutex_unlock(&cam->v4l2_lock); wait_event_interruptible(cam->wq_stream, !cam->streaming || frame->status == FRAME_READY); - mutex_lock(&cam->busy_lock); + mutex_lock(&cam->v4l2_lock); if (signal_pending(current)) return -ERESTARTSYS; if(!cam->present) @@ -1293,11 +1265,11 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file) if(frame < 0) { /* Wait for a frame to become available */ struct framebuf *cb=cam->curbuff; - mutex_unlock(&cam->busy_lock); + mutex_unlock(&cam->v4l2_lock); wait_event_interruptible(cam->wq_stream, !cam->present || (cb=cam->curbuff)->status == FRAME_READY); - mutex_lock(&cam->busy_lock); + mutex_lock(&cam->v4l2_lock); if (signal_pending(current)) return -ERESTARTSYS; if(!cam->present) @@ -1337,14 +1309,8 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (!cam) return -ENOTTY; - /* make this _really_ smp-safe */ - if (mutex_lock_interruptible(&cam->busy_lock)) - return -ERESTARTSYS; - - if (!cam->present) { - mutex_unlock(&cam->busy_lock); + if (!cam->present) return -ENODEV; - } /* Priority check */ switch (cmd) { @@ -1352,10 +1318,8 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct cpia2_fh *fh = file->private_data; retval = v4l2_prio_check(&cam->prio, fh->prio); - if(retval) { - mutex_unlock(&cam->busy_lock); + if (retval) return retval; - } break; } default: @@ -1529,7 +1493,6 @@ static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg) break; } - mutex_unlock(&cam->busy_lock); return retval; } @@ -1596,7 +1559,7 @@ static const struct v4l2_file_operations cpia2_fops = { .release = cpia2_close, .read = cpia2_v4l_read, .poll = cpia2_v4l_poll, - .ioctl = cpia2_ioctl, + .unlocked_ioctl = cpia2_ioctl, .mmap = cpia2_mmap, }; @@ -1620,6 +1583,7 @@ int cpia2_register_camera(struct camera_data *cam) memcpy(cam->vdev, &cpia2_template, sizeof(cpia2_template)); video_set_drvdata(cam->vdev, cam); + cam->vdev->lock = &cam->v4l2_lock; reset_camera_struct_v4l(cam); diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 133ec2bac180..944af8adbe0c 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -664,7 +664,7 @@ static int __devinit cx18_create_in_workq(struct cx18 *cx) { snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in", cx->v4l2_dev.name); - cx->in_work_queue = create_singlethread_workqueue(cx->in_workq_name); + cx->in_work_queue = alloc_ordered_workqueue(cx->in_workq_name, 0); if (cx->in_work_queue == NULL) { CX18_ERR("Unable to create incoming mailbox handler thread\n"); return -ENOMEM; @@ -672,18 +672,6 @@ static int __devinit cx18_create_in_workq(struct cx18 *cx) return 0; } -static int __devinit cx18_create_out_workq(struct cx18 *cx) -{ - snprintf(cx->out_workq_name, sizeof(cx->out_workq_name), "%s-out", - cx->v4l2_dev.name); - cx->out_work_queue = create_workqueue(cx->out_workq_name); - if (cx->out_work_queue == NULL) { - CX18_ERR("Unable to create outgoing mailbox handler threads\n"); - return -ENOMEM; - } - return 0; -} - static void __devinit cx18_init_in_work_orders(struct cx18 *cx) { int i; @@ -710,15 +698,9 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) mutex_init(&cx->epu2apu_mb_lock); mutex_init(&cx->epu2cpu_mb_lock); - ret = cx18_create_out_workq(cx); - if (ret) - return ret; - ret = cx18_create_in_workq(cx); - if (ret) { - destroy_workqueue(cx->out_work_queue); + if (ret) return ret; - } cx18_init_in_work_orders(cx); @@ -1107,7 +1089,6 @@ free_mem: release_mem_region(cx->base_addr, CX18_MEM_SIZE); free_workqueues: destroy_workqueue(cx->in_work_queue); - destroy_workqueue(cx->out_work_queue); err: if (retval == 0) retval = -ENODEV; @@ -1259,7 +1240,6 @@ static void cx18_remove(struct pci_dev *pci_dev) cx18_halt_firmware(cx); destroy_workqueue(cx->in_work_queue); - destroy_workqueue(cx->out_work_queue); cx18_streams_cleanup(cx, 1); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index f6f3e50d4bdf..306caac6d3fc 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -617,9 +617,6 @@ struct cx18 { struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS]; char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */ - struct workqueue_struct *out_work_queue; - char out_workq_name[12]; /* "cx18-NN-out" */ - /* i2c */ struct i2c_adapter i2c_adap[2]; struct i2c_algo_bit_data i2c_algo[2]; diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 51765eb12d39..713b0e61536d 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h @@ -42,8 +42,7 @@ static inline bool cx18_stream_enabled(struct cx18_stream *s) /* Related to submission of mdls to firmware */ static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) { - struct cx18 *cx = s->cx; - queue_work(cx->out_work_queue, &s->out_work_order); + schedule_work(&s->out_work_order); } static inline void cx18_stream_put_mdl_fw(struct cx18_stream *s, diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c index fe59a1c3f064..363aa6004221 100644 --- a/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/drivers/media/video/cx231xx/cx231xx-dvb.c @@ -28,7 +28,6 @@ #include <media/videobuf-vmalloc.h> #include "xc5000.h" -#include "dvb_dummy_fe.h" #include "s5h1432.h" #include "tda18271.h" #include "s5h1411.h" @@ -619,7 +618,7 @@ static int dvb_init(struct cx231xx *dev) if (dev->dvb->frontend == NULL) { printk(DRIVER_NAME - ": Failed to attach dummy front end\n"); + ": Failed to attach s5h1411 front end\n"); result = -EINVAL; goto out_free; } @@ -665,7 +664,7 @@ static int dvb_init(struct cx231xx *dev) if (dev->dvb->frontend == NULL) { printk(DRIVER_NAME - ": Failed to attach dummy front end\n"); + ": Failed to attach s5h1411 front end\n"); result = -EINVAL; goto out_free; } diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index f16461844c5c..6fc09dd41b9d 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1682,20 +1682,6 @@ static int cx25840_log_status(struct v4l2_subdev *sd) return 0; } -static int cx25840_s_config(struct v4l2_subdev *sd, int irq, void *platform_data) -{ - struct cx25840_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (platform_data) { - struct cx25840_platform_data *pdata = platform_data; - - state->pvr150_workaround = pdata->pvr150_workaround; - set_input(client, state->vid_input, state->aud_input); - } - return 0; -} - static int cx23885_irq_handler(struct v4l2_subdev *sd, u32 status, bool *handled) { @@ -1787,7 +1773,6 @@ static const struct v4l2_ctrl_ops cx25840_ctrl_ops = { static const struct v4l2_subdev_core_ops cx25840_core_ops = { .log_status = cx25840_log_status, - .s_config = cx25840_s_config, .g_chip_ident = cx25840_g_chip_ident, .g_ctrl = v4l2_subdev_g_ctrl, .s_ctrl = v4l2_subdev_s_ctrl, @@ -1974,7 +1959,6 @@ static int cx25840_probe(struct i2c_client *client, state->vid_input = CX25840_COMPOSITE7; state->aud_input = CX25840_AUDIO8; state->audclk_freq = 48000; - state->pvr150_workaround = 0; state->audmode = V4L2_TUNER_MODE_LANG1; state->vbi_line_offset = 8; state->id = id; @@ -2034,6 +2018,12 @@ static int cx25840_probe(struct i2c_client *client, v4l2_ctrl_cluster(2, &state->volume); v4l2_ctrl_handler_setup(&state->hdl); + if (client->dev.platform_data) { + struct cx25840_platform_data *pdata = client->dev.platform_data; + + state->pvr150_workaround = pdata->pvr150_workaround; + } + cx25840_ir_probe(sd); return 0; } diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c index 1f532e31cd49..9f3bfc1eb240 100644 --- a/drivers/media/video/davinci/vpif.c +++ b/drivers/media/video/davinci/vpif.c @@ -41,6 +41,183 @@ spinlock_t vpif_lock; void __iomem *vpif_base; +/** + * ch_params: video standard configuration parameters for vpif + * The table must include all presets from supported subdevices. + */ +const struct vpif_channel_config_params ch_params[] = { + /* HDTV formats */ + { + .name = "480p59_94", + .width = 720, + .height = 480, + .frm_fmt = 1, + .ycmux_mode = 0, + .eav2sav = 138-8, + .sav2eav = 720, + .l1 = 1, + .l3 = 43, + .l5 = 523, + .vsize = 525, + .capture_format = 0, + .vbi_supported = 0, + .hd_sd = 1, + .dv_preset = V4L2_DV_480P59_94, + }, + { + .name = "576p50", + .width = 720, + .height = 576, + .frm_fmt = 1, + .ycmux_mode = 0, + .eav2sav = 144-8, + .sav2eav = 720, + .l1 = 1, + .l3 = 45, + .l5 = 621, + .vsize = 625, + .capture_format = 0, + .vbi_supported = 0, + .hd_sd = 1, + .dv_preset = V4L2_DV_576P50, + }, + { + .name = "720p50", + .width = 1280, + .height = 720, + .frm_fmt = 1, + .ycmux_mode = 0, + .eav2sav = 700-8, + .sav2eav = 1280, + .l1 = 1, + .l3 = 26, + .l5 = 746, + .vsize = 750, + .capture_format = 0, + .vbi_supported = 0, + .hd_sd = 1, + .dv_preset = V4L2_DV_720P50, + }, + { + .name = "720p60", + .width = 1280, + .height = 720, + .frm_fmt = 1, + .ycmux_mode = 0, + .eav2sav = 370 - 8, + .sav2eav = 1280, + .l1 = 1, + .l3 = 26, + .l5 = 746, + .vsize = 750, + .capture_format = 0, + .vbi_supported = 0, + .hd_sd = 1, + .dv_preset = V4L2_DV_720P60, + }, + { + .name = "1080I50", + .width = 1920, + .height = 1080, + .frm_fmt = 0, + .ycmux_mode = 0, + .eav2sav = 720 - 8, + .sav2eav = 1920, + .l1 = 1, + .l3 = 21, + .l5 = 561, + .l7 = 563, + .l9 = 584, + .l11 = 1124, + .vsize = 1125, + .capture_format = 0, + .vbi_supported = 0, + .hd_sd = 1, + .dv_preset = V4L2_DV_1080I50, + }, + { + .name = "1080I60", + .width = 1920, + .height = 1080, + .frm_fmt = 0, + .ycmux_mode = 0, + .eav2sav = 280 - 8, + .sav2eav = 1920, + .l1 = 1, + .l3 = 21, + .l5 = 561, + .l7 = 563, + .l9 = 584, + .l11 = 1124, + .vsize = 1125, + .capture_format = 0, + .vbi_supported = 0, + .hd_sd = 1, + .dv_preset = V4L2_DV_1080I60, + }, + { + .name = "1080p60", + .width = 1920, + .height = 1080, + .frm_fmt = 1, + .ycmux_mode = 0, + .eav2sav = 280 - 8, + .sav2eav = 1920, + .l1 = 1, + .l3 = 42, + .l5 = 1122, + .vsize = 1125, + .capture_format = 0, + .vbi_supported = 0, + .hd_sd = 1, + .dv_preset = V4L2_DV_1080P60, + }, + + /* SDTV formats */ + { + .name = "NTSC_M", + .width = 720, + .height = 480, + .frm_fmt = 0, + .ycmux_mode = 1, + .eav2sav = 268, + .sav2eav = 1440, + .l1 = 1, + .l3 = 23, + .l5 = 263, + .l7 = 266, + .l9 = 286, + .l11 = 525, + .vsize = 525, + .capture_format = 0, + .vbi_supported = 1, + .hd_sd = 0, + .stdid = V4L2_STD_525_60, + }, + { + .name = "PAL_BDGHIK", + .width = 720, + .height = 576, + .frm_fmt = 0, + .ycmux_mode = 1, + .eav2sav = 280, + .sav2eav = 1440, + .l1 = 1, + .l3 = 23, + .l5 = 311, + .l7 = 313, + .l9 = 336, + .l11 = 624, + .vsize = 625, + .capture_format = 0, + .vbi_supported = 1, + .hd_sd = 0, + .stdid = V4L2_STD_625_50, + }, +}; + +const unsigned int vpif_ch_params_count = ARRAY_SIZE(ch_params); + static inline void vpif_wr_bit(u32 reg, u32 bit, u32 val) { if (val) diff --git a/drivers/media/video/davinci/vpif.h b/drivers/media/video/davinci/vpif.h index ebd5c4338ebb..10550bd93b06 100644 --- a/drivers/media/video/davinci/vpif.h +++ b/drivers/media/video/davinci/vpif.h @@ -577,12 +577,10 @@ struct vpif_channel_config_params { char name[VPIF_MAX_NAME]; /* Name of the mode */ u16 width; /* Indicates width of the image */ u16 height; /* Indicates height of the image */ - u8 fps; - u8 frm_fmt; /* Indicates whether this is interlaced - * or progressive format */ - u8 ycmux_mode; /* Indicates whether this mode requires - * single or two channels */ - u16 eav2sav; /* length of sav 2 eav */ + u8 frm_fmt; /* Interlaced (0) or progressive (1) */ + u8 ycmux_mode; /* This mode requires one (0) or two (1) + channels */ + u16 eav2sav; /* length of eav 2 sav */ u16 sav2eav; /* length of sav 2 eav */ u16 l1, l3, l5, l7, l9, l11; /* Other parameter configurations */ u16 vsize; /* Vertical size of the image */ @@ -590,10 +588,14 @@ struct vpif_channel_config_params { * is in BT or in CCD/CMOS */ u8 vbi_supported; /* Indicates whether this mode * supports capturing vbi or not */ - u8 hd_sd; - v4l2_std_id stdid; + u8 hd_sd; /* HDTV (1) or SDTV (0) format */ + v4l2_std_id stdid; /* SDTV format */ + u32 dv_preset; /* HDTV format */ }; +extern const unsigned int vpif_ch_params_count; +extern const struct vpif_channel_config_params ch_params[]; + struct vpif_video_params; struct vpif_params; struct vpif_vbi_params; diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index 193abab6b355..d93ad74a34c5 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c @@ -37,6 +37,7 @@ #include <linux/slab.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-chip-ident.h> #include "vpif_capture.h" #include "vpif.h" @@ -81,20 +82,6 @@ static struct vpif_device vpif_obj = { {NULL} }; static struct device *vpif_dev; /** - * ch_params: video standard configuration parameters for vpif - */ -static const struct vpif_channel_config_params ch_params[] = { - { - "NTSC_M", 720, 480, 30, 0, 1, 268, 1440, 1, 23, 263, 266, - 286, 525, 525, 0, 1, 0, V4L2_STD_525_60, - }, - { - "PAL_BDGHIK", 720, 576, 25, 0, 1, 280, 1440, 1, 23, 311, 313, - 336, 624, 625, 0, 1, 0, V4L2_STD_625_50, - }, -}; - -/** * vpif_uservirt_to_phys : translate user/virtual address to phy address * @virtp: user/virtual address * @@ -342,7 +329,7 @@ static void vpif_schedule_next_buffer(struct common_obj *common) * @dev_id: dev_id ptr * * It changes status of the captured buffer, takes next buffer from the queue - * and sets its address in VPIF registers + * and sets its address in VPIF registers */ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) { @@ -435,24 +422,31 @@ static int vpif_update_std_info(struct channel_obj *ch) struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct vpif_params *vpifparams = &ch->vpifparams; const struct vpif_channel_config_params *config; - struct vpif_channel_config_params *std_info; + struct vpif_channel_config_params *std_info = &vpifparams->std_info; struct video_obj *vid_ch = &ch->video; int index; vpif_dbg(2, debug, "vpif_update_std_info\n"); - std_info = &vpifparams->std_info; - - for (index = 0; index < ARRAY_SIZE(ch_params); index++) { + for (index = 0; index < vpif_ch_params_count; index++) { config = &ch_params[index]; - if (config->stdid & vid_ch->stdid) { - memcpy(std_info, config, sizeof(*config)); - break; + if (config->hd_sd == 0) { + vpif_dbg(2, debug, "SD format\n"); + if (config->stdid & vid_ch->stdid) { + memcpy(std_info, config, sizeof(*config)); + break; + } + } else { + vpif_dbg(2, debug, "HD format\n"); + if (config->dv_preset == vid_ch->dv_preset) { + memcpy(std_info, config, sizeof(*config)); + break; + } } } /* standard not found */ - if (index == ARRAY_SIZE(ch_params)) + if (index == vpif_ch_params_count) return -EINVAL; common->fmt.fmt.pix.width = std_info->width; @@ -462,6 +456,7 @@ static int vpif_update_std_info(struct channel_obj *ch) common->fmt.fmt.pix.bytesperline = std_info->width; vpifparams->video_params.hpitch = std_info->width; vpifparams->video_params.storage_mode = std_info->frm_fmt; + return 0; } @@ -757,7 +752,7 @@ static int vpif_open(struct file *filep) struct video_obj *vid_ch; struct channel_obj *ch; struct vpif_fh *fh; - int i, ret = 0; + int i; vpif_dbg(2, debug, "vpif_open\n"); @@ -766,9 +761,6 @@ static int vpif_open(struct file *filep) vid_ch = &ch->video; common = &ch->common[VPIF_VIDEO_INDEX]; - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - if (NULL == ch->curr_subdev_info) { /** * search through the sub device to see a registered @@ -785,8 +777,7 @@ static int vpif_open(struct file *filep) } if (i == config->subdev_count) { vpif_err("No sub device registered\n"); - ret = -ENOENT; - goto exit; + return -ENOENT; } } @@ -794,8 +785,7 @@ static int vpif_open(struct file *filep) fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); if (NULL == fh) { vpif_err("unable to allocate memory for file handle object\n"); - ret = -ENOMEM; - goto exit; + return -ENOMEM; } /* store pointer to fh in private_data member of filep */ @@ -815,9 +805,7 @@ static int vpif_open(struct file *filep) /* Initialize priority of this instance to default priority */ fh->prio = V4L2_PRIORITY_UNSET; v4l2_prio_open(&ch->prio, &fh->prio); -exit: - mutex_unlock(&common->lock); - return ret; + return 0; } /** @@ -837,9 +825,6 @@ static int vpif_release(struct file *filep) common = &ch->common[VPIF_VIDEO_INDEX]; - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - /* if this instance is doing IO */ if (fh->io_allowed[VPIF_VIDEO_INDEX]) { /* Reset io_usrs member of channel object */ @@ -863,9 +848,6 @@ static int vpif_release(struct file *filep) /* Decrement channel usrs counter */ ch->usrs--; - /* unlock mutex on channel object */ - mutex_unlock(&common->lock); - /* Close the priority */ v4l2_prio_close(&ch->prio, fh->prio); @@ -890,7 +872,6 @@ static int vpif_reqbufs(struct file *file, void *priv, struct channel_obj *ch = fh->channel; struct common_obj *common; u8 index = 0; - int ret = 0; vpif_dbg(2, debug, "vpif_reqbufs\n"); @@ -913,13 +894,8 @@ static int vpif_reqbufs(struct file *file, void *priv, common = &ch->common[index]; - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - if (0 != common->io_usrs) { - ret = -EBUSY; - goto reqbuf_exit; - } + if (0 != common->io_usrs) + return -EBUSY; /* Initialize videobuf queue as per the buffer type */ videobuf_queue_dma_contig_init(&common->buffer_queue, @@ -928,7 +904,7 @@ static int vpif_reqbufs(struct file *file, void *priv, reqbuf->type, common->fmt.fmt.pix.field, sizeof(struct videobuf_buffer), fh, - NULL); + &common->lock); /* Set io allowed member of file handle to TRUE */ fh->io_allowed[index] = 1; @@ -939,11 +915,7 @@ static int vpif_reqbufs(struct file *file, void *priv, INIT_LIST_HEAD(&common->dma_queue); /* Allocate buffers */ - ret = videobuf_reqbufs(&common->buffer_queue, reqbuf); - -reqbuf_exit: - mutex_unlock(&common->lock); - return ret; + return videobuf_reqbufs(&common->buffer_queue, reqbuf); } /** @@ -1157,11 +1129,6 @@ static int vpif_streamon(struct file *file, void *priv, return ret; } - if (mutex_lock_interruptible(&common->lock)) { - ret = -ERESTARTSYS; - goto streamoff_exit; - } - /* If buffer queue is empty, return error */ if (list_empty(&common->dma_queue)) { vpif_dbg(1, debug, "buffer queue is empty\n"); @@ -1240,13 +1207,10 @@ static int vpif_streamon(struct file *file, void *priv, enable_channel1(1); } channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; - mutex_unlock(&common->lock); return ret; exit: - mutex_unlock(&common->lock); -streamoff_exit: - ret = videobuf_streamoff(&common->buffer_queue); + videobuf_streamoff(&common->buffer_queue); return ret; } @@ -1284,9 +1248,6 @@ static int vpif_streamoff(struct file *file, void *priv, return -EINVAL; } - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - /* disable channel */ if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { enable_channel0(0); @@ -1304,8 +1265,6 @@ static int vpif_streamoff(struct file *file, void *priv, if (ret && (ret != -ENOIOCTLCMD)) vpif_dbg(1, debug, "stream off failed in subdev\n"); - mutex_unlock(&common->lock); - return videobuf_streamoff(&common->buffer_queue); } @@ -1381,21 +1340,16 @@ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id) { struct vpif_fh *fh = priv; struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; int ret = 0; vpif_dbg(2, debug, "vpif_querystd\n"); - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - /* Call querystd function of decoder device */ ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, querystd, std_id); if (ret < 0) vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); - mutex_unlock(&common->lock); return ret; } @@ -1451,16 +1405,14 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) fh->initialized = 1; /* Call encoder subdevice function to set the standard */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - ch->video.stdid = *std_id; + ch->video.dv_preset = V4L2_DV_INVALID; + memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings)); /* Get the information about the standard */ if (vpif_update_std_info(ch)) { - ret = -EINVAL; vpif_err("Error getting the standard info\n"); - goto s_std_exit; + return -EINVAL; } /* Configure the default format information */ @@ -1471,9 +1423,6 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) s_std, *std_id); if (ret < 0) vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); - -s_std_exit: - mutex_unlock(&common->lock); return ret; } @@ -1567,9 +1516,6 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) return -EINVAL; } - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - /* first setup input path from sub device to vpif */ if (config->setup_input_path) { ret = config->setup_input_path(ch->channel_id, @@ -1578,7 +1524,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) vpif_dbg(1, debug, "couldn't setup input path for the" " sub device %s, for input index %d\n", subdev_info->name, index); - goto exit; + return ret; } } @@ -1589,7 +1535,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) input, output, 0); if (ret < 0) { vpif_dbg(1, debug, "Failed to set input\n"); - goto exit; + return ret; } } vid_ch->input_idx = index; @@ -1600,9 +1546,6 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index) /* update tvnorms from the sub device input info */ ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std; - -exit: - mutex_unlock(&common->lock); return ret; } @@ -1671,11 +1614,7 @@ static int vpif_g_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; /* Fill in the information about format */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - *fmt = common->fmt; - mutex_unlock(&common->lock); return 0; } @@ -1694,7 +1633,7 @@ static int vpif_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_pix_format *pixfmt; int ret = 0; - vpif_dbg(2, debug, "VIDIOC_S_FMT\n"); + vpif_dbg(2, debug, "%s\n", __func__); /* If streaming is started, return error */ if (common->started) { @@ -1723,12 +1662,7 @@ static int vpif_s_fmt_vid_cap(struct file *file, void *priv, if (ret) return ret; /* store the format in the channel object */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - common->fmt = *fmt; - mutex_unlock(&common->lock); - return 0; } @@ -1807,6 +1741,306 @@ static int vpif_cropcap(struct file *file, void *priv, return 0; } +/** + * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler + * @file: file ptr + * @priv: file handle + * @preset: input preset + */ +static int vpif_enum_dv_presets(struct file *file, void *priv, + struct v4l2_dv_enum_preset *preset) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + + return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], + video, enum_dv_presets, preset); +} + +/** + * vpif_query_dv_presets() - QUERY_DV_PRESET handler + * @file: file ptr + * @priv: file handle + * @preset: input preset + */ +static int vpif_query_dv_preset(struct file *file, void *priv, + struct v4l2_dv_preset *preset) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + + return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], + video, query_dv_preset, preset); +} +/** + * vpif_s_dv_presets() - S_DV_PRESETS handler + * @file: file ptr + * @priv: file handle + * @preset: input preset + */ +static int vpif_s_dv_preset(struct file *file, void *priv, + struct v4l2_dv_preset *preset) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + int ret = 0; + + if (common->started) { + vpif_dbg(1, debug, "streaming in progress\n"); + return -EBUSY; + } + + if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || + (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { + if (!fh->initialized) { + vpif_dbg(1, debug, "Channel Busy\n"); + return -EBUSY; + } + } + + ret = v4l2_prio_check(&ch->prio, fh->prio); + if (ret) + return ret; + + fh->initialized = 1; + + /* Call encoder subdevice function to set the standard */ + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; + + ch->video.dv_preset = preset->preset; + ch->video.stdid = V4L2_STD_UNKNOWN; + memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings)); + + /* Get the information about the standard */ + if (vpif_update_std_info(ch)) { + vpif_dbg(1, debug, "Error getting the standard info\n"); + ret = -EINVAL; + } else { + /* Configure the default format information */ + vpif_config_format(ch); + + ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], + video, s_dv_preset, preset); + } + + mutex_unlock(&common->lock); + + return ret; +} +/** + * vpif_g_dv_presets() - G_DV_PRESETS handler + * @file: file ptr + * @priv: file handle + * @preset: input preset + */ +static int vpif_g_dv_preset(struct file *file, void *priv, + struct v4l2_dv_preset *preset) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + + preset->preset = ch->video.dv_preset; + + return 0; +} + +/** + * vpif_s_dv_timings() - S_DV_TIMINGS handler + * @file: file ptr + * @priv: file handle + * @timings: digital video timings + */ +static int vpif_s_dv_timings(struct file *file, void *priv, + struct v4l2_dv_timings *timings) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct vpif_params *vpifparams = &ch->vpifparams; + struct vpif_channel_config_params *std_info = &vpifparams->std_info; + struct video_obj *vid_ch = &ch->video; + struct v4l2_bt_timings *bt = &vid_ch->bt_timings; + int ret; + + if (timings->type != V4L2_DV_BT_656_1120) { + vpif_dbg(2, debug, "Timing type not defined\n"); + return -EINVAL; + } + + /* Configure subdevice timings, if any */ + ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], + video, s_dv_timings, timings); + if (ret == -ENOIOCTLCMD) { + vpif_dbg(2, debug, "Custom DV timings not supported by " + "subdevice\n"); + return -EINVAL; + } + if (ret < 0) { + vpif_dbg(2, debug, "Error setting custom DV timings\n"); + return ret; + } + + if (!(timings->bt.width && timings->bt.height && + (timings->bt.hbackporch || + timings->bt.hfrontporch || + timings->bt.hsync) && + timings->bt.vfrontporch && + (timings->bt.vbackporch || + timings->bt.vsync))) { + vpif_dbg(2, debug, "Timings for width, height, " + "horizontal back porch, horizontal sync, " + "horizontal front porch, vertical back porch, " + "vertical sync and vertical back porch " + "must be defined\n"); + return -EINVAL; + } + + *bt = timings->bt; + + /* Configure video port timings */ + + std_info->eav2sav = bt->hbackporch + bt->hfrontporch + + bt->hsync - 8; + std_info->sav2eav = bt->width; + + std_info->l1 = 1; + std_info->l3 = bt->vsync + bt->vbackporch + 1; + + if (bt->interlaced) { + if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) { + std_info->vsize = bt->height * 2 + + bt->vfrontporch + bt->vsync + bt->vbackporch + + bt->il_vfrontporch + bt->il_vsync + + bt->il_vbackporch; + std_info->l5 = std_info->vsize/2 - + (bt->vfrontporch - 1); + std_info->l7 = std_info->vsize/2 + 1; + std_info->l9 = std_info->l7 + bt->il_vsync + + bt->il_vbackporch + 1; + std_info->l11 = std_info->vsize - + (bt->il_vfrontporch - 1); + } else { + vpif_dbg(2, debug, "Required timing values for " + "interlaced BT format missing\n"); + return -EINVAL; + } + } else { + std_info->vsize = bt->height + bt->vfrontporch + + bt->vsync + bt->vbackporch; + std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); + } + strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME); + std_info->width = bt->width; + std_info->height = bt->height; + std_info->frm_fmt = bt->interlaced ? 0 : 1; + std_info->ycmux_mode = 0; + std_info->capture_format = 0; + std_info->vbi_supported = 0; + std_info->hd_sd = 1; + std_info->stdid = 0; + std_info->dv_preset = V4L2_DV_INVALID; + + vid_ch->stdid = 0; + vid_ch->dv_preset = V4L2_DV_INVALID; + return 0; +} + +/** + * vpif_g_dv_timings() - G_DV_TIMINGS handler + * @file: file ptr + * @priv: file handle + * @timings: digital video timings + */ +static int vpif_g_dv_timings(struct file *file, void *priv, + struct v4l2_dv_timings *timings) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct video_obj *vid_ch = &ch->video; + struct v4l2_bt_timings *bt = &vid_ch->bt_timings; + + timings->bt = *bt; + + return 0; +} + +/* + * vpif_g_chip_ident() - Identify the chip + * @file: file ptr + * @priv: file handle + * @chip: chip identity + * + * Returns zero or -EINVAL if read operations fails. + */ +static int vpif_g_chip_ident(struct file *file, void *priv, + struct v4l2_dbg_chip_ident *chip) +{ + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && + chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) { + vpif_dbg(2, debug, "match_type is invalid.\n"); + return -EINVAL; + } + + return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core, + g_chip_ident, chip); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +/* + * vpif_dbg_g_register() - Read register + * @file: file ptr + * @priv: file handle + * @reg: register to be read + * + * Debugging only + * Returns zero or -EINVAL if read operations fails. + */ +static int vpif_dbg_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg){ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + + return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core, + g_register, reg); +} + +/* + * vpif_dbg_s_register() - Write to register + * @file: file ptr + * @priv: file handle + * @reg: register to be modified + * + * Debugging only + * Returns zero or -EINVAL if write operations fails. + */ +static int vpif_dbg_s_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg){ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + + return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core, + s_register, reg); +} +#endif + +/* + * vpif_log_status() - Status information + * @file: file ptr + * @priv: file handle + * + * Returns zero. + */ +static int vpif_log_status(struct file *filep, void *priv) +{ + /* status for sub devices */ + v4l2_device_call_all(&vpif_obj.v4l2_dev, 0, core, log_status); + + return 0; +} + /* vpif capture ioctl operations */ static const struct v4l2_ioctl_ops vpif_ioctl_ops = { .vidioc_querycap = vpif_querycap, @@ -1829,6 +2063,18 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = { .vidioc_streamon = vpif_streamon, .vidioc_streamoff = vpif_streamoff, .vidioc_cropcap = vpif_cropcap, + .vidioc_enum_dv_presets = vpif_enum_dv_presets, + .vidioc_s_dv_preset = vpif_s_dv_preset, + .vidioc_g_dv_preset = vpif_g_dv_preset, + .vidioc_query_dv_preset = vpif_query_dv_preset, + .vidioc_s_dv_timings = vpif_s_dv_timings, + .vidioc_g_dv_timings = vpif_g_dv_timings, + .vidioc_g_chip_ident = vpif_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vpif_dbg_g_register, + .vidioc_s_register = vpif_dbg_s_register, +#endif + .vidioc_log_status = vpif_log_status, }; /* vpif file operations */ @@ -1836,7 +2082,7 @@ static struct v4l2_file_operations vpif_fops = { .owner = THIS_MODULE, .open = vpif_open, .release = vpif_release, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .mmap = vpif_mmap, .poll = vpif_poll }; @@ -1979,6 +2225,7 @@ static __init int vpif_probe(struct platform_device *pdev) common = &(ch->common[VPIF_VIDEO_INDEX]); spin_lock_init(&common->irqlock); mutex_init(&common->lock); + ch->video_dev->lock = &common->lock; /* Initialize prio member of channel object */ v4l2_prio_init(&ch->prio); err = video_register_device(ch->video_dev, @@ -2026,9 +2273,9 @@ static __init int vpif_probe(struct platform_device *pdev) if (vpif_obj.sd[i]) vpif_obj.sd[i]->grp_id = 1 << i; } - v4l2_info(&vpif_obj.v4l2_dev, "DM646x VPIF Capture driver" - " initialized\n"); + v4l2_info(&vpif_obj.v4l2_dev, + "DM646x VPIF capture driver initialized\n"); return 0; probe_subdev_out: diff --git a/drivers/media/video/davinci/vpif_capture.h b/drivers/media/video/davinci/vpif_capture.h index 4e12ec8cac6f..7a4196dfdce1 100644 --- a/drivers/media/video/davinci/vpif_capture.h +++ b/drivers/media/video/davinci/vpif_capture.h @@ -59,6 +59,8 @@ struct video_obj { enum v4l2_field buf_field; /* Currently selected or default standard */ v4l2_std_id stdid; + u32 dv_preset; + struct v4l2_bt_timings bt_timings; /* This is to track the last input that is passed to application */ u32 input_idx; }; diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index 412c65d54fe1..cdf659abdc2a 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c @@ -38,6 +38,7 @@ #include <media/adv7343.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-chip-ident.h> #include <mach/dm646x.h> @@ -84,17 +85,6 @@ static struct vpif_config_params config_params = { static struct vpif_device vpif_obj = { {NULL} }; static struct device *vpif_dev; -static const struct vpif_channel_config_params ch_params[] = { - { - "NTSC", 720, 480, 30, 0, 1, 268, 1440, 1, 23, 263, 266, - 286, 525, 525, 0, 1, 0, V4L2_STD_525_60, - }, - { - "PAL", 720, 576, 25, 0, 1, 280, 1440, 1, 23, 311, 313, - 336, 624, 625, 0, 1, 0, V4L2_STD_625_50, - }, -}; - /* * vpif_uservirt_to_phys: This function is used to convert user * space virtual address to physical address. @@ -373,30 +363,54 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int vpif_get_std_info(struct channel_obj *ch) +static int vpif_update_std_info(struct channel_obj *ch) { - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; struct video_obj *vid_ch = &ch->video; struct vpif_params *vpifparams = &ch->vpifparams; struct vpif_channel_config_params *std_info = &vpifparams->std_info; const struct vpif_channel_config_params *config; - int index; - - std_info->stdid = vid_ch->stdid; - if (!std_info->stdid) - return -1; + int i; - for (index = 0; index < ARRAY_SIZE(ch_params); index++) { - config = &ch_params[index]; - if (config->stdid & std_info->stdid) { - memcpy(std_info, config, sizeof(*config)); - break; + for (i = 0; i < vpif_ch_params_count; i++) { + config = &ch_params[i]; + if (config->hd_sd == 0) { + vpif_dbg(2, debug, "SD format\n"); + if (config->stdid & vid_ch->stdid) { + memcpy(std_info, config, sizeof(*config)); + break; + } + } else { + vpif_dbg(2, debug, "HD format\n"); + if (config->dv_preset == vid_ch->dv_preset) { + memcpy(std_info, config, sizeof(*config)); + break; + } } } - if (index == ARRAY_SIZE(ch_params)) - return -1; + if (i == vpif_ch_params_count) { + vpif_dbg(1, debug, "Format not found\n"); + return -EINVAL; + } + + return 0; +} + +static int vpif_update_resolution(struct channel_obj *ch) +{ + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct video_obj *vid_ch = &ch->video; + struct vpif_params *vpifparams = &ch->vpifparams; + struct vpif_channel_config_params *std_info = &vpifparams->std_info; + + if (!vid_ch->stdid && !vid_ch->dv_preset && !vid_ch->bt_timings.height) + return -EINVAL; + + if (vid_ch->stdid || vid_ch->dv_preset) { + if (vpif_update_std_info(ch)) + return -EINVAL; + } common->fmt.fmt.pix.width = std_info->width; common->fmt.fmt.pix.height = std_info->height; @@ -404,8 +418,8 @@ static int vpif_get_std_info(struct channel_obj *ch) common->fmt.fmt.pix.width, common->fmt.fmt.pix.height); /* Set height and width paramateres */ - ch->common[VPIF_VIDEO_INDEX].height = std_info->height; - ch->common[VPIF_VIDEO_INDEX].width = std_info->width; + common->height = std_info->height; + common->width = std_info->width; return 0; } @@ -516,10 +530,8 @@ static int vpif_check_format(struct channel_obj *ch, else sizeimage = config_params.channel_bufsize[ch->channel_id]; - if (vpif_get_std_info(ch)) { - vpif_err("Error getting the standard info\n"); + if (vpif_update_resolution(ch)) return -EINVAL; - } hpitch = pixfmt->bytesperline; vpitch = sizeimage / (hpitch * 2); @@ -568,7 +580,10 @@ static void vpif_config_addr(struct channel_obj *ch, int muxmode) static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) { struct vpif_fh *fh = filep->private_data; - struct common_obj *common = &fh->channel->common[VPIF_VIDEO_INDEX]; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); + + vpif_dbg(2, debug, "vpif_mmap\n"); return videobuf_mmap_mapper(&common->buffer_queue, vma); } @@ -637,9 +652,6 @@ static int vpif_release(struct file *filep) struct channel_obj *ch = fh->channel; struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - /* if this instance is doing IO */ if (fh->io_allowed[VPIF_VIDEO_INDEX]) { /* Reset io_usrs member of channel object */ @@ -662,8 +674,6 @@ static int vpif_release(struct file *filep) config_params.numbuffers[ch->channel_id]; } - mutex_unlock(&common->lock); - /* Decrement channel usrs counter */ atomic_dec(&ch->usrs); /* If this file handle has initialize encoder device, reset it */ @@ -680,7 +690,12 @@ static int vpif_release(struct file *filep) } /* functions implementing ioctls */ - +/** + * vpif_querycap() - QUERYCAP handler + * @file: file ptr + * @priv: file handle + * @cap: ptr to v4l2_capability structure + */ static int vpif_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { @@ -722,17 +737,9 @@ static int vpif_g_fmt_vid_out(struct file *file, void *priv, if (common->fmt.type != fmt->type) return -EINVAL; - /* Fill in the information about format */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - if (vpif_get_std_info(ch)) { - vpif_err("Error getting the standard info\n"); + if (vpif_update_resolution(ch)) return -EINVAL; - } - *fmt = common->fmt; - mutex_unlock(&common->lock); return 0; } @@ -773,12 +780,7 @@ static int vpif_s_fmt_vid_out(struct file *file, void *priv, /* store the pix format in the channel object */ common->fmt.fmt.pix = *pixfmt; /* store the format in the channel object */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - common->fmt = *fmt; - mutex_unlock(&common->lock); - return 0; } @@ -808,7 +810,6 @@ static int vpif_reqbufs(struct file *file, void *priv, struct common_obj *common; enum v4l2_field field; u8 index = 0; - int ret = 0; /* This file handle has not initialized the channel, It is not allowed to do settings */ @@ -826,18 +827,12 @@ static int vpif_reqbufs(struct file *file, void *priv, index = VPIF_VIDEO_INDEX; common = &ch->common[index]; - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - if (common->fmt.type != reqbuf->type) { - ret = -EINVAL; - goto reqbuf_exit; - } + if (common->fmt.type != reqbuf->type) + return -EINVAL; - if (0 != common->io_usrs) { - ret = -EBUSY; - goto reqbuf_exit; - } + if (0 != common->io_usrs) + return -EBUSY; if (reqbuf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { if (common->fmt.fmt.pix.field == V4L2_FIELD_ANY) @@ -854,7 +849,7 @@ static int vpif_reqbufs(struct file *file, void *priv, &common->irqlock, reqbuf->type, field, sizeof(struct videobuf_buffer), fh, - NULL); + &common->lock); /* Set io allowed member of file handle to TRUE */ fh->io_allowed[index] = 1; @@ -865,11 +860,7 @@ static int vpif_reqbufs(struct file *file, void *priv, INIT_LIST_HEAD(&common->dma_queue); /* Allocate buffers */ - ret = videobuf_reqbufs(&common->buffer_queue, reqbuf); - -reqbuf_exit: - mutex_unlock(&common->lock); - return ret; + return videobuf_reqbufs(&common->buffer_queue, reqbuf); } static int vpif_querybuf(struct file *file, void *priv, @@ -990,22 +981,19 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) } /* Call encoder subdevice function to set the standard */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - ch->video.stdid = *std_id; + ch->video.dv_preset = V4L2_DV_INVALID; + memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings)); + /* Get the information about the standard */ - if (vpif_get_std_info(ch)) { - vpif_err("Error getting the standard info\n"); + if (vpif_update_resolution(ch)) return -EINVAL; - } if ((ch->vpifparams.std_info.width * ch->vpifparams.std_info.height * 2) > config_params.channel_bufsize[ch->channel_id]) { vpif_err("invalid std for this size\n"); - ret = -EINVAL; - goto s_std_exit; + return -EINVAL; } common->fmt.fmt.pix.bytesperline = common->fmt.fmt.pix.width; @@ -1016,16 +1004,13 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) s_std_output, *std_id); if (ret < 0) { vpif_err("Failed to set output standard\n"); - goto s_std_exit; + return ret; } ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, core, s_std, *std_id); if (ret < 0) vpif_err("Failed to set standard for sub devices\n"); - -s_std_exit: - mutex_unlock(&common->lock); return ret; } @@ -1090,21 +1075,17 @@ static int vpif_streamon(struct file *file, void *priv, if (ret < 0) return ret; - /* Call videobuf_streamon to start streaming in videobuf */ + /* Call videobuf_streamon to start streaming in videobuf */ ret = videobuf_streamon(&common->buffer_queue); if (ret < 0) { vpif_err("videobuf_streamon\n"); return ret; } - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - /* If buffer queue is empty, return error */ if (list_empty(&common->dma_queue)) { vpif_err("buffer queue is empty\n"); - ret = -EIO; - goto streamon_exit; + return -EIO; } /* Get the next frame from the buffer queue */ @@ -1130,8 +1111,7 @@ static int vpif_streamon(struct file *file, void *priv, || (!ch->vpifparams.std_info.frm_fmt && (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { vpif_err("conflict in field format and std format\n"); - ret = -EINVAL; - goto streamon_exit; + return -EINVAL; } /* clock settings */ @@ -1140,13 +1120,13 @@ static int vpif_streamon(struct file *file, void *priv, ch->vpifparams.std_info.hd_sd); if (ret < 0) { vpif_err("can't set clock\n"); - goto streamon_exit; + return ret; } /* set the parameters and addresses */ ret = vpif_set_video_params(vpif, ch->channel_id + 2); if (ret < 0) - goto streamon_exit; + return ret; common->started = ret; vpif_config_addr(ch, ret); @@ -1171,9 +1151,6 @@ static int vpif_streamon(struct file *file, void *priv, } channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; } - -streamon_exit: - mutex_unlock(&common->lock); return ret; } @@ -1199,9 +1176,6 @@ static int vpif_streamoff(struct file *file, void *priv, return -EINVAL; } - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { /* disable channel */ if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { @@ -1216,8 +1190,6 @@ static int vpif_streamoff(struct file *file, void *priv, } common->started = 0; - mutex_unlock(&common->lock); - return videobuf_streamoff(&common->buffer_queue); } @@ -1264,13 +1236,9 @@ static int vpif_s_output(struct file *file, void *priv, unsigned int i) struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; int ret = 0; - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - if (common->started) { vpif_err("Streaming in progress\n"); - ret = -EBUSY; - goto s_output_exit; + return -EBUSY; } ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video, @@ -1280,9 +1248,6 @@ static int vpif_s_output(struct file *file, void *priv, unsigned int i) vpif_err("Failed to set output standard\n"); vid_ch->output_id = i; - -s_output_exit: - mutex_unlock(&common->lock); return ret; } @@ -1315,6 +1280,287 @@ static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p) return v4l2_prio_change(&ch->prio, &fh->prio, p); } +/** + * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler + * @file: file ptr + * @priv: file handle + * @preset: input preset + */ +static int vpif_enum_dv_presets(struct file *file, void *priv, + struct v4l2_dv_enum_preset *preset) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct video_obj *vid_ch = &ch->video; + + return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], + video, enum_dv_presets, preset); +} + +/** + * vpif_s_dv_presets() - S_DV_PRESETS handler + * @file: file ptr + * @priv: file handle + * @preset: input preset + */ +static int vpif_s_dv_preset(struct file *file, void *priv, + struct v4l2_dv_preset *preset) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; + struct video_obj *vid_ch = &ch->video; + int ret = 0; + + if (common->started) { + vpif_dbg(1, debug, "streaming in progress\n"); + return -EBUSY; + } + + ret = v4l2_prio_check(&ch->prio, fh->prio); + if (ret != 0) + return ret; + + fh->initialized = 1; + + /* Call encoder subdevice function to set the standard */ + if (mutex_lock_interruptible(&common->lock)) + return -ERESTARTSYS; + + ch->video.dv_preset = preset->preset; + ch->video.stdid = V4L2_STD_UNKNOWN; + memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings)); + + /* Get the information about the standard */ + if (vpif_update_resolution(ch)) { + ret = -EINVAL; + } else { + /* Configure the default format information */ + vpif_config_format(ch); + + ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], + video, s_dv_preset, preset); + } + + mutex_unlock(&common->lock); + + return ret; +} +/** + * vpif_g_dv_presets() - G_DV_PRESETS handler + * @file: file ptr + * @priv: file handle + * @preset: input preset + */ +static int vpif_g_dv_preset(struct file *file, void *priv, + struct v4l2_dv_preset *preset) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + + preset->preset = ch->video.dv_preset; + + return 0; +} +/** + * vpif_s_dv_timings() - S_DV_TIMINGS handler + * @file: file ptr + * @priv: file handle + * @timings: digital video timings + */ +static int vpif_s_dv_timings(struct file *file, void *priv, + struct v4l2_dv_timings *timings) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct vpif_params *vpifparams = &ch->vpifparams; + struct vpif_channel_config_params *std_info = &vpifparams->std_info; + struct video_obj *vid_ch = &ch->video; + struct v4l2_bt_timings *bt = &vid_ch->bt_timings; + int ret; + + if (timings->type != V4L2_DV_BT_656_1120) { + vpif_dbg(2, debug, "Timing type not defined\n"); + return -EINVAL; + } + + /* Configure subdevice timings, if any */ + ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], + video, s_dv_timings, timings); + if (ret == -ENOIOCTLCMD) { + vpif_dbg(2, debug, "Custom DV timings not supported by " + "subdevice\n"); + return -EINVAL; + } + if (ret < 0) { + vpif_dbg(2, debug, "Error setting custom DV timings\n"); + return ret; + } + + if (!(timings->bt.width && timings->bt.height && + (timings->bt.hbackporch || + timings->bt.hfrontporch || + timings->bt.hsync) && + timings->bt.vfrontporch && + (timings->bt.vbackporch || + timings->bt.vsync))) { + vpif_dbg(2, debug, "Timings for width, height, " + "horizontal back porch, horizontal sync, " + "horizontal front porch, vertical back porch, " + "vertical sync and vertical back porch " + "must be defined\n"); + return -EINVAL; + } + + *bt = timings->bt; + + /* Configure video port timings */ + + std_info->eav2sav = bt->hbackporch + bt->hfrontporch + + bt->hsync - 8; + std_info->sav2eav = bt->width; + + std_info->l1 = 1; + std_info->l3 = bt->vsync + bt->vbackporch + 1; + + if (bt->interlaced) { + if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) { + std_info->vsize = bt->height * 2 + + bt->vfrontporch + bt->vsync + bt->vbackporch + + bt->il_vfrontporch + bt->il_vsync + + bt->il_vbackporch; + std_info->l5 = std_info->vsize/2 - + (bt->vfrontporch - 1); + std_info->l7 = std_info->vsize/2 + 1; + std_info->l9 = std_info->l7 + bt->il_vsync + + bt->il_vbackporch + 1; + std_info->l11 = std_info->vsize - + (bt->il_vfrontporch - 1); + } else { + vpif_dbg(2, debug, "Required timing values for " + "interlaced BT format missing\n"); + return -EINVAL; + } + } else { + std_info->vsize = bt->height + bt->vfrontporch + + bt->vsync + bt->vbackporch; + std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); + } + strncpy(std_info->name, "Custom timings BT656/1120", + VPIF_MAX_NAME); + std_info->width = bt->width; + std_info->height = bt->height; + std_info->frm_fmt = bt->interlaced ? 0 : 1; + std_info->ycmux_mode = 0; + std_info->capture_format = 0; + std_info->vbi_supported = 0; + std_info->hd_sd = 1; + std_info->stdid = 0; + std_info->dv_preset = V4L2_DV_INVALID; + + vid_ch->stdid = 0; + vid_ch->dv_preset = V4L2_DV_INVALID; + + return 0; +} + +/** + * vpif_g_dv_timings() - G_DV_TIMINGS handler + * @file: file ptr + * @priv: file handle + * @timings: digital video timings + */ +static int vpif_g_dv_timings(struct file *file, void *priv, + struct v4l2_dv_timings *timings) +{ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct video_obj *vid_ch = &ch->video; + struct v4l2_bt_timings *bt = &vid_ch->bt_timings; + + timings->bt = *bt; + + return 0; +} + +/* + * vpif_g_chip_ident() - Identify the chip + * @file: file ptr + * @priv: file handle + * @chip: chip identity + * + * Returns zero or -EINVAL if read operations fails. + */ +static int vpif_g_chip_ident(struct file *file, void *priv, + struct v4l2_dbg_chip_ident *chip) +{ + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && + chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) { + vpif_dbg(2, debug, "match_type is invalid.\n"); + return -EINVAL; + } + + return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core, + g_chip_ident, chip); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +/* + * vpif_dbg_g_register() - Read register + * @file: file ptr + * @priv: file handle + * @reg: register to be read + * + * Debugging only + * Returns zero or -EINVAL if read operations fails. + */ +static int vpif_dbg_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg){ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct video_obj *vid_ch = &ch->video; + + return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core, + g_register, reg); +} + +/* + * vpif_dbg_s_register() - Write to register + * @file: file ptr + * @priv: file handle + * @reg: register to be modified + * + * Debugging only + * Returns zero or -EINVAL if write operations fails. + */ +static int vpif_dbg_s_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg){ + struct vpif_fh *fh = priv; + struct channel_obj *ch = fh->channel; + struct video_obj *vid_ch = &ch->video; + + return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core, + s_register, reg); +} +#endif + +/* + * vpif_log_status() - Status information + * @file: file ptr + * @priv: file handle + * + * Returns zero. + */ +static int vpif_log_status(struct file *filep, void *priv) +{ + /* status for sub devices */ + v4l2_device_call_all(&vpif_obj.v4l2_dev, 0, core, log_status); + + return 0; +} + /* vpif display ioctl operations */ static const struct v4l2_ioctl_ops vpif_ioctl_ops = { .vidioc_querycap = vpif_querycap, @@ -1336,13 +1582,24 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = { .vidioc_s_output = vpif_s_output, .vidioc_g_output = vpif_g_output, .vidioc_cropcap = vpif_cropcap, + .vidioc_enum_dv_presets = vpif_enum_dv_presets, + .vidioc_s_dv_preset = vpif_s_dv_preset, + .vidioc_g_dv_preset = vpif_g_dv_preset, + .vidioc_s_dv_timings = vpif_s_dv_timings, + .vidioc_g_dv_timings = vpif_g_dv_timings, + .vidioc_g_chip_ident = vpif_g_chip_ident, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vpif_dbg_g_register, + .vidioc_s_register = vpif_dbg_s_register, +#endif + .vidioc_log_status = vpif_log_status, }; static const struct v4l2_file_operations vpif_fops = { .owner = THIS_MODULE, .open = vpif_open, .release = vpif_release, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .mmap = vpif_mmap, .poll = vpif_poll }; @@ -1526,6 +1783,7 @@ static __init int vpif_probe(struct platform_device *pdev) v4l2_prio_init(&ch->prio); ch->common[VPIF_VIDEO_INDEX].fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + ch->video_dev->lock = &common->lock; /* register video device */ vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", @@ -1565,6 +1823,8 @@ static __init int vpif_probe(struct platform_device *pdev) vpif_obj.sd[i]->grp_id = 1 << i; } + v4l2_info(&vpif_obj.v4l2_dev, + "DM646x VPIF display driver initialized\n"); return 0; probe_subdev_out: diff --git a/drivers/media/video/davinci/vpif_display.h b/drivers/media/video/davinci/vpif_display.h index a2a7cd166bbf..b53aaa883075 100644 --- a/drivers/media/video/davinci/vpif_display.h +++ b/drivers/media/video/davinci/vpif_display.h @@ -67,6 +67,8 @@ struct video_obj { * most recent displayed frame only */ v4l2_std_id stdid; /* Currently selected or default * standard */ + u32 dv_preset; + struct v4l2_bt_timings bt_timings; u32 output_id; /* Current output id */ }; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 099d5df8c572..87f77a34eeab 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -33,6 +33,7 @@ #include <media/saa7115.h> #include <media/tvp5150.h> #include <media/tvaudio.h> +#include <media/mt9v011.h> #include <media/i2c-addr.h> #include <media/tveeprom.h> #include <media/v4l2-common.h> @@ -1917,11 +1918,6 @@ static unsigned short tvp5150_addrs[] = { I2C_CLIENT_END }; -static unsigned short mt9v011_addrs[] = { - 0xba >> 1, - I2C_CLIENT_END -}; - static unsigned short msp3400_addrs[] = { 0x80 >> 1, 0x88 >> 1, @@ -2437,6 +2433,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) dev->init_data.ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW; dev->init_data.get_key = em28xx_get_key_em_haup; dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; + break; case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE; dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; @@ -2623,11 +2620,17 @@ void em28xx_card_setup(struct em28xx *dev) "tvp5150", 0, tvp5150_addrs); if (dev->em28xx_sensor == EM28XX_MT9V011) { + struct mt9v011_platform_data pdata; + struct i2c_board_info mt9v011_info = { + .type = "mt9v011", + .addr = 0xba >> 1, + .platform_data = &pdata, + }; struct v4l2_subdev *sd; - sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, "mt9v011", 0, mt9v011_addrs); - v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal); + pdata.xtal = dev->sensor_xtal; + sd = v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap, + &mt9v011_info, NULL); } diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h index cc77d144df3c..bf66189cb26d 100644 --- a/drivers/media/video/et61x251/et61x251.h +++ b/drivers/media/video/et61x251/et61x251.h @@ -59,31 +59,7 @@ /*****************************************************************************/ static const struct usb_device_id et61x251_id_table[] = { - { USB_DEVICE(0x102c, 0x6151), }, { USB_DEVICE(0x102c, 0x6251), }, - { USB_DEVICE(0x102c, 0x6253), }, - { USB_DEVICE(0x102c, 0x6254), }, - { USB_DEVICE(0x102c, 0x6255), }, - { USB_DEVICE(0x102c, 0x6256), }, - { USB_DEVICE(0x102c, 0x6257), }, - { USB_DEVICE(0x102c, 0x6258), }, - { USB_DEVICE(0x102c, 0x6259), }, - { USB_DEVICE(0x102c, 0x625a), }, - { USB_DEVICE(0x102c, 0x625b), }, - { USB_DEVICE(0x102c, 0x625c), }, - { USB_DEVICE(0x102c, 0x625d), }, - { USB_DEVICE(0x102c, 0x625e), }, - { USB_DEVICE(0x102c, 0x625f), }, - { USB_DEVICE(0x102c, 0x6260), }, - { USB_DEVICE(0x102c, 0x6261), }, - { USB_DEVICE(0x102c, 0x6262), }, - { USB_DEVICE(0x102c, 0x6263), }, - { USB_DEVICE(0x102c, 0x6264), }, - { USB_DEVICE(0x102c, 0x6265), }, - { USB_DEVICE(0x102c, 0x6266), }, - { USB_DEVICE(0x102c, 0x6267), }, - { USB_DEVICE(0x102c, 0x6268), }, - { USB_DEVICE(0x102c, 0x6269), }, { } }; diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c index 629043933501..a09c4709d613 100644 --- a/drivers/media/video/gspca/benq.c +++ b/drivers/media/video/gspca/benq.c @@ -276,7 +276,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x04a5, 0x3035)}, {} }; diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 1eacb6c7926d..8b398493f96b 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -1040,14 +1040,14 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const struct usb_device_id device_table[] __devinitconst = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0572, 0x0041)}, {} }; MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ -static int __devinit sd_probe(struct usb_interface *intf, +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), diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c index c1ae05f4661f..4bf2cab98d64 100644 --- a/drivers/media/video/gspca/cpia1.c +++ b/drivers/media/video/gspca/cpia1.c @@ -2088,7 +2088,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0553, 0x0002)}, {USB_DEVICE(0x0813, 0x0001)}, {} diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index a594b36d6199..4b2c483fce6f 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -864,7 +864,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const struct usb_device_id device_table[] __devinitconst = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106}, #if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX}, @@ -875,7 +875,7 @@ static const struct usb_device_id device_table[] __devinitconst = { MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ -static int __devinit sd_probe(struct usb_interface *intf, +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), diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c index d78226455d1f..987b4b69d7ab 100644 --- a/drivers/media/video/gspca/finepix.c +++ b/drivers/media/video/gspca/finepix.c @@ -229,7 +229,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } /* Table of supported USB devices */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x04cb, 0x0104)}, {USB_DEVICE(0x04cb, 0x0109)}, {USB_DEVICE(0x04cb, 0x010b)}, diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index b05bec7321b5..99083038cec3 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c @@ -488,7 +488,7 @@ static void sd_callback(struct gspca_dev *gspca_dev) /*=================== USB driver structure initialisation ==================*/ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x05e3, 0x0503)}, {USB_DEVICE(0x05e3, 0xf191)}, {} diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 442970073e8a..f21f2a258ae0 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -55,7 +55,7 @@ MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); MODULE_DESCRIPTION("GSPCA USB Camera Driver"); MODULE_LICENSE("GPL"); -#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 11, 0) +#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 12, 0) #ifdef GSPCA_DEBUG int gspca_debug = D_ERR | D_PROBE; @@ -508,8 +508,8 @@ static int gspca_is_compressed(__u32 format) return 0; } -static int frame_alloc(struct gspca_dev *gspca_dev, - unsigned int count) +static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file, + enum v4l2_memory memory, unsigned int count) { struct gspca_frame *frame; unsigned int frsz; @@ -519,7 +519,6 @@ static int frame_alloc(struct gspca_dev *gspca_dev, frsz = gspca_dev->cam.cam_mode[i].sizeimage; PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz); frsz = PAGE_ALIGN(frsz); - gspca_dev->frsz = frsz; if (count >= GSPCA_MAX_FRAMES) count = GSPCA_MAX_FRAMES - 1; gspca_dev->frbuf = vmalloc_32(frsz * count); @@ -527,6 +526,9 @@ static int frame_alloc(struct gspca_dev *gspca_dev, err("frame alloc failed"); return -ENOMEM; } + gspca_dev->capt_file = file; + gspca_dev->memory = memory; + gspca_dev->frsz = frsz; gspca_dev->nframes = count; for (i = 0; i < count; i++) { frame = &gspca_dev->frame[i]; @@ -535,7 +537,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev, frame->v4l2_buf.flags = 0; frame->v4l2_buf.field = V4L2_FIELD_NONE; frame->v4l2_buf.length = frsz; - frame->v4l2_buf.memory = gspca_dev->memory; + frame->v4l2_buf.memory = memory; frame->v4l2_buf.sequence = 0; frame->data = gspca_dev->frbuf + i * frsz; frame->v4l2_buf.m.offset = i * frsz; @@ -558,6 +560,9 @@ static void frame_free(struct gspca_dev *gspca_dev) gspca_dev->frame[i].data = NULL; } gspca_dev->nframes = 0; + gspca_dev->frsz = 0; + gspca_dev->capt_file = NULL; + gspca_dev->memory = GSPCA_MEMORY_NO; } static void destroy_urbs(struct gspca_dev *gspca_dev) @@ -1210,29 +1215,15 @@ static void gspca_release(struct video_device *vfd) static int dev_open(struct file *file) { struct gspca_dev *gspca_dev; - int ret; PDEBUG(D_STREAM, "[%s] open", current->comm); gspca_dev = (struct gspca_dev *) video_devdata(file); - if (mutex_lock_interruptible(&gspca_dev->queue_lock)) - return -ERESTARTSYS; - if (!gspca_dev->present) { - ret = -ENODEV; - goto out; - } - - if (gspca_dev->users > 4) { /* (arbitrary value) */ - ret = -EBUSY; - goto out; - } + if (!gspca_dev->present) + return -ENODEV; /* protect the subdriver against rmmod */ - if (!try_module_get(gspca_dev->module)) { - ret = -ENODEV; - goto out; - } - - gspca_dev->users++; + if (!try_module_get(gspca_dev->module)) + return -ENODEV; file->private_data = gspca_dev; #ifdef GSPCA_DEBUG @@ -1244,14 +1235,7 @@ static int dev_open(struct file *file) gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG); #endif - ret = 0; -out: - mutex_unlock(&gspca_dev->queue_lock); - if (ret != 0) - PDEBUG(D_ERR|D_STREAM, "open failed err %d", ret); - else - PDEBUG(D_STREAM, "open done"); - return ret; + return 0; } static int dev_close(struct file *file) @@ -1261,7 +1245,6 @@ static int dev_close(struct file *file) PDEBUG(D_STREAM, "[%s] close", current->comm); if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return -ERESTARTSYS; - gspca_dev->users--; /* if the file did the capture, free the streaming resources */ if (gspca_dev->capt_file == file) { @@ -1272,8 +1255,6 @@ static int dev_close(struct file *file) mutex_unlock(&gspca_dev->usb_lock); } frame_free(gspca_dev); - gspca_dev->capt_file = NULL; - gspca_dev->memory = GSPCA_MEMORY_NO; } file->private_data = NULL; module_put(gspca_dev->module); @@ -1516,6 +1497,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, return -ERESTARTSYS; if (gspca_dev->memory != GSPCA_MEMORY_NO + && gspca_dev->memory != GSPCA_MEMORY_READ && gspca_dev->memory != rb->memory) { ret = -EBUSY; goto out; @@ -1544,19 +1526,18 @@ static int vidioc_reqbufs(struct file *file, void *priv, gspca_stream_off(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); } + /* Don't restart the stream when switching from read to mmap mode */ + if (gspca_dev->memory == GSPCA_MEMORY_READ) + streaming = 0; /* free the previous allocated buffers, if any */ - if (gspca_dev->nframes != 0) { + if (gspca_dev->nframes != 0) frame_free(gspca_dev); - gspca_dev->capt_file = NULL; - } if (rb->count == 0) /* unrequest */ goto out; - gspca_dev->memory = rb->memory; - ret = frame_alloc(gspca_dev, rb->count); + ret = frame_alloc(gspca_dev, file, rb->memory, rb->count); if (ret == 0) { rb->count = gspca_dev->nframes; - gspca_dev->capt_file = file; if (streaming) ret = gspca_init_transfer(gspca_dev); } @@ -1630,11 +1611,15 @@ static int vidioc_streamoff(struct file *file, void *priv, if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - if (!gspca_dev->streaming) - return 0; + if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return -ERESTARTSYS; + if (!gspca_dev->streaming) { + ret = 0; + goto out; + } + /* check the capture file */ if (gspca_dev->capt_file != file) { ret = -EBUSY; @@ -1649,6 +1634,8 @@ static int vidioc_streamoff(struct file *file, void *priv, gspca_dev->usb_err = 0; gspca_stream_off(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); + /* In case another thread is waiting in dqbuf */ + wake_up_interruptible(&gspca_dev->wq); /* empty the transfer queues */ atomic_set(&gspca_dev->fr_q, 0); @@ -1827,33 +1814,77 @@ out: return ret; } +static int frame_ready_nolock(struct gspca_dev *gspca_dev, struct file *file, + enum v4l2_memory memory) +{ + if (!gspca_dev->present) + return -ENODEV; + if (gspca_dev->capt_file != file || gspca_dev->memory != memory || + !gspca_dev->streaming) + return -EINVAL; + + /* check if a frame is ready */ + return gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i); +} + +static int frame_ready(struct gspca_dev *gspca_dev, struct file *file, + enum v4l2_memory memory) +{ + int ret; + + if (mutex_lock_interruptible(&gspca_dev->queue_lock)) + return -ERESTARTSYS; + ret = frame_ready_nolock(gspca_dev, file, memory); + mutex_unlock(&gspca_dev->queue_lock); + return ret; +} + /* - * wait for a video frame + * dequeue a video buffer * - * If a frame is ready, its index is returned. + * If nonblock_ing is false, block until a buffer is available. */ -static int frame_wait(struct gspca_dev *gspca_dev, - int nonblock_ing) +static int vidioc_dqbuf(struct file *file, void *priv, + struct v4l2_buffer *v4l2_buf) { - int i, ret; + struct gspca_dev *gspca_dev = priv; + struct gspca_frame *frame; + int i, j, ret; - /* check if a frame is ready */ - i = gspca_dev->fr_o; - if (i == atomic_read(&gspca_dev->fr_i)) { - if (nonblock_ing) + PDEBUG(D_FRAM, "dqbuf"); + + if (mutex_lock_interruptible(&gspca_dev->queue_lock)) + return -ERESTARTSYS; + + for (;;) { + ret = frame_ready_nolock(gspca_dev, file, v4l2_buf->memory); + if (ret < 0) + goto out; + if (ret > 0) + break; + + mutex_unlock(&gspca_dev->queue_lock); + + if (file->f_flags & O_NONBLOCK) return -EAGAIN; /* wait till a frame is ready */ ret = wait_event_interruptible_timeout(gspca_dev->wq, - i != atomic_read(&gspca_dev->fr_i) || - !gspca_dev->streaming || !gspca_dev->present, + frame_ready(gspca_dev, file, v4l2_buf->memory), msecs_to_jiffies(3000)); if (ret < 0) return ret; - if (ret == 0 || !gspca_dev->streaming || !gspca_dev->present) + if (ret == 0) return -EIO; + + if (mutex_lock_interruptible(&gspca_dev->queue_lock)) + return -ERESTARTSYS; } + i = gspca_dev->fr_o; + j = gspca_dev->fr_queue[i]; + frame = &gspca_dev->frame[j]; + gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES; if (gspca_dev->sd_desc->dq_callback) { @@ -1863,46 +1894,12 @@ static int frame_wait(struct gspca_dev *gspca_dev, gspca_dev->sd_desc->dq_callback(gspca_dev); mutex_unlock(&gspca_dev->usb_lock); } - return gspca_dev->fr_queue[i]; -} - -/* - * dequeue a video buffer - * - * If nonblock_ing is false, block until a buffer is available. - */ -static int vidioc_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *v4l2_buf) -{ - struct gspca_dev *gspca_dev = priv; - struct gspca_frame *frame; - int i, ret; - - PDEBUG(D_FRAM, "dqbuf"); - if (v4l2_buf->memory != gspca_dev->memory) - return -EINVAL; - - if (!gspca_dev->present) - return -ENODEV; - - /* if not streaming, be sure the application will not loop forever */ - if (!(file->f_flags & O_NONBLOCK) - && !gspca_dev->streaming && gspca_dev->users == 1) - return -EINVAL; - /* only the capturing file may dequeue */ - if (gspca_dev->capt_file != file) - return -EINVAL; - - /* only one dequeue / read at a time */ - if (mutex_lock_interruptible(&gspca_dev->read_lock)) - return -ERESTARTSYS; + frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; + memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); + PDEBUG(D_FRAM, "dqbuf %d", j); + ret = 0; - ret = frame_wait(gspca_dev, file->f_flags & O_NONBLOCK); - if (ret < 0) - goto out; - i = ret; /* frame index */ - frame = &gspca_dev->frame[i]; if (gspca_dev->memory == V4L2_MEMORY_USERPTR) { if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr, frame->data, @@ -1910,15 +1907,10 @@ static int vidioc_dqbuf(struct file *file, void *priv, PDEBUG(D_ERR|D_STREAM, "dqbuf cp to user failed"); ret = -EFAULT; - goto out; } } - frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; - memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); - PDEBUG(D_FRAM, "dqbuf %d", i); - ret = 0; out: - mutex_unlock(&gspca_dev->read_lock); + mutex_unlock(&gspca_dev->queue_lock); return ret; } @@ -2033,9 +2025,7 @@ static unsigned int dev_poll(struct file *file, poll_table *wait) poll_wait(file, &gspca_dev->wq, wait); /* if reqbufs is not done, the user would use read() */ - if (gspca_dev->nframes == 0) { - if (gspca_dev->memory != GSPCA_MEMORY_NO) - return POLLERR; /* not the 1st time */ + if (gspca_dev->memory == GSPCA_MEMORY_NO) { ret = read_alloc(gspca_dev, file); if (ret != 0) return POLLERR; @@ -2067,18 +2057,10 @@ static ssize_t dev_read(struct file *file, char __user *data, PDEBUG(D_FRAM, "read (%zd)", count); if (!gspca_dev->present) return -ENODEV; - switch (gspca_dev->memory) { - case GSPCA_MEMORY_NO: /* first time */ + if (gspca_dev->memory == GSPCA_MEMORY_NO) { /* first time ? */ ret = read_alloc(gspca_dev, file); if (ret != 0) return ret; - break; - case GSPCA_MEMORY_READ: - if (gspca_dev->capt_file == file) - break; - /* fall thru */ - default: - return -EINVAL; } /* get a frame */ @@ -2266,7 +2248,6 @@ int gspca_dev_probe2(struct usb_interface *intf, goto out; mutex_init(&gspca_dev->usb_lock); - mutex_init(&gspca_dev->read_lock); mutex_init(&gspca_dev->queue_lock); init_waitqueue_head(&gspca_dev->wq); @@ -2341,12 +2322,11 @@ void gspca_disconnect(struct usb_interface *intf) PDEBUG(D_PROBE, "%s disconnect", video_device_node_name(&gspca_dev->vdev)); mutex_lock(&gspca_dev->usb_lock); + gspca_dev->present = 0; + wake_up_interruptible(&gspca_dev->wq); - if (gspca_dev->streaming) { - destroy_urbs(gspca_dev); - wake_up_interruptible(&gspca_dev->wq); - } + destroy_urbs(gspca_dev); #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) gspca_input_destroy_urb(gspca_dev); diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 97b77a26a2eb..41755226d389 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -205,14 +205,12 @@ struct gspca_dev { wait_queue_head_t wq; /* wait queue */ struct mutex usb_lock; /* usb exchange protection */ - struct mutex read_lock; /* read protection */ struct mutex queue_lock; /* ISOC queue protection */ int usb_err; /* USB error - protected by usb_lock */ u16 pkt_size; /* ISOC packet size */ #ifdef CONFIG_PM char frozen; /* suspend - resume */ #endif - char users; /* number of opens */ char present; /* device connected */ char nbufread; /* number of buffers for read() */ char memory; /* memory type (V4L2_MEMORY_xxx) */ diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c index a35e87bb0388..06b777f5379e 100644 --- a/drivers/media/video/gspca/jeilinj.c +++ b/drivers/media/video/gspca/jeilinj.c @@ -314,7 +314,7 @@ static int sd_start(struct gspca_dev *gspca_dev) } /* Table of supported USB devices */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0979, 0x0280)}, {} }; diff --git a/drivers/media/video/gspca/jpeg.h b/drivers/media/video/gspca/jpeg.h index de63c36806c0..ab54910418b4 100644 --- a/drivers/media/video/gspca/jpeg.h +++ b/drivers/media/video/gspca/jpeg.h @@ -141,9 +141,9 @@ static void jpeg_define(u8 *jpeg_hdr, memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head); #ifndef CONEX_CAM jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8; - jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height & 0xff; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height; jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8; - jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width & 0xff; + jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width; jpeg_hdr[JPEG_HEIGHT_OFFSET + 6] = samplesY; #endif } diff --git a/drivers/media/video/gspca/konica.c b/drivers/media/video/gspca/konica.c index d2ce65dcbfdc..5964691c0e95 100644 --- a/drivers/media/video/gspca/konica.c +++ b/drivers/media/video/gspca/konica.c @@ -607,7 +607,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x04c8, 0x0720)}, /* Intel YC 76 */ {} }; diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index c872b93a3351..a7722b1aef9b 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c @@ -28,7 +28,7 @@ int force_sensor; static int dump_bridge; int dump_sensor; -static const __devinitdata struct usb_device_id m5602_table[] = { +static const struct usb_device_id m5602_table[] = { {USB_DEVICE(0x0402, 0x5602)}, {} }; diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index a81536e78698..cb4d0bf0d784 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -490,7 +490,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x050f)}, {} }; diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 7607a288b51c..3884c9d300c5 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c @@ -1229,7 +1229,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x08ca, 0x0110)}, /* Trust Spyc@m 100 */ {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */ {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */ diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index e1c3b9328ace..8ab2c452c25e 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -488,7 +488,6 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { #define R511_SNAP_PXDIV 0x1c #define R511_SNAP_LNDIV 0x1d #define R511_SNAP_UV_EN 0x1e -#define R511_SNAP_UV_EN 0x1e #define R511_SNAP_OPTS 0x1f #define R511_DRAM_FLOW_CTL 0x20 @@ -1847,8 +1846,7 @@ static const struct ov_i2c_regvals norm_7670[] = { { 0x6c, 0x0a }, { 0x6d, 0x55 }, { 0x6e, 0x11 }, - { 0x6f, 0x9f }, - /* "9e for advance AWB" */ + { 0x6f, 0x9f }, /* "9e for advance AWB" */ { 0x6a, 0x40 }, { OV7670_R01_BLUE, 0x40 }, { OV7670_R02_RED, 0x60 }, @@ -3054,7 +3052,7 @@ static void ov519_configure(struct sd *sd) { static const struct ov_regvals init_519[] = { { 0x5a, 0x6d }, /* EnableSystem */ - { 0x53, 0x9b }, + { 0x53, 0x9b }, /* don't enable the microcontroller */ { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */ { 0x5d, 0x03 }, { 0x49, 0x01 }, @@ -4747,7 +4745,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF }, {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 }, {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 0edf93973b1c..04da22802736 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -479,15 +479,20 @@ static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) struct usb_device *udev = gspca_dev->dev; int ret; - PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val); + if (gspca_dev->usb_err < 0) + return; + + PDEBUG(D_USBO, "SET 01 0000 %04x %02x", reg, val); gspca_dev->usb_buf[0] = val; ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); - if (ret < 0) + if (ret < 0) { err("write failed %d", ret); + gspca_dev->usb_err = ret; + } } static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg) @@ -495,14 +500,18 @@ static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg) struct usb_device *udev = gspca_dev->dev; int ret; + if (gspca_dev->usb_err < 0) + return 0; ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x01, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); - PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, gspca_dev->usb_buf[0]); - if (ret < 0) + PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]); + if (ret < 0) { err("read failed %d", ret); + gspca_dev->usb_err = ret; + } return gspca_dev->usb_buf[0]; } @@ -558,13 +567,15 @@ static int sccb_check_status(struct gspca_dev *gspca_dev) static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val) { - PDEBUG(D_USBO, "reg: 0x%02x, val: 0x%02x", reg, val); + PDEBUG(D_USBO, "sccb write: %02x %02x", reg, val); ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg); ov534_reg_write(gspca_dev, OV534_REG_WRITE, val); ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3); - if (!sccb_check_status(gspca_dev)) + if (!sccb_check_status(gspca_dev)) { err("sccb_reg_write failed"); + gspca_dev->usb_err = -EIO; + } } static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg) @@ -885,7 +896,7 @@ static int sd_init(struct gspca_dev *gspca_dev) ov534_set_led(gspca_dev, 0); set_frame_rate(gspca_dev); - return 0; + return gspca_dev->usb_err; } static int sd_start(struct gspca_dev *gspca_dev) @@ -920,7 +931,7 @@ static int sd_start(struct gspca_dev *gspca_dev) ov534_set_led(gspca_dev, 1); ov534_reg_write(gspca_dev, 0xe0, 0x00); - return 0; + return gspca_dev->usb_err; } static void sd_stopN(struct gspca_dev *gspca_dev) @@ -1289,7 +1300,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x1415, 0x2000)}, {} }; diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c index c5244b4b4777..aaf5428c57f5 100644 --- a/drivers/media/video/gspca/ov534_9.c +++ b/drivers/media/video/gspca/ov534_9.c @@ -1429,7 +1429,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x06f8, 0x3003)}, {} }; diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 96f9986305b4..81739a2f205e 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -530,7 +530,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4028)}, {USB_DEVICE(0x093a, 0x2460)}, {USB_DEVICE(0x093a, 0x2461)}, diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 2700975abce5..5615d7bd8304 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -1184,7 +1184,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const struct usb_device_id device_table[] __devinitconst = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x06f8, 0x3009)}, {USB_DEVICE(0x093a, 0x2620)}, {USB_DEVICE(0x093a, 0x2621)}, @@ -1201,7 +1201,7 @@ static const struct usb_device_id device_table[] __devinitconst = { MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ -static int __devinit sd_probe(struct usb_interface *intf, +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), diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 6820f5d58b19..f8801b50e64f 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -837,7 +837,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const struct usb_device_id device_table[] __devinitconst = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x2600)}, {USB_DEVICE(0x093a, 0x2601)}, {USB_DEVICE(0x093a, 0x2603)}, @@ -849,7 +849,7 @@ static const struct usb_device_id device_table[] __devinitconst = { MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ -static int __devinit sd_probe(struct usb_interface *intf, +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), diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c index 40a06680502d..4271f86dfe01 100644 --- a/drivers/media/video/gspca/sn9c2028.c +++ b/drivers/media/video/gspca/sn9c2028.c @@ -703,7 +703,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */ /* The Genius Smart is untested. I can't find an owner ! */ /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */ diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index cb08d00d0a31..fcf29897b713 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -2470,7 +2470,7 @@ static const struct sd_desc sd_desc = { | (SENSOR_ ## sensor << 8) \ | (i2c_addr) -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)}, {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)}, diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 73504a3f87b7..c6cd68d66b53 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -23,8 +23,15 @@ /* Some documentation on known sonixb registers: Reg Use +sn9c101 / sn9c102: 0x10 high nibble red gain low nibble blue gain 0x11 low nibble green gain +sn9c103: +0x05 red gain 0-127 +0x06 blue gain 0-127 +0x07 green gain 0-127 +all: +0x08-0x0f i2c / 3wire registers 0x12 hstart 0x13 vstart 0x15 hsize (hsize = register-value * 16) @@ -88,12 +95,9 @@ struct sd { typedef const __u8 sensor_init_t[8]; struct sensor_data { - const __u8 *bridge_init[2]; - int bridge_init_size[2]; + const __u8 *bridge_init; sensor_init_t *sensor_init; int sensor_init_size; - sensor_init_t *sensor_bridge_init[2]; - int sensor_bridge_init_size[2]; int flags; unsigned ctrl_dis; __u8 sensor_addr; @@ -114,7 +118,6 @@ struct sensor_data { #define NO_FREQ (1 << FREQ_IDX) #define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) -#define COMP2 0x8f #define COMP 0xc7 /* 0x87 //0x07 */ #define COMP1 0xc9 /* 0x89 //0x09 */ @@ -123,15 +126,11 @@ struct sensor_data { #define SYS_CLK 0x04 -#define SENS(bridge_1, bridge_3, sensor, sensor_1, \ - sensor_3, _flags, _ctrl_dis, _sensor_addr) \ +#define SENS(bridge, sensor, _flags, _ctrl_dis, _sensor_addr) \ { \ - .bridge_init = { bridge_1, bridge_3 }, \ - .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \ + .bridge_init = bridge, \ .sensor_init = sensor, \ .sensor_init_size = sizeof(sensor), \ - .sensor_bridge_init = { sensor_1, sensor_3,}, \ - .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \ .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \ } @@ -311,7 +310,6 @@ static const __u8 initHv7131d[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x28, 0x1e, 0x60, 0x8e, 0x42, - 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c }; static const __u8 hv7131d_sensor_init[][8] = { {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17}, @@ -326,7 +324,6 @@ static const __u8 initHv7131r[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x28, 0x1e, 0x60, 0x8a, 0x20, - 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c }; static const __u8 hv7131r_sensor_init[][8] = { {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10}, @@ -339,7 +336,7 @@ static const __u8 initOv6650[] = { 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b, - 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07 + 0x10, }; static const __u8 ov6650_sensor_init[][8] = { /* Bright, contrast, etc are set through SCBB interface. @@ -378,24 +375,13 @@ static const __u8 initOv7630[] = { 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */ 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */ 0x28, 0x1e, /* H & V sizes r15 .. r16 */ - 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */ - 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */ -}; -static const __u8 initOv7630_3[] = { - 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */ - 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */ - 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ - 0x28, 0x1e, /* H & V sizes r15 .. r16 */ 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ - 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */ - 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */ - 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */ }; static const __u8 ov7630_sensor_init[][8] = { {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10}, /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */ - {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */ + {0xd0, 0x21, 0x12, 0x5c, 0x00, 0x80, 0x34, 0x10}, /* jfm */ {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10}, {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10}, {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10}, @@ -413,16 +399,11 @@ static const __u8 ov7630_sensor_init[][8] = { {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10}, }; -static const __u8 ov7630_sensor_init_3[][8] = { - {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10}, -}; - static const __u8 initPas106[] = { 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x16, 0x12, 0x24, COMP1, MCK_INIT1, - 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 }; /* compression 0x86 mckinit1 0x2b */ @@ -496,7 +477,6 @@ static const __u8 initPas202[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a, 0x28, 0x1e, 0x20, 0x89, 0x20, - 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c }; /* "Known" PAS202BCB registers: @@ -537,7 +517,6 @@ static const __u8 initTas5110c[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a, 0x16, 0x12, 0x60, 0x86, 0x2b, - 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 }; /* Same as above, except a different hstart */ static const __u8 initTas5110d[] = { @@ -545,12 +524,19 @@ static const __u8 initTas5110d[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a, 0x16, 0x12, 0x60, 0x86, 0x2b, - 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 }; -static const __u8 tas5110_sensor_init[][8] = { +/* tas5110c is 3 wire, tas5110d is 2 wire (regular i2c) */ +static const __u8 tas5110c_sensor_init[][8] = { {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10}, {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10}, - {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17}, +}; +/* Known TAS5110D registers + * reg02: gain, bit order reversed!! 0 == max gain, 255 == min gain + * reg03: bit3: vflip, bit4: ~hflip, bit7: ~gainboost (~ == inverted) + * Note: writing reg03 seems to only work when written together with 02 + */ +static const __u8 tas5110d_sensor_init[][8] = { + {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17}, /* reset */ }; static const __u8 initTas5130[] = { @@ -558,7 +544,6 @@ static const __u8 initTas5130[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a, 0x28, 0x1e, 0x60, COMP, MCK_INIT, - 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c }; static const __u8 tas5130_sensor_init[][8] = { /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10}, @@ -569,21 +554,18 @@ static const __u8 tas5130_sensor_init[][8] = { }; static struct sensor_data sensor_data[] = { -SENS(initHv7131d, NULL, hv7131d_sensor_init, NULL, NULL, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0), -SENS(initHv7131r, NULL, hv7131r_sensor_init, NULL, NULL, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0), -SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), -SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, - F_GAIN, 0, 0x21), -SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_FREQ, - 0), -SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN, - NO_FREQ, 0), -SENS(initTas5110c, NULL, tas5110_sensor_init, NULL, NULL, - F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0), -SENS(initTas5110d, NULL, tas5110_sensor_init, NULL, NULL, - F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0), -SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, - 0), +SENS(initHv7131d, hv7131d_sensor_init, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0), +SENS(initHv7131r, hv7131r_sensor_init, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0), +SENS(initOv6650, ov6650_sensor_init, F_GAIN|F_SIF, 0, 0x60), +SENS(initOv7630, ov7630_sensor_init, F_GAIN, 0, 0x21), +SENS(initPas106, pas106_sensor_init, F_GAIN|F_SIF, NO_FREQ, 0), +SENS(initPas202, pas202_sensor_init, F_GAIN, NO_FREQ, 0), +SENS(initTas5110c, tas5110c_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO, + NO_BRIGHTNESS|NO_FREQ, 0), +SENS(initTas5110d, tas5110d_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO, + NO_BRIGHTNESS|NO_FREQ, 0), +SENS(initTas5130, tas5130_sensor_init, F_GAIN, + NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0), }; /* get one byte in gspca_dev->usb_buf */ @@ -655,7 +637,6 @@ static void i2c_w_vector(struct gspca_dev *gspca_dev, static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 value; switch (sd->sensor) { case SENSOR_OV6650: @@ -697,17 +678,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) goto err; break; } - case SENSOR_TAS5130CXX: { - __u8 i2c[] = - {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}; - - value = 0xff - sd->brightness; - i2c[4] = value; - PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]); - if (i2c_w(gspca_dev, i2c) < 0) - goto err; - break; - } } return; err: @@ -733,7 +703,7 @@ static void setsensorgain(struct gspca_dev *gspca_dev) break; } case SENSOR_TAS5110C: - case SENSOR_TAS5110D: { + case SENSOR_TAS5130CXX: { __u8 i2c[] = {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}; @@ -742,6 +712,23 @@ static void setsensorgain(struct gspca_dev *gspca_dev) goto err; break; } + case SENSOR_TAS5110D: { + __u8 i2c[] = { + 0xb0, 0x61, 0x02, 0x00, 0x10, 0x00, 0x00, 0x17 }; + gain = 255 - gain; + /* The bits in the register are the wrong way around!! */ + i2c[3] |= (gain & 0x80) >> 7; + i2c[3] |= (gain & 0x40) >> 5; + i2c[3] |= (gain & 0x20) >> 3; + i2c[3] |= (gain & 0x10) >> 1; + i2c[3] |= (gain & 0x08) << 1; + i2c[3] |= (gain & 0x04) << 3; + i2c[3] |= (gain & 0x02) << 5; + i2c[3] |= (gain & 0x01) << 7; + if (i2c_w(gspca_dev, i2c) < 0) + goto err; + break; + } case SENSOR_OV6650: gain >>= 1; @@ -796,7 +783,7 @@ static void setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u8 gain; - __u8 buf[2] = { 0, 0 }; + __u8 buf[3] = { 0, 0, 0 }; if (sensor_data[sd->sensor].flags & F_GAIN) { /* Use the sensor gain to do the actual gain */ @@ -804,13 +791,18 @@ static void setgain(struct gspca_dev *gspca_dev) return; } - gain = sd->gain >> 4; - - /* red and blue gain */ - buf[0] = gain << 4 | gain; - /* green gain */ - buf[1] = gain; - reg_w(gspca_dev, 0x10, buf, 2); + if (sd->bridge == BRIDGE_103) { + gain = sd->gain >> 1; + buf[0] = gain; /* Red */ + buf[1] = gain; /* Green */ + buf[2] = gain; /* Blue */ + reg_w(gspca_dev, 0x05, buf, 3); + } else { + gain = sd->gain >> 4; + buf[0] = gain << 4 | gain; /* Red and blue */ + buf[1] = gain; /* Green */ + reg_w(gspca_dev, 0x10, buf, 2); + } } static void setexposure(struct gspca_dev *gspca_dev) @@ -1049,7 +1041,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) desired_avg_lum = 5000; } else { deadzone = 1500; - desired_avg_lum = 18000; + desired_avg_lum = 13000; } if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) @@ -1127,53 +1119,91 @@ static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam = &gspca_dev->cam; - int mode, l; - const __u8 *sn9c10x; - __u8 reg12_19[8]; + int i, mode; + __u8 regs[0x31]; mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07; - sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge]; - l = sensor_data[sd->sensor].bridge_init_size[sd->bridge]; - memcpy(reg12_19, &sn9c10x[0x12 - 1], 8); - reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4); - /* Special cases where reg 17 and or 19 value depends on mode */ + /* Copy registers 0x01 - 0x19 from the template */ + memcpy(®s[0x01], sensor_data[sd->sensor].bridge_init, 0x19); + /* Set the mode */ + regs[0x18] |= mode << 4; + + /* Set bridge gain to 1.0 */ + if (sd->bridge == BRIDGE_103) { + regs[0x05] = 0x20; /* Red */ + regs[0x06] = 0x20; /* Green */ + regs[0x07] = 0x20; /* Blue */ + } else { + regs[0x10] = 0x00; /* Red and blue */ + regs[0x11] = 0x00; /* Green */ + } + + /* Setup pixel numbers and auto exposure window */ + if (sensor_data[sd->sensor].flags & F_SIF) { + regs[0x1a] = 0x14; /* HO_SIZE 640, makes no sense */ + regs[0x1b] = 0x0a; /* VO_SIZE 320, makes no sense */ + regs[0x1c] = 0x02; /* AE H-start 64 */ + regs[0x1d] = 0x02; /* AE V-start 64 */ + regs[0x1e] = 0x09; /* AE H-end 288 */ + regs[0x1f] = 0x07; /* AE V-end 224 */ + } else { + regs[0x1a] = 0x1d; /* HO_SIZE 960, makes no sense */ + regs[0x1b] = 0x10; /* VO_SIZE 512, makes no sense */ + regs[0x1c] = 0x05; /* AE H-start 160 */ + regs[0x1d] = 0x03; /* AE V-start 96 */ + regs[0x1e] = 0x0f; /* AE H-end 480 */ + regs[0x1f] = 0x0c; /* AE V-end 384 */ + } + + /* Setup the gamma table (only used with the sn9c103 bridge) */ + for (i = 0; i < 16; i++) + regs[0x20 + i] = i * 16; + regs[0x20 + i] = 255; + + /* Special cases where some regs depend on mode or bridge */ switch (sd->sensor) { case SENSOR_TAS5130CXX: - /* probably not mode specific at all most likely the upper + /* FIXME / TESTME + probably not mode specific at all most likely the upper nibble of 0x19 is exposure (clock divider) just as with the tas5110, we need someone to test this. */ - reg12_19[7] = mode ? 0x23 : 0x43; + regs[0x19] = mode ? 0x23 : 0x43; break; + case SENSOR_OV7630: + /* FIXME / TESTME for some reason with the 101/102 bridge the + clock is set to 12 Mhz (reg1 == 0x04), rather then 24. + Also the hstart needs to go from 1 to 2 when using a 103, + which is likely related. This does not seem right. */ + if (sd->bridge == BRIDGE_103) { + regs[0x01] = 0x44; /* Select 24 Mhz clock */ + regs[0x12] = 0x02; /* Set hstart to 2 */ + } } /* Disable compression when the raw bayer format has been selected */ if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) - reg12_19[6] &= ~0x80; + regs[0x18] &= ~0x80; /* Vga mode emulation on SIF sensor? */ if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) { - reg12_19[0] += 16; /* 0x12: hstart adjust */ - reg12_19[1] += 24; /* 0x13: vstart adjust */ - reg12_19[3] = 320 / 16; /* 0x15: hsize */ - reg12_19[4] = 240 / 16; /* 0x16: vsize */ + regs[0x12] += 16; /* hstart adjust */ + regs[0x13] += 24; /* vstart adjust */ + regs[0x15] = 320 / 16; /* hsize */ + regs[0x16] = 240 / 16; /* vsize */ } /* reg 0x01 bit 2 video transfert on */ - reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1); + reg_w(gspca_dev, 0x01, ®s[0x01], 1); /* reg 0x17 SensorClk enable inv Clk 0x60 */ - reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1); + reg_w(gspca_dev, 0x17, ®s[0x17], 1); /* Set the registers from the template */ - reg_w(gspca_dev, 0x01, sn9c10x, l); + reg_w(gspca_dev, 0x01, ®s[0x01], + (sd->bridge == BRIDGE_103) ? 0x30 : 0x1f); /* Init the sensor */ i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init, sensor_data[sd->sensor].sensor_init_size); - if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge]) - i2c_w_vector(gspca_dev, - sensor_data[sd->sensor].sensor_bridge_init[sd->bridge], - sensor_data[sd->sensor].sensor_bridge_init_size[ - sd->bridge]); - /* Mode specific sensor setup */ + /* Mode / bridge specific sensor setup */ switch (sd->sensor) { case SENSOR_PAS202: { const __u8 i2cpclockdiv[] = @@ -1181,27 +1211,37 @@ static int sd_start(struct gspca_dev *gspca_dev) /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */ if (mode) i2c_w(gspca_dev, i2cpclockdiv); + break; } + case SENSOR_OV7630: + /* FIXME / TESTME We should be able to handle this identical + for the 101/102 and the 103 case */ + if (sd->bridge == BRIDGE_103) { + const __u8 i2c[] = { 0xa0, 0x21, 0x13, + 0x80, 0x00, 0x00, 0x00, 0x10 }; + i2c_w(gspca_dev, i2c); + } + break; } /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ - reg_w(gspca_dev, 0x15, ®12_19[3], 2); + reg_w(gspca_dev, 0x15, ®s[0x15], 2); /* compression register */ - reg_w(gspca_dev, 0x18, ®12_19[6], 1); + reg_w(gspca_dev, 0x18, ®s[0x18], 1); /* H_start */ - reg_w(gspca_dev, 0x12, ®12_19[0], 1); + reg_w(gspca_dev, 0x12, ®s[0x12], 1); /* V_START */ - reg_w(gspca_dev, 0x13, ®12_19[1], 1); + reg_w(gspca_dev, 0x13, ®s[0x13], 1); /* reset 0x17 SensorClk enable inv Clk 0x60 */ /*fixme: ov7630 [17]=68 8f (+20 if 102)*/ - reg_w(gspca_dev, 0x17, ®12_19[5], 1); + reg_w(gspca_dev, 0x17, ®s[0x17], 1); /*MCKSIZE ->3 */ /*fixme: not ov7630*/ - reg_w(gspca_dev, 0x19, ®12_19[7], 1); + reg_w(gspca_dev, 0x19, ®s[0x19], 1); /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ - reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4); + reg_w(gspca_dev, 0x1c, ®s[0x1c], 4); /* Enable video transfert */ - reg_w(gspca_dev, 0x01, &sn9c10x[0], 1); + reg_w(gspca_dev, 0x01, ®s[0x01], 1); /* Compression */ - reg_w(gspca_dev, 0x18, ®12_19[6], 2); + reg_w(gspca_dev, 0x18, ®s[0x18], 2); msleep(20); sd->reg11 = -1; @@ -1525,15 +1565,15 @@ static const struct sd_desc sd_desc = { .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge -static const struct usb_device_id device_table[] __devinitconst = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */ {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */ {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */ {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, +#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, #endif @@ -1544,18 +1584,22 @@ static const struct usb_device_id device_table[] __devinitconst = { {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, - /* {USB_DEVICE(0x0c45, 0x602b), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */ + /* {USB_DEVICE(0x0c45, 0x6030), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */ + /* {USB_DEVICE(0x0c45, 0x6082), SB(MI03XX, 103)}, */ /* MI0343 MI0360 */ + {USB_DEVICE(0x0c45, 0x6083), SB(HV7131D, 103)}, + {USB_DEVICE(0x0c45, 0x608c), SB(HV7131R, 103)}, + /* {USB_DEVICE(0x0c45, 0x608e), SB(CISVF10, 103)}, */ {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE + {USB_DEVICE(0x0c45, 0x60a8), SB(PAS106, 103)}, + {USB_DEVICE(0x0c45, 0x60aa), SB(TAS5130CXX, 103)}, {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, -#endif {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)}, {} }; MODULE_DEVICE_TABLE(usb, device_table); /* -- device connect -- */ -static int __devinit sd_probe(struct usb_interface *intf, +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), diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 2d0bb17a30a2..d6f39ce1b7e1 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -25,12 +25,12 @@ #include "gspca.h" #include "jpeg.h" -#define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0) - MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver"); MODULE_LICENSE("GPL"); +static int starcam; + /* controls */ enum e_ctrl { BRIGHTNESS, @@ -43,7 +43,7 @@ enum e_ctrl { HFLIP, VFLIP, SHARPNESS, - INFRARED, + ILLUM, FREQ, NCTRLS /* number of controls */ }; @@ -100,7 +100,8 @@ enum sensors { }; /* device flags */ -#define PDN_INV 1 /* inverse pin S_PWR_DN / sn_xxx tables */ +#define F_PDN_INV 0x01 /* inverse pin S_PWR_DN / sn_xxx tables */ +#define F_ILLUM 0x02 /* presence of illuminator */ /* sn9c1xx definitions */ /* register 0x01 */ @@ -124,7 +125,7 @@ static void setgamma(struct gspca_dev *gspca_dev); static void setautogain(struct gspca_dev *gspca_dev); static void sethvflip(struct gspca_dev *gspca_dev); static void setsharpness(struct gspca_dev *gspca_dev); -static void setinfrared(struct gspca_dev *gspca_dev); +static void setillum(struct gspca_dev *gspca_dev); static void setfreq(struct gspca_dev *gspca_dev); static const struct ctrl sd_ctrls[NCTRLS] = { @@ -251,18 +252,17 @@ static const struct ctrl sd_ctrls[NCTRLS] = { }, .set_control = setsharpness }, -/* mt9v111 only */ -[INFRARED] = { +[ILLUM] = { { - .id = V4L2_CID_INFRARED, + .id = V4L2_CID_ILLUMINATORS_1, .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Infrared", + .name = "Illuminator / infrared", .minimum = 0, .maximum = 1, .step = 1, .default_value = 0, }, - .set_control = setinfrared + .set_control = setillum }, /* ov7630/ov7648/ov7660 only */ [FREQ] = { @@ -282,32 +282,26 @@ static const struct ctrl sd_ctrls[NCTRLS] = { /* table of the disabled controls */ static const __u32 ctrl_dis[] = { [SENSOR_ADCM1700] = (1 << AUTOGAIN) | - (1 << INFRARED) | (1 << HFLIP) | (1 << VFLIP) | (1 << FREQ), -[SENSOR_GC0307] = (1 << INFRARED) | - (1 << HFLIP) | +[SENSOR_GC0307] = (1 << HFLIP) | (1 << VFLIP) | (1 << FREQ), -[SENSOR_HV7131R] = (1 << INFRARED) | - (1 << HFLIP) | +[SENSOR_HV7131R] = (1 << HFLIP) | (1 << FREQ), -[SENSOR_MI0360] = (1 << INFRARED) | - (1 << HFLIP) | +[SENSOR_MI0360] = (1 << HFLIP) | (1 << VFLIP) | (1 << FREQ), -[SENSOR_MI0360B] = (1 << INFRARED) | - (1 << HFLIP) | +[SENSOR_MI0360B] = (1 << HFLIP) | (1 << VFLIP) | (1 << FREQ), -[SENSOR_MO4000] = (1 << INFRARED) | - (1 << HFLIP) | +[SENSOR_MO4000] = (1 << HFLIP) | (1 << VFLIP) | (1 << FREQ), @@ -315,40 +309,32 @@ static const __u32 ctrl_dis[] = { (1 << VFLIP) | (1 << FREQ), -[SENSOR_OM6802] = (1 << INFRARED) | - (1 << HFLIP) | +[SENSOR_OM6802] = (1 << HFLIP) | (1 << VFLIP) | (1 << FREQ), -[SENSOR_OV7630] = (1 << INFRARED) | - (1 << HFLIP), +[SENSOR_OV7630] = (1 << HFLIP), -[SENSOR_OV7648] = (1 << INFRARED) | - (1 << HFLIP), +[SENSOR_OV7648] = (1 << HFLIP), [SENSOR_OV7660] = (1 << AUTOGAIN) | - (1 << INFRARED) | (1 << HFLIP) | (1 << VFLIP), [SENSOR_PO1030] = (1 << AUTOGAIN) | - (1 << INFRARED) | (1 << HFLIP) | (1 << VFLIP) | (1 << FREQ), [SENSOR_PO2030N] = (1 << AUTOGAIN) | - (1 << INFRARED) | (1 << FREQ), [SENSOR_SOI768] = (1 << AUTOGAIN) | - (1 << INFRARED) | (1 << HFLIP) | (1 << VFLIP) | (1 << FREQ), [SENSOR_SP80708] = (1 << AUTOGAIN) | - (1 << INFRARED) | (1 << HFLIP) | (1 << VFLIP) | (1 << FREQ), @@ -1822,44 +1808,46 @@ static int sd_init(struct gspca_dev *gspca_dev) PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1); switch (sd->bridge) { case BRIDGE_SN9C102P: + case BRIDGE_SN9C105: if (regF1 != 0x11) return -ENODEV; + break; + default: +/* case BRIDGE_SN9C110: */ +/* case BRIDGE_SN9C120: */ + if (regF1 != 0x12) + return -ENODEV; + } + + switch (sd->sensor) { + case SENSOR_MI0360: + mi0360_probe(gspca_dev); + break; + case SENSOR_OV7630: + ov7630_probe(gspca_dev); + break; + case SENSOR_OV7648: + ov7648_probe(gspca_dev); + break; + case SENSOR_PO2030N: + po2030n_probe(gspca_dev); + break; + } + + switch (sd->bridge) { + case BRIDGE_SN9C102P: reg_w1(gspca_dev, 0x02, regGpio[1]); break; case BRIDGE_SN9C105: - if (regF1 != 0x11) - return -ENODEV; - if (sd->sensor == SENSOR_MI0360) - mi0360_probe(gspca_dev); reg_w(gspca_dev, 0x01, regGpio, 2); break; + case BRIDGE_SN9C110: + reg_w1(gspca_dev, 0x02, 0x62); + break; case BRIDGE_SN9C120: - if (regF1 != 0x12) - return -ENODEV; - switch (sd->sensor) { - case SENSOR_MI0360: - mi0360_probe(gspca_dev); - break; - case SENSOR_OV7630: - ov7630_probe(gspca_dev); - break; - case SENSOR_OV7648: - ov7648_probe(gspca_dev); - break; - case SENSOR_PO2030N: - po2030n_probe(gspca_dev); - break; - } regGpio[1] = 0x70; /* no audio */ reg_w(gspca_dev, 0x01, regGpio, 2); break; - default: -/* case BRIDGE_SN9C110: */ -/* case BRIDGE_SN9C325: */ - if (regF1 != 0x12) - return -ENODEV; - reg_w1(gspca_dev, 0x02, 0x62); - break; } if (sd->sensor == SENSOR_OM6802) @@ -1874,6 +1862,8 @@ static int sd_init(struct gspca_dev *gspca_dev) sd->i2c_addr = sn9c1xx[9]; gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; + if (!(sd->flags & F_ILLUM)) + gspca_dev->ctrl_dis |= (1 << ILLUM); return gspca_dev->usb_err; } @@ -2197,16 +2187,28 @@ static void setsharpness(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x99, sd->ctrls[SHARPNESS].val); } -static void setinfrared(struct gspca_dev *gspca_dev) +static void setillum(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (gspca_dev->ctrl_dis & (1 << INFRARED)) + if (gspca_dev->ctrl_dis & (1 << ILLUM)) return; -/*fixme: different sequence for StarCam Clip and StarCam 370i */ -/* Clip */ - i2c_w1(gspca_dev, 0x02, /* gpio */ - sd->ctrls[INFRARED].val ? 0x66 : 0x64); + switch (sd->sensor) { + case SENSOR_ADCM1700: + reg_w1(gspca_dev, 0x02, /* gpio */ + sd->ctrls[ILLUM].val ? 0x64 : 0x60); + break; + case SENSOR_MT9V111: + if (starcam) + reg_w1(gspca_dev, 0x02, + sd->ctrls[ILLUM].val ? + 0x55 : 0x54); /* 370i */ + else + reg_w1(gspca_dev, 0x02, + sd->ctrls[ILLUM].val ? + 0x66 : 0x64); /* Clip */ + break; + } } static void setfreq(struct gspca_dev *gspca_dev) @@ -2344,7 +2346,7 @@ static int sd_start(struct gspca_dev *gspca_dev) /* sensor clock already enabled in sd_init */ /* reg_w1(gspca_dev, 0xf1, 0x00); */ reg01 = sn9c1xx[1]; - if (sd->flags & PDN_INV) + if (sd->flags & F_PDN_INV) reg01 ^= S_PDN_INV; /* power down inverted */ reg_w1(gspca_dev, 0x01, reg01); @@ -2907,13 +2909,11 @@ static const struct sd_desc sd_desc = { .driver_info = (BRIDGE_ ## bridge << 16) \ | (SENSOR_ ## sensor << 8) \ | (flags) -static const __devinitdata struct usb_device_id device_table[] = { -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)}, {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)}, -#endif - {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)}, - {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)}, + {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, F_PDN_INV)}, + {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, F_PDN_INV)}, {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)}, {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)}, {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)}, @@ -2925,7 +2925,7 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */ {USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)}, /* {USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */ - {USB_DEVICE(0x0c45, 0x60c0), BS(SN9C105, MI0360)}, + {USB_DEVICE(0x0c45, 0x60c0), BSF(SN9C105, MI0360, F_ILLUM)}, /* or MT9V111 */ /* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */ /* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */ @@ -2936,10 +2936,8 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */ /* {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */ {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)}, -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)}, {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)}, -#endif {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)}, /* /GC0305*/ /* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */ @@ -2962,16 +2960,15 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */ {USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)}, {USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)}, -#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)}, -#endif {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)}, {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)}, {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/ /* or GC0305 / GC0307 */ {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ - {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/ + {USB_DEVICE(0x0c45, 0x614a), BSF(SN9C120, ADCM1700, F_ILLUM)}, +/* {USB_DEVICE(0x0c45, 0x614c), BS(SN9C120, GC0306)}, */ /*sn9c120b*/ {} }; MODULE_DEVICE_TABLE(usb, device_table); @@ -3007,3 +3004,7 @@ static void __exit sd_mod_exit(void) module_init(sd_mod_init); module_exit(sd_mod_exit); + +module_param(starcam, int, 0644); +MODULE_PARM_DESC(starcam, + "StarCam model. 0: Clip, 1: 370i"); diff --git a/drivers/media/video/gspca/spca1528.c b/drivers/media/video/gspca/spca1528.c index e64338664410..76c006b2bc83 100644 --- a/drivers/media/video/gspca/spca1528.c +++ b/drivers/media/video/gspca/spca1528.c @@ -555,7 +555,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x04fc, 0x1528)}, {} }; diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 8e202b9039f1..45552c3ff8d9 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -1051,7 +1051,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200}, {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300}, {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler}, diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index 642839a11e8d..f7ef282cc600 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c @@ -2155,7 +2155,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x040a, 0x0002), .driver_info = KodakDVC325}, {USB_DEVICE(0x0497, 0xc001), .driver_info = SmileIntlCamera}, {USB_DEVICE(0x0506, 0x00df), .driver_info = ThreeComHomeConnectLite}, diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index bc9dd9034ab4..e5bf865147d7 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -786,7 +786,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra}, {USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro}, /*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */ diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 7307638ac91d..348319371523 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -1509,7 +1509,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam}, {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista}, {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110}, diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 3a162c6d5466..e836e778dfb6 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -1061,7 +1061,7 @@ static const struct sd_desc *sd_desc[2] = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A}, {USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A}, {USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A}, diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c index 404067745775..2e9c06175192 100644 --- a/drivers/media/video/gspca/sq905.c +++ b/drivers/media/video/gspca/sq905.c @@ -396,7 +396,7 @@ static int sd_start(struct gspca_dev *gspca_dev) } /* Table of supported USB devices */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x2770, 0x9120)}, {} }; diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c index 8ba199543856..457563b7a71b 100644 --- a/drivers/media/video/gspca/sq905c.c +++ b/drivers/media/video/gspca/sq905c.c @@ -298,7 +298,7 @@ static int sd_start(struct gspca_dev *gspca_dev) } /* Table of supported USB devices */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x2770, 0x905c)}, {USB_DEVICE(0x2770, 0x9050)}, {USB_DEVICE(0x2770, 0x9051)}, diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c index a4a98811b9e3..8215d5dcd456 100644 --- a/drivers/media/video/gspca/sq930x.c +++ b/drivers/media/video/gspca/sq930x.c @@ -1163,7 +1163,7 @@ static const struct sd_desc sd_desc = { #define ST(sensor, type) \ .driver_info = (SENSOR_ ## sensor << 8) \ | (type) -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x4038), ST(MI0360, 0)}, {USB_DEVICE(0x041e, 0x403c), ST(LZ24BP, 0)}, {USB_DEVICE(0x041e, 0x403d), ST(LZ24BP, 0)}, diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 11a192b95ed4..87be52b5e1e3 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -495,7 +495,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x05e1, 0x0893)}, {} }; diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c index b199ad4666bd..e2ef41cf72d7 100644 --- a/drivers/media/video/gspca/stv0680.c +++ b/drivers/media/video/gspca/stv0680.c @@ -327,7 +327,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0553, 0x0202)}, {USB_DEVICE(0x041e, 0x4007)}, {} diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index 28ea4175b80e..7e0661429293 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c @@ -564,7 +564,7 @@ static int stv06xx_config(struct gspca_dev *gspca_dev, /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { /* QuickCam Express */ {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 }, /* LEGO cam / QuickCam Web */ diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index a9cbcd6011d9..543542af2720 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -1162,7 +1162,7 @@ static const struct sd_desc sd_desc = { #define BS(bridge, subtype) \ .driver_info = (BRIDGE_ ## bridge << 8) \ | (subtype) -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)}, {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)}, {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)}, diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 8f0c33116e0d..a3eccd815766 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -1416,7 +1416,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x17a1, 0x0128)}, {} }; diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 38c22f0a4263..933ef2ca658c 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -388,7 +388,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x046d, 0x0920)}, {USB_DEVICE(0x046d, 0x0921)}, {USB_DEVICE(0x0545, 0x808b)}, diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 9b2ae1b6cc75..6caed734a06a 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -4192,7 +4192,7 @@ static const struct sd_desc sd_desc = { #define BF(bridge, flags) \ .driver_info = (BRIDGE_ ## bridge << 8) \ | (flags) -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x405b), BF(VC0323, FL_VFLIP)}, {USB_DEVICE(0x046d, 0x0892), BF(VC0321, 0)}, {USB_DEVICE(0x046d, 0x0896), BF(VC0321, 0)}, diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c index 5b5039a02031..c089a0f6f1d0 100644 --- a/drivers/media/video/gspca/xirlink_cit.c +++ b/drivers/media/video/gspca/xirlink_cit.c @@ -3270,7 +3270,7 @@ static const struct sd_desc sd_desc_isoc_nego = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { { USB_DEVICE_VER(0x0545, 0x8080, 0x0001, 0x0001), .driver_info = CIT_MODEL0 }, { USB_DEVICE_VER(0x0545, 0x8080, 0x0002, 0x0002), .driver_info = CIT_MODEL1 }, { USB_DEVICE_VER(0x0545, 0x8080, 0x030a, 0x030a), .driver_info = CIT_MODEL2 }, diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 14b85d483163..865216e9362c 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6909,7 +6909,7 @@ static const struct sd_desc sd_desc = { #endif }; -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x041e)}, {USB_DEVICE(0x041e, 0x4017)}, {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106}, diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile index e0230fcb2e36..3baa9f613ca3 100644 --- a/drivers/media/video/hdpvr/Makefile +++ b/drivers/media/video/hdpvr/Makefile @@ -1,6 +1,4 @@ -hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o - -hdpvr-$(CONFIG_I2C) += hdpvr-i2c.o +hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index f7d1ee55185a..a6572e5ae369 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c @@ -378,19 +378,17 @@ static int hdpvr_probe(struct usb_interface *interface, goto error; } -#ifdef CONFIG_I2C - /* until i2c is working properly */ - retval = 0; /* hdpvr_register_i2c_adapter(dev); */ +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + retval = hdpvr_register_i2c_adapter(dev); if (retval < 0) { v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n"); goto error; } - /* until i2c is working properly */ - retval = 0; /* hdpvr_register_i2c_ir(dev); */ + retval = hdpvr_register_i2c_ir(dev); if (retval < 0) v4l2_err(&dev->v4l2_dev, "registering i2c IR devices failed\n"); -#endif /* CONFIG_I2C */ +#endif /* let the user know what node this device is now attached to */ v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c index 24966aa02a70..89b71faeaac2 100644 --- a/drivers/media/video/hdpvr/hdpvr-i2c.c +++ b/drivers/media/video/hdpvr/hdpvr-i2c.c @@ -13,6 +13,8 @@ * */ +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + #include <linux/i2c.h> #include <linux/slab.h> @@ -28,106 +30,78 @@ #define Z8F0811_IR_TX_I2C_ADDR 0x70 #define Z8F0811_IR_RX_I2C_ADDR 0x71 -static const u8 ir_i2c_addrs[] = { - Z8F0811_IR_TX_I2C_ADDR, - Z8F0811_IR_RX_I2C_ADDR, -}; -static const char * const ir_devicenames[] = { - "ir_tx_z8f0811_hdpvr", - "ir_rx_z8f0811_hdpvr", +static struct i2c_board_info hdpvr_i2c_board_info = { + I2C_BOARD_INFO("ir_tx_z8f0811_hdpvr", Z8F0811_IR_TX_I2C_ADDR), + I2C_BOARD_INFO("ir_rx_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR), }; -static int hdpvr_new_i2c_ir(struct hdpvr_device *dev, struct i2c_adapter *adap, - const char *type, u8 addr) +int hdpvr_register_i2c_ir(struct hdpvr_device *dev) { - struct i2c_board_info info; + struct i2c_client *c; struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data; - unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; - - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, type, I2C_NAME_SIZE); /* Our default information for ir-kbd-i2c.c to use */ - switch (addr) { - case Z8F0811_IR_RX_I2C_ADDR: - init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = RC_TYPE_RC5; - init_data->name = "HD PVR"; - info.platform_data = init_data; - break; - } + init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + init_data->type = RC_TYPE_RC5; + init_data->name = "HD PVR"; + hdpvr_i2c_board_info.platform_data = init_data; - return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ? - -1 : 0; -} + c = i2c_new_device(&dev->i2c_adapter, &hdpvr_i2c_board_info); -int hdpvr_register_i2c_ir(struct hdpvr_device *dev) -{ - int i; - int ret = 0; - - for (i = 0; i < ARRAY_SIZE(ir_i2c_addrs); i++) - ret += hdpvr_new_i2c_ir(dev, dev->i2c_adapter, - ir_devicenames[i], ir_i2c_addrs[i]); - - return ret; + return (c == NULL) ? -ENODEV : 0; } -static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, - char *data, int len) +static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus, + unsigned char addr, char *data, int len) { int ret; - char *buf = kmalloc(len, GFP_KERNEL); - if (!buf) - return -ENOMEM; + + if (len > sizeof(dev->i2c_buf)) + return -EINVAL; ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), REQTYPE_I2C_READ, CTRL_READ_REQUEST, - 0x100|addr, 0, buf, len, 1000); + (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); if (ret == len) { - memcpy(data, buf, len); + memcpy(data, &dev->i2c_buf, len); ret = 0; } else if (ret >= 0) ret = -EIO; - kfree(buf); - return ret; } -static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr, - char *data, int len) +static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus, + unsigned char addr, char *data, int len) { int ret; - char *buf = kmalloc(len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - memcpy(buf, data, len); + if (len > sizeof(dev->i2c_buf)) + return -EINVAL; + + memcpy(&dev->i2c_buf, data, len); ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, - 0x100|addr, 0, buf, len, 1000); + (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); if (ret < 0) - goto error; + return ret; ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, - 0, 0, buf, 2, 1000); + 0, 0, &dev->i2c_buf, 2, 1000); - if (ret == 2) + if ((ret == 2) && (dev->i2c_buf[1] == (len - 1))) ret = 0; else if (ret >= 0) ret = -EIO; -error: - kfree(buf); return ret; } @@ -146,10 +120,10 @@ static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs, addr = msgs[i].addr << 1; if (msgs[i].flags & I2C_M_RD) - retval = hdpvr_i2c_read(dev, addr, msgs[i].buf, + retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf, msgs[i].len); else - retval = hdpvr_i2c_write(dev, addr, msgs[i].buf, + retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf, msgs[i].len); } @@ -168,30 +142,47 @@ static struct i2c_algorithm hdpvr_algo = { .functionality = hdpvr_functionality, }; +static struct i2c_adapter hdpvr_i2c_adapter_template = { + .name = "Hauppage HD PVR I2C", + .owner = THIS_MODULE, + .algo = &hdpvr_algo, +}; + +static int hdpvr_activate_ir(struct hdpvr_device *dev) +{ + char buffer[8]; + + mutex_lock(&dev->i2c_mutex); + + hdpvr_i2c_read(dev, 0, 0x54, buffer, 1); + + buffer[0] = 0; + buffer[1] = 0x8; + hdpvr_i2c_write(dev, 1, 0x54, buffer, 2); + + buffer[1] = 0x18; + hdpvr_i2c_write(dev, 1, 0x54, buffer, 2); + + mutex_unlock(&dev->i2c_mutex); + + return 0; +} + int hdpvr_register_i2c_adapter(struct hdpvr_device *dev) { - struct i2c_adapter *i2c_adap; int retval = -ENOMEM; - i2c_adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); - if (i2c_adap == NULL) - goto error; - - strlcpy(i2c_adap->name, "Hauppauge HD PVR I2C", - sizeof(i2c_adap->name)); - i2c_adap->algo = &hdpvr_algo; - i2c_adap->owner = THIS_MODULE; - i2c_adap->dev.parent = &dev->udev->dev; + hdpvr_activate_ir(dev); - i2c_set_adapdata(i2c_adap, dev); + memcpy(&dev->i2c_adapter, &hdpvr_i2c_adapter_template, + sizeof(struct i2c_adapter)); + dev->i2c_adapter.dev.parent = &dev->udev->dev; - retval = i2c_add_adapter(i2c_adap); + i2c_set_adapdata(&dev->i2c_adapter, dev); - if (!retval) - dev->i2c_adapter = i2c_adap; - else - kfree(i2c_adap); + retval = i2c_add_adapter(&dev->i2c_adapter); -error: return retval; } + +#endif diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index d38fe1043e47..514aea76eaa5 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c @@ -1220,12 +1220,9 @@ static void hdpvr_device_release(struct video_device *vdev) v4l2_device_unregister(&dev->v4l2_dev); /* deregister I2C adapter */ -#ifdef CONFIG_I2C +#if defined(CONFIG_I2C) || (CONFIG_I2C_MODULE) mutex_lock(&dev->i2c_mutex); - if (dev->i2c_adapter) - i2c_del_adapter(dev->i2c_adapter); - kfree(dev->i2c_adapter); - dev->i2c_adapter = NULL; + i2c_del_adapter(&dev->i2c_adapter); mutex_unlock(&dev->i2c_mutex); #endif /* CONFIG_I2C */ diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 37f1e4c7675d..ee74e3be9a6a 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h @@ -25,6 +25,7 @@ KERNEL_VERSION(HDPVR_MAJOR_VERSION, HDPVR_MINOR_VERSION, HDPVR_RELEASE) #define HDPVR_MAX 8 +#define HDPVR_I2C_MAX_SIZE 128 /* Define these values to match your devices */ #define HD_PVR_VENDOR_ID 0x2040 @@ -106,9 +107,11 @@ struct hdpvr_device { struct work_struct worker; /* I2C adapter */ - struct i2c_adapter *i2c_adapter; + struct i2c_adapter i2c_adapter; /* I2C lock */ struct mutex i2c_mutex; + /* I2C message buffer space */ + char i2c_buf[HDPVR_I2C_MAX_SIZE]; /* For passing data to ir-kbd-i2c */ struct IR_i2c_init_data ir_i2c_init_data; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index c87b6bc45555..d2b20ad383a3 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -244,15 +244,17 @@ static void ir_key_poll(struct IR_i2c *ir) static u32 ir_key, ir_raw; int rc; - dprintk(2,"ir_poll_key\n"); + dprintk(3, "%s\n", __func__); rc = ir->get_key(ir, &ir_key, &ir_raw); if (rc < 0) { dprintk(2,"error\n"); return; } - if (rc) + if (rc) { + dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key); rc_keydown(ir->rc, ir_key, 0); + } } static void ir_work(struct work_struct *work) @@ -321,6 +323,12 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) rc_type = RC_TYPE_OTHER; ir_codes = RC_MAP_AVERMEDIA_CARDBUS; break; + case 0x71: + name = "Hauppauge/Zilog Z8"; + ir->get_key = get_key_haup_xvr; + rc_type = RC_TYPE_RC5; + ir_codes = hauppauge ? RC_MAP_HAUPPAUGE_NEW : RC_MAP_RC5_TV; + break; } /* Let the caller override settings */ diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index e103b8fc7452..9fb86a081c0f 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -300,10 +300,15 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) adap, type, 0, I2C_ADDRS(hw_addrs[idx])); } else if (hw == IVTV_HW_CX25840) { struct cx25840_platform_data pdata; + struct i2c_board_info cx25840_info = { + .type = "cx25840", + .addr = hw_addrs[idx], + .platform_data = &pdata, + }; pdata.pvr150_workaround = itv->pvr150_workaround; - sd = v4l2_i2c_new_subdev_cfg(&itv->v4l2_dev, - adap, type, 0, &pdata, hw_addrs[idx], NULL); + sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap, + &cx25840_info, NULL); } else { sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, hw_addrs[idx], NULL); diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c index 209ff97261a9..4904d25f689f 100644 --- a/drivers/media/video/mt9v011.c +++ b/drivers/media/video/mt9v011.c @@ -12,17 +12,41 @@ #include <asm/div64.h> #include <media/v4l2-device.h> #include <media/v4l2-chip-ident.h> -#include "mt9v011.h" +#include <media/mt9v011.h> MODULE_DESCRIPTION("Micron mt9v011 sensor driver"); MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); MODULE_LICENSE("GPL"); - static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-2)"); +#define R00_MT9V011_CHIP_VERSION 0x00 +#define R01_MT9V011_ROWSTART 0x01 +#define R02_MT9V011_COLSTART 0x02 +#define R03_MT9V011_HEIGHT 0x03 +#define R04_MT9V011_WIDTH 0x04 +#define R05_MT9V011_HBLANK 0x05 +#define R06_MT9V011_VBLANK 0x06 +#define R07_MT9V011_OUT_CTRL 0x07 +#define R09_MT9V011_SHUTTER_WIDTH 0x09 +#define R0A_MT9V011_CLK_SPEED 0x0a +#define R0B_MT9V011_RESTART 0x0b +#define R0C_MT9V011_SHUTTER_DELAY 0x0c +#define R0D_MT9V011_RESET 0x0d +#define R1E_MT9V011_DIGITAL_ZOOM 0x1e +#define R20_MT9V011_READ_MODE 0x20 +#define R2B_MT9V011_GREEN_1_GAIN 0x2b +#define R2C_MT9V011_BLUE_GAIN 0x2c +#define R2D_MT9V011_RED_GAIN 0x2d +#define R2E_MT9V011_GREEN_2_GAIN 0x2e +#define R35_MT9V011_GLOBAL_GAIN 0x35 +#define RF1_MT9V011_CHIP_ENABLE 0xf1 + +#define MT9V011_VERSION 0x8232 +#define MT9V011_REV_B_VERSION 0x8243 + /* supported controls */ static struct v4l2_queryctrl mt9v011_qctrl[] = { { @@ -469,23 +493,6 @@ static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt return 0; } -static int mt9v011_s_config(struct v4l2_subdev *sd, int dumb, void *data) -{ - struct mt9v011 *core = to_mt9v011(sd); - unsigned *xtal = data; - - v4l2_dbg(1, debug, sd, "s_config called\n"); - - if (xtal) { - core->xtal = *xtal; - v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n", - *xtal / 1000000, (*xtal / 1000) % 1000); - } - - return 0; -} - - #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9v011_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -536,7 +543,6 @@ static const struct v4l2_subdev_core_ops mt9v011_core_ops = { .g_ctrl = mt9v011_g_ctrl, .s_ctrl = mt9v011_s_ctrl, .reset = mt9v011_reset, - .s_config = mt9v011_s_config, .g_chip_ident = mt9v011_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9v011_g_register, @@ -596,6 +602,14 @@ static int mt9v011_probe(struct i2c_client *c, core->height = 480; core->xtal = 27000000; /* Hz */ + if (c->dev.platform_data) { + struct mt9v011_platform_data *pdata = c->dev.platform_data; + + core->xtal = pdata->xtal; + v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n", + core->xtal / 1000000, (core->xtal / 1000) % 1000); + } + v4l_info(c, "chip found @ 0x%02x (%s - chip version 0x%04x)\n", c->addr << 1, c->adapter->name, version); diff --git a/drivers/media/video/mt9v011.h b/drivers/media/video/mt9v011.h deleted file mode 100644 index 3350fd6083c3..000000000000 --- a/drivers/media/video/mt9v011.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor - * - * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com) - * This code is placed under the terms of the GNU General Public License v2 - */ - -#ifndef MT9V011_H_ -#define MT9V011_H_ - -#define R00_MT9V011_CHIP_VERSION 0x00 -#define R01_MT9V011_ROWSTART 0x01 -#define R02_MT9V011_COLSTART 0x02 -#define R03_MT9V011_HEIGHT 0x03 -#define R04_MT9V011_WIDTH 0x04 -#define R05_MT9V011_HBLANK 0x05 -#define R06_MT9V011_VBLANK 0x06 -#define R07_MT9V011_OUT_CTRL 0x07 -#define R09_MT9V011_SHUTTER_WIDTH 0x09 -#define R0A_MT9V011_CLK_SPEED 0x0a -#define R0B_MT9V011_RESTART 0x0b -#define R0C_MT9V011_SHUTTER_DELAY 0x0c -#define R0D_MT9V011_RESET 0x0d -#define R1E_MT9V011_DIGITAL_ZOOM 0x1e -#define R20_MT9V011_READ_MODE 0x20 -#define R2B_MT9V011_GREEN_1_GAIN 0x2b -#define R2C_MT9V011_BLUE_GAIN 0x2c -#define R2D_MT9V011_RED_GAIN 0x2d -#define R2E_MT9V011_GREEN_2_GAIN 0x2e -#define R35_MT9V011_GLOBAL_GAIN 0x35 -#define RF1_MT9V011_CHIP_ENABLE 0xf1 - -#define MT9V011_VERSION 0x8232 -#define MT9V011_REV_B_VERSION 0x8243 - -#endif diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index c881a64b41fd..d4e7c11553c3 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c @@ -1449,47 +1449,6 @@ static int ov7670_g_chip_ident(struct v4l2_subdev *sd, return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0); } -static int ov7670_s_config(struct v4l2_subdev *sd, int dumb, void *data) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov7670_config *config = data; - struct ov7670_info *info = to_state(sd); - int ret; - - info->clock_speed = 30; /* default: a guess */ - - /* - * Must apply configuration before initializing device, because it - * selects I/O method. - */ - if (config) { - info->min_width = config->min_width; - info->min_height = config->min_height; - info->use_smbus = config->use_smbus; - - if (config->clock_speed) - info->clock_speed = config->clock_speed; - } - - /* Make sure it's an ov7670 */ - ret = ov7670_detect(sd); - if (ret) { - v4l_dbg(1, debug, client, - "chip found @ 0x%x (%s) is not an ov7670 chip.\n", - client->addr << 1, client->adapter->name); - kfree(info); - return ret; - } - v4l_info(client, "chip found @ 0x%02x (%s)\n", - client->addr << 1, client->adapter->name); - - info->fmt = &ov7670_formats[0]; - info->sat = 128; /* Review this */ - info->clkrc = info->clock_speed / 30; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { @@ -1528,7 +1487,6 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = { .s_ctrl = ov7670_s_ctrl, .queryctrl = ov7670_queryctrl, .reset = ov7670_reset, - .s_config = ov7670_s_config, .init = ov7670_init, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov7670_g_register, @@ -1558,6 +1516,7 @@ static int ov7670_probe(struct i2c_client *client, { struct v4l2_subdev *sd; struct ov7670_info *info; + int ret; info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL); if (info == NULL) @@ -1565,6 +1524,37 @@ static int ov7670_probe(struct i2c_client *client, sd = &info->sd; v4l2_i2c_subdev_init(sd, client, &ov7670_ops); + info->clock_speed = 30; /* default: a guess */ + if (client->dev.platform_data) { + struct ov7670_config *config = client->dev.platform_data; + + /* + * Must apply configuration before initializing device, because it + * selects I/O method. + */ + info->min_width = config->min_width; + info->min_height = config->min_height; + info->use_smbus = config->use_smbus; + + if (config->clock_speed) + info->clock_speed = config->clock_speed; + } + + /* Make sure it's an ov7670 */ + ret = ov7670_detect(sd); + if (ret) { + v4l_dbg(1, debug, client, + "chip found @ 0x%x (%s) is not an ov7670 chip.\n", + client->addr << 1, client->adapter->name); + kfree(info); + return ret; + } + v4l_info(client, "chip found @ 0x%02x (%s)\n", + client->addr << 1, client->adapter->name); + + info->fmt = &ov7670_formats[0]; + info->sat = 128; /* Review this */ + info->clkrc = info->clock_speed / 30; return 0; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index ac94a8bf883e..305e6aaa844a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -40,6 +40,7 @@ #include "pvrusb2-io.h" #include <media/v4l2-device.h> #include <media/cx2341x.h> +#include <media/ir-kbd-i2c.h> #include "pvrusb2-devattr.h" /* Legal values for PVR2_CID_HSM */ @@ -202,6 +203,7 @@ struct pvr2_hdw { /* IR related */ unsigned int ir_scheme_active; /* IR scheme as seen from the outside */ + struct IR_i2c_init_data ir_init_data; /* params passed to IR modules */ /* Frequency table */ unsigned int freqTable[FREQTABLE_SIZE]; diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 7cbe18c4ca95..ccc884948f34 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -19,6 +19,7 @@ */ #include <linux/i2c.h> +#include <media/ir-kbd-i2c.h> #include "pvrusb2-i2c-core.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" @@ -48,13 +49,6 @@ module_param_named(disable_autoload_ir_video, pvr2_disable_ir_video, MODULE_PARM_DESC(disable_autoload_ir_video, "1=do not try to autoload ir_video IR receiver"); -/* Mapping of IR schemes to known I2C addresses - if any */ -static const unsigned char ir_video_addresses[] = { - [PVR2_IR_SCHEME_ZILOG] = 0x71, - [PVR2_IR_SCHEME_29XXX] = 0x18, - [PVR2_IR_SCHEME_24XXX] = 0x18, -}; - static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */ u8 i2c_addr, /* I2C address we're talking to */ u8 *data, /* Data to write */ @@ -574,26 +568,56 @@ static void do_i2c_scan(struct pvr2_hdw *hdw) static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) { struct i2c_board_info info; - unsigned char addr = 0; + struct IR_i2c_init_data *init_data = &hdw->ir_init_data; if (pvr2_disable_ir_video) { pvr2_trace(PVR2_TRACE_INFO, "Automatic binding of ir_video has been disabled."); return; } - if (hdw->ir_scheme_active < ARRAY_SIZE(ir_video_addresses)) { - addr = ir_video_addresses[hdw->ir_scheme_active]; - } - if (!addr) { + memset(&info, 0, sizeof(struct i2c_board_info)); + switch (hdw->ir_scheme_active) { + case PVR2_IR_SCHEME_24XXX: /* FX2-controlled IR */ + case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */ + init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; + init_data->type = RC_TYPE_RC5; + init_data->name = hdw->hdw_desc->description; + init_data->polling_interval = 100; /* ms From ir-kbd-i2c */ + /* IR Receiver */ + info.addr = 0x18; + info.platform_data = init_data; + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.", + info.type, info.addr); + i2c_new_device(&hdw->i2c_adap, &info); + break; + case PVR2_IR_SCHEME_ZILOG: /* HVR-1950 style */ + case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */ + init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + init_data->type = RC_TYPE_RC5; + init_data->name = hdw->hdw_desc->description; + init_data->polling_interval = 260; /* ms From lirc_zilog */ + /* IR Receiver */ + info.addr = 0x71; + info.platform_data = init_data; + strlcpy(info.type, "ir_rx_z8f0811_haup", I2C_NAME_SIZE); + pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.", + info.type, info.addr); + i2c_new_device(&hdw->i2c_adap, &info); + /* IR Trasmitter */ + info.addr = 0x70; + info.platform_data = init_data; + strlcpy(info.type, "ir_tx_z8f0811_haup", I2C_NAME_SIZE); + pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.", + info.type, info.addr); + i2c_new_device(&hdw->i2c_adap, &info); + break; + default: /* The device either doesn't support I2C-based IR or we don't know (yet) how to operate IR on the device. */ - return; + break; } - pvr2_trace(PVR2_TRACE_INFO, - "Binding ir_video to i2c address 0x%02x.", addr); - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - info.addr = addr; - i2c_new_device(&hdw->i2c_adap, &info); } void pvr2_i2c_core_init(struct pvr2_hdw *hdw) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index e7aa588c6c5a..deb8fcf4aa49 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -5179,18 +5179,8 @@ struct saa7134_board saa7134_boards[] = { [SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG] = { .name = "Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid", .audio_clock = 0x00187de7, -#if 0 - /* - * FIXME: Analog mode doesn't work, if digital is enabled. The proper - * fix is to use tda8290 driver, but Kworld seems to use an - * unsupported version of tda8295. - */ - .tuner_type = TUNER_NXP_TDA18271, /* TUNER_PHILIPS_TDA8290 */ - .tuner_addr = 0x60, -#else - .tuner_type = UNSET, + .tuner_type = TUNER_PHILIPS_TDA8290, .tuner_addr = ADDR_UNSET, -#endif .radio_type = UNSET, .radio_addr = ADDR_UNSET, .gpiomask = 0x8e054000, @@ -6932,10 +6922,17 @@ static inline int saa7134_kworld_sbtvd_toggle_agc(struct saa7134_dev *dev, /* toggle AGC switch through GPIO 27 */ switch (mode) { case TDA18271_ANALOG: - saa7134_set_gpio(dev, 27, 0); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000); + msleep(20); break; case TDA18271_DIGITAL: - saa7134_set_gpio(dev, 27, 1); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x14000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x14000); + msleep(20); + saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x54000); + saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x54000); + msleep(30); break; default: return -EINVAL; @@ -6993,6 +6990,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, int saa7134_tuner_callback(void *priv, int component, int command, int arg) { struct saa7134_dev *dev = priv; + if (dev != NULL) { switch (dev->tuner_type) { case TUNER_PHILIPS_TDA8290: @@ -7659,36 +7657,11 @@ int saa7134_board_init2(struct saa7134_dev *dev) break; } case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: - { - struct i2c_msg msg = { .addr = 0x4b, .flags = 0 }; - int i; - static u8 buffer[][2] = { - {0x30, 0x31}, - {0xff, 0x00}, - {0x41, 0x03}, - {0x41, 0x1a}, - {0xff, 0x02}, - {0x34, 0x00}, - {0x45, 0x97}, - {0x45, 0xc1}, - }; saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000); saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000); - /* - * FIXME: identify what device is at addr 0x4b and what means - * this initialization - */ - for (i = 0; i < ARRAY_SIZE(buffer); i++) { - msg.buf = &buffer[i][0]; - msg.len = ARRAY_SIZE(buffer[0]); - if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) - printk(KERN_WARNING - "%s: Unable to enable tuner(%i).\n", - dev->name, i); - } + saa7134_set_gpio(dev, 27, 0); break; - } } /* switch() */ /* initialize tuner */ diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 3315a48a848b..f65cad287b83 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -237,12 +237,39 @@ static struct tda18271_std_map mb86a20s_tda18271_std_map = { static struct tda18271_config kworld_tda18271_config = { .std_map = &mb86a20s_tda18271_std_map, .gate = TDA18271_GATE_DIGITAL, + .config = 3, /* Use tuner callback for AGC */ + }; static const struct mb86a20s_config kworld_mb86a20s_config = { .demod_address = 0x10, }; +static int kworld_sbtvd_gate_ctrl(struct dvb_frontend* fe, int enable) +{ + struct saa7134_dev *dev = fe->dvb->priv; + + unsigned char initmsg[] = {0x45, 0x97}; + unsigned char msg_enable[] = {0x45, 0xc1}; + unsigned char msg_disable[] = {0x45, 0x81}; + struct i2c_msg msg = {.addr = 0x4b, .flags = 0, .buf = initmsg, .len = 2}; + + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) { + wprintk("could not access the I2C gate\n"); + return -EIO; + } + if (enable) + msg.buf = msg_enable; + else + msg.buf = msg_disable; + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) { + wprintk("could not access the I2C gate\n"); + return -EIO; + } + msleep(20); + return 0; +} + /* ================================================================== * tda1004x based DVB-T cards, helper functions */ @@ -623,37 +650,6 @@ static struct tda827x_config tda827x_cfg_2_sw42 = { /* ------------------------------------------------------------------ */ -static int __kworld_sbtvd_i2c_gate_ctrl(struct saa7134_dev *dev, int enable) -{ - unsigned char initmsg[] = {0x45, 0x97}; - unsigned char msg_enable[] = {0x45, 0xc1}; - unsigned char msg_disable[] = {0x45, 0x81}; - struct i2c_msg msg = {.addr = 0x4b, .flags = 0, .buf = initmsg, .len = 2}; - - if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) { - wprintk("could not access the I2C gate\n"); - return -EIO; - } - if (enable) - msg.buf = msg_enable; - else - msg.buf = msg_disable; - if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) { - wprintk("could not access the I2C gate\n"); - return -EIO; - } - msleep(20); - return 0; -} -static int kworld_sbtvd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) -{ - struct saa7134_dev *dev = fe->dvb->priv; - - return __kworld_sbtvd_i2c_gate_ctrl(dev, enable); -} - -/* ------------------------------------------------------------------ */ - static struct tda1004x_config tda827x_lifeview_config = { .demod_address = 0x08, .invert = 1, @@ -1660,27 +1656,23 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: - __kworld_sbtvd_i2c_gate_ctrl(dev, 0); - saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x14000); - saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x14000); - msleep(20); - saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x54000); - saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x54000); - msleep(20); + /* Switch to digital mode */ + saa7134_tuner_callback(dev, 0, + TDA18271_CALLBACK_CMD_AGC_ENABLE, 1); fe0->dvb.frontend = dvb_attach(mb86a20s_attach, &kworld_mb86a20s_config, &dev->i2c_adap); - __kworld_sbtvd_i2c_gate_ctrl(dev, 1); if (fe0->dvb.frontend != NULL) { + dvb_attach(tda829x_attach, fe0->dvb.frontend, + &dev->i2c_adap, 0x4b, + &tda829x_no_probe); dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, &kworld_tda18271_config); - /* - * Only after success, it can initialize the gate, otherwise - * an OOPS will hit, due to kfree(fe0->dvb.frontend) - */ - fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_i2c_gate_ctrl; + fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_gate_ctrl; } + + /* mb86a20s need to use the I2C gateway */ break; default: wprintk("Huh? unknown DVB card?\n"); diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 41064c7b5ef8..b3d2cc729657 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -47,8 +47,8 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ -#endif { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, +#endif { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE @@ -56,78 +56,68 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, #endif - { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, + { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, /* not in sonixb */ #if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, #endif - { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, + { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, /* not in sonixb */ /* SN9C103 */ - { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, non existent ? */ + { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, /* not in sonixb */ +#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE /* { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */ - { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, non existent ? */ { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */ -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), }, -#endif - { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, non existent ? */ /* { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */ /* { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */ -/* { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5130 */ - { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5110, non existent */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, non existent ? */ { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), }, -#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, non existent ? */ #endif - { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, /* SN9C105 */ #if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, -#endif { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), }, PO1030 */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, OM6801 */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, HV7131GP */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, non existent ? */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, MO4000 */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, ICM105C */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, OV7648 */ { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), }, /* SN9C120 */ { SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), }, -#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE - { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, -#endif - { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, - { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, -#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE +/* { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, po2030 */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, om6801 */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, S5K53BEB */ { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, -#endif /* { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */ -#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, -#endif { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, -#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), }, #endif diff --git a/drivers/media/video/sr030pc30.c b/drivers/media/video/sr030pc30.c index 864696b7a006..c901721a1db3 100644 --- a/drivers/media/video/sr030pc30.c +++ b/drivers/media/video/sr030pc30.c @@ -714,15 +714,6 @@ static int sr030pc30_base_config(struct v4l2_subdev *sd) return ret; } -static int sr030pc30_s_config(struct v4l2_subdev *sd, - int irq, void *platform_data) -{ - struct sr030pc30_info *info = to_sr030pc30(sd); - - info->pdata = platform_data; - return 0; -} - static int sr030pc30_s_stream(struct v4l2_subdev *sd, int enable) { return 0; @@ -763,7 +754,6 @@ static int sr030pc30_s_power(struct v4l2_subdev *sd, int on) } static const struct v4l2_subdev_core_ops sr030pc30_core_ops = { - .s_config = sr030pc30_s_config, .s_power = sr030pc30_s_power, .queryctrl = sr030pc30_queryctrl, .s_ctrl = sr030pc30_s_ctrl, diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c deleted file mode 100644 index 35b6ff5db319..000000000000 --- a/drivers/media/video/tda9875.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * For the TDA9875 chip - * (The TDA9875 is used on the Diamond DTV2000 french version - * Other cards probably use these chips as well.) - * This driver will not complain if used with any - * other i2c device with the same address. - * - * Copyright (c) 2000 Guillaume Delvit based on Gerd Knorr source and - * Eric Sandeen - * Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org> - * This code is placed under the terms of the GNU General Public License - * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) - * Which was based on tda8425.c by Greg Alexander (c) 1998 - * - * OPTIONS: - * debug - set to 1 if you'd like to see debug messages - * - * Revision: 0.1 - original version - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/videodev2.h> -#include <media/v4l2-device.h> -#include <media/i2c-addr.h> - -static int debug; /* insmod parameter */ -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_LICENSE("GPL"); - - -/* This is a superset of the TDA9875 */ -struct tda9875 { - struct v4l2_subdev sd; - int rvol, lvol; - int bass, treble; -}; - -static inline struct tda9875 *to_state(struct v4l2_subdev *sd) -{ - return container_of(sd, struct tda9875, sd); -} - -#define dprintk if (debug) printk - -/* The TDA9875 is made by Philips Semiconductor - * http://www.semiconductors.philips.com - * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator - * - */ - - /* subaddresses for TDA9875 */ -#define TDA9875_MUT 0x12 /*General mute (value --> 0b11001100*/ -#define TDA9875_CFG 0x01 /* Config register (value --> 0b00000000 */ -#define TDA9875_DACOS 0x13 /*DAC i/o select (ADC) 0b0000100*/ -#define TDA9875_LOSR 0x16 /*Line output select regirter 0b0100 0001*/ - -#define TDA9875_CH1V 0x0c /*Channel 1 volume (mute)*/ -#define TDA9875_CH2V 0x0d /*Channel 2 volume (mute)*/ -#define TDA9875_SC1 0x14 /*SCART 1 in (mono)*/ -#define TDA9875_SC2 0x15 /*SCART 2 in (mono)*/ - -#define TDA9875_ADCIS 0x17 /*ADC input select (mono) 0b0110 000*/ -#define TDA9875_AER 0x19 /*Audio effect (AVL+Pseudo) 0b0000 0110*/ -#define TDA9875_MCS 0x18 /*Main channel select (DAC) 0b0000100*/ -#define TDA9875_MVL 0x1a /* Main volume gauche */ -#define TDA9875_MVR 0x1b /* Main volume droite */ -#define TDA9875_MBA 0x1d /* Main Basse */ -#define TDA9875_MTR 0x1e /* Main treble */ -#define TDA9875_ACS 0x1f /* Auxilary channel select (FM) 0b0000000*/ -#define TDA9875_AVL 0x20 /* Auxilary volume gauche */ -#define TDA9875_AVR 0x21 /* Auxilary volume droite */ -#define TDA9875_ABA 0x22 /* Auxilary Basse */ -#define TDA9875_ATR 0x23 /* Auxilary treble */ - -#define TDA9875_MSR 0x02 /* Monitor select register */ -#define TDA9875_C1MSB 0x03 /* Carrier 1 (FM) frequency register MSB */ -#define TDA9875_C1MIB 0x04 /* Carrier 1 (FM) frequency register (16-8]b */ -#define TDA9875_C1LSB 0x05 /* Carrier 1 (FM) frequency register LSB */ -#define TDA9875_C2MSB 0x06 /* Carrier 2 (nicam) frequency register MSB */ -#define TDA9875_C2MIB 0x07 /* Carrier 2 (nicam) frequency register (16-8]b */ -#define TDA9875_C2LSB 0x08 /* Carrier 2 (nicam) frequency register LSB */ -#define TDA9875_DCR 0x09 /* Demodulateur configuration regirter*/ -#define TDA9875_DEEM 0x0a /* FM de-emphasis regirter*/ -#define TDA9875_FMAT 0x0b /* FM Matrix regirter*/ - -/* values */ -#define TDA9875_MUTE_ON 0xff /* general mute */ -#define TDA9875_MUTE_OFF 0xcc /* general no mute */ - - - -/* Begin code */ - -static int tda9875_write(struct v4l2_subdev *sd, int subaddr, unsigned char val) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - unsigned char buffer[2]; - - v4l2_dbg(1, debug, sd, "Writing %d 0x%x\n", subaddr, val); - buffer[0] = subaddr; - buffer[1] = val; - if (2 != i2c_master_send(client, buffer, 2)) { - v4l2_warn(sd, "I/O error, trying (write %d 0x%x)\n", - subaddr, val); - return -1; - } - return 0; -} - - -static int i2c_read_register(struct i2c_client *client, int addr, int reg) -{ - unsigned char write[1]; - unsigned char read[1]; - struct i2c_msg msgs[2] = { - { addr, 0, 1, write }, - { addr, I2C_M_RD, 1, read } - }; - - write[0] = reg; - - if (2 != i2c_transfer(client->adapter, msgs, 2)) { - v4l_warn(client, "I/O error (read2)\n"); - return -1; - } - v4l_dbg(1, debug, client, "chip_read2: reg%d=0x%x\n", reg, read[0]); - return read[0]; -} - -static void tda9875_set(struct v4l2_subdev *sd) -{ - struct tda9875 *tda = to_state(sd); - unsigned char a; - - v4l2_dbg(1, debug, sd, "tda9875_set(%04x,%04x,%04x,%04x)\n", - tda->lvol, tda->rvol, tda->bass, tda->treble); - - a = tda->lvol & 0xff; - tda9875_write(sd, TDA9875_MVL, a); - a =tda->rvol & 0xff; - tda9875_write(sd, TDA9875_MVR, a); - a =tda->bass & 0xff; - tda9875_write(sd, TDA9875_MBA, a); - a =tda->treble & 0xff; - tda9875_write(sd, TDA9875_MTR, a); -} - -static void do_tda9875_init(struct v4l2_subdev *sd) -{ - struct tda9875 *t = to_state(sd); - - v4l2_dbg(1, debug, sd, "In tda9875_init\n"); - tda9875_write(sd, TDA9875_CFG, 0xd0); /*reg de config 0 (reset)*/ - tda9875_write(sd, TDA9875_MSR, 0x03); /* Monitor 0b00000XXX*/ - tda9875_write(sd, TDA9875_C1MSB, 0x00); /*Car1(FM) MSB XMHz*/ - tda9875_write(sd, TDA9875_C1MIB, 0x00); /*Car1(FM) MIB XMHz*/ - tda9875_write(sd, TDA9875_C1LSB, 0x00); /*Car1(FM) LSB XMHz*/ - tda9875_write(sd, TDA9875_C2MSB, 0x00); /*Car2(NICAM) MSB XMHz*/ - tda9875_write(sd, TDA9875_C2MIB, 0x00); /*Car2(NICAM) MIB XMHz*/ - tda9875_write(sd, TDA9875_C2LSB, 0x00); /*Car2(NICAM) LSB XMHz*/ - tda9875_write(sd, TDA9875_DCR, 0x00); /*Demod config 0x00*/ - tda9875_write(sd, TDA9875_DEEM, 0x44); /*DE-Emph 0b0100 0100*/ - tda9875_write(sd, TDA9875_FMAT, 0x00); /*FM Matrix reg 0x00*/ - tda9875_write(sd, TDA9875_SC1, 0x00); /* SCART 1 (SC1)*/ - tda9875_write(sd, TDA9875_SC2, 0x01); /* SCART 2 (sc2)*/ - - tda9875_write(sd, TDA9875_CH1V, 0x10); /* Channel volume 1 mute*/ - tda9875_write(sd, TDA9875_CH2V, 0x10); /* Channel volume 2 mute */ - tda9875_write(sd, TDA9875_DACOS, 0x02); /* sig DAC i/o(in:nicam)*/ - tda9875_write(sd, TDA9875_ADCIS, 0x6f); /* sig ADC input(in:mono)*/ - tda9875_write(sd, TDA9875_LOSR, 0x00); /* line out (in:mono)*/ - tda9875_write(sd, TDA9875_AER, 0x00); /*06 Effect (AVL+PSEUDO) */ - tda9875_write(sd, TDA9875_MCS, 0x44); /* Main ch select (DAC) */ - tda9875_write(sd, TDA9875_MVL, 0x03); /* Vol Main left 10dB */ - tda9875_write(sd, TDA9875_MVR, 0x03); /* Vol Main right 10dB*/ - tda9875_write(sd, TDA9875_MBA, 0x00); /* Main Bass Main 0dB*/ - tda9875_write(sd, TDA9875_MTR, 0x00); /* Main Treble Main 0dB*/ - tda9875_write(sd, TDA9875_ACS, 0x44); /* Aux chan select (dac)*/ - tda9875_write(sd, TDA9875_AVL, 0x00); /* Vol Aux left 0dB*/ - tda9875_write(sd, TDA9875_AVR, 0x00); /* Vol Aux right 0dB*/ - tda9875_write(sd, TDA9875_ABA, 0x00); /* Aux Bass Main 0dB*/ - tda9875_write(sd, TDA9875_ATR, 0x00); /* Aux Aigus Main 0dB*/ - - tda9875_write(sd, TDA9875_MUT, 0xcc); /* General mute */ - - t->lvol = t->rvol = 0; /* 0dB */ - t->bass = 0; /* 0dB */ - t->treble = 0; /* 0dB */ - tda9875_set(sd); -} - - -static int tda9875_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct tda9875 *t = to_state(sd); - - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - { - int left = (t->lvol+84)*606; - int right = (t->rvol+84)*606; - - ctrl->value=max(left,right); - return 0; - } - case V4L2_CID_AUDIO_BALANCE: - { - int left = (t->lvol+84)*606; - int right = (t->rvol+84)*606; - int volume = max(left,right); - int balance = (32768*min(left,right))/ - (volume ? volume : 1); - ctrl->value=(left<right)? - (65535-balance) : balance; - return 0; - } - case V4L2_CID_AUDIO_BASS: - ctrl->value = (t->bass+12)*2427; /* min -12 max +15 */ - return 0; - case V4L2_CID_AUDIO_TREBLE: - ctrl->value = (t->treble+12)*2730;/* min -12 max +12 */ - return 0; - } - return -EINVAL; -} - -static int tda9875_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct tda9875 *t = to_state(sd); - int chvol = 0, volume = 0, balance = 0, left, right; - - switch (ctrl->id) { - case V4L2_CID_AUDIO_VOLUME: - left = (t->lvol+84)*606; - right = (t->rvol+84)*606; - - volume = max(left,right); - balance = (32768*min(left,right))/ - (volume ? volume : 1); - balance =(left<right)? - (65535-balance) : balance; - - volume = ctrl->value; - - chvol=1; - break; - case V4L2_CID_AUDIO_BALANCE: - left = (t->lvol+84)*606; - right = (t->rvol+84)*606; - - volume=max(left,right); - - balance = ctrl->value; - - chvol=1; - break; - case V4L2_CID_AUDIO_BASS: - t->bass = ((ctrl->value/2400)-12) & 0xff; - if (t->bass > 15) - t->bass = 15; - if (t->bass < -12) - t->bass = -12 & 0xff; - break; - case V4L2_CID_AUDIO_TREBLE: - t->treble = ((ctrl->value/2700)-12) & 0xff; - if (t->treble > 12) - t->treble = 12; - if (t->treble < -12) - t->treble = -12 & 0xff; - break; - default: - return -EINVAL; - } - - if (chvol) { - left = (min(65536 - balance,32768) * - volume) / 32768; - right = (min(balance,32768) * - volume) / 32768; - t->lvol = ((left/606)-84) & 0xff; - if (t->lvol > 24) - t->lvol = 24; - if (t->lvol < -84) - t->lvol = -84 & 0xff; - - t->rvol = ((right/606)-84) & 0xff; - if (t->rvol > 24) - t->rvol = 24; - if (t->rvol < -84) - t->rvol = -84 & 0xff; - } - - tda9875_set(sd); - return 0; -} - -static int tda9875_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) -{ - switch (qc->id) { - case V4L2_CID_AUDIO_VOLUME: - return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 58880); - case V4L2_CID_AUDIO_BASS: - case V4L2_CID_AUDIO_TREBLE: - return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768); - } - return -EINVAL; -} - -/* ----------------------------------------------------------------------- */ - -static const struct v4l2_subdev_core_ops tda9875_core_ops = { - .queryctrl = tda9875_queryctrl, - .g_ctrl = tda9875_g_ctrl, - .s_ctrl = tda9875_s_ctrl, -}; - -static const struct v4l2_subdev_ops tda9875_ops = { - .core = &tda9875_core_ops, -}; - -/* ----------------------------------------------------------------------- */ - - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tda9875_checkit(struct i2c_client *client, int addr) -{ - int dic, rev; - - dic = i2c_read_register(client, addr, 254); - rev = i2c_read_register(client, addr, 255); - - if (dic == 0 || dic == 2) { /* tda9875 and tda9875A */ - v4l_info(client, "tda9875%s rev. %d detected at 0x%02x\n", - dic == 0 ? "" : "A", rev, addr << 1); - return 1; - } - v4l_info(client, "no such chip at 0x%02x (dic=0x%x rev=0x%x)\n", - addr << 1, dic, rev); - return 0; -} - -static int tda9875_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct tda9875 *t; - struct v4l2_subdev *sd; - - v4l_info(client, "chip found @ 0x%02x (%s)\n", - client->addr << 1, client->adapter->name); - - if (!tda9875_checkit(client, client->addr)) - return -ENODEV; - - t = kzalloc(sizeof(*t), GFP_KERNEL); - if (!t) - return -ENOMEM; - sd = &t->sd; - v4l2_i2c_subdev_init(sd, client, &tda9875_ops); - - do_tda9875_init(sd); - return 0; -} - -static int tda9875_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - - do_tda9875_init(sd); - v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); - return 0; -} - -static const struct i2c_device_id tda9875_id[] = { - { "tda9875", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, tda9875_id); - -static struct i2c_driver tda9875_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "tda9875", - }, - .probe = tda9875_probe, - .remove = tda9875_remove, - .id_table = tda9875_id, -}; - -static __init int init_tda9875(void) -{ - return i2c_add_driver(&tda9875_driver); -} - -static __exit void exit_tda9875(void) -{ - i2c_del_driver(&tda9875_driver); -} - -module_init(init_tda9875); -module_exit(exit_tda9875); diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/video/tlg2300/pd-video.c index a1ffe18640fe..df33a1d188bb 100644 --- a/drivers/media/video/tlg2300/pd-video.c +++ b/drivers/media/video/tlg2300/pd-video.c @@ -512,19 +512,20 @@ int alloc_bulk_urbs_generic(struct urb **urb_array, int num, int buf_size, gfp_t gfp_flags, usb_complete_t complete_fn, void *context) { - struct urb *urb; - void *mem; - int i; + int i = 0; - for (i = 0; i < num; i++) { - urb = usb_alloc_urb(0, gfp_flags); + for (; i < num; i++) { + void *mem; + struct urb *urb = usb_alloc_urb(0, gfp_flags); if (urb == NULL) return i; mem = usb_alloc_coherent(udev, buf_size, gfp_flags, &urb->transfer_dma); - if (mem == NULL) + if (mem == NULL) { + usb_free_urb(urb); return i; + } usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, ep_addr), mem, buf_size, complete_fn, context); diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 3f0871b550ad..810eef43c216 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -407,18 +407,6 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, /* 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, - info->irq, info->platform_data); - - if (err && err != -ENOIOCTLCMD) { - v4l2_device_unregister_subdev(sd); - sd = NULL; - } - } - error: /* If we have a client but no subdev, then something went wrong and we must unregister the client. */ @@ -428,9 +416,8 @@ error: } EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board); -struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev, +struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, struct i2c_adapter *adapter, const char *client_type, - int irq, void *platform_data, u8 addr, const unsigned short *probe_addrs) { struct i2c_board_info info; @@ -440,12 +427,10 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev, memset(&info, 0, sizeof(info)); strlcpy(info.type, client_type, sizeof(info.type)); info.addr = addr; - info.irq = irq; - info.platform_data = platform_data; return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs); } -EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg); +EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev); /* Return i2c client address of v4l2_subdev. */ unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd) diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 8f81efcfcf56..ef66d2af0c57 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -569,7 +569,7 @@ static int user_to_new(struct v4l2_ext_control *c, int ret; u32 size; - ctrl->has_new = 1; + ctrl->is_new = 1; switch (ctrl->type) { case V4L2_CTRL_TYPE_INTEGER64: ctrl->val64 = c->value64; @@ -1280,8 +1280,12 @@ int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl) if (ctrl->done) continue; - for (i = 0; i < master->ncontrols; i++) - cur_to_new(master->cluster[i]); + for (i = 0; i < master->ncontrols; i++) { + if (master->cluster[i]) { + cur_to_new(master->cluster[i]); + master->cluster[i]->is_new = 1; + } + } /* Skip button controls and read-only controls. */ if (ctrl->type == V4L2_CTRL_TYPE_BUTTON || @@ -1340,12 +1344,15 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) ctrl = ref->ctrl; memset(qc, 0, sizeof(*qc)); - qc->id = ctrl->id; + if (id >= V4L2_CID_PRIVATE_BASE) + qc->id = id; + else + qc->id = ctrl->id; strlcpy(qc->name, ctrl->name, sizeof(qc->name)); qc->minimum = ctrl->minimum; qc->maximum = ctrl->maximum; qc->default_value = ctrl->default_value; - if (qc->type == V4L2_CTRL_TYPE_MENU) + if (ctrl->type == V4L2_CTRL_TYPE_MENU) qc->step = 1; else qc->step = ctrl->step; @@ -1645,7 +1652,7 @@ static int try_or_set_control_cluster(struct v4l2_ctrl *master, bool set) if (ctrl == NULL) continue; - if (ctrl->has_new) { + if (ctrl->is_new) { /* Double check this: it may have changed since the last check in try_or_set_ext_ctrls(). */ if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) @@ -1719,13 +1726,13 @@ static int try_or_set_ext_ctrls(struct v4l2_ctrl_handler *hdl, v4l2_ctrl_lock(ctrl); - /* Reset the 'has_new' flags of the cluster */ + /* Reset the 'is_new' flags of the cluster */ for (j = 0; j < master->ncontrols; j++) if (master->cluster[j]) - master->cluster[j]->has_new = 0; + master->cluster[j]->is_new = 0; /* Copy the new caller-supplied control values. - user_to_new() sets 'has_new' to 1. */ + user_to_new() sets 'is_new' to 1. */ ret = cluster_walk(i, cs, helpers, user_to_new); if (!ret) @@ -1820,15 +1827,18 @@ static int set_ctrl(struct v4l2_ctrl *ctrl, s32 *val) int ret; int i; + if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) + return -EACCES; + v4l2_ctrl_lock(ctrl); - /* Reset the 'has_new' flags of the cluster */ + /* Reset the 'is_new' flags of the cluster */ for (i = 0; i < master->ncontrols; i++) if (master->cluster[i]) - master->cluster[i]->has_new = 0; + master->cluster[i]->is_new = 0; ctrl->val = *val; - ctrl->has_new = 1; + ctrl->is_new = 1; ret = try_or_set_control_cluster(master, false); if (!ret) ret = try_or_set_control_cluster(master, true); diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 359e23290a7e..341764a3a990 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -419,6 +419,10 @@ static int get_index(struct video_device *vdev) * The registration code assigns minor numbers and device node numbers * based on the requested type and registers the new device node with * the kernel. + * + * This function assumes that struct video_device was zeroed when it + * was allocated and does not contain any stale date. + * * An error is returned if no free minor or device node number could be * found, or if the registration of the device node failed. * @@ -440,7 +444,6 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, int minor_offset = 0; int minor_cnt = VIDEO_NUM_DEVICES; const char *name_base; - void *priv = vdev->dev.p; /* A minor value of -1 marks this video device as never having been registered */ @@ -559,10 +562,6 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, } /* Part 4: register the device with sysfs */ - memset(&vdev->dev, 0, sizeof(vdev->dev)); - /* The memset above cleared the device's device_private, so - put back the copy we made earlier. */ - vdev->dev.p = priv; vdev->dev.class = &video_class; vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor); if (vdev->parent) diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index 7fe6f92af480..ce64fe16bc60 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -100,6 +100,7 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) is a platform bus, then it is never deleted. */ if (client) i2c_unregister_device(client); + continue; } #endif #if defined(CONFIG_SPI) @@ -108,6 +109,7 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) if (spi) spi_unregister_device(spi); + continue; } #endif } @@ -126,11 +128,19 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, WARN_ON(sd->v4l2_dev != NULL); if (!try_module_get(sd->owner)) return -ENODEV; + sd->v4l2_dev = v4l2_dev; + if (sd->internal_ops && sd->internal_ops->registered) { + err = sd->internal_ops->registered(sd); + if (err) + return err; + } /* This just returns 0 if either of the two args is NULL */ err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler); - if (err) + if (err) { + if (sd->internal_ops && sd->internal_ops->unregistered) + sd->internal_ops->unregistered(sd); return err; - sd->v4l2_dev = v4l2_dev; + } spin_lock(&v4l2_dev->lock); list_add_tail(&sd->list, &v4l2_dev->subdevs); spin_unlock(&v4l2_dev->lock); @@ -146,6 +156,8 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) spin_lock(&sd->v4l2_dev->lock); list_del(&sd->list); spin_unlock(&sd->v4l2_dev->lock); + if (sd->internal_ops && sd->internal_ops->unregistered) + sd->internal_ops->unregistered(sd); sd->v4l2_dev = NULL; module_put(sd->owner); } diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 7e47f15f350d..f51327ef6757 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -1659,20 +1659,24 @@ static long __video_do_ioctl(struct file *file, { struct v4l2_dbg_register *p = arg; - if (!capable(CAP_SYS_ADMIN)) - ret = -EPERM; - else if (ops->vidioc_g_register) - ret = ops->vidioc_g_register(file, fh, p); + if (ops->vidioc_g_register) { + if (!capable(CAP_SYS_ADMIN)) + ret = -EPERM; + else + ret = ops->vidioc_g_register(file, fh, p); + } break; } case VIDIOC_DBG_S_REGISTER: { struct v4l2_dbg_register *p = arg; - if (!capable(CAP_SYS_ADMIN)) - ret = -EPERM; - else if (ops->vidioc_s_register) - ret = ops->vidioc_s_register(file, fh, p); + if (ops->vidioc_s_register) { + if (!capable(CAP_SYS_ADMIN)) + ret = -EPERM; + else + ret = ops->vidioc_s_register(file, fh, p); + } break; } #endif diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 019ee206cbee..fa35639d0c15 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -937,6 +937,7 @@ static void w9966_term(struct w9966 *cam) parport_unregister_device(cam->pdev); w9966_set_state(cam, W9966_STATE_PDEV, 0); } + memset(cam, 0, sizeof(*cam)); } diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 9cdc3bb15b15..9f2bac519647 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -1041,7 +1041,7 @@ zr36057_init (struct zoran *zr) /* allocate memory *before* doing anything to the hardware * in case allocation fails */ zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL); - zr->video_dev = kmalloc(sizeof(struct video_device), GFP_KERNEL); + zr->video_dev = video_device_alloc(); if (!zr->stat_com || !zr->video_dev) { dprintk(1, KERN_ERR diff --git a/drivers/staging/lirc/TODO.lirc_zilog b/drivers/staging/lirc/TODO.lirc_zilog index 6aa312df4018..2d0263f07937 100644 --- a/drivers/staging/lirc/TODO.lirc_zilog +++ b/drivers/staging/lirc/TODO.lirc_zilog @@ -1,13 +1,37 @@ -The binding between hdpvr and lirc_zilog is currently disabled, +1. Both ir-kbd-i2c and lirc_zilog provide support for RX events. +The 'tx_only' lirc_zilog module parameter will allow ir-kbd-i2c +and lirc_zilog to coexist in the kernel, if the user requires such a set-up. +However the IR unit will not work well without coordination between the +two modules. A shared mutex, for transceiver access locking, needs to be +supplied by bridge drivers, in struct IR_i2_init_data, to both ir-kbd-i2c +and lirc_zilog, before they will coexist usefully. This should be fixed +before moving out of staging. + +2. References and locking need careful examination. For cx18 and ivtv PCI +cards, which are not easily "hot unplugged", the imperfect state of reference +counting and locking is acceptable if not correct. For USB connected units +like HD PVR, PVR USB2, HVR-1900, and HVR1950, the likelyhood of an Ooops on +unplug is probably great. Proper reference counting and locking needs to be +implemented before this module is moved out of staging. + +3. The binding between hdpvr and lirc_zilog is currently disabled, due to an OOPS reported a few years ago when both the hdpvr and cx18 drivers were loaded in his system. More details can be seen at: http://www.mail-archive.com/linux-media@vger.kernel.org/msg09163.html More tests need to be done, in order to fix the reported issue. -There's a conflict between ir-kbd-i2c: Both provide support for RX events. -Such conflict needs to be fixed, before moving it out of staging. +4. In addition to providing a shared mutex for transceiver access +locking, bridge drivers, if able, should provide a chip reset() callback +to lirc_zilog via struct IR_i2c_init_data. cx18 and ivtv already have routines +to perform Z8 chip resets via GPIO manipulations. This will allow lirc_zilog +to bring the chip back to normal when it hangs, in the same places the +original lirc_pvr150 driver code does. This is not strictly needed, so it +is not required to move lirc_zilog out of staging. + +5. Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed +and installed on Hauppauge products. When working on either module, developers +must consider at least the following bridge drivers which mention an IR Rx unit +at address 0x71 (indicative of a Z8): -The way I2C probe works, it will try to register the driver twice, one -for RX and another for TX. The logic needs to be fixed to avoid such -issue. + ivtv cx18 hdpvr pvrusb2 bt8xx cx88 saa7134 diff --git a/drivers/staging/lirc/lirc_imon.c b/drivers/staging/lirc/lirc_imon.c index 0da6b9518af9..235cab0eb087 100644 --- a/drivers/staging/lirc/lirc_imon.c +++ b/drivers/staging/lirc/lirc_imon.c @@ -447,6 +447,7 @@ static ssize_t vfd_write(struct file *file, const char *buf, exit: mutex_unlock(&context->ctx_lock); + kfree(data_buf); return (!retval) ? n_bytes : retval; } diff --git a/drivers/staging/lirc/lirc_it87.c b/drivers/staging/lirc/lirc_it87.c index 929ae5795467..5938616f3e8f 100644 --- a/drivers/staging/lirc/lirc_it87.c +++ b/drivers/staging/lirc/lirc_it87.c @@ -232,6 +232,7 @@ static ssize_t lirc_write(struct file *file, const char *buf, i++; } terminate_send(tx_buf[i - 1]); + kfree(tx_buf); return n; } diff --git a/drivers/staging/lirc/lirc_parallel.c b/drivers/staging/lirc/lirc_parallel.c index dfd2c447e67d..3a9c09881b2b 100644 --- a/drivers/staging/lirc/lirc_parallel.c +++ b/drivers/staging/lirc/lirc_parallel.c @@ -376,6 +376,7 @@ static ssize_t lirc_write(struct file *filep, const char *buf, size_t n, unsigned long flags; int counttimer; int *wbuf; + ssize_t ret; if (!is_claimed) return -EBUSY; @@ -393,8 +394,10 @@ static ssize_t lirc_write(struct file *filep, const char *buf, size_t n, if (timer == 0) { /* try again if device is ready */ timer = init_lirc_timer(); - if (timer == 0) - return -EIO; + if (timer == 0) { + ret = -EIO; + goto out; + } } /* adjust values from usecs */ @@ -420,7 +423,8 @@ static ssize_t lirc_write(struct file *filep, const char *buf, size_t n, if (check_pselecd && (in(1) & LP_PSELECD)) { lirc_off(); local_irq_restore(flags); - return -EIO; + ret = -EIO; + goto out; } } while (counttimer < wbuf[i]); i++; @@ -436,7 +440,8 @@ static ssize_t lirc_write(struct file *filep, const char *buf, size_t n, level = newlevel; if (check_pselecd && (in(1) & LP_PSELECD)) { local_irq_restore(flags); - return -EIO; + ret = -EIO; + goto out; } } while (counttimer < wbuf[i]); i++; @@ -445,7 +450,11 @@ static ssize_t lirc_write(struct file *filep, const char *buf, size_t n, #else /* place code that handles write without external timer here */ #endif - return n; + ret = n; +out: + kfree(wbuf); + + return ret; } static unsigned int lirc_poll(struct file *file, poll_table *wait) diff --git a/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c index 998485ebdbce..925eabe14854 100644 --- a/drivers/staging/lirc/lirc_sasem.c +++ b/drivers/staging/lirc/lirc_sasem.c @@ -448,6 +448,7 @@ static ssize_t vfd_write(struct file *file, const char *buf, exit: mutex_unlock(&context->ctx_lock); + kfree(data_buf); return (!retval) ? n_bytes : retval; } diff --git a/drivers/staging/lirc/lirc_serial.c b/drivers/staging/lirc/lirc_serial.c index 9bcf149c4260..1c3099b388e0 100644 --- a/drivers/staging/lirc/lirc_serial.c +++ b/drivers/staging/lirc/lirc_serial.c @@ -966,7 +966,7 @@ static ssize_t lirc_write(struct file *file, const char *buf, if (n % sizeof(int) || count % 2 == 0) return -EINVAL; wbuf = memdup_user(buf, n); - if (PTR_ERR(wbuf)) + if (IS_ERR(wbuf)) return PTR_ERR(wbuf); spin_lock_irqsave(&hardware[type].lock, flags); if (type == LIRC_IRDEO) { @@ -981,6 +981,7 @@ static ssize_t lirc_write(struct file *file, const char *buf, } off(); spin_unlock_irqrestore(&hardware[type].lock, flags); + kfree(wbuf); return n; } diff --git a/drivers/staging/lirc/lirc_sir.c b/drivers/staging/lirc/lirc_sir.c index c553ab626238..76be7b8c6209 100644 --- a/drivers/staging/lirc/lirc_sir.c +++ b/drivers/staging/lirc/lirc_sir.c @@ -330,6 +330,7 @@ static ssize_t lirc_write(struct file *file, const char *buf, size_t n, /* enable receiver */ Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE; #endif + kfree(tx_buf); return count; } diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c index ad29bb1275ab..3fe5f4160194 100644 --- a/drivers/staging/lirc/lirc_zilog.c +++ b/drivers/staging/lirc/lirc_zilog.c @@ -20,6 +20,9 @@ * * parts are cut&pasted from the lirc_i2c.c driver * + * Numerous changes updating lirc_zilog.c in kernel 2.6.38 and later are + * Copyright (C) 2011 Andy Walls <awalls@md.metrocast.net> + * * 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 @@ -60,38 +63,44 @@ #include <media/lirc_dev.h> #include <media/lirc.h> -struct IR { - struct lirc_driver l; - - /* Device info */ - struct mutex ir_lock; - int open; - bool is_hdpvr; - +struct IR_rx { /* RX device */ - struct i2c_client c_rx; - int have_rx; + struct i2c_client *c; /* RX device buffer & lock */ struct lirc_buffer buf; struct mutex buf_lock; /* RX polling thread data */ - struct completion *t_notify; - struct completion *t_notify2; - int shutdown; struct task_struct *task; /* RX read data */ unsigned char b[3]; + bool hdpvr_data_fmt; +}; +struct IR_tx { /* TX device */ - struct i2c_client c_tx; + struct i2c_client *c; + + /* TX additional actions needed */ int need_boot; - int have_tx; + bool post_tx_ready_poll; +}; + +struct IR { + struct lirc_driver l; + + struct mutex ir_lock; + int open; + + struct i2c_adapter *adapter; + struct IR_rx *rx; + struct IR_tx *tx; }; /* Minor -> data mapping */ +static struct mutex ir_devices_lock; static struct IR *ir_devices[MAX_IRCTL_DEVICES]; /* Block size for IR transmitter */ @@ -124,14 +133,11 @@ static struct mutex tx_data_lock; #define zilog_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, \ ## args) #define zilog_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) - -#define ZILOG_HAUPPAUGE_IR_RX_NAME "Zilog/Hauppauge IR RX" -#define ZILOG_HAUPPAUGE_IR_TX_NAME "Zilog/Hauppauge IR TX" +#define zilog_info(s, args...) printk(KERN_INFO KBUILD_MODNAME ": " s, ## args) /* module parameters */ static int debug; /* debug output */ -static int disable_rx; /* disable RX device */ -static int disable_tx; /* disable TX device */ +static int tx_only; /* only handle the IR Tx function */ static int minor = -1; /* minor number */ #define dprintk(fmt, args...) \ @@ -150,8 +156,12 @@ static int add_to_buf(struct IR *ir) int ret; int failures = 0; unsigned char sendbuf[1] = { 0 }; + struct IR_rx *rx = ir->rx; - if (lirc_buffer_full(&ir->buf)) { + if (rx == NULL) + return -ENXIO; + + if (lirc_buffer_full(&rx->buf)) { dprintk("buffer overflow\n"); return -EOVERFLOW; } @@ -161,17 +171,25 @@ static int add_to_buf(struct IR *ir) * data and we have space */ do { + if (kthread_should_stop()) + return -ENODATA; + /* * Lock i2c bus for the duration. RX/TX chips interfere so * this is worth it */ mutex_lock(&ir->ir_lock); + if (kthread_should_stop()) { + mutex_unlock(&ir->ir_lock); + return -ENODATA; + } + /* * Send random "poll command" (?) Windows driver does this * and it is a good point to detect chip failure. */ - ret = i2c_master_send(&ir->c_rx, sendbuf, 1); + ret = i2c_master_send(rx->c, sendbuf, 1); if (ret != 1) { zilog_error("i2c_master_send failed with %d\n", ret); if (failures >= 3) { @@ -186,45 +204,53 @@ static int add_to_buf(struct IR *ir) "trying reset\n"); set_current_state(TASK_UNINTERRUPTIBLE); + if (kthread_should_stop()) { + mutex_unlock(&ir->ir_lock); + return -ENODATA; + } schedule_timeout((100 * HZ + 999) / 1000); - ir->need_boot = 1; + ir->tx->need_boot = 1; ++failures; mutex_unlock(&ir->ir_lock); continue; } - ret = i2c_master_recv(&ir->c_rx, keybuf, sizeof(keybuf)); + if (kthread_should_stop()) { + mutex_unlock(&ir->ir_lock); + return -ENODATA; + } + ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf)); mutex_unlock(&ir->ir_lock); if (ret != sizeof(keybuf)) { zilog_error("i2c_master_recv failed with %d -- " "keeping last read buffer\n", ret); } else { - ir->b[0] = keybuf[3]; - ir->b[1] = keybuf[4]; - ir->b[2] = keybuf[5]; - dprintk("key (0x%02x/0x%02x)\n", ir->b[0], ir->b[1]); + rx->b[0] = keybuf[3]; + rx->b[1] = keybuf[4]; + rx->b[2] = keybuf[5]; + dprintk("key (0x%02x/0x%02x)\n", rx->b[0], rx->b[1]); } /* key pressed ? */ - if (ir->is_hdpvr) { + if (rx->hdpvr_data_fmt) { if (got_data && (keybuf[0] == 0x80)) return 0; else if (got_data && (keybuf[0] == 0x00)) return -ENODATA; - } else if ((ir->b[0] & 0x80) == 0) + } else if ((rx->b[0] & 0x80) == 0) return got_data ? 0 : -ENODATA; /* look what we have */ - code = (((__u16)ir->b[0] & 0x7f) << 6) | (ir->b[1] >> 2); + code = (((__u16)rx->b[0] & 0x7f) << 6) | (rx->b[1] >> 2); codes[0] = (code >> 8) & 0xff; codes[1] = code & 0xff; /* return it */ - lirc_buffer_write(&ir->buf, codes); + lirc_buffer_write(&rx->buf, codes); ++got_data; - } while (!lirc_buffer_full(&ir->buf)); + } while (!lirc_buffer_full(&rx->buf)); return 0; } @@ -242,46 +268,35 @@ static int add_to_buf(struct IR *ir) static int lirc_thread(void *arg) { struct IR *ir = arg; - - if (ir->t_notify != NULL) - complete(ir->t_notify); + struct IR_rx *rx = ir->rx; dprintk("poll thread started\n"); - do { - if (ir->open) { - set_current_state(TASK_INTERRUPTIBLE); + while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); - /* - * This is ~113*2 + 24 + jitter (2*repeat gap + - * code length). We use this interval as the chip - * resets every time you poll it (bad!). This is - * therefore just sufficient to catch all of the - * button presses. It makes the remote much more - * responsive. You can see the difference by - * running irw and holding down a button. With - * 100ms, the old polling interval, you'll notice - * breaks in the repeat sequence corresponding to - * lost keypresses. - */ - schedule_timeout((260 * HZ) / 1000); - if (ir->shutdown) - break; - if (!add_to_buf(ir)) - wake_up_interruptible(&ir->buf.wait_poll); - } else { - /* if device not opened so we can sleep half a second */ - set_current_state(TASK_INTERRUPTIBLE); + /* if device not opened, we can sleep half a second */ + if (!ir->open) { schedule_timeout(HZ/2); + continue; } - } while (!ir->shutdown); - - if (ir->t_notify2 != NULL) - wait_for_completion(ir->t_notify2); - ir->task = NULL; - if (ir->t_notify != NULL) - complete(ir->t_notify); + /* + * This is ~113*2 + 24 + jitter (2*repeat gap + code length). + * We use this interval as the chip resets every time you poll + * it (bad!). This is therefore just sufficient to catch all + * of the button presses. It makes the remote much more + * responsive. You can see the difference by running irw and + * holding down a button. With 100ms, the old polling + * interval, you'll notice breaks in the repeat sequence + * corresponding to lost keypresses. + */ + schedule_timeout((260 * HZ) / 1000); + if (kthread_should_stop()) + break; + if (!add_to_buf(ir)) + wake_up_interruptible(&rx->buf.wait_poll); + } dprintk("poll thread ended\n"); return 0; @@ -299,10 +314,10 @@ static int set_use_inc(void *data) * this is completely broken code. lirc_unregister_driver() * must be possible even when the device is open */ - if (ir->c_rx.addr) - i2c_use_client(&ir->c_rx); - if (ir->c_tx.addr) - i2c_use_client(&ir->c_tx); + if (ir->rx != NULL) + i2c_use_client(ir->rx->c); + if (ir->tx != NULL) + i2c_use_client(ir->tx->c); return 0; } @@ -311,10 +326,10 @@ static void set_use_dec(void *data) { struct IR *ir = data; - if (ir->c_rx.addr) - i2c_release_client(&ir->c_rx); - if (ir->c_tx.addr) - i2c_release_client(&ir->c_tx); + if (ir->rx) + i2c_release_client(ir->rx->c); + if (ir->tx) + i2c_release_client(ir->tx->c); if (ir->l.owner != NULL) module_put(ir->l.owner); } @@ -453,7 +468,7 @@ corrupt: } /* send a block of data to the IR TX device */ -static int send_data_block(struct IR *ir, unsigned char *data_block) +static int send_data_block(struct IR_tx *tx, unsigned char *data_block) { int i, j, ret; unsigned char buf[5]; @@ -467,7 +482,7 @@ static int send_data_block(struct IR *ir, unsigned char *data_block) buf[1 + j] = data_block[i + j]; dprintk("%02x %02x %02x %02x %02x", buf[0], buf[1], buf[2], buf[3], buf[4]); - ret = i2c_master_send(&ir->c_tx, buf, tosend + 1); + ret = i2c_master_send(tx->c, buf, tosend + 1); if (ret != tosend + 1) { zilog_error("i2c_master_send failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; @@ -478,32 +493,32 @@ static int send_data_block(struct IR *ir, unsigned char *data_block) } /* send boot data to the IR TX device */ -static int send_boot_data(struct IR *ir) +static int send_boot_data(struct IR_tx *tx) { int ret; unsigned char buf[4]; /* send the boot block */ - ret = send_data_block(ir, tx_data->boot_data); + ret = send_data_block(tx, tx_data->boot_data); if (ret != 0) return ret; /* kick it off? */ buf[0] = 0x00; buf[1] = 0x20; - ret = i2c_master_send(&ir->c_tx, buf, 2); + ret = i2c_master_send(tx->c, buf, 2); if (ret != 2) { zilog_error("i2c_master_send failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; } - ret = i2c_master_send(&ir->c_tx, buf, 1); + ret = i2c_master_send(tx->c, buf, 1); if (ret != 1) { zilog_error("i2c_master_send failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; } /* Here comes the firmware version... (hopefully) */ - ret = i2c_master_recv(&ir->c_tx, buf, 4); + ret = i2c_master_recv(tx->c, buf, 4); if (ret != 4) { zilog_error("i2c_master_recv failed with %d\n", ret); return 0; @@ -543,7 +558,7 @@ static void fw_unload(void) } /* load "firmware" for the IR TX device */ -static int fw_load(struct IR *ir) +static int fw_load(struct IR_tx *tx) { int ret; unsigned int i; @@ -558,7 +573,7 @@ static int fw_load(struct IR *ir) } /* Request codeset data file */ - ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", &ir->c_tx.dev); + ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", &tx->c->dev); if (ret != 0) { zilog_error("firmware haup-ir-blaster.bin not available " "(%d)\n", ret); @@ -685,20 +700,20 @@ out: } /* initialise the IR TX device */ -static int tx_init(struct IR *ir) +static int tx_init(struct IR_tx *tx) { int ret; /* Load 'firmware' */ - ret = fw_load(ir); + ret = fw_load(tx); if (ret != 0) return ret; /* Send boot block */ - ret = send_boot_data(ir); + ret = send_boot_data(tx); if (ret != 0) return ret; - ir->need_boot = 0; + tx->need_boot = 0; /* Looks good */ return 0; @@ -714,20 +729,20 @@ static loff_t lseek(struct file *filep, loff_t offset, int orig) static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) { struct IR *ir = filep->private_data; - unsigned char buf[ir->buf.chunk_size]; + struct IR_rx *rx = ir->rx; int ret = 0, written = 0; DECLARE_WAITQUEUE(wait, current); dprintk("read called\n"); - if (ir->c_rx.addr == 0) + if (rx == NULL) return -ENODEV; - if (mutex_lock_interruptible(&ir->buf_lock)) + if (mutex_lock_interruptible(&rx->buf_lock)) return -ERESTARTSYS; - if (n % ir->buf.chunk_size) { + if (n % rx->buf.chunk_size) { dprintk("read result = -EINVAL\n"); - mutex_unlock(&ir->buf_lock); + mutex_unlock(&rx->buf_lock); return -EINVAL; } @@ -736,7 +751,7 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) * to avoid losing scan code (in case when queue is awaken somewhere * between while condition checking and scheduling) */ - add_wait_queue(&ir->buf.wait_poll, &wait); + add_wait_queue(&rx->buf.wait_poll, &wait); set_current_state(TASK_INTERRUPTIBLE); /* @@ -744,7 +759,7 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) * mode and 'copy_to_user' is happy, wait for data. */ while (written < n && ret == 0) { - if (lirc_buffer_empty(&ir->buf)) { + if (lirc_buffer_empty(&rx->buf)) { /* * According to the read(2) man page, 'written' can be * returned as less than 'n', instead of blocking @@ -764,16 +779,17 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) schedule(); set_current_state(TASK_INTERRUPTIBLE); } else { - lirc_buffer_read(&ir->buf, buf); + unsigned char buf[rx->buf.chunk_size]; + lirc_buffer_read(&rx->buf, buf); ret = copy_to_user((void *)outbuf+written, buf, - ir->buf.chunk_size); - written += ir->buf.chunk_size; + rx->buf.chunk_size); + written += rx->buf.chunk_size; } } - remove_wait_queue(&ir->buf.wait_poll, &wait); + remove_wait_queue(&rx->buf.wait_poll, &wait); set_current_state(TASK_RUNNING); - mutex_unlock(&ir->buf_lock); + mutex_unlock(&rx->buf_lock); dprintk("read result = %s (%d)\n", ret ? "-EFAULT" : "OK", ret); @@ -782,7 +798,7 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) } /* send a keypress to the IR TX device */ -static int send_code(struct IR *ir, unsigned int code, unsigned int key) +static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key) { unsigned char data_block[TX_BLOCK_SIZE]; unsigned char buf[2]; @@ -799,26 +815,26 @@ static int send_code(struct IR *ir, unsigned int code, unsigned int key) return ret; /* Send the data block */ - ret = send_data_block(ir, data_block); + ret = send_data_block(tx, data_block); if (ret != 0) return ret; /* Send data block length? */ buf[0] = 0x00; buf[1] = 0x40; - ret = i2c_master_send(&ir->c_tx, buf, 2); + ret = i2c_master_send(tx->c, buf, 2); if (ret != 2) { zilog_error("i2c_master_send failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; } - ret = i2c_master_send(&ir->c_tx, buf, 1); + ret = i2c_master_send(tx->c, buf, 1); if (ret != 1) { zilog_error("i2c_master_send failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; } /* Send finished download? */ - ret = i2c_master_recv(&ir->c_tx, buf, 1); + ret = i2c_master_recv(tx->c, buf, 1); if (ret != 1) { zilog_error("i2c_master_recv failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; @@ -832,7 +848,7 @@ static int send_code(struct IR *ir, unsigned int code, unsigned int key) /* Send prepare command? */ buf[0] = 0x00; buf[1] = 0x80; - ret = i2c_master_send(&ir->c_tx, buf, 2); + ret = i2c_master_send(tx->c, buf, 2); if (ret != 2) { zilog_error("i2c_master_send failed with %d\n", ret); return ret < 0 ? ret : -EFAULT; @@ -843,7 +859,7 @@ static int send_code(struct IR *ir, unsigned int code, unsigned int key) * last i2c_master_recv always fails with a -5, so for now, we're * going to skip this whole mess and say we're done on the HD PVR */ - if (ir->is_hdpvr) { + if (!tx->post_tx_ready_poll) { dprintk("sent code %u, key %u\n", code, key); return 0; } @@ -857,7 +873,7 @@ static int send_code(struct IR *ir, unsigned int code, unsigned int key) for (i = 0; i < 20; ++i) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((50 * HZ + 999) / 1000); - ret = i2c_master_send(&ir->c_tx, buf, 1); + ret = i2c_master_send(tx->c, buf, 1); if (ret == 1) break; dprintk("NAK expected: i2c_master_send " @@ -870,7 +886,7 @@ static int send_code(struct IR *ir, unsigned int code, unsigned int key) } /* Seems to be an 'ok' response */ - i = i2c_master_recv(&ir->c_tx, buf, 1); + i = i2c_master_recv(tx->c, buf, 1); if (i != 1) { zilog_error("i2c_master_recv failed with %d\n", ret); return -EFAULT; @@ -895,10 +911,11 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, loff_t *ppos) { struct IR *ir = filep->private_data; + struct IR_tx *tx = ir->tx; size_t i; int failures = 0; - if (ir->c_tx.addr == 0) + if (tx == NULL) return -ENODEV; /* Validate user parameters */ @@ -919,15 +936,15 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, } /* Send boot data first if required */ - if (ir->need_boot == 1) { - ret = send_boot_data(ir); + if (tx->need_boot == 1) { + ret = send_boot_data(tx); if (ret == 0) - ir->need_boot = 0; + tx->need_boot = 0; } /* Send the code */ if (ret == 0) { - ret = send_code(ir, (unsigned)command >> 16, + ret = send_code(tx, (unsigned)command >> 16, (unsigned)command & 0xFFFF); if (ret == -EPROTO) { mutex_unlock(&ir->ir_lock); @@ -952,7 +969,7 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, } set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((100 * HZ + 999) / 1000); - ir->need_boot = 1; + tx->need_boot = 1; ++failures; } else i += sizeof(int); @@ -969,22 +986,23 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, static unsigned int poll(struct file *filep, poll_table *wait) { struct IR *ir = filep->private_data; + struct IR_rx *rx = ir->rx; unsigned int ret; dprintk("poll called\n"); - if (ir->c_rx.addr == 0) + if (rx == NULL) return -ENODEV; - mutex_lock(&ir->buf_lock); + mutex_lock(&rx->buf_lock); - poll_wait(filep, &ir->buf.wait_poll, wait); + poll_wait(filep, &rx->buf.wait_poll, wait); dprintk("poll result = %s\n", - lirc_buffer_empty(&ir->buf) ? "0" : "POLLIN|POLLRDNORM"); + lirc_buffer_empty(&rx->buf) ? "0" : "POLLIN|POLLRDNORM"); - ret = lirc_buffer_empty(&ir->buf) ? 0 : (POLLIN|POLLRDNORM); + ret = lirc_buffer_empty(&rx->buf) ? 0 : (POLLIN|POLLRDNORM); - mutex_unlock(&ir->buf_lock); + mutex_unlock(&rx->buf_lock); return ret; } @@ -994,10 +1012,9 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) int result; unsigned long mode, features = 0; - if (ir->c_rx.addr != 0) + features |= LIRC_CAN_SEND_PULSE; + if (ir->rx != NULL) features |= LIRC_CAN_REC_LIRCCODE; - if (ir->c_tx.addr != 0) - features |= LIRC_CAN_SEND_PULSE; switch (cmd) { case LIRC_GET_LENGTH: @@ -1024,15 +1041,9 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) result = -EINVAL; break; case LIRC_GET_SEND_MODE: - if (!(features&LIRC_CAN_SEND_MASK)) - return -ENOSYS; - result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg); break; case LIRC_SET_SEND_MODE: - if (!(features&LIRC_CAN_SEND_MASK)) - return -ENOSYS; - result = get_user(mode, (unsigned long *) arg); if (!result && mode != LIRC_MODE_PULSE) return -EINVAL; @@ -1043,6 +1054,15 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) return result; } +/* ir_devices_lock must be held */ +static struct IR *find_ir_device_by_minor(unsigned int minor) +{ + if (minor >= MAX_IRCTL_DEVICES) + return NULL; + + return ir_devices[minor]; +} + /* * Open the IR device. Get hold of our IR structure and * stash it in private_data for the file @@ -1051,15 +1071,15 @@ static int open(struct inode *node, struct file *filep) { struct IR *ir; int ret; + unsigned int minor = MINOR(node->i_rdev); /* find our IR struct */ - unsigned minor = MINOR(node->i_rdev); - if (minor >= MAX_IRCTL_DEVICES) { - dprintk("minor %d: open result = -ENODEV\n", - minor); + mutex_lock(&ir_devices_lock); + ir = find_ir_device_by_minor(minor); + mutex_unlock(&ir_devices_lock); + + if (ir == NULL) return -ENODEV; - } - ir = ir_devices[minor]; /* increment in use count */ mutex_lock(&ir->ir_lock); @@ -1106,7 +1126,6 @@ static struct lirc_driver lirc_template = { static int ir_remove(struct i2c_client *client); static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id); -static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg); #define ID_FLAG_TX 0x01 #define ID_FLAG_HDPVR 0x02 @@ -1126,7 +1145,6 @@ static struct i2c_driver driver = { }, .probe = ir_probe, .remove = ir_remove, - .command = ir_command, .id_table = ir_transceiver_id, }; @@ -1144,214 +1162,253 @@ static const struct file_operations lirc_fops = { .release = close }; -static int ir_remove(struct i2c_client *client) +static void destroy_rx_kthread(struct IR_rx *rx) { - struct IR *ir = i2c_get_clientdata(client); + /* end up polling thread */ + if (rx != NULL && !IS_ERR_OR_NULL(rx->task)) { + kthread_stop(rx->task); + rx->task = NULL; + } +} - mutex_lock(&ir->ir_lock); +/* ir_devices_lock must be held */ +static int add_ir_device(struct IR *ir) +{ + int i; - if (ir->have_rx || ir->have_tx) { - DECLARE_COMPLETION(tn); - DECLARE_COMPLETION(tn2); - - /* end up polling thread */ - if (ir->task && !IS_ERR(ir->task)) { - ir->t_notify = &tn; - ir->t_notify2 = &tn2; - ir->shutdown = 1; - wake_up_process(ir->task); - complete(&tn2); - wait_for_completion(&tn); - ir->t_notify = NULL; - ir->t_notify2 = NULL; + for (i = 0; i < MAX_IRCTL_DEVICES; i++) + if (ir_devices[i] == NULL) { + ir_devices[i] = ir; + break; } - } else { - mutex_unlock(&ir->ir_lock); - zilog_error("%s: detached from something we didn't " - "attach to\n", __func__); - return -ENODEV; + return i == MAX_IRCTL_DEVICES ? -ENOMEM : i; +} + +/* ir_devices_lock must be held */ +static void del_ir_device(struct IR *ir) +{ + int i; + + for (i = 0; i < MAX_IRCTL_DEVICES; i++) + if (ir_devices[i] == ir) { + ir_devices[i] = NULL; + break; + } +} + +static int ir_remove(struct i2c_client *client) +{ + struct IR *ir = i2c_get_clientdata(client); + + mutex_lock(&ir_devices_lock); + + if (ir == NULL) { + /* We destroyed everything when the first client came through */ + mutex_unlock(&ir_devices_lock); + return 0; } - /* unregister lirc driver */ - if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) { - lirc_unregister_driver(ir->l.minor); - ir_devices[ir->l.minor] = NULL; + /* Good-bye LIRC */ + lirc_unregister_driver(ir->l.minor); + + /* Good-bye Rx */ + destroy_rx_kthread(ir->rx); + if (ir->rx != NULL) { + if (ir->rx->buf.fifo_initialized) + lirc_buffer_free(&ir->rx->buf); + i2c_set_clientdata(ir->rx->c, NULL); + kfree(ir->rx); } - /* free memory */ - lirc_buffer_free(&ir->buf); - mutex_unlock(&ir->ir_lock); + /* Good-bye Tx */ + i2c_set_clientdata(ir->tx->c, NULL); + kfree(ir->tx); + + /* Good-bye IR */ + del_ir_device(ir); kfree(ir); + mutex_unlock(&ir_devices_lock); return 0; } -static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) + +/* ir_devices_lock must be held */ +static struct IR *find_ir_device_by_adapter(struct i2c_adapter *adapter) { + int i; struct IR *ir = NULL; + + for (i = 0; i < MAX_IRCTL_DEVICES; i++) + if (ir_devices[i] != NULL && + ir_devices[i]->adapter == adapter) { + ir = ir_devices[i]; + break; + } + + return ir; +} + +static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct IR *ir; struct i2c_adapter *adap = client->adapter; - char buf; int ret; - int have_rx = 0, have_tx = 0; + bool tx_probe = false; - dprintk("%s: adapter name (%s) nr %d, i2c_device_id name (%s), " - "client addr=0x%02x\n", - __func__, adap->name, adap->nr, id->name, client->addr); + dprintk("%s: %s on i2c-%d (%s), client addr=0x%02x\n", + __func__, id->name, adap->nr, adap->name, client->addr); /* - * FIXME - This probe function probes both the Tx and Rx - * addresses of the IR microcontroller. - * - * However, the I2C subsystem is passing along one I2C client at a - * time, based on matches to the ir_transceiver_id[] table above. - * The expectation is that each i2c_client address will be probed - * individually by drivers so the I2C subsystem can mark all client - * addresses as claimed or not. - * - * This probe routine causes only one of the client addresses, TX or RX, - * to be claimed. This will cause a problem if the I2C subsystem is - * subsequently triggered to probe unclaimed clients again. + * The IR receiver is at i2c address 0x71. + * The IR transmitter is at i2c address 0x70. */ - /* - * The external IR receiver is at i2c address 0x71. - * The IR transmitter is at 0x70. - */ - client->addr = 0x70; - if (!disable_tx) { - if (i2c_master_recv(client, &buf, 1) == 1) - have_tx = 1; - dprintk("probe 0x70 @ %s: %s\n", - adap->name, have_tx ? "success" : "failed"); - } + if (id->driver_data & ID_FLAG_TX) + tx_probe = true; + else if (tx_only) /* module option */ + return -ENXIO; - if (!disable_rx) { - client->addr = 0x71; - if (i2c_master_recv(client, &buf, 1) == 1) - have_rx = 1; - dprintk("probe 0x71 @ %s: %s\n", - adap->name, have_rx ? "success" : "failed"); - } + zilog_info("probing IR %s on %s (i2c-%d)\n", + tx_probe ? "Tx" : "Rx", adap->name, adap->nr); - if (!(have_rx || have_tx)) { - zilog_error("%s: no devices found\n", adap->name); - goto out_nodev; - } + mutex_lock(&ir_devices_lock); - printk(KERN_INFO "lirc_zilog: chip found with %s\n", - have_rx && have_tx ? "RX and TX" : - have_rx ? "RX only" : "TX only"); + /* Use a single struct IR instance for both the Rx and Tx functions */ + ir = find_ir_device_by_adapter(adap); + if (ir == NULL) { + ir = kzalloc(sizeof(struct IR), GFP_KERNEL); + if (ir == NULL) { + ret = -ENOMEM; + goto out_no_ir; + } + /* store for use in ir_probe() again, and open() later on */ + ret = add_ir_device(ir); + if (ret) + goto out_free_ir; + + ir->adapter = adap; + mutex_init(&ir->ir_lock); + + /* set lirc_dev stuff */ + memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); + ir->l.minor = minor; /* module option */ + ir->l.code_length = 13; + ir->l.rbuf = NULL; + ir->l.fops = &lirc_fops; + ir->l.data = ir; + ir->l.dev = &adap->dev; + ir->l.sample_rate = 0; + } - ir = kzalloc(sizeof(struct IR), GFP_KERNEL); + if (tx_probe) { + /* Set up a struct IR_tx instance */ + ir->tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL); + if (ir->tx == NULL) { + ret = -ENOMEM; + goto out_free_xx; + } - if (!ir) - goto out_nomem; + ir->tx->c = client; + ir->tx->need_boot = 1; + ir->tx->post_tx_ready_poll = + (id->driver_data & ID_FLAG_HDPVR) ? false : true; + } else { + /* Set up a struct IR_rx instance */ + ir->rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL); + if (ir->rx == NULL) { + ret = -ENOMEM; + goto out_free_xx; + } - ret = lirc_buffer_init(&ir->buf, 2, BUFLEN / 2); - if (ret) - goto out_nomem; + ret = lirc_buffer_init(&ir->rx->buf, 2, BUFLEN / 2); + if (ret) + goto out_free_xx; - mutex_init(&ir->ir_lock); - mutex_init(&ir->buf_lock); - ir->need_boot = 1; - ir->is_hdpvr = (id->driver_data & ID_FLAG_HDPVR) ? true : false; + mutex_init(&ir->rx->buf_lock); + ir->rx->c = client; + ir->rx->hdpvr_data_fmt = + (id->driver_data & ID_FLAG_HDPVR) ? true : false; - memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); - ir->l.minor = -1; + /* set lirc_dev stuff */ + ir->l.rbuf = &ir->rx->buf; + } - /* I2C attach to device */ i2c_set_clientdata(client, ir); - /* initialise RX device */ - if (have_rx) { - DECLARE_COMPLETION(tn); - memcpy(&ir->c_rx, client, sizeof(struct i2c_client)); - - ir->c_rx.addr = 0x71; - strlcpy(ir->c_rx.name, ZILOG_HAUPPAUGE_IR_RX_NAME, - I2C_NAME_SIZE); + /* Proceed only if we have the required Tx and Rx clients ready to go */ + if (ir->tx == NULL || + (ir->rx == NULL && !tx_only)) { + zilog_info("probe of IR %s on %s (i2c-%d) done. Waiting on " + "IR %s.\n", tx_probe ? "Tx" : "Rx", adap->name, + adap->nr, tx_probe ? "Rx" : "Tx"); + goto out_ok; + } + /* initialise RX device */ + if (ir->rx != NULL) { /* try to fire up polling thread */ - ir->t_notify = &tn; - ir->task = kthread_run(lirc_thread, ir, "lirc_zilog"); - if (IS_ERR(ir->task)) { - ret = PTR_ERR(ir->task); - zilog_error("lirc_register_driver: cannot run " - "poll thread %d\n", ret); - goto err; + ir->rx->task = kthread_run(lirc_thread, ir, + "zilog-rx-i2c-%d", adap->nr); + if (IS_ERR(ir->rx->task)) { + ret = PTR_ERR(ir->rx->task); + zilog_error("%s: could not start IR Rx polling thread" + "\n", __func__); + goto out_free_xx; } - wait_for_completion(&tn); - ir->t_notify = NULL; - ir->have_rx = 1; - } - - /* initialise TX device */ - if (have_tx) { - memcpy(&ir->c_tx, client, sizeof(struct i2c_client)); - ir->c_tx.addr = 0x70; - strlcpy(ir->c_tx.name, ZILOG_HAUPPAUGE_IR_TX_NAME, - I2C_NAME_SIZE); - ir->have_tx = 1; } - /* set lirc_dev stuff */ - ir->l.code_length = 13; - ir->l.rbuf = &ir->buf; - ir->l.fops = &lirc_fops; - ir->l.data = ir; - ir->l.minor = minor; - ir->l.dev = &adap->dev; - ir->l.sample_rate = 0; - /* register with lirc */ ir->l.minor = lirc_register_driver(&ir->l); if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) { - zilog_error("ir_attach: \"minor\" must be between 0 and %d " - "(%d)!\n", MAX_IRCTL_DEVICES-1, ir->l.minor); + zilog_error("%s: \"minor\" must be between 0 and %d (%d)!\n", + __func__, MAX_IRCTL_DEVICES-1, ir->l.minor); ret = -EBADRQC; - goto err; + goto out_free_thread; } - /* store this for getting back in open() later on */ - ir_devices[ir->l.minor] = ir; - /* * if we have the tx device, load the 'firmware'. We do this * after registering with lirc as otherwise hotplug seems to take * 10s to create the lirc device. */ - if (have_tx) { - /* Special TX init */ - ret = tx_init(ir); - if (ret != 0) - goto err; - } + ret = tx_init(ir->tx); + if (ret != 0) + goto out_unregister; + zilog_info("probe of IR %s on %s (i2c-%d) done. IR unit ready.\n", + tx_probe ? "Tx" : "Rx", adap->name, adap->nr); +out_ok: + mutex_unlock(&ir_devices_lock); return 0; -err: - /* undo everything, hopefully... */ - if (ir->c_rx.addr) - ir_remove(&ir->c_rx); - if (ir->c_tx.addr) - ir_remove(&ir->c_tx); - return ret; - -out_nodev: - zilog_error("no device found\n"); - return -ENODEV; - -out_nomem: - zilog_error("memory allocation failure\n"); +out_unregister: + lirc_unregister_driver(ir->l.minor); +out_free_thread: + destroy_rx_kthread(ir->rx); +out_free_xx: + if (ir->rx != NULL) { + if (ir->rx->buf.fifo_initialized) + lirc_buffer_free(&ir->rx->buf); + if (ir->rx->c != NULL) + i2c_set_clientdata(ir->rx->c, NULL); + kfree(ir->rx); + } + if (ir->tx != NULL) { + if (ir->tx->c != NULL) + i2c_set_clientdata(ir->tx->c, NULL); + kfree(ir->tx); + } +out_free_ir: + del_ir_device(ir); kfree(ir); - return -ENOMEM; -} - -static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - /* nothing */ - return 0; +out_no_ir: + zilog_error("%s: probing IR %s on %s (i2c-%d) failed with %d\n", + __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr, + ret); + mutex_unlock(&ir_devices_lock); + return ret; } static int __init zilog_init(void) @@ -1361,6 +1418,7 @@ static int __init zilog_init(void) zilog_notify("Zilog/Hauppauge IR driver initializing\n"); mutex_init(&tx_data_lock); + mutex_init(&ir_devices_lock); request_module("firmware_class"); @@ -1386,7 +1444,8 @@ module_exit(zilog_exit); MODULE_DESCRIPTION("Zilog/Hauppauge infrared transmitter driver (i2c stack)"); MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, " - "Ulrich Mueller, Stefan Jahn, Jerome Brock, Mark Weaver"); + "Ulrich Mueller, Stefan Jahn, Jerome Brock, Mark Weaver, " + "Andy Walls"); MODULE_LICENSE("GPL"); /* for compat with old name, which isn't all that accurate anymore */ MODULE_ALIAS("lirc_pvr150"); @@ -1397,8 +1456,5 @@ MODULE_PARM_DESC(minor, "Preferred minor device number"); module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Enable debugging messages"); -module_param(disable_rx, bool, 0644); -MODULE_PARM_DESC(disable_rx, "Disable the IR receiver device"); - -module_param(disable_tx, bool, 0644); -MODULE_PARM_DESC(disable_tx, "Disable the IR transmitter device"); +module_param(tx_only, bool, 0644); +MODULE_PARM_DESC(tx_only, "Only handle the IR transmit function"); diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c index 8fe017c3721f..eb9b9f1bc138 100644 --- a/drivers/staging/tm6000/tm6000-video.c +++ b/drivers/staging/tm6000/tm6000-video.c @@ -1450,29 +1450,55 @@ static struct video_device tm6000_template = { * ------------------------------------------------------------------ */ -int tm6000_v4l2_register(struct tm6000_core *dev) +static struct video_device *vdev_init(struct tm6000_core *dev, + const struct video_device + *template, const char *type_name) { - int ret = -1; struct video_device *vfd; vfd = video_device_alloc(); - if(!vfd) { + if (NULL == vfd) + return NULL; + + *vfd = *template; + vfd->v4l2_dev = &dev->v4l2_dev; + vfd->release = video_device_release; + vfd->debug = tm6000_debug; + vfd->lock = &dev->lock; + + snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); + + video_set_drvdata(vfd, dev); + return vfd; +} + +int tm6000_v4l2_register(struct tm6000_core *dev) +{ + int ret = -1; + + dev->vfd = vdev_init(dev, &tm6000_template, "video"); + + if (!dev->vfd) { + printk(KERN_INFO "%s: can't register video device\n", + dev->name); return -ENOMEM; } - dev->vfd = vfd; /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); INIT_LIST_HEAD(&dev->vidq.queued); - memcpy(dev->vfd, &tm6000_template, sizeof(*(dev->vfd))); - dev->vfd->debug = tm6000_debug; - dev->vfd->lock = &dev->lock; + ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr); - vfd->v4l2_dev = &dev->v4l2_dev; - video_set_drvdata(vfd, dev); + if (ret < 0) { + printk(KERN_INFO "%s: can't register video device\n", + dev->name); + return ret; + } + + printk(KERN_INFO "%s: registered device %s\n", + dev->name, video_device_node_name(dev->vfd)); - ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr); printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret); return ret; } |