On Thu, Sep 06, 2012 at 11:10:14PM +0400, Volokh Konstantin wrote: > On Mon, Sep 03, 2012 at 02:37:16PM -0400, Adam Rosi-Kessel wrote: > > > > [469.928881] wis-saa7115: initializing SAA7115 at address 32 on WIS > > GO7007SB EZ-USB > > > > [469.989083] go7007: probing for module i2c:wis_saa7115 failed > > > > [470.004785] wis-uda1342: initializing UDA1342 at address 26 on WIS > > GO7007SB EZ-USB > > > > [470.005454] go7007: probing for module i2c:wis_uda1342 failed > > > > [470.011659] wis-sony-tuner: initializing tuner at address 96 on WIS > > GO7007SB EZ-USB Hi, I generated patchs, that u may in your own go7007/ folder It contains go7007 initialization and i2c_subdev fixing It was checked for 3.6 branch (compile only) Regards, Volokh Konstantin
diff --git a/drivers/staging/media/go7007/go7007-driver.c b/drivers/staging/media/go7007/go7007-driver.c index ece2dd1..2dff9b5 100644 --- a/drivers/staging/media/go7007/go7007-driver.c +++ b/drivers/staging/media/go7007/go7007-driver.c @@ -173,6 +173,11 @@ static int go7007_init_encoder(struct go7007 *go) go7007_write_addr(go, 0x3c82, 0x0001); go7007_write_addr(go, 0x3c80, 0x00fe); } + if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { + /* set GPIO5 to be an output, currently low */ + go7007_write_addr(go, 0x3c82, 0x0000); + go7007_write_addr(go, 0x3c80, 0x00df); + } return 0; } @@ -192,17 +197,23 @@ int go7007_reset_encoder(struct go7007 *go) /* * Attempt to instantiate an I2C client by ID, probably loading a module. */ -static int init_i2c_module(struct i2c_adapter *adapter, const char *type, - int addr) +static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *const i2c) { struct go7007 *go = i2c_get_adapdata(adapter); struct v4l2_device *v4l2_dev = &go->v4l2_dev; + struct i2c_board_info info; + + memset(&info, 0, sizeof(info)); + strlcpy(info.type, i2c->type, sizeof(info.type)); + info.addr = i2c->addr; - if (v4l2_i2c_new_subdev(v4l2_dev, adapter, type, addr, NULL)) + if (i2c->id == I2C_DRIVERID_WIS_TW2804) + info.flags |= I2C_CLIENT_TEN; + if (v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, NULL)) return 0; - printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", type); - return -1; + printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", i2c->type); + return -EINVAL; } /* @@ -238,9 +249,7 @@ int go7007_register_encoder(struct go7007 *go) } if (go->i2c_adapter_online) { for (i = 0; i < go->board_info->num_i2c_devs; ++i) - init_i2c_module(&go->i2c_adapter, - go->board_info->i2c_devs[i].type, - go->board_info->i2c_devs[i].addr); + init_i2c_module(&go->i2c_adapter, &go->board_info->i2c_devs[i]); if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) i2c_clients_command(&go->i2c_adapter, DECODER_SET_CHANNEL, &go->channel_number); @@ -571,7 +580,7 @@ struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev) struct go7007 *go; int i; - go = kmalloc(sizeof(struct go7007), GFP_KERNEL); + go = kzalloc(sizeof(struct go7007), GFP_KERNEL); if (go == NULL) return NULL; go->dev = dev; diff --git a/drivers/staging/media/go7007/go7007-priv.h b/drivers/staging/media/go7007/go7007-priv.h index b58c394..b7b939a 100644 --- a/drivers/staging/media/go7007/go7007-priv.h +++ b/drivers/staging/media/go7007/go7007-priv.h @@ -88,7 +88,7 @@ struct go7007_board_info { int audio_bclk_div; int audio_main_div; int num_i2c_devs; - struct { + struct go_i2c { const char *type; int id; int addr; diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c index 5443e25..9dbf5ec 100644 --- a/drivers/staging/media/go7007/go7007-usb.c +++ b/drivers/staging/media/go7007/go7007-usb.c @@ -1110,9 +1110,6 @@ static int go7007_usb_probe(struct usb_interface *intf, } else { u16 channel; - /* set GPIO5 to be an output, currently low */ - go7007_write_addr(go, 0x3c82, 0x0000); - go7007_write_addr(go, 0x3c80, 0x00df); /* read channel number from GPIO[1:0] */ go7007_read_addr(go, 0x3c81, &channel); channel &= 0x3; @@ -1245,7 +1242,6 @@ static void go7007_usb_disconnect(struct usb_interface *intf) struct urb *vurb, *aurb; int i; - go->status = STATUS_SHUTDOWN; usb_kill_urb(usb->intr_urb); /* Free USB-related structs */ @@ -1269,6 +1265,7 @@ static void go7007_usb_disconnect(struct usb_interface *intf) kfree(go->hpi_context); go7007_remove(go); + go->status = STATUS_SHUTDOWN; } static struct usb_driver go7007_usb_driver = { diff --git a/drivers/staging/media/go7007/go7007-v4l2.c b/drivers/staging/media/go7007/go7007-v4l2.c index c184ad3..b8f2eb6 100644 --- a/drivers/staging/media/go7007/go7007-v4l2.c +++ b/drivers/staging/media/go7007/go7007-v4l2.c @@ -98,7 +98,7 @@ static int go7007_open(struct file *file) if (go->status != STATUS_ONLINE) return -EBUSY; - gofh = kmalloc(sizeof(struct go7007_file), GFP_KERNEL); + gofh = kzalloc(sizeof(struct go7007_file), GFP_KERNEL); if (gofh == NULL) return -ENOMEM; ++go->ref_count; @@ -953,6 +953,7 @@ static int vidioc_streamon(struct file *file, void *priv, } mutex_unlock(&go->hw_lock); mutex_unlock(&gofh->lock); + call_all(&go->v4l2_dev, video, s_stream, 1); return retval; } @@ -968,6 +969,7 @@ static int vidioc_streamoff(struct file *file, void *priv, mutex_lock(&gofh->lock); go7007_streamoff(go); mutex_unlock(&gofh->lock); + call_all(&go->v4l2_dev, video, s_stream, 0); return 0; } @@ -1832,5 +1834,6 @@ 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); + if (go->status != STATUS_SHUTDOWN) + v4l2_device_unregister(&go->v4l2_dev); } diff --git a/drivers/staging/media/go7007/wis-saa7115.c b/drivers/staging/media/go7007/wis-saa7115.c index 46cff59..9065cc7 100644 --- a/drivers/staging/media/go7007/wis-saa7115.c +++ b/drivers/staging/media/go7007/wis-saa7115.c @@ -21,10 +21,17 @@ #include <linux/videodev2.h> #include <linux/ioctl.h> #include <linux/slab.h> +#include <media/v4l2-common.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-subdev.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> #include "wis-i2c.h" struct wis_saa7115 { + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; int norm; int brightness; int contrast; @@ -182,6 +189,15 @@ static u8 initial_registers[] = 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */ }; +static const struct v4l2_subdev_core_ops wis_saa7115_core_ops = { +}; + +static const struct v4l2_subdev_video_ops wis_saa7115_video_ops = { +/* .s_routing = tw2804_s_video_routing, + .s_mbus_fmt = tw2804_s_mbus_fmt, + .s_stream = tw2804_s_stream,*/ +}; + static int write_reg(struct i2c_client *client, u8 reg, u8 value) { return i2c_smbus_write_byte_data(client, reg, value); @@ -197,10 +213,16 @@ static int write_regs(struct i2c_client *client, u8 *regs) return 0; } +inline struct wis_saa7115 *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct wis_saa7115, sd); +} + static int wis_saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct wis_saa7115 *dec = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct wis_saa7115 *dec = to_state(sd); switch (cmd) { case VIDIOC_S_INPUT: @@ -395,11 +417,18 @@ static int wis_saa7115_command(struct i2c_client *client, return 0; } +static const struct v4l2_subdev_ops wis_saa7115_ops = { + .core = &wis_saa7115_core_ops, + .video = &wis_saa7115_video_ops, +// .video = &wis_sony_tuner_video_ops, +}; + static int wis_saa7115_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = client->adapter; struct wis_saa7115 *dec; + struct v4l2_subdev *sd; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; @@ -407,13 +436,14 @@ static int wis_saa7115_probe(struct i2c_client *client, dec = kmalloc(sizeof(struct wis_saa7115), GFP_KERNEL); if (dec == NULL) return -ENOMEM; + sd = &dec->sd; + v4l2_i2c_subdev_init(sd, client, &wis_saa7115_ops); dec->norm = V4L2_STD_NTSC; dec->brightness = 128; dec->contrast = 64; dec->saturation = 64; dec->hue = 0; - i2c_set_clientdata(client, dec); printk(KERN_DEBUG "wis-saa7115: initializing SAA7115 at address %d on %s\n", @@ -431,8 +461,10 @@ static int wis_saa7115_probe(struct i2c_client *client, static int wis_saa7115_remove(struct i2c_client *client) { - struct wis_saa7115 *dec = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct wis_saa7115 *dec = to_state(sd); + v4l2_device_unregister_subdev(sd); kfree(dec); return 0; } diff --git a/drivers/staging/media/go7007/wis-sony-tuner.c b/drivers/staging/media/go7007/wis-sony-tuner.c index 8f1b7d4..884a261 100644 --- a/drivers/staging/media/go7007/wis-sony-tuner.c +++ b/drivers/staging/media/go7007/wis-sony-tuner.c @@ -23,6 +23,9 @@ #include <media/tuner.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-subdev.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> #include "wis-i2c.h" @@ -67,6 +70,8 @@ static struct sony_tunertype sony_tuners[] = { }; struct wis_sony_tuner { + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; int type; v4l2_std_id std; unsigned int freq; @@ -74,10 +79,32 @@ struct wis_sony_tuner { u32 audmode; }; +inline struct wis_sony_tuner *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct wis_sony_tuner, sd); +} + +static const struct v4l2_subdev_tuner_ops wis_sony_tuner_ops = { +}; + +static const struct v4l2_subdev_core_ops wis_sony_core_ops = { +/* .log_status = wis_sony_tuner_log_status, + .g_chip_ident = wis_sony_tuner_g_chip_ident, + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, + .queryctrl = v4l2_subdev_queryctrl, + .querymenu = v4l2_subdev_querymenu, + .s_std = wis_sony_tuner_s_std,*/ +}; + /* Basically the same as default_set_tv_freq() in tuner.c */ static int set_freq(struct i2c_client *client, int freq) { - struct wis_sony_tuner *t = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct wis_sony_tuner *t = to_state(sd); char *band_name; int n; int band_select; @@ -220,7 +247,8 @@ static struct { static int mpx_setup(struct i2c_client *client) { - struct wis_sony_tuner *t = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct wis_sony_tuner *t = to_state(sd); u16 source = 0; u8 buffer[3]; struct i2c_msg msg; @@ -336,7 +364,8 @@ static int mpx_setup(struct i2c_client *client) static int set_if(struct i2c_client *client) { - struct wis_sony_tuner *t = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct wis_sony_tuner *t = to_state(sd); u8 buffer[4]; struct i2c_msg msg; int default_mpx_mode = 0; @@ -384,7 +413,8 @@ static int set_if(struct i2c_client *client) static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) { - struct wis_sony_tuner *t = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct wis_sony_tuner *t = to_state(sd); switch (cmd) { #if 0 @@ -654,24 +684,33 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } + +static const struct v4l2_subdev_ops wis_sony_ops = { + .core = &wis_sony_core_ops, + .tuner = &wis_sony_tuner_ops, +// .video = &wis_sony_tuner_video_ops, +}; + static int wis_sony_tuner_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = client->adapter; struct wis_sony_tuner *t; + struct v4l2_subdev *sd; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) return -ENODEV; - t = kmalloc(sizeof(struct wis_sony_tuner), GFP_KERNEL); + t = kzalloc(sizeof(struct wis_sony_tuner), GFP_KERNEL); if (t == NULL) return -ENOMEM; + sd = &t->sd; + v4l2_i2c_subdev_init(sd, client, &wis_sony_ops); t->type = -1; t->freq = 0; t->mpxmode = 0; t->audmode = V4L2_TUNER_MODE_STEREO; - i2c_set_clientdata(client, t); printk(KERN_DEBUG "wis-sony-tuner: initializing tuner at address %d on %s\n", @@ -682,8 +721,10 @@ static int wis_sony_tuner_probe(struct i2c_client *client, static int wis_sony_tuner_remove(struct i2c_client *client) { - struct wis_sony_tuner *t = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct wis_sony_tuner *t = to_state(sd); + v4l2_device_unregister_subdev(sd); kfree(t); return 0; } diff --git a/drivers/staging/media/go7007/wis-uda1342.c b/drivers/staging/media/go7007/wis-uda1342.c index 0127be2..83aa1b9 100644 --- a/drivers/staging/media/go7007/wis-uda1342.c +++ b/drivers/staging/media/go7007/wis-uda1342.c @@ -18,9 +18,14 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/i2c.h> +#include <linux/slab.h> #include <linux/videodev2.h> #include <media/tvaudio.h> #include <media/v4l2-common.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-subdev.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> #include "wis-i2c.h" @@ -31,6 +36,9 @@ static int write_reg(struct i2c_client *client, int reg, int value) return 0; } +static const struct v4l2_subdev_audio_ops wis_uda1342_audio_ops = { +}; + static int wis_uda1342_command(struct i2c_client *client, unsigned int cmd, void *arg) { @@ -59,10 +67,16 @@ static int wis_uda1342_command(struct i2c_client *client, return 0; } +static const struct v4l2_subdev_ops wis_uda1342_ops = { +// .core = &wis_uda1342_core_ops, + .audio = &wis_uda1342_audio_ops, +}; + static int wis_uda1342_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = client->adapter; + struct v4l2_subdev *sd; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) return -ENODEV; @@ -70,7 +84,11 @@ static int wis_uda1342_probe(struct i2c_client *client, printk(KERN_DEBUG "wis-uda1342: initializing UDA1342 at address %d on %s\n", client->addr, adapter->name); + sd=kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + v4l2_i2c_subdev_init(sd, client, &wis_uda1342_ops); write_reg(client, 0x00, 0x8000); /* reset registers */ write_reg(client, 0x00, 0x1241); /* select input 1 */ @@ -79,6 +97,10 @@ static int wis_uda1342_probe(struct i2c_client *client, static int wis_uda1342_remove(struct i2c_client *client) { + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_device_unregister_subdev(sd); + kfree(sd); return 0; }