Commit 1a23f81b authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

V4L/DVB (9979): em28xx: move usb probe code to a proper place

em28xx-video were holding several code that are not specific to V4L2
interface.

This patch moves the core code for em28xx-core, and usb probing code
into em28xx-cards.

This opens the possibility of breaking em28xx into a core module and a
V4L2 module, loaded only on devices that have analog interfaces.

Some cleanup may be done at em28xx-cards to optimize the config code.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 126be90f
This diff is collapsed.
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <media/v4l2-common.h>
#include "em28xx.h" #include "em28xx.h"
...@@ -974,3 +975,145 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, ...@@ -974,3 +975,145 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(em28xx_init_isoc); EXPORT_SYMBOL_GPL(em28xx_init_isoc);
/*
* em28xx_wake_i2c()
* configure i2c attached devices
*/
void em28xx_wake_i2c(struct em28xx *dev)
{
struct v4l2_routing route;
int zero = 0;
route.input = INPUT(dev->ctl_input)->vmux;
route.output = 0;
em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero);
em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
}
/*
* Device control list
*/
static LIST_HEAD(em28xx_devlist);
static DEFINE_MUTEX(em28xx_devlist_mutex);
struct em28xx *em28xx_get_device(struct inode *inode,
enum v4l2_buf_type *fh_type,
int *has_radio)
{
struct em28xx *h, *dev = NULL;
int minor = iminor(inode);
*fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
*has_radio = 0;
mutex_lock(&em28xx_devlist_mutex);
list_for_each_entry(h, &em28xx_devlist, devlist) {
if (h->vdev->minor == minor)
dev = h;
if (h->vbi_dev->minor == minor) {
dev = h;
*fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
}
if (h->radio_dev &&
h->radio_dev->minor == minor) {
dev = h;
*has_radio = 1;
}
}
mutex_unlock(&em28xx_devlist_mutex);
return dev;
}
/*
* em28xx_realease_resources()
* unregisters the v4l2,i2c and usb devices
* called when the device gets disconected or at module unload
*/
void em28xx_remove_from_devlist(struct em28xx *dev)
{
mutex_lock(&em28xx_devlist_mutex);
list_del(&dev->devlist);
mutex_unlock(&em28xx_devlist_mutex);
};
void em28xx_add_into_devlist(struct em28xx *dev)
{
mutex_lock(&em28xx_devlist_mutex);
list_add_tail(&dev->devlist, &em28xx_devlist);
mutex_unlock(&em28xx_devlist_mutex);
};
/*
* Extension interface
*/
static LIST_HEAD(em28xx_extension_devlist);
static DEFINE_MUTEX(em28xx_extension_devlist_lock);
int em28xx_register_extension(struct em28xx_ops *ops)
{
struct em28xx *dev = NULL;
mutex_lock(&em28xx_devlist_mutex);
mutex_lock(&em28xx_extension_devlist_lock);
list_add_tail(&ops->next, &em28xx_extension_devlist);
list_for_each_entry(dev, &em28xx_devlist, devlist) {
if (dev)
ops->init(dev);
}
printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
mutex_unlock(&em28xx_extension_devlist_lock);
mutex_unlock(&em28xx_devlist_mutex);
return 0;
}
EXPORT_SYMBOL(em28xx_register_extension);
void em28xx_unregister_extension(struct em28xx_ops *ops)
{
struct em28xx *dev = NULL;
mutex_lock(&em28xx_devlist_mutex);
list_for_each_entry(dev, &em28xx_devlist, devlist) {
if (dev)
ops->fini(dev);
}
mutex_lock(&em28xx_extension_devlist_lock);
printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
list_del(&ops->next);
mutex_unlock(&em28xx_extension_devlist_lock);
mutex_unlock(&em28xx_devlist_mutex);
}
EXPORT_SYMBOL(em28xx_unregister_extension);
void em28xx_init_extension(struct em28xx *dev)
{
struct em28xx_ops *ops = NULL;
mutex_lock(&em28xx_extension_devlist_lock);
if (!list_empty(&em28xx_extension_devlist)) {
list_for_each_entry(ops, &em28xx_extension_devlist, next) {
if (ops->init)
ops->init(dev);
}
}
mutex_unlock(&em28xx_extension_devlist_lock);
}
void em28xx_close_extension(struct em28xx *dev)
{
struct em28xx_ops *ops = NULL;
mutex_lock(&em28xx_extension_devlist_lock);
if (!list_empty(&em28xx_extension_devlist)) {
list_for_each_entry(ops, &em28xx_extension_devlist, next) {
if (ops->fini)
ops->fini(dev);
}
}
mutex_unlock(&em28xx_extension_devlist_lock);
}
This diff is collapsed.
...@@ -581,10 +581,21 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, ...@@ -581,10 +581,21 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
void em28xx_uninit_isoc(struct em28xx *dev); void em28xx_uninit_isoc(struct em28xx *dev);
int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
void em28xx_wake_i2c(struct em28xx *dev);
/* Provided by em28xx-video.c */ void em28xx_remove_from_devlist(struct em28xx *dev);
void em28xx_add_into_devlist(struct em28xx *dev);
struct em28xx *em28xx_get_device(struct inode *inode,
enum v4l2_buf_type *fh_type,
int *has_radio);
int em28xx_register_extension(struct em28xx_ops *dev); int em28xx_register_extension(struct em28xx_ops *dev);
void em28xx_unregister_extension(struct em28xx_ops *dev); void em28xx_unregister_extension(struct em28xx_ops *dev);
void em28xx_init_extension(struct em28xx *dev);
void em28xx_close_extension(struct em28xx *dev);
/* Provided by em28xx-video.c */
int em28xx_analog_config(struct em28xx *dev);
int em28xx_register_analog_devices(struct em28xx *dev);
void em28xx_release_analog_resources(struct em28xx *dev);
/* Provided by em28xx-cards.c */ /* Provided by em28xx-cards.c */
extern int em2800_variant_detect(struct usb_device *udev, int model); extern int em2800_variant_detect(struct usb_device *udev, int model);
...@@ -595,6 +606,7 @@ extern struct usb_device_id em28xx_id_table[]; ...@@ -595,6 +606,7 @@ extern struct usb_device_id em28xx_id_table[];
extern const unsigned int em28xx_bcount; extern const unsigned int em28xx_bcount;
void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir); void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
int em28xx_tuner_callback(void *ptr, int component, int command, int arg); int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
void em28xx_release_resources(struct em28xx *dev);
/* Provided by em28xx-input.c */ /* Provided by em28xx-input.c */
int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment