diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 19:50:49 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 19:50:49 -0800 |
commit | 3e7468313758913c5e4d372f35b271b96bad1298 (patch) | |
tree | eb612d252a9e2349a1173451cd779beebd18a33e /drivers/staging | |
parent | 6825fbc4cb219f2c98bb7d157915d797cf5cb823 (diff) | |
parent | e97f4677961f68e29bd906022ebf60a6df7f530a (diff) | |
download | op-kernel-dev-3e7468313758913c5e4d372f35b271b96bad1298.zip op-kernel-dev-3e7468313758913c5e4d372f35b271b96bad1298.tar.gz |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (345 commits)
V4L/DVB (13542): ir-keytable: Allow dynamic table change
V4L/DVB (13541): atbm8830: replace 64-bit division and floating point usage
V4L/DVB (13540): ir-common: Cleanup get key evdev code
V4L/DVB (13539): ir-common: add __func__ for debug messages
V4L/DVB (13538): ir-common: Use a dynamic keycode table
V4L/DVB (13537): ir: Prepare the code for dynamic keycode table allocation
V4L/DVB (13536): em28xx: Use the full RC5 code on HVR-950 Remote Controller
V4L/DVB (13535): ir-common: Add a hauppauge new table with the complete RC5 code
V4L/DVB (13534): ir-common: Remove some unused fields/structs
V4L/DVB (13533): ir: use dynamic tables, instead of static ones
V4L/DVB (13532): ir-common: Add infrastructure to use a dynamic keycode table
V4L/DVB (13531): ir-common: rename the debug routine to allow exporting it
V4L/DVB (13458): go7007: subdev conversion
V4L/DVB (13457): s2250: subdev conversion
V4L/DVB (13456): s2250: Change module structure
V4L/DVB (13528): em28xx: add support for em2800 VC211A card
em28xx: don't reduce scale to half size for em2800
em28xx: don't load audio modules when AC97 is mis-detected
em28xx: em2800 chips support max width of 640
V4L/DVB (13523): dvb-bt8xx: fix compile warning
...
Fix up trivial conflicts due to spelling fixes from the trivial tree in
Documentation/video4linux/gspca.txt
drivers/media/video/cx18/cx18-mailbox.h
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/go7007/Makefile | 4 | ||||
-rw-r--r-- | drivers/staging/go7007/go7007-driver.c | 30 | ||||
-rw-r--r-- | drivers/staging/go7007/go7007-priv.h | 8 | ||||
-rw-r--r-- | drivers/staging/go7007/go7007-usb.c | 6 | ||||
-rw-r--r-- | drivers/staging/go7007/go7007-v4l2.c | 109 | ||||
-rw-r--r-- | drivers/staging/go7007/s2250-board.c | 558 | ||||
-rw-r--r-- | drivers/staging/go7007/s2250-loader.c | 12 |
7 files changed, 355 insertions, 372 deletions
diff --git a/drivers/staging/go7007/Makefile b/drivers/staging/go7007/Makefile index 1301caa..d37b7ed 100644 --- a/drivers/staging/go7007/Makefile +++ b/drivers/staging/go7007/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_VIDEO_GO7007) += go7007.o obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o -obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o +obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o s2250-loader.o obj-$(CONFIG_VIDEO_GO7007_SAA7113) += wis-saa7113.o obj-$(CONFIG_VIDEO_GO7007_OV7640) += wis-ov7640.o obj-$(CONFIG_VIDEO_GO7007_SAA7115) += wis-saa7115.o @@ -17,7 +17,7 @@ obj-$(CONFIG_VIDEO_GO7007_TW2804) += wis-tw2804.o go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ snd-go7007.o -s2250-objs += s2250-board.o s2250-loader.o +s2250-objs += s2250-board.o # Uncomment when the saa7134 patches get into upstream #ifneq ($(CONFIG_VIDEO_SAA7134),) diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c index 472f4bb..fb1345f 100644 --- a/drivers/staging/go7007/go7007-driver.c +++ b/drivers/staging/go7007/go7007-driver.c @@ -49,7 +49,7 @@ int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data) go->hpi_ops->read_interrupt(go); if (wait_event_timeout(go->interrupt_waitq, go->interrupt_available, 5*HZ) < 0) { - v4l2_err(go->video_dev, "timeout waiting for read interrupt\n"); + v4l2_err(&go->v4l2_dev, "timeout waiting for read interrupt\n"); return -1; } if (!go->interrupt_available) @@ -193,7 +193,8 @@ int go7007_reset_encoder(struct go7007 *go) static int init_i2c_module(struct i2c_adapter *adapter, const char *type, int id, int addr) { - struct i2c_board_info info; + struct go7007 *go = i2c_get_adapdata(adapter); + struct v4l2_device *v4l2_dev = &go->v4l2_dev; char *modname; switch (id) { @@ -219,20 +220,16 @@ static int init_i2c_module(struct i2c_adapter *adapter, const char *type, modname = "wis-ov7640"; break; case I2C_DRIVERID_S2250: - modname = "s2250-board"; + modname = "s2250"; break; default: modname = NULL; break; } - if (modname != NULL) - request_module(modname); - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = addr; - strlcpy(info.type, type, I2C_NAME_SIZE); - if (!i2c_new_device(adapter, &info)) + if (v4l2_i2c_new_subdev(v4l2_dev, adapter, modname, type, addr, NULL)) return 0; + if (modname != NULL) printk(KERN_INFO "go7007: probing for module %s failed\n", modname); @@ -262,6 +259,11 @@ int go7007_register_encoder(struct go7007 *go) if (ret < 0) return -1; + /* v4l2 init must happen before i2c subdevs */ + ret = go7007_v4l2_init(go); + if (ret < 0) + return ret; + if (!go->i2c_adapter_online && go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) { if (go7007_i2c_init(go) < 0) @@ -282,7 +284,7 @@ int go7007_register_encoder(struct go7007 *go) go->audio_enabled = 1; go7007_snd_init(go); } - return go7007_v4l2_init(go); + return 0; } EXPORT_SYMBOL(go7007_register_encoder); @@ -315,7 +317,7 @@ int go7007_start_encoder(struct go7007 *go) if (go7007_send_firmware(go, fw, fw_len) < 0 || go7007_read_interrupt(go, &intr_val, &intr_data) < 0) { - v4l2_err(go->video_dev, "error transferring firmware\n"); + v4l2_err(&go->v4l2_dev, "error transferring firmware\n"); rv = -1; goto start_error; } @@ -324,7 +326,7 @@ int go7007_start_encoder(struct go7007 *go) go->parse_length = 0; go->seen_frame = 0; if (go7007_stream_start(go) < 0) { - v4l2_err(go->video_dev, "error starting stream transfer\n"); + v4l2_err(&go->v4l2_dev, "error starting stream transfer\n"); rv = -1; goto start_error; } @@ -420,7 +422,7 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) for (i = 0; i < length; ++i) { if (go->active_buf != NULL && go->active_buf->bytesused >= GO7007_BUF_SIZE - 3) { - v4l2_info(go->video_dev, "dropping oversized frame\n"); + v4l2_info(&go->v4l2_dev, "dropping oversized frame\n"); go->active_buf->offset -= go->active_buf->bytesused; go->active_buf->bytesused = 0; go->active_buf->modet_active = 0; @@ -668,7 +670,7 @@ void go7007_remove(struct go7007 *go) if (i2c_del_adapter(&go->i2c_adapter) == 0) go->i2c_adapter_online = 0; else - v4l2_err(go->video_dev, + v4l2_err(&go->v4l2_dev, "error removing I2C adapter!\n"); } diff --git a/drivers/staging/go7007/go7007-priv.h b/drivers/staging/go7007/go7007-priv.h index ce9307e..b58c394 100644 --- a/drivers/staging/go7007/go7007-priv.h +++ b/drivers/staging/go7007/go7007-priv.h @@ -21,6 +21,8 @@ * user-space applications. */ +#include <media/v4l2-device.h> + struct go7007; /* IDs to activate board-specific support code */ @@ -167,6 +169,7 @@ struct go7007 { int channel_number; /* for multi-channel boards like Adlink PCI-MPG24 */ char name[64]; struct video_device *video_dev; + struct v4l2_device v4l2_dev; int ref_count; enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status; spinlock_t spinlock; @@ -240,6 +243,11 @@ struct go7007 { unsigned short interrupt_data; }; +static inline struct go7007 *to_go7007(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct go7007, v4l2_dev); +} + /* All of these must be called with the hpi_lock mutex held! */ #define go7007_interface_reset(go) \ ((go)->hpi_ops->interface_reset(go)) diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c index ecaa3c9..1e89dc0 100644 --- a/drivers/staging/go7007/go7007-usb.c +++ b/drivers/staging/go7007/go7007-usb.c @@ -425,7 +425,7 @@ static struct go7007_usb_board board_sensoray_2250 = { .num_i2c_devs = 1, .i2c_devs = { { - .type = "s2250_board", + .type = "s2250", .id = I2C_DRIVERID_S2250, .addr = 0x43, }, @@ -1057,7 +1057,7 @@ static int go7007_usb_probe(struct usb_interface *intf, usb_rcvintpipe(usb->usbdev, 4), usb->intr_urb->transfer_buffer, 2*sizeof(u16), go7007_usb_readinterrupt_complete, go, 8); - usb_set_intfdata(intf, go); + usb_set_intfdata(intf, &go->v4l2_dev); /* Boot the GO7007 */ if (go7007_boot_encoder(go, go->board_info->flags & @@ -1233,7 +1233,7 @@ allocfail: static void go7007_usb_disconnect(struct usb_interface *intf) { - struct go7007 *go = usb_get_intfdata(intf); + struct go7007 *go = to_go7007(usb_get_intfdata(intf)); struct go7007_usb *usb = go->hpi_context; struct urb *vurb, *aurb; int i; diff --git a/drivers/staging/go7007/go7007-v4l2.c b/drivers/staging/go7007/go7007-v4l2.c index 4bd353a..b18d8e2 100644 --- a/drivers/staging/go7007/go7007-v4l2.c +++ b/drivers/staging/go7007/go7007-v4l2.c @@ -29,6 +29,7 @@ #include <linux/videodev2.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-subdev.h> #include <linux/i2c.h> #include <linux/mutex.h> #include <linux/uaccess.h> @@ -46,6 +47,9 @@ #define V4L2_MPEG_VIDEO_ENCODING_MPEG_4 3 #endif +#define call_all(dev, o, f, args...) \ + v4l2_device_call_until_err(dev, 0, o, f, ##args) + static void deactivate_buffer(struct go7007_buffer *gobuf) { int i; @@ -247,19 +251,23 @@ static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try) go->modet_map[i] = 0; if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) { - struct video_decoder_resolution res; + struct v4l2_format res; + + if (fmt != NULL) { + res = *fmt; + } else { + res.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + res.fmt.pix.width = width; + } - res.width = width; if (height > sensor_height / 2) { - res.height = height / 2; + res.fmt.pix.height = height / 2; go->encoder_v_halve = 0; } else { - res.height = height; + res.fmt.pix.height = height; go->encoder_v_halve = 1; } - if (go->i2c_adapter_online) - i2c_clients_command(&go->i2c_adapter, - DECODER_SET_RESOLUTION, &res); + call_all(&go->v4l2_dev, video, s_fmt, &res); } else { if (width <= sensor_width / 4) { go->encoder_h_halve = 1; @@ -385,7 +393,7 @@ static int clip_to_modet_map(struct go7007 *go, int region, } #endif -static int mpeg_queryctrl(struct v4l2_queryctrl *ctrl) +static int mpeg_query_ctrl(struct v4l2_queryctrl *ctrl) { static const u32 mpeg_ctrls[] = { V4L2_CID_MPEG_CLASS, @@ -973,51 +981,35 @@ static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *query) { struct go7007 *go = ((struct go7007_file *) priv)->go; + int id = query->id; - if (!go->i2c_adapter_online) - return -EIO; - - i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, query); + if (0 == call_all(&go->v4l2_dev, core, queryctrl, query)) + return 0; - return (!query->name[0]) ? mpeg_queryctrl(query) : 0; + query->id = id; + return mpeg_query_ctrl(query); } static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct go7007 *go = ((struct go7007_file *) priv)->go; - struct v4l2_queryctrl query; - if (!go->i2c_adapter_online) - return -EIO; - - memset(&query, 0, sizeof(query)); - query.id = ctrl->id; - i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query); - if (query.name[0] == 0) - return mpeg_g_ctrl(ctrl, go); - i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, ctrl); + if (0 == call_all(&go->v4l2_dev, core, g_ctrl, ctrl)) + return 0; - return 0; + return mpeg_g_ctrl(ctrl, go); } static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct go7007 *go = ((struct go7007_file *) priv)->go; - struct v4l2_queryctrl query; - if (!go->i2c_adapter_online) - return -EIO; - - memset(&query, 0, sizeof(query)); - query.id = ctrl->id; - i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query); - if (query.name[0] == 0) - return mpeg_s_ctrl(ctrl, go); - i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, ctrl); + if (0 == call_all(&go->v4l2_dev, core, s_ctrl, ctrl)) + return 0; - return 0; + return mpeg_s_ctrl(ctrl, go); } static int vidioc_g_parm(struct file *filp, void *priv, @@ -1135,8 +1127,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) if (go->streaming) return -EBUSY; - if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) && - *std != 0) + if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) && *std != 0) return -EINVAL; if (*std == 0) @@ -1146,9 +1137,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) go->input == go->board_info->num_inputs - 1) { if (!go->i2c_adapter_online) return -EIO; - i2c_clients_command(&go->i2c_adapter, - VIDIOC_S_STD, std); - if (!*std) /* hack to indicate EINVAL from tuner */ + if (call_all(&go->v4l2_dev, core, s_std, *std) < 0) return -EINVAL; } @@ -1164,9 +1153,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std) } else return -EINVAL; - if (go->i2c_adapter_online) - i2c_clients_command(&go->i2c_adapter, - VIDIOC_S_STD, std); + call_all(&go->v4l2_dev, core, s_std, *std); set_capture_size(go, NULL, 0); return 0; @@ -1180,7 +1167,7 @@ static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std) go->input == go->board_info->num_inputs - 1) { if (!go->i2c_adapter_online) return -EIO; - i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYSTD, std); + return call_all(&go->v4l2_dev, video, querystd, std); } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV) *std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; else @@ -1238,14 +1225,8 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int input) return -EBUSY; go->input = input; - if (go->i2c_adapter_online) { - i2c_clients_command(&go->i2c_adapter, VIDIOC_S_INPUT, - &go->board_info->inputs[input].video_input); - i2c_clients_command(&go->i2c_adapter, VIDIOC_S_AUDIO, - &go->board_info->inputs[input].audio_input); - } - return 0; + return call_all(&go->v4l2_dev, video, s_routing, input, 0, 0); } static int vidioc_g_tuner(struct file *file, void *priv, @@ -1260,10 +1241,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (!go->i2c_adapter_online) return -EIO; - i2c_clients_command(&go->i2c_adapter, VIDIOC_G_TUNER, t); - - t->index = 0; - return 0; + return call_all(&go->v4l2_dev, tuner, g_tuner, t); } static int vidioc_s_tuner(struct file *file, void *priv, @@ -1287,9 +1265,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, break; } - i2c_clients_command(&go->i2c_adapter, VIDIOC_S_TUNER, t); - - return 0; + return call_all(&go->v4l2_dev, tuner, s_tuner, t); } static int vidioc_g_frequency(struct file *file, void *priv, @@ -1303,8 +1279,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, return -EIO; f->type = V4L2_TUNER_ANALOG_TV; - i2c_clients_command(&go->i2c_adapter, VIDIOC_G_FREQUENCY, f); - return 0; + + return call_all(&go->v4l2_dev, tuner, g_frequency, f); } static int vidioc_s_frequency(struct file *file, void *priv, @@ -1317,9 +1293,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (!go->i2c_adapter_online) return -EIO; - i2c_clients_command(&go->i2c_adapter, VIDIOC_S_FREQUENCY, f); - - return 0; + return call_all(&go->v4l2_dev, tuner, s_frequency, f); } static int vidioc_cropcap(struct file *file, void *priv, @@ -1827,7 +1801,7 @@ int go7007_v4l2_init(struct go7007 *go) go->video_dev = video_device_alloc(); if (go->video_dev == NULL) return -ENOMEM; - memcpy(go->video_dev, &go7007_template, sizeof(go7007_template)); + *go->video_dev = go7007_template; go->video_dev->parent = go->dev; rv = video_register_device(go->video_dev, VFL_TYPE_GRABBER, -1); if (rv < 0) { @@ -1835,6 +1809,12 @@ int go7007_v4l2_init(struct go7007 *go) go->video_dev = NULL; return rv; } + rv = v4l2_device_register(go->dev, &go->v4l2_dev); + if (rv < 0) { + video_device_release(go->video_dev); + go->video_dev = NULL; + return rv; + } video_set_drvdata(go->video_dev, go); ++go->ref_count; printk(KERN_INFO "%s: registered device video%d [v4l2]\n", @@ -1858,4 +1838,5 @@ void go7007_v4l2_remove(struct go7007 *go) mutex_unlock(&go->hw_lock); if (go->video_dev) video_unregister_device(go->video_dev); + v4l2_device_unregister(&go->v4l2_dev); } diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c index f4a6541..8cf7f27 100644 --- a/drivers/staging/go7007/s2250-board.c +++ b/drivers/staging/go7007/s2250-board.c @@ -20,10 +20,14 @@ #include <linux/usb.h> #include <linux/i2c.h> #include <linux/videodev2.h> +#include <media/v4l2-device.h> #include <media/v4l2-common.h> -#include "s2250-loader.h" +#include <media/v4l2-i2c-drv.h> +#include <media/v4l2-subdev.h> #include "go7007-priv.h" -#include "wis-i2c.h" + +MODULE_DESCRIPTION("Sensoray 2250/2251 i2c v4l2 subdev driver"); +MODULE_LICENSE("GPL v2"); #define TLV320_ADDRESS 0x34 #define VPX322_ADDR_ANALOGCONTROL1 0x02 @@ -112,6 +116,7 @@ static u16 vid_regs_fp_pal[] = }; struct s2250 { + struct v4l2_subdev sd; v4l2_std_id std; int input; int brightness; @@ -123,6 +128,11 @@ struct s2250 { struct i2c_client *audio; }; +static inline struct s2250 *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct s2250, sd); +} + /* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/ static int go7007_usb_vendor_request(struct go7007 *go, u16 request, u16 value, u16 index, void *transfer_buffer, int length, int in) @@ -306,253 +316,262 @@ static int write_regs_fp(struct i2c_client *client, u16 *regs) } -static int s2250_command(struct i2c_client *client, - unsigned int cmd, void *arg) +/* ------------------------------------------------------------------------- */ + +static int s2250_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output, + u32 config) { - struct s2250 *dec = i2c_get_clientdata(client); + struct s2250 *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int vidsys; + + vidsys = (state->std == V4L2_STD_NTSC) ? 0x01 : 0x00; + if (input == 0) { + /* composite */ + write_reg_fp(client, 0x20, 0x020 | vidsys); + write_reg_fp(client, 0x21, 0x662); + write_reg_fp(client, 0x140, 0x060); + } else if (input == 1) { + /* S-Video */ + write_reg_fp(client, 0x20, 0x040 | vidsys); + write_reg_fp(client, 0x21, 0x666); + write_reg_fp(client, 0x140, 0x060); + } else { + return -EINVAL; + } + state->input = input; + return 0; +} - switch (cmd) { - case VIDIOC_S_INPUT: - { - int vidsys; - int *input = arg; - - vidsys = (dec->std == V4L2_STD_NTSC) ? 0x01 : 0x00; - if (*input == 0) { - /* composite */ - write_reg_fp(client, 0x20, 0x020 | vidsys); - write_reg_fp(client, 0x21, 0x662); - write_reg_fp(client, 0x140, 0x060); - } else { - /* S-Video */ - write_reg_fp(client, 0x20, 0x040 | vidsys); - write_reg_fp(client, 0x21, 0x666); - write_reg_fp(client, 0x140, 0x060); - } - dec->input = *input; +static int s2250_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) +{ + struct s2250 *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + u16 vidsource; + + vidsource = (state->input == 1) ? 0x040 : 0x020; + switch (norm) { + case V4L2_STD_NTSC: + write_regs_fp(client, vid_regs_fp); + write_reg_fp(client, 0x20, vidsource | 1); break; - } - case VIDIOC_S_STD: - { - v4l2_std_id *std = arg; - u16 vidsource; - - vidsource = (dec->input == 1) ? 0x040 : 0x020; - dec->std = *std; - switch (dec->std) { - case V4L2_STD_NTSC: - write_regs_fp(client, vid_regs_fp); - write_reg_fp(client, 0x20, vidsource | 1); - break; - case V4L2_STD_PAL: - write_regs_fp(client, vid_regs_fp); - write_regs_fp(client, vid_regs_fp_pal); - write_reg_fp(client, 0x20, vidsource); - break; - default: - return -EINVAL; - } + case V4L2_STD_PAL: + write_regs_fp(client, vid_regs_fp); + write_regs_fp(client, vid_regs_fp_pal); + write_reg_fp(client, 0x20, vidsource); break; + default: + return -EINVAL; } - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *ctrl = arg; - static const u32 user_ctrls[] = { - V4L2_CID_BRIGHTNESS, - V4L2_CID_CONTRAST, - V4L2_CID_SATURATION, - V4L2_CID_HUE, - 0 - }; - static const u32 *ctrl_classes[] = { - user_ctrls, - NULL - }; - - ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id); - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); - break; - case V4L2_CID_CONTRAST: - v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); - break; - case V4L2_CID_SATURATION: - v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50); - break; - case V4L2_CID_HUE: - v4l2_ctrl_query_fill(ctrl, -50, 50, 1, 0); - break; - default: - ctrl->name[0] = '\0'; - return -EINVAL; - } - break; + state->std = norm; + return 0; +} + +static int s2250_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *query) +{ + switch (query->id) { + case V4L2_CID_BRIGHTNESS: + return v4l2_ctrl_query_fill(query, 0, 100, 1, 50); + case V4L2_CID_CONTRAST: + return v4l2_ctrl_query_fill(query, 0, 100, 1, 50); + case V4L2_CID_SATURATION: + return v4l2_ctrl_query_fill(query, 0, 100, 1, 50); + case V4L2_CID_HUE: + return v4l2_ctrl_query_fill(query, -50, 50, 1, 0); + default: + return -EINVAL; } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl = arg; - int value1; - u16 oldvalue; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - if (ctrl->value > 100) - dec->brightness = 100; - else if (ctrl->value < 0) - dec->brightness = 0; - else - dec->brightness = ctrl->value; - value1 = (dec->brightness - 50) * 255 / 100; - read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue); - write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, - value1 | (oldvalue & ~0xff)); - read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue); - write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, - value1 | (oldvalue & ~0xff)); - write_reg_fp(client, 0x140, 0x60); - break; - case V4L2_CID_CONTRAST: - if (ctrl->value > 100) - dec->contrast = 100; - else if (ctrl->value < 0) - dec->contrast = 0; - else - dec->contrast = ctrl->value; - value1 = dec->contrast * 0x40 / 100; - if (value1 > 0x3f) - value1 = 0x3f; /* max */ - read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue); - write_reg_fp(client, VPX322_ADDR_CONTRAST0, - value1 | (oldvalue & ~0x3f)); - read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue); - write_reg_fp(client, VPX322_ADDR_CONTRAST1, - value1 | (oldvalue & ~0x3f)); - write_reg_fp(client, 0x140, 0x60); - break; - case V4L2_CID_SATURATION: - if (ctrl->value > 127) - dec->saturation = 127; - else if (ctrl->value < 0) - dec->saturation = 0; - else - dec->saturation = ctrl->value; - - value1 = dec->saturation * 4140 / 100; - if (value1 > 4094) - value1 = 4094; - write_reg_fp(client, VPX322_ADDR_SAT, value1); - break; - case V4L2_CID_HUE: - if (ctrl->value > 50) - dec->hue = 50; - else if (ctrl->value < -50) - dec->hue = -50; - else - dec->hue = ctrl->value; - /* clamp the hue range */ - value1 = dec->hue * 280 / 50; - write_reg_fp(client, VPX322_ADDR_HUE, value1); - break; - } + return 0; +} + +static int s2250_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct s2250 *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int value1; + u16 oldvalue; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + if (ctrl->value > 100) + state->brightness = 100; + else if (ctrl->value < 0) + state->brightness = 0; + else + state->brightness = ctrl->value; + value1 = (state->brightness - 50) * 255 / 100; + read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue); + write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, + value1 | (oldvalue & ~0xff)); + read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue); + write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, + value1 | (oldvalue & ~0xff)); + write_reg_fp(client, 0x140, 0x60); break; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl = arg; - - switch (ctrl->id) { - case V4L2_CID_BRIGHTNESS: - ctrl->value = dec->brightness; - break; - case V4L2_CID_CONTRAST: - ctrl->value = dec->contrast; - break; - case V4L2_CID_SATURATION: - ctrl->value = dec->saturation; - break; - case V4L2_CID_HUE: - ctrl->value = dec->hue; - break; - } + case V4L2_CID_CONTRAST: + if (ctrl->value > 100) + state->contrast = 100; + else if (ctrl->value < 0) + state->contrast = 0; + else + state->contrast = ctrl->value; + value1 = state->contrast * 0x40 / 100; + if (value1 > 0x3f) + value1 = 0x3f; /* max */ + read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue); + write_reg_fp(client, VPX322_ADDR_CONTRAST0, + value1 | (oldvalue & ~0x3f)); + read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue); + write_reg_fp(client, VPX322_ADDR_CONTRAST1, + value1 | (oldvalue & ~0x3f)); + write_reg_fp(client, 0x140, 0x60); break; + case V4L2_CID_SATURATION: + if (ctrl->value > 100) + state->saturation = 100; + else if (ctrl->value < 0) + state->saturation = 0; + else + state->saturation = ctrl->value; + value1 = state->saturation * 4140 / 100; + if (value1 > 4094) + value1 = 4094; + write_reg_fp(client, VPX322_ADDR_SAT, value1); + break; + case V4L2_CID_HUE: + if (ctrl->value > 50) + state->hue = 50; + else if (ctrl->value < -50) + state->hue = -50; + else + state->hue = ctrl->value; + /* clamp the hue range */ + value1 = state->hue * 280 / 50; + write_reg_fp(client, VPX322_ADDR_HUE, value1); + break; + default: + return -EINVAL; } - case VIDIOC_S_FMT: - { - struct v4l2_format *fmt = arg; - if (fmt->fmt.pix.height < 640) { - write_reg_fp(client, 0x12b, dec->reg12b_val | 0x400); - write_reg_fp(client, 0x140, 0x060); - } else { - write_reg_fp(client, 0x12b, dec->reg12b_val & ~0x400); - write_reg_fp(client, 0x140, 0x060); - } - return 0; - } - case VIDIOC_G_AUDIO: - { - struct v4l2_audio *audio = arg; + return 0; +} - memset(audio, 0, sizeof(*audio)); - audio->index = dec->audio_input; - /* fall through */ - } - case VIDIOC_ENUMAUDIO: - { - struct v4l2_audio *audio = arg; - - switch (audio->index) { - case 0: - strcpy(audio->name, "Line In"); - break; - case 1: - strcpy(audio->name, "Mic"); - break; - case 2: - strcpy(audio->name, "Mic Boost"); - break; - default: - audio->name[0] = '\0'; - return 0; - } - audio->capability = V4L2_AUDCAP_STEREO; - audio->mode = 0; - return 0; +static int s2250_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct s2250 *state = to_state(sd); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->value = state->brightness; + break; + case V4L2_CID_CONTRAST: + ctrl->value = state->contrast; + break; + case V4L2_CID_SATURATION: + ctrl->value = state->saturation; + break; + case V4L2_CID_HUE: + ctrl->value = state->hue; + break; + default: + return -EINVAL; } - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *audio = arg; - - switch (audio->index) { - case 0: - write_reg(dec->audio, 0x08, 0x02); /* Line In */ - break; - case 1: - write_reg(dec->audio, 0x08, 0x04); /* Mic */ - break; - case 2: - write_reg(dec->audio, 0x08, 0x05); /* Mic Boost */ - break; - default: - return -EINVAL; - } - dec->audio_input = audio->index; - return 0; + return 0; +} + +static int s2250_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct s2250 *state = to_state(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (fmt->fmt.pix.height < 640) { + write_reg_fp(client, 0x12b, state->reg12b_val | 0x400); + write_reg_fp(client, 0x140, 0x060); + } else { + write_reg_fp(client, 0x12b, state->reg12b_val & ~0x400); + write_reg_fp(client, 0x140, 0x060); } + return 0; +} - default: - printk(KERN_INFO "s2250: unknown command 0x%x\n", cmd); +static int s2250_s_audio_routing(struct v4l2_subdev *sd, u32 input, u32 output, + u32 config) +{ + struct s2250 *state = to_state(sd); + + switch (input) { + case 0: + write_reg(state->audio, 0x08, 0x02); /* Line In */ + break; + case 1: + write_reg(state->audio, 0x08, 0x04); /* Mic */ break; + case 2: + write_reg(state->audio, 0x08, 0x05); /* Mic Boost */ + break; + default: + return -EINVAL; } + state->audio_input = input; + return 0; +} + + +static int s2250_log_status(struct v4l2_subdev *sd) +{ + struct s2250 *state = to_state(sd); + + v4l2_info(sd, "Standard: %s\n", state->std == V4L2_STD_NTSC ? "NTSC" : + state->std == V4L2_STD_PAL ? "PAL" : + state->std == V4L2_STD_SECAM ? "SECAM" : + "unknown"); + v4l2_info(sd, "Input: %s\n", state->input == 0 ? "Composite" : + state->input == 1 ? "S-video" : + "error"); + v4l2_info(sd, "Brightness: %d\n", state->brightness); + v4l2_info(sd, "Contrast: %d\n", state->contrast); + v4l2_info(sd, "Saturation: %d\n", state->saturation); + v4l2_info(sd, "Hue: %d\n", state->hue); return 0; + v4l2_info(sd, "Audio input: %s\n", state->audio_input == 0 ? "Line In" : + state->audio_input == 1 ? "Mic" : + state->audio_input == 2 ? "Mic Boost" : + "error"); return 0; } +/* --------------------------------------------------------------------------*/ + +static const struct v4l2_subdev_core_ops s2250_core_ops = { + .log_status = s2250_log_status, + .g_ctrl = s2250_g_ctrl, + .s_ctrl = s2250_s_ctrl, + .queryctrl = s2250_queryctrl, + .s_std = s2250_s_std, +}; + +static const struct v4l2_subdev_audio_ops s2250_audio_ops = { + .s_routing = s2250_s_audio_routing, +}; + +static const struct v4l2_subdev_video_ops s2250_video_ops = { + .s_routing = s2250_s_video_routing, + .s_fmt = s2250_s_fmt, +}; + +static const struct v4l2_subdev_ops s2250_ops = { + .core = &s2250_core_ops, + .audio = &s2250_audio_ops, + .video = &s2250_video_ops, +}; + +/* --------------------------------------------------------------------------*/ + static int s2250_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_client *audio; struct i2c_adapter *adapter = client->adapter; - struct s2250 *dec; + struct s2250 *state; + struct v4l2_subdev *sd; u8 *data; struct go7007 *go = i2c_get_adapdata(adapter); struct go7007_usb *usb = go->hpi_context; @@ -561,30 +580,31 @@ static int s2250_probe(struct i2c_client *client, if (audio == NULL) return -ENOMEM; - dec = kmalloc(sizeof(struct s2250), GFP_KERNEL); - if (dec == NULL) { + state = kmalloc(sizeof(struct s2250), GFP_KERNEL); + if (state == NULL) { i2c_unregister_device(audio); return -ENOMEM; } - dec->std = V4L2_STD_NTSC; - dec->brightness = 50; - dec->contrast = 50; - dec->saturation = 50; - dec->hue = 0; - dec->audio = audio; - i2c_set_clientdata(client, dec); + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &s2250_ops); + + v4l2_info(sd, "initializing %s at address 0x%x on %s\n", + "Sensoray 2250/2251", client->addr, client->adapter->name); - printk(KERN_DEBUG - "s2250: initializing video decoder on %s\n", - adapter->name); + state->std = V4L2_STD_NTSC; + state->brightness = 50; + state->contrast = 50; + state->saturation = 50; + state->hue = 0; + state->audio = audio; /* initialize the audio */ if (write_regs(audio, aud_regs) < 0) { printk(KERN_ERR "s2250: error initializing audio\n"); i2c_unregister_device(audio); - kfree(dec); + kfree(state); return 0; } @@ -592,14 +612,14 @@ static int s2250_probe(struct i2c_client *client, printk(KERN_ERR "s2250: error initializing decoder\n"); i2c_unregister_device(audio); - kfree(dec); + kfree(state); return 0; } if (write_regs_fp(client, vid_regs_fp) < 0) { printk(KERN_ERR "s2250: error initializing decoder\n"); i2c_unregister_device(audio); - kfree(dec); + kfree(state); return 0; } /* set default channel */ @@ -609,7 +629,7 @@ static int s2250_probe(struct i2c_client *client, write_reg_fp(client, 0x140, 0x060); /* set default audio input */ - dec->audio_input = 0; + state->audio_input = 0; write_reg(client, 0x08, 0x02); /* Line In */ if (mutex_lock_interruptible(&usb->i2c_lock) == 0) { @@ -634,60 +654,28 @@ static int s2250_probe(struct i2c_client *client, mutex_unlock(&usb->i2c_lock); } - printk("s2250: initialized successfully\n"); + v4l2_info(sd, "initialized successfully\n"); return 0; } static int s2250_remove(struct i2c_client *client) { - struct s2250 *dec = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); - i2c_unregister_device(dec->audio); - kfree(dec); + v4l2_device_unregister_subdev(sd); + kfree(to_state(sd)); return 0; } static struct i2c_device_id s2250_id[] = { - { "s2250_board", 0 }, + { "s2250", 0 }, { } }; +MODULE_DEVICE_TABLE(i2c, s2250_id); -static struct i2c_driver s2250_driver = { - .driver = { - .name = "Sensoray 2250 board driver", - }, - .probe = s2250_probe, - .remove = s2250_remove, - .command = s2250_command, - .id_table = s2250_id, +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "s2250", + .probe = s2250_probe, + .remove = s2250_remove, + .id_table = s2250_id, }; - -static int __init s2250_init(void) -{ - int r; - - r = s2250loader_init(); - if (r < 0) - return r; - - r = i2c_add_driver(&s2250_driver); - if (r < 0) - s2250loader_cleanup(); - - return r; -} - -static void __exit s2250_cleanup(void) -{ - i2c_del_driver(&s2250_driver); - - s2250loader_cleanup(); -} - -module_init(s2250_init); -module_exit(s2250_cleanup); - -MODULE_AUTHOR(""); -MODULE_DESCRIPTION("Board driver for Sensoryray 2250"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/go7007/s2250-loader.c b/drivers/staging/go7007/s2250-loader.c index d7bf829..c152ab9 100644 --- a/drivers/staging/go7007/s2250-loader.c +++ b/drivers/staging/go7007/s2250-loader.c @@ -162,7 +162,7 @@ static struct usb_driver s2250loader_driver = { .id_table = s2250loader_ids, }; -int s2250loader_init(void) +static int __init s2250loader_init(void) { int r; unsigned i = 0; @@ -179,11 +179,15 @@ int s2250loader_init(void) printk(KERN_INFO "s2250loader_init: driver registered\n"); return 0; } -EXPORT_SYMBOL(s2250loader_init); +module_init(s2250loader_init); -void s2250loader_cleanup(void) +static void __exit s2250loader_cleanup(void) { printk(KERN_INFO "s2250loader_cleanup\n"); usb_deregister(&s2250loader_driver); } -EXPORT_SYMBOL(s2250loader_cleanup); +module_exit(s2250loader_cleanup); + +MODULE_AUTHOR(""); +MODULE_DESCRIPTION("firmware loader for Sensoray 2250/2251"); +MODULE_LICENSE("GPL v2"); |