Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46671b03 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6:
  [media] soc_camera: preserve const attribute
  [media] uvc_entity: initialize return value
  [media] media: Fix media device minor registration
  [media] Make nchg variable signed because the code compares this variable against negative values
  [media] omap3isp: fix compiler warning
  [media] v4l: Fix media_entity_to_video_device macro argument name
  [media] ivtv: Internally separate encoder & decoder standard setting
  [media] ivtvfb: Add sanity check to ivtvfb_pan_display()
  [media] ivtvfb: use display information in info not in var for panning
  [media] ivtv: Make two ivtv_msleep_timeout calls uninterruptable
  [media] anysee: return EOPNOTSUPP for unsupported I2C messages
  [media] gspca - ov519: Set the default frame rate to 15 fps
  [media] gspca - stv06xx: Set a lower default value of gain for hdcs sensors
  [media] gspca: Remove coarse_expo_autogain.h
  [media] gspca - ov519: Change the ovfx2 bulk transfer size
  [media] gspca - ov519: Fix a regression for ovfx2 webcams
parents 18367c0e d364ee4f
Loading
Loading
Loading
Loading
+11 −6
Original line number Original line Diff line number Diff line
@@ -60,8 +60,6 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
	int act_len, ret;
	int act_len, ret;
	u8 buf[64];
	u8 buf[64];


	if (slen > sizeof(buf))
		slen = sizeof(buf);
	memcpy(&buf[0], sbuf, slen);
	memcpy(&buf[0], sbuf, slen);
	buf[60] = state->seq++;
	buf[60] = state->seq++;


@@ -180,30 +178,37 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
{
{
	struct dvb_usb_device *d = i2c_get_adapdata(adap);
	struct dvb_usb_device *d = i2c_get_adapdata(adap);
	int ret = 0, inc, i = 0;
	int ret = 0, inc, i = 0;
	u8 buf[52]; /* 4 + 48 (I2C WR USB command header + I2C WR max) */


	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
		return -EAGAIN;
		return -EAGAIN;


	while (i < num) {
	while (i < num) {
		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
			u8 buf[6];
			if (msg[i].len > 2 || msg[i+1].len > 60) {
				ret = -EOPNOTSUPP;
				break;
			}
			buf[0] = CMD_I2C_READ;
			buf[0] = CMD_I2C_READ;
			buf[1] = (msg[i].addr << 1) | 0x01;
			buf[1] = (msg[i].addr << 1) | 0x01;
			buf[2] = msg[i].buf[0];
			buf[2] = msg[i].buf[0];
			buf[3] = msg[i].buf[1];
			buf[3] = msg[i].buf[1];
			buf[4] = msg[i].len-1;
			buf[4] = msg[i].len-1;
			buf[5] = msg[i+1].len;
			buf[5] = msg[i+1].len;
			ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf,
			ret = anysee_ctrl_msg(d, buf, 6, msg[i+1].buf,
				msg[i+1].len);
				msg[i+1].len);
			inc = 2;
			inc = 2;
		} else {
		} else {
			u8 buf[4+msg[i].len];
			if (msg[i].len > 48) {
				ret = -EOPNOTSUPP;
				break;
			}
			buf[0] = CMD_I2C_WRITE;
			buf[0] = CMD_I2C_WRITE;
			buf[1] = (msg[i].addr << 1);
			buf[1] = (msg[i].addr << 1);
			buf[2] = msg[i].len;
			buf[2] = msg[i].len;
			buf[3] = 0x01;
			buf[3] = 0x01;
			memcpy(&buf[4], msg[i].buf, msg[i].len);
			memcpy(&buf[4], msg[i].buf, msg[i].len);
			ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
			ret = anysee_ctrl_msg(d, buf, 4 + msg[i].len, NULL, 0);
			inc = 1;
			inc = 1;
		}
		}
		if (ret)
		if (ret)
+2 −2
Original line number Original line Diff line number Diff line
@@ -213,14 +213,14 @@ int __must_check media_devnode_register(struct media_devnode *mdev)


	/* Part 1: Find a free minor number */
	/* Part 1: Find a free minor number */
	mutex_lock(&media_devnode_lock);
	mutex_lock(&media_devnode_lock);
	minor = find_next_zero_bit(media_devnode_nums, 0, MEDIA_NUM_DEVICES);
	minor = find_next_zero_bit(media_devnode_nums, MEDIA_NUM_DEVICES, 0);
	if (minor == MEDIA_NUM_DEVICES) {
	if (minor == MEDIA_NUM_DEVICES) {
		mutex_unlock(&media_devnode_lock);
		mutex_unlock(&media_devnode_lock);
		printk(KERN_ERR "could not get a free minor\n");
		printk(KERN_ERR "could not get a free minor\n");
		return -ENFILE;
		return -ENFILE;
	}
	}


	set_bit(mdev->minor, media_devnode_nums);
	set_bit(minor, media_devnode_nums);
	mutex_unlock(&media_devnode_lock);
	mutex_unlock(&media_devnode_lock);


	mdev->minor = minor;
	mdev->minor = minor;
+0 −116
Original line number Original line Diff line number Diff line
/*
 * Auto gain algorithm for camera's with a coarse exposure control
 *
 * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/* Autogain + exposure algorithm for cameras with a coarse exposure control
   (usually this means we can only control the clockdiv to change exposure)
   As changing the clockdiv so that the fps drops from 30 to 15 fps for
   example, will lead to a huge exposure change (it effectively doubles),
   this algorithm normally tries to only adjust the gain (between 40 and
   80 %) and if that does not help, only then changes exposure. This leads
   to a much more stable image then using the knee algorithm which at
   certain points of the knee graph will only try to adjust exposure,
   which leads to oscilating as one exposure step is huge.

   Note this assumes that the sd struct for the cam in question has
   exp_too_high_cnt and exp_too_high_cnt int members for use by this function.

   Returns 0 if no changes were made, 1 if the gain and or exposure settings
   where changed. */
static int gspca_coarse_grained_expo_autogain(struct gspca_dev *gspca_dev,
	int avg_lum, int desired_avg_lum, int deadzone)
{
	int i, steps, gain, orig_gain, exposure, orig_exposure;
	int gain_low, gain_high;
	const struct ctrl *gain_ctrl = NULL;
	const struct ctrl *exposure_ctrl = NULL;
	struct sd *sd = (struct sd *) gspca_dev;
	int retval = 0;

	for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
		if (gspca_dev->ctrl_dis & (1 << i))
			continue;
		if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN)
			gain_ctrl = &gspca_dev->sd_desc->ctrls[i];
		if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE)
			exposure_ctrl = &gspca_dev->sd_desc->ctrls[i];
	}
	if (!gain_ctrl || !exposure_ctrl) {
		PDEBUG(D_ERR, "Error: gspca_coarse_grained_expo_autogain "
			"called on cam without gain or exposure");
		return 0;
	}

	if (gain_ctrl->get(gspca_dev, &gain) ||
	    exposure_ctrl->get(gspca_dev, &exposure))
		return 0;

	orig_gain = gain;
	orig_exposure = exposure;
	gain_low =
		(gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 2;
	gain_low += gain_ctrl->qctrl.minimum;
	gain_high =
		(gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 4;
	gain_high += gain_ctrl->qctrl.minimum;

	/* If we are of a multiple of deadzone, do multiple steps to reach the
	   desired lumination fast (with the risc of a slight overshoot) */
	steps = (desired_avg_lum - avg_lum) / deadzone;

	PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
		avg_lum, desired_avg_lum, steps);

	if ((gain + steps) > gain_high &&
	    sd->exposure < exposure_ctrl->qctrl.maximum) {
		gain = gain_high;
		sd->exp_too_low_cnt++;
	} else if ((gain + steps) < gain_low &&
		   sd->exposure > exposure_ctrl->qctrl.minimum) {
		gain = gain_low;
		sd->exp_too_high_cnt++;
	} else {
		gain += steps;
		if (gain > gain_ctrl->qctrl.maximum)
			gain = gain_ctrl->qctrl.maximum;
		else if (gain < gain_ctrl->qctrl.minimum)
			gain = gain_ctrl->qctrl.minimum;
		sd->exp_too_high_cnt = 0;
		sd->exp_too_low_cnt = 0;
	}

	if (sd->exp_too_high_cnt > 3) {
		exposure--;
		sd->exp_too_high_cnt = 0;
	} else if (sd->exp_too_low_cnt > 3) {
		exposure++;
		sd->exp_too_low_cnt = 0;
	}

	if (gain != orig_gain) {
		gain_ctrl->set(gspca_dev, gain);
		retval = 1;
	}
	if (exposure != orig_exposure) {
		exposure_ctrl->set(gspca_dev, exposure);
		retval = 1;
	}

	return retval;
}
+4 −4
Original line number Original line Diff line number Diff line
@@ -609,7 +609,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
 * buffers, there are some pretty strict real time constraints for
 * buffers, there are some pretty strict real time constraints for
 * isochronous transfer for larger frame sizes).
 * isochronous transfer for larger frame sizes).
 */
 */
/*jfm: this value works well for 1600x1200, but not 800x600 - see isoc_init */
/*jfm: this value does not work for 800x600 - see isoc_init */
#define OVFX2_BULK_SIZE (13 * 4096)
#define OVFX2_BULK_SIZE (13 * 4096)


/* I2C registers */
/* I2C registers */
@@ -3307,6 +3307,7 @@ static int sd_config(struct gspca_dev *gspca_dev,


	gspca_dev->cam.ctrls = sd->ctrls;
	gspca_dev->cam.ctrls = sd->ctrls;
	sd->quality = QUALITY_DEF;
	sd->quality = QUALITY_DEF;
	sd->frame_rate = 15;


	return 0;
	return 0;
}
}
@@ -3469,7 +3470,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
				ARRAY_SIZE(init_519_ov7660));
				ARRAY_SIZE(init_519_ov7660));
		write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660));
		write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660));
		sd->gspca_dev.curr_mode = 1;	/* 640x480 */
		sd->gspca_dev.curr_mode = 1;	/* 640x480 */
		sd->frame_rate = 15;
		ov519_set_mode(sd);
		ov519_set_mode(sd);
		ov519_set_fr(sd);
		ov519_set_fr(sd);
		sd->ctrls[COLORS].max = 4;	/* 0..4 */
		sd->ctrls[COLORS].max = 4;	/* 0..4 */
@@ -3511,7 +3511,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)


	switch (sd->bridge) {
	switch (sd->bridge) {
	case BRIDGE_OVFX2:
	case BRIDGE_OVFX2:
		if (gspca_dev->width == 1600)
		if (gspca_dev->width != 800)
			gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE;
			gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE;
		else
		else
			gspca_dev->cam.bulk_size = 7 * 4096;
			gspca_dev->cam.bulk_size = 7 * 4096;
@@ -4478,7 +4478,7 @@ static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev,
	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);


	/* A short read signals EOF */
	/* A short read signals EOF */
	if (len < OVFX2_BULK_SIZE) {
	if (len < gspca_dev->cam.bulk_size) {
		/* If the frame is short, and it is one of the first ones
		/* If the frame is short, and it is one of the first ones
		   the sensor and bridge are still syncing, so drop it. */
		   the sensor and bridge are still syncing, so drop it. */
		if (sd->first_frame) {
		if (sd->first_frame) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -60,7 +60,7 @@ struct sd {


	u32 pktsz;			/* (used by pkt_scan) */
	u32 pktsz;			/* (used by pkt_scan) */
	u16 npkt;
	u16 npkt;
	u8 nchg;
	s8 nchg;
	s8 short_mark;
	s8 short_mark;


	u8 quality;			/* image quality */
	u8 quality;			/* image quality */
Loading