Re: [PATCH 5/5] soc-camera: Convert to a platform driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Guennadi,


Reviewing your patch, I've got curious about a thing.
I think your soc camera subsystem is covering multiple camera
devices(sensors) in one target board, but if that is true I'm afraid
I'm confused how to handle them properly.
Because according to your patch, video_dev_create() takes camera
device as parameter and it seems to be creating device node for each
camera devices.
It means, if I have one camera host and several camera devices, there
should be several device nodes for camera devices but cannot be used
at the same time. Because typical camera host(camera interface) can
handle only one camera device at a time. But multiple device nodes
mean "we can open and handle them at the same time".

How about registering camera host device as v4l2 device and make
camera device a input device which could be handled using
VIDIOC_S_INPUT/G_INPUT api?

Actually, I'm working on S3C64xx camera interface driver with soc
camera subsystem, and I'm facing that issue right now because I've got
dual camera on my target board.

I hope you to consider this concept, and also want to know your opinion.
Cheers,

Nate

On Wed, Apr 15, 2009 at 9:20 PM, Guennadi Liakhovetski
<g.liakhovetski@xxxxxx> wrote:
> Convert soc-camera core to a platform driver. With this approach I2C
> devices are no longer statically registered in platform code, instead they
> are registered dynamically by the soc-camera core, when a match with a
> host driver is found. With this patch all platforms and all soc-camera
> device drivers are converted too. This is a preparatory step for the
> v4l-subdev conversion.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@xxxxxx>
> ---
>
> Ok, here goes the bad guy. Hit it hard, hit it as hard as you can.
>
> Robert, I addressed your wishes from your previous comments, but kept the
> semicolon rearrangement hunk. I think, it is better not to terminate a
> define with a semicolon, if you like, we can make this a separate patch.
>
>  arch/arm/mach-mx3/pcm037.c                 |   25 ++-
>  arch/arm/mach-pxa/em-x270.c                |   21 ++-
>  arch/arm/mach-pxa/mioa701.c                |   35 ++--
>  arch/arm/mach-pxa/pcm990-baseboard.c       |   52 ++++-
>  arch/sh/boards/board-ap325rxa.c            |   55 +++--
>  arch/sh/boards/mach-migor/setup.c          |   77 ++++--
>  drivers/media/video/mt9m001.c              |  113 ++++-----
>  drivers/media/video/mt9m111.c              |  152 ++++++------
>  drivers/media/video/mt9t031.c              |  113 ++++-----
>  drivers/media/video/mt9v022.c              |  118 +++++-----
>  drivers/media/video/mx3_camera.c           |   27 ++-
>  drivers/media/video/ov772x.c               |  148 +++++++-----
>  drivers/media/video/pxa_camera.c           |   27 ++-
>  drivers/media/video/sh_mobile_ceu_camera.c |   13 +-
>  drivers/media/video/soc_camera.c           |  364 +++++++++++++++-------------
>  drivers/media/video/soc_camera_platform.c  |  112 +++++----
>  drivers/media/video/tw9910.c               |  106 +++++----
>  include/media/soc_camera.h                 |   30 ++-
>  include/media/soc_camera_platform.h        |    5 +-
>  19 files changed, 894 insertions(+), 699 deletions(-)
>
> diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
> index 6bfd29a..00ce1eb 100644
> --- a/arch/arm/mach-mx3/pcm037.c
> +++ b/arch/arm/mach-mx3/pcm037.c
> @@ -241,9 +241,17 @@ static int pcm037_camera_power(struct device *dev, int on)
>        return 0;
>  }
>
> +static struct i2c_board_info pcm037_i2c_2_devices[] = {
> +       {
> +               I2C_BOARD_INFO("mt9t031", 0x5d),
> +       },
> +};
> +
>  static struct soc_camera_link iclink = {
> -       .bus_id = 0,                    /* Must match with the camera ID */
> -       .power = pcm037_camera_power,
> +       .bus_id         = 0,            /* Must match with the camera ID */
> +       .power          = pcm037_camera_power,
> +       .board_info     = &pcm037_i2c_2_devices[0],
> +       .i2c_adapter_id = 2,
>  };
>
>  static struct i2c_board_info pcm037_i2c_devices[] = {
> @@ -256,9 +264,10 @@ static struct i2c_board_info pcm037_i2c_devices[] = {
>        }
>  };
>
> -static struct i2c_board_info pcm037_i2c_2_devices[] = {
> -       {
> -               I2C_BOARD_INFO("mt9t031", 0x5d),
> +static struct platform_device pcm037_camera = {
> +       .name   = "soc-camera-pdrv",
> +       .id     = 0,
> +       .dev    = {
>                .platform_data = &iclink,
>        },
>  };
> @@ -338,6 +347,9 @@ static struct platform_device *devices[] __initdata = {
>        &pcm037_flash,
>        &pcm037_eth,
>        &pcm037_sram_device,
> +#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
> +       &pcm037_camera,
> +#endif
>  };
>
>  static struct ipu_platform_data mx3_ipu_data = {
> @@ -395,9 +407,6 @@ static void __init mxc_board_init(void)
>        i2c_register_board_info(1, pcm037_i2c_devices,
>                        ARRAY_SIZE(pcm037_i2c_devices));
>
> -       i2c_register_board_info(2, pcm037_i2c_2_devices,
> -                       ARRAY_SIZE(pcm037_i2c_2_devices));
> -
>        mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
>        mxc_register_device(&mxc_i2c_device2, &pcm037_i2c_2_data);
>  #endif
> diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
> index 920dfb8..d4eb0c7 100644
> --- a/arch/arm/mach-pxa/em-x270.c
> +++ b/arch/arm/mach-pxa/em-x270.c
> @@ -847,14 +847,23 @@ static int em_x270_sensor_power(struct device *dev, int on)
>        return 0;
>  }
>
> -static struct soc_camera_link iclink = {
> -       .bus_id = 0,
> -       .power = em_x270_sensor_power,
> -};
> -
>  static struct i2c_board_info em_x270_i2c_cam_info[] = {
>        {
>                I2C_BOARD_INFO("mt9m111", 0x48),
> +       },
> +};
> +
> +static struct soc_camera_link iclink = {
> +       .bus_id         = 0,
> +       .power          = em_x270_sensor_power,
> +       .board_info     = &em_x270_i2c_cam_info[0],
> +       .i2c_adapter_id = 0,
> +};
> +
> +static struct platform_device em_x270_camera = {
> +       .name   = "soc-camera-pdrv",
> +       .id     = -1,
> +       .dev    = {
>                .platform_data = &iclink,
>        },
>  };
> @@ -866,8 +875,8 @@ static struct i2c_pxa_platform_data em_x270_i2c_info = {
>  static void  __init em_x270_init_camera(void)
>  {
>        pxa_set_i2c_info(&em_x270_i2c_info);
> -       i2c_register_board_info(0, ARRAY_AND_SIZE(em_x270_i2c_cam_info));
>        pxa_set_camera_info(&em_x270_camera_platform_data);
> +       platform_device_register(&em_x270_camera);
>  }
>  #else
>  static inline void em_x270_init_camera(void) {}
> diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
> index 97c93a7..444818b 100644
> --- a/arch/arm/mach-pxa/mioa701.c
> +++ b/arch/arm/mach-pxa/mioa701.c
> @@ -724,19 +724,21 @@ struct pxacamera_platform_data mioa701_pxacamera_platform_data = {
>        .mclk_10khz = 5000,
>  };
>
> -static struct soc_camera_link iclink = {
> -       .bus_id = 0, /* Must match id in pxa27x_device_camera in device.c */
> -};
> -
> -/* Board I2C devices. */
> +/*
> + * Board I2C devices
> + */
>  static struct i2c_board_info __initdata mioa701_i2c_devices[] = {
>        {
> -               /* Must initialize before the camera(s) */
>                I2C_BOARD_INFO("mt9m111", 0x5d),
> -               .platform_data = &iclink,
>        },
>  };
>
> +static struct soc_camera_link iclink = {
> +       .bus_id         = 0, /* Match id in pxa27x_device_camera in device.c */
> +       .board_info     = &mioa701_i2c_devices[0],
> +       .i2c_adapter_id = 0,
> +};
> +
>  struct i2c_pxa_platform_data i2c_pdata = {
>        .fast_mode = 1,
>  };
> @@ -754,20 +756,21 @@ static struct platform_device var = {                     \
>                .platform_data = pdata,                 \
>                .parent = tparent,                      \
>        },                                              \
> -};
> +}
>  #define MIO_SIMPLE_DEV(var, strname, pdata)    \
>        MIO_PARENT_DEV(var, strname, NULL, pdata)
>
> -MIO_SIMPLE_DEV(mioa701_gpio_keys, "gpio-keys",     &mioa701_gpio_keys_data)
> +MIO_SIMPLE_DEV(mioa701_gpio_keys, "gpio-keys",     &mioa701_gpio_keys_data);
>  MIO_PARENT_DEV(mioa701_backlight, "pwm-backlight",  &pxa27x_device_pwm0.dev,
>                &mioa701_backlight_data);
> -MIO_SIMPLE_DEV(mioa701_led,      "leds-gpio",      &gpio_led_info)
> -MIO_SIMPLE_DEV(pxa2xx_pcm,       "pxa2xx-pcm",     NULL)
> -MIO_SIMPLE_DEV(pxa2xx_ac97,      "pxa2xx-ac97",    NULL)
> -MIO_PARENT_DEV(mio_wm9713_codec,  "wm9713-codec",   &pxa2xx_ac97.dev, NULL)
> -MIO_SIMPLE_DEV(mioa701_sound,    "mioa701-wm9713", NULL)
> -MIO_SIMPLE_DEV(mioa701_board,    "mioa701-board",  NULL)
> +MIO_SIMPLE_DEV(mioa701_led,      "leds-gpio",      &gpio_led_info);
> +MIO_SIMPLE_DEV(pxa2xx_pcm,       "pxa2xx-pcm",     NULL);
> +MIO_SIMPLE_DEV(pxa2xx_ac97,      "pxa2xx-ac97",    NULL);
> +MIO_PARENT_DEV(mio_wm9713_codec,  "wm9713-codec",   &pxa2xx_ac97.dev, NULL);
> +MIO_SIMPLE_DEV(mioa701_sound,    "mioa701-wm9713", NULL);
> +MIO_SIMPLE_DEV(mioa701_board,    "mioa701-board",  NULL);
>  MIO_SIMPLE_DEV(gpio_vbus,        "gpio-vbus",      &gpio_vbus_data);
> +MIO_SIMPLE_DEV(mioa701_camera,   "soc-camera-pdrv",&iclink[0]);
>
>  static struct platform_device *devices[] __initdata = {
>        &mioa701_gpio_keys,
> @@ -780,6 +783,7 @@ static struct platform_device *devices[] __initdata = {
>        &power_dev,
>        &strataflash,
>        &gpio_vbus,
> +       &mioa701_camera,
>        &mioa701_board,
>  };
>
> @@ -825,7 +829,6 @@ static void __init mioa701_machine_init(void)
>
>        pxa_set_i2c_info(&i2c_pdata);
>        pxa_set_camera_info(&mioa701_pxacamera_platform_data);
> -       i2c_register_board_info(0, ARRAY_AND_SIZE(mioa701_i2c_devices));
>  }
>
>  static void mioa701_machine_exit(void)
> diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
> index 9ce1ef2..619b90e 100644
> --- a/arch/arm/mach-pxa/pcm990-baseboard.c
> +++ b/arch/arm/mach-pxa/pcm990-baseboard.c
> @@ -427,25 +427,54 @@ static void pcm990_camera_free_bus(struct soc_camera_link *link)
>        gpio_bus_switch = -EINVAL;
>  }
>
> -static struct soc_camera_link iclink = {
> -       .bus_id = 0, /* Must match with the camera ID above */
> -       .query_bus_param = pcm990_camera_query_bus_param,
> -       .set_bus_param = pcm990_camera_set_bus_param,
> -       .free_bus = pcm990_camera_free_bus,
> -};
> -
>  /* Board I2C devices. */
>  static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
>        {
>                /* Must initialize before the camera(s) */
>                I2C_BOARD_INFO("pca9536", 0x41),
>                .platform_data = &pca9536_data,
> -       }, {
> +       },
> +};
> +
> +static struct i2c_board_info __initdata pcm990_camera_i2c[] = {
> +       {
>                I2C_BOARD_INFO("mt9v022", 0x48),
> -               .platform_data = &iclink, /* With extender */
>        }, {
>                I2C_BOARD_INFO("mt9m001", 0x5d),
> -               .platform_data = &iclink, /* With extender */
> +       },
> +};
> +
> +static struct soc_camera_link iclink[] = {
> +       {
> +               .bus_id                 = 0, /* Must match with the camera ID */
> +               .board_info             = &pcm990_camera_i2c[0],
> +               .i2c_adapter_id         = 0,
> +               .query_bus_param        = pcm990_camera_query_bus_param,
> +               .set_bus_param          = pcm990_camera_set_bus_param,
> +               .free_bus               = pcm990_camera_free_bus,
> +       }, {
> +               .bus_id                 = 0, /* Must match with the camera ID */
> +               .board_info             = &pcm990_camera_i2c[1],
> +               .i2c_adapter_id         = 0,
> +               .query_bus_param        = pcm990_camera_query_bus_param,
> +               .set_bus_param          = pcm990_camera_set_bus_param,
> +               .free_bus               = pcm990_camera_free_bus,
> +       },
> +};
> +
> +static struct platform_device pcm990_camera[] = {
> +       {
> +               .name   = "soc-camera-pdrv",
> +               .id     = 0,
> +               .dev    = {
> +                       .platform_data = &iclink[0],
> +               },
> +       }, {
> +               .name   = "soc-camera-pdrv",
> +               .id     = 1,
> +               .dev    = {
> +                       .platform_data = &iclink[1],
> +               },
>        },
>  };
>  #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
> @@ -501,6 +530,9 @@ void __init pcm990_baseboard_init(void)
>        pxa_set_camera_info(&pcm990_pxacamera_platform_data);
>
>        i2c_register_board_info(0, ARRAY_AND_SIZE(pcm990_i2c_devices));
> +
> +       platform_device_register(&pcm990_camera[0]);
> +       platform_device_register(&pcm990_camera[1]);
>  #endif
>
>        printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n");
> diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c
> index e27655b..37c9139 100644
> --- a/arch/sh/boards/board-ap325rxa.c
> +++ b/arch/sh/boards/board-ap325rxa.c
> @@ -228,12 +228,6 @@ static struct platform_device lcdc_device = {
>        },
>  };
>
> -static void camera_power(int val)
> -{
> -       gpio_set_value(GPIO_PTZ5, val); /* RST_CAM/RSTB */
> -       mdelay(10);
> -}
> -
>  #ifdef CONFIG_I2C
>  static unsigned char camera_ncm03j_magic[] =
>  {
> @@ -255,23 +249,28 @@ static unsigned char camera_ncm03j_magic[] =
>        0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
>  };
>
> -static int camera_set_capture(struct soc_camera_platform_info *info,
> -                             int enable)
> +static int ap325rxa_camera_power(struct device *dev, int on)
>  {
> -       struct i2c_adapter *a = i2c_get_adapter(0);
> +       gpio_set_value(GPIO_PTZ5, on); /* RST_CAM/RSTB */
> +       mdelay(10);
> +       return 0;
> +}
> +
> +static int ap325rxa_camera_set_capture(struct soc_camera_platform_info *info,
> +                                      int enable)
> +{
> +       struct i2c_adapter *a = i2c_get_adapter(info->link.i2c_adapter_id);
>        struct i2c_msg msg;
>        int ret = 0;
>        int i;
>
> -       camera_power(0);
>        if (!enable)
> -               return 0; /* no disable for now */
> +               return ap325rxa_camera_power(NULL, 0); /* no disable for now */
>
> -       camera_power(1);
>        for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) {
>                u_int8_t buf[8];
>
> -               msg.addr = 0x6e;
> +               msg.addr = info->link.board_info->addr;
>                msg.buf = buf;
>                msg.len = 2;
>                msg.flags = 0;
> @@ -285,8 +284,11 @@ static int camera_set_capture(struct soc_camera_platform_info *info,
>        return ret;
>  }
>
> +static struct i2c_board_info __initdata ap325rxa_camera_i2c = {
> +       I2C_BOARD_INFO("soc_camera_platform", 0x6e),
> +};
> +
>  static struct soc_camera_platform_info camera_info = {
> -       .iface = 0,
>        .format_name = "UYVY",
>        .format_depth = 16,
>        .format = {
> @@ -296,22 +298,29 @@ static struct soc_camera_platform_info camera_info = {
>                .height = 480,
>        },
>        .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
> -       SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
> -       .set_capture = camera_set_capture,
> +               SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
> +       .set_capture = ap325rxa_camera_set_capture,
> +       .link = {
> +               .bus_id = 0,
> +               .board_info = &ap325rxa_camera_i2c,
> +               .i2c_adapter_id = 0,
> +               .power = ap325rxa_camera_power,
> +       },
>  };
>
> -static struct platform_device camera_device = {
> -       .name           = "soc_camera_platform",
> -       .dev            = {
> -               .platform_data  = &camera_info,
> +static struct platform_device ap325rxa_camera = {
> +       .name   = "soc-camera-pdrv",
> +       .id     = -1,
> +       .dev    = {
> +               .platform_data = &camera_info.link,
>        },
>  };
>  #endif /* CONFIG_I2C */
>
>  static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
>        .flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
> -       SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER |
> -       SOCAM_DATAWIDTH_8,
> +               SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH |
> +               SOCAM_MASTER | SOCAM_DATAWIDTH_8,
>  };
>
>  static struct resource ceu_resources[] = {
> @@ -360,7 +369,7 @@ static struct platform_device *ap325rxa_devices[] __initdata = {
>        &lcdc_device,
>        &ceu_device,
>  #ifdef CONFIG_I2C
> -       &camera_device,
> +       &ap325rxa_camera,
>  #endif
>        &nand_flash_device,
>        &sdcard_cn3_device,
> diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
> index 4fd6a72..b8cb246 100644
> --- a/arch/sh/boards/mach-migor/setup.c
> +++ b/arch/sh/boards/mach-migor/setup.c
> @@ -383,21 +383,6 @@ static struct platform_device migor_ceu_device = {
>        },
>  };
>
> -static struct ov772x_camera_info ov7725_info = {
> -       .buswidth  = SOCAM_DATAWIDTH_8,
> -       .link = {
> -               .power  = ov7725_power,
> -       },
> -};
> -
> -static struct tw9910_video_info tw9910_info = {
> -       .buswidth = SOCAM_DATAWIDTH_8,
> -       .mpout    = TW9910_MPO_FIELD,
> -       .link = {
> -               .power  = tw9910_power,
> -       }
> -};
> -
>  struct spi_gpio_platform_data sdcard_cn9_platform_data = {
>        .sck = GPIO_PTD0,
>        .mosi = GPIO_PTD1,
> @@ -412,16 +397,6 @@ static struct platform_device sdcard_cn9_device = {
>        },
>  };
>
> -static struct platform_device *migor_devices[] __initdata = {
> -       &smc91x_eth_device,
> -       &sh_keysc_device,
> -       &migor_lcdc_device,
> -       &migor_ceu_device,
> -       &migor_nor_flash_device,
> -       &migor_nand_flash_device,
> -       &sdcard_cn9_device,
> -};
> -
>  static struct i2c_board_info migor_i2c_devices[] = {
>        {
>                I2C_BOARD_INFO("rs5c372b", 0x32),
> @@ -430,16 +405,64 @@ static struct i2c_board_info migor_i2c_devices[] = {
>                I2C_BOARD_INFO("migor_ts", 0x51),
>                .irq = 38, /* IRQ6 */
>        },
> +};
> +
> +static struct i2c_board_info migor_camera_i2c[] = {
>        {
>                I2C_BOARD_INFO("ov772x", 0x21),
> -               .platform_data = &ov7725_info,
>        },
>        {
>                I2C_BOARD_INFO("tw9910", 0x45),
> -               .platform_data = &tw9910_info,
>        },
>  };
>
> +static struct ov772x_camera_info ov7725_info = {
> +       .buswidth  = SOCAM_DATAWIDTH_8,
> +       .link = {
> +               .power  = ov7725_power,
> +               .board_info             = &migor_camera_i2c[0],
> +               .i2c_adapter_id         = 0,
> +       },
> +};
> +
> +static struct tw9910_video_info tw9910_info = {
> +       .buswidth = SOCAM_DATAWIDTH_8,
> +       .mpout    = TW9910_MPO_FIELD,
> +       .link = {
> +               .power  = tw9910_power,
> +               .board_info             = &migor_camera_i2c[1],
> +               .i2c_adapter_id         = 0,
> +       }
> +};
> +
> +static struct platform_device migor_camera[] = {
> +       {
> +               .name   = "soc-camera-pdrv",
> +               .id     = 0,
> +               .dev    = {
> +                       .platform_data = &ov7725_info.link,
> +               },
> +       }, {
> +               .name   = "soc-camera-pdrv",
> +               .id     = 1,
> +               .dev    = {
> +                       .platform_data = &tw9910_info.link,
> +               },
> +       },
> +};
> +
> +static struct platform_device *migor_devices[] __initdata = {
> +       &smc91x_eth_device,
> +       &sh_keysc_device,
> +       &migor_lcdc_device,
> +       &migor_ceu_device,
> +       &migor_nor_flash_device,
> +       &migor_nand_flash_device,
> +       &sdcard_cn9_device,
> +       &migor_camera[0],
> +       &migor_camera[1],
> +};
> +
>  static struct spi_board_info migor_spi_devices[] = {
>        {
>                .modalias = "mmc_spi",
> diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
> index 459c04c..b0f4ad5 100644
> --- a/drivers/media/video/mt9m001.c
> +++ b/drivers/media/video/mt9m001.c
> @@ -69,8 +69,6 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
>  };
>
>  struct mt9m001 {
> -       struct i2c_client *client;
> -       struct soc_camera_device icd;
>        int model;      /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
>        unsigned char autoexposure;
>  };
> @@ -111,11 +109,11 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
>
>  static int mt9m001_init(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>        int ret;
>
> -       dev_dbg(icd->vdev->parent, "%s\n", __func__);
> +       dev_dbg(&icd->dev, "%s\n", __func__);
>
>        if (icl->power) {
>                ret = icl->power(&client->dev, 1);
> @@ -147,8 +145,8 @@ static int mt9m001_init(struct soc_camera_device *icd)
>
>  static int mt9m001_release(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>
>        /* Disable the chip */
>        reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
> @@ -161,7 +159,7 @@ static int mt9m001_release(struct soc_camera_device *icd)
>
>  static int mt9m001_start_capture(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        /* Switch to master "normal" mode */
>        if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0)
> @@ -171,7 +169,7 @@ static int mt9m001_start_capture(struct soc_camera_device *icd)
>
>  static int mt9m001_stop_capture(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        /* Stop sensor readout */
>        if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0)
> @@ -182,8 +180,7 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd)
>  static int mt9m001_set_bus_param(struct soc_camera_device *icd,
>                                 unsigned long flags)
>  {
> -       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> -       struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>        unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
>
>        /* Only one width bit may be set */
> @@ -205,8 +202,7 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd,
>
>  static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
>  {
> -       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> -       struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>        /* MT9M001 has all capture_format parameters fixed */
>        unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING |
>                SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
> @@ -223,8 +219,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
>  static int mt9m001_set_crop(struct soc_camera_device *icd,
>                            struct v4l2_rect *rect)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
>        int ret;
>        const u16 hblank = 9, vblank = 25;
>
> @@ -296,12 +292,13 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd,
>  static int mt9m001_get_chip_id(struct soc_camera_device *icd,
>                               struct v4l2_dbg_chip_ident *id)
>  {
> -       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
>
>        if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
>                return -EINVAL;
>
> -       if (id->match.addr != mt9m001->client->addr)
> +       if (id->match.addr != client->addr)
>                return -ENODEV;
>
>        id->ident       = mt9m001->model;
> @@ -314,7 +311,7 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd,
>  static int mt9m001_get_register(struct soc_camera_device *icd,
>                                struct v4l2_dbg_register *reg)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
>                return -EINVAL;
> @@ -334,7 +331,7 @@ static int mt9m001_get_register(struct soc_camera_device *icd,
>  static int mt9m001_set_register(struct soc_camera_device *icd,
>                                struct v4l2_dbg_register *reg)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
>                return -EINVAL;
> @@ -387,15 +384,11 @@ static const struct v4l2_queryctrl mt9m001_controls[] = {
>        }
>  };
>
> -static int mt9m001_video_probe(struct soc_camera_device *);
> -static void mt9m001_video_remove(struct soc_camera_device *);
>  static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *);
>  static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *);
>
>  static struct soc_camera_ops mt9m001_ops = {
>        .owner                  = THIS_MODULE,
> -       .probe                  = mt9m001_video_probe,
> -       .remove                 = mt9m001_video_remove,
>        .init                   = mt9m001_init,
>        .release                = mt9m001_release,
>        .start_capture          = mt9m001_start_capture,
> @@ -418,8 +411,8 @@ static struct soc_camera_ops mt9m001_ops = {
>
>  static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
>        int data;
>
>        switch (ctrl->id) {
> @@ -438,8 +431,8 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro
>
>  static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
>        const struct v4l2_queryctrl *qctrl;
>        int data;
>
> @@ -531,11 +524,11 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
>
>  /* 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 mt9m001_video_probe(struct soc_camera_device *icd)
> +static int mt9m001_video_probe(struct soc_camera_device *icd,
> +                              struct i2c_client *client)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>        s32 data;
>        int ret;
>        unsigned long flags;
> @@ -546,6 +539,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
>            to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
>                return -ENODEV;
>
> +       /* Switch master clock on */
> +       ret = soc_camera_video_start(icd, &client->dev);
> +       if (ret)
> +               return ret;
> +
>        /* Enable the chip */
>        data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
>        dev_dbg(&icd->dev, "write: %d\n", data);
> @@ -553,6 +551,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
>        /* Read out the chip version register */
>        data = reg_read(client, MT9M001_CHIP_VERSION);
>
> +       soc_camera_video_stop(icd);
> +
>        /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
>        switch (data) {
>        case 0x8411:
> @@ -565,10 +565,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
>                icd->formats = mt9m001_monochrome_formats;
>                break;
>        default:
> -               ret = -ENODEV;
>                dev_err(&icd->dev,
>                        "No MT9M001 chip detected, register read %x\n", data);
> -               goto ei2c;
> +               return -ENODEV;
>        }
>
>        icd->num_formats = 0;
> @@ -594,26 +593,17 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
>        dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
>                 data == 0x8431 ? "C12STM" : "C12ST");
>
> -       /* Now that we know the model, we can start video */
> -       ret = soc_camera_video_start(icd);
> -       if (ret)
> -               goto eisis;
> -
>        return 0;
> -
> -eisis:
> -ei2c:
> -       return ret;
>  }
>
>  static void mt9m001_video_remove(struct soc_camera_device *icd)
>  {
> -       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> -       struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> -       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
> +       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
>                icd->dev.parent, icd->vdev);
> -       soc_camera_video_stop(icd);
> +       icd->ops = NULL;
>        if (icl->free_bus)
>                icl->free_bus(icl);
>  }
> @@ -622,11 +612,17 @@ static int mt9m001_probe(struct i2c_client *client,
>                         const struct i2c_device_id *did)
>  {
>        struct mt9m001 *mt9m001;
> -       struct soc_camera_device *icd;
> +       struct soc_camera_device *icd = client->dev.platform_data;
>        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct soc_camera_link *icl;
>        int ret;
>
> +       if (!icd) {
> +               dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
> +               return -EINVAL;
> +       }
> +
> +       icl = to_soc_camera_link(icd);
>        if (!icl) {
>                dev_err(&client->dev, "MT9M001 driver needs platform data\n");
>                return -EINVAL;
> @@ -642,13 +638,10 @@ static int mt9m001_probe(struct i2c_client *client,
>        if (!mt9m001)
>                return -ENOMEM;
>
> -       mt9m001->client = client;
>        i2c_set_clientdata(client, mt9m001);
>
>        /* Second stage probe - when a capture adapter is there */
> -       icd = &mt9m001->icd;
>        icd->ops        = &mt9m001_ops;
> -       icd->control    = &client->dev;
>        icd->x_min      = 20;
>        icd->y_min      = 12;
>        icd->x_current  = 20;
> @@ -658,27 +651,27 @@ static int mt9m001_probe(struct i2c_client *client,
>        icd->height_min = 32;
>        icd->height_max = 1024;
>        icd->y_skip_top = 1;
> -       icd->iface      = icl->bus_id;
>        /* Simulated autoexposure. If enabled, we calculate shutter width
>         * ourselves in the driver based on vertical blanking and frame width */
>        mt9m001->autoexposure = 1;
>
> -       ret = soc_camera_device_register(icd);
> -       if (ret)
> -               goto eisdr;
> -
> -       return 0;
> +       ret = mt9m001_video_probe(icd, client);
> +       if (ret) {
> +               i2c_set_clientdata(client, NULL);
> +               kfree(mt9m001);
> +       }
>
> -eisdr:
> -       kfree(mt9m001);
>        return ret;
>  }
>
>  static int mt9m001_remove(struct i2c_client *client)
>  {
>        struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> +       struct soc_camera_device *icd = client->dev.platform_data;
>
> -       soc_camera_device_unregister(&mt9m001->icd);
> +       mt9m001_video_remove(icd);
> +       i2c_set_clientdata(client, NULL);
> +       client->driver = NULL;
>        kfree(mt9m001);
>
>        return 0;
> diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
> index fc5e2de..330753a 100644
> --- a/drivers/media/video/mt9m111.c
> +++ b/drivers/media/video/mt9m111.c
> @@ -148,8 +148,6 @@ enum mt9m111_context {
>  };
>
>  struct mt9m111 {
> -       struct i2c_client *client;
> -       struct soc_camera_device icd;
>        int model;      /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */
>        enum mt9m111_context context;
>        struct v4l2_rect rect;
> @@ -203,7 +201,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
>
>        ret = reg_page_map_set(client, reg);
>        if (!ret)
> -               ret = i2c_smbus_write_word_data(client, (reg & 0xff),
> +               ret = i2c_smbus_write_word_data(client, reg & 0xff,
>                                                swab16(data));
>        dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
>        return ret;
> @@ -232,7 +230,7 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
>  static int mt9m111_set_context(struct soc_camera_device *icd,
>                               enum mt9m111_context ctxt)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>        int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
>                | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
>                | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
> @@ -249,8 +247,8 @@ static int mt9m111_set_context(struct soc_camera_device *icd,
>  static int mt9m111_setup_rect(struct soc_camera_device *icd,
>                              struct v4l2_rect *rect)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int ret, is_raw_format;
>        int width = rect->width;
>        int height = rect->height;
> @@ -294,7 +292,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd,
>
>  static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>        int ret;
>
>        ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt);
> @@ -315,7 +313,8 @@ static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd)
>
>  static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int val = 0;
>
>        if (mt9m111->swap_rgb_red_blue)
> @@ -329,7 +328,8 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
>
>  static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int val = 0;
>
>        if (mt9m111->swap_rgb_red_blue)
> @@ -343,7 +343,8 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
>
>  static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int val = 0;
>
>        if (mt9m111->swap_yuv_cb_cr)
> @@ -356,9 +357,9 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
>
>  static int mt9m111_enable(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int ret;
>
>        if (icl->power) {
> @@ -378,9 +379,9 @@ static int mt9m111_enable(struct soc_camera_device *icd)
>
>  static int mt9m111_disable(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int ret;
>
>        ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
> @@ -395,8 +396,8 @@ static int mt9m111_disable(struct soc_camera_device *icd)
>
>  static int mt9m111_reset(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>        int ret;
>
>        ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
> @@ -424,8 +425,7 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd)
>
>  static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> -       struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>        unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
>                SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
>                SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
> @@ -441,7 +441,8 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
>  static int mt9m111_set_crop(struct soc_camera_device *icd,
>                            struct v4l2_rect *rect)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int ret;
>
>        dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
> @@ -456,7 +457,8 @@ static int mt9m111_set_crop(struct soc_camera_device *icd,
>
>  static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int ret;
>
>        switch (pixfmt) {
> @@ -506,7 +508,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
>  static int mt9m111_set_fmt(struct soc_camera_device *icd,
>                           struct v4l2_format *f)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        struct v4l2_pix_format *pix = &f->fmt.pix;
>        struct v4l2_rect rect = {
>                .left   = mt9m111->rect.left,
> @@ -544,12 +547,13 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd,
>  static int mt9m111_get_chip_id(struct soc_camera_device *icd,
>                               struct v4l2_dbg_chip_ident *id)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>
>        if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
>                return -EINVAL;
>
> -       if (id->match.addr != mt9m111->client->addr)
> +       if (id->match.addr != client->addr)
>                return -ENODEV;
>
>        id->ident       = mt9m111->model;
> @@ -562,8 +566,8 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd,
>  static int mt9m111_get_register(struct soc_camera_device *icd,
>                                struct v4l2_dbg_register *reg)
>  {
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>        int val;
> -       struct i2c_client *client = to_i2c_client(icd->control);
>
>        if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
>                return -EINVAL;
> @@ -583,7 +587,7 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
>  static int mt9m111_set_register(struct soc_camera_device *icd,
>                                struct v4l2_dbg_register *reg)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
>                return -EINVAL;
> @@ -635,8 +639,6 @@ static const struct v4l2_queryctrl mt9m111_controls[] = {
>        }
>  };
>
> -static int mt9m111_video_probe(struct soc_camera_device *);
> -static void mt9m111_video_remove(struct soc_camera_device *);
>  static int mt9m111_get_control(struct soc_camera_device *,
>                               struct v4l2_control *);
>  static int mt9m111_set_control(struct soc_camera_device *,
> @@ -647,8 +649,6 @@ static int mt9m111_release(struct soc_camera_device *icd);
>
>  static struct soc_camera_ops mt9m111_ops = {
>        .owner                  = THIS_MODULE,
> -       .probe                  = mt9m111_video_probe,
> -       .remove                 = mt9m111_video_remove,
>        .init                   = mt9m111_init,
>        .resume                 = mt9m111_resume,
>        .release                = mt9m111_release,
> @@ -672,8 +672,8 @@ static struct soc_camera_ops mt9m111_ops = {
>
>  static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int ret;
>
>        if (mt9m111->context == HIGHPOWER) {
> @@ -693,7 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
>
>  static int mt9m111_get_global_gain(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>        int data;
>
>        data = reg_read(GLOBAL_GAIN);
> @@ -705,7 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd)
>
>  static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>        u16 val;
>
>        if (gain > 63 * 2 * 2)
> @@ -724,8 +724,8 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
>
>  static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int ret;
>
>        if (on)
> @@ -741,8 +741,8 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
>
>  static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int ret;
>
>        if (on)
> @@ -759,8 +759,8 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
>  static int mt9m111_get_control(struct soc_camera_device *icd,
>                               struct v4l2_control *ctrl)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int data;
>
>        switch (ctrl->id) {
> @@ -803,7 +803,8 @@ static int mt9m111_get_control(struct soc_camera_device *icd,
>  static int mt9m111_set_control(struct soc_camera_device *icd,
>                               struct v4l2_control *ctrl)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        const struct v4l2_queryctrl *qctrl;
>        int ret;
>
> @@ -841,7 +842,8 @@ static int mt9m111_set_control(struct soc_camera_device *icd,
>
>  static int mt9m111_restore_state(struct soc_camera_device *icd)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>
>        mt9m111_set_context(icd, mt9m111->context);
>        mt9m111_set_pixfmt(icd, mt9m111->pixfmt);
> @@ -856,7 +858,8 @@ static int mt9m111_restore_state(struct soc_camera_device *icd)
>
>  static int mt9m111_resume(struct soc_camera_device *icd)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int ret = 0;
>
>        if (mt9m111->powered) {
> @@ -871,7 +874,8 @@ static int mt9m111_resume(struct soc_camera_device *icd)
>
>  static int mt9m111_init(struct soc_camera_device *icd)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        int ret;
>
>        mt9m111->context = HIGHPOWER;
> @@ -902,10 +906,10 @@ static int mt9m111_release(struct soc_camera_device *icd)
>  * 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 mt9m111_video_probe(struct soc_camera_device *icd)
> +static int mt9m111_video_probe(struct soc_camera_device *icd,
> +                              struct i2c_client *client)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>        s32 data;
>        int ret;
>
> @@ -917,6 +921,11 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
>            to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
>                return -ENODEV;
>
> +       /* Switch master clock on */
> +       ret = soc_camera_video_start(icd, &client->dev);
> +       if (ret)
> +               return ret;
> +
>        ret = mt9m111_enable(icd);
>        if (ret)
>                goto ei2c;
> @@ -945,40 +954,42 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
>
>        dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data);
>
> -       ret = soc_camera_video_start(icd);
> -       if (ret)
> -               goto eisis;
> -
>        mt9m111->autoexposure = 1;
>        mt9m111->autowhitebalance = 1;
>
>        mt9m111->swap_rgb_even_odd = 1;
>        mt9m111->swap_rgb_red_blue = 1;
>
> -       return 0;
> -eisis:
>  ei2c:
> +       soc_camera_video_stop(icd);
> +
>        return ret;
>  }
>
>  static void mt9m111_video_remove(struct soc_camera_device *icd)
>  {
> -       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> -       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr,
> -               mt9m111->icd.dev.parent, mt9m111->icd.vdev);
> -       soc_camera_video_stop(&mt9m111->icd);
> +       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
> +               icd->dev.parent, icd->vdev);
> +       icd->ops = NULL;
>  }
>
>  static int mt9m111_probe(struct i2c_client *client,
>                         const struct i2c_device_id *did)
>  {
>        struct mt9m111 *mt9m111;
> -       struct soc_camera_device *icd;
> +       struct soc_camera_device *icd = client->dev.platform_data;
>        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct soc_camera_link *icl;
>        int ret;
>
> +       if (!icd) {
> +               dev_err(&client->dev, "MT9M11x: missing soc-camera data!\n");
> +               return -EINVAL;
> +       }
> +
> +       icl = to_soc_camera_link(icd);
>        if (!icl) {
>                dev_err(&client->dev, "MT9M11x driver needs platform data\n");
>                return -EINVAL;
> @@ -994,13 +1005,10 @@ static int mt9m111_probe(struct i2c_client *client,
>        if (!mt9m111)
>                return -ENOMEM;
>
> -       mt9m111->client = client;
>        i2c_set_clientdata(client, mt9m111);
>
>        /* Second stage probe - when a capture adapter is there */
> -       icd             = &mt9m111->icd;
>        icd->ops        = &mt9m111_ops;
> -       icd->control    = &client->dev;
>        icd->x_min      = MT9M111_MIN_DARK_COLS;
>        icd->y_min      = MT9M111_MIN_DARK_ROWS;
>        icd->x_current  = icd->x_min;
> @@ -1010,22 +1018,24 @@ static int mt9m111_probe(struct i2c_client *client,
>        icd->height_min = MT9M111_MIN_DARK_COLS;
>        icd->height_max = MT9M111_MAX_HEIGHT;
>        icd->y_skip_top = 0;
> -       icd->iface      = icl->bus_id;
>
> -       ret = soc_camera_device_register(icd);
> -       if (ret)
> -               goto eisdr;
> -       return 0;
> +       ret = mt9m111_video_probe(icd, client);
> +       if (ret) {
> +               i2c_set_clientdata(client, NULL);
> +               kfree(mt9m111);
> +       }
>
> -eisdr:
> -       kfree(mt9m111);
>        return ret;
>  }
>
>  static int mt9m111_remove(struct i2c_client *client)
>  {
>        struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> -       soc_camera_device_unregister(&mt9m111->icd);
> +       struct soc_camera_device *icd = client->dev.platform_data;
> +
> +       mt9m111_video_remove(icd);
> +       i2c_set_clientdata(client, NULL);
> +       client->driver = NULL;
>        kfree(mt9m111);
>
>        return 0;
> diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
> index f72aeb7..da09906 100644
> --- a/drivers/media/video/mt9t031.c
> +++ b/drivers/media/video/mt9t031.c
> @@ -68,8 +68,6 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = {
>  };
>
>  struct mt9t031 {
> -       struct i2c_client *client;
> -       struct soc_camera_device icd;
>        int model;      /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
>        unsigned char autoexposure;
>        u16 xskip;
> @@ -138,8 +136,8 @@ static int get_shutter(struct i2c_client *client, u32 *data)
>
>  static int mt9t031_init(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>        int ret;
>
>        if (icl->power) {
> @@ -166,8 +164,8 @@ static int mt9t031_init(struct soc_camera_device *icd)
>
>  static int mt9t031_release(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>
>        /* Disable the chip */
>        reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
> @@ -180,7 +178,7 @@ static int mt9t031_release(struct soc_camera_device *icd)
>
>  static int mt9t031_start_capture(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        /* Switch to master "normal" mode */
>        if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
> @@ -190,7 +188,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd)
>
>  static int mt9t031_stop_capture(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        /* Stop sensor readout */
>        if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
> @@ -201,7 +199,7 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd)
>  static int mt9t031_set_bus_param(struct soc_camera_device *icd,
>                                 unsigned long flags)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        /* The caller should have queried our parameters, check anyway */
>        if (flags & ~MT9T031_BUS_PARAM)
> @@ -217,8 +215,7 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd,
>
>  static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd)
>  {
> -       struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> -       struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>
>        return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
>  }
> @@ -238,8 +235,8 @@ static void recalculate_limits(struct soc_camera_device *icd,
>  static int mt9t031_set_params(struct soc_camera_device *icd,
>                              struct v4l2_rect *rect, u16 xskip, u16 yskip)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
>        int ret;
>        u16 xbin, ybin, width, height, left, top;
>        const u16 hblank = MT9T031_HORIZONTAL_BLANK,
> @@ -336,7 +333,8 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
>  static int mt9t031_set_crop(struct soc_camera_device *icd,
>                            struct v4l2_rect *rect)
>  {
> -       struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
>
>        /* CROP - no change in scaling, or in limits */
>        return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip);
> @@ -345,7 +343,8 @@ static int mt9t031_set_crop(struct soc_camera_device *icd,
>  static int mt9t031_set_fmt(struct soc_camera_device *icd,
>                           struct v4l2_format *f)
>  {
> -       struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
>        int ret;
>        u16 xskip, yskip;
>        struct v4l2_rect rect = {
> @@ -403,12 +402,13 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd,
>  static int mt9t031_get_chip_id(struct soc_camera_device *icd,
>                               struct v4l2_dbg_chip_ident *id)
>  {
> -       struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
>
>        if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
>                return -EINVAL;
>
> -       if (id->match.addr != mt9t031->client->addr)
> +       if (id->match.addr != client->addr)
>                return -ENODEV;
>
>        id->ident       = mt9t031->model;
> @@ -421,7 +421,7 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd,
>  static int mt9t031_get_register(struct soc_camera_device *icd,
>                                struct v4l2_dbg_register *reg)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
>                return -EINVAL;
> @@ -440,7 +440,7 @@ static int mt9t031_get_register(struct soc_camera_device *icd,
>  static int mt9t031_set_register(struct soc_camera_device *icd,
>                                struct v4l2_dbg_register *reg)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
>                return -EINVAL;
> @@ -501,15 +501,11 @@ static const struct v4l2_queryctrl mt9t031_controls[] = {
>        }
>  };
>
> -static int mt9t031_video_probe(struct soc_camera_device *);
> -static void mt9t031_video_remove(struct soc_camera_device *);
>  static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *);
>  static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *);
>
>  static struct soc_camera_ops mt9t031_ops = {
>        .owner                  = THIS_MODULE,
> -       .probe                  = mt9t031_video_probe,
> -       .remove                 = mt9t031_video_remove,
>        .init                   = mt9t031_init,
>        .release                = mt9t031_release,
>        .start_capture          = mt9t031_start_capture,
> @@ -532,8 +528,8 @@ static struct soc_camera_ops mt9t031_ops = {
>
>  static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
>        int data;
>
>        switch (ctrl->id) {
> @@ -558,8 +554,8 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro
>
>  static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
>        const struct v4l2_queryctrl *qctrl;
>        int data;
>
> @@ -665,10 +661,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
>
>  /* 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 mt9t031_video_probe(struct soc_camera_device *icd)
> +static int mt9t031_video_probe(struct soc_camera_device *icd,
> +                              struct i2c_client *client)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +       struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
>        s32 data;
>        int ret;
>
> @@ -678,6 +674,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
>            to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
>                return -ENODEV;
>
> +       /* Switch master clock on */
> +       ret = soc_camera_video_start(icd, &client->dev);
> +       if (ret)
> +               return ret;
> +
>        /* Enable the chip */
>        data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
>        dev_dbg(&icd->dev, "write: %d\n", data);
> @@ -685,6 +686,8 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
>        /* Read out the chip version register */
>        data = reg_read(client, MT9T031_CHIP_VERSION);
>
> +       soc_camera_video_stop(icd);
> +
>        switch (data) {
>        case 0x1621:
>                mt9t031->model = V4L2_IDENT_MT9T031;
> @@ -692,44 +695,40 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
>                icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats);
>                break;
>        default:
> -               ret = -ENODEV;
>                dev_err(&icd->dev,
>                        "No MT9T031 chip detected, register read %x\n", data);
> -               goto ei2c;
> +               return -ENODEV;
>        }
>
>        dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data);
>
> -       /* Now that we know the model, we can start video */
> -       ret = soc_camera_video_start(icd);
> -       if (ret)
> -               goto evstart;
> -
>        return 0;
> -
> -evstart:
> -ei2c:
> -       return ret;
>  }
>
>  static void mt9t031_video_remove(struct soc_camera_device *icd)
>  {
> -       struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> -       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9t031->client->addr,
> +       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
>                icd->dev.parent, icd->vdev);
> -       soc_camera_video_stop(icd);
> +       icd->ops = NULL;
>  }
>
>  static int mt9t031_probe(struct i2c_client *client,
>                         const struct i2c_device_id *did)
>  {
>        struct mt9t031 *mt9t031;
> -       struct soc_camera_device *icd;
> +       struct soc_camera_device *icd = client->dev.platform_data;
>        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct soc_camera_link *icl;
>        int ret;
>
> +       if (!icd) {
> +               dev_err(&client->dev, "MT9T031: missing soc-camera data!\n");
> +               return -EINVAL;
> +       }
> +
> +       icl = to_soc_camera_link(icd);
>        if (!icl) {
>                dev_err(&client->dev, "MT9T031 driver needs platform data\n");
>                return -EINVAL;
> @@ -745,13 +744,10 @@ static int mt9t031_probe(struct i2c_client *client,
>        if (!mt9t031)
>                return -ENOMEM;
>
> -       mt9t031->client = client;
>        i2c_set_clientdata(client, mt9t031);
>
>        /* Second stage probe - when a capture adapter is there */
> -       icd = &mt9t031->icd;
>        icd->ops        = &mt9t031_ops;
> -       icd->control    = &client->dev;
>        icd->x_min      = MT9T031_COLUMN_SKIP;
>        icd->y_min      = MT9T031_ROW_SKIP;
>        icd->x_current  = icd->x_min;
> @@ -761,7 +757,6 @@ static int mt9t031_probe(struct i2c_client *client,
>        icd->height_min = MT9T031_MIN_HEIGHT;
>        icd->height_max = MT9T031_MAX_HEIGHT;
>        icd->y_skip_top = 0;
> -       icd->iface      = icl->bus_id;
>        /* Simulated autoexposure. If enabled, we calculate shutter width
>         * ourselves in the driver based on vertical blanking and frame width */
>        mt9t031->autoexposure = 1;
> @@ -769,24 +764,24 @@ static int mt9t031_probe(struct i2c_client *client,
>        mt9t031->xskip = 1;
>        mt9t031->yskip = 1;
>
> -       ret = soc_camera_device_register(icd);
> -       if (ret)
> -               goto eisdr;
> -
> -       return 0;
> +       ret = mt9t031_video_probe(icd, client);
> +       if (ret) {
> +               icd->ops = NULL;
> +               i2c_set_clientdata(client, NULL);
> +               kfree(mt9t031);
> +       }
>
> -eisdr:
> -       i2c_set_clientdata(client, NULL);
> -       kfree(mt9t031);
>        return ret;
>  }
>
>  static int mt9t031_remove(struct i2c_client *client)
>  {
>        struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> +       struct soc_camera_device *icd = client->dev.platform_data;
>
> -       soc_camera_device_unregister(&mt9t031->icd);
> +       mt9t031_video_remove(icd);
>        i2c_set_clientdata(client, NULL);
> +       client->driver = NULL;
>        kfree(mt9t031);
>
>        return 0;
> diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
> index be20d31..1683af1 100644
> --- a/drivers/media/video/mt9v022.c
> +++ b/drivers/media/video/mt9v022.c
> @@ -85,8 +85,6 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
>  };
>
>  struct mt9v022 {
> -       struct i2c_client *client;
> -       struct soc_camera_device icd;
>        int model;      /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
>        u16 chip_control;
>  };
> @@ -127,9 +125,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
>
>  static int mt9v022_init(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
> +       struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
>        int ret;
>
>        if (icl->power) {
> @@ -173,19 +171,19 @@ static int mt9v022_init(struct soc_camera_device *icd)
>
>  static int mt9v022_release(struct soc_camera_device *icd)
>  {
> -       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> -       struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>
>        if (icl->power)
> -               icl->power(&mt9v022->client->dev, 0);
> +               icl->power(&client->dev, 0);
>
>        return 0;
>  }
>
>  static int mt9v022_start_capture(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
>        /* Switch to master "normal" mode */
>        mt9v022->chip_control &= ~0x10;
>        if (reg_write(client, MT9V022_CHIP_CONTROL,
> @@ -196,8 +194,8 @@ static int mt9v022_start_capture(struct soc_camera_device *icd)
>
>  static int mt9v022_stop_capture(struct soc_camera_device *icd)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
>        /* Switch to snapshot mode */
>        mt9v022->chip_control |= 0x10;
>        if (reg_write(client, MT9V022_CHIP_CONTROL,
> @@ -209,9 +207,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd)
>  static int mt9v022_set_bus_param(struct soc_camera_device *icd,
>                                 unsigned long flags)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>        unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
>        int ret;
>        u16 pixclk = 0;
> @@ -263,8 +261,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
>
>  static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
>  {
> -       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> -       struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>        unsigned int width_flag;
>
>        if (icl->query_bus_param)
> @@ -283,7 +280,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
>  static int mt9v022_set_crop(struct soc_camera_device *icd,
>                            struct v4l2_rect *rect)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>        int ret;
>
>        /* Like in example app. Contradicts the datasheet though */
> @@ -326,7 +323,8 @@ static int mt9v022_set_crop(struct soc_camera_device *icd,
>  static int mt9v022_set_fmt(struct soc_camera_device *icd,
>                           struct v4l2_format *f)
>  {
> -       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
>        struct v4l2_pix_format *pix = &f->fmt.pix;
>        struct v4l2_rect rect = {
>                .left   = icd->x_current,
> @@ -380,12 +378,13 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd,
>  static int mt9v022_get_chip_id(struct soc_camera_device *icd,
>                               struct v4l2_dbg_chip_ident *id)
>  {
> -       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
>
>        if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
>                return -EINVAL;
>
> -       if (id->match.addr != mt9v022->client->addr)
> +       if (id->match.addr != client->addr)
>                return -ENODEV;
>
>        id->ident       = mt9v022->model;
> @@ -398,7 +397,7 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd,
>  static int mt9v022_get_register(struct soc_camera_device *icd,
>                                struct v4l2_dbg_register *reg)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
>                return -EINVAL;
> @@ -418,7 +417,7 @@ static int mt9v022_get_register(struct soc_camera_device *icd,
>  static int mt9v022_set_register(struct soc_camera_device *icd,
>                                struct v4l2_dbg_register *reg)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
>                return -EINVAL;
> @@ -487,15 +486,11 @@ static const struct v4l2_queryctrl mt9v022_controls[] = {
>        }
>  };
>
> -static int mt9v022_video_probe(struct soc_camera_device *);
> -static void mt9v022_video_remove(struct soc_camera_device *);
>  static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *);
>  static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *);
>
>  static struct soc_camera_ops mt9v022_ops = {
>        .owner                  = THIS_MODULE,
> -       .probe                  = mt9v022_video_probe,
> -       .remove                 = mt9v022_video_remove,
>        .init                   = mt9v022_init,
>        .release                = mt9v022_release,
>        .start_capture          = mt9v022_start_capture,
> @@ -519,7 +514,7 @@ static struct soc_camera_ops mt9v022_ops = {
>  static int mt9v022_get_control(struct soc_camera_device *icd,
>                               struct v4l2_control *ctrl)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>        int data;
>
>        switch (ctrl->id) {
> @@ -555,7 +550,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
>                               struct v4l2_control *ctrl)
>  {
>        int data;
> -       struct i2c_client *client = to_i2c_client(icd->control);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>        const struct v4l2_queryctrl *qctrl;
>
>        qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
> @@ -652,11 +647,11 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
>
>  /* 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 mt9v022_video_probe(struct soc_camera_device *icd)
> +static int mt9v022_video_probe(struct soc_camera_device *icd,
> +                              struct i2c_client *client)
>  {
> -       struct i2c_client *client = to_i2c_client(icd->control);
> -       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>        s32 data;
>        int ret;
>        unsigned long flags;
> @@ -665,6 +660,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
>            to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
>                return -ENODEV;
>
> +       /* Switch master clock on */
> +       ret = soc_camera_video_start(icd, &client->dev);
> +       if (ret)
> +               return ret;
> +
>        /* Read out the chip version register */
>        data = reg_read(client, MT9V022_CHIP_VERSION);
>
> @@ -684,6 +684,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
>        udelay(200);
>        if (reg_read(client, MT9V022_RESET)) {
>                dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
> +               if (ret > 0)
> +                       ret = -EIO;
>                goto ei2c;
>        }
>
> @@ -700,7 +702,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
>        }
>
>        if (ret < 0)
> -               goto eisis;
> +               goto ei2c;
>
>        icd->num_formats = 0;
>
> @@ -722,29 +724,24 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
>        if (flags & SOCAM_DATAWIDTH_8)
>                icd->num_formats++;
>
> -       ret = soc_camera_video_start(icd);
> -       if (ret < 0)
> -               goto eisis;
> -
>        dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
>                 data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
>                 "monochrome" : "colour");
>
> -       return 0;
> -
> -eisis:
>  ei2c:
> +       soc_camera_video_stop(icd);
> +
>        return ret;
>  }
>
>  static void mt9v022_video_remove(struct soc_camera_device *icd)
>  {
> -       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> -       struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> -       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
> +       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
>                icd->dev.parent, icd->vdev);
> -       soc_camera_video_stop(icd);
> +       icd->ops = NULL;
>        if (icl->free_bus)
>                icl->free_bus(icl);
>  }
> @@ -753,11 +750,17 @@ static int mt9v022_probe(struct i2c_client *client,
>                         const struct i2c_device_id *did)
>  {
>        struct mt9v022 *mt9v022;
> -       struct soc_camera_device *icd;
> +       struct soc_camera_device *icd = client->dev.platform_data;
>        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> -       struct soc_camera_link *icl = client->dev.platform_data;
> +       struct soc_camera_link *icl;
>        int ret;
>
> +       if (!icd) {
> +               dev_err(&client->dev, "MT9V022: missing soc-camera data!\n");
> +               return -EINVAL;
> +       }
> +
> +       icl = to_soc_camera_link(icd);
>        if (!icl) {
>                dev_err(&client->dev, "MT9V022 driver needs platform data\n");
>                return -EINVAL;
> @@ -774,12 +777,9 @@ static int mt9v022_probe(struct i2c_client *client,
>                return -ENOMEM;
>
>        mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
> -       mt9v022->client = client;
>        i2c_set_clientdata(client, mt9v022);
>
> -       icd = &mt9v022->icd;
>        icd->ops        = &mt9v022_ops;
> -       icd->control    = &client->dev;
>        icd->x_min      = 1;
>        icd->y_min      = 4;
>        icd->x_current  = 1;
> @@ -789,24 +789,24 @@ static int mt9v022_probe(struct i2c_client *client,
>        icd->height_min = 32;
>        icd->height_max = 480;
>        icd->y_skip_top = 1;
> -       icd->iface      = icl->bus_id;
> -
> -       ret = soc_camera_device_register(icd);
> -       if (ret)
> -               goto eisdr;
>
> -       return 0;
> +       ret = mt9v022_video_probe(icd, client);
> +       if (ret) {
> +               i2c_set_clientdata(client, NULL);
> +               kfree(mt9v022);
> +       }
>
> -eisdr:
> -       kfree(mt9v022);
>        return ret;
>  }
>
>  static int mt9v022_remove(struct i2c_client *client)
>  {
>        struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> +       struct soc_camera_device *icd = client->dev.platform_data;
>
> -       soc_camera_device_unregister(&mt9v022->icd);
> +       mt9v022_video_remove(icd);
> +       i2c_set_clientdata(client, NULL);
> +       client->driver = NULL;
>        kfree(mt9v022);
>
>        return 0;
> diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
> index cb13faa..ed752c5 100644
> --- a/drivers/media/video/mx3_camera.c
> +++ b/drivers/media/video/mx3_camera.c
> @@ -502,18 +502,19 @@ static int mx3_camera_add_device(struct soc_camera_device *icd)
>
>        mx3_camera_activate(mx3_cam, icd);
>        ret = icd->ops->init(icd);
> -       if (ret < 0) {
> -               clk_disable(mx3_cam->clk);
> +       if (ret < 0)
>                goto einit;
> -       }
>
>        mx3_cam->icd = icd;
>
> +       dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
> +                icd->devnum);
> +
> +       return 0;
> +
>  einit:
> +       clk_disable(mx3_cam->clk);
>  ebusy:
> -       if (!ret)
> -               dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
> -                        icd->devnum);
>
>        return ret;
>  }
> @@ -946,9 +947,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
>        camera_flags = icd->ops->query_bus_param(icd);
>
>        common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
> +       dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
> +               camera_flags, bus_flags, common_flags);
>        if (!common_flags) {
> -               dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n",
> -                       camera_flags, bus_flags);
> +               dev_dbg(ici->dev, "no common flags");
>                return -EINVAL;
>        }
>
> @@ -1001,8 +1003,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
>                        SOCAM_DATAWIDTH_4;
>
>        ret = icd->ops->set_bus_param(icd, common_flags);
> -       if (ret < 0)
> +       if (ret < 0) {
> +               dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n",
> +                       common_flags, ret);
>                return ret;
> +       }
>
>        /*
>         * So far only gated clock mode is supported. Add a line
> @@ -1130,8 +1135,9 @@ static int mx3_camera_probe(struct platform_device *pdev)
>        INIT_LIST_HEAD(&mx3_cam->capture);
>        spin_lock_init(&mx3_cam->lock);
>
> -       base = ioremap(res->start, res->end - res->start + 1);
> +       base = ioremap(res->start, resource_size(res));
>        if (!base) {
> +               pr_err("Couldn't map %x@%x\n", resource_size(res), res->start);
>                err = -ENOMEM;
>                goto eioremap;
>        }
> @@ -1218,3 +1224,4 @@ module_exit(mx3_camera_exit);
>  MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver");
>  MODULE_AUTHOR("Guennadi Liakhovetski <lg@xxxxxxx>");
>  MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME);
> diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
> index c0d9112..48f4d64 100644
> --- a/drivers/media/video/ov772x.c
> +++ b/drivers/media/video/ov772x.c
> @@ -399,8 +399,6 @@ struct ov772x_win_size {
>
>  struct ov772x_priv {
>        struct ov772x_camera_info        *info;
> -       struct i2c_client                *client;
> -       struct soc_camera_device          icd;
>        const struct ov772x_color_format *fmt;
>        const struct ov772x_win_size     *win;
>        int                               model;
> @@ -619,53 +617,56 @@ static int ov772x_reset(struct i2c_client *client)
>
>  static int ov772x_init(struct soc_camera_device *icd)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = dev_get_drvdata(&icd->dev);
>        int ret = 0;
>
> -       if (priv->info->link.power) {
> -               ret = priv->info->link.power(&priv->client->dev, 1);
> +       if (icl->power) {
> +               ret = icl->power(&client->dev, 1);
>                if (ret < 0)
>                        return ret;
>        }
>
> -       if (priv->info->link.reset)
> -               ret = priv->info->link.reset(&priv->client->dev);
> +       if (icl->reset)
> +               ret = icl->reset(&client->dev);
>
>        return ret;
>  }
>
>  static int ov772x_release(struct soc_camera_device *icd)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct soc_camera_link *icl = dev_get_drvdata(&icd->dev);
>        int ret = 0;
>
> -       if (priv->info->link.power)
> -               ret = priv->info->link.power(&priv->client->dev, 0);
> +       if (icl->power)
> +               ret = icl->power(&client->dev, 0);
>
>        return ret;
>  }
>
>  static int ov772x_start_capture(struct soc_camera_device *icd)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct ov772x_priv *priv = i2c_get_clientdata(client);
>
>        if (!priv->win || !priv->fmt) {
>                dev_err(&icd->dev, "norm or win select error\n");
>                return -EPERM;
>        }
>
> -       ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0);
> +       ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0);
>
>        dev_dbg(&icd->dev,
> -                "format %s, win %s\n", priv->fmt->name, priv->win->name);
> +               "format %s, win %s\n", priv->fmt->name, priv->win->name);
>
>        return 0;
>  }
>
>  static int ov772x_stop_capture(struct soc_camera_device *icd)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> -       ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
>        return 0;
>  }
>
> @@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd,
>
>  static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> -       struct soc_camera_link *icl = &priv->info->link;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct ov772x_priv *priv = i2c_get_clientdata(client);
> +       struct soc_camera_link *icl = dev_get_drvdata(&icd->dev);
>        unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
>                SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
>                SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
> @@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
>  static int ov772x_get_control(struct soc_camera_device *icd,
>                              struct v4l2_control *ctrl)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct ov772x_priv *priv = i2c_get_clientdata(client);
>
>        switch (ctrl->id) {
>        case V4L2_CID_VFLIP:
> @@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd,
>  static int ov772x_set_control(struct soc_camera_device *icd,
>                              struct v4l2_control *ctrl)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct ov772x_priv *priv = i2c_get_clientdata(client);
>        int ret = 0;
>        u8 val;
>
> @@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd,
>                priv->flag_vflip = ctrl->value;
>                if (priv->info->flags & OV772X_FLAG_VFLIP)
>                        val ^= VFLIP_IMG;
> -               ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val);
> +               ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val);
>                break;
>        case V4L2_CID_HFLIP:
>                val = ctrl->value ? HFLIP_IMG : 0x00;
>                priv->flag_hflip = ctrl->value;
>                if (priv->info->flags & OV772X_FLAG_HFLIP)
>                        val ^= HFLIP_IMG;
> -               ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val);
> +               ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val);
>                break;
>        }
>
> @@ -730,9 +734,10 @@ static int ov772x_set_control(struct soc_camera_device *icd,
>  }
>
>  static int ov772x_get_chip_id(struct soc_camera_device *icd,
> -                             struct v4l2_dbg_chip_ident   *id)
> +                             struct v4l2_dbg_chip_ident *id)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct ov772x_priv *priv = i2c_get_clientdata(client);
>
>        id->ident    = priv->model;
>        id->revision = 0;
> @@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd,
>  static int ov772x_get_register(struct soc_camera_device *icd,
>                               struct v4l2_dbg_register *reg)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> -       int                 ret;
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       int ret;
>
>        reg->size = 1;
>        if (reg->reg > 0xff)
>                return -EINVAL;
>
> -       ret = i2c_smbus_read_byte_data(priv->client, reg->reg);
> +       ret = i2c_smbus_read_byte_data(client, reg->reg);
>        if (ret < 0)
>                return ret;
>
> @@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd,
>  static int ov772x_set_register(struct soc_camera_device *icd,
>                               struct v4l2_dbg_register *reg)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
>        if (reg->reg > 0xff ||
>            reg->val > 0xff)
>                return -EINVAL;
>
> -       return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val);
> +       return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
>  }
>  #endif
>
> @@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height)
>        return win;
>  }
>
> -static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> -                            u32 pixfmt)
> +static int ov772x_set_params(struct soc_camera_device *icd,
> +                            u32 width, u32 height, u32 pixfmt)
>  {
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct ov772x_priv *priv = i2c_get_clientdata(client);
>        int ret = -EINVAL;
>        u8  val;
>        int i;
> @@ -821,7 +828,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
>        /*
>         * reset hardware
>         */
> -       ov772x_reset(priv->client);
> +       ov772x_reset(client);
>
>        /*
>         * Edge Ctrl
> @@ -835,17 +842,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
>                 * Remove it when manual mode.
>                 */
>
> -               ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00);
> +               ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00);
>                if (ret < 0)
>                        goto ov772x_set_fmt_error;
>
> -               ret = ov772x_mask_set(priv->client,
> +               ret = ov772x_mask_set(client,
>                                      EDGE_TRSHLD, EDGE_THRESHOLD_MASK,
>                                      priv->info->edgectrl.threshold);
>                if (ret < 0)
>                        goto ov772x_set_fmt_error;
>
> -               ret = ov772x_mask_set(priv->client,
> +               ret = ov772x_mask_set(client,
>                                      EDGE_STRNGT, EDGE_STRENGTH_MASK,
>                                      priv->info->edgectrl.strength);
>                if (ret < 0)
> @@ -857,13 +864,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
>                 *
>                 * set upper and lower limit
>                 */
> -               ret = ov772x_mask_set(priv->client,
> +               ret = ov772x_mask_set(client,
>                                      EDGE_UPPER, EDGE_UPPER_MASK,
>                                      priv->info->edgectrl.upper);
>                if (ret < 0)
>                        goto ov772x_set_fmt_error;
>
> -               ret = ov772x_mask_set(priv->client,
> +               ret = ov772x_mask_set(client,
>                                      EDGE_LOWER, EDGE_LOWER_MASK,
>                                      priv->info->edgectrl.lower);
>                if (ret < 0)
> @@ -873,7 +880,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
>        /*
>         * set size format
>         */
> -       ret = ov772x_write_array(priv->client, priv->win->regs);
> +       ret = ov772x_write_array(client, priv->win->regs);
>        if (ret < 0)
>                goto ov772x_set_fmt_error;
>
> @@ -882,7 +889,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
>         */
>        val = priv->fmt->dsp3;
>        if (val) {
> -               ret = ov772x_mask_set(priv->client,
> +               ret = ov772x_mask_set(client,
>                                      DSP_CTRL3, UV_MASK, val);
>                if (ret < 0)
>                        goto ov772x_set_fmt_error;
> @@ -901,7 +908,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
>        if (priv->flag_hflip)
>                val ^= HFLIP_IMG;
>
> -       ret = ov772x_mask_set(priv->client,
> +       ret = ov772x_mask_set(client,
>                              COM3, SWAP_MASK | IMG_MASK, val);
>        if (ret < 0)
>                goto ov772x_set_fmt_error;
> @@ -910,7 +917,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
>         * set COM7
>         */
>        val = priv->win->com7_bit | priv->fmt->com7;
> -       ret = ov772x_mask_set(priv->client,
> +       ret = ov772x_mask_set(client,
>                              COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK),
>                              val);
>        if (ret < 0)
> @@ -920,7 +927,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
>
>  ov772x_set_fmt_error:
>
> -       ov772x_reset(priv->client);
> +       ov772x_reset(client);
>        priv->win = NULL;
>        priv->fmt = NULL;
>
> @@ -930,22 +937,22 @@ ov772x_set_fmt_error:
>  static int ov772x_set_crop(struct soc_camera_device *icd,
>                           struct v4l2_rect *rect)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> +       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> +       struct ov772x_priv *priv = i2c_get_clientdata(client);
>
>        if (!priv->fmt)
>                return -EINVAL;
>
> -       return ov772x_set_params(priv, rect->width, rect->height,
> +       return ov772x_set_params(icd, rect->width, rect->height,
>                                 priv->fmt->fourcc);
>  }
>
>  static int ov772x_set_fmt(struct soc_camera_device *icd,
>                          struct v4l2_format *f)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
>        struct v4l2_pix_format *pix = &f->fmt.pix;
>
> -       return ov772x_set_params(priv, pix->width, pix->height,
> +       return ov772x_set_params(icd, pix->width, pix->height,
>                                 pix->pixelformat);
>  }
>
> @@ -967,11 +974,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd,
>        return 0;
>  }
>
> -static int ov772x_video_probe(struct soc_camera_device *icd)
> +static int ov772x_video_probe(struct soc_camera_device *icd,
> +                             struct i2c_client *client)
>  {
> -       struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> +       struct ov772x_priv *priv = i2c_get_clientdata(client);
>        u8                  pid, ver;
>        const char         *devname;
> +       int ret;
>
>        /*
>         * We must have a parent by now. And it cannot be a wrong one.
> @@ -993,11 +1002,18 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
>        icd->formats     = ov772x_fmt_lists;
>        icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists);
>
> +       /* Switch master clock on */
> +       ret = soc_camera_video_start(icd, &client->dev);
> +       if (ret)
> +               return ret;
> +
>        /*
>         * check and show product ID and manufacturer ID
>         */
> -       pid = i2c_smbus_read_byte_data(priv->client, PID);
> -       ver = i2c_smbus_read_byte_data(priv->client, VER);
> +       pid = i2c_smbus_read_byte_data(client, PID);
> +       ver = i2c_smbus_read_byte_data(client, VER);
> +
> +       soc_camera_video_stop(icd);
>
>        switch (VERSION(pid, ver)) {
>        case OV7720:
> @@ -1019,21 +1035,19 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
>                 devname,
>                 pid,
>                 ver,
> -                i2c_smbus_read_byte_data(priv->client, MIDH),
> -                i2c_smbus_read_byte_data(priv->client, MIDL));
> +                i2c_smbus_read_byte_data(client, MIDH),
> +                i2c_smbus_read_byte_data(client, MIDL));
>
> -       return soc_camera_video_start(icd);
> +       return 0;
>  }
>
>  static void ov772x_video_remove(struct soc_camera_device *icd)
>  {
> -       soc_camera_video_stop(icd);
> +       icd->ops = NULL;
>  }
>
>  static struct soc_camera_ops ov772x_ops = {
>        .owner                  = THIS_MODULE,
> -       .probe                  = ov772x_video_probe,
> -       .remove                 = ov772x_video_remove,
>        .init                   = ov772x_init,
>        .release                = ov772x_release,
>        .start_capture          = ov772x_start_capture,
> @@ -1063,13 +1077,21 @@ static int ov772x_probe(struct i2c_client *client,
>  {
>        struct ov772x_priv        *priv;
>        struct ov772x_camera_info *info;
> -       struct soc_camera_device  *icd;
> +       struct soc_camera_device  *icd = client->dev.platform_data;
>        struct i2c_adapter        *adapter = to_i2c_adapter(client->dev.parent);
> +       struct soc_camera_link    *icl;
>        int                        ret;
>
> -       info = client->dev.platform_data;
> -       if (!info)
> +       if (!icd) {
> +               dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
>                return -EINVAL;
> +       }
> +
> +       icl = dev_get_drvdata(&icd->dev);
> +       if (!icl)
> +               return -EINVAL;
> +
> +       info = container_of(icl, struct ov772x_camera_info, link);
>
>        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
>                dev_err(&adapter->dev,
> @@ -1083,18 +1105,13 @@ static int ov772x_probe(struct i2c_client *client,
>                return -ENOMEM;
>
>        priv->info   = info;
> -       priv->client = client;
>        i2c_set_clientdata(client, priv);
>
> -       icd             = &priv->icd;
>        icd->ops        = &ov772x_ops;
> -       icd->control    = &client->dev;
>        icd->width_max  = MAX_WIDTH;
>        icd->height_max = MAX_HEIGHT;
> -       icd->iface      = priv->info->link.bus_id;
> -
> -       ret = soc_camera_device_register(icd);
>
> +       ret = ov772x_video_probe(icd, client);
>        if (ret) {
>                i2c_set_clientdata(client, NULL);
>                kfree(priv);
> @@ -1106,8 +1123,9 @@ static int ov772x_probe(struct i2c_client *client,
>  static int ov772x_remove(struct i2c_client *client)
>  {
>        struct ov772x_priv *priv = i2c_get_clientdata(client);
> +       struct soc_camera_device *icd = client->dev.platform_data;
>
> -       soc_camera_device_unregister(&priv->icd);
> +       ov772x_video_remove(icd);
>        i2c_set_clientdata(client, NULL);
>        kfree(priv);
>        return 0;
> diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
> index 2da5eef..63964d0 100644
> --- a/drivers/media/video/pxa_camera.c
> +++ b/drivers/media/video/pxa_camera.c
> @@ -841,7 +841,8 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q,
>                                sizeof(struct pxa_buffer), icd);
>  }
>
> -static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
> +static u32 mclk_get_divisor(struct platform_device *pdev,
> +                           struct pxa_camera_dev *pcdev)
>  {
>        unsigned long mclk = pcdev->mclk;
>        u32 div;
> @@ -853,7 +854,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
>        /* mclk <= ciclk / 4 (27.4.2) */
>        if (mclk > lcdclk / 4) {
>                mclk = lcdclk / 4;
> -               dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk);
> +               dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk);
>        }
>
>        /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */
> @@ -863,8 +864,8 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
>        if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
>                pcdev->mclk = lcdclk / (2 * (div + 1));
>
> -       dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, "
> -               "divisor %u\n", lcdclk, mclk, div);
> +       dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n",
> +               lcdclk, mclk, div);
>
>        return div;
>  }
> @@ -969,15 +970,20 @@ static int pxa_camera_add_device(struct soc_camera_device *icd)
>                goto ebusy;
>        }
>
> -       dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
> -                icd->devnum);
> -
>        pxa_camera_activate(pcdev);
>        ret = icd->ops->init(icd);
> +       if (ret < 0)
> +               goto einit;
> +
> +       pcdev->icd = icd;
>
> -       if (!ret)
> -               pcdev->icd = icd;
> +       dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
> +                icd->devnum);
>
> +       return 0;
> +
> +einit:
> +       pxa_camera_deactivate(pcdev);
>  ebusy:
>        return ret;
>  }
> @@ -1599,7 +1605,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
>                pcdev->mclk = 20000000;
>        }
>
> -       pcdev->mclk_divisor = mclk_get_divisor(pcdev);
> +       pcdev->mclk_divisor = mclk_get_divisor(pdev, pcdev);
>
>        INIT_LIST_HEAD(&pcdev->capture);
>        spin_lock_init(&pcdev->lock);
> @@ -1746,3 +1752,4 @@ module_exit(pxa_camera_exit);
>  MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
>  MODULE_AUTHOR("Guennadi Liakhovetski <kernel@xxxxxxxxxxxxxx>");
>  MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:" PXA_CAM_DRV_NAME);
> diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
> index d369e84..ac9b467 100644
> --- a/drivers/media/video/sh_mobile_ceu_camera.c
> +++ b/drivers/media/video/sh_mobile_ceu_camera.c
> @@ -360,11 +360,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
>                 "SuperH Mobile CEU driver attached to camera %d\n",
>                 icd->devnum);
>
> +       clk_enable(pcdev->clk);
> +
>        ret = icd->ops->init(icd);
> -       if (ret)
> +       if (ret) {
> +               clk_disable(pcdev->clk);
>                goto err;
> -
> -       clk_enable(pcdev->clk);
> +       }
>
>        ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
>        while (ceu_read(pcdev, CSTSR) & 1)
> @@ -398,10 +400,10 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
>        }
>        spin_unlock_irqrestore(&pcdev->lock, flags);
>
> -       clk_disable(pcdev->clk);
> -
>        icd->ops->release(icd);
>
> +       clk_disable(pcdev->clk);
> +
>        dev_info(&icd->dev,
>                 "SuperH Mobile CEU driver detached from camera %d\n",
>                 icd->devnum);
> @@ -948,3 +950,4 @@ module_exit(sh_mobile_ceu_exit);
>  MODULE_DESCRIPTION("SuperH Mobile CEU driver");
>  MODULE_AUTHOR("Magnus Damm");
>  MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:sh_mobile_ceu");
> diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
> index 03a6c29..d2b765d 100644
> --- a/drivers/media/video/soc_camera.c
> +++ b/drivers/media/video/soc_camera.c
> @@ -16,19 +16,21 @@
>  * published by the Free Software Foundation.
>  */
>
> -#include <linux/module.h>
> -#include <linux/init.h>
>  #include <linux/device.h>
> -#include <linux/list.h>
>  #include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/list.h>
>  #include <linux/mutex.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
>  #include <linux/vmalloc.h>
>
> +#include <media/soc_camera.h>
>  #include <media/v4l2-common.h>
>  #include <media/v4l2-ioctl.h>
>  #include <media/v4l2-dev.h>
>  #include <media/videobuf-core.h>
> -#include <media/soc_camera.h>
>
>  /* Default to VGA resolution */
>  #define DEFAULT_WIDTH  640
> @@ -36,7 +38,7 @@
>
>  static LIST_HEAD(hosts);
>  static LIST_HEAD(devices);
> -static DEFINE_MUTEX(list_lock);
> +static DEFINE_MUTEX(list_lock);                /* Protects the list of hosts */
>
>  const struct soc_camera_data_format *soc_camera_format_by_fourcc(
>        struct soc_camera_device *icd, unsigned int fourcc)
> @@ -207,6 +209,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
>        return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
>  }
>
> +/* Always entered with .video_lock held */
>  static int soc_camera_init_user_formats(struct soc_camera_device *icd)
>  {
>        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> @@ -255,9 +258,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
>        return 0;
>  }
>
> +/* Always entered with .video_lock held */
>  static void soc_camera_free_user_formats(struct soc_camera_device *icd)
>  {
> +       icd->current_fmt = NULL;
>        vfree(icd->user_formats);
> +       icd->user_formats = NULL;
>  }
>
>  /* Called with .vb_lock held */
> @@ -308,10 +314,6 @@ static int soc_camera_open(struct file *file)
>        struct soc_camera_file *icf;
>        int ret;
>
> -       icf = vmalloc(sizeof(*icf));
> -       if (!icf)
> -               return -ENOMEM;
> -
>        /*
>         * It is safe to dereference these pointers now as long as a user has
>         * the video device open - we are protected by the held cdev reference.
> @@ -319,8 +321,17 @@ static int soc_camera_open(struct file *file)
>
>        vdev = video_devdata(file);
>        icd = container_of(vdev->parent, struct soc_camera_device, dev);
> +
> +       if (!icd->ops)
> +               /* No device driver attached */
> +               return -ENODEV;
> +
>        ici = to_soc_camera_host(icd->dev.parent);
>
> +       icf = vmalloc(sizeof(*icf));
> +       if (!icf)
> +               return -ENOMEM;
> +
>        if (!try_module_get(icd->ops->owner)) {
>                dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
>                ret = -EINVAL;
> @@ -333,7 +344,7 @@ static int soc_camera_open(struct file *file)
>                goto emgi;
>        }
>
> -       /* Protect against icd->remove() until we module_get() both drivers. */
> +       /* Protect against icd->ops->remove() until we module_get() both drivers. */
>        mutex_lock(&icd->video_lock);
>
>        icf->icd = icd;
> @@ -348,11 +359,16 @@ static int soc_camera_open(struct file *file)
>                                .width          = icd->width,
>                                .height         = icd->height,
>                                .field          = icd->field,
> -                               .pixelformat    = icd->current_fmt->fourcc,
> -                               .colorspace     = icd->current_fmt->colorspace,
>                        },
>                };
>
> +               ret = soc_camera_init_user_formats(icd);
> +               if (ret < 0)
> +                       goto eiufmt;
> +
> +               f.fmt.pix.pixelformat   = icd->current_fmt->fourcc;
> +               f.fmt.pix.colorspace    = icd->current_fmt->colorspace;
> +
>                ret = ici->ops->add(icd);
>                if (ret < 0) {
>                        dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
> @@ -381,6 +397,8 @@ static int soc_camera_open(struct file *file)
>  esfmt:
>        ici->ops->remove(icd);
>  eiciadd:
> +       soc_camera_free_user_formats(icd);
> +eiufmt:
>        icd->use_count--;
>        mutex_unlock(&icd->video_lock);
>        module_put(ici->ops->owner);
> @@ -400,8 +418,10 @@ static int soc_camera_close(struct file *file)
>
>        mutex_lock(&icd->video_lock);
>        icd->use_count--;
> -       if (!icd->use_count)
> +       if (!icd->use_count) {
>                ici->ops->remove(icd);
> +               soc_camera_free_user_formats(icd);
> +       }
>
>        mutex_unlock(&icd->video_lock);
>
> @@ -762,29 +782,6 @@ static int soc_camera_s_register(struct file *file, void *fh,
>  }
>  #endif
>
> -static int device_register_link(struct soc_camera_device *icd)
> -{
> -       int ret = dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum);
> -
> -       if (!ret)
> -               ret = device_register(&icd->dev);
> -
> -       if (ret < 0) {
> -               /* Prevent calling device_unregister() */
> -               icd->dev.parent = NULL;
> -               dev_err(&icd->dev, "Cannot register device: %d\n", ret);
> -       /* Even if probe() was unsuccessful for all registered drivers,
> -        * device_register() returns 0, and we add the link, just to
> -        * document this camera's control device */
> -       } else if (icd->control)
> -               /* Have to sysfs_remove_link() before device_unregister()? */
> -               if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj,
> -                                     "control"))
> -                       dev_warn(&icd->dev,
> -                                "Failed creating the control symlink\n");
> -       return ret;
> -}
> -
>  /* So far this function cannot fail */
>  static void scan_add_host(struct soc_camera_host *ici)
>  {
> @@ -794,103 +791,70 @@ static void scan_add_host(struct soc_camera_host *ici)
>
>        list_for_each_entry(icd, &devices, list) {
>                if (icd->iface == ici->nr) {
> +                       int ret;
>                        icd->dev.parent = ici->dev;
> -                       device_register_link(icd);
> -               }
> -       }
> -
> -       mutex_unlock(&list_lock);
> -}
> -
> -/* return: 0 if no match found or a match found and
> - * device_register() successful, error code otherwise */
> -static int scan_add_device(struct soc_camera_device *icd)
> -{
> -       struct soc_camera_host *ici;
> -       int ret = 0;
> -
> -       mutex_lock(&list_lock);
> -
> -       list_add_tail(&icd->list, &devices);
> -
> -       /* Watch out for class_for_each_device / class_find_device API by
> -        * Dave Young <hidave.darkstar@xxxxxxxxx> */
> -       list_for_each_entry(ici, &hosts, list) {
> -               if (icd->iface == ici->nr) {
> -                       ret = 1;
> -                       icd->dev.parent = ici->dev;
> -                       break;
> +                       dev_set_name(&icd->dev, "%u-%u", icd->iface,
> +                                    icd->devnum);
> +                       ret = device_register(&icd->dev);
> +                       if (ret < 0) {
> +                               icd->dev.parent = NULL;
> +                               dev_err(&icd->dev,
> +                                       "Cannot register device: %d\n", ret);
> +                       }
>                }
>        }
>
>        mutex_unlock(&list_lock);
> -
> -       if (ret)
> -               ret = device_register_link(icd);
> -
> -       return ret;
>  }
>
> +static int video_dev_create(struct soc_camera_device *icd);
> +/* Called during host-driver probe */
>  static int soc_camera_probe(struct device *dev)
>  {
>        struct soc_camera_device *icd = to_soc_camera_dev(dev);
> -       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> +       struct soc_camera_link *icl = to_soc_camera_link(icd);
>        int ret;
> +       struct i2c_client *client;
> +       struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id);
>
> -       /*
> -        * Possible race scenario:
> -        * modprobe <camera-host-driver> triggers __func__
> -        * at this moment respective <camera-sensor-driver> gets rmmod'ed
> -        * to protect take module references.
> -        */
> -
> -       if (!try_module_get(icd->ops->owner)) {
> -               dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
> -               ret = -EINVAL;
> -               goto emgd;
> -       }
> -
> -       if (!try_module_get(ici->ops->owner)) {
> -               dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
> -               ret = -EINVAL;
> -               goto emgi;
> +       if (!adap) {
> +               ret = -ENODEV;
> +               dev_err(dev, "Cannot get I2C adapter %d\n", icl->i2c_adapter_id);
> +               goto ei2cga;
>        }
>
> -       mutex_lock(&icd->video_lock);
> +       dev_info(dev, "Probing %s\n", dev_name(dev));
>
> -       /* We only call ->add() here to activate and probe the camera.
> -        * We shall ->remove() and deactivate it immediately afterwards. */
> -       ret = ici->ops->add(icd);
> -       if (ret < 0)
> -               goto eiadd;
> +       client = i2c_new_device(adap, icl->board_info);
> +       if (!client) {
> +               ret = -ENOMEM;
> +               goto ei2cnd;
> +       }
>
> -       ret = icd->ops->probe(icd);
> -       if (ret >= 0) {
> -               const struct v4l2_queryctrl *qctrl;
> +       /*
> +        * We set icd drvdata at two locations - here and in
> +        * soc_camera_video_start(). Depending on the module loading /
> +        * initialisation order one of these locations will be entered first
> +        */
> +       /* Use to_i2c_client(dev) to recover the i2c client */
> +       dev_set_drvdata(&icd->dev, &client->dev);
>
> -               qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
> -               icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
> -               qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
> -               icd->exposure = qctrl ? qctrl->default_value :
> -                       (unsigned short)~0;
> +       /* Do we have to sysfs_remove_link() before device_unregister()? */
> +       if (sysfs_create_link(&dev->kobj, &to_soc_camera_control(icd)->kobj,
> +                             "control"))
> +               dev_warn(dev, "Failed creating the control symlink\n");
>
> -               ret = soc_camera_init_user_formats(icd);
> -               if (ret < 0)
> -                       goto eiufmt;
> +       ret = video_dev_create(icd);
> +       if (ret < 0)
> +               goto evdc;
>
> -               icd->height     = DEFAULT_HEIGHT;
> -               icd->width      = DEFAULT_WIDTH;
> -               icd->field      = V4L2_FIELD_ANY;
> -       }
> +       return 0;
>
> -eiufmt:
> -       ici->ops->remove(icd);
> -eiadd:
> -       mutex_unlock(&icd->video_lock);
> -       module_put(ici->ops->owner);
> -emgi:
> -       module_put(icd->ops->owner);
> -emgd:
> +evdc:
> +       i2c_unregister_device(client);
> +ei2cnd:
> +       i2c_put_adapter(adap);
> +ei2cga:
>        return ret;
>  }
>
> @@ -899,11 +863,23 @@ emgd:
>  static int soc_camera_remove(struct device *dev)
>  {
>        struct soc_camera_device *icd = to_soc_camera_dev(dev);
> +       struct video_device *vdev = icd->vdev;
>
> -       if (icd->ops->remove)
> -               icd->ops->remove(icd);
> +       BUG_ON(!dev->parent);
>
> -       soc_camera_free_user_formats(icd);
> +       if (vdev) {
> +               mutex_lock(&icd->video_lock);
> +               video_unregister_device(vdev);
> +               icd->vdev = NULL;
> +               mutex_unlock(&icd->video_lock);
> +       }
> +
> +       if (to_soc_camera_control(icd)) {
> +               struct i2c_client *client =
> +                       to_i2c_client(to_soc_camera_control(icd));
> +               i2c_unregister_device(client);
> +               i2c_put_adapter(client->adapter);
> +       }
>
>        return 0;
>  }
> @@ -998,10 +974,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
>
>        list_for_each_entry(icd, &devices, list) {
>                if (icd->dev.parent == ici->dev) {
> +                       /* The bus->remove will be called */
>                        device_unregister(&icd->dev);
>                        /* Not before device_unregister(), .remove
>                         * needs parent to call ici->ops->remove() */
>                        icd->dev.parent = NULL;
> +
> +                       /* If the host module is loaded again, device_register()
> +                        * would complain "already initialised" */
>                        memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj));
>                }
>        }
> @@ -1013,26 +993,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
>  EXPORT_SYMBOL(soc_camera_host_unregister);
>
>  /* Image capture device */
> -int soc_camera_device_register(struct soc_camera_device *icd)
> +static int soc_camera_device_register(struct soc_camera_device *icd)
>  {
>        struct soc_camera_device *ix;
>        int num = -1, i;
>
> -       if (!icd || !icd->ops ||
> -           !icd->ops->probe ||
> -           !icd->ops->init ||
> -           !icd->ops->release ||
> -           !icd->ops->start_capture ||
> -           !icd->ops->stop_capture ||
> -           !icd->ops->set_crop ||
> -           !icd->ops->set_fmt ||
> -           !icd->ops->try_fmt ||
> -           !icd->ops->query_bus_param ||
> -           !icd->ops->set_bus_param)
> -               return -EINVAL;
> -
>        for (i = 0; i < 256 && num < 0; i++) {
>                num = i;
> +               /* Check if this index is available on this interface */
>                list_for_each_entry(ix, &devices, list) {
>                        if (ix->iface == icd->iface && ix->devnum == i) {
>                                num = -1;
> @@ -1054,21 +1022,15 @@ int soc_camera_device_register(struct soc_camera_device *icd)
>        icd->host_priv          = NULL;
>        mutex_init(&icd->video_lock);
>
> -       return scan_add_device(icd);
> +       list_add_tail(&icd->list, &devices);
> +
> +       return 0;
>  }
> -EXPORT_SYMBOL(soc_camera_device_register);
>
> -void soc_camera_device_unregister(struct soc_camera_device *icd)
> +static void soc_camera_device_unregister(struct soc_camera_device *icd)
>  {
> -       mutex_lock(&list_lock);
>        list_del(&icd->list);
> -
> -       /* The bus->remove will be eventually called */
> -       if (icd->dev.parent)
> -               device_unregister(&icd->dev);
> -       mutex_unlock(&list_lock);
>  }
> -EXPORT_SYMBOL(soc_camera_device_unregister);
>
>  static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
>        .vidioc_querycap         = soc_camera_querycap,
> @@ -1099,22 +1061,14 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
>  #endif
>  };
>
> -/*
> - * Usually called from the struct soc_camera_ops .probe() method, i.e., from
> - * soc_camera_probe() above with .video_lock held
> - */
> -int soc_camera_video_start(struct soc_camera_device *icd)
> +static int video_dev_create(struct soc_camera_device *icd)
>  {
>        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> -       int err = -ENOMEM;
> -       struct video_device *vdev;
> -
> -       if (!icd->dev.parent)
> -               return -ENODEV;
> +       int ret;
> +       struct video_device *vdev = video_device_alloc();
>
> -       vdev = video_device_alloc();
>        if (!vdev)
> -               goto evidallocd;
> +               return -ENOMEM;
>        dev_dbg(ici->dev, "Allocated video_device %p\n", vdev);
>
>        strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
> @@ -1125,10 +1079,10 @@ int soc_camera_video_start(struct soc_camera_device *icd)
>        vdev->ioctl_ops         = &soc_camera_ioctl_ops;
>        vdev->release           = video_device_release;
>        vdev->minor             = -1;
> -       vdev->tvnorms           = V4L2_STD_UNKNOWN,
> +       vdev->tvnorms           = V4L2_STD_UNKNOWN;
>
> -       err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
> -       if (err < 0) {
> +       ret = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
> +       if (ret < 0) {
>                dev_err(vdev->parent, "video_register_device failed\n");
>                goto evidregd;
>        }
> @@ -1138,27 +1092,99 @@ int soc_camera_video_start(struct soc_camera_device *icd)
>
>  evidregd:
>        video_device_release(vdev);
> -evidallocd:
> -       return err;
> +       return ret;
> +}
> +
> +/*
> + * Usually called from the struct soc_camera_ops .probe() method, i.e., from
> + * soc_camera_probe() above with .video_lock held
> + */
> +int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev)
> +{
> +       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> +       const struct v4l2_queryctrl *qctrl;
> +
> +       if (!icd->dev.parent)
> +               return -ENODEV;
> +
> +       if (!icd->ops ||
> +           !icd->ops->init ||
> +           !icd->ops->release ||
> +           !icd->ops->start_capture ||
> +           !icd->ops->stop_capture ||
> +           !icd->ops->set_fmt ||
> +           !icd->ops->try_fmt ||
> +           !icd->ops->query_bus_param ||
> +           !icd->ops->set_bus_param)
> +               return -EINVAL;
> +
> +       /* See comment in soc_camera_probe() */
> +       dev_set_drvdata(&icd->dev, dev);
> +
> +       qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
> +       icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
> +       qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
> +       icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0;
> +
> +       return ici->ops->add(icd);
>  }
>  EXPORT_SYMBOL(soc_camera_video_start);
>
>  void soc_camera_video_stop(struct soc_camera_device *icd)
>  {
> -       struct video_device *vdev = icd->vdev;
> +       struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
>
>        dev_dbg(&icd->dev, "%s\n", __func__);
>
> -       if (!icd->dev.parent || !vdev)
> -               return;
> -
> -       mutex_lock(&icd->video_lock);
> -       video_unregister_device(vdev);
> -       icd->vdev = NULL;
> -       mutex_unlock(&icd->video_lock);
> +       ici->ops->remove(icd);
>  }
>  EXPORT_SYMBOL(soc_camera_video_stop);
>
> +static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
> +{
> +       struct soc_camera_link *icl = pdev->dev.platform_data;
> +       struct soc_camera_device *icd;
> +
> +       if (!icl)
> +               return -EINVAL;
> +
> +       icd = kzalloc(sizeof(*icd), GFP_KERNEL);
> +       if (!icd)
> +               return -ENOMEM;
> +
> +       icd->iface = icl->bus_id;
> +       icl->board_info->platform_data = icd;
> +       platform_set_drvdata(pdev, icd);
> +       icd->dev.platform_data = icl;
> +
> +       return soc_camera_device_register(icd);
> +}
> +
> +/* Only called on rmmod for each platform device, since they are not
> + * hot-plugg...
>
> [Message clipped]



-- 
========================================================
DongSoo, Nathaniel Kim
Engineer
Mobile S/W Platform Lab.
Digital Media & Communications R&D Centre
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@xxxxxxxxx
          dongsoo45.kim@xxxxxxxxxxx
========================================================
--
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

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux