Merge branch 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (87 commits)
  V4L/DVB: ivtv: Timing tweaks and code re-order to try and improve stability
  V4L/DVB: ivtv: Avoid accidental video standard change
  V4L/DVB: ivtvfb : Module load / unload fixes
  V4L/DVB: cx2341x: Report correct temporal setting for log-status
  V4L/DVB: cx18, cx23885, v4l2 doc, MAINTAINERS: Update Andy Walls' email address
  V4L/DVB: drivers/media: Eliminate a NULL pointer dereference
  V4L/DVB: dvb-core: Fix ULE decapsulation bug
  V4L/DVB: Bug fix: make IR work again for dm1105
  V4L/DVB: media/IR: nec-decoder needs to select BITREV
  V4L/DVB: video/saa7134: change dprintk() to i2cdprintk()
  V4L/DVB: video/saa7134: remove duplicate break
  V4L/DVB: IR/imon: add auto-config for 0xffdc rf device
  V4L/DVB: IR/imon: clean up usage of bools
  V4L/DVB: em28xx: remove unneeded null checks
  V4L/DVB: ngene: remove unused #include <linux/version.h>
  V4L/DVB: ak881x needs slab.h
  V4L/DVB: FusionHDTV: Use quick reads for I2C IR device probing
  V4L/DVB: Technotrend S2-3200 ships with a TT 1500 remote
  V4L/DVB: drivers/media: Use kzalloc
  V4L/DVB: m920x: Select simple tuner
  ...
This commit is contained in:
Linus Torvalds 2010-06-04 15:38:12 -07:00
commit e620d1e39a
139 changed files with 2131 additions and 1608 deletions

View File

@ -58,7 +58,7 @@ MPEG stream embedded, sliced VBI data format in this specification.
</contrib> </contrib>
<affiliation> <affiliation>
<address> <address>
<email>awalls@radix.net</email> <email>awalls@md.metrocast.net</email>
</address> </address>
</affiliation> </affiliation>
</author> </author>

View File

@ -53,8 +53,10 @@ input</refpurpose>
automatically, similar to sensing the video standard. To do so, applications automatically, similar to sensing the video standard. To do so, applications
call <constant> VIDIOC_QUERY_DV_PRESET</constant> with a pointer to a call <constant> VIDIOC_QUERY_DV_PRESET</constant> with a pointer to a
&v4l2-dv-preset; type. Once the hardware detects a preset, that preset is &v4l2-dv-preset; type. Once the hardware detects a preset, that preset is
returned in the preset field of &v4l2-dv-preset;. When detection is not returned in the preset field of &v4l2-dv-preset;. If the preset could not be
possible or fails, the value V4L2_DV_INVALID is returned.</para> detected because there was no signal, or the signal was unreliable, or the
signal did not map to a supported preset, then the value V4L2_DV_INVALID is
returned.</para>
</refsect1> </refsect1>
<refsect1> <refsect1>

View File

@ -176,5 +176,6 @@
175 -> Leadtek Winfast DTV1000S [107d:6655] 175 -> Leadtek Winfast DTV1000S [107d:6655]
176 -> Beholder BeholdTV 505 RDS [0000:5051] 176 -> Beholder BeholdTV 505 RDS [0000:5051]
177 -> Hawell HW-404M7 177 -> Hawell HW-404M7
179 -> Beholder BeholdTV H7 [5ace:7190] 178 -> Beholder BeholdTV H7 [5ace:7190]
180 -> Beholder BeholdTV A7 [5ace:7090] 179 -> Beholder BeholdTV A7 [5ace:7090]
180 -> Avermedia M733A [1461:4155,1461:4255]

View File

@ -290,6 +290,7 @@ sonixb 0c45:602e Genius VideoCam Messenger
sonixj 0c45:6040 Speed NVC 350K sonixj 0c45:6040 Speed NVC 350K
sonixj 0c45:607c Sonix sn9c102p Hv7131R sonixj 0c45:607c Sonix sn9c102p Hv7131R
sonixj 0c45:60c0 Sangha Sn535 sonixj 0c45:60c0 Sangha Sn535
sonixj 0c45:60ce USB-PC-Camera-168 (TALK-5067)
sonixj 0c45:60ec SN9C105+MO4000 sonixj 0c45:60ec SN9C105+MO4000
sonixj 0c45:60fb Surfer NoName sonixj 0c45:60fb Surfer NoName
sonixj 0c45:60fc LG-LIC300 sonixj 0c45:60fc LG-LIC300

View File

@ -1731,7 +1731,7 @@ S: Maintained
F: sound/pci/cs5535audio/ F: sound/pci/cs5535audio/
CX18 VIDEO4LINUX DRIVER CX18 VIDEO4LINUX DRIVER
M: Andy Walls <awalls@radix.net> M: Andy Walls <awalls@md.metrocast.net>
L: ivtv-devel@ivtvdriver.org (moderated for non-subscribers) L: ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@ -3165,7 +3165,7 @@ F: Documentation/hwmon/it87
F: drivers/hwmon/it87.c F: drivers/hwmon/it87.c
IVTV VIDEO4LINUX DRIVER IVTV VIDEO4LINUX DRIVER
M: Andy Walls <awalls@radix.net> M: Andy Walls <awalls@md.metrocast.net>
L: ivtv-devel@ivtvdriver.org (moderated for non-subscribers) L: ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git

View File

@ -13,6 +13,7 @@ source "drivers/media/IR/keymaps/Kconfig"
config IR_NEC_DECODER config IR_NEC_DECODER
tristate "Enable IR raw decoder for the NEC protocol" tristate "Enable IR raw decoder for the NEC protocol"
depends on IR_CORE depends on IR_CORE
select BITREVERSE
default y default y
---help--- ---help---
@ -22,6 +23,7 @@ config IR_NEC_DECODER
config IR_RC5_DECODER config IR_RC5_DECODER
tristate "Enable IR raw decoder for the RC-5 protocol" tristate "Enable IR raw decoder for the RC-5 protocol"
depends on IR_CORE depends on IR_CORE
select BITREVERSE
default y default y
---help--- ---help---

View File

@ -94,6 +94,7 @@ struct imon_context {
bool display_supported; /* not all controllers do */ bool display_supported; /* not all controllers do */
bool display_isopen; /* display port has been opened */ bool display_isopen; /* display port has been opened */
bool rf_device; /* true if iMON 2.4G LT/DT RF device */
bool rf_isassociating; /* RF remote associating */ bool rf_isassociating; /* RF remote associating */
bool dev_present_intf0; /* USB device presence, interface 0 */ bool dev_present_intf0; /* USB device presence, interface 0 */
bool dev_present_intf1; /* USB device presence, interface 1 */ bool dev_present_intf1; /* USB device presence, interface 1 */
@ -385,7 +386,7 @@ static int display_open(struct inode *inode, struct file *file)
err("%s: display port is already open", __func__); err("%s: display port is already open", __func__);
retval = -EBUSY; retval = -EBUSY;
} else { } else {
ictx->display_isopen = 1; ictx->display_isopen = true;
file->private_data = ictx; file->private_data = ictx;
dev_dbg(ictx->dev, "display port opened\n"); dev_dbg(ictx->dev, "display port opened\n");
} }
@ -422,7 +423,7 @@ static int display_close(struct inode *inode, struct file *file)
err("%s: display is not open", __func__); err("%s: display is not open", __func__);
retval = -EIO; retval = -EIO;
} else { } else {
ictx->display_isopen = 0; ictx->display_isopen = false;
dev_dbg(ictx->dev, "display port closed\n"); dev_dbg(ictx->dev, "display port closed\n");
if (!ictx->dev_present_intf0) { if (!ictx->dev_present_intf0) {
/* /*
@ -491,12 +492,12 @@ static int send_packet(struct imon_context *ictx)
} }
init_completion(&ictx->tx.finished); init_completion(&ictx->tx.finished);
ictx->tx.busy = 1; ictx->tx.busy = true;
smp_rmb(); /* ensure later readers know we're busy */ smp_rmb(); /* ensure later readers know we're busy */
retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL); retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL);
if (retval) { if (retval) {
ictx->tx.busy = 0; ictx->tx.busy = false;
smp_rmb(); /* ensure later readers know we're not busy */ smp_rmb(); /* ensure later readers know we're not busy */
err("%s: error submitting urb(%d)", __func__, retval); err("%s: error submitting urb(%d)", __func__, retval);
} else { } else {
@ -682,7 +683,7 @@ static ssize_t store_associate_remote(struct device *d,
return -ENODEV; return -ENODEV;
mutex_lock(&ictx->lock); mutex_lock(&ictx->lock);
ictx->rf_isassociating = 1; ictx->rf_isassociating = true;
send_associate_24g(ictx); send_associate_24g(ictx);
mutex_unlock(&ictx->lock); mutex_unlock(&ictx->lock);
@ -950,7 +951,7 @@ static void usb_tx_callback(struct urb *urb)
ictx->tx.status = urb->status; ictx->tx.status = urb->status;
/* notify waiters that write has finished */ /* notify waiters that write has finished */
ictx->tx.busy = 0; ictx->tx.busy = false;
smp_rmb(); /* ensure later readers know we're not busy */ smp_rmb(); /* ensure later readers know we're not busy */
complete(&ictx->tx.finished); complete(&ictx->tx.finished);
} }
@ -1215,7 +1216,7 @@ static bool imon_mouse_event(struct imon_context *ictx,
{ {
char rel_x = 0x00, rel_y = 0x00; char rel_x = 0x00, rel_y = 0x00;
u8 right_shift = 1; u8 right_shift = 1;
bool mouse_input = 1; bool mouse_input = true;
int dir = 0; int dir = 0;
/* newer iMON device PAD or mouse button */ /* newer iMON device PAD or mouse button */
@ -1246,7 +1247,7 @@ static bool imon_mouse_event(struct imon_context *ictx,
} else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) { } else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) {
dir = -1; dir = -1;
} else } else
mouse_input = 0; mouse_input = false;
if (mouse_input) { if (mouse_input) {
dev_dbg(ictx->dev, "sending mouse data via input subsystem\n"); dev_dbg(ictx->dev, "sending mouse data via input subsystem\n");
@ -1450,7 +1451,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
unsigned char *buf = urb->transfer_buffer; unsigned char *buf = urb->transfer_buffer;
struct device *dev = ictx->dev; struct device *dev = ictx->dev;
u32 kc; u32 kc;
bool norelease = 0; bool norelease = false;
int i; int i;
u64 temp_key; u64 temp_key;
u64 panel_key = 0; u64 panel_key = 0;
@ -1465,7 +1466,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
idev = ictx->idev; idev = ictx->idev;
/* filter out junk data on the older 0xffdc imon devices */ /* filter out junk data on the older 0xffdc imon devices */
if ((buf[0] == 0xff) && (buf[7] == 0xff)) if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff))
return; return;
/* Figure out what key was pressed */ /* Figure out what key was pressed */
@ -1517,7 +1518,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
!(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) { !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) {
len = 8; len = 8;
imon_pad_to_keys(ictx, buf); imon_pad_to_keys(ictx, buf);
norelease = 1; norelease = true;
} }
if (debug) { if (debug) {
@ -1580,7 +1581,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
(buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */ (buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */
dev_warn(dev, "%s: remote associated refid=%02X\n", dev_warn(dev, "%s: remote associated refid=%02X\n",
__func__, buf[1]); __func__, buf[1]);
ictx->rf_isassociating = 0; ictx->rf_isassociating = false;
} }
} }
@ -1790,9 +1791,9 @@ static bool imon_find_endpoints(struct imon_context *ictx,
int ifnum = iface_desc->desc.bInterfaceNumber; int ifnum = iface_desc->desc.bInterfaceNumber;
int num_endpts = iface_desc->desc.bNumEndpoints; int num_endpts = iface_desc->desc.bNumEndpoints;
int i, ep_dir, ep_type; int i, ep_dir, ep_type;
bool ir_ep_found = 0; bool ir_ep_found = false;
bool display_ep_found = 0; bool display_ep_found = false;
bool tx_control = 0; bool tx_control = false;
/* /*
* Scan the endpoint list and set: * Scan the endpoint list and set:
@ -1808,13 +1809,13 @@ static bool imon_find_endpoints(struct imon_context *ictx,
ep_type == USB_ENDPOINT_XFER_INT) { ep_type == USB_ENDPOINT_XFER_INT) {
rx_endpoint = ep; rx_endpoint = ep;
ir_ep_found = 1; ir_ep_found = true;
dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__); dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__);
} else if (!display_ep_found && ep_dir == USB_DIR_OUT && } else if (!display_ep_found && ep_dir == USB_DIR_OUT &&
ep_type == USB_ENDPOINT_XFER_INT) { ep_type == USB_ENDPOINT_XFER_INT) {
tx_endpoint = ep; tx_endpoint = ep;
display_ep_found = 1; display_ep_found = true;
dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__); dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__);
} }
} }
@ -1835,8 +1836,8 @@ static bool imon_find_endpoints(struct imon_context *ictx,
* newer iMON devices that use control urb instead of interrupt * newer iMON devices that use control urb instead of interrupt
*/ */
if (!display_ep_found) { if (!display_ep_found) {
tx_control = 1; tx_control = true;
display_ep_found = 1; display_ep_found = true;
dev_dbg(ictx->dev, "%s: device uses control endpoint, not " dev_dbg(ictx->dev, "%s: device uses control endpoint, not "
"interface OUT endpoint\n", __func__); "interface OUT endpoint\n", __func__);
} }
@ -1847,7 +1848,7 @@ static bool imon_find_endpoints(struct imon_context *ictx,
* and without... :\ * and without... :\
*/ */
if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) { if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) {
display_ep_found = 0; display_ep_found = false;
dev_dbg(ictx->dev, "%s: device has no display\n", __func__); dev_dbg(ictx->dev, "%s: device has no display\n", __func__);
} }
@ -1856,7 +1857,7 @@ static bool imon_find_endpoints(struct imon_context *ictx,
* that refers to e.g. /dev/lcd0 (a character device LCD or VFD). * that refers to e.g. /dev/lcd0 (a character device LCD or VFD).
*/ */
if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) {
display_ep_found = 0; display_ep_found = false;
dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__); dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__);
} }
@ -1905,9 +1906,10 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
ictx->dev = dev; ictx->dev = dev;
ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf)); ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf));
ictx->dev_present_intf0 = 1; ictx->dev_present_intf0 = true;
ictx->rx_urb_intf0 = rx_urb; ictx->rx_urb_intf0 = rx_urb;
ictx->tx_urb = tx_urb; ictx->tx_urb = tx_urb;
ictx->rf_device = false;
ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor); ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor);
ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct); ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct);
@ -1979,7 +1981,7 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf,
} }
ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf)); ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf));
ictx->dev_present_intf1 = 1; ictx->dev_present_intf1 = true;
ictx->rx_urb_intf1 = rx_urb; ictx->rx_urb_intf1 = rx_urb;
ret = -ENODEV; ret = -ENODEV;
@ -2047,6 +2049,12 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR"); dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR");
ictx->display_supported = false; ictx->display_supported = false;
break; break;
/* iMON 2.4G LT (usb stick), no display, iMON RF */
case 0x4e:
dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF");
ictx->display_supported = false;
ictx->rf_device = true;
break;
/* iMON VFD, no IR (does have vol knob tho) */ /* iMON VFD, no IR (does have vol knob tho) */
case 0x35: case 0x35:
dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR"); dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
@ -2197,15 +2205,6 @@ static int __devinit imon_probe(struct usb_interface *interface,
goto fail; goto fail;
} }
if (product == 0xffdc) {
/* RF products *also* use 0xffdc... sigh... */
sysfs_err = sysfs_create_group(&interface->dev.kobj,
&imon_rf_attribute_group);
if (sysfs_err)
err("%s: Could not create RF sysfs entries(%d)",
__func__, sysfs_err);
}
} else { } else {
/* this is the secondary interface on the device */ /* this is the secondary interface on the device */
ictx = imon_init_intf1(interface, first_if_ctx); ictx = imon_init_intf1(interface, first_if_ctx);
@ -2233,6 +2232,14 @@ static int __devinit imon_probe(struct usb_interface *interface,
imon_set_display_type(ictx, interface); imon_set_display_type(ictx, interface);
if (product == 0xffdc && ictx->rf_device) {
sysfs_err = sysfs_create_group(&interface->dev.kobj,
&imon_rf_attribute_group);
if (sysfs_err)
err("%s: Could not create RF sysfs entries(%d)",
__func__, sysfs_err);
}
if (ictx->display_supported) if (ictx->display_supported)
imon_init_display(ictx, interface); imon_init_display(ictx, interface);
} }
@ -2297,7 +2304,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
} }
if (ifnum == 0) { if (ifnum == 0) {
ictx->dev_present_intf0 = 0; ictx->dev_present_intf0 = false;
usb_kill_urb(ictx->rx_urb_intf0); usb_kill_urb(ictx->rx_urb_intf0);
input_unregister_device(ictx->idev); input_unregister_device(ictx->idev);
if (ictx->display_supported) { if (ictx->display_supported) {
@ -2307,7 +2314,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
usb_deregister_dev(interface, &imon_vfd_class); usb_deregister_dev(interface, &imon_vfd_class);
} }
} else { } else {
ictx->dev_present_intf1 = 0; ictx->dev_present_intf1 = false;
usb_kill_urb(ictx->rx_urb_intf1); usb_kill_urb(ictx->rx_urb_intf1);
if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) if (ictx->display_type == IMON_DISPLAY_TYPE_VGA)
input_unregister_device(ictx->touch); input_unregister_device(ictx->touch);

View File

@ -490,11 +490,12 @@ int __ir_input_register(struct input_dev *input_dev,
if (rc < 0) if (rc < 0)
goto out_table; goto out_table;
if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) { if (ir_dev->props)
rc = ir_raw_event_register(input_dev); if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) {
if (rc < 0) rc = ir_raw_event_register(input_dev);
goto out_event; if (rc < 0)
} goto out_event;
}
IR_dprintk(1, "Registered input device on %s for %s remote.\n", IR_dprintk(1, "Registered input device on %s for %s remote.\n",
driver_name, rc_tab->name); driver_name, rc_tab->name);
@ -530,8 +531,10 @@ void ir_input_unregister(struct input_dev *input_dev)
IR_dprintk(1, "Freed keycode table\n"); IR_dprintk(1, "Freed keycode table\n");
del_timer_sync(&ir_dev->timer_keyup); del_timer_sync(&ir_dev->timer_keyup);
if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) if (ir_dev->props)
ir_raw_event_unregister(input_dev); if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
ir_raw_event_unregister(input_dev);
rc_tab = &ir_dev->rc_tab; rc_tab = &ir_dev->rc_tab;
rc_tab->size = 0; rc_tab->size = 0;
kfree(rc_tab->scan); kfree(rc_tab->scan);

View File

@ -221,9 +221,10 @@ int ir_register_class(struct input_dev *input_dev)
if (unlikely(devno < 0)) if (unlikely(devno < 0))
return devno; return devno;
if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) if (ir_dev->props) {
ir_dev->dev.type = &rc_dev_type; if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
else ir_dev->dev.type = &rc_dev_type;
} else
ir_dev->dev.type = &ir_raw_dev_type; ir_dev->dev.type = &ir_raw_dev_type;
ir_dev->dev.class = &ir_input_class; ir_dev->dev.class = &ir_input_class;

View File

@ -6,7 +6,8 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
rc-avermedia.o \ rc-avermedia.o \
rc-avermedia-cardbus.o \ rc-avermedia-cardbus.o \
rc-avermedia-dvbt.o \ rc-avermedia-dvbt.o \
rc-avermedia-m135a-rm-jx.o \ rc-avermedia-m135a.o \
rc-avermedia-m733a-rm-k6.o \
rc-avertv-303.o \ rc-avertv-303.o \
rc-behold.o \ rc-behold.o \
rc-behold-columbus.o \ rc-behold-columbus.o \

View File

@ -1,90 +0,0 @@
/* avermedia-m135a-rm-jx.h - Keytable for avermedia_m135a_rm_jx Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@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.
*/
#include <media/rc-map.h>
/*
* Avermedia M135A with IR model RM-JX
* The same codes exist on both Positivo (BR) and original IR
* Mauro Carvalho Chehab <mchehab@infradead.org>
*/
static struct ir_scancode avermedia_m135a_rm_jx[] = {
{ 0x0200, KEY_POWER2 },
{ 0x022e, KEY_DOT }, /* '.' */
{ 0x0201, KEY_MODE }, /* TV/FM or SOURCE */
{ 0x0205, KEY_1 },
{ 0x0206, KEY_2 },
{ 0x0207, KEY_3 },
{ 0x0209, KEY_4 },
{ 0x020a, KEY_5 },
{ 0x020b, KEY_6 },
{ 0x020d, KEY_7 },
{ 0x020e, KEY_8 },
{ 0x020f, KEY_9 },
{ 0x0211, KEY_0 },
{ 0x0213, KEY_RIGHT }, /* -> or L */
{ 0x0212, KEY_LEFT }, /* <- or R */
{ 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */
{ 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */
{ 0x0303, KEY_CHANNELUP },
{ 0x0302, KEY_CHANNELDOWN },
{ 0x021f, KEY_VOLUMEUP },
{ 0x021e, KEY_VOLUMEDOWN },
{ 0x020c, KEY_ENTER }, /* Full Screen */
{ 0x0214, KEY_MUTE },
{ 0x0208, KEY_AUDIO },
{ 0x0203, KEY_TEXT }, /* Teletext */
{ 0x0204, KEY_EPG },
{ 0x022b, KEY_TV2 }, /* TV2 or PIP */
{ 0x021d, KEY_RED },
{ 0x021c, KEY_YELLOW },
{ 0x0301, KEY_GREEN },
{ 0x0300, KEY_BLUE },
{ 0x021a, KEY_PLAYPAUSE },
{ 0x0219, KEY_RECORD },
{ 0x0218, KEY_PLAY },
{ 0x021b, KEY_STOP },
};
static struct rc_keymap avermedia_m135a_rm_jx_map = {
.map = {
.scan = avermedia_m135a_rm_jx,
.size = ARRAY_SIZE(avermedia_m135a_rm_jx),
.ir_type = IR_TYPE_NEC,
.name = RC_MAP_AVERMEDIA_M135A_RM_JX,
}
};
static int __init init_rc_map_avermedia_m135a_rm_jx(void)
{
return ir_register_map(&avermedia_m135a_rm_jx_map);
}
static void __exit exit_rc_map_avermedia_m135a_rm_jx(void)
{
ir_unregister_map(&avermedia_m135a_rm_jx_map);
}
module_init(init_rc_map_avermedia_m135a_rm_jx)
module_exit(exit_rc_map_avermedia_m135a_rm_jx)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");

View File

@ -0,0 +1,147 @@
/* avermedia-m135a.c - Keytable for Avermedia M135A Remote Controllers
*
* Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
* Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
*
* 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.
*/
#include <media/rc-map.h>
/*
* Avermedia M135A with RM-JX and RM-K6 remote controls
*
* On Avermedia M135A with IR model RM-JX, the same codes exist on both
* Positivo (BR) and original IR, initial version and remote control codes
* added by Mauro Carvalho Chehab <mchehab@infradead.org>
*
* Positivo also ships Avermedia M135A with model RM-K6, extra control
* codes added by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
*/
static struct ir_scancode avermedia_m135a[] = {
/* RM-JX */
{ 0x0200, KEY_POWER2 },
{ 0x022e, KEY_DOT }, /* '.' */
{ 0x0201, KEY_MODE }, /* TV/FM or SOURCE */
{ 0x0205, KEY_1 },
{ 0x0206, KEY_2 },
{ 0x0207, KEY_3 },
{ 0x0209, KEY_4 },
{ 0x020a, KEY_5 },
{ 0x020b, KEY_6 },
{ 0x020d, KEY_7 },
{ 0x020e, KEY_8 },
{ 0x020f, KEY_9 },
{ 0x0211, KEY_0 },
{ 0x0213, KEY_RIGHT }, /* -> or L */
{ 0x0212, KEY_LEFT }, /* <- or R */
{ 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */
{ 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */
{ 0x0303, KEY_CHANNELUP },
{ 0x0302, KEY_CHANNELDOWN },
{ 0x021f, KEY_VOLUMEUP },
{ 0x021e, KEY_VOLUMEDOWN },
{ 0x020c, KEY_ENTER }, /* Full Screen */
{ 0x0214, KEY_MUTE },
{ 0x0208, KEY_AUDIO },
{ 0x0203, KEY_TEXT }, /* Teletext */
{ 0x0204, KEY_EPG },
{ 0x022b, KEY_TV2 }, /* TV2 or PIP */
{ 0x021d, KEY_RED },
{ 0x021c, KEY_YELLOW },
{ 0x0301, KEY_GREEN },
{ 0x0300, KEY_BLUE },
{ 0x021a, KEY_PLAYPAUSE },
{ 0x0219, KEY_RECORD },
{ 0x0218, KEY_PLAY },
{ 0x021b, KEY_STOP },
/* RM-K6 */
{ 0x0401, KEY_POWER2 },
{ 0x0406, KEY_MUTE },
{ 0x0408, KEY_MODE }, /* TV/FM */
{ 0x0409, KEY_1 },
{ 0x040a, KEY_2 },
{ 0x040b, KEY_3 },
{ 0x040c, KEY_4 },
{ 0x040d, KEY_5 },
{ 0x040e, KEY_6 },
{ 0x040f, KEY_7 },
{ 0x0410, KEY_8 },
{ 0x0411, KEY_9 },
{ 0x044c, KEY_DOT }, /* '.' */
{ 0x0412, KEY_0 },
{ 0x0407, KEY_REFRESH }, /* Refresh/Reload */
{ 0x0413, KEY_AUDIO },
{ 0x0440, KEY_SCREEN }, /* Full Screen toggle */
{ 0x0441, KEY_HOME },
{ 0x0442, KEY_BACK },
{ 0x0447, KEY_UP },
{ 0x0448, KEY_DOWN },
{ 0x0449, KEY_LEFT },
{ 0x044a, KEY_RIGHT },
{ 0x044b, KEY_OK },
{ 0x0404, KEY_VOLUMEUP },
{ 0x0405, KEY_VOLUMEDOWN },
{ 0x0402, KEY_CHANNELUP },
{ 0x0403, KEY_CHANNELDOWN },
{ 0x0443, KEY_RED },
{ 0x0444, KEY_GREEN },
{ 0x0445, KEY_YELLOW },
{ 0x0446, KEY_BLUE },
{ 0x0414, KEY_TEXT },
{ 0x0415, KEY_EPG },
{ 0x041a, KEY_TV2 }, /* PIP */
{ 0x041b, KEY_MHP }, /* Snapshot */
{ 0x0417, KEY_RECORD },
{ 0x0416, KEY_PLAYPAUSE },
{ 0x0418, KEY_STOP },
{ 0x0419, KEY_PAUSE },
{ 0x041f, KEY_PREVIOUS },
{ 0x041c, KEY_REWIND },
{ 0x041d, KEY_FORWARD },
{ 0x041e, KEY_NEXT },
};
static struct rc_keymap avermedia_m135a_map = {
.map = {
.scan = avermedia_m135a,
.size = ARRAY_SIZE(avermedia_m135a),
.ir_type = IR_TYPE_NEC,
.name = RC_MAP_AVERMEDIA_M135A,
}
};
static int __init init_rc_map_avermedia_m135a(void)
{
return ir_register_map(&avermedia_m135a_map);
}
static void __exit exit_rc_map_avermedia_m135a(void)
{
ir_unregister_map(&avermedia_m135a_map);
}
module_init(init_rc_map_avermedia_m135a)
module_exit(exit_rc_map_avermedia_m135a)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");

View File

@ -0,0 +1,95 @@
/* avermedia-m733a-rm-k6.h - Keytable for avermedia_m733a_rm_k6 Remote Controller
*
* Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
*
* 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.
*/
#include <media/rc-map.h>
/*
* Avermedia M733A with IR model RM-K6
* This is the stock remote controller used with Positivo machines with M733A
* Herton Ronaldo Krzesinski <herton@mandriva.com.br>
*/
static struct ir_scancode avermedia_m733a_rm_k6[] = {
{ 0x0401, KEY_POWER2 },
{ 0x0406, KEY_MUTE },
{ 0x0408, KEY_MODE }, /* TV/FM */
{ 0x0409, KEY_1 },
{ 0x040a, KEY_2 },
{ 0x040b, KEY_3 },
{ 0x040c, KEY_4 },
{ 0x040d, KEY_5 },
{ 0x040e, KEY_6 },
{ 0x040f, KEY_7 },
{ 0x0410, KEY_8 },
{ 0x0411, KEY_9 },
{ 0x044c, KEY_DOT }, /* '.' */
{ 0x0412, KEY_0 },
{ 0x0407, KEY_REFRESH }, /* Refresh/Reload */
{ 0x0413, KEY_AUDIO },
{ 0x0440, KEY_SCREEN }, /* Full Screen toggle */
{ 0x0441, KEY_HOME },
{ 0x0442, KEY_BACK },
{ 0x0447, KEY_UP },
{ 0x0448, KEY_DOWN },
{ 0x0449, KEY_LEFT },
{ 0x044a, KEY_RIGHT },
{ 0x044b, KEY_OK },
{ 0x0404, KEY_VOLUMEUP },
{ 0x0405, KEY_VOLUMEDOWN },
{ 0x0402, KEY_CHANNELUP },
{ 0x0403, KEY_CHANNELDOWN },
{ 0x0443, KEY_RED },
{ 0x0444, KEY_GREEN },
{ 0x0445, KEY_YELLOW },
{ 0x0446, KEY_BLUE },
{ 0x0414, KEY_TEXT },
{ 0x0415, KEY_EPG },
{ 0x041a, KEY_TV2 }, /* PIP */
{ 0x041b, KEY_MHP }, /* Snapshot */
{ 0x0417, KEY_RECORD },
{ 0x0416, KEY_PLAYPAUSE },
{ 0x0418, KEY_STOP },
{ 0x0419, KEY_PAUSE },
{ 0x041f, KEY_PREVIOUS },
{ 0x041c, KEY_REWIND },
{ 0x041d, KEY_FORWARD },
{ 0x041e, KEY_NEXT },
};
static struct rc_keymap avermedia_m733a_rm_k6_map = {
.map = {
.scan = avermedia_m733a_rm_k6,
.size = ARRAY_SIZE(avermedia_m733a_rm_k6),
.ir_type = IR_TYPE_NEC,
.name = RC_MAP_AVERMEDIA_M733A_RM_K6,
}
};
static int __init init_rc_map_avermedia_m733a_rm_k6(void)
{
return ir_register_map(&avermedia_m733a_rm_k6_map);
}
static void __exit exit_rc_map_avermedia_m733a_rm_k6(void)
{
ir_unregister_map(&avermedia_m733a_rm_k6_map);
}
module_init(init_rc_map_avermedia_m733a_rm_k6)
module_exit(exit_rc_map_avermedia_m733a_rm_k6)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");

View File

@ -594,7 +594,7 @@ static irqreturn_t dm1105_irq(int irq, void *dev_id)
int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
{ {
struct input_dev *input_dev; struct input_dev *input_dev;
char *ir_codes = NULL; char *ir_codes = RC_MAP_DM1105_NEC;
int err = -ENOMEM; int err = -ENOMEM;
input_dev = input_allocate_device(); input_dev = input_allocate_device();

View File

@ -351,6 +351,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
const u8 *ts, *ts_end, *from_where = NULL; const u8 *ts, *ts_end, *from_where = NULL;
u8 ts_remain = 0, how_much = 0, new_ts = 1; u8 ts_remain = 0, how_much = 0, new_ts = 1;
struct ethhdr *ethh = NULL; struct ethhdr *ethh = NULL;
bool error = false;
#ifdef ULE_DEBUG #ifdef ULE_DEBUG
/* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */ /* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */
@ -460,10 +461,16 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
/* Drop partly decoded SNDU, reset state, resync on PUSI. */ /* Drop partly decoded SNDU, reset state, resync on PUSI. */
if (priv->ule_skb) { if (priv->ule_skb) {
dev_kfree_skb( priv->ule_skb ); error = true;
dev_kfree_skb(priv->ule_skb);
}
if (error || priv->ule_sndu_remain) {
dev->stats.rx_errors++; dev->stats.rx_errors++;
dev->stats.rx_frame_errors++; dev->stats.rx_frame_errors++;
error = false;
} }
reset_ule(priv); reset_ule(priv);
priv->need_pusi = 1; priv->need_pusi = 1;
continue; continue;
@ -535,6 +542,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
from_where += 2; from_where += 2;
} }
priv->ule_sndu_remain = priv->ule_sndu_len + 2;
/* /*
* State of current TS: * State of current TS:
* ts_remain (remaining bytes in the current TS cell) * ts_remain (remaining bytes in the current TS cell)
@ -544,6 +552,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
*/ */
switch (ts_remain) { switch (ts_remain) {
case 1: case 1:
priv->ule_sndu_remain--;
priv->ule_sndu_type = from_where[0] << 8; priv->ule_sndu_type = from_where[0] << 8;
priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */ priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */
ts_remain -= 1; from_where += 1; ts_remain -= 1; from_where += 1;
@ -557,6 +566,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
default: /* complete ULE header is present in current TS. */ default: /* complete ULE header is present in current TS. */
/* Extract ULE type field. */ /* Extract ULE type field. */
if (priv->ule_sndu_type_1) { if (priv->ule_sndu_type_1) {
priv->ule_sndu_type_1 = 0;
priv->ule_sndu_type |= from_where[0]; priv->ule_sndu_type |= from_where[0];
from_where += 1; /* points to payload start. */ from_where += 1; /* points to payload start. */
ts_remain -= 1; ts_remain -= 1;

View File

@ -76,6 +76,7 @@ config DVB_USB_DIB0700
select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE
select DVB_LGDT3305 if !DVB_FE_CUSTOMISE select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
select DVB_TUNER_DIB0090 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
@ -134,6 +135,7 @@ config DVB_USB_M920X
select DVB_TDA1004X if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
Currently, only devices with a product id of Currently, only devices with a product id of
@ -264,7 +266,7 @@ config DVB_USB_DW2102
select DVB_STB6000 if !DVB_FE_CUSTOMISE select DVB_STB6000 if !DVB_FE_CUSTOMISE
select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE
select DVB_SI21XX if !DVB_FE_CUSTOMISE select DVB_SI21XX if !DVB_FE_CUSTOMISE
select DVB_TDA10021 if !DVB_FE_CUSTOMISE select DVB_TDA10023 if !DVB_FE_CUSTOMISE
select DVB_MT312 if !DVB_FE_CUSTOMISE select DVB_MT312 if !DVB_FE_CUSTOMISE
select DVB_ZL10039 if !DVB_FE_CUSTOMISE select DVB_ZL10039 if !DVB_FE_CUSTOMISE
select DVB_DS3000 if !DVB_FE_CUSTOMISE select DVB_DS3000 if !DVB_FE_CUSTOMISE

View File

@ -1026,8 +1026,10 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
&cxusb_dualdig4_rev2_config) < 0) &cxusb_dualdig4_rev2_config) < 0) {
printk(KERN_WARNING "Unable to enumerate dib7000p\n");
return -ENODEV; return -ENODEV;
}
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&cxusb_dualdig4_rev2_config); &cxusb_dualdig4_rev2_config);

View File

@ -198,6 +198,7 @@
#define USB_PID_AVERMEDIA_A850 0x850a #define USB_PID_AVERMEDIA_A850 0x850a
#define USB_PID_AVERMEDIA_A805 0xa805 #define USB_PID_AVERMEDIA_A805 0xa805
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058

View File

@ -29,6 +29,8 @@
#include "tda826x.h" #include "tda826x.h"
#include "tda10086.h" #include "tda10086.h"
#include "tda1002x.h"
#include "tda827x.h"
#include "lnbp21.h" #include "lnbp21.h"
/* debug */ /* debug */
@ -150,7 +152,17 @@ static struct tda10086_config tda10086_config = {
.xtal_freq = TDA10086_XTAL_16M, .xtal_freq = TDA10086_XTAL_16M,
}; };
static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap) static struct tda10023_config tda10023_config = {
.demod_address = 0x0c,
.invert = 0,
.xtal = 16000000,
.pll_m = 11,
.pll_p = 3,
.pll_n = 1,
.deltaf = 0xa511,
};
static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
{ {
if (usb_set_interface(adap->dev->udev,0,3) < 0) if (usb_set_interface(adap->dev->udev,0,3) < 0)
err("set interface to alts=3 failed"); err("set interface to alts=3 failed");
@ -163,7 +175,27 @@ static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
return 0; return 0;
} }
static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap) static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
{
if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
err("set interface to alts=3 failed");
if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) {
deb_info("TDA10023 attach failed\n");
return -ENODEV;
}
return 0;
}
static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
{
if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) {
printk(KERN_ERR "%s: No tda827x found!\n", __func__);
return -ENODEV;
}
return 0;
}
static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
{ {
if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) { if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
deb_info("TDA8263 attach failed\n"); deb_info("TDA8263 attach failed\n");
@ -180,6 +212,7 @@ static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
/* DVB USB Driver stuff */ /* DVB USB Driver stuff */
static struct dvb_usb_device_properties ttusb2_properties; static struct dvb_usb_device_properties ttusb2_properties;
static struct dvb_usb_device_properties ttusb2_properties_s2400; static struct dvb_usb_device_properties ttusb2_properties_s2400;
static struct dvb_usb_device_properties ttusb2_properties_ct3650;
static int ttusb2_probe(struct usb_interface *intf, static int ttusb2_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
@ -187,6 +220,8 @@ static int ttusb2_probe(struct usb_interface *intf,
if (0 == dvb_usb_device_init(intf, &ttusb2_properties, if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400, 0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &ttusb2_properties_ct3650,
THIS_MODULE, NULL, adapter_nr)) THIS_MODULE, NULL, adapter_nr))
return 0; return 0;
return -ENODEV; return -ENODEV;
@ -197,6 +232,8 @@ static struct usb_device_id ttusb2_table [] = {
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
{ USB_DEVICE(USB_VID_TECHNOTREND, { USB_DEVICE(USB_VID_TECHNOTREND,
USB_PID_TECHNOTREND_CONNECT_S2400) }, USB_PID_TECHNOTREND_CONNECT_S2400) },
{ USB_DEVICE(USB_VID_TECHNOTREND,
USB_PID_TECHNOTREND_CONNECT_CT3650) },
{} /* Terminating entry */ {} /* Terminating entry */
}; };
MODULE_DEVICE_TABLE (usb, ttusb2_table); MODULE_DEVICE_TABLE (usb, ttusb2_table);
@ -214,8 +251,8 @@ static struct dvb_usb_device_properties ttusb2_properties = {
{ {
.streaming_ctrl = NULL, // ttusb2_streaming_ctrl, .streaming_ctrl = NULL, // ttusb2_streaming_ctrl,
.frontend_attach = ttusb2_frontend_attach, .frontend_attach = ttusb2_frontend_tda10086_attach,
.tuner_attach = ttusb2_tuner_attach, .tuner_attach = ttusb2_tuner_tda826x_attach,
/* parameter for the MPEG2-data transfer */ /* parameter for the MPEG2-data transfer */
.stream = { .stream = {
@ -266,8 +303,8 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
{ {
.streaming_ctrl = NULL, .streaming_ctrl = NULL,
.frontend_attach = ttusb2_frontend_attach, .frontend_attach = ttusb2_frontend_tda10086_attach,
.tuner_attach = ttusb2_tuner_attach, .tuner_attach = ttusb2_tuner_tda826x_attach,
/* parameter for the MPEG2-data transfer */ /* parameter for the MPEG2-data transfer */
.stream = { .stream = {
@ -301,6 +338,52 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
} }
}; };
static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = CYPRESS_FX2,
.size_of_priv = sizeof(struct ttusb2_state),
.num_adapters = 1,
.adapter = {
{
.streaming_ctrl = NULL,
.frontend_attach = ttusb2_frontend_tda10023_attach,
.tuner_attach = ttusb2_tuner_tda827x_attach,
/* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_ISOC,
.count = 5,
.endpoint = 0x02,
.u = {
.isoc = {
.framesperurb = 4,
.framesize = 940,
.interval = 1,
}
}
}
},
},
.power_ctrl = ttusb2_power_ctrl,
.identify_state = ttusb2_identify_state,
.i2c_algo = &ttusb2_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x01,
.num_device_descs = 1,
.devices = {
{ "Technotrend TT-connect CT-3650",
.warm_ids = { &ttusb2_table[3], NULL },
},
}
};
static struct usb_driver ttusb2_driver = { static struct usb_driver ttusb2_driver = {
.name = "dvb_usb_ttusb2", .name = "dvb_usb_ttusb2",
.probe = ttusb2_probe, .probe = ttusb2_probe,

View File

@ -58,7 +58,7 @@ static void rawiso_activity_cb(struct hpsb_iso *iso)
num = hpsb_iso_n_ready(iso); num = hpsb_iso_n_ready(iso);
if (!fdtv) { if (!fdtv) {
dev_err(fdtv->device, "received at unknown iso channel\n"); pr_err("received at unknown iso channel\n");
goto out; goto out;
} }

View File

@ -567,30 +567,6 @@ static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
{
switch (fmt->type) {
default:
return -EINVAL;
}
return 0;
}
static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
{
switch (fmt->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
/* Not yet implemented */
break;
default:
return -EINVAL;
}
return 0;
}
/* ----------------------------------------------------------------------- */
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
static int au8522_g_register(struct v4l2_subdev *sd, static int au8522_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
@ -772,8 +748,6 @@ static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
static const struct v4l2_subdev_video_ops au8522_video_ops = { static const struct v4l2_subdev_video_ops au8522_video_ops = {
.s_routing = au8522_s_video_routing, .s_routing = au8522_s_video_routing,
.g_fmt = au8522_g_fmt,
.s_fmt = au8522_s_fmt,
.s_stream = au8522_s_stream, .s_stream = au8522_s_stream,
}; };

View File

@ -969,15 +969,12 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
/* allocate memory for the internal state */ /* allocate memory for the internal state */
state = kmalloc(sizeof(struct ds3000_state), GFP_KERNEL); state = kzalloc(sizeof(struct ds3000_state), GFP_KERNEL);
if (state == NULL) { if (state == NULL) {
printk(KERN_ERR "Unable to kmalloc\n"); printk(KERN_ERR "Unable to kmalloc\n");
goto error2; goto error2;
} }
/* setup the state */
memset(state, 0, sizeof(struct ds3000_state));
state->config = config; state->config = config;
state->i2c = i2c; state->i2c = i2c;
state->prevUCBS2 = 0; state->prevUCBS2 = 0;

View File

@ -303,7 +303,10 @@ static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
static int stv6110x_sleep(struct dvb_frontend *fe) static int stv6110x_sleep(struct dvb_frontend *fe)
{ {
return stv6110x_set_mode(fe, TUNER_SLEEP); if (fe->tuner_priv)
return stv6110x_set_mode(fe, TUNER_SLEEP);
return 0;
} }
static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status) static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)

View File

@ -217,6 +217,19 @@ static struct ngene_info ngene_info_cineS2v5 = {
.fw_version = 15, .fw_version = 15,
}; };
static struct ngene_info ngene_info_duoFlexS2 = {
.type = NGENE_SIDEWINDER,
.name = "Digital Devices DuoFlex S2 miniPCIe",
.io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN},
.demod_attach = {demod_attach_stv0900, demod_attach_stv0900},
.tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110},
.fe_config = {&fe_cineS2, &fe_cineS2},
.tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1},
.lnb = {0x0a, 0x08},
.tsf = {3, 3},
.fw_version = 15,
};
static struct ngene_info ngene_info_m780 = { static struct ngene_info ngene_info_m780 = {
.type = NGENE_APP, .type = NGENE_APP,
.name = "Aver M780 ATSC/QAM-B", .name = "Aver M780 ATSC/QAM-B",
@ -256,6 +269,8 @@ static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2), NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2), NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2),
NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5), NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5),
NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlexS2),
NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlexS2),
NGENE_ID(0x1461, 0x062e, ngene_info_m780), NGENE_ID(0x1461, 0x062e, ngene_info_m780),
{0} {0}
}; };

View File

@ -53,8 +53,6 @@ MODULE_PARM_DESC(debug, "Print debugging information.");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
#define COMMAND_TIMEOUT_WORKAROUND
#define dprintk if (debug) printk #define dprintk if (debug) printk
#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) #define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr)))
@ -147,24 +145,24 @@ static void demux_tasklet(unsigned long data)
} else { } else {
if (chan->HWState == HWSTATE_RUN) { if (chan->HWState == HWSTATE_RUN) {
u32 Flags = 0; u32 Flags = 0;
IBufferExchange *exch1 = chan->pBufferExchange;
IBufferExchange *exch2 = chan->pBufferExchange2;
if (Cur->ngeneBuffer.SR.Flags & 0x01) if (Cur->ngeneBuffer.SR.Flags & 0x01)
Flags |= BEF_EVEN_FIELD; Flags |= BEF_EVEN_FIELD;
if (Cur->ngeneBuffer.SR.Flags & 0x20) if (Cur->ngeneBuffer.SR.Flags & 0x20)
Flags |= BEF_OVERFLOW; Flags |= BEF_OVERFLOW;
if (chan->pBufferExchange) spin_unlock_irq(&chan->state_lock);
chan->pBufferExchange(chan, if (exch1)
Cur->Buffer1, exch1(chan, Cur->Buffer1,
chan-> chan->Capture1Length,
Capture1Length, Cur->ngeneBuffer.SR.Clock,
Cur->ngeneBuffer. Flags);
SR.Clock, Flags); if (exch2)
if (chan->pBufferExchange2) exch2(chan, Cur->Buffer2,
chan->pBufferExchange2(chan, chan->Capture2Length,
Cur->Buffer2, Cur->ngeneBuffer.SR.Clock,
chan-> Flags);
Capture2Length, spin_lock_irq(&chan->state_lock);
Cur->ngeneBuffer.
SR.Clock, Flags);
} else if (chan->HWState != HWSTATE_STOP) } else if (chan->HWState != HWSTATE_STOP)
chan->HWState = HWSTATE_RUN; chan->HWState = HWSTATE_RUN;
} }
@ -572,11 +570,7 @@ static int ngene_command_stream_control(struct ngene *dev, u8 stream,
u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700); u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700);
u16 BsSDO = 0x9B00; u16 BsSDO = 0x9B00;
/* down(&dev->stream_mutex); */ down(&dev->stream_mutex);
while (down_trylock(&dev->stream_mutex)) {
printk(KERN_INFO DEVICE_NAME ": SC locked\n");
msleep(1);
}
memset(&com, 0, sizeof(com)); memset(&com, 0, sizeof(com));
com.cmd.hdr.Opcode = CMD_CONTROL; com.cmd.hdr.Opcode = CMD_CONTROL;
com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2; com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2;
@ -1252,14 +1246,17 @@ static int ngene_load_firm(struct ngene *dev)
version = 15; version = 15;
size = 23466; size = 23466;
fw_name = "ngene_15.fw"; fw_name = "ngene_15.fw";
dev->cmd_timeout_workaround = true;
break; break;
case 16: case 16:
size = 23498; size = 23498;
fw_name = "ngene_16.fw"; fw_name = "ngene_16.fw";
dev->cmd_timeout_workaround = true;
break; break;
case 17: case 17:
size = 24446; size = 24446;
fw_name = "ngene_17.fw"; fw_name = "ngene_17.fw";
dev->cmd_timeout_workaround = true;
break; break;
} }
@ -1299,11 +1296,16 @@ static void ngene_stop(struct ngene *dev)
ngwritel(0, NGENE_EVENT); ngwritel(0, NGENE_EVENT);
ngwritel(0, NGENE_EVENT_HI); ngwritel(0, NGENE_EVENT_HI);
free_irq(dev->pci_dev->irq, dev); free_irq(dev->pci_dev->irq, dev);
#ifdef CONFIG_PCI_MSI
if (dev->msi_enabled)
pci_disable_msi(dev->pci_dev);
#endif
} }
static int ngene_start(struct ngene *dev) static int ngene_start(struct ngene *dev)
{ {
int stat; int stat;
unsigned long flags;
int i; int i;
pci_set_master(dev->pci_dev); pci_set_master(dev->pci_dev);
@ -1333,6 +1335,28 @@ static int ngene_start(struct ngene *dev)
if (stat < 0) if (stat < 0)
goto fail; goto fail;
#ifdef CONFIG_PCI_MSI
/* enable MSI if kernel and card support it */
if (pci_msi_enabled() && dev->card_info->msi_supported) {
ngwritel(0, NGENE_INT_ENABLE);
free_irq(dev->pci_dev->irq, dev);
stat = pci_enable_msi(dev->pci_dev);
if (stat) {
printk(KERN_INFO DEVICE_NAME
": MSI not available\n");
flags = IRQF_SHARED;
} else {
flags = 0;
dev->msi_enabled = true;
}
stat = request_irq(dev->pci_dev->irq, irq_handler,
flags, "nGene", dev);
if (stat < 0)
goto fail2;
ngwritel(1, NGENE_INT_ENABLE);
}
#endif
stat = ngene_i2c_init(dev, 0); stat = ngene_i2c_init(dev, 0);
if (stat < 0) if (stat < 0)
goto fail; goto fail;
@ -1358,10 +1382,18 @@ static int ngene_start(struct ngene *dev)
bconf = BUFFER_CONFIG_3333; bconf = BUFFER_CONFIG_3333;
stat = ngene_command_config_buf(dev, bconf); stat = ngene_command_config_buf(dev, bconf);
} }
return stat; if (!stat)
return stat;
/* otherwise error: fall through */
fail: fail:
ngwritel(0, NGENE_INT_ENABLE); ngwritel(0, NGENE_INT_ENABLE);
free_irq(dev->pci_dev->irq, dev); free_irq(dev->pci_dev->irq, dev);
#ifdef CONFIG_PCI_MSI
fail2:
if (dev->msi_enabled)
pci_disable_msi(dev->pci_dev);
#endif
return stat; return stat;
} }
@ -1379,10 +1411,8 @@ static void release_channel(struct ngene_channel *chan)
struct ngene_info *ni = dev->card_info; struct ngene_info *ni = dev->card_info;
int io = ni->io_type[chan->number]; int io = ni->io_type[chan->number];
#ifdef COMMAND_TIMEOUT_WORKAROUND if (chan->dev->cmd_timeout_workaround && chan->running)
if (chan->running)
set_transfer(chan, 0); set_transfer(chan, 0);
#endif
tasklet_kill(&chan->demux_tasklet); tasklet_kill(&chan->demux_tasklet);

View File

@ -37,15 +37,12 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/version.h>
#include <linux/byteorder/generic.h> #include <linux/byteorder/generic.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include "ngene.h" #include "ngene.h"
#define COMMAND_TIMEOUT_WORKAROUND
/****************************************************************************/ /****************************************************************************/
/* COMMAND API interface ****************************************************/ /* COMMAND API interface ****************************************************/
@ -69,9 +66,7 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
struct ngene_channel *chan = priv; struct ngene_channel *chan = priv;
#ifdef COMMAND_TIMEOUT_WORKAROUND
if (chan->users > 0) if (chan->users > 0)
#endif
dvb_dmx_swfilter(&chan->demux, buf, len); dvb_dmx_swfilter(&chan->demux, buf, len);
return NULL; return NULL;
} }
@ -106,11 +101,8 @@ int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed)
struct ngene_channel *chan = dvbdmx->priv; struct ngene_channel *chan = dvbdmx->priv;
if (chan->users == 0) { if (chan->users == 0) {
#ifdef COMMAND_TIMEOUT_WORKAROUND if (!chan->dev->cmd_timeout_workaround || !chan->running)
if (!chan->running)
#endif
set_transfer(chan, 1); set_transfer(chan, 1);
/* msleep(10); */
} }
return ++chan->users; return ++chan->users;
@ -124,9 +116,8 @@ int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
if (--chan->users) if (--chan->users)
return chan->users; return chan->users;
#ifndef COMMAND_TIMEOUT_WORKAROUND if (!chan->dev->cmd_timeout_workaround)
set_transfer(chan, 0); set_transfer(chan, 0);
#endif
return 0; return 0;
} }

View File

@ -39,7 +39,6 @@
#include <linux/pci_ids.h> #include <linux/pci_ids.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/version.h>
#include <linux/byteorder/generic.h> #include <linux/byteorder/generic.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>

View File

@ -725,6 +725,8 @@ struct ngene {
u32 device_version; u32 device_version;
u32 fw_interface_version; u32 fw_interface_version;
u32 icounts; u32 icounts;
bool msi_enabled;
bool cmd_timeout_workaround;
u8 *CmdDoneByte; u8 *CmdDoneByte;
int BootFirmware; int BootFirmware;
@ -797,6 +799,7 @@ struct ngene_info {
#define NGENE_VBOX_V2 7 #define NGENE_VBOX_V2 7
int fw_version; int fw_version;
bool msi_supported;
char *name; char *name;
int io_type[MAX_STREAM]; int io_type[MAX_STREAM];

View File

@ -68,13 +68,14 @@ config DVB_BUDGET
select DVB_VES1820 if !DVB_FE_CUSTOMISE select DVB_VES1820 if !DVB_FE_CUSTOMISE
select DVB_L64781 if !DVB_FE_CUSTOMISE select DVB_L64781 if !DVB_FE_CUSTOMISE
select DVB_TDA8083 if !DVB_FE_CUSTOMISE select DVB_TDA8083 if !DVB_FE_CUSTOMISE
select DVB_TDA10021 if !DVB_FE_CUSTOMISE
select DVB_TDA10023 if !DVB_FE_CUSTOMISE
select DVB_S5H1420 if !DVB_FE_CUSTOMISE select DVB_S5H1420 if !DVB_FE_CUSTOMISE
select DVB_TDA10086 if !DVB_FE_CUSTOMISE select DVB_TDA10086 if !DVB_FE_CUSTOMISE
select DVB_TDA826X if !DVB_FE_CUSTOMISE select DVB_TDA826X if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE select DVB_LNBP21 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select DVB_ISL6423 if !DVB_FE_CUSTOMISE
select DVB_STV090x if !DVB_FE_CUSTOMISE
select DVB_STV6110x if !DVB_FE_CUSTOMISE
help help
Support for simple SAA7146 based DVB cards (so called Budget- Support for simple SAA7146 based DVB cards (so called Budget-
or Nova-PCI cards) without onboard MPEG2 decoder, and without or Nova-PCI cards) without onboard MPEG2 decoder, and without

View File

@ -215,6 +215,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
break; break;
case 0x1010: case 0x1010:
case 0x1017: case 0x1017:
case 0x1019:
case 0x101a: case 0x101a:
/* for the Technotrend 1500 bundled remote */ /* for the Technotrend 1500 bundled remote */
ir_codes = RC_MAP_TT_1500; ir_codes = RC_MAP_TT_1500;

View File

@ -646,7 +646,7 @@ config VIDEO_PMS
config VIDEO_BWQCAM config VIDEO_BWQCAM
tristate "Quickcam BW Video For Linux" tristate "Quickcam BW Video For Linux"
depends on PARPORT && VIDEO_V4L1 depends on PARPORT && VIDEO_V4L2
help help
Say Y have if you the black and white version of the QuickCam Say Y have if you the black and white version of the QuickCam
camera. See the next option for the color version. camera. See the next option for the color version.
@ -656,7 +656,7 @@ config VIDEO_BWQCAM
config VIDEO_CQCAM config VIDEO_CQCAM
tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)" tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)"
depends on EXPERIMENTAL && PARPORT && VIDEO_V4L1 depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2
help help
This is the video4linux driver for the colour version of the This is the video4linux driver for the colour version of the
Connectix QuickCam. If you have one of these cameras, say Y here, Connectix QuickCam. If you have one of these cameras, say Y here,

View File

@ -11,6 +11,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/ak881x.h> #include <media/ak881x.h>
@ -141,7 +142,7 @@ static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd,
return ak881x_try_g_mbus_fmt(sd, mf); return ak881x_try_g_mbus_fmt(sd, mf);
} }
static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, int index, static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code) enum v4l2_mbus_pixelcode *code)
{ {
if (index) if (index)

View File

@ -66,19 +66,58 @@ OTHER DEALINGS IN THE SOFTWARE.
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/videodev.h> #include <linux/version.h>
#include <media/v4l2-common.h> #include <linux/videodev2.h>
#include <media/v4l2-ioctl.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
#include "bw-qcam.h" /* One from column A... */
#define QC_NOTSET 0
#define QC_UNIDIR 1
#define QC_BIDIR 2
#define QC_SERIAL 3
/* ... and one from column B */
#define QC_ANY 0x00
#define QC_FORCE_UNIDIR 0x10
#define QC_FORCE_BIDIR 0x20
#define QC_FORCE_SERIAL 0x30
/* in the port_mode member */
#define QC_MODE_MASK 0x07
#define QC_FORCE_MASK 0x70
#define MAX_HEIGHT 243
#define MAX_WIDTH 336
/* Bit fields for status flags */
#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */
struct qcam {
struct v4l2_device v4l2_dev;
struct video_device vdev;
struct pardevice *pdev;
struct parport *pport;
struct mutex lock;
int width, height;
int bpp;
int mode;
int contrast, brightness, whitebal;
int port_mode;
int transfer_scale;
int top, left;
int status;
unsigned int saved_bits;
unsigned long in_use;
};
static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */ static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */
static unsigned int yieldlines = 4; /* Yield after this many during capture */ static unsigned int yieldlines = 4; /* Yield after this many during capture */
@ -93,22 +132,26 @@ module_param(video_nr, int, 0);
* immediately attempt to initialize qcam */ * immediately attempt to initialize qcam */
module_param(force_init, int, 0); module_param(force_init, int, 0);
static inline int read_lpstatus(struct qcam_device *q) #define MAX_CAMS 4
static struct qcam *qcams[MAX_CAMS];
static unsigned int num_cams;
static inline int read_lpstatus(struct qcam *q)
{ {
return parport_read_status(q->pport); return parport_read_status(q->pport);
} }
static inline int read_lpdata(struct qcam_device *q) static inline int read_lpdata(struct qcam *q)
{ {
return parport_read_data(q->pport); return parport_read_data(q->pport);
} }
static inline void write_lpdata(struct qcam_device *q, int d) static inline void write_lpdata(struct qcam *q, int d)
{ {
parport_write_data(q->pport, d); parport_write_data(q->pport, d);
} }
static inline void write_lpcontrol(struct qcam_device *q, int d) static void write_lpcontrol(struct qcam *q, int d)
{ {
if (d & 0x20) { if (d & 0x20) {
/* Set bidirectional mode to reverse (data in) */ /* Set bidirectional mode to reverse (data in) */
@ -124,126 +167,11 @@ static inline void write_lpcontrol(struct qcam_device *q, int d)
parport_write_control(q->pport, d); parport_write_control(q->pport, d);
} }
static int qc_waithand(struct qcam_device *q, int val);
static int qc_command(struct qcam_device *q, int command);
static int qc_readparam(struct qcam_device *q);
static int qc_setscanmode(struct qcam_device *q);
static int qc_readbytes(struct qcam_device *q, char buffer[]);
static struct video_device qcam_template;
static int qc_calibrate(struct qcam_device *q)
{
/*
* Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
* The white balance is an individiual value for each
* quickcam.
*/
int value;
int count = 0;
qc_command(q, 27); /* AutoAdjustOffset */
qc_command(q, 0); /* Dummy Parameter, ignored by the camera */
/* GetOffset (33) will read 255 until autocalibration */
/* is finished. After that, a value of 1-254 will be */
/* returned. */
do {
qc_command(q, 33);
value = qc_readparam(q);
mdelay(1);
schedule();
count++;
} while (value == 0xff && count < 2048);
q->whitebal = value;
return value;
}
/* Initialize the QuickCam driver control structure. This is where
* defaults are set for people who don't have a config file.*/
static struct qcam_device *qcam_init(struct parport *port)
{
struct qcam_device *q;
q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
if (q == NULL)
return NULL;
q->pport = port;
q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
NULL, 0, NULL);
if (q->pdev == NULL) {
printk(KERN_ERR "bw-qcam: couldn't register for %s.\n",
port->name);
kfree(q);
return NULL;
}
memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
mutex_init(&q->lock);
q->port_mode = (QC_ANY | QC_NOTSET);
q->width = 320;
q->height = 240;
q->bpp = 4;
q->transfer_scale = 2;
q->contrast = 192;
q->brightness = 180;
q->whitebal = 105;
q->top = 1;
q->left = 14;
q->mode = -1;
q->status = QC_PARAM_CHANGE;
return q;
}
/* qc_command is probably a bit of a misnomer -- it's used to send
* bytes *to* the camera. Generally, these bytes are either commands
* or arguments to commands, so the name fits, but it still bugs me a
* bit. See the documentation for a list of commands. */
static int qc_command(struct qcam_device *q, int command)
{
int n1, n2;
int cmd;
write_lpdata(q, command);
write_lpcontrol(q, 6);
n1 = qc_waithand(q, 1);
write_lpcontrol(q, 0xe);
n2 = qc_waithand(q, 0);
cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
return cmd;
}
static int qc_readparam(struct qcam_device *q)
{
int n1, n2;
int cmd;
write_lpcontrol(q, 6);
n1 = qc_waithand(q, 1);
write_lpcontrol(q, 0xe);
n2 = qc_waithand(q, 0);
cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
return cmd;
}
/* qc_waithand busy-waits for a handshake signal from the QuickCam. /* qc_waithand busy-waits for a handshake signal from the QuickCam.
* Almost all communication with the camera requires handshaking. */ * Almost all communication with the camera requires handshaking. */
static int qc_waithand(struct qcam_device *q, int val) static int qc_waithand(struct qcam *q, int val)
{ {
int status; int status;
int runs = 0; int runs = 0;
@ -286,7 +214,7 @@ static int qc_waithand(struct qcam_device *q, int val)
* (bit 3 of status register). It also returns the last value read, * (bit 3 of status register). It also returns the last value read,
* since this data is useful. */ * since this data is useful. */
static unsigned int qc_waithand2(struct qcam_device *q, int val) static unsigned int qc_waithand2(struct qcam *q, int val)
{ {
unsigned int status; unsigned int status;
int runs = 0; int runs = 0;
@ -309,6 +237,43 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val)
return status; return status;
} }
/* qc_command is probably a bit of a misnomer -- it's used to send
* bytes *to* the camera. Generally, these bytes are either commands
* or arguments to commands, so the name fits, but it still bugs me a
* bit. See the documentation for a list of commands. */
static int qc_command(struct qcam *q, int command)
{
int n1, n2;
int cmd;
write_lpdata(q, command);
write_lpcontrol(q, 6);
n1 = qc_waithand(q, 1);
write_lpcontrol(q, 0xe);
n2 = qc_waithand(q, 0);
cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
return cmd;
}
static int qc_readparam(struct qcam *q)
{
int n1, n2;
int cmd;
write_lpcontrol(q, 6);
n1 = qc_waithand(q, 1);
write_lpcontrol(q, 0xe);
n2 = qc_waithand(q, 0);
cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
return cmd;
}
/* Try to detect a QuickCam. It appears to flash the upper 4 bits of /* Try to detect a QuickCam. It appears to flash the upper 4 bits of
the status register at 5-10 Hz. This is only used in the autoprobe the status register at 5-10 Hz. This is only used in the autoprobe
@ -317,7 +282,7 @@ static unsigned int qc_waithand2(struct qcam_device *q, int val)
almost completely safe, while their method screws up my printer if almost completely safe, while their method screws up my printer if
I plug it in before the camera. */ I plug it in before the camera. */
static int qc_detect(struct qcam_device *q) static int qc_detect(struct qcam *q)
{ {
int reg, lastreg; int reg, lastreg;
int count = 0; int count = 0;
@ -358,41 +323,6 @@ static int qc_detect(struct qcam_device *q)
} }
} }
/* Reset the QuickCam. This uses the same sequence the Windows
* QuickPic program uses. Someone with a bi-directional port should
* check that bi-directional mode is detected right, and then
* implement bi-directional mode in qc_readbyte(). */
static void qc_reset(struct qcam_device *q)
{
switch (q->port_mode & QC_FORCE_MASK) {
case QC_FORCE_UNIDIR:
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
break;
case QC_FORCE_BIDIR:
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
break;
case QC_ANY:
write_lpcontrol(q, 0x20);
write_lpdata(q, 0x75);
if (read_lpdata(q) != 0x75)
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
else
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
break;
}
write_lpcontrol(q, 0xb);
udelay(250);
write_lpcontrol(q, 0xe);
qc_setscanmode(q); /* in case port_mode changed */
}
/* Decide which scan mode to use. There's no real requirement that /* Decide which scan mode to use. There's no real requirement that
* the scanmode match the resolution in q->height and q-> width -- the * the scanmode match the resolution in q->height and q-> width -- the
* camera takes the picture at the resolution specified in the * camera takes the picture at the resolution specified in the
@ -402,7 +332,7 @@ static void qc_reset(struct qcam_device *q)
* returned. If the scan is smaller, then the rest of the image * returned. If the scan is smaller, then the rest of the image
* returned contains garbage. */ * returned contains garbage. */
static int qc_setscanmode(struct qcam_device *q) static int qc_setscanmode(struct qcam *q)
{ {
int old_mode = q->mode; int old_mode = q->mode;
@ -442,10 +372,45 @@ static int qc_setscanmode(struct qcam_device *q)
} }
/* Reset the QuickCam. This uses the same sequence the Windows
* QuickPic program uses. Someone with a bi-directional port should
* check that bi-directional mode is detected right, and then
* implement bi-directional mode in qc_readbyte(). */
static void qc_reset(struct qcam *q)
{
switch (q->port_mode & QC_FORCE_MASK) {
case QC_FORCE_UNIDIR:
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
break;
case QC_FORCE_BIDIR:
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
break;
case QC_ANY:
write_lpcontrol(q, 0x20);
write_lpdata(q, 0x75);
if (read_lpdata(q) != 0x75)
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
else
q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
break;
}
write_lpcontrol(q, 0xb);
udelay(250);
write_lpcontrol(q, 0xe);
qc_setscanmode(q); /* in case port_mode changed */
}
/* Reset the QuickCam and program for brightness, contrast, /* Reset the QuickCam and program for brightness, contrast,
* white-balance, and resolution. */ * white-balance, and resolution. */
static void qc_set(struct qcam_device *q) static void qc_set(struct qcam *q)
{ {
int val; int val;
int val2; int val2;
@ -499,7 +464,7 @@ static void qc_set(struct qcam_device *q)
the supplied buffer. It returns the number of bytes read, the supplied buffer. It returns the number of bytes read,
or -1 on error. */ or -1 on error. */
static inline int qc_readbytes(struct qcam_device *q, char buffer[]) static inline int qc_readbytes(struct qcam *q, char buffer[])
{ {
int ret = 1; int ret = 1;
unsigned int hi, lo; unsigned int hi, lo;
@ -590,7 +555,7 @@ static inline int qc_readbytes(struct qcam_device *q, char buffer[])
* n=2^(bit depth)-1. Ask me for more details if you don't understand * n=2^(bit depth)-1. Ask me for more details if you don't understand
* this. */ * this. */
static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len) static long qc_capture(struct qcam *q, char __user *buf, unsigned long len)
{ {
int i, j, k, yield; int i, j, k, yield;
int bytes; int bytes;
@ -674,171 +639,206 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
* Video4linux interfacing * Video4linux interfacing
*/ */
static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) static int qcam_querycap(struct file *file, void *priv,
struct v4l2_capability *vcap)
{ {
struct video_device *dev = video_devdata(file); struct qcam *qcam = video_drvdata(file);
struct qcam_device *qcam = (struct qcam_device *)dev;
switch (cmd) { strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
case VIDIOCGCAP: strlcpy(vcap->card, "B&W Quickcam", sizeof(vcap->card));
{ strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
struct video_capability *b = arg; vcap->version = KERNEL_VERSION(0, 0, 2);
strcpy(b->name, "Quickcam"); vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
b->type = VID_TYPE_CAPTURE|VID_TYPE_SCALES|VID_TYPE_MONOCHROME;
b->channels = 1;
b->audios = 0;
b->maxwidth = 320;
b->maxheight = 240;
b->minwidth = 80;
b->minheight = 60;
return 0;
}
case VIDIOCGCHAN:
{
struct video_channel *v = arg;
if (v->channel != 0)
return -EINVAL;
v->flags = 0;
v->tuners = 0;
/* Good question.. its composite or SVHS so.. */
v->type = VIDEO_TYPE_CAMERA;
strcpy(v->name, "Camera");
return 0;
}
case VIDIOCSCHAN:
{
struct video_channel *v = arg;
if (v->channel != 0)
return -EINVAL;
return 0;
}
case VIDIOCGTUNER:
{
struct video_tuner *v = arg;
if (v->tuner)
return -EINVAL;
strcpy(v->name, "Format");
v->rangelow = 0;
v->rangehigh = 0;
v->flags = 0;
v->mode = VIDEO_MODE_AUTO;
return 0;
}
case VIDIOCSTUNER:
{
struct video_tuner *v = arg;
if (v->tuner)
return -EINVAL;
if (v->mode != VIDEO_MODE_AUTO)
return -EINVAL;
return 0;
}
case VIDIOCGPICT:
{
struct video_picture *p = arg;
p->colour = 0x8000;
p->hue = 0x8000;
p->brightness = qcam->brightness << 8;
p->contrast = qcam->contrast << 8;
p->whiteness = qcam->whitebal << 8;
p->depth = qcam->bpp;
p->palette = VIDEO_PALETTE_GREY;
return 0;
}
case VIDIOCSPICT:
{
struct video_picture *p = arg;
if (p->palette != VIDEO_PALETTE_GREY)
return -EINVAL;
if (p->depth != 4 && p->depth != 6)
return -EINVAL;
/*
* Now load the camera.
*/
qcam->brightness = p->brightness >> 8;
qcam->contrast = p->contrast >> 8;
qcam->whitebal = p->whiteness >> 8;
qcam->bpp = p->depth;
mutex_lock(&qcam->lock);
qc_setscanmode(qcam);
mutex_unlock(&qcam->lock);
qcam->status |= QC_PARAM_CHANGE;
return 0;
}
case VIDIOCSWIN:
{
struct video_window *vw = arg;
if (vw->flags)
return -EINVAL;
if (vw->clipcount)
return -EINVAL;
if (vw->height < 60 || vw->height > 240)
return -EINVAL;
if (vw->width < 80 || vw->width > 320)
return -EINVAL;
qcam->width = 320;
qcam->height = 240;
qcam->transfer_scale = 4;
if (vw->width >= 160 && vw->height >= 120)
qcam->transfer_scale = 2;
if (vw->width >= 320 && vw->height >= 240) {
qcam->width = 320;
qcam->height = 240;
qcam->transfer_scale = 1;
}
mutex_lock(&qcam->lock);
qc_setscanmode(qcam);
mutex_unlock(&qcam->lock);
/* We must update the camera before we grab. We could
just have changed the grab size */
qcam->status |= QC_PARAM_CHANGE;
/* Ok we figured out what to use from our wide choice */
return 0;
}
case VIDIOCGWIN:
{
struct video_window *vw = arg;
memset(vw, 0, sizeof(*vw));
vw->width = qcam->width / qcam->transfer_scale;
vw->height = qcam->height / qcam->transfer_scale;
return 0;
}
case VIDIOCKEY:
return 0;
case VIDIOCCAPTURE:
case VIDIOCGFBUF:
case VIDIOCSFBUF:
case VIDIOCGFREQ:
case VIDIOCSFREQ:
case VIDIOCGAUDIO:
case VIDIOCSAUDIO:
return -EINVAL;
default:
return -ENOIOCTLCMD;
}
return 0; return 0;
} }
static long qcam_ioctl(struct file *file, static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
unsigned int cmd, unsigned long arg)
{ {
return video_usercopy(file, cmd, arg, qcam_do_ioctl); if (vin->index > 0)
return -EINVAL;
strlcpy(vin->name, "Camera", sizeof(vin->name));
vin->type = V4L2_INPUT_TYPE_CAMERA;
vin->audioset = 0;
vin->tuner = 0;
vin->std = 0;
vin->status = 0;
return 0;
}
static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
{
*inp = 0;
return 0;
}
static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
{
return (inp > 0) ? -EINVAL : 0;
}
static int qcam_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qc)
{
switch (qc->id) {
case V4L2_CID_BRIGHTNESS:
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 180);
case V4L2_CID_CONTRAST:
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192);
case V4L2_CID_GAMMA:
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 105);
}
return -EINVAL;
}
static int qcam_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
struct qcam *qcam = video_drvdata(file);
int ret = 0;
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
ctrl->value = qcam->brightness;
break;
case V4L2_CID_CONTRAST:
ctrl->value = qcam->contrast;
break;
case V4L2_CID_GAMMA:
ctrl->value = qcam->whitebal;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static int qcam_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
struct qcam *qcam = video_drvdata(file);
int ret = 0;
mutex_lock(&qcam->lock);
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
qcam->brightness = ctrl->value;
break;
case V4L2_CID_CONTRAST:
qcam->contrast = ctrl->value;
break;
case V4L2_CID_GAMMA:
qcam->whitebal = ctrl->value;
break;
default:
ret = -EINVAL;
break;
}
if (ret == 0) {
qc_setscanmode(qcam);
qcam->status |= QC_PARAM_CHANGE;
}
mutex_unlock(&qcam->lock);
return ret;
}
static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
{
struct qcam *qcam = video_drvdata(file);
struct v4l2_pix_format *pix = &fmt->fmt.pix;
pix->width = qcam->width / qcam->transfer_scale;
pix->height = qcam->height / qcam->transfer_scale;
pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
pix->field = V4L2_FIELD_NONE;
pix->bytesperline = qcam->width;
pix->sizeimage = qcam->width * qcam->height;
/* Just a guess */
pix->colorspace = V4L2_COLORSPACE_SRGB;
return 0;
}
static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
{
struct v4l2_pix_format *pix = &fmt->fmt.pix;
if (pix->height <= 60 || pix->width <= 80) {
pix->height = 60;
pix->width = 80;
} else if (pix->height <= 120 || pix->width <= 160) {
pix->height = 120;
pix->width = 160;
} else {
pix->height = 240;
pix->width = 320;
}
if (pix->pixelformat != V4L2_PIX_FMT_Y4 &&
pix->pixelformat != V4L2_PIX_FMT_Y6)
pix->pixelformat = V4L2_PIX_FMT_Y4;
pix->field = V4L2_FIELD_NONE;
pix->bytesperline = pix->width;
pix->sizeimage = pix->width * pix->height;
/* Just a guess */
pix->colorspace = V4L2_COLORSPACE_SRGB;
return 0;
}
static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
{
struct qcam *qcam = video_drvdata(file);
struct v4l2_pix_format *pix = &fmt->fmt.pix;
int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
if (ret)
return ret;
qcam->width = 320;
qcam->height = 240;
if (pix->height == 60)
qcam->transfer_scale = 4;
else if (pix->height == 120)
qcam->transfer_scale = 2;
else
qcam->transfer_scale = 1;
if (pix->pixelformat == V4L2_PIX_FMT_Y6)
qcam->bpp = 6;
else
qcam->bpp = 4;
mutex_lock(&qcam->lock);
qc_setscanmode(qcam);
/* We must update the camera before we grab. We could
just have changed the grab size */
qcam->status |= QC_PARAM_CHANGE;
mutex_unlock(&qcam->lock);
return 0;
}
static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
{
static struct v4l2_fmtdesc formats[] = {
{ 0, 0, 0,
"4-Bit Monochrome", V4L2_PIX_FMT_Y4,
{ 0, 0, 0, 0 }
},
{ 0, 0, 0,
"6-Bit Monochrome", V4L2_PIX_FMT_Y6,
{ 0, 0, 0, 0 }
},
};
enum v4l2_buf_type type = fmt->type;
if (fmt->index > 1)
return -EINVAL;
*fmt = formats[fmt->index];
fmt->type = type;
return 0;
} }
static ssize_t qcam_read(struct file *file, char __user *buf, static ssize_t qcam_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct video_device *v = video_devdata(file); struct qcam *qcam = video_drvdata(file);
struct qcam_device *qcam = (struct qcam_device *)v;
int len; int len;
parport_claim_or_block(qcam->pdev); parport_claim_or_block(qcam->pdev);
@ -858,43 +858,112 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
return len; return len;
} }
static int qcam_exclusive_open(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam = (struct qcam_device *)dev;
return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
}
static int qcam_exclusive_release(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam = (struct qcam_device *)dev;
clear_bit(0, &qcam->in_use);
return 0;
}
static const struct v4l2_file_operations qcam_fops = { static const struct v4l2_file_operations qcam_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = qcam_exclusive_open, .ioctl = video_ioctl2,
.release = qcam_exclusive_release,
.ioctl = qcam_ioctl,
.read = qcam_read, .read = qcam_read,
}; };
static struct video_device qcam_template = {
.name = "Connectix Quickcam", static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
.fops = &qcam_fops, .vidioc_querycap = qcam_querycap,
.release = video_device_release_empty, .vidioc_g_input = qcam_g_input,
.vidioc_s_input = qcam_s_input,
.vidioc_enum_input = qcam_enum_input,
.vidioc_queryctrl = qcam_queryctrl,
.vidioc_g_ctrl = qcam_g_ctrl,
.vidioc_s_ctrl = qcam_s_ctrl,
.vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
}; };
#define MAX_CAMS 4 /* Initialize the QuickCam driver control structure. This is where
static struct qcam_device *qcams[MAX_CAMS]; * defaults are set for people who don't have a config file.*/
static unsigned int num_cams;
static struct qcam *qcam_init(struct parport *port)
{
struct qcam *qcam;
struct v4l2_device *v4l2_dev;
qcam = kzalloc(sizeof(struct qcam), GFP_KERNEL);
if (qcam == NULL)
return NULL;
v4l2_dev = &qcam->v4l2_dev;
strlcpy(v4l2_dev->name, "bw-qcam", sizeof(v4l2_dev->name));
if (v4l2_device_register(NULL, v4l2_dev) < 0) {
v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
return NULL;
}
qcam->pport = port;
qcam->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
NULL, 0, NULL);
if (qcam->pdev == NULL) {
v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
kfree(qcam);
return NULL;
}
strlcpy(qcam->vdev.name, "Connectix QuickCam", sizeof(qcam->vdev.name));
qcam->vdev.v4l2_dev = v4l2_dev;
qcam->vdev.fops = &qcam_fops;
qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
qcam->vdev.release = video_device_release_empty;
video_set_drvdata(&qcam->vdev, qcam);
mutex_init(&qcam->lock);
qcam->port_mode = (QC_ANY | QC_NOTSET);
qcam->width = 320;
qcam->height = 240;
qcam->bpp = 4;
qcam->transfer_scale = 2;
qcam->contrast = 192;
qcam->brightness = 180;
qcam->whitebal = 105;
qcam->top = 1;
qcam->left = 14;
qcam->mode = -1;
qcam->status = QC_PARAM_CHANGE;
return qcam;
}
static int qc_calibrate(struct qcam *q)
{
/*
* Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
* The white balance is an individual value for each
* quickcam.
*/
int value;
int count = 0;
qc_command(q, 27); /* AutoAdjustOffset */
qc_command(q, 0); /* Dummy Parameter, ignored by the camera */
/* GetOffset (33) will read 255 until autocalibration */
/* is finished. After that, a value of 1-254 will be */
/* returned. */
do {
qc_command(q, 33);
value = qc_readparam(q);
mdelay(1);
schedule();
count++;
} while (value == 0xff && count < 2048);
q->whitebal = value;
return value;
}
static int init_bwqcam(struct parport *port) static int init_bwqcam(struct parport *port)
{ {
struct qcam_device *qcam; struct qcam *qcam;
if (num_cams == MAX_CAMS) { if (num_cams == MAX_CAMS) {
printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS); printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS);
@ -919,7 +988,7 @@ static int init_bwqcam(struct parport *port)
parport_release(qcam->pdev); parport_release(qcam->pdev);
printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name); v4l2_info(&qcam->v4l2_dev, "Connectix Quickcam on %s\n", qcam->pport->name);
if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
parport_unregister_device(qcam->pdev); parport_unregister_device(qcam->pdev);
@ -932,7 +1001,7 @@ static int init_bwqcam(struct parport *port)
return 0; return 0;
} }
static void close_bwqcam(struct qcam_device *qcam) static void close_bwqcam(struct qcam *qcam)
{ {
video_unregister_device(&qcam->vdev); video_unregister_device(&qcam->vdev);
parport_unregister_device(qcam->pdev); parport_unregister_device(qcam->pdev);
@ -983,7 +1052,7 @@ static void bwqcam_detach(struct parport *port)
{ {
int i; int i;
for (i = 0; i < num_cams; i++) { for (i = 0; i < num_cams; i++) {
struct qcam_device *qcam = qcams[i]; struct qcam *qcam = qcams[i];
if (qcam && qcam->pdev->port == port) { if (qcam && qcam->pdev->port == port) {
qcams[i] = NULL; qcams[i] = NULL;
close_bwqcam(qcam); close_bwqcam(qcam);

View File

@ -1,69 +0,0 @@
/*
* Video4Linux bw-qcam driver
*
* Derived from code..
*/
/******************************************************************
Copyright (C) 1996 by Scott Laird
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL SCOTT LAIRD BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
******************************************************************/
/* One from column A... */
#define QC_NOTSET 0
#define QC_UNIDIR 1
#define QC_BIDIR 2
#define QC_SERIAL 3
/* ... and one from column B */
#define QC_ANY 0x00
#define QC_FORCE_UNIDIR 0x10
#define QC_FORCE_BIDIR 0x20
#define QC_FORCE_SERIAL 0x30
/* in the port_mode member */
#define QC_MODE_MASK 0x07
#define QC_FORCE_MASK 0x70
#define MAX_HEIGHT 243
#define MAX_WIDTH 336
/* Bit fields for status flags */
#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */
struct qcam_device {
struct video_device vdev;
struct pardevice *pdev;
struct parport *pport;
struct mutex lock;
int width, height;
int bpp;
int mode;
int contrast, brightness, whitebal;
int port_mode;
int transfer_scale;
int top, left;
int status;
unsigned int saved_bits;
unsigned long in_use;
};

View File

@ -33,15 +33,17 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/videodev.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/version.h>
#include <linux/videodev2.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <media/v4l2-device.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
struct qcam_device { struct qcam {
struct v4l2_device v4l2_dev;
struct video_device vdev; struct video_device vdev;
struct pardevice *pdev; struct pardevice *pdev;
struct parport *pport; struct parport *pport;
@ -51,7 +53,6 @@ struct qcam_device {
int contrast, brightness, whitebal; int contrast, brightness, whitebal;
int top, left; int top, left;
unsigned int bidirectional; unsigned int bidirectional;
unsigned long in_use;
struct mutex lock; struct mutex lock;
}; };
@ -68,33 +69,45 @@ struct qcam_device {
#define QC_DECIMATION_2 2 #define QC_DECIMATION_2 2
#define QC_DECIMATION_4 4 #define QC_DECIMATION_4 4
#define BANNER "Colour QuickCam for Video4Linux v0.05" #define BANNER "Colour QuickCam for Video4Linux v0.06"
static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 }; static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
static int probe = 2; static int probe = 2;
static int force_rgb; static int force_rgb;
static int video_nr = -1; static int video_nr = -1;
static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i) /* FIXME: parport=auto would never have worked, surely? --RR */
MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
"probe=<0|1|2> for camera detection method\n"
"force_rgb=<0|1> for RGB data format (default BGR)");
module_param_array(parport, int, NULL, 0);
module_param(probe, int, 0);
module_param(force_rgb, bool, 0);
module_param(video_nr, int, 0);
static struct qcam *qcams[MAX_CAMS];
static unsigned int num_cams;
static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
{ {
/* note: the QC specs refer to the PCAck pin by voltage, not /* note: the QC specs refer to the PCAck pin by voltage, not
software level. PC ports have builtin inverters. */ software level. PC ports have builtin inverters. */
parport_frob_control(qcam->pport, 8, i ? 8 : 0); parport_frob_control(qcam->pport, 8, i ? 8 : 0);
} }
static inline unsigned int qcam_ready1(struct qcam_device *qcam) static inline unsigned int qcam_ready1(struct qcam *qcam)
{ {
return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0; return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
} }
static inline unsigned int qcam_ready2(struct qcam_device *qcam) static inline unsigned int qcam_ready2(struct qcam *qcam)
{ {
return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0; return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
} }
static unsigned int qcam_await_ready1(struct qcam_device *qcam, static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
int value)
{ {
struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
unsigned long oldjiffies = jiffies; unsigned long oldjiffies = jiffies;
unsigned int i; unsigned int i;
@ -112,14 +125,15 @@ static unsigned int qcam_await_ready1(struct qcam_device *qcam,
} }
/* Probably somebody pulled the plug out. Not much we can do. */ /* Probably somebody pulled the plug out. Not much we can do. */
printk(KERN_ERR "c-qcam: ready1 timeout (%d) %x %x\n", value, v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value,
parport_read_status(qcam->pport), parport_read_status(qcam->pport),
parport_read_control(qcam->pport)); parport_read_control(qcam->pport));
return 1; return 1;
} }
static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value) static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
{ {
struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
unsigned long oldjiffies = jiffies; unsigned long oldjiffies = jiffies;
unsigned int i; unsigned int i;
@ -137,14 +151,14 @@ static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
} }
/* Probably somebody pulled the plug out. Not much we can do. */ /* Probably somebody pulled the plug out. Not much we can do. */
printk(KERN_ERR "c-qcam: ready2 timeout (%d) %x %x %x\n", value, v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value,
parport_read_status(qcam->pport), parport_read_status(qcam->pport),
parport_read_control(qcam->pport), parport_read_control(qcam->pport),
parport_read_data(qcam->pport)); parport_read_data(qcam->pport));
return 1; return 1;
} }
static int qcam_read_data(struct qcam_device *qcam) static int qcam_read_data(struct qcam *qcam)
{ {
unsigned int idata; unsigned int idata;
@ -159,21 +173,22 @@ static int qcam_read_data(struct qcam_device *qcam)
return idata; return idata;
} }
static int qcam_write_data(struct qcam_device *qcam, unsigned int data) static int qcam_write_data(struct qcam *qcam, unsigned int data)
{ {
struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
unsigned int idata; unsigned int idata;
parport_write_data(qcam->pport, data); parport_write_data(qcam->pport, data);
idata = qcam_read_data(qcam); idata = qcam_read_data(qcam);
if (data != idata) { if (data != idata) {
printk(KERN_WARNING "cqcam: sent %x but received %x\n", data, v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
idata); idata);
return 1; return 1;
} }
return 0; return 0;
} }
static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned int data) static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
{ {
if (qcam_write_data(qcam, cmd)) if (qcam_write_data(qcam, cmd))
return -1; return -1;
@ -182,14 +197,14 @@ static inline int qcam_set(struct qcam_device *qcam, unsigned int cmd, unsigned
return 0; return 0;
} }
static inline int qcam_get(struct qcam_device *qcam, unsigned int cmd) static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
{ {
if (qcam_write_data(qcam, cmd)) if (qcam_write_data(qcam, cmd))
return -1; return -1;
return qcam_read_data(qcam); return qcam_read_data(qcam);
} }
static int qc_detect(struct qcam_device *qcam) static int qc_detect(struct qcam *qcam)
{ {
unsigned int stat, ostat, i, count = 0; unsigned int stat, ostat, i, count = 0;
@ -246,7 +261,7 @@ static int qc_detect(struct qcam_device *qcam)
return 0; return 0;
} }
static void qc_reset(struct qcam_device *qcam) static void qc_reset(struct qcam *qcam)
{ {
parport_write_control(qcam->pport, 0xc); parport_write_control(qcam->pport, 0xc);
parport_write_control(qcam->pport, 0x8); parport_write_control(qcam->pport, 0x8);
@ -258,55 +273,55 @@ static void qc_reset(struct qcam_device *qcam)
/* Reset the QuickCam and program for brightness, contrast, /* Reset the QuickCam and program for brightness, contrast,
* white-balance, and resolution. */ * white-balance, and resolution. */
static void qc_setup(struct qcam_device *q) static void qc_setup(struct qcam *qcam)
{ {
qc_reset(q); qc_reset(qcam);
/* Set the brightness. */ /* Set the brightness. */
qcam_set(q, 11, q->brightness); qcam_set(qcam, 11, qcam->brightness);
/* Set the height and width. These refer to the actual /* Set the height and width. These refer to the actual
CCD area *before* applying the selected decimation. */ CCD area *before* applying the selected decimation. */
qcam_set(q, 17, q->ccd_height); qcam_set(qcam, 17, qcam->ccd_height);
qcam_set(q, 19, q->ccd_width / 2); qcam_set(qcam, 19, qcam->ccd_width / 2);
/* Set top and left. */ /* Set top and left. */
qcam_set(q, 0xd, q->top); qcam_set(qcam, 0xd, qcam->top);
qcam_set(q, 0xf, q->left); qcam_set(qcam, 0xf, qcam->left);
/* Set contrast and white balance. */ /* Set contrast and white balance. */
qcam_set(q, 0x19, q->contrast); qcam_set(qcam, 0x19, qcam->contrast);
qcam_set(q, 0x1f, q->whitebal); qcam_set(qcam, 0x1f, qcam->whitebal);
/* Set the speed. */ /* Set the speed. */
qcam_set(q, 45, 2); qcam_set(qcam, 45, 2);
} }
/* Read some bytes from the camera and put them in the buffer. /* Read some bytes from the camera and put them in the buffer.
nbytes should be a multiple of 3, because bidirectional mode gives nbytes should be a multiple of 3, because bidirectional mode gives
us three bytes at a time. */ us three bytes at a time. */
static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, unsigned int nbytes) static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
{ {
unsigned int bytes = 0; unsigned int bytes = 0;
qcam_set_ack(q, 0); qcam_set_ack(qcam, 0);
if (q->bidirectional) { if (qcam->bidirectional) {
/* It's a bidirectional port */ /* It's a bidirectional port */
while (bytes < nbytes) { while (bytes < nbytes) {
unsigned int lo1, hi1, lo2, hi2; unsigned int lo1, hi1, lo2, hi2;
unsigned char r, g, b; unsigned char r, g, b;
if (qcam_await_ready2(q, 1)) if (qcam_await_ready2(qcam, 1))
return bytes; return bytes;
lo1 = parport_read_data(q->pport) >> 1; lo1 = parport_read_data(qcam->pport) >> 1;
hi1 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
qcam_set_ack(q, 1); qcam_set_ack(qcam, 1);
if (qcam_await_ready2(q, 0)) if (qcam_await_ready2(qcam, 0))
return bytes; return bytes;
lo2 = parport_read_data(q->pport) >> 1; lo2 = parport_read_data(qcam->pport) >> 1;
hi2 = ((parport_read_status(q->pport) >> 3) & 0x1f) ^ 0x10; hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
qcam_set_ack(q, 0); qcam_set_ack(qcam, 0);
r = lo1 | ((hi1 & 1) << 7); r = lo1 | ((hi1 & 1) << 7);
g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1); g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1);
b = lo2 | ((hi2 & 1) << 7); b = lo2 | ((hi2 & 1) << 7);
@ -328,14 +343,14 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, u
while (bytes < nbytes) { while (bytes < nbytes) {
unsigned int hi, lo; unsigned int hi, lo;
if (qcam_await_ready1(q, 1)) if (qcam_await_ready1(qcam, 1))
return bytes; return bytes;
hi = (parport_read_status(q->pport) & 0xf0); hi = (parport_read_status(qcam->pport) & 0xf0);
qcam_set_ack(q, 1); qcam_set_ack(qcam, 1);
if (qcam_await_ready1(q, 0)) if (qcam_await_ready1(qcam, 0))
return bytes; return bytes;
lo = (parport_read_status(q->pport) & 0xf0); lo = (parport_read_status(qcam->pport) & 0xf0);
qcam_set_ack(q, 0); qcam_set_ack(qcam, 0);
/* flip some bits */ /* flip some bits */
rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88; rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
if (i >= 2) { if (i >= 2) {
@ -361,10 +376,11 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, u
#define BUFSZ 150 #define BUFSZ 150
static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long len) static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
{ {
struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
unsigned lines, pixelsperline, bitsperxfer; unsigned lines, pixelsperline, bitsperxfer;
unsigned int is_bi_dir = q->bidirectional; unsigned int is_bi_dir = qcam->bidirectional;
size_t wantlen, outptr = 0; size_t wantlen, outptr = 0;
char tmpbuf[BUFSZ]; char tmpbuf[BUFSZ];
@ -373,10 +389,10 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
/* Wait for camera to become ready */ /* Wait for camera to become ready */
for (;;) { for (;;) {
int i = qcam_get(q, 41); int i = qcam_get(qcam, 41);
if (i == -1) { if (i == -1) {
qc_setup(q); qc_setup(qcam);
return -EIO; return -EIO;
} }
if ((i & 0x80) == 0) if ((i & 0x80) == 0)
@ -384,25 +400,25 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
schedule(); schedule();
} }
if (qcam_set(q, 7, (q->mode | (is_bi_dir ? 1 : 0)) + 1)) if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
return -EIO; return -EIO;
lines = q->height; lines = qcam->height;
pixelsperline = q->width; pixelsperline = qcam->width;
bitsperxfer = (is_bi_dir) ? 24 : 8; bitsperxfer = (is_bi_dir) ? 24 : 8;
if (is_bi_dir) { if (is_bi_dir) {
/* Turn the port around */ /* Turn the port around */
parport_data_reverse(q->pport); parport_data_reverse(qcam->pport);
mdelay(3); mdelay(3);
qcam_set_ack(q, 0); qcam_set_ack(qcam, 0);
if (qcam_await_ready1(q, 1)) { if (qcam_await_ready1(qcam, 1)) {
qc_setup(q); qc_setup(qcam);
return -EIO; return -EIO;
} }
qcam_set_ack(q, 1); qcam_set_ack(qcam, 1);
if (qcam_await_ready1(q, 0)) { if (qcam_await_ready1(qcam, 0)) {
qc_setup(q); qc_setup(qcam);
return -EIO; return -EIO;
} }
} }
@ -413,7 +429,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
size_t t, s; size_t t, s;
s = (wantlen > BUFSZ) ? BUFSZ : wantlen; s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
t = qcam_read_bytes(q, tmpbuf, s); t = qcam_read_bytes(qcam, tmpbuf, s);
if (outptr < len) { if (outptr < len) {
size_t sz = len - outptr; size_t sz = len - outptr;
@ -432,10 +448,10 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
len = outptr; len = outptr;
if (wantlen) { if (wantlen) {
printk(KERN_ERR "qcam: short read.\n"); v4l2_err(v4l2_dev, "short read.\n");
if (is_bi_dir) if (is_bi_dir)
parport_data_forward(q->pport); parport_data_forward(qcam->pport);
qc_setup(q); qc_setup(qcam);
return len; return len;
} }
@ -443,49 +459,49 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
int l; int l;
do { do {
l = qcam_read_bytes(q, tmpbuf, 3); l = qcam_read_bytes(qcam, tmpbuf, 3);
cond_resched(); cond_resched();
} while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e)); } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
if (force_rgb) { if (force_rgb) {
if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
printk(KERN_ERR "qcam: bad EOF\n"); v4l2_err(v4l2_dev, "bad EOF\n");
} else { } else {
if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
printk(KERN_ERR "qcam: bad EOF\n"); v4l2_err(v4l2_dev, "bad EOF\n");
} }
qcam_set_ack(q, 0); qcam_set_ack(qcam, 0);
if (qcam_await_ready1(q, 1)) { if (qcam_await_ready1(qcam, 1)) {
printk(KERN_ERR "qcam: no ack after EOF\n"); v4l2_err(v4l2_dev, "no ack after EOF\n");
parport_data_forward(q->pport); parport_data_forward(qcam->pport);
qc_setup(q); qc_setup(qcam);
return len; return len;
} }
parport_data_forward(q->pport); parport_data_forward(qcam->pport);
mdelay(3); mdelay(3);
qcam_set_ack(q, 1); qcam_set_ack(qcam, 1);
if (qcam_await_ready1(q, 0)) { if (qcam_await_ready1(qcam, 0)) {
printk(KERN_ERR "qcam: no ack to port turnaround\n"); v4l2_err(v4l2_dev, "no ack to port turnaround\n");
qc_setup(q); qc_setup(qcam);
return len; return len;
} }
} else { } else {
int l; int l;
do { do {
l = qcam_read_bytes(q, tmpbuf, 1); l = qcam_read_bytes(qcam, tmpbuf, 1);
cond_resched(); cond_resched();
} while (l && tmpbuf[0] == 0x7e); } while (l && tmpbuf[0] == 0x7e);
l = qcam_read_bytes(q, tmpbuf + 1, 2); l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
if (force_rgb) { if (force_rgb) {
if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf) if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
printk(KERN_ERR "qcam: bad EOF\n"); v4l2_err(v4l2_dev, "bad EOF\n");
} else { } else {
if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe) if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
printk(KERN_ERR "qcam: bad EOF\n"); v4l2_err(v4l2_dev, "bad EOF\n");
} }
} }
qcam_write_data(q, 0); qcam_write_data(qcam, 0);
return len; return len;
} }
@ -493,184 +509,202 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
* Video4linux interfacing * Video4linux interfacing
*/ */
static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg) static int qcam_querycap(struct file *file, void *priv,
struct v4l2_capability *vcap)
{ {
struct video_device *dev = video_devdata(file); struct qcam *qcam = video_drvdata(file);
struct qcam_device *qcam = (struct qcam_device *)dev;
switch (cmd) { strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
case VIDIOCGCAP: strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
{ strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
struct video_capability *b = arg; vcap->version = KERNEL_VERSION(0, 0, 3);
vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
strcpy(b->name, "Quickcam");
b->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
b->channels = 1;
b->audios = 0;
b->maxwidth = 320;
b->maxheight = 240;
b->minwidth = 80;
b->minheight = 60;
return 0;
}
case VIDIOCGCHAN:
{
struct video_channel *v = arg;
if (v->channel != 0)
return -EINVAL;
v->flags = 0;
v->tuners = 0;
/* Good question.. its composite or SVHS so.. */
v->type = VIDEO_TYPE_CAMERA;
strcpy(v->name, "Camera");
return 0;
}
case VIDIOCSCHAN:
{
struct video_channel *v = arg;
if (v->channel != 0)
return -EINVAL;
return 0;
}
case VIDIOCGTUNER:
{
struct video_tuner *v = arg;
if (v->tuner)
return -EINVAL;
memset(v, 0, sizeof(*v));
strcpy(v->name, "Format");
v->mode = VIDEO_MODE_AUTO;
return 0;
}
case VIDIOCSTUNER:
{
struct video_tuner *v = arg;
if (v->tuner)
return -EINVAL;
if (v->mode != VIDEO_MODE_AUTO)
return -EINVAL;
return 0;
}
case VIDIOCGPICT:
{
struct video_picture *p = arg;
p->colour = 0x8000;
p->hue = 0x8000;
p->brightness = qcam->brightness << 8;
p->contrast = qcam->contrast << 8;
p->whiteness = qcam->whitebal << 8;
p->depth = 24;
p->palette = VIDEO_PALETTE_RGB24;
return 0;
}
case VIDIOCSPICT:
{
struct video_picture *p = arg;
/*
* Sanity check args
*/
if (p->depth != 24 || p->palette != VIDEO_PALETTE_RGB24)
return -EINVAL;
/*
* Now load the camera.
*/
qcam->brightness = p->brightness >> 8;
qcam->contrast = p->contrast >> 8;
qcam->whitebal = p->whiteness >> 8;
mutex_lock(&qcam->lock);
parport_claim_or_block(qcam->pdev);
qc_setup(qcam);
parport_release(qcam->pdev);
mutex_unlock(&qcam->lock);
return 0;
}
case VIDIOCSWIN:
{
struct video_window *vw = arg;
if (vw->flags)
return -EINVAL;
if (vw->clipcount)
return -EINVAL;
if (vw->height < 60 || vw->height > 240)
return -EINVAL;
if (vw->width < 80 || vw->width > 320)
return -EINVAL;
qcam->width = 80;
qcam->height = 60;
qcam->mode = QC_DECIMATION_4;
if (vw->width >= 160 && vw->height >= 120) {
qcam->width = 160;
qcam->height = 120;
qcam->mode = QC_DECIMATION_2;
}
if (vw->width >= 320 && vw->height >= 240) {
qcam->width = 320;
qcam->height = 240;
qcam->mode = QC_DECIMATION_1;
}
qcam->mode |= QC_MILLIONS;
#if 0
if (vw->width >= 640 && vw->height >= 480) {
qcam->width = 640;
qcam->height = 480;
qcam->mode = QC_BILLIONS | QC_DECIMATION_1;
}
#endif
/* Ok we figured out what to use from our
wide choice */
mutex_lock(&qcam->lock);
parport_claim_or_block(qcam->pdev);
qc_setup(qcam);
parport_release(qcam->pdev);
mutex_unlock(&qcam->lock);
return 0;
}
case VIDIOCGWIN:
{
struct video_window *vw = arg;
memset(vw, 0, sizeof(*vw));
vw->width = qcam->width;
vw->height = qcam->height;
return 0;
}
case VIDIOCKEY:
return 0;
case VIDIOCCAPTURE:
case VIDIOCGFBUF:
case VIDIOCSFBUF:
case VIDIOCGFREQ:
case VIDIOCSFREQ:
case VIDIOCGAUDIO:
case VIDIOCSAUDIO:
return -EINVAL;
default:
return -ENOIOCTLCMD;
}
return 0; return 0;
} }
static long qcam_ioctl(struct file *file, static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
unsigned int cmd, unsigned long arg)
{ {
return video_usercopy(file, cmd, arg, qcam_do_ioctl); if (vin->index > 0)
return -EINVAL;
strlcpy(vin->name, "Camera", sizeof(vin->name));
vin->type = V4L2_INPUT_TYPE_CAMERA;
vin->audioset = 0;
vin->tuner = 0;
vin->std = 0;
vin->status = 0;
return 0;
}
static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
{
*inp = 0;
return 0;
}
static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
{
return (inp > 0) ? -EINVAL : 0;
}
static int qcam_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qc)
{
switch (qc->id) {
case V4L2_CID_BRIGHTNESS:
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 240);
case V4L2_CID_CONTRAST:
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 192);
case V4L2_CID_GAMMA:
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
}
return -EINVAL;
}
static int qcam_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
struct qcam *qcam = video_drvdata(file);
int ret = 0;
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
ctrl->value = qcam->brightness;
break;
case V4L2_CID_CONTRAST:
ctrl->value = qcam->contrast;
break;
case V4L2_CID_GAMMA:
ctrl->value = qcam->whitebal;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static int qcam_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
struct qcam *qcam = video_drvdata(file);
int ret = 0;
mutex_lock(&qcam->lock);
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
qcam->brightness = ctrl->value;
break;
case V4L2_CID_CONTRAST:
qcam->contrast = ctrl->value;
break;
case V4L2_CID_GAMMA:
qcam->whitebal = ctrl->value;
break;
default:
ret = -EINVAL;
break;
}
if (ret == 0) {
parport_claim_or_block(qcam->pdev);
qc_setup(qcam);
parport_release(qcam->pdev);
}
mutex_unlock(&qcam->lock);
return ret;
}
static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
{
struct qcam *qcam = video_drvdata(file);
struct v4l2_pix_format *pix = &fmt->fmt.pix;
pix->width = qcam->width;
pix->height = qcam->height;
pix->pixelformat = V4L2_PIX_FMT_RGB24;
pix->field = V4L2_FIELD_NONE;
pix->bytesperline = 3 * qcam->width;
pix->sizeimage = 3 * qcam->width * qcam->height;
/* Just a guess */
pix->colorspace = V4L2_COLORSPACE_SRGB;
return 0;
}
static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
{
struct v4l2_pix_format *pix = &fmt->fmt.pix;
if (pix->height < 60 || pix->width < 80) {
pix->height = 60;
pix->width = 80;
} else if (pix->height < 120 || pix->width < 160) {
pix->height = 120;
pix->width = 160;
} else {
pix->height = 240;
pix->width = 320;
}
pix->pixelformat = V4L2_PIX_FMT_RGB24;
pix->field = V4L2_FIELD_NONE;
pix->bytesperline = 3 * pix->width;
pix->sizeimage = 3 * pix->width * pix->height;
/* Just a guess */
pix->colorspace = V4L2_COLORSPACE_SRGB;
return 0;
}
static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
{
struct qcam *qcam = video_drvdata(file);
struct v4l2_pix_format *pix = &fmt->fmt.pix;
int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
if (ret)
return ret;
switch (pix->height) {
case 60:
qcam->mode = QC_DECIMATION_4;
break;
case 120:
qcam->mode = QC_DECIMATION_2;
break;
default:
qcam->mode = QC_DECIMATION_1;
break;
}
mutex_lock(&qcam->lock);
qcam->mode |= QC_MILLIONS;
qcam->height = pix->height;
qcam->width = pix->width;
parport_claim_or_block(qcam->pdev);
qc_setup(qcam);
parport_release(qcam->pdev);
mutex_unlock(&qcam->lock);
return 0;
}
static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
{
static struct v4l2_fmtdesc formats[] = {
{ 0, 0, 0,
"RGB 8:8:8", V4L2_PIX_FMT_RGB24,
{ 0, 0, 0, 0 }
},
};
enum v4l2_buf_type type = fmt->type;
if (fmt->index > 0)
return -EINVAL;
*fmt = formats[fmt->index];
fmt->type = type;
return 0;
} }
static ssize_t qcam_read(struct file *file, char __user *buf, static ssize_t qcam_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct video_device *v = video_devdata(file); struct qcam *qcam = video_drvdata(file);
struct qcam_device *qcam = (struct qcam_device *)v;
int len; int len;
mutex_lock(&qcam->lock); mutex_lock(&qcam->lock);
@ -682,81 +716,80 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
return len; return len;
} }
static int qcam_exclusive_open(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam = (struct qcam_device *)dev;
return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
}
static int qcam_exclusive_release(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam = (struct qcam_device *)dev;
clear_bit(0, &qcam->in_use);
return 0;
}
/* video device template */
static const struct v4l2_file_operations qcam_fops = { static const struct v4l2_file_operations qcam_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = qcam_exclusive_open, .ioctl = video_ioctl2,
.release = qcam_exclusive_release,
.ioctl = qcam_ioctl,
.read = qcam_read, .read = qcam_read,
}; };
static struct video_device qcam_template = { static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
.name = "Colour QuickCam", .vidioc_querycap = qcam_querycap,
.fops = &qcam_fops, .vidioc_g_input = qcam_g_input,
.release = video_device_release_empty, .vidioc_s_input = qcam_s_input,
.vidioc_enum_input = qcam_enum_input,
.vidioc_queryctrl = qcam_queryctrl,
.vidioc_g_ctrl = qcam_g_ctrl,
.vidioc_s_ctrl = qcam_s_ctrl,
.vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
}; };
/* Initialize the QuickCam driver control structure. */ /* Initialize the QuickCam driver control structure. */
static struct qcam_device *qcam_init(struct parport *port) static struct qcam *qcam_init(struct parport *port)
{ {
struct qcam_device *q; struct qcam *qcam;
struct v4l2_device *v4l2_dev;
q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL); qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
if (q == NULL) if (qcam == NULL)
return NULL; return NULL;
q->pport = port; v4l2_dev = &qcam->v4l2_dev;
q->pdev = parport_register_device(port, "c-qcam", NULL, NULL, strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
NULL, 0, NULL);
q->bidirectional = (q->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0; if (v4l2_device_register(NULL, v4l2_dev) < 0) {
v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
if (q->pdev == NULL) {
printk(KERN_ERR "c-qcam: couldn't register for %s.\n",
port->name);
kfree(q);
return NULL; return NULL;
} }
memcpy(&q->vdev, &qcam_template, sizeof(qcam_template)); qcam->pport = port;
qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
NULL, 0, NULL);
mutex_init(&q->lock); qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
q->width = q->ccd_width = 320;
q->height = q->ccd_height = 240; if (qcam->pdev == NULL) {
q->mode = QC_MILLIONS | QC_DECIMATION_1; v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
q->contrast = 192; kfree(qcam);
q->brightness = 240; return NULL;
q->whitebal = 128; }
q->top = 1;
q->left = 14; strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name));
return q; qcam->vdev.v4l2_dev = v4l2_dev;
qcam->vdev.fops = &qcam_fops;
qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
qcam->vdev.release = video_device_release_empty;
video_set_drvdata(&qcam->vdev, qcam);
mutex_init(&qcam->lock);
qcam->width = qcam->ccd_width = 320;
qcam->height = qcam->ccd_height = 240;
qcam->mode = QC_MILLIONS | QC_DECIMATION_1;
qcam->contrast = 192;
qcam->brightness = 240;
qcam->whitebal = 128;
qcam->top = 1;
qcam->left = 14;
return qcam;
} }
static struct qcam_device *qcams[MAX_CAMS];
static unsigned int num_cams;
static int init_cqcam(struct parport *port) static int init_cqcam(struct parport *port)
{ {
struct qcam_device *qcam; struct qcam *qcam;
struct v4l2_device *v4l2_dev;
if (parport[0] != -1) { if (parport[0] != -1) {
/* The user gave specific instructions */ /* The user gave specific instructions */
@ -777,6 +810,8 @@ static int init_cqcam(struct parport *port)
if (qcam == NULL) if (qcam == NULL)
return -ENODEV; return -ENODEV;
v4l2_dev = &qcam->v4l2_dev;
parport_claim_or_block(qcam->pdev); parport_claim_or_block(qcam->pdev);
qc_reset(qcam); qc_reset(qcam);
@ -793,14 +828,14 @@ static int init_cqcam(struct parport *port)
parport_release(qcam->pdev); parport_release(qcam->pdev);
if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
printk(KERN_ERR "Unable to register Colour QuickCam on %s\n", v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n",
qcam->pport->name); qcam->pport->name);
parport_unregister_device(qcam->pdev); parport_unregister_device(qcam->pdev);
kfree(qcam); kfree(qcam);
return -ENODEV; return -ENODEV;
} }
printk(KERN_INFO "%s: Colour QuickCam found on %s\n", v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
video_device_node_name(&qcam->vdev), qcam->pport->name); video_device_node_name(&qcam->vdev), qcam->pport->name);
qcams[num_cams++] = qcam; qcams[num_cams++] = qcam;
@ -808,7 +843,7 @@ static int init_cqcam(struct parport *port)
return 0; return 0;
} }
static void close_cqcam(struct qcam_device *qcam) static void close_cqcam(struct qcam *qcam)
{ {
video_unregister_device(&qcam->vdev); video_unregister_device(&qcam->vdev);
parport_unregister_device(qcam->pdev); parport_unregister_device(qcam->pdev);
@ -833,7 +868,7 @@ static struct parport_driver cqcam_driver = {
static int __init cqcam_init(void) static int __init cqcam_init(void)
{ {
printk(BANNER "\n"); printk(KERN_INFO BANNER "\n");
return parport_register_driver(&cqcam_driver); return parport_register_driver(&cqcam_driver);
} }
@ -852,14 +887,5 @@ MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
MODULE_DESCRIPTION(BANNER); MODULE_DESCRIPTION(BANNER);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* FIXME: parport=auto would never have worked, surely? --RR */
MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
"probe=<0|1|2> for camera detection method\n"
"force_rgb=<0|1> for RGB data format (default BGR)");
module_param_array(parport, int, NULL, 0);
module_param(probe, int, 0);
module_param(force_rgb, bool, 0);
module_param(video_nr, int, 0);
module_init(cqcam_init); module_init(cqcam_init);
module_exit(cqcam_cleanup); module_exit(cqcam_cleanup);

View File

@ -1,7 +1,7 @@
/* /*
* ALSA interface to cx18 PCM capture streams * ALSA interface to cx18 PCM capture streams
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
* *
* Portions of this work were sponsored by ONELAN Limited. * Portions of this work were sponsored by ONELAN Limited.

View File

@ -2,7 +2,7 @@
* ALSA mixer controls for the * ALSA mixer controls for the
* ALSA interface to cx18 PCM capture streams * ALSA interface to cx18 PCM capture streams
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* ALSA mixer controls for the * ALSA mixer controls for the
* ALSA interface to cx18 PCM capture streams * ALSA interface to cx18 PCM capture streams
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* ALSA PCM device for the * ALSA PCM device for the
* ALSA interface to cx18 PCM capture streams * ALSA interface to cx18 PCM capture streams
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
* *
* Portions of this work were sponsored by ONELAN Limited. * Portions of this work were sponsored by ONELAN Limited.

View File

@ -2,7 +2,7 @@
* ALSA PCM device for the * ALSA PCM device for the
* ALSA interface to cx18 PCM capture streams * ALSA interface to cx18 PCM capture streams
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/* /*
* ALSA interface to cx18 PCM capture streams * ALSA interface to cx18 PCM capture streams
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
* Derived from cx25840-audio.c * Derived from cx25840-audio.c
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View File

@ -4,7 +4,7 @@
* Derived from cx25840-core.c * Derived from cx25840-core.c
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -1021,86 +1021,74 @@ static int cx18_av_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
return -EINVAL; return -EINVAL;
} }
static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{
if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
return -EINVAL;
return cx18_av_g_sliced_fmt(sd, &fmt->fmt.sliced);
}
static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
{ {
struct cx18_av_state *state = to_cx18_av_state(sd); struct cx18_av_state *state = to_cx18_av_state(sd);
struct cx18 *cx = v4l2_get_subdevdata(sd); struct cx18 *cx = v4l2_get_subdevdata(sd);
struct v4l2_pix_format *pix;
int HSC, VSC, Vsrc, Hsrc, filter, Vlines; int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(state->std & V4L2_STD_525_60); int is_50Hz = !(state->std & V4L2_STD_525_60);
switch (fmt->type) { if (fmt->code != V4L2_MBUS_FMT_FIXED)
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
pix = &(fmt->fmt.pix);
Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
/*
* This adjustment reflects the excess of vactive, set in
* cx18_av_std_setup(), above standard values:
*
* 480 + 1 for 60 Hz systems
* 576 + 3 for 50 Hz systems
*/
Vlines = pix->height + (is_50Hz ? 3 : 1);
/*
* Invalid height and width scaling requests are:
* 1. width less than 1/16 of the source width
* 2. width greater than the source width
* 3. height less than 1/8 of the source height
* 4. height greater than the source height
*/
if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
(Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
pix->width, pix->height);
return -ERANGE;
}
HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);
VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
VSC &= 0x1fff;
if (pix->width >= 385)
filter = 0;
else if (pix->width > 192)
filter = 1;
else if (pix->width > 96)
filter = 2;
else
filter = 3;
CX18_DEBUG_INFO_DEV(sd,
"decoder set size %dx%d -> scale %ux%u\n",
pix->width, pix->height, HSC, VSC);
/* HSCALE=HSC */
cx18_av_write(cx, 0x418, HSC & 0xff);
cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
cx18_av_write(cx, 0x41a, HSC >> 16);
/* VSCALE=VSC */
cx18_av_write(cx, 0x41c, VSC & 0xff);
cx18_av_write(cx, 0x41d, VSC >> 8);
/* VS_INTRLACE=1 VFILT=filter */
cx18_av_write(cx, 0x41e, 0x8 | filter);
break;
default:
return -EINVAL; return -EINVAL;
fmt->field = V4L2_FIELD_INTERLACED;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
/*
* This adjustment reflects the excess of vactive, set in
* cx18_av_std_setup(), above standard values:
*
* 480 + 1 for 60 Hz systems
* 576 + 3 for 50 Hz systems
*/
Vlines = fmt->height + (is_50Hz ? 3 : 1);
/*
* Invalid height and width scaling requests are:
* 1. width less than 1/16 of the source width
* 2. width greater than the source width
* 3. height less than 1/8 of the source height
* 4. height greater than the source height
*/
if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
(Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
fmt->width, fmt->height);
return -ERANGE;
} }
HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
VSC &= 0x1fff;
if (fmt->width >= 385)
filter = 0;
else if (fmt->width > 192)
filter = 1;
else if (fmt->width > 96)
filter = 2;
else
filter = 3;
CX18_DEBUG_INFO_DEV(sd,
"decoder set size %dx%d -> scale %ux%u\n",
fmt->width, fmt->height, HSC, VSC);
/* HSCALE=HSC */
cx18_av_write(cx, 0x418, HSC & 0xff);
cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
cx18_av_write(cx, 0x41a, HSC >> 16);
/* VSCALE=VSC */
cx18_av_write(cx, 0x41c, VSC & 0xff);
cx18_av_write(cx, 0x41d, VSC >> 8);
/* VS_INTRLACE=1 VFILT=filter */
cx18_av_write(cx, 0x41e, 0x8 | filter);
return 0; return 0;
} }
@ -1398,8 +1386,7 @@ static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = {
static const struct v4l2_subdev_video_ops cx18_av_video_ops = { static const struct v4l2_subdev_video_ops cx18_av_video_ops = {
.s_routing = cx18_av_s_video_routing, .s_routing = cx18_av_s_video_routing,
.s_stream = cx18_av_s_stream, .s_stream = cx18_av_s_stream,
.g_fmt = cx18_av_g_fmt, .s_mbus_fmt = cx18_av_s_mbus_fmt,
.s_fmt = cx18_av_s_fmt,
}; };
static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = { static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {

View File

@ -4,7 +4,7 @@
* Derived from cx25840-core.h * Derived from cx25840-core.h
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View File

@ -2,7 +2,7 @@
* cx18 ADEC firmware functions * cx18 ADEC firmware functions
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View File

@ -4,7 +4,7 @@
* Derived from ivtv-cards.c * Derived from ivtv-cards.c
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
* Derived from ivtv-cards.c * Derived from ivtv-cards.c
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -297,14 +297,13 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
if (p.video_encoding != cx->params.video_encoding) { if (p.video_encoding != cx->params.video_encoding) {
int is_mpeg1 = p.video_encoding == int is_mpeg1 = p.video_encoding ==
V4L2_MPEG_VIDEO_ENCODING_MPEG_1; V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
struct v4l2_format fmt; struct v4l2_mbus_framefmt fmt;
/* fix videodecoder resolution */ /* fix videodecoder resolution */
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.width = cx->params.width / (is_mpeg1 ? 2 : 1);
fmt.fmt.pix.width = cx->params.width fmt.height = cx->params.height;
/ (is_mpeg1 ? 2 : 1); fmt.code = V4L2_MBUS_FMT_FIXED;
fmt.fmt.pix.height = cx->params.height; v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
v4l2_subdev_call(cx->sd_av, video, s_fmt, &fmt);
} }
priv.cx = cx; priv.cx = cx;
priv.s = &cx->streams[id->type]; priv.s = &cx->streams[id->type];

View File

@ -4,7 +4,7 @@
* Derived from ivtv-driver.c * Derived from ivtv-driver.c
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
* Derived from ivtv-driver.h * Derived from ivtv-driver.h
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* cx18 functions for DVB support * cx18 functions for DVB support
* *
* Copyright (c) 2008 Steven Toth <stoth@linuxtv.org> * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
* Derived from ivtv-fileops.c * Derived from ivtv-fileops.c
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* cx18 firmware functions * cx18 firmware functions
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
* Derived from ivtv-gpio.c * Derived from ivtv-gpio.c
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
* Derived from ivtv-gpio.h * Derived from ivtv-gpio.h
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
* Derived from ivtv-i2c.c * Derived from ivtv-i2c.c
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* cx18 driver PCI memory mapped IO access routines * cx18 driver PCI memory mapped IO access routines
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* cx18 driver PCI memory mapped IO access routines * cx18 driver PCI memory mapped IO access routines
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -28,7 +28,7 @@
/* /*
* Readback and retry of MMIO access for reliability: * Readback and retry of MMIO access for reliability:
* The concept was suggested by Steve Toth <stoth@linuxtv.org>. * The concept was suggested by Steve Toth <stoth@linuxtv.org>.
* The implmentation is the fault of Andy Walls <awalls@radix.net>. * The implmentation is the fault of Andy Walls <awalls@md.metrocast.net>.
* *
* *write* functions are implied to retry the mmio unless suffixed with _noretry * *write* functions are implied to retry the mmio unless suffixed with _noretry
* *read* functions never retry the mmio (it never helps to do so) * *read* functions never retry the mmio (it never helps to do so)

View File

@ -4,7 +4,7 @@
* Derived from ivtv-ioctl.c * Derived from ivtv-ioctl.c
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -274,6 +274,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
{ {
struct cx18_open_id *id = fh; struct cx18_open_id *id = fh;
struct cx18 *cx = id->cx; struct cx18 *cx = id->cx;
struct v4l2_mbus_framefmt mbus_fmt;
int ret; int ret;
int w, h; int w, h;
@ -293,9 +294,10 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
if (atomic_read(&cx->ana_capturing) > 0) if (atomic_read(&cx->ana_capturing) > 0)
return -EBUSY; return -EBUSY;
cx->params.width = w; mbus_fmt.width = cx->params.width = w;
cx->params.height = h; mbus_fmt.height = cx->params.height = h;
v4l2_subdev_call(cx->sd_av, video, s_fmt, fmt); mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
return cx18_g_fmt_vid_cap(file, fh, fmt); return cx18_g_fmt_vid_cap(file, fh, fmt);
} }

View File

@ -4,7 +4,7 @@
* Derived from ivtv-ioctl.h * Derived from ivtv-ioctl.h
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* cx18 interrupt handling * cx18 interrupt handling
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* cx18 interrupt handling * cx18 interrupt handling
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* cx18 mailbox functions * cx18 mailbox functions
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* cx18 mailbox functions * cx18 mailbox functions
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
* Derived from ivtv-queue.c * Derived from ivtv-queue.c
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
* Derived from ivtv-queue.h * Derived from ivtv-queue.h
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* cx18 System Control Block initialization * cx18 System Control Block initialization
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
* cx18 System Control Block initialization * cx18 System Control Block initialization
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
* Derived from ivtv-streams.c * Derived from ivtv-streams.c
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -4,7 +4,7 @@
* Derived from ivtv-streams.h * Derived from ivtv-streams.h
* *
* Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
* Copyright (C) 2008 Andy Walls <awalls@radix.net> * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -993,6 +993,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct cx231xx *dev = fh->dev; struct cx231xx *dev = fh->dev;
int rc; int rc;
struct cx231xx_fmt *fmt; struct cx231xx_fmt *fmt;
struct v4l2_mbus_framefmt mbus_fmt;
rc = check_dev(dev); rc = check_dev(dev);
if (rc < 0) if (rc < 0)
@ -1026,7 +1027,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
dev->format = fmt; dev->format = fmt;
get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
call_all(dev, video, s_fmt, f); v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
call_all(dev, video, s_mbus_fmt, &mbus_fmt);
v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
/* Set the correct alternate setting for this resolution */ /* Set the correct alternate setting for this resolution */
cx231xx_resolution_set(dev); cx231xx_resolution_set(dev);

View File

@ -1113,7 +1113,6 @@ static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id
void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix) void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
{ {
int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
int temporal = p->video_temporal_filter;
/* Stream */ /* Stream */
printk(KERN_INFO "%s: Stream: %s", printk(KERN_INFO "%s: Stream: %s",
@ -1179,14 +1178,11 @@ void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE), V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
p->video_spatial_filter); p->video_spatial_filter);
if (p->width != 720 || p->height != (p->is_50hz ? 576 : 480))
temporal = 0;
printk(KERN_INFO "%s: Temporal Filter: %s, %d\n", printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
prefix, prefix,
cx2341x_menu_item(p, cx2341x_menu_item(p,
V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE), V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
temporal); p->video_temporal_filter);
printk(KERN_INFO printk(KERN_INFO
"%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n", "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n",
prefix, prefix,

View File

@ -991,6 +991,8 @@ static int dvb_register(struct cx23885_tsport *port)
ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
&dev->pci->dev, adapter_nr, 0, &dev->pci->dev, adapter_nr, 0,
cx23885_dvb_fe_ioctl_override); cx23885_dvb_fe_ioctl_override);
if (!ret)
return ret;
/* init CI & MAC */ /* init CI & MAC */
switch (dev->board) { switch (dev->board) {

View File

@ -365,7 +365,17 @@ int cx23885_i2c_register(struct cx23885_i2c *bus)
memset(&info, 0, sizeof(struct i2c_board_info)); memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "ir_video", I2C_NAME_SIZE); strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
i2c_new_probed_device(&bus->i2c_adap, &info, addr_list); /*
* We can't call i2c_new_probed_device() because it uses
* quick writes for probing and the IR receiver device only
* replies to reads.
*/
if (i2c_smbus_xfer(&bus->i2c_adap, addr_list[0], 0,
I2C_SMBUS_READ, 0, I2C_SMBUS_QUICK,
NULL) >= 0) {
info.addr = addr_list[0];
i2c_new_device(&bus->i2c_adap, &info);
}
} }
return bus->i2c_rc; return bus->i2c_rc;

View File

@ -5,7 +5,7 @@
* *
* Most of this file is * Most of this file is
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* However, the cx23885_input_{init,fini} functions contained herein are * However, the cx23885_input_{init,fini} functions contained herein are
* derived from Linux kernel files linux/media/video/.../...-input.c marked as: * derived from Linux kernel files linux/media/video/.../...-input.c marked as:

View File

@ -3,7 +3,7 @@
* *
* Infrared remote control input device * Infrared remote control input device
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View File

@ -3,7 +3,7 @@
* *
* Various common ioctl() support functions * Various common ioctl() support functions
* *
* Copyright (c) 2009 Andy Walls <awalls@radix.net> * Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
* *
* Various common ioctl() support functions * Various common ioctl() support functions
* *
* Copyright (c) 2009 Andy Walls <awalls@radix.net> * Copyright (c) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
* *
* Infrared device support routines - non-input, non-vl42_subdev routines * Infrared device support routines - non-input, non-vl42_subdev routines
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View File

@ -3,7 +3,7 @@
* *
* Infrared device support routines - non-input, non-vl42_subdev routines * Infrared device support routines - non-input, non-vl42_subdev routines
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View File

@ -976,6 +976,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
{ {
struct cx23885_fh *fh = priv; struct cx23885_fh *fh = priv;
struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
struct v4l2_mbus_framefmt mbus_fmt;
int err; int err;
dprintk(2, "%s()\n", __func__); dprintk(2, "%s()\n", __func__);
@ -989,7 +990,9 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
fh->vidq.field = f->fmt.pix.field; fh->vidq.field = f->fmt.pix.field;
dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
fh->width, fh->height, fh->vidq.field); fh->width, fh->height, fh->vidq.field);
call_all(dev, video, s_fmt, f); v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
call_all(dev, video, s_mbus_fmt, &mbus_fmt);
v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
return 0; return 0;
} }

View File

@ -3,7 +3,7 @@
* *
* CX23888 Integrated Consumer Infrared Controller * CX23888 Integrated Consumer Infrared Controller
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View File

@ -3,7 +3,7 @@
* *
* CX23888 Integrated Consumer Infrared Controller * CX23888 Integrated Consumer Infrared Controller
* *
* Copyright (C) 2009 Andy Walls <awalls@radix.net> * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View File

@ -1014,75 +1014,59 @@ static int cx25840_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{
switch (fmt->type) {
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
return cx25840_g_sliced_fmt(sd, &fmt->fmt.sliced);
default:
return -EINVAL;
}
return 0;
}
static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
{ {
struct cx25840_state *state = to_state(sd); struct cx25840_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd); struct i2c_client *client = v4l2_get_subdevdata(sd);
struct v4l2_pix_format *pix;
int HSC, VSC, Vsrc, Hsrc, filter, Vlines; int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(state->std & V4L2_STD_525_60); int is_50Hz = !(state->std & V4L2_STD_525_60);
switch (fmt->type) { if (fmt->code != V4L2_MBUS_FMT_FIXED)
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
pix = &(fmt->fmt.pix);
Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
Vlines = pix->height + (is_50Hz ? 4 : 7);
if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
(Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
v4l_err(client, "%dx%d is not a valid size!\n",
pix->width, pix->height);
return -ERANGE;
}
HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);
VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
VSC &= 0x1fff;
if (pix->width >= 385)
filter = 0;
else if (pix->width > 192)
filter = 1;
else if (pix->width > 96)
filter = 2;
else
filter = 3;
v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n",
pix->width, pix->height, HSC, VSC);
/* HSCALE=HSC */
cx25840_write(client, 0x418, HSC & 0xff);
cx25840_write(client, 0x419, (HSC >> 8) & 0xff);
cx25840_write(client, 0x41a, HSC >> 16);
/* VSCALE=VSC */
cx25840_write(client, 0x41c, VSC & 0xff);
cx25840_write(client, 0x41d, VSC >> 8);
/* VS_INTRLACE=1 VFILT=filter */
cx25840_write(client, 0x41e, 0x8 | filter);
break;
default:
return -EINVAL; return -EINVAL;
fmt->field = V4L2_FIELD_INTERLACED;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
Vlines = fmt->height + (is_50Hz ? 4 : 7);
if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
(Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
v4l_err(client, "%dx%d is not a valid size!\n",
fmt->width, fmt->height);
return -ERANGE;
} }
HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
VSC &= 0x1fff;
if (fmt->width >= 385)
filter = 0;
else if (fmt->width > 192)
filter = 1;
else if (fmt->width > 96)
filter = 2;
else
filter = 3;
v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n",
fmt->width, fmt->height, HSC, VSC);
/* HSCALE=HSC */
cx25840_write(client, 0x418, HSC & 0xff);
cx25840_write(client, 0x419, (HSC >> 8) & 0xff);
cx25840_write(client, 0x41a, HSC >> 16);
/* VSCALE=VSC */
cx25840_write(client, 0x41c, VSC & 0xff);
cx25840_write(client, 0x41d, VSC >> 8);
/* VS_INTRLACE=1 VFILT=filter */
cx25840_write(client, 0x41e, 0x8 | filter);
return 0; return 0;
} }
@ -1627,8 +1611,7 @@ static const struct v4l2_subdev_audio_ops cx25840_audio_ops = {
static const struct v4l2_subdev_video_ops cx25840_video_ops = { static const struct v4l2_subdev_video_ops cx25840_video_ops = {
.s_routing = cx25840_s_video_routing, .s_routing = cx25840_s_video_routing,
.g_fmt = cx25840_g_fmt, .s_mbus_fmt = cx25840_s_mbus_fmt,
.s_fmt = cx25840_s_fmt,
.s_stream = cx25840_s_stream, .s_stream = cx25840_s_stream,
}; };

View File

@ -188,10 +188,24 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
0x18, 0x6b, 0x71, 0x18, 0x6b, 0x71,
I2C_CLIENT_END I2C_CLIENT_END
}; };
const unsigned short *addrp;
memset(&info, 0, sizeof(struct i2c_board_info)); memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "ir_video", I2C_NAME_SIZE); strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
i2c_new_probed_device(&core->i2c_adap, &info, addr_list); /*
* We can't call i2c_new_probed_device() because it uses
* quick writes for probing and at least some R receiver
* devices only reply to reads.
*/
for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {
if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
I2C_SMBUS_READ, 0,
I2C_SMBUS_QUICK, NULL) >= 0) {
info.addr = *addrp;
i2c_new_device(&core->i2c_adap, &info);
break;
}
}
} }
return core->i2c_rc; return core->i2c_rc;
} }

View File

@ -1186,8 +1186,7 @@ int em28xx_register_extension(struct em28xx_ops *ops)
mutex_lock(&em28xx_devlist_mutex); mutex_lock(&em28xx_devlist_mutex);
list_add_tail(&ops->next, &em28xx_extension_devlist); list_add_tail(&ops->next, &em28xx_extension_devlist);
list_for_each_entry(dev, &em28xx_devlist, devlist) { list_for_each_entry(dev, &em28xx_devlist, devlist) {
if (dev) ops->init(dev);
ops->init(dev);
} }
printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
mutex_unlock(&em28xx_devlist_mutex); mutex_unlock(&em28xx_devlist_mutex);
@ -1201,10 +1200,8 @@ void em28xx_unregister_extension(struct em28xx_ops *ops)
mutex_lock(&em28xx_devlist_mutex); mutex_lock(&em28xx_devlist_mutex);
list_for_each_entry(dev, &em28xx_devlist, devlist) { list_for_each_entry(dev, &em28xx_devlist, devlist) {
if (dev) ops->fini(dev);
ops->fini(dev);
} }
printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
list_del(&ops->next); list_del(&ops->next);
mutex_unlock(&em28xx_devlist_mutex); mutex_unlock(&em28xx_devlist_mutex);

View File

@ -1453,9 +1453,7 @@ static const struct usb_device_id device_table[] __devinitconst = {
{USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
{USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
{USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
#endif
{USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},

View File

@ -3022,16 +3022,18 @@ static const __devinitdata struct usb_device_id device_table[] = {
/* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */ /* {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
/* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */ /* {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
/* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */ /* {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */
{USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},
{USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)}, {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},
/* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */ /* {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */
/* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */ /* {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
/* {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
{USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)}, {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
{USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)}, {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
{USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)}, {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
#endif #endif
{USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)}, /*sn9c128*/
/* {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, P1030xC)}, */ /* {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)}, * / GC0305*/
/* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */ /* {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
{USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)}, /*sn9c128*/
{USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/ {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)}, /*sn9c128*/
@ -3058,6 +3060,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)}, {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
{USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)}, {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
{USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/ {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, /*sn9c120b*/
/* or GC0305 / GC0307 */
{USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/
{USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/
{USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/ {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/

View File

@ -366,7 +366,7 @@ static int hdpvr_open(struct file *file)
dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file)); dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file));
if (!dev) { if (!dev) {
v4l2_err(&dev->v4l2_dev, "open failing with with ENODEV\n"); pr_err("open failing with with ENODEV\n");
retval = -ENODEV; retval = -ENODEV;
goto err; goto err;
} }

View File

@ -267,13 +267,13 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
if (p.video_encoding != itv->params.video_encoding) { if (p.video_encoding != itv->params.video_encoding) {
int is_mpeg1 = p.video_encoding == int is_mpeg1 = p.video_encoding ==
V4L2_MPEG_VIDEO_ENCODING_MPEG_1; V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
struct v4l2_format fmt; struct v4l2_mbus_framefmt fmt;
/* fix videodecoder resolution */ /* fix videodecoder resolution */
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.width = itv->params.width / (is_mpeg1 ? 2 : 1);
fmt.fmt.pix.width = itv->params.width / (is_mpeg1 ? 2 : 1); fmt.height = itv->params.height;
fmt.fmt.pix.height = itv->params.height; fmt.code = V4L2_MBUS_FMT_FIXED;
v4l2_subdev_call(itv->sd_video, video, s_fmt, &fmt); v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
} }
err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p); err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p);
if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt) if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt)

View File

@ -823,6 +823,12 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
IVTV_DEBUG_FILE("close() of %s\n", s->name); IVTV_DEBUG_FILE("close() of %s\n", s->name);
if (id->type == IVTV_DEC_STREAM_TYPE_YUV &&
test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) {
/* Restore registers we've changed & clean up any mess */
ivtv_yuv_close(itv);
}
/* Stop decoding */ /* Stop decoding */
if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
IVTV_DEBUG_INFO("close stopping decode\n"); IVTV_DEBUG_INFO("close stopping decode\n");
@ -832,10 +838,7 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
} }
clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
if (id->type == IVTV_DEC_STREAM_TYPE_YUV && test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) {
/* Restore registers we've changed & clean up any mess we've made */
ivtv_yuv_close(itv);
}
if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames) if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames)
itv->output_mode = OUT_NONE; itv->output_mode = OUT_NONE;

View File

@ -569,6 +569,7 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
struct ivtv_open_id *id = fh; struct ivtv_open_id *id = fh;
struct ivtv *itv = id->itv; struct ivtv *itv = id->itv;
struct cx2341x_mpeg_params *p = &itv->params; struct cx2341x_mpeg_params *p = &itv->params;
struct v4l2_mbus_framefmt mbus_fmt;
int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
int w = fmt->fmt.pix.width; int w = fmt->fmt.pix.width;
int h = fmt->fmt.pix.height; int h = fmt->fmt.pix.height;
@ -586,7 +587,10 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
p->height = h; p->height = h;
if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
fmt->fmt.pix.width /= 2; fmt->fmt.pix.width /= 2;
v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); mbus_fmt.width = fmt->fmt.pix.width;
mbus_fmt.height = h;
mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
return ivtv_g_fmt_vid_cap(file, fh, fmt); return ivtv_g_fmt_vid_cap(file, fh, fmt);
} }

View File

@ -618,12 +618,17 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
struct ivtv *itv = s->itv; struct ivtv *itv = s->itv;
struct cx2341x_mpeg_params *p = &itv->params; struct cx2341x_mpeg_params *p = &itv->params;
int datatype; int datatype;
u16 width;
u16 height;
if (s->vdev == NULL) if (s->vdev == NULL)
return -EINVAL; return -EINVAL;
IVTV_DEBUG_INFO("Setting some initial decoder settings\n"); IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
width = p->width;
height = p->height;
/* set audio mode to left/stereo for dual/stereo mode. */ /* set audio mode to left/stereo for dual/stereo mode. */
ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
@ -646,7 +651,14 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
2 = yuv_from_host */ 2 = yuv_from_host */
switch (s->type) { switch (s->type) {
case IVTV_DEC_STREAM_TYPE_YUV: case IVTV_DEC_STREAM_TYPE_YUV:
datatype = itv->output_mode == OUT_PASSTHROUGH ? 1 : 2; if (itv->output_mode == OUT_PASSTHROUGH) {
datatype = 1;
} else {
/* Fake size to avoid switching video standard */
datatype = 2;
width = 720;
height = itv->is_out_50hz ? 576 : 480;
}
IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype); IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype);
break; break;
case IVTV_DEC_STREAM_TYPE_MPG: case IVTV_DEC_STREAM_TYPE_MPG:
@ -655,9 +667,13 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
break; break;
} }
if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype, if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
p->width, p->height, p->audio_properties)) { width, height, p->audio_properties)) {
IVTV_DEBUG_WARN("Couldn't initialize decoder source\n"); IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
} }
/* Decoder sometimes dies here, so wait a moment */
ivtv_msleep_timeout(10, 0);
return 0; return 0;
} }
@ -697,6 +713,9 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
/* start playback */ /* start playback */
ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0); ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0);
/* Let things settle before we actually start */
ivtv_msleep_timeout(10, 0);
/* Clear the following Interrupt mask bits for decoding */ /* Clear the following Interrupt mask bits for decoding */
ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE); ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask); IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask);

View File

@ -1066,7 +1066,11 @@ static int ivtvfb_init_io(struct ivtv *itv)
} }
mutex_unlock(&itv->serialize_lock); mutex_unlock(&itv->serialize_lock);
ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size); if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
&oi->video_buffer_size) < 0) {
IVTVFB_ERR("Firmware failed to respond\n");
return -EIO;
}
/* The osd buffer size depends on the number of video buffers allocated /* The osd buffer size depends on the number of video buffers allocated
on the PVR350 itself. For now we'll hardcode the smallest osd buffer on the PVR350 itself. For now we'll hardcode the smallest osd buffer
@ -1158,8 +1162,11 @@ static int ivtvfb_init_card(struct ivtv *itv)
} }
/* Find & setup the OSD buffer */ /* Find & setup the OSD buffer */
if ((rc = ivtvfb_init_io(itv))) rc = ivtvfb_init_io(itv);
if (rc) {
ivtvfb_release_buffers(itv);
return rc; return rc;
}
/* Set the startup video mode information */ /* Set the startup video mode information */
if ((rc = ivtvfb_init_vidmode(itv))) { if ((rc = ivtvfb_init_vidmode(itv))) {
@ -1210,6 +1217,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p)
{ {
struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
struct osd_info *oi = itv->osd_info;
if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
@ -1218,7 +1226,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p)
return 0; return 0;
} }
IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info); ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
ivtvfb_release_buffers(itv); ivtvfb_release_buffers(itv);
itv->osd_video_pbase = 0; itv->osd_video_pbase = 0;
} }

View File

@ -701,13 +701,13 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
#endif #endif
}; };
static int mt9m001_enum_fmt(struct v4l2_subdev *sd, int index, static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code) enum v4l2_mbus_pixelcode *code)
{ {
struct i2c_client *client = sd->priv; struct i2c_client *client = sd->priv;
struct mt9m001 *mt9m001 = to_mt9m001(client); struct mt9m001 *mt9m001 = to_mt9m001(client);
if ((unsigned int)index >= mt9m001->num_fmts) if (index >= mt9m001->num_fmts)
return -EINVAL; return -EINVAL;
*code = mt9m001->fmts[index].code; *code = mt9m001->fmts[index].code;

View File

@ -999,10 +999,10 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
#endif #endif
}; };
static int mt9m111_enum_fmt(struct v4l2_subdev *sd, int index, static int mt9m111_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code) enum v4l2_mbus_pixelcode *code)
{ {
if ((unsigned int)index >= ARRAY_SIZE(mt9m111_colour_fmts)) if (index >= ARRAY_SIZE(mt9m111_colour_fmts))
return -EINVAL; return -EINVAL;
*code = mt9m111_colour_fmts[index].code; *code = mt9m111_colour_fmts[index].code;

View File

@ -798,7 +798,7 @@ static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
#endif #endif
}; };
static int mt9t031_enum_fmt(struct v4l2_subdev *sd, int index, static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code) enum v4l2_mbus_pixelcode *code)
{ {
if (index) if (index)

View File

@ -1017,10 +1017,10 @@ static int mt9t112_try_fmt(struct v4l2_subdev *sd,
return 0; return 0;
} }
static int mt9t112_enum_fmt(struct v4l2_subdev *sd, int index, static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code) enum v4l2_mbus_pixelcode *code)
{ {
if ((unsigned int)index >= ARRAY_SIZE(mt9t112_cfmts)) if (index >= ARRAY_SIZE(mt9t112_cfmts))
return -EINVAL; return -EINVAL;
*code = mt9t112_cfmts[index].code; *code = mt9t112_cfmts[index].code;

View File

@ -392,27 +392,25 @@ static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
return 0; return 0;
} }
static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
enum v4l2_mbus_pixelcode *code)
{ {
if (fmt->index > 0) if (index > 0)
return -EINVAL; return -EINVAL;
fmt->flags = 0; *code = V4L2_MBUS_FMT_SGRBG8_1X8;
strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG");
fmt->pixelformat = V4L2_PIX_FMT_SGRBG8;
return 0; return 0;
} }
static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{ {
struct v4l2_pix_format *pix = &fmt->fmt.pix; if (fmt->code != V4L2_MBUS_FMT_SGRBG8_1X8)
if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8)
return -EINVAL; return -EINVAL;
v4l_bound_align_image(&pix->width, 48, 639, 1, v4l_bound_align_image(&fmt->width, 48, 639, 1,
&pix->height, 32, 480, 1, 0); &fmt->height, 32, 480, 1, 0);
fmt->field = V4L2_FIELD_NONE;
fmt->colorspace = V4L2_COLORSPACE_SRGB;
return 0; return 0;
} }
@ -455,18 +453,17 @@ static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
return 0; return 0;
} }
static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{ {
struct v4l2_pix_format *pix = &fmt->fmt.pix;
struct mt9v011 *core = to_mt9v011(sd); struct mt9v011 *core = to_mt9v011(sd);
int rc; int rc;
rc = mt9v011_try_fmt(sd, fmt); rc = mt9v011_try_mbus_fmt(sd, fmt);
if (rc < 0) if (rc < 0)
return -EINVAL; return -EINVAL;
core->width = pix->width; core->width = fmt->width;
core->height = pix->height; core->height = fmt->height;
set_res(sd); set_res(sd);
@ -549,9 +546,9 @@ static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
}; };
static const struct v4l2_subdev_video_ops mt9v011_video_ops = { static const struct v4l2_subdev_video_ops mt9v011_video_ops = {
.enum_fmt = mt9v011_enum_fmt, .enum_mbus_fmt = mt9v011_enum_mbus_fmt,
.try_fmt = mt9v011_try_fmt, .try_mbus_fmt = mt9v011_try_mbus_fmt,
.s_fmt = mt9v011_s_fmt, .s_mbus_fmt = mt9v011_s_mbus_fmt,
.g_parm = mt9v011_g_parm, .g_parm = mt9v011_g_parm,
.s_parm = mt9v011_s_parm, .s_parm = mt9v011_s_parm,
}; };

View File

@ -838,13 +838,13 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
#endif #endif
}; };
static int mt9v022_enum_fmt(struct v4l2_subdev *sd, int index, static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code) enum v4l2_mbus_pixelcode *code)
{ {
struct i2c_client *client = sd->priv; struct i2c_client *client = sd->priv;
struct mt9v022 *mt9v022 = to_mt9v022(client); struct mt9v022 *mt9v022 = to_mt9v022(client);
if ((unsigned int)index >= mt9v022->num_fmts) if (index >= mt9v022->num_fmts)
return -EINVAL; return -EINVAL;
*code = mt9v022->fmts[index].code; *code = mt9v022->fmts[index].code;

Some files were not shown because too many files have changed in this diff Show More