Hi, after reading the topic "controls, subdevs, and media framework" (http://www.spinics.net/lists/linux-media/msg24474.html) I guess I double-posted something here :S But what I still don't understand is, how configuring the camera works. You say that the subdevs (my camera sensor) are configured directly. 2 things make me wonder. How gets the ISP informed about the change and why don't I see my camera in the subdevs name list I posted. All subdevs are from the ISP. My camera already receives a clock, the i2c connection works and my oscilloscope shows that the sensor is throwing out data on the parallel bus pins. But unfortunately I am a completely v4l2 newbie. I read through the v4l2-docs now but the first example already didn't work because of the new framework. Can you point me to a way to read /dev/video2? Thank you very much, Bastian 2010/10/28 Bastian Hecht <hechtb@xxxxxxxxxxxxxx>: > Hello Laurent, > > my mt9p031 camera project for the omap3530 isp has come to the point > where the ISP registered video[0-6], media0 and v4l-subdev[0-7]. > > As far as I can see from the names... > > cat /sys/class/video4linux/video*/names > OMAP3 ISP CCP2 input > OMAP3 ISP CSI2a output > OMAP3 ISP CCDC output > OMAP3 ISP preview input > OMAP3 ISP preview output > OMAP3 ISP resizer input > OMAP3 ISP resizer output > > cat /sys/class/video4linux/v4l-subdev*/names > OMAP3 ISP CCP2 > OMAP3 ISP CSI2a > OMAP3 ISP CCDC > OMAP3 ISP preview > OMAP3 ISP resizer > OMAP3 ISP AEWB > OMAP3 ISP AF > OMAP3 ISP histogram > > ... I want to read /dev/video2 (CCDC). > > When I try out a little test program from the V4L2 doc, this line fails: > ioctl (fd, VIDIOC_G_STD, &std_id) > > > So far I adopted your mt9t001 driver, merged it with Guennadis > mt9p031. It contains lot of stubs that I want to fill out when I > succeed to make them called inside the kernel. > I looked at your presentation for the media controller and wonder if I > have to set up a pipeline by myself before I can read /dev/video2 > (http://linuxtv.org/downloads/presentations/summit_jun_2010/20100614-v4l2_summit-media.pdf). > I failed at the point where I wanted to try out the little snippet on > page 17 as I don't have definitions of the MEDIA_IOC_ENUM_ENTITIES. > Are there somewhere userspace headers available? > > int fd; > fd = open(“/dev/media0”, O_RDWR); > while (1) { > struct media_user_entity entity; > struct media_user_links links; > ret = ioctl(fd, MEDIA_IOC_ENUM_ENTITIES, &entity); > if (ret < 0) > break; > while (1) { > ret = ioctl(fd, MEDIA_IOC_ENUM_LINKS, &links); > if (ret < 0) > break; > } > > Thanks for help, > > Bastian > > > APPENDIX A: dmesg > > [ 103.356018] Linux media interface: v0.10 > [ 103.356048] device class 'media': registering > [ 103.442230] Linux video capture interface: v2.00 > [ 103.442260] device class 'video4linux': registering > [ 103.814239] bus: 'i2c': add driver mt9p031 > [ 103.894622] bus: 'platform': add driver omap3isp > [ 103.933959] address of isp_platform_data in boardconfig: bf065074 > [ 103.940155] Registering platform device 'omap3isp'. Parent at platform > [ 103.940185] device: 'omap3isp': device_add > [ 103.940246] bus: 'platform': add device omap3isp > [ 103.940490] bus: 'platform': driver_probe_device: matched device > omap3isp with driver omap3isp > [ 103.940490] bus: 'platform': really_probe: probing driver omap3isp > with device omap3isp > [ 103.940551] address of isp_platform_data bf065074 > [ 103.954467] omap3isp omap3isp: Revision 2.0 found > [ 103.962738] omap-iommu omap-iommu.0: isp: version 1.1 > [ 103.969879] omap3isp omap3isp: hist: DMA channel = 0 > [ 103.970001] omap3isp omap3isp: isp_set_xclk(): cam_xclka set to 5760000 Hz > [ 103.972229] omap3isp omap3isp: -------------ISP Register dump-------------- > [ 103.972259] omap3isp omap3isp: ###ISP SYSCONFIG=0x00000001 > [ 103.972259] omap3isp omap3isp: ###ISP SYSSTATUS=0x00000001 > [ 103.972290] omap3isp omap3isp: ###ISP IRQ0ENABLE=0x00000000 > [ 103.972290] omap3isp omap3isp: ###ISP IRQ0STATUS=0x00000000 > [ 103.972320] omap3isp omap3isp: ###ISP TCTRL_GRESET_LENGTH=0x00000000 > [ 103.972320] omap3isp omap3isp: ###ISP TCTRL_PSTRB_REPLAY=0x00000000 > [ 103.972351] omap3isp omap3isp: ###ISP CTRL=0x00200200 > [ 103.972351] omap3isp omap3isp: ###ISP TCTRL_CTRL=0x0000001e > [ 103.972381] omap3isp omap3isp: ###ISP TCTRL_FRAME=0x00000000 > [ 103.972381] omap3isp omap3isp: ###ISP TCTRL_PSTRB_DELAY=0x00000000 > [ 103.972412] omap3isp omap3isp: ###ISP TCTRL_STRB_DELAY=0x00000000 > [ 103.972442] omap3isp omap3isp: ###ISP TCTRL_SHUT_DELAY=0x00000000 > [ 103.972442] omap3isp omap3isp: ###ISP TCTRL_PSTRB_LENGTH=0x00000000 > [ 103.972473] omap3isp omap3isp: ###ISP TCTRL_STRB_LENGTH=0x00000000 > [ 103.972473] omap3isp omap3isp: ###ISP TCTRL_SHUT_LENGTH=0x00000000 > [ 103.972503] omap3isp omap3isp: ###SBL PCR=0x00000000 > [ 103.972503] omap3isp omap3isp: ###SBL SDR_REQ_EXP=0x00000000 > [ 103.972534] omap3isp omap3isp: -------------------------------------------- > [ 103.974700] device: 'media0': device_add > [ 103.975128] device: 'v4l-subdev0': device_add > [ 103.975524] device: 'video0': device_add > [ 103.975799] device: 'v4l-subdev1': device_add > [ 103.976104] device: 'video1': device_add > [ 103.976409] device: 'v4l-subdev2': device_add > [ 103.976684] device: 'video2': device_add > [ 103.976959] device: 'v4l-subdev3': device_add > [ 103.977294] device: 'video3': device_add > [ 103.977600] device: 'video4': device_add > [ 103.977905] device: 'v4l-subdev4': device_add > [ 103.978210] device: 'video5': device_add > [ 103.978485] device: 'video6': device_add > [ 103.978759] device: 'v4l-subdev5': device_add > [ 103.979156] device: 'v4l-subdev6': device_add > [ 103.979461] device: 'v4l-subdev7': device_add > [ 104.752685] device: '2-005d': device_add > [ 104.752777] bus: 'i2c': add device 2-005d > [ 104.753051] bus: 'i2c': driver_probe_device: matched device 2-005d > with driver mt9p031 > [ 104.753082] bus: 'i2c': really_probe: probing driver mt9p031 with > device 2-005d > [ 104.769897] mt9p031 2-005d: Detected a MT9P031 chip ID 1801 > [ 104.771881] mt9p031 2-005d: reset succesful > [ 104.771911] driver: '2-005d': driver_bound: bound to device 'mt9p031' > [ 104.771942] bus: 'i2c': really_probe: bound device 2-005d to driver mt9p031 > [ 104.772003] driver: 'omap3isp': driver_bound: bound to device 'omap3isp' > [ 104.772033] bus: 'platform': really_probe: bound device omap3isp to > driver omap3isp > > > APPENDIX B: mt9p031.c > > #include <linux/device.h> > #include <linux/i2c.h> > #include <linux/log2.h> > #include <linux/pm.h> > #include <linux/slab.h> > #include <linux/videodev2.h> > > //#include <media/soc_camera.h> > #include <media/v4l2-chip-ident.h> > #include <media/v4l2-subdev.h> > > /* > * mt9p031 i2c address 0x5d (0xBA read, 0xBB write) same as mt9t031 > * The platform has to define i2c_board_info and link to it from > * struct soc_camera_link > */ > > /* mt9p031 selected register addresses */ > #define MT9P031_CHIP_VERSION 0x00 > #define MT9P031_ROW_START 0x01 > #define MT9P031_COLUMN_START 0x02 > #define MT9P031_WINDOW_HEIGHT 0x03 > #define MT9P031_WINDOW_WIDTH 0x04 > #define MT9P031_HORIZONTAL_BLANKING 0x05 > #define MT9P031_VERTICAL_BLANKING 0x06 > #define MT9P031_OUTPUT_CONTROL 0x07 > #define MT9P031_SHUTTER_WIDTH_UPPER 0x08 > #define MT9P031_SHUTTER_WIDTH 0x09 > #define MT9P031_PIXEL_CLOCK_CONTROL 0x0a > #define MT9P031_FRAME_RESTART 0x0b > #define MT9P031_SHUTTER_DELAY 0x0c > #define MT9P031_RESET 0x0d > #define MT9P031_READ_MODE_1 0x1e > #define MT9P031_READ_MODE_2 0x20 > //#define MT9T031_READ_MODE_3 0x21 // NA readmode_2 is 2 bytes > #define MT9P031_ROW_ADDRESS_MODE 0x22 > #define MT9P031_COLUMN_ADDRESS_MODE 0x23 > #define MT9P031_GLOBAL_GAIN 0x35 > //#define MT9T031_CHIP_ENABLE 0xF8 // PDN is pin signal. no i2c register > > #define MT9P031_MAX_HEIGHT 1944 // adapted > #define MT9P031_MAX_WIDTH 2592 // adapted > #define MT9P031_MIN_HEIGHT 2 // could be 0 > #define MT9P031_MIN_WIDTH 18 // could be 0 > #define MT9P031_HORIZONTAL_BLANK 0 // adapted R0x05 > #define MT9P031_VERTICAL_BLANK 25 // adapted R0x06 > #define MT9P031_COLUMN_SKIP 16 // adapted > #define MT9P031_ROW_SKIP 54 // adapted > > #define MT9P031_CHIP_VERSION_VALUE 0x1801 > > /* > #define MT9T031_BUS_PARAM (SOCAM_PCLK_SAMPLE_RISING | \ > SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH | \ > SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | \ > SOCAM_MASTER | SOCAM_DATAWIDTH_10) > */ > struct mt9p031 { > struct v4l2_subdev subdev; > struct media_entity_pad pad; > > struct v4l2_rect rect; /* Sensor window */ > int model; /* V4L2_IDENT_MT9P031* codes from v4l2-chip-ident.h */ > u16 xskip; > u16 yskip; > unsigned int gain; > unsigned short y_skip_top; /* Lines to skip at the top */ > unsigned int exposure; > unsigned char autoexposure; > }; > > static struct mt9p031 *to_mt9p031(const struct i2c_client *client) > { > return container_of(i2c_get_clientdata(client), struct mt9p031, subdev); > } > > static int reg_read(struct i2c_client *client, const u8 reg) > { > s32 data = i2c_smbus_read_word_data(client, reg); > return data < 0 ? data : swab16(data); > } > > static int reg_write(struct i2c_client *client, const u8 reg, > const u16 data) > { > return i2c_smbus_write_word_data(client, reg, swab16(data)); > } > > static int reg_set(struct i2c_client *client, const u8 reg, > const u16 data) > { > int ret; > > ret = reg_read(client, reg); > if (ret < 0) > return ret; > return reg_write(client, reg, ret | data); > } > > static int reg_clear(struct i2c_client *client, const u8 reg, > const u16 data) > { > int ret; > > ret = reg_read(client, reg); > if (ret < 0) > return ret; > return reg_write(client, reg, ret & ~data); > } > > static int set_shutter(struct i2c_client *client, const u32 data) > { > int ret; > > ret = reg_write(client, MT9P031_SHUTTER_WIDTH_UPPER, data >> 16); > > if (ret >= 0) > ret = reg_write(client, MT9P031_SHUTTER_WIDTH, data & 0xffff); > > return ret; > } > > static int get_shutter(struct i2c_client *client, u32 *data) > { > int ret; > > ret = reg_read(client, MT9P031_SHUTTER_WIDTH_UPPER); > *data = ret << 16; > > if (ret >= 0) > ret = reg_read(client, MT9P031_SHUTTER_WIDTH); > *data |= ret & 0xffff; > > return ret < 0 ? ret : 0; > } > > static int mt9p031_idle(struct i2c_client *client) > { > int ret; > > /* Disable chip output, synchronous option update */ > ret = reg_write(client, MT9P031_RESET, 1); > if (ret >= 0) > ret = reg_write(client, MT9P031_RESET, 0); > if (ret >= 0) > ret = reg_clear(client, MT9P031_OUTPUT_CONTROL, 2); > > return ret >= 0 ? 0 : -EIO; > } > > ///////////////////////////////////////////////////////////////////////////////// > STUB > static int mt9t001_enum_mbus_code(struct v4l2_subdev *subdev, > struct v4l2_subdev_fh *fh, > struct v4l2_subdev_pad_mbus_code_enum *code) > { > printk(KERN_ALERT "pad_op 0\n"); > return 0; > } > > static int mt9t001_enum_frame_size(struct v4l2_subdev *subdev, > struct v4l2_subdev_fh *fh, > struct v4l2_subdev_frame_size_enum *fse) > { > printk(KERN_ALERT "pad_op 1\n"); > return 0; > } > > static int mt9t001_get_format(struct v4l2_subdev *subdev, > struct v4l2_subdev_fh *fh, unsigned int pad, > struct v4l2_mbus_framefmt *format, > enum v4l2_subdev_format which) > { > printk(KERN_ALERT "pad_op 4\n"); > return 0; > } > > static int mt9t001_set_format(struct v4l2_subdev *subdev, > struct v4l2_subdev_fh *fh, unsigned int pad, > struct v4l2_mbus_framefmt *format, > enum v4l2_subdev_format which) > { > printk(KERN_ALERT "pad_op 5\n"); > return 0; > } > static int mt9t001_get_crop(struct v4l2_subdev *subdev, > struct v4l2_subdev_fh *fh, > struct v4l2_subdev_pad_crop *crop) > { > printk(KERN_ALERT "pad_op 6\n"); > return 0; > } > > static int mt9t001_set_crop(struct v4l2_subdev *subdev, > struct v4l2_subdev_fh *fh, > struct v4l2_subdev_pad_crop *crop) > { > printk(KERN_ALERT "pad_op 7\n"); > return 0; > } > > > ///////////////////////////////////////////////////////////////////////////////// > END STUB > > > static int mt9p031_s_stream(struct v4l2_subdev *sd, int enable) > { > struct i2c_client *client = v4l2_get_subdevdata(sd); > int ret; > > if (enable) > /* Switch to master "normal" mode */ > ret = reg_set(client, MT9P031_OUTPUT_CONTROL, 2); > else > /* Stop sensor readout */ > ret = reg_clear(client, MT9P031_OUTPUT_CONTROL, 2); > > if (ret < 0) > return -EIO; > > return 0; > } > > enum { > MT9P031_CTRL_VFLIP, > MT9P031_CTRL_HFLIP, > MT9P031_CTRL_GAIN, > MT9P031_CTRL_EXPOSURE, > MT9P031_CTRL_EXPOSURE_AUTO, > }; > > static const struct v4l2_queryctrl mt9p031_controls[] = { > [MT9P031_CTRL_VFLIP] = { > .id = V4L2_CID_VFLIP, > .type = V4L2_CTRL_TYPE_BOOLEAN, > .name = "Flip Vertically", > .minimum = 0, > .maximum = 1, > .step = 1, > .default_value = 0, > }, > [MT9P031_CTRL_HFLIP] = { > .id = V4L2_CID_HFLIP, > .type = V4L2_CTRL_TYPE_BOOLEAN, > .name = "Flip Horizontally", > .minimum = 0, > .maximum = 1, > .step = 1, > .default_value = 0, > }, > [MT9P031_CTRL_GAIN] = { > .id = V4L2_CID_GAIN, > .type = V4L2_CTRL_TYPE_INTEGER, > .name = "Gain", > .minimum = 0, > .maximum = 127, > .step = 1, > .default_value = 64, > .flags = V4L2_CTRL_FLAG_SLIDER, > }, > [MT9P031_CTRL_EXPOSURE] = { > .id = V4L2_CID_EXPOSURE, > .type = V4L2_CTRL_TYPE_INTEGER, > .name = "Exposure", > .minimum = 1, > .maximum = 255, > .step = 1, > .default_value = 255, > .flags = V4L2_CTRL_FLAG_SLIDER, > }, > [MT9P031_CTRL_EXPOSURE_AUTO] = { > .id = V4L2_CID_EXPOSURE_AUTO, > .type = V4L2_CTRL_TYPE_BOOLEAN, > .name = "Automatic Exposure", > .minimum = 0, > .maximum = 1, > .step = 1, > .default_value = 1, > } > }; > > > > static int mt9p031_g_chip_ident(struct v4l2_subdev *sd, > struct v4l2_dbg_chip_ident *id) > { > struct i2c_client *client = v4l2_get_subdevdata(sd); > struct mt9p031 *mt9p031 = to_mt9p031(client); > > if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) > return -EINVAL; > > if (id->match.addr != client->addr) > return -ENODEV; > > id->ident = mt9p031->model; > id->revision = 0; > > return 0; > } > > static int mt9p031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) > { > struct i2c_client *client = v4l2_get_subdevdata(sd); > struct mt9p031 *mt9p031 = to_mt9p031(client); > int data; > > switch (ctrl->id) { > case V4L2_CID_VFLIP: > data = reg_read(client, MT9P031_READ_MODE_2); > if (data < 0) > return -EIO; > ctrl->value = !!(data & 0x8000); > break; > case V4L2_CID_HFLIP: > data = reg_read(client, MT9P031_READ_MODE_2); > if (data < 0) > return -EIO; > ctrl->value = !!(data & 0x4000); > break; > case V4L2_CID_EXPOSURE_AUTO: > ctrl->value = mt9p031->autoexposure; > break; > case V4L2_CID_GAIN: > ctrl->value = mt9p031->gain; > break; > case V4L2_CID_EXPOSURE: > ctrl->value = mt9p031->exposure; > break; > } > return 0; > } > > static int mt9p031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) > { > printk(KERN_ALERT "s_ctrl\n"); > return 0; > } > > > static struct dev_pm_ops mt9p031_dev_pm_ops = { > /* > .runtime_suspend = mt9t031_runtime_suspend, > .runtime_resume = mt9t031_runtime_resume, > */ > }; > > static struct device_type mt9p031_dev_type = { > .name = "MT9P031", > .pm = &mt9p031_dev_pm_ops, > }; > > /* > * Interface active, can use i2c. If it fails, it can indeed mean, that > * this wasn't our capture interface, so, we wait for the right one > */ > static int mt9p031_video_probe(struct i2c_client *client) > { > struct mt9p031 *mt9p031 = to_mt9p031(client); > s32 data; > int ret; > > /* Enable the chip */ > //data = reg_write(client, MT9P031_CHIP_ENABLE, 1); > //dev_dbg(&client->dev, "write: %d\n", data); > > /* Read out the chip version register */ > data = reg_read(client, MT9P031_CHIP_VERSION); > > switch (data) { > case MT9P031_CHIP_VERSION_VALUE: > mt9p031->model = V4L2_IDENT_MT9P031; > break; > default: > dev_err(&client->dev, > "No MT9P031 chip detected, register read %x\n", data); > return -ENODEV; > } > > dev_info(&client->dev, "Detected a MT9P031 chip ID %x\n", data); > > ret = mt9p031_idle(client); > if (ret < 0) > dev_err(&client->dev, "Failed to initialise the camera\n"); > else > dev_info(&client->dev, "reset succesful\n");//vdev->dev.type = > &mt9p031_dev_type; > > /* mt9t031_idle() has reset the chip to default. */ > mt9p031->exposure = 255; > mt9p031->gain = 64; > > return ret; > } > > static int mt9p031_open(struct v4l2_subdev *subdev, u32 i) > { > printk(KERN_ALERT "mt9p031 open\n"); > return 0; > } > static int mt9p031_query_ctrl(struct v4l2_subdev *subdev, > struct v4l2_queryctrl *qc) > { > return 0; > } > > > > static struct v4l2_subdev_core_ops mt9p031_subdev_core_ops = { > .g_ctrl = mt9p031_g_ctrl, > .s_ctrl = mt9p031_s_ctrl, > .g_chip_ident = mt9p031_g_chip_ident, > .init = mt9p031_open, > .queryctrl = mt9p031_query_ctrl, > > }; > > static struct v4l2_subdev_video_ops mt9p031_subdev_video_ops = { > .s_stream = mt9p031_s_stream, > }; > > > static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = { > .enum_mbus_code = mt9t001_enum_mbus_code, > .enum_frame_size = mt9t001_enum_frame_size, > .get_fmt = mt9t001_get_format, > .set_fmt = mt9t001_set_format, > .get_crop = mt9t001_get_crop, > .set_crop = mt9t001_set_crop, > }; > > > static struct v4l2_subdev_ops mt9p031_subdev_ops = { > .core = &mt9p031_subdev_core_ops, > .video = &mt9p031_subdev_video_ops, > .pad = &mt9p031_subdev_pad_ops, > }; > > static int mt9p031_probe(struct i2c_client *client, > const struct i2c_device_id *did) > { > struct mt9p031 *mt9p031; > struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); > int ret; > > > > if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { > dev_warn(&adapter->dev, > "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); > return -EIO; > } > > mt9p031 = kzalloc(sizeof(struct mt9p031), GFP_KERNEL); > if (!mt9p031) > return -ENOMEM; > > v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops); > > // struct isp_device *isp = v4l2_dev_to_isp_device(subdev->v4l2_dev); > // isp_set_xclk(isp, 16*1000*1000, ISP_XCLK_A); > > mt9p031->y_skip_top = 0; > mt9p031->rect.left = MT9P031_COLUMN_SKIP; > mt9p031->rect.top = MT9P031_ROW_SKIP; > mt9p031->rect.width = MT9P031_MAX_WIDTH; > mt9p031->rect.height = MT9P031_MAX_HEIGHT; > > /* > * Simulated autoexposure. If enabled, we calculate shutter width > * ourselves in the driver based on vertical blanking and frame width > */ > mt9p031->autoexposure = 1; > > mt9p031->xskip = 1; > mt9p031->yskip = 1; > > mt9p031_idle(client); > > ret = mt9p031_video_probe(client); > > //mt9p031_disable(client); > > if (ret) { > kfree(mt9p031); > return ret; > } > > mt9p031->pad.type = MEDIA_PAD_TYPE_OUTPUT; > ret = media_entity_init(&mt9p031->subdev.entity, 1, &mt9p031->pad, 0); > if (ret) { > kfree(mt9p031); > return ret; > } > > > > return ret; > } > > static int mt9p031_remove(struct i2c_client *client) > { > struct mt9p031 *mt9p031 = to_mt9p031(client); > > client->driver = NULL; > kfree(mt9p031); > > return 0; > } > > static const struct i2c_device_id mt9p031_id[] = { > { "mt9p031", 0 }, > { } > }; > MODULE_DEVICE_TABLE(i2c, mt9p031_id); > > static struct i2c_driver mt9p031_i2c_driver = { > .driver = { > .name = "mt9p031", > }, > .probe = mt9p031_probe, > .remove = mt9p031_remove, > .id_table = mt9p031_id, > }; > > static int __init mt9p031_mod_init(void) > { > return i2c_add_driver(&mt9p031_i2c_driver); > } > > static void __exit mt9p031_mod_exit(void) > { > i2c_del_driver(&mt9p031_i2c_driver); > } > > module_init(mt9p031_mod_init); > module_exit(mt9p031_mod_exit); > > MODULE_DESCRIPTION("Micron MT9T031 Camera driver"); > MODULE_AUTHOR("Guennadi Liakhovetski <lg@xxxxxxx>"); > MODULE_LICENSE("GPL v2"); > -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html